changeset 10373:2a6df63ca0f0 jdk8u25-b14

8048025: Ensure cache consistency Summary: To support zip entry with null character(s) embedded Reviewed-by: alanb, weijun
author sherman
date Thu, 07 Aug 2014 10:49:10 -0700
parents 2a90beea2347
children 2cb0a92c8b02
files src/share/native/java/util/zip/ZipFile.c src/share/native/java/util/zip/zip_util.c src/share/native/java/util/zip/zip_util.h
diffstat 3 files changed, 42 insertions(+), 16 deletions(-) [+]
line wrap: on
line diff
--- a/src/share/native/java/util/zip/ZipFile.c	Tue Aug 19 05:36:25 2014 -0700
+++ b/src/share/native/java/util/zip/ZipFile.c	Thu Aug 07 10:49:10 2014 -0700
@@ -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 @@
     }
     (*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 @@
     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);
--- a/src/share/native/java/util/zip/zip_util.c	Tue Aug 19 05:36:25 2014 -0700
+++ b/src/share/native/java/util/zip/zip_util.c	Thu Aug 07 10:49:10 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:
--- a/src/share/native/java/util/zip/zip_util.h	Tue Aug 19 05:36:25 2014 -0700
+++ b/src/share/native/java/util/zip/zip_util.h	Thu Aug 07 10:49:10 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_ */