Skip to content

Commit e7395c5

Browse files
committed
Add bounds check to ForwardScanZipReader when checking for CEN linked LFH
1 parent 5cd1b48 commit e7395c5

File tree

3 files changed

+34
-18
lines changed

3 files changed

+34
-18
lines changed

src/main/java/software/coley/lljzip/format/read/ForwardScanZipReader.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,9 @@ public void read(@Nonnull ZipArchive zip, @Nonnull MemorySegment data) throws IO
7777
NavigableSet<Long> offsets = new TreeSet<>();
7878
for (CentralDirectoryFileHeader directory : zip.getCentralDirectories()) {
7979
long offset = zipStart + directory.getRelativeOffsetOfLocalHeader();
80-
if (!offsets.contains(offset) && MemorySegmentUtil.readQuad(data, offset) == ZipPatterns.LOCAL_FILE_HEADER_QUAD) {
80+
if (!offsets.contains(offset)
81+
&& offset < data.byteSize()
82+
&& MemorySegmentUtil.readQuad(data, offset) == ZipPatterns.LOCAL_FILE_HEADER_QUAD) {
8183
LocalFileHeader file = newLocalFileHeader();
8284
directory.link(file);
8385
file.link(directory);

src/test/java/software/coley/lljzip/PatchingTests.java

Lines changed: 31 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,10 @@
66
import software.coley.lljzip.format.ZipPatterns;
77
import software.coley.lljzip.format.model.LocalFileHeader;
88
import software.coley.lljzip.format.model.ZipArchive;
9+
import software.coley.lljzip.format.read.ForwardScanZipReader;
910
import software.coley.lljzip.format.read.NaiveLocalFileZipReader;
1011
import software.coley.lljzip.format.read.SimpleZipPartAllocator;
12+
import software.coley.lljzip.format.read.ZipPartAllocator;
1113
import software.coley.lljzip.format.transform.IdentityZipPartMapper;
1214
import software.coley.lljzip.format.transform.JvmClassDirectoryMapper;
1315
import software.coley.lljzip.format.write.ZipOutputStreamZipWriter;
@@ -96,8 +98,34 @@ public void testTrickJarPatched(String name) {
9698

9799
@Test
98100
@SuppressWarnings("resource")
99-
public void testNaiveWithForwardScanningData() {
100-
NaiveLocalFileZipReader strategy = new NaiveLocalFileZipReader(new SimpleZipPartAllocator() {
101+
public void testReadIgnoringFileLengths() {
102+
ZipPartAllocator allocator = lengthIgnoringAllocator();
103+
104+
Path path = Paths.get("src/test/resources/resource-pack-trick-data-ioobe.zip");
105+
106+
// Naive strategy finds the file with the trailing '/'
107+
NaiveLocalFileZipReader naiveStrategy = new NaiveLocalFileZipReader(allocator);
108+
ZipArchive zip = assertDoesNotThrow(() -> ZipIO.read(path, naiveStrategy));
109+
assertNotNull(zip.getLocalFileByName("assets/luxbl/lang/en_us.json/"), "Missing 'en_us' file");
110+
111+
// Standard strategy finds it, but its authoritative CEN defines the file name to not include the trailing '/'
112+
ForwardScanZipReader forwardStrategy = new ForwardScanZipReader(allocator);
113+
zip = assertDoesNotThrow(() -> ZipIO.read(path, forwardStrategy));
114+
assertNotNull(zip.getLocalFileByName("assets/luxbl/lang/en_us.json"), "Missing 'en_us' file");
115+
}
116+
117+
@Test
118+
@SuppressWarnings("resource")
119+
public void testTrailingSlashTransform() {
120+
// The 'JvmClassDirectoryMapper' maps 'Name.class/' paths to 'Name.class'
121+
Path path = Paths.get("src/test/resources/hello-secret-trailing-slash.jar");
122+
ZipArchive zip = assertDoesNotThrow(() -> ZipIO.readStandard(path)
123+
.withMapping(new JvmClassDirectoryMapper(new IdentityZipPartMapper())));
124+
assertNotNull(zip.getLocalFileByName("Hello.class"), "Trailing slash was not patched");
125+
}
126+
127+
private static ZipPartAllocator lengthIgnoringAllocator() {
128+
return new SimpleZipPartAllocator() {
101129
@Nonnull
102130
@Override
103131
public LocalFileHeader newLocalFileHeader() {
@@ -114,20 +142,6 @@ protected MemorySegmentData readFileData(@Nonnull MemorySegment data, long heade
114142
}
115143
};
116144
}
117-
});
118-
119-
Path path = Paths.get("src/test/resources/resource-pack-trick-data-ioobe-no-end.zip");
120-
ZipArchive zip = assertDoesNotThrow(() -> ZipIO.read(path, strategy));
121-
assertNotNull(zip.getLocalFileByName("pack.mcmeta"), "IOOBE not patched");
122-
}
123-
124-
@Test
125-
@SuppressWarnings("resource")
126-
public void testTrailingSlashTransform() {
127-
// The 'JvmClassDirectoryMapper' maps 'Name.class/' paths to 'Name.class'
128-
Path path = Paths.get("src/test/resources/hello-secret-trailing-slash.jar");
129-
ZipArchive zip = assertDoesNotThrow(() -> ZipIO.readStandard(path)
130-
.withMapping(new JvmClassDirectoryMapper(new IdentityZipPartMapper())));
131-
assertNotNull(zip.getLocalFileByName("Hello.class"), "Trailing slash was not patched");
145+
};
132146
}
133147
}

0 commit comments

Comments
 (0)