aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorlana <none@none>2014-01-29 11:11:54 -0800
committerlana <none@none>2014-01-29 11:11:54 -0800
commit661b70ca3ba25e6f574d150e0b71c413ae68cf85 (patch)
treeff8dc4345ea9203c0822100ce1d42f6c3f1e62bb
parent23c23eedf498e868c7b779e0d274b2948798958f (diff)
parentc90c4f7790da9f608566887abdf2f6eb9d905a1b (diff)
-rw-r--r--THIRD_PARTY_README2
-rw-r--r--src/share/classes/java/lang/invoke/AbstractValidatingLambdaMetafactory.java18
-rw-r--r--src/share/classes/java/util/jar/JarFile.java13
-rw-r--r--src/share/classes/sun/invoke/util/VerifyAccess.java6
-rw-r--r--src/solaris/native/common/jni_util_md.c6
-rw-r--r--test/java/lang/invoke/ProtectedMemberDifferentPackage/Test.java33
-rw-r--r--test/java/lang/invoke/ProtectedMemberDifferentPackage/p1/T2.java30
-rw-r--r--test/java/lang/invoke/ProtectedMemberDifferentPackage/p2/T3.java37
-rw-r--r--test/java/lang/invoke/lambda/T8032697.java69
-rw-r--r--test/java/lang/invoke/lambda/T8032697_anotherpkg/T8032697_A.java28
-rw-r--r--test/java/lang/invoke/lambda/T8032704.java62
-rw-r--r--test/java/lang/invoke/lambda/T8032711.java62
-rw-r--r--test/sun/security/tools/jarsigner/EntriesOrder.java199
13 files changed, 556 insertions, 9 deletions
diff --git a/THIRD_PARTY_README b/THIRD_PARTY_README
index ba48858c2..a93b35b99 100644
--- a/THIRD_PARTY_README
+++ b/THIRD_PARTY_README
@@ -1400,7 +1400,7 @@ THE SOFTWARE.
-------------------------------------------------------------------------------
%% This notice is provided with respect to Little CMS 2.4, which may be
-included with OpenJDK 8.
+included with JRE 8, JDK 8, and OpenJDK 8.
--- begin of LICENSE ---
diff --git a/src/share/classes/java/lang/invoke/AbstractValidatingLambdaMetafactory.java b/src/share/classes/java/lang/invoke/AbstractValidatingLambdaMetafactory.java
index fa6ed4d5f..10c3ed146 100644
--- a/src/share/classes/java/lang/invoke/AbstractValidatingLambdaMetafactory.java
+++ b/src/share/classes/java/lang/invoke/AbstractValidatingLambdaMetafactory.java
@@ -114,6 +114,11 @@ import static sun.invoke.util.Wrapper.isWrapperType;
Class<?>[] markerInterfaces,
MethodType[] additionalBridges)
throws LambdaConversionException {
+ if ((caller.lookupModes() & MethodHandles.Lookup.PRIVATE) == 0) {
+ throw new LambdaConversionException(String.format(
+ "Invalid caller: %s",
+ caller.lookupClass().getName()));
+ }
this.targetClass = caller.lookupClass();
this.invokedType = invokedType;
@@ -221,6 +226,13 @@ import static sun.invoke.util.Wrapper.isWrapperType;
String.format("Invalid receiver type %s; not a subtype of implementation type %s",
receiverClass, implDefiningClass));
}
+
+ Class<?> implReceiverClass = implMethod.type().parameterType(0);
+ if (implReceiverClass != implDefiningClass && !implReceiverClass.isAssignableFrom(receiverClass)) {
+ throw new LambdaConversionException(
+ String.format("Invalid receiver type %s; not a subtype of implementation receiver type %s",
+ receiverClass, implReceiverClass));
+ }
} else {
// no receiver
capturedStart = 0;
@@ -256,11 +268,17 @@ import static sun.invoke.util.Wrapper.isWrapperType;
(implKind == MethodHandleInfo.REF_newInvokeSpecial)
? implDefiningClass
: implMethodType.returnType();
+ Class<?> samReturnType = samMethodType.returnType();
if (!isAdaptableToAsReturn(actualReturnType, expectedType)) {
throw new LambdaConversionException(
String.format("Type mismatch for lambda return: %s is not convertible to %s",
actualReturnType, expectedType));
}
+ if (!isAdaptableToAsReturn(expectedType, samReturnType)) {
+ throw new LambdaConversionException(
+ String.format("Type mismatch for lambda expected return: %s is not convertible to %s",
+ expectedType, samReturnType));
+ }
}
/**
diff --git a/src/share/classes/java/util/jar/JarFile.java b/src/share/classes/java/util/jar/JarFile.java
index 9aac6a10c..f78c36c61 100644
--- a/src/share/classes/java/util/jar/JarFile.java
+++ b/src/share/classes/java/util/jar/JarFile.java
@@ -40,6 +40,7 @@ import sun.misc.IOUtils;
import sun.security.action.GetPropertyAction;
import sun.security.util.ManifestEntryVerifier;
import sun.misc.SharedSecrets;
+import sun.security.util.SignatureFileVerifier;
/**
* The <code>JarFile</code> class is used to read the contents of a jar file
@@ -364,11 +365,13 @@ class JarFile extends ZipFile {
String[] names = getMetaInfEntryNames();
if (names != null) {
for (int i = 0; i < names.length; i++) {
- JarEntry e = getJarEntry(names[i]);
- if (e == null) {
- throw new JarException("corrupted jar file");
- }
- if (!e.isDirectory()) {
+ String uname = names[i].toUpperCase(Locale.ENGLISH);
+ if (MANIFEST_NAME.equals(uname)
+ || SignatureFileVerifier.isBlockOrSF(uname)) {
+ JarEntry e = getJarEntry(names[i]);
+ if (e == null) {
+ throw new JarException("corrupted jar file");
+ }
if (mev == null) {
mev = new ManifestEntryVerifier
(getManifestFromReference());
diff --git a/src/share/classes/sun/invoke/util/VerifyAccess.java b/src/share/classes/sun/invoke/util/VerifyAccess.java
index 02a6e6643..d8b338a39 100644
--- a/src/share/classes/sun/invoke/util/VerifyAccess.java
+++ b/src/share/classes/sun/invoke/util/VerifyAccess.java
@@ -118,7 +118,7 @@ public class VerifyAccess {
isSamePackage(defc, lookupClass))
return true;
if ((allowedModes & PROTECTED) != 0 &&
- isPublicSuperClass(defc, lookupClass))
+ isSuperClass(defc, lookupClass))
return true;
return false;
case PACKAGE_ONLY: // That is, zero. Unmarked member is package-only access.
@@ -140,8 +140,8 @@ public class VerifyAccess {
lookupClass.isAssignableFrom(refc));
}
- static boolean isPublicSuperClass(Class<?> defc, Class<?> lookupClass) {
- return isPublic(getClassModifiers(defc)) && defc.isAssignableFrom(lookupClass);
+ static boolean isSuperClass(Class<?> defc, Class<?> lookupClass) {
+ return defc.isAssignableFrom(lookupClass);
}
static int getClassModifiers(Class<?> c) {
diff --git a/src/solaris/native/common/jni_util_md.c b/src/solaris/native/common/jni_util_md.c
index e9e0f4e0f..42ab2de00 100644
--- a/src/solaris/native/common/jni_util_md.c
+++ b/src/solaris/native/common/jni_util_md.c
@@ -23,6 +23,8 @@
* questions.
*/
+#include <string.h>
+
#include "jni.h"
#include "jni_util.h"
#include "dlfcn.h"
@@ -40,7 +42,11 @@ void* getProcessHandle() {
if (procHandle != NULL) {
return procHandle;
}
+#ifdef __APPLE__
+ procHandle = (void*)dlopen(NULL, RTLD_FIRST);
+#else
procHandle = (void*)dlopen(NULL, RTLD_LAZY);
+#endif
return procHandle;
}
diff --git a/test/java/lang/invoke/ProtectedMemberDifferentPackage/Test.java b/test/java/lang/invoke/ProtectedMemberDifferentPackage/Test.java
new file mode 100644
index 000000000..6640a0e4e
--- /dev/null
+++ b/test/java/lang/invoke/ProtectedMemberDifferentPackage/Test.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+/**
+ * @test
+ * @bug 8032585
+ * @summary JSR292: IllegalAccessError when attempting to invoke protected method from different package
+ *
+ * @compile p1/T2.java p2/T3.java
+ * @run main/othervm p2.T3
+ */
+public class Test {}
diff --git a/test/java/lang/invoke/ProtectedMemberDifferentPackage/p1/T2.java b/test/java/lang/invoke/ProtectedMemberDifferentPackage/p1/T2.java
new file mode 100644
index 000000000..d702f9959
--- /dev/null
+++ b/test/java/lang/invoke/ProtectedMemberDifferentPackage/p1/T2.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+package p1;
+
+class T1 {
+ protected void m() { System.out.println("T1.m");}
+}
+
+public class T2 extends T1 {}
diff --git a/test/java/lang/invoke/ProtectedMemberDifferentPackage/p2/T3.java b/test/java/lang/invoke/ProtectedMemberDifferentPackage/p2/T3.java
new file mode 100644
index 000000000..c79ffa955
--- /dev/null
+++ b/test/java/lang/invoke/ProtectedMemberDifferentPackage/p2/T3.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+package p2;
+
+import p1.T2;
+
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodType;
+
+public class T3 extends T2 {
+ public static void main(String[] args) throws Throwable {
+ MethodHandles.lookup().findVirtual(T3.class, "m", MethodType.methodType(void.class));
+ System.out.println("TEST PASSED");
+ }
+}
diff --git a/test/java/lang/invoke/lambda/T8032697.java b/test/java/lang/invoke/lambda/T8032697.java
new file mode 100644
index 000000000..be422a94b
--- /dev/null
+++ b/test/java/lang/invoke/lambda/T8032697.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8032697
+ * @summary Issues with Lambda
+ */
+
+import java.lang.invoke.LambdaMetafactory;
+import java.lang.invoke.LambdaConversionException;
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodType;
+
+import T8032697_anotherpkg.T8032697_A;
+
+public class T8032697 extends T8032697_A {
+
+ interface I {
+ int m();
+ }
+
+ interface IA {
+ int m(T8032697_A x);
+ }
+
+ static MethodHandles.Lookup l;
+ static MethodHandle h;
+ private static MethodType mt(Class<?> k) { return MethodType.methodType(k); }
+ private static MethodType mt(Class<?> k, Class<?> k2) { return MethodType.methodType(k, k2); }
+ private static boolean mf(MethodType mti, MethodType mtf) {
+ try {
+ LambdaMetafactory.metafactory(l, "m", mti,mtf,h,mtf);
+ } catch(LambdaConversionException e) {
+ return true;
+ }
+ return false;
+ }
+
+ public static void main(String[] args) throws Throwable {
+ l = MethodHandles.lookup();
+ h = l.findVirtual(T8032697_A.class, "f", mt(int.class));
+ if (mf(mt(I.class, T8032697.class), mt(int.class))) throw new AssertionError("Error: Should work");
+ if (mf(mt(IA.class), mt(int.class, T8032697.class))) throw new AssertionError("Error: Should work");
+ if (!mf(mt(I.class, T8032697_A.class), mt(int.class))) throw new AssertionError("Error: Should fail");
+ if (!mf(mt(IA.class), mt(int.class, T8032697_A.class))) throw new AssertionError("Error: Should fail");
+ }
+}
diff --git a/test/java/lang/invoke/lambda/T8032697_anotherpkg/T8032697_A.java b/test/java/lang/invoke/lambda/T8032697_anotherpkg/T8032697_A.java
new file mode 100644
index 000000000..d611e3fef
--- /dev/null
+++ b/test/java/lang/invoke/lambda/T8032697_anotherpkg/T8032697_A.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package T8032697_anotherpkg;
+
+public class T8032697_A {
+ protected final int f() { return 2; }
+}
diff --git a/test/java/lang/invoke/lambda/T8032704.java b/test/java/lang/invoke/lambda/T8032704.java
new file mode 100644
index 000000000..9dfe3a0f1
--- /dev/null
+++ b/test/java/lang/invoke/lambda/T8032704.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8032704
+ * @summary Issues with lib perm in Lambda
+ */
+
+import java.io.Closeable;
+import java.lang.invoke.LambdaMetafactory;
+import java.lang.invoke.LambdaConversionException;
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodType;
+
+public class T8032704 {
+
+ public static void here() {}
+ static MethodHandle h;
+ private static MethodType mt(Class<?> k) { return MethodType.methodType(k); }
+ private static boolean mf(MethodHandles.Lookup l) {
+ try {
+ LambdaMetafactory.metafactory(l, "close",
+ mt(Closeable.class),mt(void.class),h,mt(void.class));
+ } catch(LambdaConversionException e) {
+ return true;
+ }
+ return false;
+ }
+
+ public static void main(String[] args) throws Throwable {
+ MethodHandles.Lookup ll = MethodHandles.lookup();
+ h = ll.findStatic(T8032704.class, "here", mt(void.class));
+ if (mf(ll)) throw new AssertionError("Error: Should work");
+ if (!mf(MethodHandles.publicLookup())) throw new AssertionError("Error: Should fail - public");
+ if (!mf(ll.in(T8032704other.class))) throw new AssertionError("Error: Should fail - other");
+ if (!mf(ll.in(Thread.class))) throw new AssertionError("Error: Should fail - Thread");
+ }
+}
+
+class T8032704other {}
diff --git a/test/java/lang/invoke/lambda/T8032711.java b/test/java/lang/invoke/lambda/T8032711.java
new file mode 100644
index 000000000..b01009f83
--- /dev/null
+++ b/test/java/lang/invoke/lambda/T8032711.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8032711
+ * @summary Issue with Lambda in handling
+ */
+
+import java.lang.invoke.LambdaMetafactory;
+import java.lang.invoke.LambdaConversionException;
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodType;
+
+public class T8032711 {
+
+ interface I {
+ void m();
+ }
+
+ static void here() {}
+ static MethodHandles.Lookup l;
+ static MethodHandle h;
+ private static MethodType mt(Class<?> k) { return MethodType.methodType(k); }
+ private static boolean mf(Class<?> k) {
+ try {
+ LambdaMetafactory.metafactory(l, "m",
+ mt(I.class),mt(k),h,mt(void.class));
+ } catch(LambdaConversionException e) {
+ return true;
+ }
+ return false;
+ }
+
+ public static void main(String[] args) throws Throwable {
+ l = MethodHandles.lookup();
+ h = l.findStatic(T8032711.class, "here", mt(void.class));
+ if (mf(void.class)) throw new AssertionError("Error: Should work");
+ if (!mf(String.class)) throw new AssertionError("Error: Should fail");
+ }
+}
diff --git a/test/sun/security/tools/jarsigner/EntriesOrder.java b/test/sun/security/tools/jarsigner/EntriesOrder.java
new file mode 100644
index 000000000..96c90e98e
--- /dev/null
+++ b/test/sun/security/tools/jarsigner/EntriesOrder.java
@@ -0,0 +1,199 @@
+/*
+ * Copyright (c) 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test
+ * @bug 8031572
+ * @summary jarsigner -verify exits with 0 when a jar file is not properly signed
+ */
+
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.security.cert.Certificate;
+import java.util.*;
+import java.util.jar.JarEntry;
+import java.util.jar.JarFile;
+import java.util.jar.JarInputStream;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipOutputStream;
+
+public class EntriesOrder {
+
+ public static void main(String[] args) throws Exception {
+
+ String[] entries = {
+ "META-INF/",
+ "META-INF/MANIFEST.MF",
+ "META-INF/A.RSA",
+ "META-INF/A.SF",
+ "META-INF/inf",
+ "a"};
+
+ Map<String,byte[]> content = new HashMap<>();
+
+ // We will create a jar containing entries above. Try all permutations
+ // and confirm 1) When opened as a JarFile, we can always get 3 signed
+ // ones (MANIFEST, inf, a), and 2) When opened as a JarInputStream,
+ // when the order is correct (MANIFEST at beginning, followed by RSA/SF,
+ // directory ignored), we can get 2 signed ones (inf, a).
+
+ // Prepares raw files
+ Files.write(Paths.get("a"), "a".getBytes());
+ Files.createDirectory(Paths.get("META-INF/"));
+ Files.write(Paths.get("META-INF/inf"), "inf".getBytes());
+
+ // Pack, sign, and extract to get all files
+ sun.tools.jar.Main m =
+ new sun.tools.jar.Main(System.out, System.err, "jar");
+ if (!m.run("cvf a.jar a META-INF/inf".split(" "))) {
+ throw new Exception("jar creation failed");
+ }
+ sun.security.tools.keytool.Main.main(
+ ("-keystore jks -storepass changeit -keypass changeit -dname" +
+ " CN=A -alias a -genkeypair -keyalg rsa").split(" "));
+ sun.security.tools.jarsigner.Main.main(
+ "-keystore jks -storepass changeit a.jar a".split(" "));
+ m = new sun.tools.jar.Main(System.out, System.err, "jar");
+ if (!m.run("xvf a.jar".split(" "))) {
+ throw new Exception("jar extraction failed");
+ }
+
+ // Data
+ for (String s: entries) {
+ if (!s.endsWith("/")) {
+ content.put(s, Files.readAllBytes(Paths.get(s)));
+ }
+ }
+
+ // Test
+ for (List<String> perm: Permute(entries)) {
+
+ // Recreate a jar
+ try (ZipOutputStream zos
+ = new ZipOutputStream(new FileOutputStream("x.jar"))) {
+ for (String e: perm) {
+ zos.putNextEntry(new ZipEntry(e));
+ if (Paths.get(e).toFile().isDirectory()) continue;
+ zos.write(content.get(e));
+ }
+ }
+
+ // Open with JarFile, number of signed entries should be 3.
+ int cc = 0;
+ try (JarFile jf = new JarFile("x.jar")) {
+ Enumeration<JarEntry> jes = jf.entries();
+ while (jes.hasMoreElements()) {
+ JarEntry je = jes.nextElement();
+ sun.misc.IOUtils.readFully(jf.getInputStream(je), -1, true);
+ Certificate[] certs = je.getCertificates();
+ if (certs != null && certs.length > 0) {
+ cc++;
+ }
+ }
+ }
+
+ if (cc != 3) {
+ System.out.println(perm + " - jf - " + cc);
+ throw new Exception();
+ }
+
+ // Open with JarInputStream
+ int signed;
+
+ perm.remove("META-INF/");
+ if (perm.get(0).equals("META-INF/MANIFEST.MF") &&
+ perm.get(1).contains("/A.") &&
+ perm.get(2).contains("/A.")) {
+ signed = 2; // Good order
+ } else {
+ signed = 0; // Bad order. In this case, the number of signed
+ // entries is not documented. Just test impl.
+ }
+
+ cc = 0;
+ try (JarInputStream jis
+ = new JarInputStream(new FileInputStream("x.jar"))) {
+ while (true) {
+ JarEntry je = jis.getNextJarEntry();
+ if (je == null) break;
+ sun.misc.IOUtils.readFully(jis, -1, true);
+ Certificate[] certs = je.getCertificates();
+ if (certs != null && certs.length > 0) {
+ cc++;
+ }
+ }
+ }
+
+ if (cc != signed) {
+ System.out.println(perm + " - jis - " + cc + " " + signed);
+ throw new Exception();
+ }
+ }
+ }
+
+ // Helper method to return all permutations of an array. Each output can
+ // be altered without damaging the iteration process.
+ static Iterable<List<String>> Permute(String[] entries) {
+ return new Iterable<List<String>>() {
+
+ int s = entries.length;
+ long c = factorial(s) - 1; // number of permutations
+
+ private long factorial(int n) {
+ return (n == 1) ? 1: (n * factorial(n-1));
+ }
+
+ @Override
+ public Iterator<List<String>> iterator() {
+ return new Iterator<List<String>>() {
+ @Override
+ public boolean hasNext() {
+ return c >= 0;
+ }
+
+ @Override
+ public List<String> next() {
+ if (c < 0) return null;
+ List<String> result = new ArrayList<>(s);
+ LinkedList<String> source = new LinkedList<>(
+ Arrays.asList(entries));
+ // Treat c as a integer with different radixes at
+ // different digits, i.e. at digit 0, radix is s;
+ // at digit 1, radix is s-1. Thus a s-digit number
+ // is able to represent s! different values.
+ long n = c;
+ for (int i=s; i>=1; i--) {
+ int x = (int)(n % i);
+ result.add(source.remove(x));
+ n = n / i;
+ }
+ c--;
+ return result;
+ }
+ };
+ }
+ };
+ }
+}