8301873: Avoid string decoding in ZipFile.Source.getEntryPos

Reviewed-by: redestad, lancea
This commit is contained in:
Eirik Bjorsnos 2023-02-18 12:39:19 +00:00 committed by Claes Redestad
parent f82385e587
commit 78f71b4d41
4 changed files with 374 additions and 24 deletions

View file

@ -1633,40 +1633,41 @@ public class ZipFile implements ZipConstants, Closeable {
int hsh = ZipCoder.hash(name);
int idx = table[(hsh & 0x7fffffff) % tablelen];
int dirPos = -1; // Position of secondary match "name/"
// Search down the target hash chain for a entry whose
// 32 bit hash matches the hashed name.
while (idx != ZIP_ENDCHAIN) {
if (getEntryHash(idx) == hsh) {
// The CEN name must match the specified one
int pos = getEntryPos(idx);
int noff = pos + CENHDR;
int nlen = CENNAM(cen, pos);
try {
ZipCoder zc = zipCoderForPos(pos);
String entry = zc.toString(cen, pos + CENHDR, CENNAM(cen, pos));
ZipCoder zc = zipCoderForPos(pos);
// If addSlash is true we'll test for name+/ in addition to
// name, unless name is the empty string or already ends with a
// slash
int entryLen = entry.length();
int nameLen = name.length();
if (entryLen == nameLen && entry.equals(name)) {
// Found our match
// Compare the lookup name with the name encoded in the CEN
switch (zc.compare(name, cen, noff, nlen, addSlash)) {
case EXACT_MATCH:
// We found an exact match for "name"
return pos;
}
// If addSlash is true we'll now test for name+/ providing
if (addSlash && nameLen + 1 == entryLen
&& entry.startsWith(name) &&
entry.charAt(entryLen - 1) == '/') {
// Found the entry "name+/", now find the CEN entry pos
int exactPos = getEntryPos(name, false);
return exactPos == -1 ? pos : exactPos;
}
} catch (IllegalArgumentException iae) {
// Ignore
case DIRECTORY_MATCH:
// We found the directory "name/"
// Track its position, then continue the search for "name"
dirPos = pos;
break;
case NO_MATCH:
// Hash collision, continue searching
}
}
idx = getEntryNext(idx);
}
// Reaching this point means we did not find "name".
// Return the position of "name/" if we found it
if (dirPos != -1) {
return dirPos;
}
// No entry found
return -1;
}