Skip to content

Commit 011fd3a

Browse files
committed
Improve fallback detection of start offset in JvmZipReaderStrategy
1 parent 901c03c commit 011fd3a

File tree

1 file changed

+30
-24
lines changed

1 file changed

+30
-24
lines changed

src/main/java/software/coley/llzip/format/read/JvmZipReaderStrategy.java

Lines changed: 30 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -58,28 +58,11 @@ public void read(ZipArchive zip, ByteData data) throws IOException {
5858
}
5959

6060
// Determine base offset for computing file header locations with.
61-
// - If there is a preceding block of another zip, start with that.
62-
long jvmBaseFileOffset;
63-
if (precedingEndOfCentralDirectory == -1L) {
64-
// There was no match for a prior end part. We will seek forwards until finding a *VALID* PK starting header.
65-
jvmBaseFileOffset = ByteDataUtil.indexOf(data, ZipPatterns.PK);
66-
while (jvmBaseFileOffset >= 0L) {
67-
// Check that the PK discovered represents a valid zip part
68-
try {
69-
if (ByteDataUtil.startsWith(data, jvmBaseFileOffset, ZipPatterns.LOCAL_FILE_HEADER))
70-
new LocalFileHeader().read(data, jvmBaseFileOffset);
71-
else if (ByteDataUtil.startsWith(data, jvmBaseFileOffset, ZipPatterns.CENTRAL_DIRECTORY_FILE_HEADER))
72-
new CentralDirectoryFileHeader().read(data, jvmBaseFileOffset);
73-
else
74-
throw new IllegalStateException("No match for LocalFileHeader/CentralDirectoryFileHeader");
75-
// Valid, we're good to go
76-
break;
77-
} catch (Exception ex) {
78-
// Invalid, seek forward
79-
jvmBaseFileOffset = ByteDataUtil.indexOf(data, jvmBaseFileOffset + 1L, ZipPatterns.PK);
80-
}
81-
}
82-
} else {
61+
long jvmBaseFileOffset = 0;
62+
boolean priorZipEndWasBogus = false;
63+
64+
// If there is a preceding block of another zip, start with that.
65+
if (precedingEndOfCentralDirectory != -1) {
8366
// There was a prior end part, so we will seek past it's length and use that as the base offset.
8467
try {
8568
// Make sure it isn't bogus before we use it as a reference point
@@ -97,8 +80,31 @@ else if (ByteDataUtil.startsWith(data, jvmBaseFileOffset, ZipPatterns.CENTRAL_DI
9780
// - Needs to be done in such a way where we do not get tricked by the '-trick.jar' samples
9881
jvmBaseFileOffset = precedingEndOfCentralDirectory + tempEnd.length();
9982
} catch (Exception ex) {
100-
// It's bogus and the sig-match was a coincidence. Use the first PK match instead.
101-
jvmBaseFileOffset = ByteDataUtil.indexOf(data, ZipPatterns.PK);
83+
// It's bogus and the sig-match was a coincidence.
84+
priorZipEndWasBogus = true;
85+
}
86+
}
87+
88+
// Search for the first valid PK header if there was either no prior ZIP file
89+
// or if the prior ZIP detection was bogus.
90+
if (priorZipEndWasBogus || precedingEndOfCentralDirectory == -1L) {
91+
// There was no match for a prior end part. We will seek forwards until finding a *VALID* PK starting header.
92+
jvmBaseFileOffset = ByteDataUtil.indexOf(data, ZipPatterns.PK);
93+
while (jvmBaseFileOffset >= 0L) {
94+
// Check that the PK discovered represents a valid zip part
95+
try {
96+
if (ByteDataUtil.startsWith(data, jvmBaseFileOffset, ZipPatterns.LOCAL_FILE_HEADER))
97+
new LocalFileHeader().read(data, jvmBaseFileOffset);
98+
else if (ByteDataUtil.startsWith(data, jvmBaseFileOffset, ZipPatterns.CENTRAL_DIRECTORY_FILE_HEADER))
99+
new CentralDirectoryFileHeader().read(data, jvmBaseFileOffset);
100+
else
101+
throw new IllegalStateException("No match for LocalFileHeader/CentralDirectoryFileHeader");
102+
// Valid, we're good to go
103+
break;
104+
} catch (Exception ex) {
105+
// Invalid, seek forward
106+
jvmBaseFileOffset = ByteDataUtil.indexOf(data, jvmBaseFileOffset + 1L, ZipPatterns.PK);
107+
}
102108
}
103109
}
104110

0 commit comments

Comments
 (0)