< prev index next >

src/java.base/share/classes/java/util/jar/JarFile.java

Print this page
rev 16859 : 8176709: JarFileSystem::isMultiReleaseJar is incorrect
Reviewed-by: mchung, psandoz, sherman

*** 34,43 **** --- 34,44 ---- import java.util.zip.*; import java.security.CodeSigner; import java.security.cert.Certificate; import java.security.CodeSource; import jdk.internal.misc.SharedSecrets; + import jdk.internal.util.jar.JarAttributes; import sun.security.action.GetPropertyAction; import sun.security.util.ManifestEntryVerifier; import sun.security.util.SignatureFileVerifier; /**
*** 825,893 **** return ((JarFileEntry)ze).realEntry(); } return (JarEntry)ze; } - // Statics for hand-coded Boyer-Moore search - private static final byte[] CLASSPATH_CHARS = - {'C','L','A','S','S','-','P','A','T','H', ':', ' '}; - - // The bad character shift for "class-path: " - private static final byte[] CLASSPATH_LASTOCC; - - // The good suffix shift for "class-path: " - private static final byte[] CLASSPATH_OPTOSFT; - - private static final byte[] MULTIRELEASE_CHARS = - {'M','U','L','T','I','-','R','E','L','E', 'A', 'S', 'E', ':', - ' ', 'T', 'R', 'U', 'E'}; - - // The bad character shift for "multi-release: true" - private static final byte[] MULTIRELEASE_LASTOCC; - - // The good suffix shift for "multi-release: true" - private static final byte[] MULTIRELEASE_OPTOSFT; - - static { - CLASSPATH_LASTOCC = new byte[64]; - CLASSPATH_OPTOSFT = new byte[12]; - CLASSPATH_LASTOCC[(int)'C' - 32] = 1; - CLASSPATH_LASTOCC[(int)'L' - 32] = 2; - CLASSPATH_LASTOCC[(int)'S' - 32] = 5; - CLASSPATH_LASTOCC[(int)'-' - 32] = 6; - CLASSPATH_LASTOCC[(int)'P' - 32] = 7; - CLASSPATH_LASTOCC[(int)'A' - 32] = 8; - CLASSPATH_LASTOCC[(int)'T' - 32] = 9; - CLASSPATH_LASTOCC[(int)'H' - 32] = 10; - CLASSPATH_LASTOCC[(int)':' - 32] = 11; - CLASSPATH_LASTOCC[(int)' ' - 32] = 12; - for (int i = 0; i < 11; i++) { - CLASSPATH_OPTOSFT[i] = 12; - } - CLASSPATH_OPTOSFT[11] = 1; - - MULTIRELEASE_LASTOCC = new byte[64]; - MULTIRELEASE_OPTOSFT = new byte[19]; - MULTIRELEASE_LASTOCC[(int)'M' - 32] = 1; - MULTIRELEASE_LASTOCC[(int)'I' - 32] = 5; - MULTIRELEASE_LASTOCC[(int)'-' - 32] = 6; - MULTIRELEASE_LASTOCC[(int)'L' - 32] = 9; - MULTIRELEASE_LASTOCC[(int)'A' - 32] = 11; - MULTIRELEASE_LASTOCC[(int)'S' - 32] = 12; - MULTIRELEASE_LASTOCC[(int)':' - 32] = 14; - MULTIRELEASE_LASTOCC[(int)' ' - 32] = 15; - MULTIRELEASE_LASTOCC[(int)'T' - 32] = 16; - MULTIRELEASE_LASTOCC[(int)'R' - 32] = 17; - MULTIRELEASE_LASTOCC[(int)'U' - 32] = 18; - MULTIRELEASE_LASTOCC[(int)'E' - 32] = 19; - for (int i = 0; i < 17; i++) { - MULTIRELEASE_OPTOSFT[i] = 19; - } - MULTIRELEASE_OPTOSFT[17] = 6; - MULTIRELEASE_OPTOSFT[18] = 1; - } - private JarEntry getManEntry() { if (manEntry == null) { // First look up manifest entry using standard name ZipEntry manEntry = super.getEntry(MANIFEST_NAME); if (manEntry == null) { --- 826,835 ----
*** 917,959 **** boolean hasClassPathAttribute() throws IOException { checkForSpecialAttributes(); return hasClassPathAttribute; } - /** - * Returns true if the pattern {@code src} is found in {@code b}. - * The {@code lastOcc} array is the precomputed bad character shifts. - * Since there are no repeated substring in our search strings, - * the good suffix shifts can be replaced with a comparison. - */ - private int match(byte[] src, byte[] b, byte[] lastOcc, byte[] optoSft) { - int len = src.length; - int last = b.length - len; - int i = 0; - next: - while (i <= last) { - for (int j = (len - 1); j >= 0; j--) { - byte c = b[i + j]; - if (c >= ' ' && c <= 'z') { - if (c >= 'a') c -= 32; // Canonicalize - - if (c != src[j]) { - // no match - int badShift = lastOcc[c - 32]; - i += Math.max(j + 1 - badShift, optoSft[j]); - continue next; - } - } else { - // no match, character not valid for name - i += len; - continue next; - } - } - return i; - } - return -1; - } /** * On first invocation, check if the JAR file has the Class-Path * and the Multi-Release attribute. A no-op on subsequent calls. */ --- 859,868 ----
*** 966,1006 **** return; } JarEntry manEntry = getManEntry(); if (manEntry != null) { byte[] b = getBytes(manEntry); ! hasClassPathAttribute = match(CLASSPATH_CHARS, b, ! CLASSPATH_LASTOCC, CLASSPATH_OPTOSFT) != -1; // is this a multi-release jar file if (MULTI_RELEASE_ENABLED) { ! int i = match(MULTIRELEASE_CHARS, b, MULTIRELEASE_LASTOCC, ! MULTIRELEASE_OPTOSFT); ! if (i != -1) { ! i += MULTIRELEASE_CHARS.length; ! if (i < b.length) { ! byte c = b[i++]; ! // Check that the value is followed by a newline ! // and does not have a continuation ! if (c == '\n' && ! (i == b.length || b[i] != ' ')) { ! isMultiRelease = true; ! } else if (c == '\r') { ! if (i == b.length) { ! isMultiRelease = true; ! } else { ! c = b[i++]; ! if (c == '\n') { ! if (i == b.length || b[i] != ' ') { ! isMultiRelease = true; ! } ! } else if (c != ' ') { ! isMultiRelease = true; ! } ! } ! } ! } ! } } } hasCheckedSpecialAttributes = true; } } --- 875,888 ---- return; } JarEntry manEntry = getManEntry(); if (manEntry != null) { byte[] b = getBytes(manEntry); ! hasClassPathAttribute = JarAttributes.hasClassPathAttribute(b); // is this a multi-release jar file if (MULTI_RELEASE_ENABLED) { ! isMultiRelease = JarAttributes.isMultiRelease(b); } } hasCheckedSpecialAttributes = true; } }
< prev index next >