From 539567c2e4a375923321994faa62119ce80d122c Mon Sep 17 00:00:00 2001 From: sherman Date: Thu, 7 Aug 2014 10:49:10 -0700 Subject: [PATCH] 8048026: Ensure cache consistency Summary: To support zip entry with null character(s) embedded Reviewed-by: alanb, weijun --- src/share/native/java/util/zip/ZipFile.c | 10 ++---- src/share/native/java/util/zip/zip_util.c | 44 ++++++++++++++++++----- src/share/native/java/util/zip/zip_util.h | 4 ++- 3 files changed, 42 insertions(+), 16 deletions(-) diff --git a/src/share/native/java/util/zip/ZipFile.c b/src/share/native/java/util/zip/ZipFile.c index e2916c235..7b34f66a2 100644 --- a/src/share/native/java/util/zip/ZipFile.c +++ b/src/share/native/java/util/zip/ZipFile.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -172,11 +172,7 @@ Java_java_util_zip_ZipFile_getEntry(JNIEnv *env, jclass cls, jlong zfile, } (*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); } @@ -269,7 +265,7 @@ Java_java_util_zip_ZipFile_getEntryBytes(JNIEnv *env, switch (type) { case java_util_zip_ZipFile_JZENTRY_NAME: if (ze->name != 0) { - len = (int)strlen(ze->name); + len = (int)ze->nlen; if (len == 0 || (jba = (*env)->NewByteArray(env, len)) == NULL) break; (*env)->SetByteArrayRegion(env, jba, 0, len, (jbyte *)ze->name); diff --git a/src/share/native/java/util/zip/zip_util.c b/src/share/native/java/util/zip/zip_util.c index a072e6624..b172cde31 100644 --- a/src/share/native/java/util/zip/zip_util.c +++ b/src/share/native/java/util/zip/zip_util.c @@ -1021,6 +1021,7 @@ newEntry(jzfile *zip, jzcell *zc, AccessHint accessHint) 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 @@ ZIP_FreeEntry(jzfile *jz, jzentry *ze) 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 @@ ZIP_GetEntry(jzfile *zip, char *name, jint ulen) /* 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 @@ ZIP_GetEntry(jzfile *zip, char *name, jint ulen) * 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 @@ ZIP_GetEntry(jzfile *zip, char *name, jint ulen) 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 @@ ZIP_GetEntry(jzfile *zip, char *name, jint ulen) } /* 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 --git a/src/share/native/java/util/zip/zip_util.h b/src/share/native/java/util/zip/zip_util.h index a4aaf8382..a64668cd6 100644 --- a/src/share/native/java/util/zip/zip_util.h +++ b/src/share/native/java/util/zip/zip_util.h @@ -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 @@ typedef struct jzentry { /* Zip file entry */ 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 @@ void ZIP_Unlock(jzfile *zip); 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_ */ -- GitLab