# HG changeset patch # User sherman # Date 1407441443 25200 # Node ID d7fbf9a294af9cab190722f6606033a8db13efd6 # Parent cbf7fcda2e3f15461bf3386f585e86ac77f45985 8048025: Ensure cache consistency Summary: To support zip entry with null character(s) embedded Reviewed-by: alanb, weijun diff -r cbf7fcda2e3f -r d7fbf9a294af jdk/src/java.base/share/native/libzip/ZipFile.c --- a/jdk/src/java.base/share/native/libzip/ZipFile.c Tue Jun 24 14:00:01 2014 -0700 +++ b/jdk/src/java.base/share/native/libzip/ZipFile.c Thu Aug 07 12:57:23 2014 -0700 @@ -174,11 +174,7 @@ } (*env)->GetByteArrayRegion(env, name, 0, ulen, (jbyte *)path); path[ulen] = '\0'; - if (addSlash == JNI_FALSE) { - ze = ZIP_GetEntry(zip, path, 0); - } else { - ze = ZIP_GetEntry(zip, path, (jint)ulen); - } + ze = ZIP_GetEntry2(zip, path, (jint)ulen, addSlash); if (path != buf) { free(path); } @@ -271,7 +267,7 @@ switch (type) { case java_util_zip_ZipFile_JZENTRY_NAME: if (ze->name != 0) { - len = (int)strlen(ze->name); + len = (int)ze->nlen; // Unlike for extra and comment, we never return null for // an (extremely rarely seen) empty name if ((jba = (*env)->NewByteArray(env, len)) == NULL) diff -r cbf7fcda2e3f -r d7fbf9a294af jdk/src/java.base/share/native/libzip/zip_util.c --- a/jdk/src/java.base/share/native/libzip/zip_util.c Tue Jun 24 14:00:01 2014 -0700 +++ b/jdk/src/java.base/share/native/libzip/zip_util.c Thu Aug 07 12:57:23 2014 -0700 @@ -1021,6 +1021,7 @@ if ((ze->name = malloc(nlen + 1)) == NULL) goto Catch; memcpy(ze->name, cen + CENHDR, nlen); ze->name[nlen] = '\0'; + ze->nlen = nlen; if (elen > 0) { char *extra = cen + CENHDR + nlen; @@ -1118,7 +1119,34 @@ jzentry * ZIP_GetEntry(jzfile *zip, char *name, jint ulen) { - unsigned int hsh = hash(name); + if (ulen == 0) { + return ZIP_GetEntry2(zip, name, strlen(name), JNI_FALSE); + } + return ZIP_GetEntry2(zip, name, ulen, JNI_TRUE); +} + +jboolean equals(char* name1, int len1, char* name2, int len2) { + if (len1 != len2) { + return JNI_FALSE; + } + while (len1-- > 0) { + if (*name1++ != *name2++) { + return JNI_FALSE; + } + } + return JNI_TRUE; +} + +/* + * Returns the zip entry corresponding to the specified name, or + * NULL if not found. + * This method supports embedded null character in "name", use ulen + * for the length of "name". + */ +jzentry * +ZIP_GetEntry2(jzfile *zip, char *name, jint ulen, jboolean addSlash) +{ + unsigned int hsh = hashN(name, ulen); jint idx; jzentry *ze = 0; @@ -1139,7 +1167,7 @@ /* Check the cached entry first */ ze = zip->cache; - if (ze && strcmp(ze->name,name) == 0) { + if (ze && equals(ze->name, ze->nlen, name, ulen)) { /* Cache hit! Remove and return the cached entry. */ zip->cache = 0; ZIP_Unlock(zip); @@ -1165,7 +1193,7 @@ * we keep searching. */ ze = newEntry(zip, zc, ACCESS_RANDOM); - if (ze && strcmp(ze->name, name)==0) { + if (ze && equals(ze->name, ze->nlen, name, ulen)) { break; } if (ze != 0) { @@ -1184,8 +1212,8 @@ break; } - /* If no real length was passed in, we are done */ - if (ulen == 0) { + /* If no need to try appending slash, we are done */ + if (!addSlash) { break; } @@ -1195,11 +1223,11 @@ } /* Add slash and try once more */ - name[ulen] = '/'; - name[ulen+1] = '\0'; + name[ulen++] = '/'; + name[ulen] = '\0'; hsh = hash_append(hsh, '/'); idx = zip->table[hsh % zip->tablelen]; - ulen = 0; + addSlash = JNI_FALSE; } Finally: diff -r cbf7fcda2e3f -r d7fbf9a294af jdk/src/java.base/share/native/libzip/zip_util.h --- a/jdk/src/java.base/share/native/libzip/zip_util.h Tue Jun 24 14:00:01 2014 -0700 +++ b/jdk/src/java.base/share/native/libzip/zip_util.h Thu Aug 07 12:57:23 2014 -0700 @@ -154,6 +154,7 @@ * - If pos <= 0 then it is the position of entry LOC header. * If pos > 0 then it is the position of entry data. * pos should not be accessed directly, but only by ZIP_GetEntryDataOffset. + * - entry name may include embedded null character, use nlen for length */ typedef struct jzentry { /* Zip file entry */ @@ -166,6 +167,7 @@ jbyte *extra; /* optional extra data */ jlong pos; /* position of LOC header or entry data */ jint flag; /* general purpose flag */ + jint nlen; /* length of the entry name */ } jzentry; /* @@ -269,5 +271,5 @@ jint ZIP_Read(jzfile *zip, jzentry *entry, jlong pos, void *buf, jint len); void ZIP_FreeEntry(jzfile *zip, jzentry *ze); jlong ZIP_GetEntryDataOffset(jzfile *zip, jzentry *entry); - +jzentry * ZIP_GetEntry2(jzfile *zip, char *name, jint ulen, jboolean addSlash); #endif /* !_ZIP_H_ */