--- a/jdk/make/CompileModuleTools.gmk Fri Jan 20 10:28:34 2017 -0800
+++ b/jdk/make/CompileModuleTools.gmk Fri Jan 20 08:53:42 2017 -0800
@@ -37,6 +37,5 @@
build/tools/jigsaw, \
BIN := $(TOOLS_CLASSES_DIR), \
ADD_JAVAC_FLAGS := \
- --add-exports jdk.jdeps/com.sun.tools.classfile=ALL-UNNAMED \
--add-exports java.base/jdk.internal.module=ALL-UNNAMED \
))
--- a/jdk/make/ModuleTools.gmk Fri Jan 20 10:28:34 2017 -0800
+++ b/jdk/make/ModuleTools.gmk Fri Jan 20 08:53:42 2017 -0800
@@ -39,7 +39,6 @@
build.tools.jigsaw.GenGraphs
TOOL_MODULESUMMARY := $(BUILD_JAVA) -esa -ea -cp $(TOOLS_CLASSES_DIR) \
- --add-exports jdk.jdeps/com.sun.tools.classfile=ALL-UNNAMED \
build.tools.jigsaw.ModuleSummary
TOOL_ADD_PACKAGES_ATTRIBUTE := $(BUILD_JAVA) $(JAVA_FLAGS_SMALL) \
--- a/jdk/src/java.base/share/classes/com/sun/net/ssl/HttpsURLConnection.java Fri Jan 20 10:28:34 2017 -0800
+++ b/jdk/src/java.base/share/classes/com/sun/net/ssl/HttpsURLConnection.java Fri Jan 20 08:53:42 2017 -0800
@@ -69,6 +69,10 @@
/**
* Returns the server's X.509 certificate chain, or null if
* the server did not authenticate.
+ * <P>
+ * Note: The returned value may not be a valid certificate chain
+ * and should not be relied on for trust decisions.
+ *
* @return the server certificate chain
*/
public abstract Certificate[] getServerCertificates()
--- a/jdk/src/java.base/share/classes/java/lang/Class.java Fri Jan 20 10:28:34 2017 -0800
+++ b/jdk/src/java.base/share/classes/java/lang/Class.java Fri Jan 20 08:53:42 2017 -0800
@@ -508,8 +508,9 @@
public T newInstance()
throws InstantiationException, IllegalAccessException
{
- if (System.getSecurityManager() != null) {
- checkMemberAccess(Member.PUBLIC, Reflection.getCallerClass(), false);
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null) {
+ checkMemberAccess(sm, Member.PUBLIC, Reflection.getCallerClass(), false);
}
// NOTE: the following code may not be strictly correct under
@@ -1223,38 +1224,27 @@
// Perform access check
final Class<?> enclosingCandidate = enclosingInfo.getEnclosingClass();
- enclosingCandidate.checkMemberAccess(Member.DECLARED,
- Reflection.getCallerClass(), true);
- // Client is ok to access declared methods but j.l.Class might not be.
- Method[] candidates = AccessController.doPrivileged(
- new PrivilegedAction<>() {
- @Override
- public Method[] run() {
- return enclosingCandidate.getDeclaredMethods();
- }
- });
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null) {
+ enclosingCandidate.checkMemberAccess(sm, Member.DECLARED,
+ Reflection.getCallerClass(), true);
+ }
+ Method[] candidates = enclosingCandidate.privateGetDeclaredMethods(false);
+
/*
* Loop over all declared methods; match method name,
* number of and type of parameters, *and* return
* type. Matching return type is also necessary
* because of covariant returns, etc.
*/
- for(Method m: candidates) {
- if (m.getName().equals(enclosingInfo.getName()) ) {
- Class<?>[] candidateParamClasses = m.getParameterTypes();
- if (candidateParamClasses.length == parameterClasses.length) {
- boolean matches = true;
- for(int i = 0; i < candidateParamClasses.length; i++) {
- if (!candidateParamClasses[i].equals(parameterClasses[i])) {
- matches = false;
- break;
- }
- }
-
- if (matches) { // finally, check return type
- if (m.getReturnType().equals(returnType) )
- return m;
- }
+ ReflectionFactory fact = getReflectionFactory();
+ for (Method m : candidates) {
+ if (m.getName().equals(enclosingInfo.getName()) &&
+ arrayContentsEq(parameterClasses,
+ fact.getExecutableSharedParameterTypes(m))) {
+ // finally, check return type
+ if (m.getReturnType().equals(returnType)) {
+ return fact.copyMethod(m);
}
}
}
@@ -1390,33 +1380,23 @@
// Perform access check
final Class<?> enclosingCandidate = enclosingInfo.getEnclosingClass();
- enclosingCandidate.checkMemberAccess(Member.DECLARED,
- Reflection.getCallerClass(), true);
- // Client is ok to access declared methods but j.l.Class might not be.
- Constructor<?>[] candidates = AccessController.doPrivileged(
- new PrivilegedAction<>() {
- @Override
- public Constructor<?>[] run() {
- return enclosingCandidate.getDeclaredConstructors();
- }
- });
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null) {
+ enclosingCandidate.checkMemberAccess(sm, Member.DECLARED,
+ Reflection.getCallerClass(), true);
+ }
+
+ Constructor<?>[] candidates = enclosingCandidate
+ .privateGetDeclaredConstructors(false);
/*
* Loop over all declared constructors; match number
* of and type of parameters.
*/
- for(Constructor<?> c: candidates) {
- Class<?>[] candidateParamClasses = c.getParameterTypes();
- if (candidateParamClasses.length == parameterClasses.length) {
- boolean matches = true;
- for(int i = 0; i < candidateParamClasses.length; i++) {
- if (!candidateParamClasses[i].equals(parameterClasses[i])) {
- matches = false;
- break;
- }
- }
-
- if (matches)
- return c;
+ ReflectionFactory fact = getReflectionFactory();
+ for (Constructor<?> c : candidates) {
+ if (arrayContentsEq(parameterClasses,
+ fact.getExecutableSharedParameterTypes(c))) {
+ return fact.copyConstructor(c);
}
}
@@ -1446,9 +1426,13 @@
public Class<?> getDeclaringClass() throws SecurityException {
final Class<?> candidate = getDeclaringClass0();
- if (candidate != null)
- candidate.checkPackageAccess(
+ if (candidate != null) {
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null) {
+ candidate.checkPackageAccess(sm,
ClassLoader.getClassLoader(Reflection.getCallerClass()), true);
+ }
+ }
return candidate;
}
@@ -1496,9 +1480,13 @@
enclosingCandidate = enclosingClass;
}
- if (enclosingCandidate != null)
- enclosingCandidate.checkPackageAccess(
+ if (enclosingCandidate != null) {
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null) {
+ enclosingCandidate.checkPackageAccess(sm,
ClassLoader.getClassLoader(Reflection.getCallerClass()), true);
+ }
+ }
return enclosingCandidate;
}
@@ -1688,7 +1676,10 @@
*/
@CallerSensitive
public Class<?>[] getClasses() {
- checkMemberAccess(Member.PUBLIC, Reflection.getCallerClass(), false);
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null) {
+ checkMemberAccess(sm, Member.PUBLIC, Reflection.getCallerClass(), false);
+ }
// Privileged so this implementation can look at DECLARED classes,
// something the caller might not have privilege to do. The code here
@@ -1754,7 +1745,10 @@
*/
@CallerSensitive
public Field[] getFields() throws SecurityException {
- checkMemberAccess(Member.PUBLIC, Reflection.getCallerClass(), true);
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null) {
+ checkMemberAccess(sm, Member.PUBLIC, Reflection.getCallerClass(), true);
+ }
return copyFields(privateGetPublicFields(null));
}
@@ -1841,7 +1835,10 @@
*/
@CallerSensitive
public Method[] getMethods() throws SecurityException {
- checkMemberAccess(Member.PUBLIC, Reflection.getCallerClass(), true);
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null) {
+ checkMemberAccess(sm, Member.PUBLIC, Reflection.getCallerClass(), true);
+ }
return copyMethods(privateGetPublicMethods());
}
@@ -1877,7 +1874,10 @@
*/
@CallerSensitive
public Constructor<?>[] getConstructors() throws SecurityException {
- checkMemberAccess(Member.PUBLIC, Reflection.getCallerClass(), true);
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null) {
+ checkMemberAccess(sm, Member.PUBLIC, Reflection.getCallerClass(), true);
+ }
return copyConstructors(privateGetDeclaredConstructors(true));
}
@@ -1928,7 +1928,10 @@
public Field getField(String name)
throws NoSuchFieldException, SecurityException {
Objects.requireNonNull(name);
- checkMemberAccess(Member.PUBLIC, Reflection.getCallerClass(), true);
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null) {
+ checkMemberAccess(sm, Member.PUBLIC, Reflection.getCallerClass(), true);
+ }
Field field = getField0(name);
if (field == null) {
throw new NoSuchFieldException(name);
@@ -2034,10 +2037,13 @@
public Method getMethod(String name, Class<?>... parameterTypes)
throws NoSuchMethodException, SecurityException {
Objects.requireNonNull(name);
- checkMemberAccess(Member.PUBLIC, Reflection.getCallerClass(), true);
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null) {
+ checkMemberAccess(sm, Member.PUBLIC, Reflection.getCallerClass(), true);
+ }
Method method = getMethod0(name, parameterTypes);
if (method == null) {
- throw new NoSuchMethodException(getName() + "." + name + argumentTypesToString(parameterTypes));
+ throw new NoSuchMethodException(methodToString(name, parameterTypes));
}
return getReflectionFactory().copyMethod(method);
}
@@ -2092,8 +2098,12 @@
*/
@CallerSensitive
public Constructor<T> getConstructor(Class<?>... parameterTypes)
- throws NoSuchMethodException, SecurityException {
- checkMemberAccess(Member.PUBLIC, Reflection.getCallerClass(), true);
+ throws NoSuchMethodException, SecurityException
+ {
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null) {
+ checkMemberAccess(sm, Member.PUBLIC, Reflection.getCallerClass(), true);
+ }
return getReflectionFactory().copyConstructor(
getConstructor0(parameterTypes, Member.PUBLIC));
}
@@ -2136,7 +2146,10 @@
*/
@CallerSensitive
public Class<?>[] getDeclaredClasses() throws SecurityException {
- checkMemberAccess(Member.DECLARED, Reflection.getCallerClass(), false);
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null) {
+ checkMemberAccess(sm, Member.DECLARED, Reflection.getCallerClass(), false);
+ }
return getDeclaredClasses0();
}
@@ -2185,7 +2198,10 @@
*/
@CallerSensitive
public Field[] getDeclaredFields() throws SecurityException {
- checkMemberAccess(Member.DECLARED, Reflection.getCallerClass(), true);
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null) {
+ checkMemberAccess(sm, Member.DECLARED, Reflection.getCallerClass(), true);
+ }
return copyFields(privateGetDeclaredFields(false));
}
@@ -2244,7 +2260,10 @@
*/
@CallerSensitive
public Method[] getDeclaredMethods() throws SecurityException {
- checkMemberAccess(Member.DECLARED, Reflection.getCallerClass(), true);
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null) {
+ checkMemberAccess(sm, Member.DECLARED, Reflection.getCallerClass(), true);
+ }
return copyMethods(privateGetDeclaredMethods(false));
}
@@ -2289,7 +2308,10 @@
*/
@CallerSensitive
public Constructor<?>[] getDeclaredConstructors() throws SecurityException {
- checkMemberAccess(Member.DECLARED, Reflection.getCallerClass(), true);
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null) {
+ checkMemberAccess(sm, Member.DECLARED, Reflection.getCallerClass(), true);
+ }
return copyConstructors(privateGetDeclaredConstructors(false));
}
@@ -2338,7 +2360,10 @@
public Field getDeclaredField(String name)
throws NoSuchFieldException, SecurityException {
Objects.requireNonNull(name);
- checkMemberAccess(Member.DECLARED, Reflection.getCallerClass(), true);
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null) {
+ checkMemberAccess(sm, Member.DECLARED, Reflection.getCallerClass(), true);
+ }
Field field = searchFields(privateGetDeclaredFields(false), name);
if (field == null) {
throw new NoSuchFieldException(name);
@@ -2399,10 +2424,13 @@
public Method getDeclaredMethod(String name, Class<?>... parameterTypes)
throws NoSuchMethodException, SecurityException {
Objects.requireNonNull(name);
- checkMemberAccess(Member.DECLARED, Reflection.getCallerClass(), true);
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null) {
+ checkMemberAccess(sm, Member.DECLARED, Reflection.getCallerClass(), true);
+ }
Method method = searchMethods(privateGetDeclaredMethods(false), name, parameterTypes);
if (method == null) {
- throw new NoSuchMethodException(getName() + "." + name + argumentTypesToString(parameterTypes));
+ throw new NoSuchMethodException(methodToString(name, parameterTypes));
}
return getReflectionFactory().copyMethod(method);
}
@@ -2448,8 +2476,13 @@
*/
@CallerSensitive
public Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes)
- throws NoSuchMethodException, SecurityException {
- checkMemberAccess(Member.DECLARED, Reflection.getCallerClass(), true);
+ throws NoSuchMethodException, SecurityException
+ {
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null) {
+ checkMemberAccess(sm, Member.DECLARED, Reflection.getCallerClass(), true);
+ }
+
return getReflectionFactory().copyConstructor(
getConstructor0(parameterTypes, Member.DECLARED));
}
@@ -2697,51 +2730,49 @@
*
* <p> Default policy: allow all clients access with normal Java access
* control.
+ *
+ * <p> NOTE: should only be called if a SecurityManager is installed
*/
- private void checkMemberAccess(int which, Class<?> caller, boolean checkProxyInterfaces) {
- final SecurityManager s = System.getSecurityManager();
- if (s != null) {
- /* Default policy allows access to all {@link Member#PUBLIC} members,
- * as well as access to classes that have the same class loader as the caller.
- * In all other cases, it requires RuntimePermission("accessDeclaredMembers")
- * permission.
- */
- final ClassLoader ccl = ClassLoader.getClassLoader(caller);
+ private void checkMemberAccess(SecurityManager sm, int which,
+ Class<?> caller, boolean checkProxyInterfaces) {
+ /* Default policy allows access to all {@link Member#PUBLIC} members,
+ * as well as access to classes that have the same class loader as the caller.
+ * In all other cases, it requires RuntimePermission("accessDeclaredMembers")
+ * permission.
+ */
+ final ClassLoader ccl = caller.getClassLoader0();
+ if (which != Member.PUBLIC) {
final ClassLoader cl = getClassLoader0();
- if (which != Member.PUBLIC) {
- if (ccl != cl) {
- s.checkPermission(SecurityConstants.CHECK_MEMBER_ACCESS_PERMISSION);
- }
+ if (ccl != cl) {
+ sm.checkPermission(SecurityConstants.CHECK_MEMBER_ACCESS_PERMISSION);
}
- this.checkPackageAccess(ccl, checkProxyInterfaces);
}
+ this.checkPackageAccess(sm, ccl, checkProxyInterfaces);
}
/*
* Checks if a client loaded in ClassLoader ccl is allowed to access this
* class under the current package access policy. If access is denied,
* throw a SecurityException.
+ *
+ * NOTE: this method should only be called if a SecurityManager is active
*/
- private void checkPackageAccess(final ClassLoader ccl, boolean checkProxyInterfaces) {
- final SecurityManager s = System.getSecurityManager();
- if (s != null) {
- final ClassLoader cl = getClassLoader0();
-
- if (ReflectUtil.needsPackageAccessCheck(ccl, cl)) {
- String name = this.getName();
- int i = name.lastIndexOf('.');
- if (i != -1) {
- // skip the package access check on a proxy class in default proxy package
- String pkg = name.substring(0, i);
- if (!Proxy.isProxyClass(this) || ReflectUtil.isNonPublicProxyClass(this)) {
- s.checkPackageAccess(pkg);
- }
+ private void checkPackageAccess(SecurityManager sm, final ClassLoader ccl,
+ boolean checkProxyInterfaces) {
+ final ClassLoader cl = getClassLoader0();
+
+ if (ReflectUtil.needsPackageAccessCheck(ccl, cl)) {
+ String pkg = this.getPackageName();
+ if (pkg != null && !pkg.isEmpty()) {
+ // skip the package access check on a proxy class in default proxy package
+ if (!Proxy.isProxyClass(this) || ReflectUtil.isNonPublicProxyClass(this)) {
+ sm.checkPackageAccess(pkg);
}
}
- // check package access on the proxy interfaces
- if (checkProxyInterfaces && Proxy.isProxyClass(this)) {
- ReflectUtil.checkProxyPackageAccess(ccl, this.getInterfaces());
- }
+ }
+ // check package access on the proxy interfaces
+ if (checkProxyInterfaces && Proxy.isProxyClass(this)) {
+ ReflectUtil.checkProxyPackageAccess(ccl, this.getInterfaces());
}
}
@@ -2755,11 +2786,9 @@
while (c.isArray()) {
c = c.getComponentType();
}
- String baseName = c.getName();
- int index = baseName.lastIndexOf('.');
- if (index != -1) {
- name = baseName.substring(0, index).replace('.', '/')
- +"/"+name;
+ String baseName = c.getPackageName();
+ if (baseName != null && !baseName.isEmpty()) {
+ name = baseName.replace('.', '/') + "/" + name;
}
} else {
name = name.substring(1);
@@ -3233,7 +3262,7 @@
return constructor;
}
}
- throw new NoSuchMethodException(getName() + ".<init>" + argumentTypesToString(parameterTypes));
+ throw new NoSuchMethodException(methodToString("<init>", parameterTypes));
}
//
@@ -3294,8 +3323,11 @@
private native Constructor<T>[] getDeclaredConstructors0(boolean publicOnly);
private native Class<?>[] getDeclaredClasses0();
- private static String argumentTypesToString(Class<?>[] argTypes) {
- StringJoiner sj = new StringJoiner(", ", "(", ")");
+ /**
+ * Helper method to get the method name from arguments.
+ */
+ private String methodToString(String name, Class<?>[] argTypes) {
+ StringJoiner sj = new StringJoiner(", ", getName() + "." + name + "(", ")");
if (argTypes != null) {
for (int i = 0; i < argTypes.length; i++) {
Class<?> c = argTypes[i];
--- a/jdk/src/java.base/share/classes/java/lang/SecurityManager.java Fri Jan 20 10:28:34 2017 -0800
+++ b/jdk/src/java.base/share/classes/java/lang/SecurityManager.java Fri Jan 20 08:53:42 2017 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1995, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1995, 2017, 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
@@ -25,18 +25,30 @@
package java.lang;
-import java.security.*;
+import java.lang.RuntimePermission;
+import java.lang.module.ModuleDescriptor;
+import java.lang.module.ModuleDescriptor.Exports;
+import java.lang.module.ModuleDescriptor.Opens;
+import java.lang.reflect.Layer;
+import java.lang.reflect.Member;
+import java.lang.reflect.Module;
import java.io.FileDescriptor;
import java.io.File;
import java.io.FilePermission;
-import java.util.PropertyPermission;
-import java.lang.RuntimePermission;
+import java.net.InetAddress;
import java.net.SocketPermission;
-import java.net.NetPermission;
-import java.util.Hashtable;
-import java.net.InetAddress;
-import java.lang.reflect.*;
-import java.net.URL;
+import java.security.AccessControlContext;
+import java.security.AccessController;
+import java.security.Permission;
+import java.security.PrivilegedAction;
+import java.security.Security;
+import java.security.SecurityPermission;
+import java.util.HashSet;
+import java.util.Objects;
+import java.util.PropertyPermission;
+import java.util.Set;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
import jdk.internal.reflect.CallerSensitive;
import sun.security.util.SecurityConstants;
@@ -1415,46 +1427,108 @@
}
}
- if (packages == null)
+ if (packages == null) {
packages = new String[0];
+ }
return packages;
}
+ // The non-exported packages of the modules in the boot layer that are
+ // loaded by the platform class loader or its ancestors. A non-exported
+ // package is a package that either is not exported at all by its containing
+ // module or is exported in a qualified fashion by its containing module.
+ private static final Set<String> nonExportedPkgs;
+
+ static {
+ // Get the modules in the boot layer
+ Stream<Module> bootLayerModules = Layer.boot().modules().stream();
+
+ // Filter out the modules loaded by the boot or platform loader
+ PrivilegedAction<Set<Module>> pa = () ->
+ bootLayerModules.filter(SecurityManager::isBootOrPlatformModule)
+ .collect(Collectors.toSet());
+ Set<Module> modules = AccessController.doPrivileged(pa);
+
+ // Filter out the non-exported packages
+ nonExportedPkgs = modules.stream()
+ .map(Module::getDescriptor)
+ .map(SecurityManager::nonExportedPkgs)
+ .flatMap(Set::stream)
+ .collect(Collectors.toSet());
+ }
+
+ /**
+ * Returns true if the module's loader is the boot or platform loader.
+ */
+ private static boolean isBootOrPlatformModule(Module m) {
+ return m.getClassLoader() == null ||
+ m.getClassLoader() == ClassLoader.getPlatformClassLoader();
+ }
+
/**
- * Throws a <code>SecurityException</code> if the
- * calling thread is not allowed to access the package specified by
- * the argument.
- * <p>
- * This method is used by the <code>loadClass</code> method of class
- * loaders.
+ * Returns the non-exported packages of the specified module.
+ */
+ private static Set<String> nonExportedPkgs(ModuleDescriptor md) {
+ // start with all packages in the module
+ Set<String> pkgs = new HashSet<>(md.packages());
+
+ // remove the non-qualified exported packages
+ md.exports().stream()
+ .filter(p -> !p.isQualified())
+ .map(Exports::source)
+ .forEach(pkgs::remove);
+
+ // remove the non-qualified open packages
+ md.opens().stream()
+ .filter(p -> !p.isQualified())
+ .map(Opens::source)
+ .forEach(pkgs::remove);
+
+ return pkgs;
+ }
+
+ /**
+ * Throws a {@code SecurityException} if the calling thread is not allowed
+ * to access the specified package.
* <p>
- * This method first gets a list of
- * restricted packages by obtaining a comma-separated list from
- * a call to
- * <code>java.security.Security.getProperty("package.access")</code>,
- * and checks to see if <code>pkg</code> starts with or equals
- * any of the restricted packages. If it does, then
- * <code>checkPermission</code> gets called with the
- * <code>RuntimePermission("accessClassInPackage."+pkg)</code>
- * permission.
+ * This method is called by the {@code loadClass} method of class loaders.
+ * <p>
+ * This method checks if the specified package starts with or equals
+ * any of the packages in the {@code package.access} Security Property.
+ * An implementation may also check the package against an additional
+ * list of restricted packages as noted below. If the package is restricted,
+ * {@link #checkPermission(Permission)} is called with a
+ * {@code RuntimePermission("accessClassInPackage."+pkg)} permission.
* <p>
- * If this method is overridden, then
- * <code>super.checkPackageAccess</code> should be called
- * as the first line in the overridden method.
+ * If this method is overridden, then {@code super.checkPackageAccess}
+ * should be called as the first line in the overridden method.
+ *
+ * @implNote
+ * This implementation also restricts all non-exported packages of modules
+ * loaded by {@linkplain ClassLoader#getPlatformClassLoader
+ * the platform class loader} or its ancestors. A "non-exported package"
+ * refers to a package that is not exported to all modules. Specifically,
+ * it refers to a package that either is not exported at all by its
+ * containing module or is exported in a qualified fashion by its
+ * containing module.
*
* @param pkg the package name.
- * @exception SecurityException if the calling thread does not have
+ * @throws SecurityException if the calling thread does not have
* permission to access the specified package.
- * @exception NullPointerException if the package name argument is
- * <code>null</code>.
- * @see java.lang.ClassLoader#loadClass(java.lang.String, boolean)
- * loadClass
+ * @throws NullPointerException if the package name argument is
+ * {@code null}.
+ * @see java.lang.ClassLoader#loadClass(String, boolean) loadClass
* @see java.security.Security#getProperty getProperty
- * @see #checkPermission(java.security.Permission) checkPermission
+ * @see #checkPermission(Permission) checkPermission
*/
public void checkPackageAccess(String pkg) {
- if (pkg == null) {
- throw new NullPointerException("package name can't be null");
+ Objects.requireNonNull(pkg, "package name can't be null");
+
+ // check if pkg is not exported to all modules
+ if (nonExportedPkgs.contains(pkg)) {
+ checkPermission(
+ new RuntimePermission("accessClassInPackage." + pkg));
+ return;
}
String[] restrictedPkgs;
@@ -1512,36 +1586,48 @@
}
/**
- * Throws a <code>SecurityException</code> if the
- * calling thread is not allowed to define classes in the package
- * specified by the argument.
+ * Throws a {@code SecurityException} if the calling thread is not
+ * allowed to define classes in the specified package.
* <p>
- * This method is used by the <code>loadClass</code> method of some
+ * This method is called by the {@code loadClass} method of some
* class loaders.
* <p>
- * This method first gets a list of restricted packages by
- * obtaining a comma-separated list from a call to
- * <code>java.security.Security.getProperty("package.definition")</code>,
- * and checks to see if <code>pkg</code> starts with or equals
- * any of the restricted packages. If it does, then
- * <code>checkPermission</code> gets called with the
- * <code>RuntimePermission("defineClassInPackage."+pkg)</code>
- * permission.
+ * This method checks if the specified package starts with or equals
+ * any of the packages in the {@code package.definition} Security
+ * Property. An implementation may also check the package against an
+ * additional list of restricted packages as noted below. If the package
+ * is restricted, {@link #checkPermission(Permission)} is called with a
+ * {@code RuntimePermission("defineClassInPackage."+pkg)} permission.
* <p>
- * If this method is overridden, then
- * <code>super.checkPackageDefinition</code> should be called
- * as the first line in the overridden method.
+ * If this method is overridden, then {@code super.checkPackageDefinition}
+ * should be called as the first line in the overridden method.
+ *
+ * @implNote
+ * This implementation also restricts all non-exported packages of modules
+ * loaded by {@linkplain ClassLoader#getPlatformClassLoader
+ * the platform class loader} or its ancestors. A "non-exported package"
+ * refers to a package that is not exported to all modules. Specifically,
+ * it refers to a package that either is not exported at all by its
+ * containing module or is exported in a qualified fashion by its
+ * containing module.
*
* @param pkg the package name.
- * @exception SecurityException if the calling thread does not have
+ * @throws SecurityException if the calling thread does not have
* permission to define classes in the specified package.
- * @see java.lang.ClassLoader#loadClass(java.lang.String, boolean)
+ * @throws NullPointerException if the package name argument is
+ * {@code null}.
+ * @see java.lang.ClassLoader#loadClass(String, boolean)
* @see java.security.Security#getProperty getProperty
- * @see #checkPermission(java.security.Permission) checkPermission
+ * @see #checkPermission(Permission) checkPermission
*/
public void checkPackageDefinition(String pkg) {
- if (pkg == null) {
- throw new NullPointerException("package name can't be null");
+ Objects.requireNonNull(pkg, "package name can't be null");
+
+ // check if pkg is not exported to all modules
+ if (nonExportedPkgs.contains(pkg)) {
+ checkPermission(
+ new RuntimePermission("defineClassInPackage." + pkg));
+ return;
}
String[] pkgs;
--- a/jdk/src/java.base/share/classes/java/lang/System.java Fri Jan 20 10:28:34 2017 -0800
+++ b/jdk/src/java.base/share/classes/java/lang/System.java Fri Jan 20 08:53:42 2017 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1994, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1994, 2017, 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
@@ -310,12 +310,13 @@
* @see SecurityManager#checkPermission
* @see java.lang.RuntimePermission
*/
- public static
- void setSecurityManager(final SecurityManager s) {
- try {
- s.checkPackageAccess("java.lang");
- } catch (Exception e) {
- // no-op
+ public static void setSecurityManager(final SecurityManager s) {
+ if (s != null) {
+ try {
+ s.checkPackageAccess("java.lang");
+ } catch (Exception e) {
+ // no-op
+ }
}
setSecurityManager0(s);
}
--- a/jdk/src/java.base/share/classes/java/lang/invoke/CallSite.java Fri Jan 20 10:28:34 2017 -0800
+++ b/jdk/src/java.base/share/classes/java/lang/invoke/CallSite.java Fri Jan 20 08:53:42 2017 -0800
@@ -28,6 +28,8 @@
import static java.lang.invoke.MethodHandleStatics.*;
import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
+import jdk.internal.vm.annotation.Stable;
+
/**
* A {@code CallSite} is a holder for a variable {@link MethodHandle},
* which is called its {@code target}.
@@ -215,19 +217,36 @@
public abstract MethodHandle dynamicInvoker();
/*non-public*/ MethodHandle makeDynamicInvoker() {
- MethodHandle getTarget = GET_TARGET.bindArgumentL(0, this);
+ MethodHandle getTarget = getTargetHandle().bindArgumentL(0, this);
MethodHandle invoker = MethodHandles.exactInvoker(this.type());
return MethodHandles.foldArguments(invoker, getTarget);
}
- private static final MethodHandle GET_TARGET;
- private static final MethodHandle THROW_UCS;
- static {
+ private static @Stable MethodHandle GET_TARGET;
+ private static MethodHandle getTargetHandle() {
+ MethodHandle handle = GET_TARGET;
+ if (handle != null) {
+ return handle;
+ }
try {
- GET_TARGET = IMPL_LOOKUP.
- findVirtual(CallSite.class, "getTarget", MethodType.methodType(MethodHandle.class));
- THROW_UCS = IMPL_LOOKUP.
- findStatic(CallSite.class, "uninitializedCallSite", MethodType.methodType(Object.class, Object[].class));
+ return GET_TARGET = IMPL_LOOKUP.
+ findVirtual(CallSite.class, "getTarget",
+ MethodType.methodType(MethodHandle.class));
+ } catch (ReflectiveOperationException e) {
+ throw newInternalError(e);
+ }
+ }
+
+ private static @Stable MethodHandle THROW_UCS;
+ private static MethodHandle uninitializedCallSiteHandle() {
+ MethodHandle handle = THROW_UCS;
+ if (handle != null) {
+ return handle;
+ }
+ try {
+ return THROW_UCS = IMPL_LOOKUP.
+ findStatic(CallSite.class, "uninitializedCallSite",
+ MethodType.methodType(Object.class, Object[].class));
} catch (ReflectiveOperationException e) {
throw newInternalError(e);
}
@@ -242,7 +261,7 @@
MethodType basicType = targetType.basicType();
MethodHandle invoker = basicType.form().cachedMethodHandle(MethodTypeForm.MH_UNINIT_CS);
if (invoker == null) {
- invoker = THROW_UCS.asType(basicType);
+ invoker = uninitializedCallSiteHandle().asType(basicType);
invoker = basicType.form().setCachedMethodHandle(MethodTypeForm.MH_UNINIT_CS, invoker);
}
// unchecked view is OK since no values will be received or returned
@@ -250,12 +269,16 @@
}
// unsafe stuff:
- private static final long TARGET_OFFSET;
- private static final long CONTEXT_OFFSET;
- static {
+ private static @Stable long TARGET_OFFSET;
+ private static long getTargetOffset() {
+ long offset = TARGET_OFFSET;
+ if (offset > 0) {
+ return offset;
+ }
try {
- TARGET_OFFSET = UNSAFE.objectFieldOffset(CallSite.class.getDeclaredField("target"));
- CONTEXT_OFFSET = UNSAFE.objectFieldOffset(CallSite.class.getDeclaredField("context"));
+ offset = TARGET_OFFSET = UNSAFE.objectFieldOffset(CallSite.class.getDeclaredField("target"));
+ assert(offset > 0);
+ return offset;
} catch (Exception ex) { throw newInternalError(ex); }
}
@@ -265,7 +288,7 @@
}
/*package-private*/
MethodHandle getTargetVolatile() {
- return (MethodHandle) UNSAFE.getObjectVolatile(this, TARGET_OFFSET);
+ return (MethodHandle) UNSAFE.getObjectVolatile(this, getTargetOffset());
}
/*package-private*/
void setTargetVolatile(MethodHandle newTarget) {
@@ -324,7 +347,7 @@
final int NON_SPREAD_ARG_COUNT = 3; // (caller, name, type)
if (NON_SPREAD_ARG_COUNT + argv.length > MethodType.MAX_MH_ARITY)
throw new BootstrapMethodError("too many bootstrap method arguments");
- MethodType bsmType = bootstrapMethod.type();
+
MethodType invocationType = MethodType.genericMethodType(NON_SPREAD_ARG_COUNT + argv.length);
MethodHandle typedBSM = bootstrapMethod.asType(invocationType);
MethodHandle spreader = invocationType.invokers().spreadInvoker(NON_SPREAD_ARG_COUNT);
--- a/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandles.java Fri Jan 20 10:28:34 2017 -0800
+++ b/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandles.java Fri Jan 20 08:53:42 2017 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2008, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2017, 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
@@ -846,8 +846,11 @@
// that does not bluntly restrict classes under packages within
// java.base from looking up MethodHandles or VarHandles.
if (allowedModes == ALL_MODES && lookupClass.getClassLoader() == null) {
- if ((name.startsWith("java.") && !name.startsWith("java.util.concurrent.")) ||
- (name.startsWith("sun.") && !name.startsWith("sun.invoke."))) {
+ if ((name.startsWith("java.") &&
+ !name.equals("java.lang.Thread") &&
+ !name.startsWith("java.util.concurrent.")) ||
+ (name.startsWith("sun.") &&
+ !name.startsWith("sun.invoke."))) {
throw newIllegalArgumentException("illegal lookupClass: " + lookupClass);
}
}
--- a/jdk/src/java.base/share/classes/java/lang/invoke/MethodType.java Fri Jan 20 10:28:34 2017 -0800
+++ b/jdk/src/java.base/share/classes/java/lang/invoke/MethodType.java Fri Jan 20 08:53:42 2017 -0800
@@ -1128,7 +1128,7 @@
public String toMethodDescriptorString() {
String desc = methodDescriptor;
if (desc == null) {
- desc = BytecodeDescriptor.unparse(this);
+ desc = BytecodeDescriptor.unparseMethod(this.rtype, this.ptypes);
methodDescriptor = desc;
}
return desc;
@@ -1256,7 +1256,7 @@
private final ReferenceQueue<T> stale;
public ConcurrentWeakInternSet() {
- this.map = new ConcurrentHashMap<>();
+ this.map = new ConcurrentHashMap<>(512);
this.stale = new ReferenceQueue<>();
}
--- a/jdk/src/java.base/share/classes/java/net/SocketInputStream.java Fri Jan 20 10:28:34 2017 -0800
+++ b/jdk/src/java.base/share/classes/java/net/SocketInputStream.java Fri Jan 20 08:53:42 2017 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1995, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1995, 2016, 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
@@ -155,11 +155,12 @@
}
// bounds check
- if (length <= 0 || off < 0 || off + length > b.length) {
+ if (length <= 0 || off < 0 || length > b.length - off) {
if (length == 0) {
return 0;
}
- throw new ArrayIndexOutOfBoundsException();
+ throw new ArrayIndexOutOfBoundsException("length == " + length
+ + " off == " + off + " buffer length == " + b.length);
}
boolean gotReset = false;
--- a/jdk/src/java.base/share/classes/java/net/SocketOutputStream.java Fri Jan 20 10:28:34 2017 -0800
+++ b/jdk/src/java.base/share/classes/java/net/SocketOutputStream.java Fri Jan 20 08:53:42 2017 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1995, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1995, 2016, 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
@@ -97,11 +97,13 @@
*/
private void socketWrite(byte b[], int off, int len) throws IOException {
- if (len <= 0 || off < 0 || off + len > b.length) {
+
+ if (len <= 0 || off < 0 || len > b.length - off) {
if (len == 0) {
return;
}
- throw new ArrayIndexOutOfBoundsException();
+ throw new ArrayIndexOutOfBoundsException("len == " + len
+ + " off == " + off + " buffer length == " + b.length);
}
FileDescriptor fd = impl.acquireFD();
--- a/jdk/src/java.base/share/classes/java/net/URL.java Fri Jan 20 10:28:34 2017 -0800
+++ b/jdk/src/java.base/share/classes/java/net/URL.java Fri Jan 20 08:53:42 2017 -0800
@@ -1556,9 +1556,6 @@
path = file;
}
- if (port == -1) {
- port = 0;
- }
// Set the object fields.
this.protocol = protocol;
this.host = host;
--- a/jdk/src/java.base/share/classes/java/net/URLClassLoader.java Fri Jan 20 10:28:34 2017 -0800
+++ b/jdk/src/java.base/share/classes/java/net/URLClassLoader.java Fri Jan 20 08:53:42 2017 -0800
@@ -115,8 +115,8 @@
if (security != null) {
security.checkCreateClassLoader();
}
- this.ucp = new URLClassPath(urls);
this.acc = AccessController.getContext();
+ this.ucp = new URLClassPath(urls, acc);
}
URLClassLoader(String name, URL[] urls, ClassLoader parent,
@@ -127,8 +127,8 @@
if (security != null) {
security.checkCreateClassLoader();
}
- this.ucp = new URLClassPath(urls);
this.acc = acc;
+ this.ucp = new URLClassPath(urls, acc);
}
/**
@@ -159,8 +159,8 @@
if (security != null) {
security.checkCreateClassLoader();
}
- this.ucp = new URLClassPath(urls);
this.acc = AccessController.getContext();
+ this.ucp = new URLClassPath(urls, acc);
}
URLClassLoader(URL[] urls, AccessControlContext acc) {
@@ -170,8 +170,8 @@
if (security != null) {
security.checkCreateClassLoader();
}
- this.ucp = new URLClassPath(urls);
this.acc = acc;
+ this.ucp = new URLClassPath(urls, acc);
}
/**
@@ -203,8 +203,8 @@
if (security != null) {
security.checkCreateClassLoader();
}
- this.ucp = new URLClassPath(urls, factory);
this.acc = AccessController.getContext();
+ this.ucp = new URLClassPath(urls, factory, acc);
}
@@ -238,8 +238,8 @@
if (security != null) {
security.checkCreateClassLoader();
}
- this.ucp = new URLClassPath(urls);
this.acc = AccessController.getContext();
+ this.ucp = new URLClassPath(urls, acc);
}
/**
@@ -271,8 +271,8 @@
if (security != null) {
security.checkCreateClassLoader();
}
- this.ucp = new URLClassPath(urls, factory);
this.acc = AccessController.getContext();
+ this.ucp = new URLClassPath(urls, factory, acc);
}
/* A map (used as a set) to keep track of closeable local resources
--- a/jdk/src/java.base/share/classes/java/net/URLStreamHandler.java Fri Jan 20 10:28:34 2017 -0800
+++ b/jdk/src/java.base/share/classes/java/net/URLStreamHandler.java Fri Jan 20 08:53:42 2017 -0800
@@ -161,9 +161,9 @@
(spec.charAt(start + 1) == '/')) {
start += 2;
i = spec.indexOf('/', start);
- if (i < 0) {
+ if (i < 0 || i > limit) {
i = spec.indexOf('?', start);
- if (i < 0)
+ if (i < 0 || i > limit)
i = limit;
}
@@ -171,8 +171,14 @@
int ind = authority.indexOf('@');
if (ind != -1) {
- userInfo = authority.substring(0, ind);
- host = authority.substring(ind+1);
+ if (ind != authority.lastIndexOf('@')) {
+ // more than one '@' in authority. This is not server based
+ userInfo = null;
+ host = null;
+ } else {
+ userInfo = authority.substring(0, ind);
+ host = authority.substring(ind+1);
+ }
} else {
userInfo = null;
}
--- a/jdk/src/java.base/share/classes/java/util/ResourceBundle.java Fri Jan 20 10:28:34 2017 -0800
+++ b/jdk/src/java.base/share/classes/java/util/ResourceBundle.java Fri Jan 20 08:53:42 2017 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2017, 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
@@ -43,6 +43,7 @@
import java.io.IOException;
import java.io.InputStream;
import java.io.UncheckedIOException;
+import java.lang.ref.Reference;
import java.lang.ref.ReferenceQueue;
import java.lang.ref.SoftReference;
import java.lang.ref.WeakReference;
@@ -365,7 +366,7 @@
@Override
public ResourceBundle getBundle(String baseName, Locale locale, Module module) {
// use the given module as the caller to bypass the access check
- return getBundleImpl(module, module, getLoader(module),
+ return getBundleImpl(module, module,
baseName, locale, Control.INSTANCE);
}
@@ -537,63 +538,19 @@
return locale;
}
- /*
- * Automatic determination of the ClassLoader to be used to load
- * resources on behalf of the client.
- */
- private static ClassLoader getLoader(Class<?> caller) {
- ClassLoader cl = caller == null ? null : caller.getClassLoader();
- if (cl == null) {
- // When the caller's loader is the boot class loader, cl is null
- // here. In that case, ClassLoader.getSystemClassLoader() may
- // return the same class loader that the application is
- // using. We therefore use a wrapper ClassLoader to create a
- // separate scope for bundles loaded on behalf of the Java
- // runtime so that these bundles cannot be returned from the
- // cache to the application (5048280).
- cl = RBClassLoader.INSTANCE;
- }
- return cl;
- }
-
private static ClassLoader getLoader(Module module) {
PrivilegedAction<ClassLoader> pa = module::getClassLoader;
return AccessController.doPrivileged(pa);
}
/**
- * A wrapper of ClassLoader.getSystemClassLoader().
+ * @param module a non-null-screened module form the {@link CacheKey#getModule()}.
+ * @return the ClassLoader to use in {@link Control#needsReload}
+ * and {@link Control#newBundle}
*/
- private static class RBClassLoader extends ClassLoader {
- private static final RBClassLoader INSTANCE = AccessController.doPrivileged(
- new PrivilegedAction<RBClassLoader>() {
- public RBClassLoader run() {
- return new RBClassLoader();
- }
- });
- private RBClassLoader() {
- }
- public Class<?> loadClass(String name) throws ClassNotFoundException {
- ClassLoader loader = ClassLoader.getSystemClassLoader();
- if (loader != null) {
- return loader.loadClass(name);
- }
- return Class.forName(name);
- }
- public URL getResource(String name) {
- ClassLoader loader = ClassLoader.getSystemClassLoader();
- if (loader != null) {
- return loader.getResource(name);
- }
- return ClassLoader.getSystemResource(name);
- }
- public InputStream getResourceAsStream(String name) {
- ClassLoader loader = ClassLoader.getSystemClassLoader();
- if (loader != null) {
- return loader.getResourceAsStream(name);
- }
- return ClassLoader.getSystemResourceAsStream(name);
- }
+ private static ClassLoader getLoaderForControl(Module module) {
+ ClassLoader loader = getLoader(module);
+ return loader == null ? ClassLoader.getSystemClassLoader() : loader;
}
/**
@@ -610,23 +567,23 @@
/**
* Key used for cached resource bundles. The key checks the base
- * name, the locale, the class loader, and the caller module
+ * name, the locale, the bundle module, and the caller module
* to determine if the resource is a match to the requested one.
- * The loader may be null, but the base name, the locale and
- * module must have a non-null value.
+ * The base name, the locale and both modules must have a non-null value.
*/
- private static class CacheKey implements Cloneable {
+ private static final class CacheKey {
// These four are the actual keys for lookup in Map.
- private String name;
- private Locale locale;
- private KeyElementReference<ClassLoader> loaderRef;
- private KeyElementReference<Module> moduleRef;
- private KeyElementReference<Module> callerRef;
-
+ private final String name;
+ private volatile Locale locale;
+ private final KeyElementReference<Module> moduleRef;
+ private final KeyElementReference<Module> callerRef;
+ // this is the part of hashCode that pertains to module and callerModule
+ // which can be GCed..
+ private final int modulesHash;
// bundle format which is necessary for calling
// Control.needsReload().
- private String format;
+ private volatile String format;
// These time values are in CacheKey so that NONEXISTENT_BUNDLE
// doesn't need to be cloned for caching.
@@ -639,63 +596,55 @@
private volatile long expirationTime;
// Placeholder for an error report by a Throwable
- private Throwable cause;
-
- // Hash code value cache to avoid recalculating the hash code
- // of this instance.
- private int hashCodeCache;
+ private volatile Throwable cause;
// ResourceBundleProviders for loading ResourceBundles
- private ServiceLoader<ResourceBundleProvider> providers;
- private boolean providersChecked;
+ private volatile ServiceLoader<ResourceBundleProvider> providers;
+ private volatile boolean providersChecked;
// Boolean.TRUE if the factory method caller provides a ResourceBundleProvier.
- private Boolean callerHasProvider;
+ private volatile Boolean callerHasProvider;
- CacheKey(String baseName, Locale locale, ClassLoader loader, Module module, Module caller) {
+ CacheKey(String baseName, Locale locale, Module module, Module caller) {
Objects.requireNonNull(module);
+ Objects.requireNonNull(caller);
this.name = baseName;
this.locale = locale;
- if (loader == null) {
- this.loaderRef = null;
- } else {
- this.loaderRef = new KeyElementReference<>(loader, referenceQueue, this);
- }
this.moduleRef = new KeyElementReference<>(module, referenceQueue, this);
this.callerRef = new KeyElementReference<>(caller, referenceQueue, this);
+ this.modulesHash = module.hashCode() ^ caller.hashCode();
+ }
- calculateHashCode();
+ CacheKey(CacheKey src) {
+ // Create References to src's modules
+ this.moduleRef = new KeyElementReference<>(
+ Objects.requireNonNull(src.getModule()), referenceQueue, this);
+ this.callerRef = new KeyElementReference<>(
+ Objects.requireNonNull(src.getCallerModule()), referenceQueue, this);
+ // Copy fields from src. ResourceBundleProviders related fields
+ // and "cause" should not be copied.
+ this.name = src.name;
+ this.locale = src.locale;
+ this.modulesHash = src.modulesHash;
+ this.format = src.format;
+ this.loadTime = src.loadTime;
+ this.expirationTime = src.expirationTime;
}
String getName() {
return name;
}
- CacheKey setName(String baseName) {
- if (!this.name.equals(baseName)) {
- this.name = baseName;
- calculateHashCode();
- }
- return this;
- }
-
Locale getLocale() {
return locale;
}
CacheKey setLocale(Locale locale) {
- if (!this.locale.equals(locale)) {
- this.locale = locale;
- calculateHashCode();
- }
+ this.locale = locale;
return this;
}
- ClassLoader getLoader() {
- return (loaderRef != null) ? loaderRef.get() : null;
- }
-
Module getModule() {
return moduleRef.get();
}
@@ -728,7 +677,7 @@
try {
final CacheKey otherEntry = (CacheKey)other;
//quick check to see if they are not equal
- if (hashCodeCache != otherEntry.hashCodeCache) {
+ if (modulesHash != otherEntry.modulesHash) {
return false;
}
//are the names the same?
@@ -739,24 +688,11 @@
if (!locale.equals(otherEntry.locale)) {
return false;
}
- //are refs (both non-null) or (both null)?
- if (loaderRef == null) {
- return otherEntry.loaderRef == null;
- }
- ClassLoader loader = getLoader();
+ // are modules and callerModules the same and non-null?
Module module = getModule();
Module caller = getCallerModule();
-
- return (otherEntry.loaderRef != null)
- // with a null reference we can no longer find
- // out which class loader or module was referenced; so
- // treat it as unequal
- && (loader != null)
- && (loader == otherEntry.getLoader())
- && (module != null)
- && (module.equals(otherEntry.getModule()))
- && (caller != null)
- && (caller.equals(otherEntry.getCallerModule()));
+ return ((module != null) && (module.equals(otherEntry.getModule())) &&
+ (caller != null) && (caller.equals(otherEntry.getCallerModule())));
} catch (NullPointerException | ClassCastException e) {
}
return false;
@@ -764,51 +700,7 @@
@Override
public int hashCode() {
- return hashCodeCache;
- }
-
- private void calculateHashCode() {
- hashCodeCache = name.hashCode() << 3;
- hashCodeCache ^= locale.hashCode();
- ClassLoader loader = getLoader();
- if (loader != null) {
- hashCodeCache ^= loader.hashCode();
- }
- Module module = getModule();
- if (module != null) {
- hashCodeCache ^= module.hashCode();
- }
- Module caller = getCallerModule();
- if (caller != null) {
- hashCodeCache ^= caller.hashCode();
- }
- }
-
- @Override
- public Object clone() {
- try {
- CacheKey clone = (CacheKey) super.clone();
- if (loaderRef != null) {
- clone.loaderRef = new KeyElementReference<>(getLoader(),
- referenceQueue, clone);
- }
- clone.moduleRef = new KeyElementReference<>(getModule(),
- referenceQueue, clone);
- clone.callerRef = new KeyElementReference<>(getCallerModule(),
- referenceQueue, clone);
-
- // Clear the reference to ResourceBundleProviders and the flag
- clone.providers = null;
- clone.providersChecked = false;
- // Clear the reference to a Throwable
- clone.cause = null;
- // Clear callerHasProvider
- clone.callerHasProvider = null;
- return clone;
- } catch (CloneNotSupportedException e) {
- //this should never happen
- throw new InternalError(e);
- }
+ return (name.hashCode() << 3) ^ locale.hashCode() ^ modulesHash;
}
String getFormat() {
@@ -845,8 +737,12 @@
l = "\"\"";
}
}
- return "CacheKey[" + name + ", lc=" + l + ", ldr=" + getLoader()
- + "(format=" + format + ")]";
+ return "CacheKey[" + name +
+ ", locale=" + l +
+ ", module=" + getModule() +
+ ", callerModule=" + getCallerModule() +
+ ", format=" + format +
+ "]";
}
}
@@ -1568,7 +1464,7 @@
Locale locale,
Class<?> caller,
Control control) {
- return getBundleImpl(baseName, locale, caller, getLoader(caller), control);
+ return getBundleImpl(baseName, locale, caller, caller.getClassLoader(), control);
}
/**
@@ -1587,26 +1483,25 @@
Class<?> caller,
ClassLoader loader,
Control control) {
- if (caller != null && caller.getModule().isNamed()) {
- Module module = caller.getModule();
- ClassLoader ml = getLoader(module);
- // get resource bundles for a named module only
- // if loader is the module's class loader
- if (loader == ml || (ml == null && loader == RBClassLoader.INSTANCE)) {
- return getBundleImpl(module, module, loader, baseName, locale, control);
- }
- }
- // find resource bundles from unnamed module
- Module unnamedModule = loader != null
- ? loader.getUnnamedModule()
- : ClassLoader.getSystemClassLoader().getUnnamedModule();
-
if (caller == null) {
throw new InternalError("null caller");
}
+ Module callerModule = caller.getModule();
- Module callerModule = caller.getModule();
- return getBundleImpl(callerModule, unnamedModule, loader, baseName, locale, control);
+ // get resource bundles for a named module only if loader is the module's class loader
+ if (callerModule.isNamed() && loader == getLoader(callerModule)) {
+ return getBundleImpl(callerModule, callerModule, baseName, locale, control);
+ }
+
+ // find resource bundles from unnamed module of given class loader
+ // Java agent can add to the bootclasspath e.g. via
+ // java.lang.instrument.Instrumentation and load classes in unnamed module.
+ // It may call RB::getBundle that will end up here with loader == null.
+ Module unnamedModule = loader != null
+ ? loader.getUnnamedModule()
+ : BootLoader.getUnnamedModule();
+
+ return getBundleImpl(callerModule, unnamedModule, baseName, locale, control);
}
private static ResourceBundle getBundleFromModule(Class<?> caller,
@@ -1622,12 +1517,11 @@
sm.checkPermission(GET_CLASSLOADER_PERMISSION);
}
}
- return getBundleImpl(callerModule, module, getLoader(module), baseName, locale, control);
+ return getBundleImpl(callerModule, module, baseName, locale, control);
}
private static ResourceBundle getBundleImpl(Module callerModule,
Module module,
- ClassLoader loader,
String baseName,
Locale locale,
Control control) {
@@ -1636,10 +1530,10 @@
}
// We create a CacheKey here for use by this call. The base name
- // loader, and module will never change during the bundle loading
+ // and modules will never change during the bundle loading
// process. We have to make sure that the locale is set before
// using it as a cache key.
- CacheKey cacheKey = new CacheKey(baseName, locale, loader, module, callerModule);
+ CacheKey cacheKey = new CacheKey(baseName, locale, module, callerModule);
ResourceBundle bundle = null;
// Quick lookup of the cache.
@@ -1708,6 +1602,11 @@
bundle = baseBundle;
}
+ // keep callerModule and module reachable for as long as we are operating
+ // with WeakReference(s) to them (in CacheKey)...
+ Reference.reachabilityFence(callerModule);
+ Reference.reachabilityFence(module);
+
return bundle;
}
@@ -1745,7 +1644,7 @@
}
// Before we do the real loading work, see whether we need to
- // do some housekeeping: If references to class loaders or
+ // do some housekeeping: If references to modules or
// resource bundles have been nulled out, remove all related
// information from the cache.
Object ref;
@@ -1781,31 +1680,24 @@
}
if (bundle != NONEXISTENT_BUNDLE) {
- CacheKey constKey = (CacheKey) cacheKey.clone();
trace("findBundle: %d %s %s formats: %s%n", index, candidateLocales, cacheKey, formats);
- try {
- if (module.isNamed()) {
- bundle = loadBundle(cacheKey, formats, control, module, callerModule);
- } else {
- bundle = loadBundle(cacheKey, formats, control, expiredBundle);
+ if (module.isNamed()) {
+ bundle = loadBundle(cacheKey, formats, control, module, callerModule);
+ } else {
+ bundle = loadBundle(cacheKey, formats, control, expiredBundle);
+ }
+ if (bundle != null) {
+ if (bundle.parent == null) {
+ bundle.setParent(parent);
}
- if (bundle != null) {
- if (bundle.parent == null) {
- bundle.setParent(parent);
- }
- bundle.locale = targetLocale;
- bundle = putBundleInCache(cacheKey, bundle, control);
- return bundle;
- }
+ bundle.locale = targetLocale;
+ bundle = putBundleInCache(cacheKey, bundle, control);
+ return bundle;
+ }
- // Put NONEXISTENT_BUNDLE in the cache as a mark that there's no bundle
- // instance for the locale.
- putBundleInCache(cacheKey, NONEXISTENT_BUNDLE, control);
- } finally {
- if (constKey.getCause() instanceof InterruptedException) {
- Thread.currentThread().interrupt();
- }
- }
+ // Put NONEXISTENT_BUNDLE in the cache as a mark that there's no bundle
+ // instance for the locale.
+ putBundleInCache(cacheKey, NONEXISTENT_BUNDLE, control);
}
return parent;
}
@@ -1991,12 +1883,20 @@
// specified by the getFormats() value.
Locale targetLocale = cacheKey.getLocale();
+ Module module = cacheKey.getModule();
+ if (module == null) {
+ // should not happen
+ throw new InternalError(
+ "Module for cache key: " + cacheKey + " has been GCed.");
+ }
+ ClassLoader loader = getLoaderForControl(module);
+
ResourceBundle bundle = null;
for (String format : formats) {
try {
// ResourceBundle.Control.newBundle may be overridden
bundle = control.newBundle(cacheKey.getName(), targetLocale, format,
- cacheKey.getLoader(), reload);
+ loader, reload);
} catch (LinkageError | Exception error) {
// We need to handle the LinkageError case due to
// inconsistent case-sensitivity in ClassLoader.
@@ -2138,12 +2038,15 @@
if (!bundle.expired && expirationTime >= 0 &&
expirationTime <= System.currentTimeMillis()) {
try {
- bundle.expired = control.needsReload(key.getName(),
- key.getLocale(),
- key.getFormat(),
- key.getLoader(),
- bundle,
- key.loadTime);
+ Module module = cacheKey.getModule();
+ bundle.expired =
+ module == null || // already GCed
+ control.needsReload(key.getName(),
+ key.getLocale(),
+ key.getFormat(),
+ getLoaderForControl(module),
+ bundle,
+ key.loadTime);
} catch (Exception e) {
cacheKey.setCause(e);
}
@@ -2185,7 +2088,7 @@
Control control) {
setExpirationTime(cacheKey, control);
if (cacheKey.expirationTime != Control.TTL_DONT_CACHE) {
- CacheKey key = (CacheKey) cacheKey.clone();
+ CacheKey key = new CacheKey(cacheKey);
BundleReference bundleRef = new BundleReference(bundle, referenceQueue, key);
bundle.cacheKey = key;
@@ -2231,7 +2134,7 @@
/**
* Removes all resource bundles from the cache that have been loaded
- * by the caller's module using the caller's class loader.
+ * by the caller's module.
*
* @since 1.6
* @see ResourceBundle.Control#getTimeToLive(String,Locale)
@@ -2239,47 +2142,29 @@
@CallerSensitive
public static final void clearCache() {
Class<?> caller = Reflection.getCallerClass();
- clearCache(getLoader(caller), caller.getModule());
+ cacheList.keySet().removeIf(
+ key -> key.getCallerModule() == caller.getModule()
+ );
}
/**
* Removes all resource bundles from the cache that have been loaded
- * by the caller's module using the given class loader.
+ * by the given class loader.
*
* @param loader the class loader
* @exception NullPointerException if <code>loader</code> is null
* @since 1.6
* @see ResourceBundle.Control#getTimeToLive(String,Locale)
*/
- @CallerSensitive
public static final void clearCache(ClassLoader loader) {
Objects.requireNonNull(loader);
- clearCache(loader, Reflection.getCallerClass().getModule());
- }
-
- /**
- * Removes all resource bundles from the cache that have been loaded by the
- * given {@code module}.
- *
- * @param module the module
- * @throws NullPointerException
- * if {@code module} is {@code null}
- * @throws SecurityException
- * if the caller doesn't have the permission to
- * {@linkplain Module#getClassLoader() get the class loader}
- * of the given {@code module}
- * @since 9
- * @see ResourceBundle.Control#getTimeToLive(String,Locale)
- */
- public static final void clearCache(Module module) {
- clearCache(module.getClassLoader(), module);
- }
-
- private static void clearCache(ClassLoader loader, Module module) {
- Set<CacheKey> set = cacheList.keySet();
- set.stream()
- .filter((key) -> (key.getLoader() == loader && key.getModule() == module))
- .forEach(set::remove);
+ cacheList.keySet().removeIf(
+ key -> {
+ Module m;
+ return (m = key.getModule()) != null &&
+ getLoader(m) == loader;
+ }
+ );
}
/**
--- a/jdk/src/java.base/share/classes/java/util/concurrent/ForkJoinWorkerThread.java Fri Jan 20 10:28:34 2017 -0800
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/ForkJoinWorkerThread.java Fri Jan 20 08:53:42 2017 -0800
@@ -185,7 +185,14 @@
static final class InnocuousForkJoinWorkerThread extends ForkJoinWorkerThread {
/** The ThreadGroup for all InnocuousForkJoinWorkerThreads */
private static final ThreadGroup innocuousThreadGroup =
- ThreadLocalRandom.createThreadGroup("InnocuousForkJoinWorkerThreadGroup");
+ java.security.AccessController.doPrivileged(
+ new java.security.PrivilegedAction<>() {
+ public ThreadGroup run() {
+ ThreadGroup group = Thread.currentThread().getThreadGroup();
+ for (ThreadGroup p; (p = group.getParent()) != null; )
+ group = p;
+ return new ThreadGroup(group, "InnocuousForkJoinWorkerThreadGroup");
+ }});
/** An AccessControlContext supporting no privileges */
private static final AccessControlContext INNOCUOUS_ACC =
@@ -215,6 +222,5 @@
public void setContextClassLoader(ClassLoader cl) {
throw new SecurityException("setContextClassLoader");
}
-
}
}
--- a/jdk/src/java.base/share/classes/java/util/concurrent/ThreadLocalRandom.java Fri Jan 20 10:28:34 2017 -0800
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/ThreadLocalRandom.java Fri Jan 20 08:53:42 2017 -0800
@@ -985,34 +985,6 @@
U.putObjectRelease(thread, INHERITEDACCESSCONTROLCONTEXT, acc);
}
- /**
- * Returns a new group with the system ThreadGroup (the
- * topmost, parent-less group) as parent. Uses Unsafe to
- * traverse Thread.group and ThreadGroup.parent fields.
- */
- static final ThreadGroup createThreadGroup(String name) {
- if (name == null)
- throw new NullPointerException();
- try {
- long tg = U.objectFieldOffset
- (Thread.class.getDeclaredField("group"));
- long gp = U.objectFieldOffset
- (ThreadGroup.class.getDeclaredField("parent"));
- ThreadGroup group = (ThreadGroup)
- U.getObject(Thread.currentThread(), tg);
- while (group != null) {
- ThreadGroup parent = (ThreadGroup)U.getObject(group, gp);
- if (parent == null)
- return new ThreadGroup(group, name);
- group = parent;
- }
- } catch (ReflectiveOperationException e) {
- throw new Error(e);
- }
- // fall through if null as cannot-happen safeguard
- throw new Error("Cannot create ThreadGroup");
- }
-
// Serialization support
private static final long serialVersionUID = -5851777807851030925L;
@@ -1087,17 +1059,17 @@
static {
try {
SEED = U.objectFieldOffset
- (Thread.class.getDeclaredField("threadLocalRandomSeed"));
+ (Thread.class.getDeclaredField("threadLocalRandomSeed"));
PROBE = U.objectFieldOffset
- (Thread.class.getDeclaredField("threadLocalRandomProbe"));
+ (Thread.class.getDeclaredField("threadLocalRandomProbe"));
SECONDARY = U.objectFieldOffset
- (Thread.class.getDeclaredField("threadLocalRandomSecondarySeed"));
+ (Thread.class.getDeclaredField("threadLocalRandomSecondarySeed"));
THREADLOCALS = U.objectFieldOffset
- (Thread.class.getDeclaredField("threadLocals"));
+ (Thread.class.getDeclaredField("threadLocals"));
INHERITABLETHREADLOCALS = U.objectFieldOffset
- (Thread.class.getDeclaredField("inheritableThreadLocals"));
+ (Thread.class.getDeclaredField("inheritableThreadLocals"));
INHERITEDACCESSCONTROLCONTEXT = U.objectFieldOffset
- (Thread.class.getDeclaredField("inheritedAccessControlContext"));
+ (Thread.class.getDeclaredField("inheritedAccessControlContext"));
} catch (ReflectiveOperationException e) {
throw new Error(e);
}
@@ -1123,7 +1095,7 @@
// at end of <clinit> to survive static initialization circularity
static {
if (java.security.AccessController.doPrivileged(
- new java.security.PrivilegedAction<Boolean>() {
+ new java.security.PrivilegedAction<>() {
public Boolean run() {
return Boolean.getBoolean("java.util.secureRandomSeed");
}})) {
--- a/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicIntegerFieldUpdater.java Fri Jan 20 10:28:34 2017 -0800
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicIntegerFieldUpdater.java Fri Jan 20 08:53:42 2017 -0800
@@ -40,6 +40,7 @@
import java.security.AccessController;
import java.security.PrivilegedActionException;
import java.security.PrivilegedExceptionAction;
+import java.util.Objects;
import java.util.function.IntBinaryOperator;
import java.util.function.IntUnaryOperator;
import jdk.internal.misc.Unsafe;
@@ -411,7 +412,17 @@
if (!Modifier.isVolatile(modifiers))
throw new IllegalArgumentException("Must be volatile type");
- this.cclass = (Modifier.isProtected(modifiers)) ? caller : tclass;
+ // Access to protected field members is restricted to receivers only
+ // of the accessing class, or one of its subclasses, and the
+ // accessing class must in turn be a subclass (or package sibling)
+ // of the protected member's defining class.
+ // If the updater refers to a protected field of a declaring class
+ // outside the current package, the receiver argument will be
+ // narrowed to the type of the accessing class.
+ this.cclass = (Modifier.isProtected(modifiers) &&
+ tclass.isAssignableFrom(caller) &&
+ !isSamePackage(tclass, caller))
+ ? caller : tclass;
this.tclass = tclass;
this.offset = U.objectFieldOffset(field);
}
@@ -433,6 +444,15 @@
}
/**
+ * Returns true if the two classes have the same class loader and
+ * package qualifier
+ */
+ private static boolean isSamePackage(Class<?> class1, Class<?> class2) {
+ return class1.getClassLoader() == class2.getClassLoader()
+ && Objects.equals(class1.getPackageName(), class2.getPackageName());
+ }
+
+ /**
* Checks that target argument is instance of cclass. On
* failure, throws cause.
*/
--- a/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicLongFieldUpdater.java Fri Jan 20 10:28:34 2017 -0800
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicLongFieldUpdater.java Fri Jan 20 08:53:42 2017 -0800
@@ -40,6 +40,7 @@
import java.security.AccessController;
import java.security.PrivilegedActionException;
import java.security.PrivilegedExceptionAction;
+import java.util.Objects;
import java.util.function.LongBinaryOperator;
import java.util.function.LongUnaryOperator;
import jdk.internal.misc.Unsafe;
@@ -409,7 +410,17 @@
if (!Modifier.isVolatile(modifiers))
throw new IllegalArgumentException("Must be volatile type");
- this.cclass = (Modifier.isProtected(modifiers)) ? caller : tclass;
+ // Access to protected field members is restricted to receivers only
+ // of the accessing class, or one of its subclasses, and the
+ // accessing class must in turn be a subclass (or package sibling)
+ // of the protected member's defining class.
+ // If the updater refers to a protected field of a declaring class
+ // outside the current package, the receiver argument will be
+ // narrowed to the type of the accessing class.
+ this.cclass = (Modifier.isProtected(modifiers) &&
+ tclass.isAssignableFrom(caller) &&
+ !isSamePackage(tclass, caller))
+ ? caller : tclass;
this.tclass = tclass;
this.offset = U.objectFieldOffset(field);
}
@@ -540,7 +551,17 @@
if (!Modifier.isVolatile(modifiers))
throw new IllegalArgumentException("Must be volatile type");
- this.cclass = (Modifier.isProtected(modifiers)) ? caller : tclass;
+ // Access to protected field members is restricted to receivers only
+ // of the accessing class, or one of its subclasses, and the
+ // accessing class must in turn be a subclass (or package sibling)
+ // of the protected member's defining class.
+ // If the updater refers to a protected field of a declaring class
+ // outside the current package, the receiver argument will be
+ // narrowed to the type of the accessing class.
+ this.cclass = (Modifier.isProtected(modifiers) &&
+ tclass.isAssignableFrom(caller) &&
+ !isSamePackage(tclass, caller))
+ ? caller : tclass;
this.tclass = tclass;
this.offset = U.objectFieldOffset(field);
}
@@ -621,4 +642,13 @@
} while (acl != null);
return false;
}
+
+ /**
+ * Returns true if the two classes have the same class loader and
+ * package qualifier
+ */
+ static boolean isSamePackage(Class<?> class1, Class<?> class2) {
+ return class1.getClassLoader() == class2.getClassLoader()
+ && Objects.equals(class1.getPackageName(), class2.getPackageName());
+ }
}
--- a/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicReferenceFieldUpdater.java Fri Jan 20 10:28:34 2017 -0800
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicReferenceFieldUpdater.java Fri Jan 20 08:53:42 2017 -0800
@@ -40,6 +40,7 @@
import java.security.AccessController;
import java.security.PrivilegedActionException;
import java.security.PrivilegedExceptionAction;
+import java.util.Objects;
import java.util.function.BinaryOperator;
import java.util.function.UnaryOperator;
import jdk.internal.misc.Unsafe;
@@ -351,7 +352,17 @@
if (!Modifier.isVolatile(modifiers))
throw new IllegalArgumentException("Must be volatile type");
- this.cclass = (Modifier.isProtected(modifiers)) ? caller : tclass;
+ // Access to protected field members is restricted to receivers only
+ // of the accessing class, or one of its subclasses, and the
+ // accessing class must in turn be a subclass (or package sibling)
+ // of the protected member's defining class.
+ // If the updater refers to a protected field of a declaring class
+ // outside the current package, the receiver argument will be
+ // narrowed to the type of the accessing class.
+ this.cclass = (Modifier.isProtected(modifiers) &&
+ tclass.isAssignableFrom(caller) &&
+ !isSamePackage(tclass, caller))
+ ? caller : tclass;
this.tclass = tclass;
this.vclass = vclass;
this.offset = U.objectFieldOffset(field);
@@ -374,6 +385,15 @@
}
/**
+ * Returns true if the two classes have the same class loader and
+ * package qualifier
+ */
+ private static boolean isSamePackage(Class<?> class1, Class<?> class2) {
+ return class1.getClassLoader() == class2.getClassLoader()
+ && Objects.equals(class1.getPackageName(), class2.getPackageName());
+ }
+
+ /**
* Checks that target argument is instance of cclass. On
* failure, throws cause.
*/
--- a/jdk/src/java.base/share/classes/java/util/concurrent/atomic/Striped64.java Fri Jan 20 10:28:34 2017 -0800
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/atomic/Striped64.java Fri Jan 20 08:53:42 2017 -0800
@@ -41,7 +41,6 @@
import java.util.concurrent.ThreadLocalRandom;
import java.util.function.DoubleBinaryOperator;
import java.util.function.LongBinaryOperator;
-import jdk.internal.misc.Unsafe;
/**
* A package-local class holding common representation and mechanics
@@ -191,7 +190,7 @@
* Duplicated from ThreadLocalRandom because of packaging restrictions.
*/
static final int getProbe() {
- return U.getInt(Thread.currentThread(), PROBE);
+ return (int) THREAD_PROBE.get(Thread.currentThread());
}
/**
@@ -203,7 +202,7 @@
probe ^= probe << 13; // xorshift
probe ^= probe >>> 17;
probe ^= probe << 5;
- U.putInt(Thread.currentThread(), PROBE, probe);
+ THREAD_PROBE.set(Thread.currentThread(), probe);
return probe;
}
@@ -373,18 +372,28 @@
}
}
- // Unsafe and VarHandle mechanics
- private static final Unsafe U = Unsafe.getUnsafe();
+ // VarHandle mechanics
private static final VarHandle BASE;
private static final VarHandle CELLSBUSY;
- private static final long PROBE;
+ private static final VarHandle THREAD_PROBE;
static {
try {
MethodHandles.Lookup l = MethodHandles.lookup();
- BASE = l.findVarHandle(Striped64.class, "base", long.class);
- CELLSBUSY = l.findVarHandle(Striped64.class, "cellsBusy", int.class);
- PROBE = U.objectFieldOffset
- (Thread.class.getDeclaredField("threadLocalRandomProbe"));
+ BASE = l.findVarHandle(Striped64.class,
+ "base", long.class);
+ CELLSBUSY = l.findVarHandle(Striped64.class,
+ "cellsBusy", int.class);
+ l = java.security.AccessController.doPrivileged(
+ new java.security.PrivilegedAction<>() {
+ public MethodHandles.Lookup run() {
+ try {
+ return MethodHandles.privateLookupIn(Thread.class, MethodHandles.lookup());
+ } catch (ReflectiveOperationException e) {
+ throw new Error(e);
+ }
+ }});
+ THREAD_PROBE = l.findVarHandle(Thread.class,
+ "threadLocalRandomProbe", int.class);
} catch (ReflectiveOperationException e) {
throw new Error(e);
}
--- a/jdk/src/java.base/share/classes/java/util/concurrent/locks/LockSupport.java Fri Jan 20 10:28:34 2017 -0800
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/locks/LockSupport.java Fri Jan 20 08:53:42 2017 -0800
@@ -425,11 +425,11 @@
static {
try {
PARKBLOCKER = U.objectFieldOffset
- (Thread.class.getDeclaredField("parkBlocker"));
+ (Thread.class.getDeclaredField("parkBlocker"));
SECONDARY = U.objectFieldOffset
- (Thread.class.getDeclaredField("threadLocalRandomSecondarySeed"));
+ (Thread.class.getDeclaredField("threadLocalRandomSecondarySeed"));
TID = U.objectFieldOffset
- (Thread.class.getDeclaredField("tid"));
+ (Thread.class.getDeclaredField("tid"));
} catch (ReflectiveOperationException e) {
throw new Error(e);
--- a/jdk/src/java.base/share/classes/javax/net/ssl/HandshakeCompletedEvent.java Fri Jan 20 10:28:34 2017 -0800
+++ b/jdk/src/java.base/share/classes/javax/net/ssl/HandshakeCompletedEvent.java Fri Jan 20 08:53:42 2017 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2016, 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
@@ -120,6 +120,9 @@
* Note: This method can be used only when using certificate-based
* cipher suites; using it with non-certificate-based cipher suites,
* such as Kerberos, will throw an SSLPeerUnverifiedException.
+ * <P>
+ * Note: The returned value may not be a valid certificate chain
+ * and should not be relied on for trust decisions.
*
* @return an ordered array of the peer certificates,
* with the peer's own certificate first followed by
@@ -140,6 +143,9 @@
* Note: This method can be used only when using certificate-based
* cipher suites; using it with non-certificate-based cipher suites,
* such as Kerberos, will throw an SSLPeerUnverifiedException.
+ * <P>
+ * Note: The returned value may not be a valid certificate chain
+ * and should not be relied on for trust decisions.
*
* <p><em>Note: this method exists for compatibility with previous
* releases. New applications should use
--- a/jdk/src/java.base/share/classes/javax/net/ssl/HttpsURLConnection.java Fri Jan 20 10:28:34 2017 -0800
+++ b/jdk/src/java.base/share/classes/javax/net/ssl/HttpsURLConnection.java Fri Jan 20 08:53:42 2017 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2016, 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
@@ -104,6 +104,9 @@
* Note: This method can be used only when using certificate-based
* cipher suites; using it with non-certificate-based cipher suites,
* such as Kerberos, will throw an SSLPeerUnverifiedException.
+ * <P>
+ * Note: The returned value may not be a valid certificate chain
+ * and should not be relied on for trust decisions.
*
* @return an ordered array of server certificates,
* with the peer's own certificate first followed by
--- a/jdk/src/java.base/share/classes/javax/net/ssl/SSLSession.java Fri Jan 20 10:28:34 2017 -0800
+++ b/jdk/src/java.base/share/classes/javax/net/ssl/SSLSession.java Fri Jan 20 08:53:42 2017 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2016, 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
@@ -219,6 +219,9 @@
* Note: This method can be used only when using certificate-based
* cipher suites; using it with non-certificate-based cipher suites,
* such as Kerberos, will throw an SSLPeerUnverifiedException.
+ * <P>
+ * Note: The returned value may not be a valid certificate chain
+ * and should not be relied on for trust decisions.
*
* @return an ordered array of peer certificates,
* with the peer's own certificate first followed by any
@@ -259,6 +262,9 @@
* Note: This method can be used only when using certificate-based
* cipher suites; using it with non-certificate-based cipher suites,
* such as Kerberos, will throw an SSLPeerUnverifiedException.
+ * <P>
+ * Note: The returned value may not be a valid certificate chain
+ * and should not be relied on for trust decisions.
*
* <p><em>Note: this method exists for compatibility with previous
* releases. New applications should use
--- a/jdk/src/java.base/share/classes/jdk/internal/loader/URLClassPath.java Fri Jan 20 10:28:34 2017 -0800
+++ b/jdk/src/java.base/share/classes/jdk/internal/loader/URLClassPath.java Fri Jan 20 08:53:42 2017 -0800
@@ -38,6 +38,7 @@
import java.net.URLConnection;
import java.net.URLStreamHandler;
import java.net.URLStreamHandlerFactory;
+import java.security.AccessControlContext;
import java.security.AccessControlException;
import java.security.AccessController;
import java.security.CodeSigner;
@@ -83,6 +84,7 @@
private static final String JAVA_VERSION;
private static final boolean DEBUG;
private static final boolean DISABLE_JAR_CHECKING;
+ private static final boolean DISABLE_ACC_CHECKING;
static {
Properties props = GetPropertyAction.privilegedGetProperties();
@@ -90,6 +92,9 @@
DEBUG = (props.getProperty("sun.misc.URLClassPath.debug") != null);
String p = props.getProperty("sun.misc.URLClassPath.disableJarChecking");
DISABLE_JAR_CHECKING = p != null ? p.equals("true") || p.equals("") : false;
+
+ p = props.getProperty("jdk.net.URLClassPath.disableRestrictedPermissions");
+ DISABLE_ACC_CHECKING = p != null ? p.equals("true") || p.equals("") : false;
}
/* The original search path of URLs. */
@@ -110,6 +115,11 @@
/* Whether this URLClassLoader has been closed yet */
private boolean closed = false;
+ /* The context to be used when loading classes and resources. If non-null
+ * this is the context that was captured during the creation of the
+ * URLClassLoader. null implies no additional security restrictions. */
+ private final AccessControlContext acc;
+
/**
* Creates a new URLClassPath for the given URLs. The URLs will be
* searched in the order specified for classes and resources. A URL
@@ -119,8 +129,12 @@
* @param urls the directory and JAR file URLs to search for classes
* and resources
* @param factory the URLStreamHandlerFactory to use when creating new URLs
+ * @param acc the context to be used when loading classes and resources, may
+ * be null
*/
- public URLClassPath(URL[] urls, URLStreamHandlerFactory factory) {
+ public URLClassPath(URL[] urls,
+ URLStreamHandlerFactory factory,
+ AccessControlContext acc) {
for (int i = 0; i < urls.length; i++) {
path.add(urls[i]);
}
@@ -128,10 +142,22 @@
if (factory != null) {
jarHandler = factory.createURLStreamHandler("jar");
}
+ if (DISABLE_ACC_CHECKING)
+ this.acc = null;
+ else
+ this.acc = acc;
}
+ /**
+ * Constructs a URLClassPath with no additional security restrictions.
+ * Used by code that implements the class path.
+ */
public URLClassPath(URL[] urls) {
- this(urls, null);
+ this(urls, null, null);
+ }
+
+ public URLClassPath(URL[] urls, AccessControlContext acc) {
+ this(urls, null, acc);
}
public synchronized List<IOException> closeLoaders() {
@@ -356,6 +382,14 @@
} catch (IOException e) {
// Silently ignore for now...
continue;
+ } catch (SecurityException se) {
+ // Always silently ignore. The context, if there is one, that
+ // this URLClassPath was given during construction will never
+ // have permission to access the URL.
+ if (DEBUG) {
+ System.err.println("Failed to access " + url + ", " + se );
+ }
+ continue;
}
// Finally, add the Loader to the search path.
loaders.add(loader);
@@ -378,7 +412,7 @@
&& file != null && (file.indexOf("!/") == file.length() - 2)) {
// extract the nested URL
URL nestedUrl = new URL(file.substring(0, file.length() - 2));
- return new JarLoader(nestedUrl, jarHandler, lmap);
+ return new JarLoader(nestedUrl, jarHandler, lmap, acc);
} else if (file != null && file.endsWith("/")) {
if ("file".equals(protocol)) {
return new FileLoader(url);
@@ -386,10 +420,10 @@
return new Loader(url);
}
} else {
- return new JarLoader(url, jarHandler, lmap);
+ return new JarLoader(url, jarHandler, lmap, acc);
}
}
- });
+ }, acc);
} catch (java.security.PrivilegedActionException pae) {
throw (IOException)pae.getException();
}
@@ -585,10 +619,11 @@
*/
static class JarLoader extends Loader {
private JarFile jar;
- private URL csu;
+ private final URL csu;
private JarIndex index;
private URLStreamHandler handler;
- private HashMap<String, Loader> lmap;
+ private final HashMap<String, Loader> lmap;
+ private final AccessControlContext acc;
private boolean closed = false;
private static final JavaUtilZipFileAccess zipAccess =
SharedSecrets.getJavaUtilZipFileAccess();
@@ -598,13 +633,15 @@
* a JAR file.
*/
JarLoader(URL url, URLStreamHandler jarHandler,
- HashMap<String, Loader> loaderMap)
+ HashMap<String, Loader> loaderMap,
+ AccessControlContext acc)
throws IOException
{
super(new URL("jar", "", -1, url + "!/", jarHandler));
csu = url;
handler = jarHandler;
lmap = loaderMap;
+ this.acc = acc;
ensureOpen();
}
@@ -663,8 +700,7 @@
}
return null;
}
- }
- );
+ }, acc);
} catch (java.security.PrivilegedActionException pae) {
throw (IOException)pae.getException();
}
@@ -859,9 +895,9 @@
new PrivilegedExceptionAction<>() {
public JarLoader run() throws IOException {
return new JarLoader(url, handler,
- lmap);
+ lmap, acc);
}
- });
+ }, acc);
/* this newly opened jar file has its own index,
* merge it into the parent's index, taking into
--- a/jdk/src/java.base/share/classes/jdk/internal/util/jar/JarIndex.java Fri Jan 20 10:28:34 2017 -0800
+++ b/jdk/src/java.base/share/classes/jdk/internal/util/jar/JarIndex.java Fri Jan 20 08:53:42 2017 -0800
@@ -29,6 +29,7 @@
import java.util.*;
import java.util.jar.*;
import java.util.zip.*;
+import static sun.security.action.GetPropertyAction.privilegedGetProperty;
/**
* This class is used to maintain mappings from packages, classes
@@ -72,7 +73,7 @@
* be added to the index. Otherwise, just the directory names are added.
*/
private static final boolean metaInfFilenames =
- "true".equals(System.getProperty("sun.misc.JarIndex.metaInfFilenames"));
+ "true".equals(privilegedGetProperty("sun.misc.JarIndex.metaInfFilenames"));
/**
* Constructs a new, empty jar index.
--- a/jdk/src/java.base/share/classes/module-info.java Fri Jan 20 10:28:34 2017 -0800
+++ b/jdk/src/java.base/share/classes/module-info.java Fri Jan 20 08:53:42 2017 -0800
@@ -249,7 +249,6 @@
jdk.crypto.token;
exports sun.security.jca to
java.smartcardio,
- java.xml.crypto,
jdk.crypto.ec,
jdk.crypto.token,
jdk.naming.dns;
@@ -279,6 +278,7 @@
java.security.jgss,
java.security.sasl,
java.smartcardio,
+ java.xml.crypto,
jdk.crypto.ec,
jdk.crypto.token,
jdk.jartool,
@@ -290,6 +290,8 @@
jdk.crypto.token,
jdk.jartool,
jdk.security.auth;
+ exports sun.security.validator to
+ jdk.jartool;
exports sun.text.resources to
jdk.localedata;
exports sun.util.cldr to
--- a/jdk/src/java.base/share/classes/sun/reflect/misc/ReflectUtil.java Fri Jan 20 10:28:34 2017 -0800
+++ b/jdk/src/java.base/share/classes/sun/reflect/misc/ReflectUtil.java Fri Jan 20 08:53:42 2017 -0800
@@ -96,7 +96,7 @@
final Class<?> declaringClass = m.getDeclaringClass();
- checkPackageAccess(declaringClass);
+ privateCheckPackageAccess(sm, declaringClass);
if (Modifier.isPublic(m.getModifiers()) &&
Modifier.isPublic(declaringClass.getModifiers()))
@@ -114,9 +114,27 @@
* also check the package access on the proxy interfaces.
*/
public static void checkPackageAccess(Class<?> clazz) {
- checkPackageAccess(clazz.getName());
+ SecurityManager s = System.getSecurityManager();
+ if (s != null) {
+ privateCheckPackageAccess(s, clazz);
+ }
+ }
+
+ /**
+ * NOTE: should only be called if a SecurityManager is installed
+ */
+ private static void privateCheckPackageAccess(SecurityManager s, Class<?> clazz) {
+ while (clazz.isArray()) {
+ clazz = clazz.getComponentType();
+ }
+
+ String pkg = clazz.getPackageName();
+ if (pkg != null && !pkg.isEmpty()) {
+ s.checkPackageAccess(pkg);
+ }
+
if (isNonPublicProxyClass(clazz)) {
- checkProxyPackageAccess(clazz);
+ privateCheckProxyPackageAccess(s, clazz);
}
}
@@ -195,15 +213,21 @@
public static void checkProxyPackageAccess(Class<?> clazz) {
SecurityManager s = System.getSecurityManager();
if (s != null) {
- // check proxy interfaces if the given class is a proxy class
- if (Proxy.isProxyClass(clazz)) {
- for (Class<?> intf : clazz.getInterfaces()) {
- checkPackageAccess(intf);
- }
+ privateCheckProxyPackageAccess(s, clazz);
+ }
+ }
+
+ /**
+ * NOTE: should only be called if a SecurityManager is installed
+ */
+ private static void privateCheckProxyPackageAccess(SecurityManager s, Class<?> clazz) {
+ // check proxy interfaces if the given class is a proxy class
+ if (Proxy.isProxyClass(clazz)) {
+ for (Class<?> intf : clazz.getInterfaces()) {
+ privateCheckPackageAccess(s, intf);
}
}
}
-
/**
* Access check on the interfaces that a proxy class implements and throw
* {@code SecurityException} if it accesses a restricted package from
@@ -220,7 +244,7 @@
for (Class<?> intf : interfaces) {
ClassLoader cl = intf.getClassLoader();
if (needsPackageAccessCheck(ccl, cl)) {
- checkPackageAccess(intf);
+ privateCheckPackageAccess(sm, intf);
}
}
}
@@ -236,10 +260,11 @@
* package that bypasses checkPackageAccess.
*/
public static boolean isNonPublicProxyClass(Class<?> cls) {
- String name = cls.getName();
- int i = name.lastIndexOf('.');
- String pkg = (i != -1) ? name.substring(0, i) : "";
- return Proxy.isProxyClass(cls) && !pkg.startsWith(PROXY_PACKAGE);
+ if (!Proxy.isProxyClass(cls)) {
+ return false;
+ }
+ String pkg = cls.getPackageName();
+ return pkg == null || !pkg.startsWith(PROXY_PACKAGE);
}
/**
@@ -255,7 +280,7 @@
// check if it is a valid proxy instance
if (proxy == null || !Proxy.isProxyClass(proxy.getClass())) {
throw new IllegalArgumentException("Not a Proxy instance");
-}
+ }
if (Modifier.isStatic(method.getModifiers())) {
throw new IllegalArgumentException("Can't handle static method");
}
--- a/jdk/src/java.base/share/classes/sun/security/provider/DSA.java Fri Jan 20 10:28:34 2017 -0800
+++ b/jdk/src/java.base/share/classes/sun/security/provider/DSA.java Fri Jan 20 08:53:42 2017 -0800
@@ -322,19 +322,20 @@
} else {
// first decode the signature.
try {
- DerInputStream in = new DerInputStream(signature, offset,
- length);
+ // Enforce strict DER checking for signatures
+ DerInputStream in =
+ new DerInputStream(signature, offset, length, false);
DerValue[] values = in.getSequence(2);
+ // check number of components in the read sequence
+ // and trailing data
+ if ((values.length != 2) || (in.available() != 0)) {
+ throw new IOException("Invalid encoding for signature");
+ }
r = values[0].getBigInteger();
s = values[1].getBigInteger();
-
- // Check for trailing signature data
- if (in.available() != 0) {
- throw new IOException("Incorrect signature length");
- }
} catch (IOException e) {
- throw new SignatureException("invalid encoding for signature");
+ throw new SignatureException("Invalid encoding for signature", e);
}
}
@@ -427,13 +428,49 @@
return t5.mod(q);
}
- // NOTE: This following impl is defined in FIPS 186-4 AppendixB.2.1.
protected BigInteger generateK(BigInteger q) {
+ // Implementation defined in FIPS 186-4 AppendixB.2.1.
SecureRandom random = getSigningRandom();
byte[] kValue = new byte[(q.bitLength() + 7)/8 + 8];
random.nextBytes(kValue);
- return new BigInteger(1, kValue).mod(q.subtract(BigInteger.ONE)).add(BigInteger.ONE);
+ BigInteger k = new BigInteger(1, kValue).mod(
+ q.subtract(BigInteger.ONE)).add(BigInteger.ONE);
+
+ // Using an equivalent exponent of fixed length (same as q or 1 bit
+ // less than q) to keep the kG timing relatively constant.
+ //
+ // Note that this is an extra step on top of the approach defined in
+ // FIPS 186-4 AppendixB.2.1 so as to make a fixed length K.
+ k = k.add(q).divide(BigInteger.TWO);
+
+ // An alternative implementation based on FIPS 186-4 AppendixB2.2
+ // with fixed-length K.
+ //
+ // Please keep it here as we may need to switch to it in the future.
+ //
+ // SecureRandom random = getSigningRandom();
+ // byte[] kValue = new byte[(q.bitLength() + 7)/8];
+ // BigInteger d = q.subtract(BigInteger.TWO);
+ // BigInteger k;
+ // do {
+ // random.nextBytes(kValue);
+ // BigInteger c = new BigInteger(1, kValue);
+ // if (c.compareTo(d) <= 0) {
+ // k = c.add(BigInteger.ONE);
+ // // Using an equivalent exponent of fixed length to keep
+ // // the g^k timing relatively constant.
+ // //
+ // // Note that this is an extra step on top of the approach
+ // // defined in FIPS 186-4 AppendixB.2.2 so as to make a
+ // // fixed length K.
+ // if (k.bitLength() >= q.bitLength()) {
+ // break;
+ // }
+ // }
+ // } while (true);
+
+ return k;
}
// Use the application-specified SecureRandom Object if provided.
--- a/jdk/src/java.base/share/classes/sun/security/rsa/RSASignature.java Fri Jan 20 10:28:34 2017 -0800
+++ b/jdk/src/java.base/share/classes/sun/security/rsa/RSASignature.java Fri Jan 20 08:53:42 2017 -0800
@@ -226,9 +226,10 @@
* Decode the signature data. Verify that the object identifier matches
* and return the message digest.
*/
- public static byte[] decodeSignature(ObjectIdentifier oid, byte[] signature)
+ public static byte[] decodeSignature(ObjectIdentifier oid, byte[] sig)
throws IOException {
- DerInputStream in = new DerInputStream(signature);
+ // Enforce strict DER checking for signatures
+ DerInputStream in = new DerInputStream(sig, 0, sig.length, false);
DerValue[] values = in.getSequence(2);
if ((values.length != 2) || (in.available() != 0)) {
throw new IOException("SEQUENCE length error");
--- a/jdk/src/java.base/share/classes/sun/security/ssl/ClientHandshaker.java Fri Jan 20 10:28:34 2017 -0800
+++ b/jdk/src/java.base/share/classes/sun/security/ssl/ClientHandshaker.java Fri Jan 20 08:53:42 2017 -0800
@@ -673,8 +673,11 @@
} else {
// we wanted to resume, but the server refused
//
- // Invalidate the session in case of reusing next time.
- session.invalidate();
+ // Invalidate the session for initial handshake in case
+ // of reusing next time.
+ if (isInitialHandshake) {
+ session.invalidate();
+ }
session = null;
if (!enableNewSession) {
throw new SSLException("New session creation is disabled");
--- a/jdk/src/java.base/share/classes/sun/security/ssl/X509KeyManagerImpl.java Fri Jan 20 10:28:34 2017 -0800
+++ b/jdk/src/java.base/share/classes/sun/security/ssl/X509KeyManagerImpl.java Fri Jan 20 08:53:42 2017 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2004, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2004, 2017, 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
@@ -818,6 +818,11 @@
checker.init(false);
} catch (CertPathValidatorException cpve) {
// unlikely to happen
+ if (useDebug) {
+ debug.println(
+ "Cannot initialize algorithm constraints checker: " + cpve);
+ }
+
return false;
}
@@ -828,6 +833,11 @@
// We don't care about the unresolved critical extensions.
checker.check(cert, Collections.<String>emptySet());
} catch (CertPathValidatorException cpve) {
+ if (useDebug) {
+ debug.println("Certificate (" + cert +
+ ") does not conform to algorithm constraints: " + cpve);
+ }
+
return false;
}
}
--- a/jdk/src/java.base/share/classes/sun/security/util/DerInputBuffer.java Fri Jan 20 10:28:34 2017 -0800
+++ b/jdk/src/java.base/share/classes/sun/security/util/DerInputBuffer.java Fri Jan 20 08:53:42 2017 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2016, 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
@@ -147,6 +147,11 @@
System.arraycopy(buf, pos, bytes, 0, len);
skip(len);
+ // check to make sure no extra leading 0s for DER
+ if (len >= 2 && (bytes[0] == 0) && (bytes[1] >= 0)) {
+ throw new IOException("Invalid encoding: redundant leading 0s");
+ }
+
if (makePositive) {
return new BigInteger(1, bytes);
} else {
--- a/jdk/src/java.base/share/classes/sun/security/util/DerInputStream.java Fri Jan 20 10:28:34 2017 -0800
+++ b/jdk/src/java.base/share/classes/sun/security/util/DerInputStream.java Fri Jan 20 08:53:42 2017 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2016, 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
@@ -77,7 +77,7 @@
* @param data the buffer from which to create the string (CONSUMED)
*/
public DerInputStream(byte[] data) throws IOException {
- init(data, 0, data.length);
+ init(data, 0, data.length, true);
}
/**
@@ -92,23 +92,48 @@
* starting at "offset"
*/
public DerInputStream(byte[] data, int offset, int len) throws IOException {
- init(data, offset, len);
+ init(data, offset, len, true);
+ }
+
+ /**
+ * Create a DER input stream from part of a data buffer with
+ * additional arg to indicate whether to allow constructed
+ * indefinite-length encoding.
+ * The buffer is not copied, it is shared. Accordingly, the
+ * buffer should be treated as read-only.
+ *
+ * @param data the buffer from which to create the string (CONSUMED)
+ * @param offset the first index of <em>data</em> which will
+ * be read as DER input in the new stream
+ * @param len how long a chunk of the buffer to use,
+ * starting at "offset"
+ * @param allowIndefiniteLength whether to allow constructed
+ * indefinite-length encoding
+ */
+ public DerInputStream(byte[] data, int offset, int len,
+ boolean allowIndefiniteLength) throws IOException {
+ init(data, offset, len, allowIndefiniteLength);
}
/*
* private helper routine
*/
- private void init(byte[] data, int offset, int len) throws IOException {
+ private void init(byte[] data, int offset, int len,
+ boolean allowIndefiniteLength) throws IOException {
if ((offset+2 > data.length) || (offset+len > data.length)) {
throw new IOException("Encoding bytes too short");
}
// check for indefinite length encoding
if (DerIndefLenConverter.isIndefinite(data[offset+1])) {
- byte[] inData = new byte[len];
- System.arraycopy(data, offset, inData, 0, len);
+ if (!allowIndefiniteLength) {
+ throw new IOException("Indefinite length BER encoding found");
+ } else {
+ byte[] inData = new byte[len];
+ System.arraycopy(data, offset, inData, 0, len);
- DerIndefLenConverter derIn = new DerIndefLenConverter();
- buffer = new DerInputBuffer(derIn.convert(inData));
+ DerIndefLenConverter derIn = new DerIndefLenConverter();
+ buffer = new DerInputBuffer(derIn.convert(inData));
+ }
} else
buffer = new DerInputBuffer(data, offset, len);
buffer.mark(Integer.MAX_VALUE);
@@ -239,15 +264,19 @@
* representation.
*/
length--;
- int validBits = length*8 - buffer.read();
+ int excessBits = buffer.read();
+ if (excessBits < 0) {
+ throw new IOException("Unused bits of bit string invalid");
+ }
+ int validBits = length*8 - excessBits;
if (validBits < 0) {
- throw new IOException("valid bits of bit string invalid");
+ throw new IOException("Valid bits of bit string invalid");
}
byte[] repn = new byte[length];
if ((length != 0) && (buffer.read(repn) != length)) {
- throw new IOException("short read of DER bit string");
+ throw new IOException("Short read of DER bit string");
}
return new BitArray(validBits, repn);
@@ -263,7 +292,7 @@
int length = getDefiniteLength(buffer);
byte[] retval = new byte[length];
if ((length != 0) && (buffer.read(retval) != length))
- throw new IOException("short read of DER octet string");
+ throw new IOException("Short read of DER octet string");
return retval;
}
@@ -273,7 +302,7 @@
*/
public void getBytes(byte[] val) throws IOException {
if ((val.length != 0) && (buffer.read(val) != val.length)) {
- throw new IOException("short read of DER octet string");
+ throw new IOException("Short read of DER octet string");
}
}
@@ -357,7 +386,7 @@
DerInputStream newstr;
byte lenByte = (byte)buffer.read();
- int len = getLength((lenByte & 0xff), buffer);
+ int len = getLength(lenByte, buffer);
if (len == -1) {
// indefinite length encoding found
@@ -403,7 +432,7 @@
} while (newstr.available() > 0);
if (newstr.available() != 0)
- throw new IOException("extra data at end of vector");
+ throw new IOException("Extra data at end of vector");
/*
* Now stick them into the array we're returning.
@@ -494,7 +523,7 @@
int length = getDefiniteLength(buffer);
byte[] retval = new byte[length];
if ((length != 0) && (buffer.read(retval) != length))
- throw new IOException("short read of DER " +
+ throw new IOException("Short read of DER " +
stringName + " string");
return new String(retval, enc);
@@ -555,7 +584,11 @@
*/
static int getLength(int lenByte, InputStream in) throws IOException {
int value, tmp;
+ if (lenByte == -1) {
+ throw new IOException("Short read of DER length");
+ }
+ String mdName = "DerInputStream.getLength(): ";
tmp = lenByte;
if ((tmp & 0x080) == 0x00) { // short form, 1 byte datum
value = tmp;
@@ -569,17 +602,23 @@
if (tmp == 0)
return -1;
if (tmp < 0 || tmp > 4)
- throw new IOException("DerInputStream.getLength(): lengthTag="
- + tmp + ", "
+ throw new IOException(mdName + "lengthTag=" + tmp + ", "
+ ((tmp < 0) ? "incorrect DER encoding." : "too big."));
- for (value = 0; tmp > 0; tmp --) {
+ value = 0x0ff & in.read();
+ tmp--;
+ if (value == 0) {
+ // DER requires length value be encoded in minimum number of bytes
+ throw new IOException(mdName + "Redundant length bytes found");
+ }
+ while (tmp-- > 0) {
value <<= 8;
value += 0x0ff & in.read();
}
if (value < 0) {
- throw new IOException("DerInputStream.getLength(): "
- + "Invalid length bytes");
+ throw new IOException(mdName + "Invalid length bytes");
+ } else if (value <= 127) {
+ throw new IOException(mdName + "Should use short form for length");
}
}
return value;
--- a/jdk/src/java.base/share/classes/sun/security/util/DerValue.java Fri Jan 20 10:28:34 2017 -0800
+++ b/jdk/src/java.base/share/classes/sun/security/util/DerValue.java Fri Jan 20 08:53:42 2017 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2016, 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
@@ -248,7 +248,7 @@
tag = (byte)in.read();
byte lenByte = (byte)in.read();
- length = DerInputStream.getLength((lenByte & 0xff), in);
+ length = DerInputStream.getLength(lenByte, in);
if (length == -1) { // indefinite length encoding found
DerInputBuffer inbuf = in.dup();
int readLen = inbuf.available();
@@ -361,7 +361,7 @@
tag = (byte)in.read();
byte lenByte = (byte)in.read();
- length = DerInputStream.getLength((lenByte & 0xff), in);
+ length = DerInputStream.getLength(lenByte, in);
if (length == -1) { // indefinite length encoding found
int readLen = in.available();
int offset = 2; // for tag and length bytes
--- a/jdk/src/java.base/share/classes/sun/security/util/ObjectIdentifier.java Fri Jan 20 10:28:34 2017 -0800
+++ b/jdk/src/java.base/share/classes/sun/security/util/ObjectIdentifier.java Fri Jan 20 08:53:42 2017 -0800
@@ -255,7 +255,13 @@
+ " (tag = " + type_id + ")"
);
- encoding = new byte[in.getDefiniteLength()];
+ int len = in.getDefiniteLength();
+ if (len > in.available()) {
+ throw new IOException("ObjectIdentifier() -- length exceeds" +
+ "data available. Length: " + len + ", Available: " +
+ in.available());
+ }
+ encoding = new byte[len];
in.getBytes(encoding);
check(encoding);
}
--- a/jdk/src/java.base/share/conf/security/java.security Fri Jan 20 10:28:34 2017 -0800
+++ b/jdk/src/java.base/share/conf/security/java.security Fri Jan 20 08:53:42 2017 -0800
@@ -298,111 +298,24 @@
#
# List of comma-separated packages that start with or equal this string
-# will cause a security exception to be thrown when
-# passed to checkPackageAccess unless the
-# corresponding RuntimePermission ("accessClassInPackage."+package) has
-# been granted.
-package.access=sun.,\
- com.sun.xml.internal.,\
- com.sun.imageio.,\
- com.sun.istack.internal.,\
- com.sun.jmx.,\
- com.sun.media.sound.,\
- com.sun.naming.internal.,\
- com.sun.proxy.,\
- com.sun.corba.se.,\
- com.sun.org.apache.bcel.internal.,\
- com.sun.org.apache.regexp.internal.,\
- com.sun.org.apache.xerces.internal.,\
- com.sun.org.apache.xpath.internal.,\
- com.sun.org.apache.xalan.internal.extensions.,\
- com.sun.org.apache.xalan.internal.lib.,\
- com.sun.org.apache.xalan.internal.res.,\
- com.sun.org.apache.xalan.internal.templates.,\
- com.sun.org.apache.xalan.internal.utils.,\
- com.sun.org.apache.xalan.internal.xslt.,\
- com.sun.org.apache.xalan.internal.xsltc.cmdline.,\
- com.sun.org.apache.xalan.internal.xsltc.compiler.,\
- com.sun.org.apache.xalan.internal.xsltc.trax.,\
- com.sun.org.apache.xalan.internal.xsltc.util.,\
- com.sun.org.apache.xml.internal.res.,\
- com.sun.org.apache.xml.internal.security.,\
- com.sun.org.apache.xml.internal.serializer.dom3.,\
- com.sun.org.apache.xml.internal.serializer.utils.,\
- com.sun.org.apache.xml.internal.utils.,\
- com.sun.org.glassfish.,\
- com.sun.tools.script.,\
- com.oracle.xmlns.internal.,\
- com.oracle.webservices.internal.,\
- org.jcp.xml.dsig.internal.,\
- jdk.internal.,\
- jdk.nashorn.internal.,\
- jdk.nashorn.tools.,\
- jdk.tools.jimage.,\
- com.sun.activation.registries.,\
- com.sun.java.accessibility.util.internal.,\
-#ifdef windows
- com.sun.java.accessibility.internal.,\
-#endif
-#ifdef macosx
- apple.,\
-#endif
+# will cause a security exception to be thrown when passed to the
+# SecurityManager::checkPackageAccess method unless the corresponding
+# RuntimePermission("accessClassInPackage."+package) has been granted.
+#
+package.access=sun.misc.,\
+ sun.reflect.,\
#
# List of comma-separated packages that start with or equal this string
-# will cause a security exception to be thrown when
-# passed to checkPackageDefinition unless the
-# corresponding RuntimePermission ("defineClassInPackage."+package) has
-# been granted.
+# will cause a security exception to be thrown when passed to the
+# SecurityManager::checkPackageDefinition method unless the corresponding
+# RuntimePermission("defineClassInPackage."+package) has been granted.
#
-# by default, none of the class loaders supplied with the JDK call
+# By default, none of the class loaders supplied with the JDK call
# checkPackageDefinition.
#
-package.definition=sun.,\
- com.sun.xml.internal.,\
- com.sun.imageio.,\
- com.sun.istack.internal.,\
- com.sun.jmx.,\
- com.sun.media.sound.,\
- com.sun.naming.internal.,\
- com.sun.proxy.,\
- com.sun.corba.se.,\
- com.sun.org.apache.bcel.internal.,\
- com.sun.org.apache.regexp.internal.,\
- com.sun.org.apache.xerces.internal.,\
- com.sun.org.apache.xpath.internal.,\
- com.sun.org.apache.xalan.internal.extensions.,\
- com.sun.org.apache.xalan.internal.lib.,\
- com.sun.org.apache.xalan.internal.res.,\
- com.sun.org.apache.xalan.internal.templates.,\
- com.sun.org.apache.xalan.internal.utils.,\
- com.sun.org.apache.xalan.internal.xslt.,\
- com.sun.org.apache.xalan.internal.xsltc.cmdline.,\
- com.sun.org.apache.xalan.internal.xsltc.compiler.,\
- com.sun.org.apache.xalan.internal.xsltc.trax.,\
- com.sun.org.apache.xalan.internal.xsltc.util.,\
- com.sun.org.apache.xml.internal.res.,\
- com.sun.org.apache.xml.internal.security.,\
- com.sun.org.apache.xml.internal.serializer.dom3.,\
- com.sun.org.apache.xml.internal.serializer.utils.,\
- com.sun.org.apache.xml.internal.utils.,\
- com.sun.org.glassfish.,\
- com.sun.tools.script.,\
- com.oracle.xmlns.internal.,\
- com.oracle.webservices.internal.,\
- org.jcp.xml.dsig.internal.,\
- jdk.internal.,\
- jdk.nashorn.internal.,\
- jdk.nashorn.tools.,\
- jdk.tools.jimage.,\
- com.sun.activation.registries.,\
- com.sun.java.accessibility.util.internal.,\
-#ifdef windows
- com.sun.java.accessibility.internal.,\
-#endif
-#ifdef macosx
- apple.,\
-#endif
+package.definition=sun.misc.,\
+ sun.reflect.,\
#
# Determines whether this properties file can be appended to
@@ -658,6 +571,36 @@
jdk.certpath.disabledAlgorithms=MD2, MD5, SHA1 jdkCA & denyAfter 2017-01-01, \
RSA keySize < 1024, DSA keySize < 1024, EC keySize < 224
+#
+# RMI Registry Serial Filter
+#
+# The filter pattern uses the same format as jdk.serialFilter.
+# This filter can override the builtin filter if additional types need to be
+# allowed or rejected from the RMI Registry.
+#
+# Note: This property is currently used by the JDK Reference implementation.
+# It is not guaranteed to be examined and used by other implementations.
+#
+#sun.rmi.registry.registryFilter=pattern;pattern
+#
+# RMI Distributed Garbage Collector (DGC) Serial Filter
+#
+# The filter pattern uses the same format as jdk.serialFilter.
+# This filter can override the builtin filter if additional types need to be
+# allowed or rejected from the RMI DGC.
+#
+# Note: This property is currently used by the JDK Reference implementation.
+# It is not guaranteed to be examined and used by other implementations.
+#
+# The builtin DGC filter can approximately be represented as the filter pattern:
+#
+#sun.rmi.transport.dgcFilter=\
+# java.rmi.server.ObjID;\
+# java.rmi.server.UID;\
+# java.rmi.dgc.VMID;\
+# java.rmi.dgc.Lease;\
+# maxdepth=5;maxarray=10000
+
# Algorithm restrictions for signed JAR files
#
# In some environments, certain algorithms or key lengths may be undesirable
@@ -720,7 +663,7 @@
# Note: The algorithm restrictions do not apply to trust anchors or
# self-signed certificates.
#
-# Note: This property is currently used by Oracle's JSSE implementation.
+# Note: This property is currently used by the JDK Reference implementation.
# It is not guaranteed to be examined and used by other implementations.
#
# Example:
@@ -740,7 +683,7 @@
# During SSL/TLS security parameters negotiation, legacy algorithms will
# not be negotiated unless there are no other candidates.
#
-# The syntax of the disabled algorithm string is described as this Java
+# The syntax of the legacy algorithms string is described as this Java
# BNF-style:
# LegacyAlgorithms:
# " LegacyAlgorithm { , LegacyAlgorithm } "
@@ -776,7 +719,7 @@
# javax.net.ssl.SSLParameters.setAlgorithmConstraints()),
# then the algorithm is completely disabled and will not be negotiated.
#
-# Note: This property is currently used by Oracle's JSSE implementation.
+# Note: This property is currently used by the JDK Reference implementation.
# It is not guaranteed to be examined and used by other implementations.
# There is no guarantee the property will continue to exist or be of the
# same syntax in future releases.
@@ -789,7 +732,8 @@
DHE_DSS_EXPORT, DHE_RSA_EXPORT, DH_anon_EXPORT, DH_DSS_EXPORT, \
DH_RSA_EXPORT, RSA_EXPORT, \
DH_anon, ECDH_anon, \
- RC4_128, RC4_40, DES_CBC, DES40_CBC
+ RC4_128, RC4_40, DES_CBC, DES40_CBC, \
+ 3DES_EDE_CBC
# The pre-defined default finite field Diffie-Hellman ephemeral (DHE)
# parameters for Transport Layer Security (SSL/TLS/DTLS) processing.
@@ -912,7 +856,7 @@
# Constraint {"," Constraint }
# Constraint:
# AlgConstraint | MaxTransformsConstraint | MaxReferencesConstraint |
-# ReferenceUriSchemeConstraint | OtherConstraint
+# ReferenceUriSchemeConstraint | KeySizeConstraint | OtherConstraint
# AlgConstraint
# "disallowAlg" Uri
# MaxTransformsConstraint:
@@ -921,12 +865,16 @@
# "maxReferences" Integer
# ReferenceUriSchemeConstraint:
# "disallowReferenceUriSchemes" String { String }
+# KeySizeConstraint:
+# "minKeySize" KeyAlg Integer
# OtherConstraint:
# "noDuplicateIds" | "noRetrievalMethodLoops"
#
# For AlgConstraint, Uri is the algorithm URI String that is not allowed.
# See the XML Signature Recommendation for more information on algorithm
-# URI Identifiers. If the MaxTransformsConstraint or MaxReferencesConstraint is
+# URI Identifiers. For KeySizeConstraint, KeyAlg is the standard algorithm
+# name of the key type (ex: "RSA"). If the MaxTransformsConstraint,
+# MaxReferencesConstraint or KeySizeConstraint (for the same key type) is
# specified more than once, only the last entry is enforced.
#
# Note: This property is currently used by the JDK Reference implementation. It
@@ -940,6 +888,8 @@
maxTransforms 5,\
maxReferences 30,\
disallowReferenceUriSchemes file http https,\
+ minKeySize RSA 1024,\
+ minKeySize DSA 1024,\
noDuplicateIds,\
noRetrievalMethodLoops
--- a/jdk/src/java.base/share/lib/security/default.policy Fri Jan 20 10:28:34 2017 -0800
+++ b/jdk/src/java.base/share/lib/security/default.policy Fri Jan 20 08:53:42 2017 -0800
@@ -81,6 +81,8 @@
};
grant codeBase "jrt:/java.xml.crypto" {
+ permission java.lang.RuntimePermission
+ "accessClassInPackage.sun.security.util";
permission java.util.PropertyPermission "*", "read";
permission java.security.SecurityPermission "putProviderProperty.XMLDSig";
permission java.security.SecurityPermission
@@ -91,10 +93,20 @@
"com.sun.org.apache.xml.internal.security.register";
permission java.security.SecurityPermission
"getProperty.jdk.xml.dsig.secureValidationPolicy";
+ permission java.lang.RuntimePermission
+ "accessClassInPackage.com.sun.org.apache.xml.internal.*";
+ permission java.lang.RuntimePermission
+ "accessClassInPackage.com.sun.org.apache.xpath.internal";
+ permission java.lang.RuntimePermission
+ "accessClassInPackage.com.sun.org.apache.xpath.internal.*";
};
grant codeBase "jrt:/java.xml.ws" {
permission java.lang.RuntimePermission
+ "accessClassInPackage.com.sun.org.apache.xml.internal.resolver";
+ permission java.lang.RuntimePermission
+ "accessClassInPackage.com.sun.org.apache.xml.internal.resolver.tools";
+ permission java.lang.RuntimePermission
"accessClassInPackage.com.sun.xml.internal.*";
permission java.lang.RuntimePermission
"accessClassInPackage.com.sun.istack.internal";
@@ -186,3 +198,10 @@
permission java.util.PropertyPermission "os.name", "read";
};
+grant codeBase "jrt:/jdk.accessibility" {
+ permission java.lang.RuntimePermission "accessClassInPackage.sun.awt";
+};
+
+grant codeBase "jrt:/jdk.desktop" {
+ permission java.lang.RuntimePermission "accessClassInPackage.com.sun.awt";
+};
--- a/jdk/src/java.base/unix/native/libnet/SocketOutputStream.c Fri Jan 20 10:28:34 2017 -0800
+++ b/jdk/src/java.base/unix/native/libnet/SocketOutputStream.c Fri Jan 20 08:53:42 2017 -0800
@@ -98,27 +98,31 @@
int llen = chunkLen;
(*env)->GetByteArrayRegion(env, data, off, chunkLen, (jbyte *)bufP);
- while(llen > 0) {
- int n = NET_Send(fd, bufP + loff, llen, 0);
- if (n > 0) {
- llen -= n;
- loff += n;
- continue;
+ if ((*env)->ExceptionCheck(env)) {
+ break;
+ } else {
+ while(llen > 0) {
+ int n = NET_Send(fd, bufP + loff, llen, 0);
+ if (n > 0) {
+ llen -= n;
+ loff += n;
+ continue;
+ }
+ if (errno == ECONNRESET) {
+ JNU_ThrowByName(env, "sun/net/ConnectionResetException",
+ "Connection reset");
+ } else {
+ JNU_ThrowByNameWithMessageAndLastError
+ (env, "java/net/SocketException", "Write failed");
+ }
+ if (bufP != BUF) {
+ free(bufP);
+ }
+ return;
}
- if (errno == ECONNRESET) {
- JNU_ThrowByName(env, "sun/net/ConnectionResetException",
- "Connection reset");
- } else {
- JNU_ThrowByNameWithMessageAndLastError
- (env, "java/net/SocketException", "Write failed");
- }
- if (bufP != BUF) {
- free(bufP);
- }
- return;
+ len -= chunkLen;
+ off += chunkLen;
}
- len -= chunkLen;
- off += chunkLen;
}
if (bufP != BUF) {
--- a/jdk/src/java.base/windows/native/libnet/SocketOutputStream.c Fri Jan 20 10:28:34 2017 -0800
+++ b/jdk/src/java.base/windows/native/libnet/SocketOutputStream.c Fri Jan 20 08:53:42 2017 -0800
@@ -92,66 +92,69 @@
int retry = 0;
(*env)->GetByteArrayRegion(env, data, off, chunkLen, (jbyte *)bufP);
-
- while(llen > 0) {
- int n = send(fd, bufP + loff, llen, 0);
- if (n > 0) {
- llen -= n;
- loff += n;
- continue;
- }
-
- /*
- * Due to a bug in Windows Sockets (observed on NT and Windows
- * 2000) it may be necessary to retry the send. The issue is that
- * on blocking sockets send/WSASend is supposed to block if there
- * is insufficient buffer space available. If there are a large
- * number of threads blocked on write due to congestion then it's
- * possile to hit the NT/2000 bug whereby send returns WSAENOBUFS.
- * The workaround we use is to retry the send. If we have a
- * large buffer to send (>2k) then we retry with a maximum of
- * 2k buffer. If we hit the issue with <=2k buffer then we backoff
- * for 1 second and retry again. We repeat this up to a reasonable
- * limit before bailing out and throwing an exception. In load
- * conditions we've observed that the send will succeed after 2-3
- * attempts but this depends on network buffers associated with
- * other sockets draining.
- */
- if (WSAGetLastError() == WSAENOBUFS) {
- if (llen > MAX_BUFFER_LEN) {
- buflen = MAX_BUFFER_LEN;
- chunkLen = MAX_BUFFER_LEN;
- llen = MAX_BUFFER_LEN;
+ if ((*env)->ExceptionCheck(env)) {
+ break;
+ } else {
+ while(llen > 0) {
+ int n = send(fd, bufP + loff, llen, 0);
+ if (n > 0) {
+ llen -= n;
+ loff += n;
continue;
}
- if (retry >= 30) {
- JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
- "No buffer space available - exhausted attempts to queue buffer");
- if (bufP != BUF) {
- free(bufP);
- }
- return;
- }
- Sleep(1000);
- retry++;
- continue;
- }
- /*
- * Send failed - can be caused by close or write error.
- */
- if (WSAGetLastError() == WSAENOTSOCK) {
- JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Socket closed");
- } else {
- NET_ThrowCurrent(env, "socket write error");
+ /*
+ * Due to a bug in Windows Sockets (observed on NT and Windows
+ * 2000) it may be necessary to retry the send. The issue is that
+ * on blocking sockets send/WSASend is supposed to block if there
+ * is insufficient buffer space available. If there are a large
+ * number of threads blocked on write due to congestion then it's
+ * possile to hit the NT/2000 bug whereby send returns WSAENOBUFS.
+ * The workaround we use is to retry the send. If we have a
+ * large buffer to send (>2k) then we retry with a maximum of
+ * 2k buffer. If we hit the issue with <=2k buffer then we backoff
+ * for 1 second and retry again. We repeat this up to a reasonable
+ * limit before bailing out and throwing an exception. In load
+ * conditions we've observed that the send will succeed after 2-3
+ * attempts but this depends on network buffers associated with
+ * other sockets draining.
+ */
+ if (WSAGetLastError() == WSAENOBUFS) {
+ if (llen > MAX_BUFFER_LEN) {
+ buflen = MAX_BUFFER_LEN;
+ chunkLen = MAX_BUFFER_LEN;
+ llen = MAX_BUFFER_LEN;
+ continue;
+ }
+ if (retry >= 30) {
+ JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
+ "No buffer space available - exhausted attempts to queue buffer");
+ if (bufP != BUF) {
+ free(bufP);
+ }
+ return;
+ }
+ Sleep(1000);
+ retry++;
+ continue;
+ }
+
+ /*
+ * Send failed - can be caused by close or write error.
+ */
+ if (WSAGetLastError() == WSAENOTSOCK) {
+ JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Socket closed");
+ } else {
+ NET_ThrowCurrent(env, "socket write error");
+ }
+ if (bufP != BUF) {
+ free(bufP);
+ }
+ return;
}
- if (bufP != BUF) {
- free(bufP);
- }
- return;
+ len -= chunkLen;
+ off += chunkLen;
}
- len -= chunkLen;
- off += chunkLen;
}
if (bufP != BUF) {
--- a/jdk/src/java.base/windows/native/libnio/ch/WindowsSelectorImpl.c Fri Jan 20 10:28:34 2017 -0800
+++ b/jdk/src/java.base/windows/native/libnio/ch/WindowsSelectorImpl.c Fri Jan 20 08:53:42 2017 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2017, 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
@@ -32,6 +32,7 @@
#define FD_SETSIZE 1024
+#include <limits.h>
#include <stdlib.h>
#include <winsock2.h>
@@ -75,8 +76,18 @@
tv = NULL;
} else {
tv = &timevalue;
- tv->tv_sec = (long)(timeout / 1000);
- tv->tv_usec = (long)((timeout % 1000) * 1000);
+ jlong sec = timeout / 1000;
+ //
+ // struct timeval members are signed 32-bit integers so the
+ // signed 64-bit jlong needs to be clamped
+ //
+ if (sec > INT_MAX) {
+ tv->tv_sec = INT_MAX;
+ tv->tv_usec = 0;
+ } else {
+ tv->tv_sec = (long)sec;
+ tv->tv_usec = (long)((timeout % 1000) * 1000);
+ }
}
/* Set FD_SET structures required for select */
--- a/jdk/src/java.desktop/macosx/classes/com/apple/eawt/_AppMenuBarHandler.java Fri Jan 20 10:28:34 2017 -0800
+++ b/jdk/src/java.desktop/macosx/classes/com/apple/eawt/_AppMenuBarHandler.java Fri Jan 20 08:53:42 2017 -0800
@@ -123,7 +123,7 @@
}
// grab the pointer to the CMenuBar, and retain it in native
- nativeSetDefaultMenuBar(((CMenuBar)peer).getModel());
+ ((CMenuBar) peer).execute(_AppMenuBarHandler::nativeSetDefaultMenuBar);
}
void setAboutMenuItemVisible(final boolean present) {
--- a/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CCheckboxMenuItem.java Fri Jan 20 10:28:34 2017 -0800
+++ b/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CCheckboxMenuItem.java Fri Jan 20 08:53:42 2017 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2016, 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
@@ -26,29 +26,28 @@
package sun.lwawt.macosx;
import java.awt.CheckboxMenuItem;
-import java.awt.EventQueue;
import java.awt.event.ItemEvent;
import java.awt.peer.CheckboxMenuItemPeer;
import sun.awt.SunToolkit;
public class CCheckboxMenuItem extends CMenuItem implements CheckboxMenuItemPeer {
- boolean fAutoToggle = true;
- boolean fIsIndeterminate = false;
+ volatile boolean fAutoToggle = true;
+ volatile boolean fIsIndeterminate = false;
private native void nativeSetState(long modelPtr, boolean state);
private native void nativeSetIsCheckbox(long modelPtr);
- CCheckboxMenuItem(CheckboxMenuItem target) {
+ CCheckboxMenuItem(final CheckboxMenuItem target) {
super(target);
- nativeSetIsCheckbox(getModel());
+ execute(this::nativeSetIsCheckbox);
setState(target.getState());
}
// MenuItemPeer implementation
@Override
- public void setState(boolean state) {
- nativeSetState(getModel(), state);
+ public void setState(final boolean state) {
+ execute(ptr -> nativeSetState(ptr, state));
}
public void handleAction(final boolean state) {
--- a/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CFRetainedResource.java Fri Jan 20 10:28:34 2017 -0800
+++ b/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CFRetainedResource.java Fri Jan 20 08:53:42 2017 -0800
@@ -23,7 +23,6 @@
* questions.
*/
-
package sun.lwawt.macosx;
/**
@@ -34,6 +33,7 @@
private static native void nativeCFRelease(final long ptr, final boolean disposeOnAppKitThread);
private final boolean disposeOnAppKitThread;
+ // TODO this pointer should be private and accessed via CFNativeAction class
protected volatile long ptr;
/**
@@ -70,8 +70,72 @@
nativeCFRelease(oldPtr, disposeOnAppKitThread); // perform outside of the synchronized block
}
+ /**
+ * The interface which allows to execute some native operations with
+ * assumption that the native pointer will be valid till the end.
+ */
+ public interface CFNativeAction {
+
+ /**
+ * The native operation should be called from this method.
+ *
+ * @param ptr the pointer to the native data
+ */
+ void run(long ptr);
+ }
+
+ /**
+ * The interface which allows to execute some native operations and get a
+ * result with assumption that the native pointer will be valid till the
+ * end.
+ */
+ interface CFNativeActionGet {
+
+ /**
+ * The native operation should be called from this method.
+ *
+ * @param ptr the pointer to the native data
+ * @return result of the native operation
+ */
+ long run(long ptr);
+ }
+
+ /**
+ * This is utility method which should be used instead of the direct access
+ * to the {@link #ptr}, because this method guaranteed that the pointer will
+ * not be zero and will be valid till the end of the operation.It is highly
+ * recomended to not use any external lock in action. If the current
+ * {@link #ptr} is {@code 0} then action will be ignored.
+ *
+ * @param action The native operation
+ */
+ public final synchronized void execute(final CFNativeAction action) {
+ if (ptr != 0) {
+ action.run(ptr);
+ }
+ }
+
+ /**
+ * This is utility method which should be used instead of the direct access
+ * to the {@link #ptr}, because this method guaranteed that the pointer will
+ * not be zero and will be valid till the end of the operation. It is highly
+ * recomended to not use any external lock in action. If the current
+ * {@link #ptr} is {@code 0} then action will be ignored and {@code} is
+ * returned.
+ *
+ * @param action the native operation
+ * @return result of the native operation, usually the native pointer to
+ * some other data
+ */
+ final synchronized long executeGet(final CFNativeActionGet action) {
+ if (ptr != 0) {
+ return action.run(ptr);
+ }
+ return 0;
+ }
+
@Override
- protected void finalize() throws Throwable {
+ protected final void finalize() throws Throwable {
dispose();
}
}
--- a/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CMenu.java Fri Jan 20 10:28:34 2017 -0800
+++ b/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CMenu.java Fri Jan 20 08:53:42 2017 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2016, 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
@@ -25,7 +25,9 @@
package sun.lwawt.macosx;
-import java.awt.*;
+import java.awt.Menu;
+import java.awt.MenuBar;
+import java.awt.MenuItem;
import java.awt.peer.MenuItemPeer;
import java.awt.peer.MenuPeer;
@@ -37,7 +39,7 @@
// This way we avoiding invocation of the setters twice
@Override
- protected void initialize(MenuItem target) {
+ protected final void initialize(MenuItem target) {
setLabel(target.getLabel());
setEnabled(target.isEnabled());
}
@@ -57,52 +59,50 @@
}
@Override
- protected long createModel() {
+ long createModel() {
CMenuComponent parent = (CMenuComponent)
LWCToolkit.targetToPeer(getTarget().getParent());
- if (parent instanceof CMenu ||
- parent instanceof CPopupMenu)
- {
- return nativeCreateSubMenu(parent.getModel());
- } else if (parent instanceof CMenuBar) {
+ if (parent instanceof CMenu) {
+ return parent.executeGet(this::nativeCreateSubMenu);
+ }
+ if (parent instanceof CMenuBar) {
MenuBar parentContainer = (MenuBar)getTarget().getParent();
boolean isHelpMenu = parentContainer.getHelpMenu() == getTarget();
int insertionLocation = ((CMenuBar)parent).getNextInsertionIndex();
- return nativeCreateMenu(parent.getModel(),
- isHelpMenu, insertionLocation);
- } else {
- throw new InternalError("Parent must be CMenu or CMenuBar");
+ return parent.executeGet(ptr -> nativeCreateMenu(ptr, isHelpMenu,
+ insertionLocation));
}
+ throw new InternalError("Parent must be CMenu or CMenuBar");
}
@Override
- public void addItem(MenuItem item) {
+ public final void addItem(MenuItem item) {
// Nothing to do here -- we added it when we created the
// menu item's peer.
}
@Override
- public void delItem(int index) {
- nativeDeleteItem(getModel(), index);
+ public final void delItem(final int index) {
+ execute(ptr -> nativeDeleteItem(ptr, index));
}
@Override
- public void setLabel(String label) {
- nativeSetMenuTitle(getModel(), label);
+ public final void setLabel(final String label) {
+ execute(ptr->nativeSetMenuTitle(ptr, label));
super.setLabel(label);
}
// Note that addSeparator is never called directly from java.awt.Menu,
// though it is required in the MenuPeer interface.
@Override
- public void addSeparator() {
- nativeAddSeparator(getModel());
+ public final void addSeparator() {
+ execute(this::nativeAddSeparator);
}
// Used by ScreenMenuBar to get to the native menu for event handling.
- public long getNativeMenu() {
- return nativeGetNSMenu(getModel());
+ public final long getNativeMenu() {
+ return executeGet(this::nativeGetNSMenu);
}
private native long nativeCreateMenu(long parentMenuPtr,
--- a/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CMenuBar.java Fri Jan 20 10:28:34 2017 -0800
+++ b/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CMenuBar.java Fri Jan 20 08:53:42 2017 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2016, 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
@@ -31,7 +31,7 @@
import sun.awt.AWTAccessor;
-public class CMenuBar extends CMenuComponent implements MenuBarPeer {
+public final class CMenuBar extends CMenuComponent implements MenuBarPeer {
private int nextInsertionIndex = -1;
@@ -40,14 +40,15 @@
}
@Override
- protected long createModel() {
+ long createModel() {
return nativeCreateMenuBar();
}
@Override
- public void addHelpMenu(Menu m) {
- CMenu cMenu = AWTAccessor.getMenuComponentAccessor().getPeer(m);
- nativeSetHelpMenu(getModel(), cMenu.getModel());
+ public void addHelpMenu(final Menu m) {
+ final CMenu cMenu = AWTAccessor.getMenuComponentAccessor().getPeer(m);
+ execute(parentPtr -> cMenu.execute(
+ menuPtr -> nativeSetHelpMenu(parentPtr, menuPtr)));
}
public int getNextInsertionIndex() {
@@ -65,8 +66,8 @@
}
@Override
- public void delMenu(int index) {
- nativeDelMenu(getModel(), index);
+ public void delMenu(final int index) {
+ execute(ptr -> nativeDelMenu(ptr, index));
}
private native long nativeCreateMenuBar();
--- a/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CMenuComponent.java Fri Jan 20 10:28:34 2017 -0800
+++ b/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CMenuComponent.java Fri Jan 20 08:53:42 2017 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2016, 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
@@ -29,36 +29,32 @@
import java.awt.MenuComponent;
import java.awt.peer.MenuComponentPeer;
-public abstract class CMenuComponent implements MenuComponentPeer {
+abstract class CMenuComponent extends CFRetainedResource
+ implements MenuComponentPeer {
+
+ private final MenuComponent target;
- private MenuComponent target;
- private long modelPtr;
-
- CMenuComponent(MenuComponent target) {
+ CMenuComponent(final MenuComponent target) {
+ super(0, true);
this.target = target;
- this.modelPtr = createModel();
+ setPtr(createModel());
}
- MenuComponent getTarget() {
+ final MenuComponent getTarget() {
return target;
}
- public long getModel() {
- return modelPtr;
+ abstract long createModel();
+
+ @Override
+ public final void dispose() {
+ super.dispose();
+ LWCToolkit.targetDisposedPeer(target, this);
}
- protected abstract long createModel();
-
- public void dispose() {
- LWCToolkit.targetDisposedPeer(target, this);
- nativeDispose(modelPtr);
- target = null;
- }
-
- private native void nativeDispose(long modelPtr);
-
// 1.5 peer method
- public void setFont(Font f) {
+ @Override
+ public final void setFont(final Font f) {
// no-op, as we don't currently support menu fonts
// c.f. radar 4032912
}
--- a/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CMenuItem.java Fri Jan 20 10:28:34 2017 -0800
+++ b/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CMenuItem.java Fri Jan 20 08:53:42 2017 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2016, 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
@@ -25,16 +25,17 @@
package sun.lwawt.macosx;
+import java.awt.MenuItem;
+import java.awt.MenuShortcut;
+import java.awt.event.ActionEvent;
+import java.awt.event.InputEvent;
+import java.awt.event.KeyEvent;
+import java.awt.peer.MenuItemPeer;
+import java.util.concurrent.atomic.AtomicBoolean;
+
import sun.awt.SunToolkit;
import sun.lwawt.LWToolkit;
-import java.awt.MenuContainer;
-import java.awt.MenuItem;
-import java.awt.MenuShortcut;
-import java.awt.event.*;
-import java.awt.peer.MenuItemPeer;
-import java.util.concurrent.atomic.AtomicBoolean;
-
public class CMenuItem extends CMenuComponent implements MenuItemPeer {
private final AtomicBoolean enabled = new AtomicBoolean(true);
@@ -58,9 +59,9 @@
}
@Override
- protected long createModel() {
+ long createModel() {
CMenuComponent parent = (CMenuComponent)LWToolkit.targetToPeer(getTarget().getParent());
- return nativeCreate(parent.getModel(), isSeparator());
+ return parent.executeGet(ptr->nativeCreate(ptr, isSeparator()));
}
public void setLabel(String label, char keyChar, int keyCode, int modifiers) {
@@ -90,7 +91,12 @@
keyChar = 0;
}
- nativeSetLabel(getModel(), label, keyChar, keyCode, keyMask);
+ final String finalLabel = label;
+ final char finalKeyChar = keyChar;
+ final int finalKeyCode = keyCode;
+ final int finalKeyMask = keyMask;
+ execute(ptr -> nativeSetLabel(ptr, finalLabel, finalKeyChar,
+ finalKeyCode, finalKeyMask));
}
@Override
@@ -105,16 +111,16 @@
* There isn't a need to expose this except in a instanceof because
* it isn't defined in the peer api.
*/
- public void setImage(java.awt.Image img) {
+ public final void setImage(final java.awt.Image img) {
CImage cimg = CImage.getCreator().createFromImage(img);
- nativeSetImage(getModel(), cimg == null ? 0L : cimg.ptr);
+ execute(ptr -> nativeSetImage(ptr, cimg == null ? 0L : cimg.ptr));
}
/**
* New API for tooltips
*/
- public void setToolTipText(String text) {
- nativeSetTooltip(getModel(), text);
+ public final void setToolTipText(final String text) {
+ execute(ptr -> nativeSetTooltip(ptr, text));
}
// @Override
@@ -138,7 +144,8 @@
b &= ((CMenuItem) parent).isEnabled();
}
if (enabled.compareAndSet(!b, b)) {
- nativeSetEnabled(getModel(), b);
+ final boolean finalB = b;
+ execute(ptr->nativeSetEnabled(ptr, finalB));
}
}
--- a/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java Fri Jan 20 10:28:34 2017 -0800
+++ b/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java Fri Jan 20 08:53:42 2017 -0800
@@ -449,7 +449,7 @@
final long nsWindowPtr = getNSWindowPtr();
CMenuBar mbPeer = (CMenuBar)LWToolkit.targetToPeer(mb);
if (mbPeer != null) {
- nativeSetNSWindowMenuBar(nsWindowPtr, mbPeer.getModel());
+ mbPeer.execute(ptr -> nativeSetNSWindowMenuBar(nsWindowPtr, ptr));
} else {
nativeSetNSWindowMenuBar(nsWindowPtr, 0);
}
--- a/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPopupMenu.java Fri Jan 20 10:28:34 2017 -0800
+++ b/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPopupMenu.java Fri Jan 20 08:53:42 2017 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2016, 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
@@ -25,18 +25,20 @@
package sun.lwawt.macosx;
-import java.awt.*;
+import java.awt.Component;
+import java.awt.Event;
+import java.awt.Point;
+import java.awt.PopupMenu;
import java.awt.peer.PopupMenuPeer;
-import sun.lwawt.LWWindowPeer;
+final class CPopupMenu extends CMenu implements PopupMenuPeer {
-public class CPopupMenu extends CMenu implements PopupMenuPeer {
CPopupMenu(PopupMenu target) {
super(target);
}
@Override
- protected long createModel() {
+ long createModel() {
return nativeCreatePopupMenu();
}
@@ -50,7 +52,7 @@
Point loc = origin.getLocationOnScreen();
e.x += loc.x;
e.y += loc.y;
- nativeShowPopupMenu(getModel(), e.x, e.y);
+ execute(ptr -> nativeShowPopupMenu(ptr, e.x, e.y));
}
}
}
--- a/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CTrayIcon.java Fri Jan 20 10:28:34 2017 -0800
+++ b/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CTrayIcon.java Fri Jan 20 08:53:42 2017 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2016, 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
@@ -118,7 +118,10 @@
}
}
- return checkAndCreatePopupPeer().getModel();
+ // This method is executed on Appkit, so if ptr is not zero means that,
+ // it is still not deallocated(even if we call NSApp postRunnableEvent)
+ // and sent CFRelease to the native queue
+ return checkAndCreatePopupPeer().ptr;
}
/**
--- a/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/CMenu.m Fri Jan 20 10:28:34 2017 -0800
+++ b/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/CMenu.m Fri Jan 20 08:53:42 2017 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2016, 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
@@ -38,7 +38,7 @@
- (id)initWithPeer:(jobject)peer {
AWT_ASSERT_APPKIT_THREAD;
// Create the new NSMenu
- self = [super initWithPeer:peer asSeparator:[NSNumber numberWithBool:NO]];
+ self = [super initWithPeer:peer asSeparator:NO];
if (self) {
fMenu = [NSMenu javaMenuWithTitle:@""];
[fMenu retain];
@@ -133,14 +133,13 @@
CMenu * createCMenu (jobject cPeerObjGlobal) {
- CMenu *aCMenu = nil;
+ __block CMenu *aCMenu = nil;
+
+ [ThreadUtilities performOnMainThreadWaiting:YES block:^(){
- // We use an array here only to be able to get a return value
- NSMutableArray *args = [[NSMutableArray alloc] initWithObjects:[NSValue valueWithBytes:&cPeerObjGlobal objCType:@encode(jobject)], nil];
-
- [ThreadUtilities performOnMainThread:@selector(_create_OnAppKitThread:) on:[CMenu alloc] withObject:args waitUntilDone:YES];
-
- aCMenu = (CMenu *)[args objectAtIndex: 0];
+ aCMenu = [[CMenu alloc] initWithPeer:cPeerObjGlobal];
+ // the aCMenu is released in CMenuComponent.dispose()
+ }];
if (aCMenu == nil) {
return 0L;
--- a/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/CMenuBar.m Fri Jan 20 10:28:34 2017 -0800
+++ b/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/CMenuBar.m Fri Jan 20 08:53:42 2017 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2016, 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
@@ -383,27 +383,20 @@
Java_sun_lwawt_macosx_CMenuBar_nativeCreateMenuBar
(JNIEnv *env, jobject peer)
{
- CMenuBar *aCMenuBar = nil;
+ __block CMenuBar *aCMenuBar = nil;
JNF_COCOA_ENTER(env);
jobject cPeerObjGlobal = (*env)->NewGlobalRef(env, peer);
- // We use an array here only to be able to get a return value
- NSMutableArray *args = [[NSMutableArray alloc] initWithObjects:[NSValue valueWithBytes:&cPeerObjGlobal objCType:@encode(jobject)], nil];
+ [ThreadUtilities performOnMainThreadWaiting:YES block:^(){
- [ThreadUtilities performOnMainThread:@selector(_create_OnAppKitThread:) on:[CMenuBar alloc] withObject:args waitUntilDone:YES];
-
- aCMenuBar = (CMenuBar *)[args objectAtIndex: 0];
-
+ aCMenuBar = [[CMenuBar alloc] initWithPeer:cPeerObjGlobal];
+ // the aCMenuBar is released in CMenuComponent.dispose()
+ }];
if (aCMenuBar == nil) {
return 0L;
}
- // [args release];
-
- // A strange memory managment after that.
-
-
JNF_COCOA_EXIT(env);
return ptr_to_jlong(aCMenuBar);
}
--- a/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/CMenuComponent.m Fri Jan 20 10:28:34 2017 -0800
+++ b/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/CMenuComponent.m Fri Jan 20 08:53:42 2017 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2016, 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
@@ -41,45 +41,11 @@
return self;
}
--(void) cleanup {
- // Used by subclasses
-}
-
--(void) disposer {
+- (void)dealloc {
JNIEnv *env = [ThreadUtilities getJNIEnvUncached];
JNFDeleteGlobalRef(env, fPeer);
fPeer = NULL;
- [self cleanup];
- [self release];
+ [super dealloc];
}
-
-// The method is used by all subclasses, since the process of the creation
-// is the same. The only exception is the CMenuItem class.
-- (void) _create_OnAppKitThread: (NSMutableArray *)argValue {
- jobject cPeerObjGlobal = (jobject)[[argValue objectAtIndex: 0] pointerValue];
- CMenuItem *aCMenuItem = [self initWithPeer:cPeerObjGlobal];
- [argValue removeAllObjects];
- [argValue addObject: aCMenuItem];
-}
-
@end
-
-/*
- * Class: sun_lwawt_macosx_CMenuComponent
- * Method: nativeDispose
- * Signature: (J)V
- */
-JNIEXPORT void JNICALL
-Java_sun_lwawt_macosx_CMenuComponent_nativeDispose
-(JNIEnv *env, jobject peer, jlong menuItemObj)
-{
-JNF_COCOA_ENTER(env);
-
- [ThreadUtilities performOnMainThread:@selector(disposer)
- on:((id)jlong_to_ptr(menuItemObj))
- withObject:nil
- waitUntilDone:NO];
-
-JNF_COCOA_EXIT(env);
-}
--- a/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/CMenuItem.h Fri Jan 20 10:28:34 2017 -0800
+++ b/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/CMenuItem.h Fri Jan 20 08:53:42 2017 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2016, 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
@@ -32,7 +32,7 @@
}
// Setup
-- (id) initWithPeer:(jobject)peer asSeparator: (NSNumber *) asSeparator;
+- (id) initWithPeer:(jobject)peer asSeparator: (BOOL) asSeparator;
- (void) setIsCheckbox;
// Events
--- a/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/CMenuItem.m Fri Jan 20 10:28:34 2017 -0800
+++ b/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/CMenuItem.m Fri Jan 20 08:53:42 2017 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2016, 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
@@ -39,11 +39,11 @@
@implementation CMenuItem
-- (id) initWithPeer:(jobject)peer asSeparator: (NSNumber *) asSeparator{
+- (id) initWithPeer:(jobject)peer asSeparator: (BOOL) asSeparator{
AWT_ASSERT_APPKIT_THREAD;
self = [super initWithPeer:peer];
if (self) {
- if ([asSeparator boolValue]) {
+ if (asSeparator) {
fMenuItem = (NSMenuItem*)[NSMenuItem separatorItem];
[fMenuItem retain];
} else {
@@ -204,12 +204,9 @@
}];
}
-- (void)cleanup {
+- (void)dealloc {
[fMenuItem setAction:NULL];
[fMenuItem setTarget:nil];
-}
-
-- (void)dealloc {
[fMenuItem release];
fMenuItem = nil;
@@ -228,14 +225,6 @@
fIsCheckbox = YES;
}
-- (void) _createMenuItem_OnAppKitThread: (NSMutableArray *)argValue {
- jobject cPeerObjGlobal = (jobject)[[argValue objectAtIndex: 0] pointerValue];
- NSNumber * asSeparator = (NSNumber *)[argValue objectAtIndex: 1];
- CMenuItem *aCMenuItem = [self initWithPeer: cPeerObjGlobal asSeparator: asSeparator];
- [argValue removeAllObjects];
- [argValue addObject: aCMenuItem];
-}
-
- (NSString *)description {
return [NSString stringWithFormat:@"CMenuItem[ %@ ]", fMenuItem];
}
@@ -397,24 +386,18 @@
(JNIEnv *env, jobject peer, jlong parentCMenuObj, jboolean isSeparator)
{
- CMenuItem *aCMenuItem = nil;
+ __block CMenuItem *aCMenuItem = nil;
+ BOOL asSeparator = (isSeparator == JNI_TRUE) ? YES: NO;
CMenu *parentCMenu = (CMenu *)jlong_to_ptr(parentCMenuObj);
JNF_COCOA_ENTER(env);
jobject cPeerObjGlobal = (*env)->NewGlobalRef(env, peer);
-
- NSMutableArray *args = nil;
-
- // Create a new item....
- if (isSeparator == JNI_TRUE) {
- args = [[NSMutableArray alloc] initWithObjects:[NSValue valueWithBytes:&cPeerObjGlobal objCType:@encode(jobject)], [NSNumber numberWithBool:YES], nil];
- } else {
- args = [[NSMutableArray alloc] initWithObjects:[NSValue valueWithBytes:&cPeerObjGlobal objCType:@encode(jobject)], [NSNumber numberWithBool:NO], nil];
- }
-
- [ThreadUtilities performOnMainThread:@selector(_createMenuItem_OnAppKitThread:) on:[CMenuItem alloc] withObject:args waitUntilDone:YES];
-
- aCMenuItem = (CMenuItem *)[args objectAtIndex: 0];
+
+ [ThreadUtilities performOnMainThreadWaiting:YES block:^(){
+ aCMenuItem = [[CMenuItem alloc] initWithPeer: cPeerObjGlobal
+ asSeparator: asSeparator];
+ // the CMenuItem is released in CMenuComponent.dispose()
+ }];
if (aCMenuItem == nil) {
return 0L;
--- a/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/png/PNGImageReader.java Fri Jan 20 10:28:34 2017 -0800
+++ b/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/png/PNGImageReader.java Fri Jan 20 08:53:42 2017 -0800
@@ -735,7 +735,11 @@
parse_iCCP_chunk(chunkLength);
break;
case iTXt_TYPE:
- parse_iTXt_chunk(chunkLength);
+ if (ignoreMetadata) {
+ stream.skipBytes(chunkLength);
+ } else {
+ parse_iTXt_chunk(chunkLength);
+ }
break;
case pHYs_TYPE:
parse_pHYs_chunk();
@@ -759,7 +763,11 @@
parse_tRNS_chunk(chunkLength);
break;
case zTXt_TYPE:
- parse_zTXt_chunk(chunkLength);
+ if (ignoreMetadata) {
+ stream.skipBytes(chunkLength);
+ } else {
+ parse_zTXt_chunk(chunkLength);
+ }
break;
default:
// Read an unknown chunk
--- a/jdk/src/java.desktop/windows/native/libawt/windows/awt_Component.cpp Fri Jan 20 10:28:34 2017 -0800
+++ b/jdk/src/java.desktop/windows/native/libawt/windows/awt_Component.cpp Fri Jan 20 08:53:42 2017 -0800
@@ -99,7 +99,6 @@
HWND AwtComponent::sm_focusOwner = NULL;
HWND AwtComponent::sm_focusedWindow = NULL;
BOOL AwtComponent::sm_bMenuLoop = FALSE;
-AwtComponent* AwtComponent::sm_getComponentCache = NULL;
BOOL AwtComponent::sm_inSynthesizeFocus = FALSE;
/************************************************************************/
@@ -276,10 +275,6 @@
* handle.
*/
DestroyHWnd();
-
- if (sm_getComponentCache == this) {
- sm_getComponentCache = NULL;
- }
}
void AwtComponent::Dispose()
@@ -352,9 +347,6 @@
if (hWnd == AwtToolkit::GetInstance().GetHWnd()) {
return NULL;
}
- if (sm_getComponentCache && sm_getComponentCache->GetHWnd() == hWnd) {
- return sm_getComponentCache;
- }
// check that it's an AWT component from the same toolkit as the caller
if (::IsWindow(hWnd) &&
@@ -362,7 +354,7 @@
{
DASSERT(WmAwtIsComponent != 0);
if (::SendMessage(hWnd, WmAwtIsComponent, 0, 0L)) {
- return sm_getComponentCache = GetComponentImpl(hWnd);
+ return GetComponentImpl(hWnd);
}
}
return NULL;
--- a/jdk/src/java.logging/share/classes/java/util/logging/Level.java Fri Jan 20 10:28:34 2017 -0800
+++ b/jdk/src/java.logging/share/classes/java/util/logging/Level.java Fri Jan 20 08:53:42 2017 -0800
@@ -692,11 +692,14 @@
Level levelObject = ref.get();
if (levelObject == null) continue;
Level other = ref.mirroredLevel;
+ Class<? extends Level> type = levelObject.getClass();
if (l.value == other.value &&
(l.resourceBundleName == other.resourceBundleName ||
(l.resourceBundleName != null &&
l.resourceBundleName.equals(other.resourceBundleName)))) {
- return Optional.of(levelObject);
+ if (type == l.getClass()) {
+ return Optional.of(levelObject);
+ }
}
}
}
--- a/jdk/src/java.logging/share/classes/java/util/logging/LogRecord.java Fri Jan 20 10:28:34 2017 -0800
+++ b/jdk/src/java.logging/share/classes/java/util/logging/LogRecord.java Fri Jan 20 08:53:42 2017 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2015, 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
@@ -619,13 +619,21 @@
throw new IOException("LogRecord: bad version: " + major + "." + minor);
}
int len = in.readInt();
- if (len == -1) {
+ if (len < -1) {
+ throw new NegativeArraySizeException();
+ } else if (len == -1) {
parameters = null;
- } else {
+ } else if (len < 255) {
parameters = new Object[len];
for (int i = 0; i < parameters.length; i++) {
parameters[i] = in.readObject();
}
+ } else {
+ List<Object> params = new ArrayList<>(Math.min(len, 1024));
+ for (int i = 0; i < len; i++) {
+ params.add(in.readObject());
+ }
+ parameters = params.toArray(new Object[params.size()]);
}
// If necessary, try to regenerate the resource bundle.
if (resourceBundleName != null) {
--- a/jdk/src/java.management/share/classes/javax/management/remote/rmi/RMIConnectionImpl.java Fri Jan 20 10:28:34 2017 -0800
+++ b/jdk/src/java.management/share/classes/javax/management/remote/rmi/RMIConnectionImpl.java Fri Jan 20 08:53:42 2017 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2002, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2016, 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
@@ -347,7 +347,7 @@
+", unwrapping parameters using classLoaderWithRepository.");
values =
- nullIsEmpty(unwrap(params, classLoaderWithRepository, Object[].class));
+ nullIsEmpty(unwrap(params, classLoaderWithRepository, Object[].class,delegationSubject));
try {
final Object params2[] =
@@ -411,7 +411,7 @@
values = nullIsEmpty(unwrap(params,
getClassLoader(loaderName),
defaultClassLoader,
- Object[].class));
+ Object[].class,delegationSubject));
try {
final Object params2[] =
@@ -522,7 +522,7 @@
"connectionId=" + connectionId
+" unwrapping query with defaultClassLoader.");
- queryValue = unwrap(query, defaultContextClassLoader, QueryExp.class);
+ queryValue = unwrap(query, defaultContextClassLoader, QueryExp.class, delegationSubject);
try {
final Object params[] = new Object[] { name, queryValue };
@@ -557,7 +557,7 @@
"connectionId=" + connectionId
+" unwrapping query with defaultClassLoader.");
- queryValue = unwrap(query, defaultContextClassLoader, QueryExp.class);
+ queryValue = unwrap(query, defaultContextClassLoader, QueryExp.class, delegationSubject);
try {
final Object params[] = new Object[] { name, queryValue };
@@ -707,7 +707,7 @@
attr = unwrap(attribute,
getClassLoaderFor(name),
defaultClassLoader,
- Attribute.class);
+ Attribute.class, delegationSubject);
try {
final Object params[] = new Object[] { name, attr };
@@ -758,7 +758,7 @@
unwrap(attributes,
getClassLoaderFor(name),
defaultClassLoader,
- AttributeList.class);
+ AttributeList.class, delegationSubject);
try {
final Object params[] = new Object[] { name, attrlist };
@@ -810,7 +810,7 @@
values = nullIsEmpty(unwrap(params,
getClassLoaderFor(name),
defaultClassLoader,
- Object[].class));
+ Object[].class, delegationSubject));
try {
final Object params2[] =
@@ -990,7 +990,7 @@
filterValues[i] =
unwrap(filters[i], targetCl, defaultClassLoader,
- NotificationFilter.class);
+ NotificationFilter.class, sbjs[i]);
if (debug) logger.debug("addNotificationListener"+
"(ObjectName,NotificationFilter)",
@@ -1058,7 +1058,7 @@
+" unwrapping filter with target extended ClassLoader.");
filterValue =
- unwrap(filter, targetCl, defaultClassLoader, NotificationFilter.class);
+ unwrap(filter, targetCl, defaultClassLoader, NotificationFilter.class, delegationSubject);
if (debug) logger.debug("addNotificationListener"+
"(ObjectName,ObjectName,NotificationFilter,Object)",
@@ -1066,7 +1066,7 @@
+" unwrapping handback with target extended ClassLoader.");
handbackValue =
- unwrap(handback, targetCl, defaultClassLoader, Object.class);
+ unwrap(handback, targetCl, defaultClassLoader, Object.class, delegationSubject);
try {
final Object params[] =
@@ -1197,7 +1197,7 @@
+" unwrapping filter with target extended ClassLoader.");
filterValue =
- unwrap(filter, targetCl, defaultClassLoader, NotificationFilter.class);
+ unwrap(filter, targetCl, defaultClassLoader, NotificationFilter.class, delegationSubject);
if (debug) logger.debug("removeNotificationListener"+
"(ObjectName,ObjectName,NotificationFilter,Object)",
@@ -1205,7 +1205,7 @@
+" unwrapping handback with target extended ClassLoader.");
handbackValue =
- unwrap(handback, targetCl, defaultClassLoader, Object.class);
+ unwrap(handback, targetCl, defaultClassLoader, Object.class, delegationSubject);
try {
final Object params[] =
@@ -1549,20 +1549,38 @@
}
}
- private static <T> T unwrap(final MarshalledObject<?> mo,
+ private <T> T unwrap(final MarshalledObject<?> mo,
final ClassLoader cl,
- final Class<T> wrappedClass)
+ final Class<T> wrappedClass,
+ Subject delegationSubject)
throws IOException {
if (mo == null) {
return null;
}
try {
final ClassLoader old = AccessController.doPrivileged(new SetCcl(cl));
- try {
- return wrappedClass.cast(mo.get());
- } catch (ClassNotFoundException cnfe) {
- throw new UnmarshalException(cnfe.toString(), cnfe);
- } finally {
+ try{
+ final AccessControlContext reqACC;
+ if (delegationSubject == null)
+ reqACC = acc;
+ else {
+ if (subject == null) {
+ final String msg =
+ "Subject delegation cannot be enabled unless " +
+ "an authenticated subject is put in place";
+ throw new SecurityException(msg);
+ }
+ reqACC = subjectDelegator.delegatedContext(
+ acc, delegationSubject, removeCallerContext);
+ }
+ if(reqACC != null){
+ return AccessController.doPrivileged(
+ (PrivilegedExceptionAction<T>) () ->
+ wrappedClass.cast(mo.get()), reqACC);
+ }else{
+ return wrappedClass.cast(mo.get());
+ }
+ }finally{
AccessController.doPrivileged(new SetCcl(old));
}
} catch (PrivilegedActionException pe) {
@@ -1575,14 +1593,19 @@
}
logger.warning("unwrap", "Failed to unmarshall object: " + e);
logger.debug("unwrap", e);
+ }catch (ClassNotFoundException ex) {
+ logger.warning("unwrap", "Failed to unmarshall object: " + ex);
+ logger.debug("unwrap", ex);
+ throw new UnmarshalException(ex.toString(), ex);
}
return null;
}
- private static <T> T unwrap(final MarshalledObject<?> mo,
+ private <T> T unwrap(final MarshalledObject<?> mo,
final ClassLoader cl1,
final ClassLoader cl2,
- final Class<T> wrappedClass)
+ final Class<T> wrappedClass,
+ Subject delegationSubject)
throws IOException {
if (mo == null) {
return null;
@@ -1596,7 +1619,7 @@
}
}
);
- return unwrap(mo, orderCL, wrappedClass);
+ return unwrap(mo, orderCL, wrappedClass,delegationSubject);
} catch (PrivilegedActionException pe) {
Exception e = extractException(pe);
if (e instanceof IOException) {
--- a/jdk/src/java.rmi/share/classes/java/rmi/MarshalledObject.java Fri Jan 20 10:28:34 2017 -0800
+++ b/jdk/src/java.rmi/share/classes/java/rmi/MarshalledObject.java Fri Jan 20 08:53:42 2017 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2016, 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
@@ -29,11 +29,15 @@
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
+import java.io.ObjectInputFilter;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.ObjectStreamConstants;
import java.io.OutputStream;
import java.io.Serializable;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+
import sun.rmi.server.MarshalInputStream;
import sun.rmi.server.MarshalOutputStream;
@@ -90,6 +94,9 @@
*/
private int hash;
+ /** Filter used when creating the instance from a stream; may be null. */
+ private transient ObjectInputFilter objectInputFilter = null;
+
/** Indicate compatibility with 1.2 version of class. */
private static final long serialVersionUID = 8988374069173025854L;
@@ -133,9 +140,25 @@
}
/**
+ * Reads in the state of the object and saves the stream's
+ * serialization filter to be used when the object is deserialized.
+ *
+ * @param stream the stream
+ * @throws IOException if an I/O error occurs
+ * @throws ClassNotFoundException if a class cannot be found
+ */
+ private void readObject(ObjectInputStream stream)
+ throws IOException, ClassNotFoundException {
+ stream.defaultReadObject(); // read in all fields
+ objectInputFilter = stream.getObjectInputFilter();
+ }
+
+ /**
* Returns a new copy of the contained marshalledobject. The internal
* representation is deserialized with the semantics used for
* unmarshaling parameters for RMI calls.
+ * If the MarshalledObject was read from an ObjectInputStream,
+ * the filter from that stream is used to deserialize the object.
*
* @return a copy of the contained object
* @exception IOException if an <code>IOException</code> occurs while
@@ -155,7 +178,7 @@
ByteArrayInputStream lin =
(locBytes == null ? null : new ByteArrayInputStream(locBytes));
MarshalledObjectInputStream in =
- new MarshalledObjectInputStream(bin, lin);
+ new MarshalledObjectInputStream(bin, lin, objectInputFilter);
@SuppressWarnings("unchecked")
T obj = (T) in.readObject();
in.close();
@@ -295,11 +318,21 @@
* <code>null</code>, then all annotations will be
* <code>null</code>.
*/
- MarshalledObjectInputStream(InputStream objIn, InputStream locIn)
+ MarshalledObjectInputStream(InputStream objIn, InputStream locIn,
+ ObjectInputFilter filter)
throws IOException
{
super(objIn);
this.locIn = (locIn == null ? null : new ObjectInputStream(locIn));
+ if (filter != null) {
+ AccessController.doPrivileged((PrivilegedAction<Void>) () -> {
+ MarshalledObjectInputStream.this.setObjectInputFilter(filter);
+ if (MarshalledObjectInputStream.this.locIn != null) {
+ MarshalledObjectInputStream.this.locIn.setObjectInputFilter(filter);
+ }
+ return null;
+ });
+ }
}
/**
--- a/jdk/src/java.rmi/share/classes/sun/rmi/registry/RegistryImpl.java Fri Jan 20 10:28:34 2017 -0800
+++ b/jdk/src/java.rmi/share/classes/sun/rmi/registry/RegistryImpl.java Fri Jan 20 08:53:42 2017 -0800
@@ -25,8 +25,12 @@
package sun.rmi.registry;
+import java.io.ObjectInputFilter;
import java.nio.file.Path;
import java.nio.file.Paths;
+import java.rmi.server.LogStream;
+import java.security.PrivilegedAction;
+import java.security.Security;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.Hashtable;
@@ -39,7 +43,6 @@
import java.net.*;
import java.rmi.*;
import java.rmi.server.ObjID;
-import java.rmi.server.RemoteServer;
import java.rmi.server.ServerNotActiveException;
import java.rmi.registry.Registry;
import java.rmi.server.RMIClientSocketFactory;
@@ -54,12 +57,12 @@
import java.security.Permissions;
import java.security.ProtectionDomain;
import java.text.MessageFormat;
-import sun.rmi.server.LoaderHandler;
+
+import sun.rmi.runtime.Log;
+import sun.rmi.server.UnicastRef;
import sun.rmi.server.UnicastServerRef;
import sun.rmi.server.UnicastServerRef2;
import sun.rmi.transport.LiveRef;
-import sun.rmi.transport.ObjectTable;
-import sun.rmi.transport.Target;
/**
* A "registry" exists on every node that allows RMI connections to
@@ -91,6 +94,48 @@
private static ResourceBundle resources = null;
/**
+ * Property name of the RMI Registry serial filter to augment
+ * the built-in list of allowed types.
+ * Setting the property in the {@code conf/security/java.security} file
+ * will enable the augmented filter.
+ */
+ private static final String REGISTRY_FILTER_PROPNAME = "sun.rmi.registry.registryFilter";
+
+ /** Registry max depth of remote invocations. **/
+ private static int REGISTRY_MAX_DEPTH = 5;
+
+ /** Registry maximum array size in remote invocations. **/
+ private static int REGISTRY_MAX_ARRAY_SIZE = 10000;
+
+ /**
+ * The registryFilter created from the value of the {@code "sun.rmi.registry.registryFilter"}
+ * property.
+ */
+ private static final ObjectInputFilter registryFilter =
+ AccessController.doPrivileged((PrivilegedAction<ObjectInputFilter>)RegistryImpl::initRegistryFilter);
+
+ /**
+ * Initialize the registryFilter from the security properties or system property; if any
+ * @return an ObjectInputFilter, or null
+ */
+ @SuppressWarnings("deprecation")
+ private static ObjectInputFilter initRegistryFilter() {
+ ObjectInputFilter filter = null;
+ String props = System.getProperty(REGISTRY_FILTER_PROPNAME);
+ if (props == null) {
+ props = Security.getProperty(REGISTRY_FILTER_PROPNAME);
+ }
+ if (props != null) {
+ filter = ObjectInputFilter.Config.createFilter(props);
+ Log regLog = Log.getLog("sun.rmi.registry", "registry", -1);
+ if (regLog.isLoggable(Log.BRIEF)) {
+ regLog.log(Log.BRIEF, "registryFilter = " + filter);
+ }
+ }
+ return filter;
+ }
+
+ /**
* Construct a new RegistryImpl on the specified port with the
* given custom socket factory pair.
*/
@@ -105,7 +150,7 @@
AccessController.doPrivileged(new PrivilegedExceptionAction<Void>() {
public Void run() throws RemoteException {
LiveRef lref = new LiveRef(id, port, csf, ssf);
- setup(new UnicastServerRef2(lref));
+ setup(new UnicastServerRef2(lref, RegistryImpl::registryFilter));
return null;
}
}, null, new SocketPermission("localhost:"+port, "listen,accept"));
@@ -114,7 +159,7 @@
}
} else {
LiveRef lref = new LiveRef(id, port, csf, ssf);
- setup(new UnicastServerRef2(lref));
+ setup(new UnicastServerRef2(lref, RegistryImpl::registryFilter));
}
}
@@ -130,7 +175,7 @@
AccessController.doPrivileged(new PrivilegedExceptionAction<Void>() {
public Void run() throws RemoteException {
LiveRef lref = new LiveRef(id, port);
- setup(new UnicastServerRef(lref));
+ setup(new UnicastServerRef(lref, RegistryImpl::registryFilter));
return null;
}
}, null, new SocketPermission("localhost:"+port, "listen,accept"));
@@ -139,7 +184,7 @@
}
} else {
LiveRef lref = new LiveRef(id, port);
- setup(new UnicastServerRef(lref));
+ setup(new UnicastServerRef(lref, RegistryImpl::registryFilter));
}
}
@@ -362,6 +407,60 @@
}
/**
+ * ObjectInputFilter to filter Registry input objects.
+ * The list of acceptable classes is limited to classes normally
+ * stored in a registry.
+ *
+ * @param filterInfo access to the class, array length, etc.
+ * @return {@link ObjectInputFilter.Status#ALLOWED} if allowed,
+ * {@link ObjectInputFilter.Status#REJECTED} if rejected,
+ * otherwise {@link ObjectInputFilter.Status#UNDECIDED}
+ */
+ private static ObjectInputFilter.Status registryFilter(ObjectInputFilter.FilterInfo filterInfo) {
+ if (registryFilter != null) {
+ ObjectInputFilter.Status status = registryFilter.checkInput(filterInfo);
+ if (status != ObjectInputFilter.Status.UNDECIDED) {
+ // The Registry filter can override the built-in white-list
+ return status;
+ }
+ }
+
+ if (filterInfo.depth() > REGISTRY_MAX_DEPTH) {
+ return ObjectInputFilter.Status.REJECTED;
+ }
+ Class<?> clazz = filterInfo.serialClass();
+ if (clazz != null) {
+ if (clazz.isArray()) {
+ if (filterInfo.arrayLength() >= 0 && filterInfo.arrayLength() > REGISTRY_MAX_ARRAY_SIZE) {
+ return ObjectInputFilter.Status.REJECTED;
+ }
+ do {
+ // Arrays are allowed depending on the component type
+ clazz = clazz.getComponentType();
+ } while (clazz.isArray());
+ }
+ if (clazz.isPrimitive()) {
+ // Arrays of primitives are allowed
+ return ObjectInputFilter.Status.ALLOWED;
+ }
+ if (String.class == clazz
+ || java.lang.Number.class.isAssignableFrom(clazz)
+ || Remote.class.isAssignableFrom(clazz)
+ || java.lang.reflect.Proxy.class.isAssignableFrom(clazz)
+ || UnicastRef.class.isAssignableFrom(clazz)
+ || RMIClientSocketFactory.class.isAssignableFrom(clazz)
+ || RMIServerSocketFactory.class.isAssignableFrom(clazz)
+ || java.rmi.activation.ActivationID.class.isAssignableFrom(clazz)
+ || java.rmi.server.UID.class.isAssignableFrom(clazz)) {
+ return ObjectInputFilter.Status.ALLOWED;
+ } else {
+ return ObjectInputFilter.Status.REJECTED;
+ }
+ }
+ return ObjectInputFilter.Status.UNDECIDED;
+ }
+
+ /**
* Return a new RegistryImpl on the requested port and export it to serve
* registry requests. A classloader is initialized from the system property
* "env.class.path" and a security manager is set unless one is already set.
--- a/jdk/src/java.rmi/share/classes/sun/rmi/runtime/Log.java Fri Jan 20 10:28:34 2017 -0800
+++ b/jdk/src/java.rmi/share/classes/sun/rmi/runtime/Log.java Fri Jan 20 08:53:42 2017 -0800
@@ -232,6 +232,11 @@
}
}
+ public String toString() {
+ return logger.toString() + ", level: " + logger.getLevel() +
+ ", name: " + logger.getName();
+ }
+
/**
* Set the output stream associated with the RMI server call
* logger.
--- a/jdk/src/java.rmi/share/classes/sun/rmi/transport/DGCImpl.java Fri Jan 20 10:28:34 2017 -0800
+++ b/jdk/src/java.rmi/share/classes/sun/rmi/transport/DGCImpl.java Fri Jan 20 08:53:42 2017 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2016, 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
@@ -24,6 +24,7 @@
*/
package sun.rmi.transport;
+import java.io.ObjectInputFilter;
import java.net.SocketPermission;
import java.rmi.Remote;
import java.rmi.RemoteException;
@@ -34,11 +35,13 @@
import java.rmi.server.ObjID;
import java.rmi.server.RemoteServer;
import java.rmi.server.ServerNotActiveException;
+import java.rmi.server.UID;
import java.security.AccessControlContext;
import java.security.AccessController;
import java.security.Permissions;
import java.security.PrivilegedAction;
import java.security.ProtectionDomain;
+import java.security.Security;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.HashMap;
@@ -100,6 +103,46 @@
}
/**
+ * Property name of the DGC serial filter to augment
+ * the built-in list of allowed types.
+ * Setting the property in the {@code conf/security/java.security} file
+ * or system property will enable the augmented filter.
+ */
+ private static final String DGC_FILTER_PROPNAME = "sun.rmi.transport.dgcFilter";
+
+ /** Registry max depth of remote invocations. **/
+ private static int DGC_MAX_DEPTH = 5;
+
+ /** Registry maximum array size in remote invocations. **/
+ private static int DGC_MAX_ARRAY_SIZE = 10000;
+
+ /**
+ * The dgcFilter created from the value of the {@code "sun.rmi.transport.dgcFilter"}
+ * property.
+ */
+ private static final ObjectInputFilter dgcFilter =
+ AccessController.doPrivileged((PrivilegedAction<ObjectInputFilter>)DGCImpl::initDgcFilter);
+
+ /**
+ * Initialize the dgcFilter from the security properties or system property; if any
+ * @return an ObjectInputFilter, or null
+ */
+ private static ObjectInputFilter initDgcFilter() {
+ ObjectInputFilter filter = null;
+ String props = System.getProperty(DGC_FILTER_PROPNAME);
+ if (props == null) {
+ props = Security.getProperty(DGC_FILTER_PROPNAME);
+ }
+ if (props != null) {
+ filter = ObjectInputFilter.Config.createFilter(props);
+ if (dgcLog.isLoggable(Log.BRIEF)) {
+ dgcLog.log(Log.BRIEF, "dgcFilter = " + filter);
+ }
+ }
+ return filter;
+ }
+
+ /**
* Construct a new server-side remote object collector at
* a particular port. Disallow construction from outside.
*/
@@ -293,7 +336,8 @@
dgc = new DGCImpl();
ObjID dgcID = new ObjID(ObjID.DGC_ID);
LiveRef ref = new LiveRef(dgcID, 0);
- UnicastServerRef disp = new UnicastServerRef(ref);
+ UnicastServerRef disp = new UnicastServerRef(ref,
+ DGCImpl::checkInput);
Remote stub =
Util.createProxy(DGCImpl.class,
new UnicastRef(ref), true);
@@ -324,6 +368,53 @@
});
}
+ /**
+ * ObjectInputFilter to filter DGC input objects.
+ * The list of acceptable classes is very short and explicit.
+ * The depth and array sizes are limited.
+ *
+ * @param filterInfo access to class, arrayLength, etc.
+ * @return {@link ObjectInputFilter.Status#ALLOWED} if allowed,
+ * {@link ObjectInputFilter.Status#REJECTED} if rejected,
+ * otherwise {@link ObjectInputFilter.Status#UNDECIDED}
+ */
+ private static ObjectInputFilter.Status checkInput(ObjectInputFilter.FilterInfo filterInfo) {
+ if (dgcFilter != null) {
+ ObjectInputFilter.Status status = dgcFilter.checkInput(filterInfo);
+ if (status != ObjectInputFilter.Status.UNDECIDED) {
+ // The DGC filter can override the built-in white-list
+ return status;
+ }
+ }
+
+ if (filterInfo.depth() > DGC_MAX_DEPTH) {
+ return ObjectInputFilter.Status.REJECTED;
+ }
+ Class<?> clazz = filterInfo.serialClass();
+ if (clazz != null) {
+ while (clazz.isArray()) {
+ if (filterInfo.arrayLength() >= 0 && filterInfo.arrayLength() > DGC_MAX_ARRAY_SIZE) {
+ return ObjectInputFilter.Status.REJECTED;
+ }
+ // Arrays are allowed depending on the component type
+ clazz = clazz.getComponentType();
+ }
+ if (clazz.isPrimitive()) {
+ // Arrays of primitives are allowed
+ return ObjectInputFilter.Status.ALLOWED;
+ }
+ return (clazz == ObjID.class ||
+ clazz == UID.class ||
+ clazz == VMID.class ||
+ clazz == Lease.class)
+ ? ObjectInputFilter.Status.ALLOWED
+ : ObjectInputFilter.Status.REJECTED;
+ }
+ // Not a class, not size limited
+ return ObjectInputFilter.Status.UNDECIDED;
+ }
+
+
private static class LeaseInfo {
VMID vmid;
long expiration;
--- a/jdk/src/java.sql.rowset/share/classes/com/sun/rowset/CachedRowSetImpl.java Fri Jan 20 10:28:34 2017 -0800
+++ b/jdk/src/java.sql.rowset/share/classes/com/sun/rowset/CachedRowSetImpl.java Fri Jan 20 08:53:42 2017 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2017, 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
@@ -31,6 +31,9 @@
import java.math.*;
import java.util.*;
import java.text.*;
+import java.security.AccessController;
+import java.security.PrivilegedActionException;
+import java.security.PrivilegedExceptionAction;
import javax.sql.rowset.*;
import javax.sql.rowset.spi.*;
@@ -357,8 +360,16 @@
}
// set the Reader, this maybe overridden latter
- provider =
- SyncFactory.getInstance(DEFAULT_SYNC_PROVIDER);
+ try {
+ provider = AccessController.doPrivileged(new PrivilegedExceptionAction<>() {
+ @Override
+ public SyncProvider run() throws SyncFactoryException {
+ return SyncFactory.getInstance(DEFAULT_SYNC_PROVIDER);
+ }
+ }, null, new RuntimePermission("accessClassInPackage.com.sun.rowset.providers"));
+ } catch (PrivilegedActionException pae) {
+ throw (SyncFactoryException) pae.getException();
+ }
if (!(provider instanceof RIOptimisticProvider)) {
throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.invalidp").toString());
--- a/jdk/src/java.sql/share/classes/java/sql/Timestamp.java Fri Jan 20 10:28:34 2017 -0800
+++ b/jdk/src/java.sql/share/classes/java/sql/Timestamp.java Fri Jan 20 08:53:42 2017 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2017, 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
@@ -259,7 +259,7 @@
/**
* Formats a timestamp in JDBC timestamp escape format.
* {@code yyyy-mm-dd hh:mm:ss.fffffffff},
- * where {@code ffffffffff} indicates nanoseconds.
+ * where {@code fffffffff} indicates nanoseconds.
*
* @return a {@code String} object in
* {@code yyyy-mm-dd hh:mm:ss.fffffffff} format
--- a/jdk/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMSignatureMethod.java Fri Jan 20 10:28:34 2017 -0800
+++ b/jdk/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMSignatureMethod.java Fri Jan 20 08:53:42 2017 -0800
@@ -21,7 +21,7 @@
* under the License.
*/
/*
- * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
*/
/*
* $Id: DOMSignatureMethod.java 1333415 2012-05-03 12:03:51Z coheigea $
@@ -41,6 +41,7 @@
import com.sun.org.apache.xml.internal.security.algorithms.implementations.SignatureECDSA;
import com.sun.org.apache.xml.internal.security.utils.JavaUtils;
import org.jcp.xml.dsig.internal.SignerOutputStream;
+import sun.security.util.KeyUtil;
/**
* DOM-based abstract implementation of SignatureMethod.
@@ -207,6 +208,7 @@
if (!(key instanceof PublicKey)) {
throw new InvalidKeyException("key must be PublicKey");
}
+ checkKeySize(context, key);
if (signature == null) {
Provider p = (Provider)context.getProperty(
"org.jcp.xml.dsig.internal.dom.SignatureProvider");
@@ -234,6 +236,37 @@
return signature.verify(s);
}
+ /**
+ * If secure validation mode is enabled, checks that the key size is
+ * restricted.
+ *
+ * @param context the context
+ * @param key the key to check
+ * @throws XMLSignatureException if the key size is restricted
+ */
+ private static void checkKeySize(XMLCryptoContext context, Key key)
+ throws XMLSignatureException {
+ if (Utils.secureValidation(context)) {
+ int size = KeyUtil.getKeySize(key);
+ if (size == -1) {
+ // key size cannot be determined, so we cannot check against
+ // restrictions. Note that a DSA key w/o params will be
+ // rejected later if the certificate chain is validated.
+ if (log.isLoggable(java.util.logging.Level.FINE)) {
+ log.log(java.util.logging.Level.FINE, "Size for " +
+ key.getAlgorithm() + " key cannot be determined");
+ }
+ return;
+ }
+ if (Policy.restrictKey(key.getAlgorithm(), size)) {
+ throw new XMLSignatureException(key.getAlgorithm() +
+ " keys less than " +
+ Policy.minKeySize(key.getAlgorithm()) + " bits are" +
+ " forbidden when secure validation is enabled");
+ }
+ }
+ }
+
byte[] sign(Key key, SignedInfo si, XMLSignContext context)
throws InvalidKeyException, XMLSignatureException
{
@@ -244,6 +277,7 @@
if (!(key instanceof PrivateKey)) {
throw new InvalidKeyException("key must be PrivateKey");
}
+ checkKeySize(context, key);
if (signature == null) {
Provider p = (Provider)context.getProperty(
"org.jcp.xml.dsig.internal.dom.SignatureProvider");
--- a/jdk/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/Policy.java Fri Jan 20 10:28:34 2017 -0800
+++ b/jdk/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/Policy.java Fri Jan 20 08:53:42 2017 -0800
@@ -31,8 +31,10 @@
import java.security.PrivilegedAction;
import java.security.Security;
import java.util.Collections;
+import java.util.HashMap;
import java.util.HashSet;
import java.util.Locale;
+import java.util.Map;
import java.util.Set;
/**
@@ -46,6 +48,7 @@
private static int maxTrans = Integer.MAX_VALUE;
private static int maxRefs = Integer.MAX_VALUE;
private static Set<String> disallowedRefUriSchemes = new HashSet<>();
+ private static Map<String, Integer> minKeyMap = new HashMap<>();
private static boolean noDuplicateIds = false;
private static boolean noRMLoops = false;
@@ -101,6 +104,13 @@
scheme.toLowerCase(Locale.ROOT));
}
break;
+ case "minKeySize":
+ if (tokens.length != 3) {
+ error(entry);
+ }
+ minKeyMap.put(tokens[1],
+ Integer.parseUnsignedInt(tokens[2]));
+ break;
case "noDuplicateIds":
if (tokens.length != 1) {
error(entry);
@@ -147,6 +157,10 @@
return false;
}
+ public static boolean restrictKey(String type, int size) {
+ return (size < minKeyMap.getOrDefault(type, 0));
+ }
+
public static boolean restrictDuplicateIds() {
return noDuplicateIds;
}
@@ -171,6 +185,10 @@
return Collections.<String>unmodifiableSet(disallowedRefUriSchemes);
}
+ public static int minKeySize(String type) {
+ return minKeyMap.getOrDefault(type, 0);
+ }
+
private static void error(String entry) {
throw new IllegalArgumentException(
"Invalid jdk.xml.dsig.secureValidationPolicy entry: " + entry);
--- a/jdk/src/jdk.crypto.ec/share/classes/sun/security/ec/ECDSASignature.java Fri Jan 20 10:28:34 2017 -0800
+++ b/jdk/src/jdk.crypto.ec/share/classes/sun/security/ec/ECDSASignature.java Fri Jan 20 08:53:42 2017 -0800
@@ -455,18 +455,22 @@
}
// Convert the DER encoding of R and S into a concatenation of R and S
- private byte[] decodeSignature(byte[] signature) throws SignatureException {
+ private byte[] decodeSignature(byte[] sig) throws SignatureException {
try {
- DerInputStream in = new DerInputStream(signature);
+ // Enforce strict DER checking for signatures
+ DerInputStream in = new DerInputStream(sig, 0, sig.length, false);
DerValue[] values = in.getSequence(2);
+
+ // check number of components in the read sequence
+ // and trailing data
+ if ((values.length != 2) || (in.available() != 0)) {
+ throw new IOException("Invalid encoding for signature");
+ }
+
BigInteger r = values[0].getPositiveBigInteger();
BigInteger s = values[1].getPositiveBigInteger();
- // Check for trailing signature data
- if (in.available() != 0) {
- throw new IOException("Incorrect signature length");
- }
// trim leading zeroes
byte[] rBytes = trimZeroes(r.toByteArray());
byte[] sBytes = trimZeroes(s.toByteArray());
@@ -480,7 +484,7 @@
return result;
} catch (Exception e) {
- throw new SignatureException("Could not decode signature", e);
+ throw new SignatureException("Invalid encoding for signature", e);
}
}
--- a/jdk/src/jdk.crypto.ec/share/native/libsunec/impl/ec.c Fri Jan 20 10:28:34 2017 -0800
+++ b/jdk/src/jdk.crypto.ec/share/native/libsunec/impl/ec.c Fri Jan 20 08:53:42 2017 -0800
@@ -34,7 +34,7 @@
* Dr Vipul Gupta <vipul.gupta@sun.com> and
* Douglas Stebila <douglas@stebila.ca>, Sun Microsystems Laboratories
*
- * Last Modified Date from the Original Code: Nov 2016
+ * Last Modified Date from the Original Code: November 2016
*********************************************************************** */
#include "mplogic.h"
@@ -715,6 +715,16 @@
}
/*
+ * Using an equivalent exponent of fixed length (same as n or 1 bit less
+ * than n) to keep the kG timing relatively constant.
+ *
+ * Note that this is an extra step on top of the approach defined in
+ * ANSI X9.62 so as to make a fixed length K.
+ */
+ CHECK_MPI_OK( mp_add(&k, &n, &k) );
+ CHECK_MPI_OK( mp_div_2(&k, &k) );
+
+ /*
** ANSI X9.62, Section 5.3.2, Step 2
**
** Compute kG
--- a/jdk/src/jdk.crypto.token/share/classes/sun/security/pkcs11/P11Signature.java Fri Jan 20 10:28:34 2017 -0800
+++ b/jdk/src/jdk.crypto.token/share/classes/sun/security/pkcs11/P11Signature.java Fri Jan 20 08:53:42 2017 -0800
@@ -740,17 +740,21 @@
}
}
- private static byte[] asn1ToDSA(byte[] signature) throws SignatureException {
+ private static byte[] asn1ToDSA(byte[] sig) throws SignatureException {
try {
- DerInputStream in = new DerInputStream(signature);
+ // Enforce strict DER checking for signatures
+ DerInputStream in = new DerInputStream(sig, 0, sig.length, false);
DerValue[] values = in.getSequence(2);
+
+ // check number of components in the read sequence
+ // and trailing data
+ if ((values.length != 2) || (in.available() != 0)) {
+ throw new IOException("Invalid encoding for signature");
+ }
+
BigInteger r = values[0].getPositiveBigInteger();
BigInteger s = values[1].getPositiveBigInteger();
- // Check for trailing signature data
- if (in.available() != 0) {
- throw new IOException("Incorrect signature length");
- }
byte[] br = toByteArray(r, 20);
byte[] bs = toByteArray(s, 20);
if ((br == null) || (bs == null)) {
@@ -760,21 +764,25 @@
} catch (SignatureException e) {
throw e;
} catch (Exception e) {
- throw new SignatureException("invalid encoding for signature", e);
+ throw new SignatureException("Invalid encoding for signature", e);
}
}
- private byte[] asn1ToECDSA(byte[] signature) throws SignatureException {
+ private byte[] asn1ToECDSA(byte[] sig) throws SignatureException {
try {
- DerInputStream in = new DerInputStream(signature);
+ // Enforce strict DER checking for signatures
+ DerInputStream in = new DerInputStream(sig, 0, sig.length, false);
DerValue[] values = in.getSequence(2);
+
+ // check number of components in the read sequence
+ // and trailing data
+ if ((values.length != 2) || (in.available() != 0)) {
+ throw new IOException("Invalid encoding for signature");
+ }
+
BigInteger r = values[0].getPositiveBigInteger();
BigInteger s = values[1].getPositiveBigInteger();
- // Check for trailing signature data
- if (in.available() != 0) {
- throw new IOException("Incorrect signature length");
- }
// trim leading zeroes
byte[] br = KeyUtil.trimZeroes(r.toByteArray());
byte[] bs = KeyUtil.trimZeroes(s.toByteArray());
@@ -785,7 +793,7 @@
System.arraycopy(bs, 0, res, res.length - bs.length, bs.length);
return res;
} catch (Exception e) {
- throw new SignatureException("invalid encoding for signature", e);
+ throw new SignatureException("Invalid encoding for signature", e);
}
}
--- a/jdk/src/jdk.jartool/share/classes/sun/security/tools/jarsigner/Main.java Fri Jan 20 10:28:34 2017 -0800
+++ b/jdk/src/jdk.jartool/share/classes/sun/security/tools/jarsigner/Main.java Fri Jan 20 08:53:42 2017 -0800
@@ -26,6 +26,8 @@
package sun.security.tools.jarsigner;
import java.io.*;
+import java.security.cert.CertPathValidatorException;
+import java.security.cert.PKIXBuilderParameters;
import java.util.*;
import java.util.zip.*;
import java.util.jar.*;
@@ -40,11 +42,9 @@
import java.net.SocketTimeoutException;
import java.net.URL;
import java.security.cert.CertPath;
-import java.security.cert.CertPathValidator;
import java.security.cert.CertificateExpiredException;
import java.security.cert.CertificateFactory;
import java.security.cert.CertificateNotYetValidException;
-import java.security.cert.PKIXParameters;
import java.security.cert.TrustAnchor;
import java.util.Map.Entry;
@@ -54,6 +54,8 @@
import sun.security.pkcs.SignerInfo;
import sun.security.timestamp.TimestampToken;
import sun.security.tools.KeyStoreUtil;
+import sun.security.validator.Validator;
+import sun.security.validator.ValidatorException;
import sun.security.x509.*;
import sun.security.util.*;
@@ -177,9 +179,7 @@
private boolean seeWeak = false;
- CertificateFactory certificateFactory;
- CertPathValidator validator;
- PKIXParameters pkixParameters;
+ PKIXBuilderParameters pkixParameters;
public void run(String args[]) {
try {
@@ -1623,19 +1623,10 @@
try {
validateCertChain(certs);
} catch (Exception e) {
- if (debug) {
- e.printStackTrace();
- }
- if (e.getCause() != null &&
- (e.getCause() instanceof CertificateExpiredException ||
- e.getCause() instanceof CertificateNotYetValidException)) {
- // No more warning, we alreay have hasExpiredCert or notYetValidCert
- } else {
- chainNotValidated = true;
- chainNotValidatedReason = e;
- sb.append(tab).append(rb.getString(".CertPath.not.validated."))
- .append(e.getLocalizedMessage()).append("]\n"); // TODO
- }
+ chainNotValidated = true;
+ chainNotValidatedReason = e;
+ sb.append(tab).append(rb.getString(".CertPath.not.validated."))
+ .append(e.getLocalizedMessage()).append("]\n"); // TODO
}
if (certs.size() == 1
&& KeyStoreUtil.isSelfSigned((X509Certificate)certs.get(0))) {
@@ -1654,9 +1645,6 @@
}
try {
-
- certificateFactory = CertificateFactory.getInstance("X.509");
- validator = CertPathValidator.getInstance("PKIX");
Set<TrustAnchor> tas = new HashSet<>();
try {
KeyStore caks = KeyStoreUtil.getCacertsKeyStore();
@@ -1732,7 +1720,7 @@
}
} finally {
try {
- pkixParameters = new PKIXParameters(tas);
+ pkixParameters = new PKIXBuilderParameters(tas, null);
pkixParameters.setRevocationEnabled(false);
} catch (InvalidAlgorithmParameterException ex) {
// Only if tas is empty
@@ -1899,17 +1887,8 @@
try {
validateCertChain(Arrays.asList(certChain));
} catch (Exception e) {
- if (debug) {
- e.printStackTrace();
- }
- if (e.getCause() != null &&
- (e.getCause() instanceof CertificateExpiredException ||
- e.getCause() instanceof CertificateNotYetValidException)) {
- // No more warning, we already have hasExpiredCert or notYetValidCert
- } else {
- chainNotValidated = true;
- chainNotValidatedReason = e;
- }
+ chainNotValidated = true;
+ chainNotValidatedReason = e;
}
if (KeyStoreUtil.isSelfSigned(certChain[0])) {
@@ -1966,18 +1945,40 @@
}
void validateCertChain(List<? extends Certificate> certs) throws Exception {
- int cpLen = 0;
- out: for (; cpLen<certs.size(); cpLen++) {
- for (TrustAnchor ta: pkixParameters.getTrustAnchors()) {
- if (ta.getTrustedCert().equals(certs.get(cpLen))) {
- break out;
+ try {
+ Validator.getInstance(Validator.TYPE_PKIX,
+ Validator.VAR_CODE_SIGNING,
+ pkixParameters)
+ .validate(certs.toArray(new X509Certificate[certs.size()]));
+ } catch (Exception e) {
+ if (debug) {
+ e.printStackTrace();
+ }
+ if (e instanceof ValidatorException) {
+ // Throw cause if it's CertPathValidatorException,
+ if (e.getCause() != null &&
+ e.getCause() instanceof CertPathValidatorException) {
+ e = (Exception) e.getCause();
+ Throwable t = e.getCause();
+ if ((t instanceof CertificateExpiredException &&
+ hasExpiredCert) ||
+ (t instanceof CertificateNotYetValidException &&
+ notYetValidCert)) {
+ // we already have hasExpiredCert and notYetValidCert
+ return;
+ }
+ }
+ if (e instanceof ValidatorException) {
+ ValidatorException ve = (ValidatorException)e;
+ if (ve.getErrorType() == ValidatorException.T_EE_EXTENSIONS &&
+ (badKeyUsage || badExtendedKeyUsage || badNetscapeCertType)) {
+ // We already have badKeyUsage, badExtendedKeyUsage
+ // and badNetscapeCertType
+ return;
+ }
}
}
- }
- if (cpLen > 0) {
- CertPath cp = certificateFactory.generateCertPath(
- (cpLen == certs.size())? certs: certs.subList(0, cpLen));
- validator.validate(cp, pkixParameters);
+ throw e;
}
}
--- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/builder/DefaultImageBuilder.java Fri Jan 20 10:28:34 2017 -0800
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/builder/DefaultImageBuilder.java Fri Jan 20 08:53:42 2017 -0800
@@ -162,22 +162,13 @@
});
if (this.targetOsName == null) {
- throw new PluginException("TargetPlatform attribute is missing for java.base module");
+ throw new PluginException("ModuleTarget attribute is missing for java.base module");
}
+ checkResourcePool(files);
+
Path bin = root.resolve(BIN_DIRNAME);
- // check any duplicated resource files
- Map<Path, Set<String>> duplicates = new HashMap<>();
- files.entries()
- .filter(f -> f.type() != ResourcePoolEntry.Type.CLASS_OR_RESOURCE)
- .collect(groupingBy(this::entryToImagePath,
- mapping(ResourcePoolEntry::moduleName, toSet())))
- .entrySet()
- .stream()
- .filter(e -> e.getValue().size() > 1)
- .forEach(e -> duplicates.put(e.getKey(), e.getValue()));
-
// write non-classes resource files to the image
files.entries()
.filter(f -> f.type() != ResourcePoolEntry.Type.CLASS_OR_RESOURCE)
@@ -185,13 +176,8 @@
try {
accept(f);
} catch (FileAlreadyExistsException e) {
- // error for duplicated entries
- Path path = entryToImagePath(f);
- UncheckedIOException x =
- new UncheckedIOException(path + " duplicated in " +
- duplicates.get(path), e);
- x.addSuppressed(e);
- throw x;
+ // Should not happen! Duplicates checking already done!
+ throw new AssertionError("Duplicate entry!", e);
} catch (IOException ioExp) {
throw new UncheckedIOException(ioExp);
}
@@ -242,6 +228,27 @@
}
}
+ private void checkResourcePool(ResourcePool pool) {
+ // For now, only duplicate resources check. Add more checks here (if any)
+ checkDuplicateResources(pool);
+ }
+
+ private void checkDuplicateResources(ResourcePool pool) {
+ // check any duplicated resources
+ Map<Path, Set<String>> duplicates = new HashMap<>();
+ pool.entries()
+ .filter(f -> f.type() != ResourcePoolEntry.Type.CLASS_OR_RESOURCE)
+ .collect(groupingBy(this::entryToImagePath,
+ mapping(ResourcePoolEntry::moduleName, toSet())))
+ .entrySet()
+ .stream()
+ .filter(e -> e.getValue().size() > 1)
+ .forEach(e -> duplicates.put(e.getKey(), e.getValue()));
+ if (!duplicates.isEmpty()) {
+ throw new PluginException("Duplicate resources: " + duplicates);
+ }
+ }
+
/**
* Generates launcher scripts.
*
--- a/jdk/src/jdk.jlink/share/classes/module-info.java Fri Jan 20 10:28:34 2017 -0800
+++ b/jdk/src/jdk.jlink/share/classes/module-info.java Fri Jan 20 08:53:42 2017 -0800
@@ -24,8 +24,6 @@
*/
module jdk.jlink {
- exports jdk.tools.jlink.plugin;
-
requires jdk.internal.opt;
requires jdk.jdeps;
--- a/jdk/src/jdk.naming.rmi/share/classes/com/sun/jndi/rmi/registry/RegistryContext.java Fri Jan 20 10:28:34 2017 -0800
+++ b/jdk/src/jdk.naming.rmi/share/classes/com/sun/jndi/rmi/registry/RegistryContext.java Fri Jan 20 08:53:42 2017 -0800
@@ -32,6 +32,8 @@
import java.rmi.server.*;
import java.rmi.registry.Registry;
import java.rmi.registry.LocateRegistry;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
import javax.naming.*;
import javax.naming.spi.NamingManager;
@@ -52,6 +54,18 @@
private int port;
private static final NameParser nameParser = new AtomicNameParser();
private static final String SOCKET_FACTORY = "com.sun.jndi.rmi.factory.socket";
+ /**
+ * Determines whether classes may be loaded from an arbitrary URL code base.
+ */
+ static final boolean trustURLCodebase;
+ static {
+ // System property to control whether classes may be loaded from an
+ // arbitrary URL codebase
+ PrivilegedAction<String> act = () -> System.getProperty(
+ "com.sun.jndi.rmi.object.trustURLCodebase", "false");
+ String trust = AccessController.doPrivileged(act);
+ trustURLCodebase = "true".equalsIgnoreCase(trust);
+ }
Reference reference = null; // ref used to create this context, if any
@@ -460,6 +474,27 @@
Object obj = (r instanceof RemoteReference)
? ((RemoteReference)r).getReference()
: (Object)r;
+
+ /*
+ * Classes may only be loaded from an arbitrary URL codebase when
+ * the system property com.sun.jndi.rmi.object.trustURLCodebase
+ * has been set to "true".
+ */
+
+ // Use reference if possible
+ Reference ref = null;
+ if (obj instanceof Reference) {
+ ref = (Reference) obj;
+ } else if (obj instanceof Referenceable) {
+ ref = ((Referenceable)(obj)).getReference();
+ }
+
+ if (ref != null && ref.getFactoryClassLocation() != null &&
+ !trustURLCodebase) {
+ throw new ConfigurationException(
+ "The object factory is untrusted. Set the system property" +
+ " 'com.sun.jndi.rmi.object.trustURLCodebase' to 'true'.");
+ }
return NamingManager.getObjectInstance(obj, name, this,
environment);
} catch (NamingException e) {
--- a/jdk/src/jdk.security.auth/share/classes/com/sun/security/auth/module/LdapLoginModule.java Fri Jan 20 10:28:34 2017 -0800
+++ b/jdk/src/jdk.security.auth/share/classes/com/sun/security/auth/module/LdapLoginModule.java Fri Jan 20 08:53:42 2017 -0800
@@ -418,7 +418,6 @@
constraints = new SearchControls();
constraints.setSearchScope(SearchControls.SUBTREE_SCOPE);
constraints.setReturningAttributes(new String[0]); //return no attrs
- constraints.setReturningObjFlag(true); // to get the full DN
}
authzIdentity = (String)options.get(AUTHZ_IDENTITY);
@@ -878,11 +877,7 @@
// (Use the first entry if more than one is returned)
if (results.hasMore()) {
SearchResult entry = results.next();
-
- // %%% - use the SearchResult.getNameInNamespace method
- // available in JDK 1.5 and later.
- // (can remove call to constraints.setReturningObjFlag)
- userDN = ((Context)entry.getObject()).getNameInNamespace();
+ userDN = entry.getNameInNamespace();
if (debug) {
System.out.println("\t\t[LdapLoginModule] found entry: " +
--- a/jdk/src/jdk.zipfs/share/classes/jdk/nio/zipfs/JarFileSystem.java Fri Jan 20 10:28:34 2017 -0800
+++ b/jdk/src/jdk.zipfs/share/classes/jdk/nio/zipfs/JarFileSystem.java Fri Jan 20 08:53:42 2017 -0800
@@ -135,7 +135,7 @@
TreeMap<Integer,IndexNode> map = new TreeMap<>();
IndexNode child = metaInfVersions.child;
while (child != null) {
- Integer key = getVersion(child.name, metaInfVersions.name.length);
+ Integer key = getVersion(child.name, metaInfVersions.name.length + 1);
if (key != null && key <= version) {
map.put(key, child);
}
@@ -149,7 +149,7 @@
*/
private Integer getVersion(byte[] name, int offset) {
try {
- return Integer.parseInt(getString(Arrays.copyOfRange(name, offset, name.length-1)));
+ return Integer.parseInt(getString(Arrays.copyOfRange(name, offset, name.length)));
} catch (NumberFormatException x) {
// ignore this even though it might indicate issues with the JAR structure
return null;
@@ -176,7 +176,7 @@
* returns foo/bar.class
*/
private byte[] getRootName(IndexNode prefix, IndexNode inode) {
- int offset = prefix.name.length - 1;
+ int offset = prefix.name.length;
byte[] fullName = inode.name;
return Arrays.copyOfRange(fullName, offset, fullName.length);
}
--- a/jdk/src/jdk.zipfs/share/classes/jdk/nio/zipfs/ZipCoder.java Fri Jan 20 10:28:34 2017 -0800
+++ b/jdk/src/jdk.zipfs/share/classes/jdk/nio/zipfs/ZipCoder.java Fri Jan 20 08:53:42 2017 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2009, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 2017, 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
@@ -34,21 +34,56 @@
import java.nio.charset.CodingErrorAction;
import java.util.Arrays;
+import static java.nio.charset.StandardCharsets.UTF_8;
+import static java.nio.charset.StandardCharsets.ISO_8859_1;
+
/**
* Utility class for zipfile name and comment decoding and encoding
*
* @author Xueming Shen
*/
-final class ZipCoder {
+class ZipCoder {
+
+ static class UTF8 extends ZipCoder {
+ UTF8() {
+ super(UTF_8);
+ }
+
+ @Override
+ byte[] getBytes(String s) { // fast pass for ascii
+ for (int i = 0; i < s.length(); i++) {
+ if (s.charAt(i) > 0x7f) return super.getBytes(s);
+ }
+ return s.getBytes(ISO_8859_1);
+ }
- String toString(byte[] ba, int length) {
+ @Override
+ String toString(byte[] ba) {
+ for (byte b : ba) {
+ if (b < 0) return super.toString(ba);
+ }
+ return new String(ba, ISO_8859_1);
+ }
+ }
+
+ private static final ZipCoder utf8 = new UTF8();
+
+ public static ZipCoder get(String csn) {
+ Charset cs = Charset.forName(csn);
+ if (cs.name().equals("UTF-8")) {
+ return utf8;
+ }
+ return new ZipCoder(cs);
+ }
+
+ String toString(byte[] ba) {
CharsetDecoder cd = decoder().reset();
- int len = (int)(length * cd.maxCharsPerByte());
- char[] ca = new char[len];
- if (len == 0)
+ int clen = (int)(ba.length * cd.maxCharsPerByte());
+ char[] ca = new char[clen];
+ if (clen == 0)
return new String(ca);
- ByteBuffer bb = ByteBuffer.wrap(ba, 0, length);
+ ByteBuffer bb = ByteBuffer.wrap(ba, 0, ba.length);
CharBuffer cb = CharBuffer.wrap(ca);
CoderResult cr = cd.decode(bb, cb, true);
if (!cr.isUnderflow())
@@ -59,10 +94,6 @@
return new String(ca, 0, cb.position());
}
- String toString(byte[] ba) {
- return toString(ba, ba.length);
- }
-
byte[] getBytes(String s) {
CharsetEncoder ce = encoder().reset();
char[] ca = s.toCharArray();
@@ -84,47 +115,14 @@
return Arrays.copyOf(ba, bb.position());
}
- // assume invoked only if "this" is not utf8
- byte[] getBytesUTF8(String s) {
- if (isutf8)
- return getBytes(s);
- if (utf8 == null)
- utf8 = new ZipCoder(Charset.forName("UTF-8"));
- return utf8.getBytes(s);
- }
-
- String toStringUTF8(byte[] ba, int len) {
- if (isutf8)
- return toString(ba, len);
- if (utf8 == null)
- utf8 = new ZipCoder(Charset.forName("UTF-8"));
- return utf8.toString(ba, len);
- }
-
boolean isUTF8() {
- return isutf8;
+ return cs == UTF_8;
}
private Charset cs;
- private boolean isutf8;
- private ZipCoder utf8;
private ZipCoder(Charset cs) {
this.cs = cs;
- this.isutf8 = cs.name().equals("UTF-8");
- }
-
- static ZipCoder get(Charset charset) {
- return new ZipCoder(charset);
- }
-
- static ZipCoder get(String csn) {
- try {
- return new ZipCoder(Charset.forName(csn));
- } catch (Throwable t) {
- t.printStackTrace();
- }
- return new ZipCoder(Charset.defaultCharset());
}
private final ThreadLocal<CharsetDecoder> decTL = new ThreadLocal<>();
@@ -133,10 +131,10 @@
private CharsetDecoder decoder() {
CharsetDecoder dec = decTL.get();
if (dec == null) {
- dec = cs.newDecoder()
- .onMalformedInput(CodingErrorAction.REPORT)
- .onUnmappableCharacter(CodingErrorAction.REPORT);
- decTL.set(dec);
+ dec = cs.newDecoder()
+ .onMalformedInput(CodingErrorAction.REPORT)
+ .onUnmappableCharacter(CodingErrorAction.REPORT);
+ decTL.set(dec);
}
return dec;
}
@@ -144,10 +142,10 @@
private CharsetEncoder encoder() {
CharsetEncoder enc = encTL.get();
if (enc == null) {
- enc = cs.newEncoder()
- .onMalformedInput(CodingErrorAction.REPORT)
- .onUnmappableCharacter(CodingErrorAction.REPORT);
- encTL.set(enc);
+ enc = cs.newEncoder()
+ .onMalformedInput(CodingErrorAction.REPORT)
+ .onUnmappableCharacter(CodingErrorAction.REPORT);
+ encTL.set(enc);
}
return enc;
}
--- a/jdk/src/jdk.zipfs/share/classes/jdk/nio/zipfs/ZipFileSystem.java Fri Jan 20 10:28:34 2017 -0800
+++ b/jdk/src/jdk.zipfs/share/classes/jdk/nio/zipfs/ZipFileSystem.java Fri Jan 20 08:53:42 2017 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2009, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 2017, 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
@@ -314,8 +314,8 @@
IndexNode inode = getInode(path);
if (inode == null)
return null;
- e = new Entry(inode.name); // pseudo directory
- e.method = METHOD_STORED; // STORED for dir
+ e = new Entry(inode.name, inode.isdir); // pseudo directory
+ e.method = METHOD_STORED; // STORED for dir
e.mtime = e.atime = e.ctime = zfsDefaultTimeStamp;
}
} finally {
@@ -400,7 +400,8 @@
List<Path> list = new ArrayList<>();
IndexNode child = inode.child;
while (child != null) {
- ZipPath zp = new ZipPath(this, child.name);
+ // assume all path from zip file itself is "normalized"
+ ZipPath zp = new ZipPath(this, child.name, true);
if (filter == null || filter.accept(zp))
list.add(zp);
child = child.sibling;
@@ -415,14 +416,14 @@
throws IOException
{
checkWritable();
- dir = toDirectoryPath(dir);
+ // dir = toDirectoryPath(dir);
beginWrite();
try {
ensureOpen();
if (dir.length == 0 || exists(dir)) // root dir, or exiting dir
throw new FileAlreadyExistsException(getString(dir));
checkParents(dir);
- Entry e = new Entry(dir, Entry.NEW);
+ Entry e = new Entry(dir, Entry.NEW, true);
e.method = METHOD_STORED; // STORED for dir
update(e);
} finally {
@@ -463,7 +464,7 @@
} else {
checkParents(dst);
}
- Entry u = new Entry(eSrc, Entry.COPY); // copy eSrc entry
+ Entry u = new Entry(eSrc, Entry.COPY); // copy eSrc entry
u.name(dst); // change name
if (eSrc.type == Entry.NEW || eSrc.type == Entry.FILECH)
{
@@ -533,7 +534,7 @@
if (!hasCreate && !hasCreateNew)
throw new NoSuchFileException(getString(path));
checkParents(path);
- return getOutputStream(new Entry(path, Entry.NEW));
+ return getOutputStream(new Entry(path, Entry.NEW, false));
}
} finally {
endRead();
@@ -887,7 +888,7 @@
int off = getParentOff(path);
if (off <= 1)
return ROOTPATH;
- return Arrays.copyOf(path, off + 1);
+ return Arrays.copyOf(path, off);
}
private static int getParentOff(byte[] path) {
@@ -1075,11 +1076,9 @@
if (pos + CENHDR + nlen > limit) {
zerror("invalid CEN header (bad header size)");
}
- byte[] name = new byte[nlen + 1];
- System.arraycopy(cen, pos + CENHDR, name, 1, nlen);
- name[0] = '/';
- IndexNode inode = new IndexNode(name, pos);
+ IndexNode inode = new IndexNode(cen, pos + CENHDR, nlen, pos);
inodes.put(inode, inode);
+
// skip ext and comment
pos += (CENHDR + nlen + elen + clen);
}
@@ -1112,7 +1111,7 @@
private boolean hasUpdate = false;
// shared key. consumer guarantees the "writeLock" before use it.
- private final IndexNode LOOKUPKEY = IndexNode.keyOf(null);
+ private final IndexNode LOOKUPKEY = new IndexNode(null, -1);
private void updateDelete(IndexNode inode) {
beginWrite();
@@ -1312,16 +1311,7 @@
IndexNode getInode(byte[] path) {
if (path == null)
throw new NullPointerException("path");
- IndexNode key = IndexNode.keyOf(path);
- IndexNode inode = inodes.get(key);
- if (inode == null &&
- (path.length == 0 || path[path.length -1] != '/')) {
- // if does not ends with a slash
- path = Arrays.copyOf(path, path.length + 1);
- path[path.length - 1] = '/';
- inode = inodes.get(key.as(path));
- }
- return inode;
+ return inodes.get(IndexNode.keyOf(path));
}
Entry getEntry(byte[] path) throws IOException {
@@ -1782,8 +1772,11 @@
int hashcode; // node is hashable/hashed by its name
int pos = -1; // position in cen table, -1 menas the
// entry does not exists in zip file
- IndexNode(byte[] name) {
+ boolean isdir;
+
+ IndexNode(byte[] name, boolean isdir) {
name(name);
+ this.isdir = isdir;
this.pos = -1;
}
@@ -1792,8 +1785,28 @@
this.pos = pos;
}
+ // constructor for cenInit()
+ IndexNode(byte[] cen, int noff, int nlen, int pos) {
+ if (cen[noff + nlen - 1] == '/') {
+ isdir = true;
+ nlen--;
+ }
+ name = new byte[nlen + 1];
+ System.arraycopy(cen, pos + CENHDR, name, 1, nlen);
+ name[0] = '/';
+ name(name);
+ this.pos = pos;
+ }
+
+ private static final ThreadLocal<IndexNode> cachedKey = new ThreadLocal<>();
+
final static IndexNode keyOf(byte[] name) { // get a lookup key;
- return new IndexNode(name, -1);
+ IndexNode key = cachedKey.get();
+ if (key == null) {
+ key = new IndexNode(name, -1);
+ cachedKey.set(key);
+ }
+ return key.as(name);
}
final void name(byte[] name) {
@@ -1807,8 +1820,7 @@
}
boolean isDir() {
- return name != null &&
- (name.length == 0 || name[name.length - 1] == '/');
+ return isdir;
}
public boolean equals(Object other) {
@@ -1865,8 +1877,9 @@
Entry() {}
- Entry(byte[] name) {
+ Entry(byte[] name, boolean isdir) {
name(name);
+ this.isdir = isdir;
this.mtime = this.ctime = this.atime = System.currentTimeMillis();
this.crc = 0;
this.size = 0;
@@ -1874,13 +1887,14 @@
this.method = METHOD_DEFLATED;
}
- Entry(byte[] name, int type) {
- this(name);
+ Entry(byte[] name, int type, boolean isdir) {
+ this(name, isdir);
this.type = type;
}
Entry (Entry e, int type) {
name(e.name);
+ this.isdir = e.isdir;
this.version = e.version;
this.ctime = e.ctime;
this.atime = e.atime;
@@ -1902,7 +1916,7 @@
}
Entry (byte[] name, Path file, int type) {
- this(name, type);
+ this(name, type, false);
this.file = file;
this.method = METHOD_STORED;
}
@@ -1948,6 +1962,7 @@
locoff = CENOFF(cen, pos);
pos += CENHDR;
this.name = inode.name;
+ this.isdir = inode.isdir;
this.hashcode = inode.hashcode;
pos += nlen;
@@ -1974,9 +1989,10 @@
int elenEXTT = 0; // extra for Extended Timestamp
boolean foundExtraTime = false; // if time stamp NTFS, EXTT present
- // confirm size/length
+ byte[] zname = isdir ? toDirectoryPath(name) : name;
- int nlen = (name != null) ? name.length - 1 : 0; // name has [0] as "slash"
+ // confirm size/length
+ int nlen = (zname != null) ? zname.length - 1 : 0; // name has [0] as "slash"
int elen = (extra != null) ? extra.length : 0;
int eoff = 0;
int clen = (comment != null) ? comment.length : 0;
@@ -2037,7 +2053,7 @@
writeShort(os, 0); // internal file attributes (unused)
writeInt(os, 0); // external file attributes (unused)
writeInt(os, locoff0); // relative offset of local header
- writeBytes(os, name, 1, nlen);
+ writeBytes(os, zname, 1, nlen);
if (elen64 != 0) {
writeShort(os, EXTID_ZIP64);// Zip64 extra
writeShort(os, elen64 - 4); // size of "this" extra block
@@ -2075,87 +2091,13 @@
}
///////////////////// LOC //////////////////////
- static Entry readLOC(ZipFileSystem zipfs, long pos)
- throws IOException
- {
- return readLOC(zipfs, pos, new byte[1024]);
- }
-
- static Entry readLOC(ZipFileSystem zipfs, long pos, byte[] buf)
- throws IOException
- {
- return new Entry().loc(zipfs, pos, buf);
- }
-
- Entry loc(ZipFileSystem zipfs, long pos, byte[] buf)
- throws IOException
- {
- assert (buf.length >= LOCHDR);
- if (zipfs.readFullyAt(buf, 0, LOCHDR , pos) != LOCHDR)
- throw new ZipException("loc: reading failed");
- if (!locSigAt(buf, 0))
- throw new ZipException("loc: wrong sig ->"
- + Long.toString(getSig(buf, 0), 16));
- //startPos = pos;
- version = LOCVER(buf);
- flag = LOCFLG(buf);
- method = LOCHOW(buf);
- mtime = dosToJavaTime(LOCTIM(buf));
- crc = LOCCRC(buf);
- csize = LOCSIZ(buf);
- size = LOCLEN(buf);
- int nlen = LOCNAM(buf);
- int elen = LOCEXT(buf);
-
- name = new byte[nlen + 1];
- name[0] = '/';
- if (zipfs.readFullyAt(name, 1, nlen, pos + LOCHDR) != nlen) {
- throw new ZipException("loc: name reading failed");
- }
- if (elen > 0) {
- extra = new byte[elen];
- if (zipfs.readFullyAt(extra, 0, elen, pos + LOCHDR + nlen)
- != elen) {
- throw new ZipException("loc: ext reading failed");
- }
- }
- pos += (LOCHDR + nlen + elen);
- if ((flag & FLAG_DATADESCR) != 0) {
- // Data Descriptor
- Entry e = zipfs.getEntry(name); // get the size/csize from cen
- if (e == null)
- throw new ZipException("loc: name not found in cen");
- size = e.size;
- csize = e.csize;
- pos += (method == METHOD_STORED ? size : csize);
- if (size >= ZIP64_MINVAL || csize >= ZIP64_MINVAL)
- pos += 24;
- else
- pos += 16;
- } else {
- if (extra != null &&
- (size == ZIP64_MINVAL || csize == ZIP64_MINVAL)) {
- // zip64 ext: must include both size and csize
- int off = 0;
- while (off + 20 < elen) { // HeaderID+DataSize+Data
- int sz = SH(extra, off + 2);
- if (SH(extra, off) == EXTID_ZIP64 && sz == 16) {
- size = LL(extra, off + 4);
- csize = LL(extra, off + 12);
- break;
- }
- off += (sz + 4);
- }
- }
- pos += (method == METHOD_STORED ? size : csize);
- }
- return this;
- }
int writeLOC(OutputStream os) throws IOException {
writeInt(os, LOCSIG); // LOC header signature
int version = version();
- int nlen = (name != null) ? name.length - 1 : 0; // [0] is slash
+
+ byte[] zname = isdir ? toDirectoryPath(name) : name;
+ int nlen = (zname != null) ? zname.length - 1 : 0; // [0] is slash
int elen = (extra != null) ? extra.length : 0;
boolean foundExtraTime = false; // if extra timestamp present
int eoff = 0;
@@ -2214,7 +2156,7 @@
}
writeShort(os, nlen);
writeShort(os, elen + elen64 + elenNTFS + elenEXTT);
- writeBytes(os, name, 1, nlen);
+ writeBytes(os, zname, 1, nlen);
if (elen64 != 0) {
writeShort(os, EXTID_ZIP64);
writeShort(os, 16);
@@ -2352,16 +2294,17 @@
locPos += locSZ;
continue;
}
+ int end = locPos + locSZ - 4;
int flag = CH(buf, locPos++);
- if ((flag & 0x1) != 0) {
+ if ((flag & 0x1) != 0 && locPos <= end) {
mtime = unixToJavaTime(LG(buf, locPos));
locPos += 4;
}
- if ((flag & 0x2) != 0) {
+ if ((flag & 0x2) != 0 && locPos <= end) {
atime = unixToJavaTime(LG(buf, locPos));
locPos += 4;
}
- if ((flag & 0x4) != 0) {
+ if ((flag & 0x4) != 0 && locPos <= end) {
ctime = unixToJavaTime(LG(buf, locPos));
locPos += 4;
}
@@ -2551,7 +2494,7 @@
private void buildNodeTree() throws IOException {
beginWrite();
try {
- IndexNode root = new IndexNode(ROOTPATH);
+ IndexNode root = new IndexNode(ROOTPATH, true);
IndexNode[] nodes = inodes.keySet().toArray(new IndexNode[0]);
inodes.put(root, root);
ParentLookup lookup = new ParentLookup();
@@ -2564,7 +2507,7 @@
root.child = node;
break;
}
- lookup = lookup.as(node.name, off + 1);
+ lookup = lookup.as(node.name, off);
if (inodes.containsKey(lookup)) {
parent = inodes.get(lookup);
node.sibling = parent.child;
@@ -2572,7 +2515,7 @@
break;
}
// add new pseudo directory entry
- parent = new IndexNode(Arrays.copyOf(node.name, off + 1));
+ parent = new IndexNode(Arrays.copyOf(node.name, off), true);
inodes.put(parent, parent);
node.sibling = parent.child;
parent.child = node;
--- a/jdk/src/jdk.zipfs/share/classes/jdk/nio/zipfs/ZipPath.java Fri Jan 20 10:28:34 2017 -0800
+++ b/jdk/src/jdk.zipfs/share/classes/jdk/nio/zipfs/ZipPath.java Fri Jan 20 08:53:42 2017 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2009, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 2017, 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
@@ -59,8 +59,7 @@
} else {
if (zfs.zc.isUTF8()) {
this.path = normalize(path);
- } else {
- // see normalize(String);
+ } else { // see normalize(String);
this.path = normalize(zfs.getString(path));
}
}
@@ -68,12 +67,7 @@
ZipPath(ZipFileSystem zfs, String path) {
this.zfs = zfs;
- if (zfs.zc.isUTF8()) {
- this.path = normalize(zfs.getBytes(path));
- } else {
- // see normalize(String);
- this.path = normalize(path);
- }
+ this.path = normalize(path);
}
@Override
@@ -84,33 +78,31 @@
return null;
}
- @Override
+ @Override
public Path getFileName() {
- initOffsets();
- int count = offsets.length;
- if (count == 0)
- return null; // no elements so no name
- if (count == 1 && path[0] != '/')
+ int off = path.length;
+ if (off == 0 || off == 1 && path[0] == '/')
+ return null;
+ while (--off >= 0 && path[off] != '/') {}
+ if (off < 0)
return this;
- int lastOffset = offsets[count-1];
- int len = path.length - lastOffset;
- byte[] result = new byte[len];
- System.arraycopy(path, lastOffset, result, 0, len);
- return new ZipPath(zfs, result);
+ off++;
+ byte[] result = new byte[path.length - off];
+ System.arraycopy(path, off, result, 0, result.length);
+ return new ZipPath(getFileSystem(), result, true);
}
@Override
public ZipPath getParent() {
- initOffsets();
- int count = offsets.length;
- if (count == 0) // no elements so no parent
+ int off = path.length;
+ if (off == 0 || off == 1 && path[0] == '/')
return null;
- int len = offsets[count-1] - 1;
- if (len <= 0) // parent is root only (may be null)
+ while (--off >= 0 && path[off] != '/') {}
+ if (off <= 0)
return getRoot();
- byte[] result = new byte[len];
- System.arraycopy(path, 0, result, 0, len);
- return new ZipPath(zfs, result);
+ byte[] result = new byte[off];
+ System.arraycopy(path, 0, result, 0, off);
+ return new ZipPath(getFileSystem(), result, true);
}
@Override
@@ -277,30 +269,36 @@
@Override
public boolean isAbsolute() {
- return (this.path.length > 0 && path[0] == '/');
+ return path.length > 0 && path[0] == '/';
}
@Override
public ZipPath resolve(Path other) {
- final ZipPath o = checkPath(other);
- int tlen = this.path.length;
- if (tlen == 0 || o.isAbsolute())
+ ZipPath o = checkPath(other);
+ if (o.path.length == 0)
+ return this;
+ if (o.isAbsolute() || this.path.length == 0)
return o;
- int olen = o.path.length;
- if (olen == 0)
- return this;
+ return resolve(o.path);
+ }
+
+ // opath is normalized, just concat
+ private ZipPath resolve(byte[] opath) {
byte[] resolved = null;
- if (this.path[tlen - 1] == '/') {
+ byte[] tpath = this.path;
+ int tlen = tpath.length;
+ int olen = opath.length;
+ if (path[tlen - 1] == '/') {
resolved = new byte[tlen + olen];
- System.arraycopy(path, 0, resolved, 0, tlen);
- System.arraycopy(o.path, 0, resolved, tlen, olen);
+ System.arraycopy(tpath, 0, resolved, 0, tlen);
+ System.arraycopy(opath, 0, resolved, tlen, olen);
} else {
resolved = new byte[tlen + 1 + olen];
- System.arraycopy(path, 0, resolved, 0, tlen);
+ System.arraycopy(tpath, 0, resolved, 0, tlen);
resolved[tlen] = '/';
- System.arraycopy(o.path, 0, resolved, tlen + 1, olen);
+ System.arraycopy(opath, 0, resolved, tlen + 1, olen);
}
- return new ZipPath(zfs, resolved);
+ return new ZipPath(zfs, resolved, true);
}
@Override
@@ -351,7 +349,12 @@
@Override
public ZipPath resolve(String other) {
- return resolve(zfs.getPath(other));
+ byte[] opath = normalize(other);
+ if (opath.length == 0)
+ return this;
+ if (opath[0] == '/' || this.path.length == 0)
+ return new ZipPath(zfs, opath, true);
+ return resolve(opath);
}
@Override
@@ -455,8 +458,9 @@
return normalize(path, i - 1);
prevC = c;
}
- if (len > 1 && prevC == '/')
+ if (len > 1 && prevC == '/') {
return Arrays.copyOf(path, len - 1);
+ }
return path;
}
@@ -490,6 +494,8 @@
// to avoid incorrectly normalizing byte '0x5c' (as '\')
// to '/'.
private byte[] normalize(String path) {
+ if (zfs.zc.isUTF8())
+ return normalize(zfs.getBytes(path));
int len = path.length();
if (len == 0)
return new byte[0];
@@ -533,7 +539,8 @@
// Remove DotSlash(./) and resolve DotDot (..) components
private byte[] getResolved() {
for (int i = 0; i < path.length; i++) {
- if (path[i] == (byte)'.') {
+ if (path[i] == (byte)'.' &&
+ (i + 1 == path.length || path[i + 1] == '/')) {
return resolve0();
}
}
@@ -976,5 +983,4 @@
}
return sb.toString();
}
-
}
--- a/jdk/test/ProblemList.txt Fri Jan 20 10:28:34 2017 -0800
+++ b/jdk/test/ProblemList.txt Fri Jan 20 08:53:42 2017 -0800
@@ -258,6 +258,8 @@
tools/jlink/multireleasejar/JLinkMultiReleaseJarTest.java 8169971 windows-x64
+tools/jlink/CustomPluginTest.java 8172864 generic-all
+
############################################################################
# jdk_jdi
--- a/jdk/test/TEST.ROOT Fri Jan 20 10:28:34 2017 -0800
+++ b/jdk/test/TEST.ROOT Fri Jan 20 08:53:42 2017 -0800
@@ -26,8 +26,8 @@
# Allow querying of various System properties in @requires clauses
requires.properties=sun.arch.data.model java.runtime.name
-# Tests using jtreg 4.2 b04 features
-requiredVersion=4.2 b04
+# Tests using jtreg 4.2 b05 features
+requiredVersion=4.2 b05
# Path to libraries in the topmost test directory. This is needed so @library
# does not need ../../ notation to reach them
--- a/jdk/test/com/sun/crypto/provider/Cipher/AES/TestAESCiphers/testAES.policy Fri Jan 20 10:28:34 2017 -0800
+++ b/jdk/test/com/sun/crypto/provider/Cipher/AES/TestAESCiphers/testAES.policy Fri Jan 20 08:53:42 2017 -0800
@@ -1,6 +1,6 @@
-grant
-{
+grant codeBase "file:${test.classes}/*" {
permission java.security.SecurityPermission "removeProvider.SunJCE";
permission java.security.SecurityPermission "insertProvider.SunJCE";
- permission java.security.SecurityPermission "putProviderProperty.SunJCE";
+ permission java.lang.RuntimePermission
+ "accessClassInPackage.com.sun.crypto.provider";
};
--- a/jdk/test/com/sun/security/auth/module/LdapLoginModule/CheckConfigs.policy Fri Jan 20 10:28:34 2017 -0800
+++ b/jdk/test/com/sun/security/auth/module/LdapLoginModule/CheckConfigs.policy Fri Jan 20 08:53:42 2017 -0800
@@ -1,9 +1,9 @@
-
-grant {
+grant codeBase "file:${test.classes}/*" {
// The following permissions are not required because the test is
// not expected to connect to an LDAP server
//
//permission java.net.SocketPermission "*:389", "connect";
//permission java.net.SocketPermission "*:636", "connect";
//permission javax.security.auth.AuthPermission "modifyPrincipals";
+ permission java.lang.RuntimePermission "accessClassInPackage.com.sun.jndi.ldap";
};
--- a/jdk/test/java/lang/SecurityManager/CheckPackageAccess.java Fri Jan 20 10:28:34 2017 -0800
+++ b/jdk/test/java/lang/SecurityManager/CheckPackageAccess.java Fri Jan 20 08:53:42 2017 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2017, 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
@@ -23,87 +23,174 @@
/*
* @test
- * @bug 6741606 7146431 8000450 8019830 8022945 8027144 8041633 8078427
- * @summary Make sure all restricted packages listed in the package.access
+ * @bug 6741606 7146431 8000450 8019830 8022945 8027144 8041633 8078427 8055206
+ * @summary Check that various restricted packages that are supposed to be
+ * restricted by default or are listed in the package.access
* property in the java.security file are blocked
+ * @modules java.xml.ws java.corba
* @run main/othervm CheckPackageAccess
*/
-import java.util.Collections;
-import java.util.ArrayList;
+import java.lang.module.ModuleFinder;
+import java.lang.module.ModuleReference;
+import java.util.Arrays;
import java.util.List;
+import java.util.Optional;
+
+public class CheckPackageAccess {
+
+ private static final SecurityManager sm = new SecurityManager();
+ private static final ModuleFinder mf = ModuleFinder.ofSystem();
+
+ /*
+ * The expected list of restricted packages of the package.access property.
+ *
+ * This array should be updated whenever new packages are added to the
+ * package.access property in the java.security file
+ * NOTE: it should be in the same order as the java.security file
+ */
+ private static final String[] EXPECTED = {
+ "sun.misc.",
+ "sun.reflect.",
+ };
+
+ /**
+ * Tests access to various packages of a module.
+ */
+ private static class Test {
+ String moduleName; // name of module
+ ModuleReference moduleRef; // module reference
+ String exports; // exported pkg
+ Optional<String> opens; // opened pkg
+ String conceals; // concealed pkg
+ Optional<String> qualExports; // qualified export pkg
+ Optional<String> qualOpens; // qualified open pkg
+ // qual open and non-qualified export pkg
+ Optional<String> qualOpensAndExports;
+ Test(String module, String exports, String opens, String conceals,
+ String qualExports, String qualOpens, String qualOpensAndExports) {
+ this.moduleName = module;
+ this.moduleRef = mf.find(moduleName).get();
+ this.exports = exports;
+ this.opens = Optional.ofNullable(opens);
+ this.conceals = conceals;
+ this.qualExports = Optional.ofNullable(qualExports);
+ this.qualOpens = Optional.ofNullable(qualOpens);
+ this.qualOpensAndExports = Optional.ofNullable(qualOpensAndExports);
+ }
+
+ void test() {
+ System.out.println("Testing module " + moduleName);
+
+ // access to exported pkg should pass
+ testNonRestricted(exports);
+
+ // access to opened pkg should pass
+ opens.ifPresent(Test::testNonRestricted);
+
+ // access to concealed pkg should fail
+ testRestricted(conceals);
-/*
- * The main benefit of this test is to catch merge errors or other types
- * of issues where one or more of the packages are accidentally
- * removed. This is why the packages that are known to be restricted have to
- * be explicitly listed below.
- */
-public class CheckPackageAccess {
+ // access to qualified export pkg should fail
+ qualExports.ifPresent(Test::testRestricted);
+
+ // access to qualified open pkg should fail
+ qualOpens.ifPresent(Test::testRestricted);
+
+ // access to qualified opened pkg that is also exported should pass
+ qualOpensAndExports.ifPresent(Test::testNonRestricted);
+ }
+
+ private static void testRestricted(String pkg) {
+ try {
+ sm.checkPackageAccess(pkg);
+ throw new RuntimeException("Able to access restricted package: "
+ + pkg);
+ } catch (SecurityException se) {}
+ try {
+ sm.checkPackageDefinition(pkg);
+ throw new RuntimeException("Able to access restricted package: "
+ + pkg);
+ } catch (SecurityException se) {}
+ }
+
+ private static void testNonRestricted(String pkg) {
+ try {
+ sm.checkPackageAccess(pkg);
+ } catch (SecurityException se) {
+ throw new RuntimeException("Unable to access exported package: "
+ + pkg, se);
+ }
+ try {
+ sm.checkPackageDefinition(pkg);
+ } catch (SecurityException se) {
+ throw new RuntimeException("Unable to access exported package: "
+ + pkg, se);
+ }
+ }
+ }
+
+ private static final Test[] tests = new Test[] {
+ // java.base module loaded by boot loader
+ new Test("java.base", "java.security", null, "jdk.internal.jrtfs",
+ "jdk.internal.loader", null, null),
+ // java.desktop module loaded by boot loader and has an openQual pkg
+ // that is exported
+ new Test("java.desktop", "java.applet", null, "sun.applet",
+ "sun.awt", "com.sun.java.swing.plaf.windows",
+ "javax.swing.plaf.basic"),
+ // java.security.jgss module loaded by platform loader
+ new Test("java.security.jgss", "org.ietf.jgss", null,
+ "sun.security.krb5.internal.crypto", "sun.security.krb5",
+ null, null),
+ // java.xml.ws module loaded by platform loader but needs to be added
+ // and has an openQual pkg that is exported
+ new Test("java.xml.ws", "javax.xml.soap", null,
+ "com.sun.xml.internal.stream.buffer",
+ "com.sun.xml.internal.ws.api", null,
+ "javax.xml.ws.wsaddressing"),
+ // java.xml.ws module loaded by platform loader but needs to be added
+ // and has an openQual pkg
+ new Test("java.corba", "javax.rmi", null, "sun.corba",
+ "com.sun.corba.se.impl.util", "com.sun.jndi.cosnaming", null),
+ };
public static void main(String[] args) throws Exception {
- // get expected list of restricted packages
- List<String> pkgs = RestrictedPackages.expected();
- // get actual list of restricted packages
- List<String> jspkgs = RestrictedPackages.actual();
+ // check expected list of restricted packages in java.security file
+ checkPackages(Arrays.asList(EXPECTED));
- if (!isOpenJDKOnly()) {
- String lastPkg = pkgs.get(pkgs.size() - 1);
-
- // Remove any closed packages from list before comparing
- int index = jspkgs.indexOf(lastPkg);
- if (index != -1 && index != jspkgs.size() - 1) {
- jspkgs.subList(index + 1, jspkgs.size()).clear();
- }
+ // check access to each module's packages
+ for (Test test : tests) {
+ test.test();
}
- // Sort to ensure lists are comparable
- Collections.sort(pkgs);
- Collections.sort(jspkgs);
+ System.out.println("Test passed");
+ }
- if (!pkgs.equals(jspkgs)) {
- for (String p : pkgs)
- if (!jspkgs.contains(p))
- System.out.println("In golden set, but not in j.s file: " + p);
- for (String p : jspkgs)
- if (!pkgs.contains(p))
- System.out.println("In j.s file, but not in golden set: " + p);
-
-
- throw new RuntimeException("restricted packages are not " +
- "consistent with java.security file");
- }
- System.setSecurityManager(new SecurityManager());
- SecurityManager sm = System.getSecurityManager();
+ private static void checkPackages(List<String> pkgs) {
for (String pkg : pkgs) {
- String subpkg = pkg + "foo";
try {
sm.checkPackageAccess(pkg);
throw new RuntimeException("Able to access " + pkg +
" package");
} catch (SecurityException se) { }
try {
- sm.checkPackageAccess(subpkg);
- throw new RuntimeException("Able to access " + subpkg +
- " package");
- } catch (SecurityException se) { }
- try {
sm.checkPackageDefinition(pkg);
throw new RuntimeException("Able to define class in " + pkg +
" package");
} catch (SecurityException se) { }
+ String subpkg = pkg + "foo";
+ try {
+ sm.checkPackageAccess(subpkg);
+ throw new RuntimeException("Able to access " + subpkg +
+ " package");
+ } catch (SecurityException se) { }
try {
sm.checkPackageDefinition(subpkg);
- throw new RuntimeException("Able to define class in " + subpkg +
- " package");
+ throw new RuntimeException("Able to define class in " +
+ subpkg + " package");
} catch (SecurityException se) { }
}
- System.out.println("Test passed");
- }
-
- private static boolean isOpenJDKOnly() {
- String prop = System.getProperty("java.runtime.name");
- return prop != null && prop.startsWith("OpenJDK");
}
}
--- a/jdk/test/java/lang/SecurityManager/CheckPackageMatching.java Fri Jan 20 10:28:34 2017 -0800
+++ b/jdk/test/java/lang/SecurityManager/CheckPackageMatching.java Fri Jan 20 08:53:42 2017 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2017, 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
@@ -28,11 +28,13 @@
* @run main/othervm CheckPackageMatching
*/
+import java.security.Security;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
+import java.util.StringTokenizer;
/*
* The purpose of this test is not to verify the content of the package
@@ -46,10 +48,23 @@
* The restricted packages listed in the package.access property of the
* java.security file.
*/
- private static final String[] packages =
- RestrictedPackages.actual().toArray(new String[0]);
+ private static final String[] packages = actual().toArray(new String[0]);
- private static final boolean OPEN_JDK = isOpenJDKOnly();
+ /**
+ * Returns the list of restricted packages in the package.access property.
+ */
+ private static List<String> actual() {
+ String prop = Security.getProperty("package.access");
+ List<String> packages = new ArrayList<>();
+ if (prop != null && !prop.equals("")) {
+ StringTokenizer tok = new StringTokenizer(prop, ",");
+ while (tok.hasMoreElements()) {
+ String s = tok.nextToken().trim();
+ packages.add(s);
+ }
+ }
+ return packages;
+ }
/**
* PackageMatcher implements a state machine that matches package
@@ -326,13 +341,8 @@
System.getSecurityManager().checkPackageAccess("com.sun.jmxa");
System.getSecurityManager().checkPackageAccess("jmx");
List<String> actual = Arrays.asList(packages);
- for (String p : actual) {
- if (!actual.contains(p)) {
- System.err.println("Warning: '" + p + " not in package.access");
- }
- }
- if (!actual.contains("sun.")) {
- throw new Error("package.access does not contain 'sun.'");
+ if (!actual.contains("sun.misc.")) {
+ throw new Error("package.access does not contain 'sun.misc.'");
}
}
@@ -447,17 +457,15 @@
// These should not match.
for (String pkg : new String[] {"gloups.machin", "su",
- "org.jcp.xml.dsig.interna",
+ "org.jcp.xml.dsig.inter",
"com.sun.jm", "com.sun.jmxa"}) {
testMatch(matcher, pkg, false, true);
}
// These should match.
for (String pkg : Arrays.asList(
- new String[] {"sun.gloups.machin", "sun", "sun.com",
- "com.sun.jmx", "com.sun.jmx.a",
- "org.jcp.xml.dsig.internal",
- "org.jcp.xml.dsig.internal.foo"})) {
+ new String[] {"sun.misc.gloups.machin", "sun.misc",
+ "sun.reflect"})) {
testMatch(matcher, pkg, true, true);
}
@@ -486,12 +494,6 @@
}
for (String pkg : pkgs) {
- if (!OPEN_JDK && pkg.equals("com.sun.media.sound.")) {
- // don't test com.sun.media.sound since there is an entry
- // for com.sun.media in non OpenJDK builds. Otherwise,
- // the test for this package will fail unexpectedly.
- continue;
- }
String candidate = pkg.substring(0, pkg.length() - 2);
boolean expected = pkglist.contains(candidate + ".");
testMatch(matcher, candidate, expected,
@@ -537,9 +539,4 @@
}
}
}
-
- private static boolean isOpenJDKOnly() {
- String prop = System.getProperty("java.runtime.name");
- return prop != null && prop.startsWith("OpenJDK");
- }
}
--- a/jdk/test/java/lang/SecurityManager/RestrictedPackages.java Fri Jan 20 10:28:34 2017 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,155 +0,0 @@
-/*
- * Copyright (c) 2015, 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.
- */
-
-import java.security.Security;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-import java.util.StringTokenizer;
-
-/**
- * A collection of utility methods and constants for testing the package
- * access and package definition security checks.
- */
-final class RestrictedPackages {
-
- /*
- * The expected list of restricted packages.
- *
- * This array should be updated whenever new packages are added to the
- * package.access property in the java.security file
- * NOTE: it should be in the same order as the java.security file
- */
- static final String[] EXPECTED = {
- "sun.",
- "com.sun.xml.internal.",
- "com.sun.imageio.",
- "com.sun.istack.internal.",
- "com.sun.jmx.",
- "com.sun.media.sound.",
- "com.sun.naming.internal.",
- "com.sun.proxy.",
- "com.sun.corba.se.",
- "com.sun.org.apache.bcel.internal.",
- "com.sun.org.apache.regexp.internal.",
- "com.sun.org.apache.xerces.internal.",
- "com.sun.org.apache.xpath.internal.",
- "com.sun.org.apache.xalan.internal.extensions.",
- "com.sun.org.apache.xalan.internal.lib.",
- "com.sun.org.apache.xalan.internal.res.",
- "com.sun.org.apache.xalan.internal.templates.",
- "com.sun.org.apache.xalan.internal.utils.",
- "com.sun.org.apache.xalan.internal.xslt.",
- "com.sun.org.apache.xalan.internal.xsltc.cmdline.",
- "com.sun.org.apache.xalan.internal.xsltc.compiler.",
- "com.sun.org.apache.xalan.internal.xsltc.trax.",
- "com.sun.org.apache.xalan.internal.xsltc.util.",
- "com.sun.org.apache.xml.internal.res.",
- "com.sun.org.apache.xml.internal.security.",
- "com.sun.org.apache.xml.internal.serializer.dom3.",
- "com.sun.org.apache.xml.internal.serializer.utils.",
- "com.sun.org.apache.xml.internal.utils.",
- "com.sun.org.glassfish.",
- "com.sun.tools.script.",
- "com.oracle.xmlns.internal.",
- "com.oracle.webservices.internal.",
- "org.jcp.xml.dsig.internal.",
- "jdk.internal.",
- "jdk.nashorn.internal.",
- "jdk.nashorn.tools.",
- "jdk.tools.jimage.",
- "com.sun.activation.registries.",
- "com.sun.java.accessibility.util.internal."
- };
-
- /*
- * A non-exhaustive list of restricted packages.
- *
- * Contrary to what is in the EXPECTED list, this list does not need
- * to be exhaustive.
- */
- static final String[] EXPECTED_NONEXHAUSTIVE = {
- "sun.",
- "com.sun.xml.internal.",
- "com.sun.imageio.",
- "com.sun.istack.internal.",
- "com.sun.jmx.",
- "com.sun.proxy.",
- "com.sun.org.apache.bcel.internal.",
- "com.sun.org.apache.regexp.internal.",
- "com.sun.org.apache.xerces.internal.",
- "com.sun.org.apache.xpath.internal.",
- "com.sun.org.apache.xalan.internal.extensions.",
- "com.sun.org.apache.xalan.internal.lib.",
- "com.sun.org.apache.xalan.internal.res.",
- "com.sun.org.apache.xalan.internal.templates.",
- "com.sun.org.apache.xalan.internal.utils.",
- "com.sun.org.apache.xalan.internal.xslt.",
- "com.sun.org.apache.xalan.internal.xsltc.cmdline.",
- "com.sun.org.apache.xalan.internal.xsltc.compiler.",
- "com.sun.org.apache.xalan.internal.xsltc.trax.",
- "com.sun.org.apache.xalan.internal.xsltc.util.",
- "com.sun.org.apache.xml.internal.res.",
- "com.sun.org.apache.xml.internal.serializer.utils.",
- "com.sun.org.apache.xml.internal.utils.",
- "com.sun.org.apache.xml.internal.security.",
- "com.sun.org.glassfish.",
- "org.jcp.xml.dsig.internal."
- };
-
- private static final String OS_NAME = System.getProperty("os.name");
-
- /**
- * Returns a list of expected restricted packages, including any
- * OS specific packages. The returned list is mutable.
- */
- static List<String> expected() {
- List<String> pkgs = new ArrayList<>(Arrays.asList(EXPECTED));
- if (OS_NAME.contains("OS X")) {
- pkgs.add("apple."); // add apple package for OS X
- }
- if (OS_NAME.contains("Win")) {
- pkgs.add("com.sun.java.accessibility.internal."); // add Win only package
- }
- return pkgs;
- }
-
- /**
- * Returns a list of actual restricted packages. The returned list
- * is mutable.
- */
- static List<String> actual() {
- String prop = Security.getProperty("package.access");
- List<String> packages = new ArrayList<>();
- if (prop != null && !prop.equals("")) {
- StringTokenizer tok = new StringTokenizer(prop, ",");
- while (tok.hasMoreElements()) {
- String s = tok.nextToken().trim();
- packages.add(s);
- }
- }
- return packages;
- }
-
- private RestrictedPackages() { }
-}
--- a/jdk/test/java/lang/invoke/lambda/LogGeneratedClassesTest.java Fri Jan 20 10:28:34 2017 -0800
+++ b/jdk/test/java/lang/invoke/lambda/LogGeneratedClassesTest.java Fri Jan 20 08:53:42 2017 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2017, 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
@@ -63,6 +63,7 @@
scratch.add(" int foo();");
scratch.add(" }");
scratch.add(" public static void main(String[] args) {");
+ scratch.add(" System.setSecurityManager(new SecurityManager());");
scratch.add(" I lam = () -> 10;");
scratch.add(" Runnable r = () -> {");
scratch.add(" System.out.println(\"Runnable\");");
@@ -114,7 +115,6 @@
public void testNotLogging() {
TestResult tr = doExec(JAVA_CMD.getAbsolutePath(),
"-cp", ".",
- "-Djava.security.manager",
"com.example.TestLambda");
tr.assertZero("Should still return 0");
}
@@ -125,7 +125,6 @@
TestResult tr = doExec(JAVA_CMD.getAbsolutePath(),
"-cp", ".",
"-Djdk.internal.lambda.dumpProxyClasses=dump",
- "-Djava.security.manager",
"com.example.TestLambda");
// 2 our own class files. We don't care about the others
assertEquals(Files.find(
@@ -143,7 +142,6 @@
TestResult tr = doExec(JAVA_CMD.getAbsolutePath(),
"-cp", ".",
"-Djdk.internal.lambda.dumpProxyClasses=notExist",
- "-Djava.security.manager",
"com.example.TestLambda");
assertEquals(tr.testOutput.stream()
.filter(s -> s.startsWith("WARNING"))
@@ -159,7 +157,6 @@
TestResult tr = doExec(JAVA_CMD.getAbsolutePath(),
"-cp", ".",
"-Djdk.internal.lambda.dumpProxyClasses=file",
- "-Djava.security.manager",
"com.example.TestLambda");
assertEquals(tr.testOutput.stream()
.filter(s -> s.startsWith("WARNING"))
@@ -218,7 +215,6 @@
TestResult tr = doExec(JAVA_CMD.getAbsolutePath(),
"-cp", ".",
"-Djdk.internal.lambda.dumpProxyClasses=readOnly",
- "-Djava.security.manager",
"com.example.TestLambda");
assertEquals(tr.testOutput.stream()
.filter(s -> s.startsWith("WARNING"))
@@ -237,7 +233,6 @@
TestResult tr = doExec(JAVA_CMD.getAbsolutePath(),
"-cp", ".",
"-Djdk.internal.lambda.dumpProxyClasses=dumpLong",
- "-Djava.security.manager",
longFQCN);
assertEquals(tr.testOutput.stream()
.filter(s -> s.startsWith("WARNING: Exception"))
--- a/jdk/test/java/nio/channels/Selector/SelectTimeout.java Fri Jan 20 10:28:34 2017 -0800
+++ b/jdk/test/java/nio/channels/Selector/SelectTimeout.java Fri Jan 20 08:53:42 2017 -0800
@@ -1,46 +1,50 @@
/*
-* Copyright (c) 2016, 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.
-*/
+ * Copyright (c) 2016, 2017, 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 8165000
- * @summary Verify no IOException on OS X for large timeout value in select().
- * @requires (os.family == "mac")
+ * @bug 8165000 8172547
+ * @summary Verify no IOException on OS X for large timeout value in select()
+ * and that timeout does not occur too early on Windows.
+ * @requires (os.family == "mac" | os.family == "windows")
*/
import java.io.IOException;
import java.nio.channels.Selector;
public class SelectTimeout {
- private static final long HUGE_TIMEOUT = 100000001000L;
- private static final long SLEEP_MILLIS = 10000;
+ private static final long BIG_TIMEOUT = 100_000_001_000L; // 8165000
+ private static final long BIGGER_TIMEOUT = 850_000_000_000_000L; // 8172547
+ private static final long SLEEP_MILLIS = 10000;
- private static Exception theException;
+ private static volatile Exception theException;
+ private static volatile boolean isTimedOut;
public static void main(String[] args)
throws IOException, InterruptedException {
int failures = 0;
long[] timeouts =
- new long[] {0, HUGE_TIMEOUT/2, HUGE_TIMEOUT - 1, HUGE_TIMEOUT};
+ new long[] {1, BIG_TIMEOUT/2, BIG_TIMEOUT - 1, BIG_TIMEOUT,
+ BIGGER_TIMEOUT};
for (long t : timeouts) {
if (!test(t)) {
failures++;
@@ -61,23 +65,35 @@
Thread t = new Thread(() -> {
try {
+ isTimedOut = false;
selector.select(timeout);
+ isTimedOut = true;
} catch (IOException ioe) {
theException = ioe;
}
});
t.start();
- Thread.currentThread().sleep(SLEEP_MILLIS);
- t.interrupt();
+ t.join(SLEEP_MILLIS);
+ boolean result;
if (theException == null) {
- System.out.printf("Test succeeded with timeout %d%n", timeout);
- return true;
+ if (timeout > SLEEP_MILLIS && isTimedOut) {
+ System.err.printf("Test timed out early with timeout %d%n",
+ timeout);
+ result = false;
+ } else {
+ System.out.printf("Test succeeded with timeout %d%n", timeout);
+ result = true;
+ }
} else {
System.err.printf("Test failed with timeout %d%n", timeout);
theException.printStackTrace();
- return false;
+ result = false;
}
+
+ t.interrupt();
+
+ return result;
}
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/rmi/MarshalledObject/MOFilterTest.java Fri Jan 20 08:53:42 2017 -0800
@@ -0,0 +1,140 @@
+/*
+ * Copyright (c) 2016, 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.
+ */
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InvalidClassException;
+import java.io.ObjectInput;
+import java.io.ObjectInputStream;
+import java.io.ObjectInputFilter;
+import java.io.ObjectOutputStream;
+import java.io.Serializable;
+import java.rmi.MarshalledObject;
+import java.util.Objects;
+
+
+import org.testng.Assert;
+import org.testng.annotations.Test;
+import org.testng.annotations.DataProvider;
+
+/* @test
+ * @run testng/othervm MOFilterTest
+ *
+ * @summary Test MarshalledObject applies ObjectInputFilter
+ */
+@Test
+public class MOFilterTest {
+
+ /**
+ * Two cases are tested.
+ * The filter = null and a filter set to verify the calls to the filter.
+ * @return array objects with test parameters for each test case
+ */
+ @DataProvider(name = "FilterCases")
+ public static Object[][] filterCases() {
+ return new Object[][] {
+ {true}, // run the test with the filter
+ {false}, // run the test without the filter
+
+ };
+ }
+
+ /**
+ * Test that MarshalledObject inherits the ObjectInputFilter from
+ * the stream it was deserialized from.
+ */
+ @Test(dataProvider="FilterCases")
+ static void delegatesToMO(boolean withFilter) {
+ try {
+ Serializable testobj = Integer.valueOf(5);
+ MarshalledObject<Serializable> mo = new MarshalledObject<>(testobj);
+ Assert.assertEquals(mo.get(), testobj, "MarshalledObject.get returned a non-equals test object");
+
+ byte[] bytes = writeObjects(mo);
+
+ try (ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
+ ObjectInputStream ois = new ObjectInputStream(bais)) {
+
+ CountingFilter filter1 = new CountingFilter();
+ ois.setObjectInputFilter(withFilter ? filter1 : null);
+ MarshalledObject<?> actualMO = (MarshalledObject<?>)ois.readObject();
+ int count = filter1.getCount();
+
+ actualMO.get();
+ int expectedCount = withFilter ? count + 2 : count;
+ int actualCount = filter1.getCount();
+ Assert.assertEquals(actualCount, expectedCount, "filter called wrong number of times during get()");
+ }
+ } catch (IOException ioe) {
+ Assert.fail("Unexpected IOException", ioe);
+ } catch (ClassNotFoundException cnf) {
+ Assert.fail("Deserializing", cnf);
+ }
+ }
+
+ /**
+ * Write objects and return a byte array with the bytes.
+ *
+ * @param objects zero or more objects to serialize
+ * @return the byte array of the serialized objects
+ * @throws IOException if an exception occurs
+ */
+ static byte[] writeObjects(Object... objects) throws IOException {
+ byte[] bytes;
+ try (ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ ObjectOutputStream oos = new ObjectOutputStream(baos)) {
+ for (Object o : objects) {
+ oos.writeObject(o);
+ }
+ bytes = baos.toByteArray();
+ }
+ return bytes;
+ }
+
+
+ static class CountingFilter implements ObjectInputFilter {
+
+ private int count; // count of calls to the filter
+
+ CountingFilter() {
+ count = 0;
+ }
+
+ int getCount() {
+ return count;
+ }
+
+ /**
+ * Filter that rejects class Integer and allows others
+ *
+ * @param filterInfo access to the class, arrayLength, etc.
+ * @return {@code STATUS.REJECTED}
+ */
+ public ObjectInputFilter.Status checkInput(FilterInfo filterInfo) {
+ count++;
+ return ObjectInputFilter.Status.ALLOWED;
+ }
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/rmi/registry/serialFilter/RegistryFilterTest.java Fri Jan 20 08:53:42 2017 -0800
@@ -0,0 +1,186 @@
+/*
+ * Copyright (c) 2016, 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.
+ */
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.ObjectOutputStream;
+import java.io.Serializable;
+
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.rmi.MarshalledObject;
+import java.rmi.NotBoundException;
+import java.rmi.Remote;
+import java.rmi.RemoteException;
+import java.rmi.AlreadyBoundException;
+import java.rmi.registry.LocateRegistry;
+import java.rmi.registry.Registry;
+import java.util.Objects;
+import java.security.Security;
+
+import org.testng.Assert;
+import org.testng.TestNG;
+import org.testng.annotations.BeforeSuite;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+/*
+ * @test
+ * @library /java/rmi/testlibrary
+ * @modules java.rmi/sun.rmi.registry
+ * java.rmi/sun.rmi.server
+ * java.rmi/sun.rmi.transport
+ * java.rmi/sun.rmi.transport.tcp
+ * @build TestLibrary
+ * @summary Test filters for the RMI Registry
+ * @run testng/othervm RegistryFilterTest
+ * @run testng/othervm
+ * -Dsun.rmi.registry.registryFilter=!java.lang.Long;!RegistryFilterTest$RejectableClass
+ * RegistryFilterTest
+ * @run testng/othervm/policy=security.policy
+ * -Djava.security.properties=${test.src}/java.security-extra1
+ * RegistryFilterTest
+ */
+public class RegistryFilterTest {
+ private static Registry impl;
+ private static int port;
+ private static Registry registry;
+
+ static final int REGISTRY_MAX_ARRAY = 10000;
+
+ static final String registryFilter =
+ System.getProperty("sun.rmi.registry.registryFilter",
+ Security.getProperty("sun.rmi.registry.registryFilter"));
+
+ @DataProvider(name = "bindAllowed")
+ static Object[][] bindAllowedObjects() {
+ Object[][] objects = {
+ };
+ return objects;
+ }
+
+ /**
+ * Data RMI Regiry bind test.
+ * - name
+ * - Object
+ * - true/false if object is blacklisted by a filter (implicit or explicit)
+ * @return array of test data
+ */
+ @DataProvider(name = "bindData")
+ static Object[][] bindObjects() {
+ Object[][] data = {
+ { "byte[max]", new XX(new byte[REGISTRY_MAX_ARRAY]), false },
+ { "String", new XX("now is the time"), false},
+ { "String[]", new XX(new String[3]), false},
+ { "Long[4]", new XX(new Long[4]), registryFilter != null },
+ { "rej-byte[toobig]", new XX(new byte[REGISTRY_MAX_ARRAY + 1]), true },
+ { "rej-MarshalledObject", createMarshalledObject(), true },
+ { "rej-RejectableClass", new RejectableClass(), registryFilter != null},
+ };
+ return data;
+ }
+
+ static XX createMarshalledObject() {
+ try {
+ return new XX(new MarshalledObject<>(null));
+ } catch (IOException ioe) {
+ return new XX(ioe);
+ }
+ }
+
+ @BeforeSuite
+ static void setupRegistry() {
+ try {
+ impl = TestLibrary.createRegistryOnEphemeralPort();
+ port = TestLibrary.getRegistryPort(impl);
+ registry = LocateRegistry.getRegistry("localhost", port);
+ } catch (RemoteException ex) {
+ Assert.fail("initialization of registry", ex);
+ }
+
+ System.out.printf("RMI Registry filter: %s%n", registryFilter);
+ }
+
+
+ /*
+ * Test registry rejects an object with the max array size + 1.
+ */
+ @Test(dataProvider="bindData")
+ public void simpleBind(String name, Remote obj, boolean blacklisted) throws RemoteException, AlreadyBoundException, NotBoundException {
+ try {
+ registry.bind(name, obj);
+ Assert.assertFalse(blacklisted, "Registry filter did not reject (but should have) ");
+ registry.unbind(name);
+ } catch (Exception rex) {
+ Assert.assertTrue(blacklisted, "Registry filter should not have rejected");
+ }
+ }
+
+ /*
+ * Test registry rejects an object with a well known class
+ * if blacklisted in the security properties.
+ */
+ @Test
+ public void simpleRejectableClass() throws RemoteException, AlreadyBoundException, NotBoundException {
+ RejectableClass r1 = null;
+ try {
+ String name = "reject1";
+ r1 = new RejectableClass();
+ registry.bind(name, r1);
+ registry.unbind(name);
+ Assert.assertNull(registryFilter, "Registry filter should not have rejected");
+ } catch (Exception rex) {
+ Assert.assertNotNull(registryFilter, "Registry filter should have rejected");
+ }
+ }
+
+ /**
+ * A simple Serializable Remote object that is passed by value.
+ * It and its contents are checked by the Registry serial filter.
+ */
+ static class XX implements Serializable, Remote {
+ private static final long serialVersionUID = 362498820763181265L;
+
+ final Object obj;
+
+ XX(Object obj) {
+ this.obj = obj;
+ }
+
+ public String toString() {
+ return super.toString() + "//" + Objects.toString(obj);
+ }
+ }
+ /**
+ * A simple Serializable Remote object that is passed by value.
+ * It and its contents are checked by the Registry serial filter.
+ */
+ static class RejectableClass implements Serializable, Remote {
+ private static final long serialVersionUID = 362498820763181264L;
+
+ RejectableClass() {}
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/rmi/registry/serialFilter/java.security-extra1 Fri Jan 20 08:53:42 2017 -0800
@@ -0,0 +1,9 @@
+# RMI Registry Input Serial Filter
+#
+# The filter pattern uses the same format as java.io.ObjectInputStream.serialFilter.
+# This filter can override the builtin filter if additional types need to be
+# allowed or rejected from the RMI Registry.
+#
+#sun.rmi.registry.registryFilter=pattern,pattern
+sun.rmi.registry.registryFilter=!java.lang.Long;!RegistryFilterTest$RejectableClass
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/rmi/registry/serialFilter/security.policy Fri Jan 20 08:53:42 2017 -0800
@@ -0,0 +1,4 @@
+grant {
+ permission java.security.AllPermission;
+};
+
--- a/jdk/test/java/security/KeyRep/SerialOld.policy Fri Jan 20 10:28:34 2017 -0800
+++ b/jdk/test/java/security/KeyRep/SerialOld.policy Fri Jan 20 08:53:42 2017 -0800
@@ -1,4 +1,4 @@
-grant {
+grant codeBase "file:${test.classes}/*" {
permission java.io.FilePermission "${test.src}${file.separator}*", "read";
permission java.util.PropertyPermission "test.src", "read";
@@ -11,4 +11,6 @@
"accessClassInPackage.sun.security.x509";
permission java.lang.RuntimePermission
"accessClassInPackage.sun.security.rsa";
+ permission java.lang.RuntimePermission
+ "accessClassInPackage.com.sun.crypto.provider";
};
--- a/jdk/test/java/util/ResourceBundle/ResourceBundleTest.java Fri Jan 20 10:28:34 2017 -0800
+++ b/jdk/test/java/util/ResourceBundle/ResourceBundleTest.java Fri Jan 20 08:53:42 2017 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2007, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 2017, 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
@@ -22,7 +22,7 @@
*/
/*
@test
- @bug 4049325 4073127 4083270 4106034 4108126 8027930
+ @bug 4049325 4073127 4083270 4106034 4108126 8027930 8171139
@summary test Resource Bundle
@build TestResource TestResource_de TestResource_fr TestResource_fr_CH
@build TestResource_it FakeTestResource
@@ -65,6 +65,7 @@
import java.util.*;
import java.util.ResourceBundle.Control;
import java.io.*;
+import java.net.URL;
public class ResourceBundleTest extends RBTestFmwk {
public static void main(String[] args) throws Exception {
@@ -330,6 +331,44 @@
}
}
+ /*
+ * @bug 8171139
+ * @summary Make sure clearCache() clears cached ResourceBundle instances
+ */
+ public void TestClearCache() {
+ final String className = "TestResource";
+ Locale loc = Locale.getDefault();
+
+ // testing no-arg clearCache()
+ ResourceBundle rb1 = ResourceBundle.getBundle(className, loc);
+ ResourceBundle.clearCache();
+ ResourceBundle rb2 = ResourceBundle.getBundle(className, loc);
+ if (rb1 == rb2) {
+ errln("clearCache(no-arg) did not clear cache");
+ }
+
+ // clearCache() with a custom classloader
+ ClassLoader cl1 = new DummyClassLoader();
+ rb1 = ResourceBundle.getBundle(className, loc, cl1);
+ if (rb1 == rb2) {
+ errln("Same bundle was returned for different class loaders");
+ }
+ ResourceBundle.clearCache(cl1);
+ rb2= ResourceBundle.getBundle(className, loc, cl1);
+ if (rb1 == rb2) {
+ errln("clearCache(classLoader) did not clear cache");
+ }
+ ClassLoader cl2 = new DummyClassLoader();
+ rb1 = ResourceBundle.getBundle(className, loc, cl2);
+ if (rb1 == rb2) {
+ errln("Same bundle was returned for different class loaders");
+ }
+ ResourceBundle.clearCache(cl1);
+ rb2 = ResourceBundle.getBundle(className, loc, cl2);
+ if (rb1 != rb2) {
+ errln("clearCache(classLoader) incorrectly cleared cache");
+ }
+ }
private void makePropertiesFile() {
try {
@@ -393,4 +432,22 @@
errln("Wrong number of elements in key list: expected " + expectedKeys.length +
" got " + elementCount);
}
+
+ private static class DummyClassLoader extends ClassLoader {
+ public DummyClassLoader() {
+ super(DummyClassLoader.class.getClassLoader());
+ }
+
+ public Class<?> loadClass(String name) throws ClassNotFoundException {
+ return DummyClassLoader.class.getClassLoader().loadClass(name);
+ }
+
+ public URL getResource(String name) {
+ return DummyClassLoader.class.getClassLoader().getResource(name);
+ }
+
+ public InputStream getResourceAsStream(String name) {
+ return DummyClassLoader.class.getClassLoader().getResourceAsStream(name);
+ }
+ }
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/logging/modules/LogManagerInModule/LogManagerInModuleTest.java Fri Jan 20 08:53:42 2017 -0800
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2017, 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.
+ */
+
+import java.nio.file.Paths;
+import java.util.logging.Handler;
+import java.util.logging.LogManager;
+import java.util.logging.Logger;
+
+/**
+ * @test
+ * @bug 8172886
+ * @summary Verifies that a custom LogManager or custom Handler can be
+ * instantiated by the logging system if they are in a package
+ * that is exported to java.logging by a module.
+ * @build test.logmanager/test.logmanager.TestLogManager
+ * test.handlers/test.handlers.TestHandler
+ * test.config/test.config.LogConfig
+ * LogManagerInModuleTest
+ * @run main/othervm --add-modules test.logmanager,test.handlers
+ * -Djava.util.logging.manager=test.logmanager.TestLogManager
+ * LogManagerInModuleTest
+ * @run main/othervm --add-modules test.logmanager,test.handlers,test.config
+ * -Djava.util.logging.manager=test.logmanager.TestLogManager
+ * -Djava.util.logging.config.class=test.config.LogConfig
+ * LogManagerInModuleTest
+ *
+ * @author danielfuchs
+ */
+public class LogManagerInModuleTest {
+
+ public static void main(String[] args) throws Exception {
+ if (System.getProperty("java.util.logging.config.class", null) == null) {
+ System.setProperty("java.util.logging.config.file",
+ Paths.get(System.getProperty("test.src", "src"),
+ "logging.properties").toString());
+ }
+ // sanity check
+ if (LogManagerInModuleTest.class.getModule().isNamed()) {
+ throw new RuntimeException("Unexpected named module for "
+ + LogManagerInModuleTest.class + ": "
+ + LogManagerInModuleTest.class.getModule().getName());
+ }
+
+ // now check that the LogManager was correctly instantiated.
+ LogManager manager = LogManager.getLogManager();
+ System.out.println("LogManager: " + manager);
+ Class<?> logManagerClass = manager.getClass();
+ if (!"test.logmanager".equals(logManagerClass.getModule().getName())) {
+ throw new RuntimeException("Bad module for log manager: "
+ + logManagerClass.getModule() + "; class is: "
+ + logManagerClass.getName());
+ }
+
+ Logger logger = Logger.getLogger("com.xyz.foo");
+ Handler[] handlers = logger.getHandlers();
+ if (handlers.length != 1) {
+ throw new RuntimeException("Expected 1 handler, found " + handlers.length);
+ }
+ Class<?> handlerClass = handlers[0].getClass();
+ if (!"test.handlers".equals(handlerClass.getModule().getName())) {
+ throw new RuntimeException("Bad module for handler: "
+ + handlerClass.getModule() + "; class is: "
+ + handlerClass.getName());
+ }
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/logging/modules/LogManagerInModule/logging.properties Fri Jan 20 08:53:42 2017 -0800
@@ -0,0 +1,56 @@
+############################################################
+# Global properties
+############################################################
+
+# "handlers" specifies a comma separated list of log Handler
+# classes. These handlers will be installed during VM startup.
+# Note that these classes must be on the system classpath.
+# By default we only configure a ConsoleHandler, which will only
+# show messages at the INFO and above levels.
+handlers= java.util.logging.ConsoleHandler
+
+# To also add the FileHandler, use the following line instead.
+#handlers= java.util.logging.FileHandler, java.util.logging.ConsoleHandler
+
+# Default global logging level.
+# This specifies which kinds of events are logged across
+# all loggers. For any given facility this global level
+# can be overriden by a facility specific level
+# Note that the ConsoleHandler also has a separate level
+# setting to limit messages printed to the console.
+.level= INFO
+
+############################################################
+# Handler specific properties.
+# Describes specific configuration info for Handlers.
+############################################################
+
+# default file output is in user's home directory.
+java.util.logging.FileHandler.pattern = %h/java%u.log
+java.util.logging.FileHandler.limit = 50000
+java.util.logging.FileHandler.count = 1
+# Default number of locks FileHandler can obtain synchronously.
+# This specifies maximum number of attempts to obtain lock file by FileHandler
+# implemented by incrementing the unique field %u as per FileHandler API documentation.
+java.util.logging.FileHandler.maxLocks = 100
+java.util.logging.FileHandler.formatter = java.util.logging.XMLFormatter
+
+# Limit the message that are printed on the console to INFO and above.
+java.util.logging.ConsoleHandler.level = INFO
+java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter
+
+# Example to customize the SimpleFormatter output format
+# to print one-line log message like this:
+# <level>: <log message> [<date/time>]
+#
+# java.util.logging.SimpleFormatter.format=%4$s: %5$s [%1$tc]%n
+
+############################################################
+# Facility specific properties.
+# Provides extra control for each logger.
+############################################################
+
+# For example, set the com.xyz.foo logger to only log SEVERE
+# messages:
+com.xyz.foo.level = SEVERE
+com.xyz.foo.handlers = test.handlers.TestHandler
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/logging/modules/LogManagerInModule/test.config/module-info.java Fri Jan 20 08:53:42 2017 -0800
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2017, 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.
+ */
+
+module test.config {
+ requires java.logging;
+ requires test.handlers;
+ // makes it possible for java.logging to instantiate test.config.LogConfig;
+ // this doesn't need to be a qualified export, but making it so will prevent
+ // any other module from being able to instantiate the provided classes.
+ exports test.config to java.logging;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/logging/modules/LogManagerInModule/test.config/test/config/LogConfig.java Fri Jan 20 08:53:42 2017 -0800
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2017, 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 test.config;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.logging.LogManager;
+import java.util.logging.Logger;
+import test.handlers.TestHandler;
+
+/**
+ * A dummy class that configures the logging system.
+ * @author danielfuchs
+ */
+public class LogConfig {
+ private static final List<Logger> LOGGERS = new ArrayList<>();
+ public LogConfig() {
+ LogManager manager = LogManager.getLogManager();
+ Logger logger = Logger.getLogger("com.xyz.foo");
+ if (logger.getHandlers().length > 0) {
+ System.err.println(this.getClass().getName() + ": "
+ + "Unexpected handlers: "
+ + List.of(logger.getHandlers()));
+ throw new RuntimeException("Unexpected handlers: "
+ + List.of(logger.getHandlers()));
+ }
+ logger.addHandler(new TestHandler());
+ LOGGERS.add(logger);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/logging/modules/LogManagerInModule/test.handlers/module-info.java Fri Jan 20 08:53:42 2017 -0800
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2017, 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.
+ */
+
+module test.handlers {
+ requires transitive java.logging;
+ // makes it possible for java.logging and test.config to instantiate
+ // test.handlers.TestHandler;
+ // this doesn't need to be a qualified export, but making it so will prevent
+ // any other module from being able to instantiate the provided classes.
+ exports test.handlers to java.logging, test.config;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/logging/modules/LogManagerInModule/test.handlers/test/handlers/TestHandler.java Fri Jan 20 08:53:42 2017 -0800
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2017, 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 test.handlers;
+
+import java.util.logging.Handler;
+import java.util.logging.LogRecord;
+
+/**
+ * A dummy Handler that does nothing.
+ * @author danielfuchs
+ */
+public class TestHandler extends Handler {
+
+ @Override
+ public void publish(LogRecord record) {
+ }
+
+ @Override
+ public void flush() {
+ }
+
+ @Override
+ public void close() throws SecurityException {
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/logging/modules/LogManagerInModule/test.logmanager/module-info.java Fri Jan 20 08:53:42 2017 -0800
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2017, 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.
+ */
+
+module test.logmanager {
+ requires java.logging;
+ // makes it possible for java.logging to instantiate
+ // test.logmanager.TestLogManager;
+ // this doesn't need to be a qualified export, but making it so will prevent
+ // any other module from being able to instantiate the provided classes.
+ exports test.logmanager to java.logging;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/logging/modules/LogManagerInModule/test.logmanager/test/logmanager/TestLogManager.java Fri Jan 20 08:53:42 2017 -0800
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2017, 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 test.logmanager;
+
+import java.util.logging.LogManager;
+
+/**
+ * A dummy LogManager that simply extends the standard class.
+ * @author danielfuchs
+ */
+public class TestLogManager extends LogManager {
+
+}
--- a/jdk/test/javax/net/ssl/SSLParameters/UseCipherSuitesOrder.java Fri Jan 20 10:28:34 2017 -0800
+++ b/jdk/test/javax/net/ssl/SSLParameters/UseCipherSuitesOrder.java Fri Jan 20 08:53:42 2017 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2016, 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
@@ -31,7 +31,7 @@
* @bug 7188657
* @summary There should be a way to reorder the JSSE ciphers
* @run main/othervm UseCipherSuitesOrder
- * TLS_RSA_WITH_AES_128_CBC_SHA,SSL_RSA_WITH_3DES_EDE_CBC_SHA
+ * TLS_RSA_WITH_AES_128_CBC_SHA,TLS_DHE_RSA_WITH_AES_128_CBC_SHA
*/
import java.io.*;
--- a/jdk/test/javax/rmi/PortableRemoteObject/8146975/jtreg.test.policy Fri Jan 20 10:28:34 2017 -0800
+++ b/jdk/test/javax/rmi/PortableRemoteObject/8146975/jtreg.test.policy Fri Jan 20 08:53:42 2017 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2017, 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
@@ -21,25 +21,12 @@
* questions.
*/
-grant codeBase "jrt:/java.corba" {
- permission java.security.AllPermission;
+grant {
+ permission java.util.PropertyPermission "*", "read";
+ permission java.io.FilePermission "<<ALL FILES>>", "read, execute";
};
-
-
-grant {
- permission java.io.FilePermission "./-", "read,write,execute";
- permission java.io.FilePermission "*", "read";
+grant codeBase "file:${test.classes}/*" {
permission java.net.SocketPermission "*:*", "connect, accept, listen, resolve";
- permission java.util.PropertyPermission "*", "read, write";
- permission java.lang.reflect.ReflectPermission "suppressAccessChecks";
- permission java.io.SerializablePermission "enableSubclassImplementation";
- permission java.lang.RuntimePermission "accessClassInPackage.jdk.internal.misc";
- permission java.lang.RuntimePermission "accessClassInPackage.sun.corba";
- permission java.lang.RuntimePermission "defineClassInPackage.sun.corba";
- permission java.lang.RuntimePermission "reflectionFactoryAccess";
- permission sun.corba.BridgePermission "getBridge";
- permission java.lang.RuntimePermission "accessClassInPackage.jdk.internal.reflect";
- permission java.util.PropertyPermission "*", "read, write";
- permission java.io.FilePermission "<<ALL FILES>>", "read,write,execute";
+ permission java.lang.RuntimePermission "accessClassInPackage.com.sun.jndi.cosnaming";
};
--- a/jdk/test/javax/rmi/PortableRemoteObject/jtreg.test.policy Fri Jan 20 10:28:34 2017 -0800
+++ b/jdk/test/javax/rmi/PortableRemoteObject/jtreg.test.policy Fri Jan 20 08:53:42 2017 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2017, 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
@@ -21,23 +21,12 @@
* questions.
*/
-grant codeBase "jrt:/java.corba" {
- permission java.security.AllPermission;
+grant {
+ permission java.util.PropertyPermission "*", "read";
+ permission java.io.FilePermission "<<ALL FILES>>", "read, execute";
};
-grant {
- permission java.io.FilePermission "./-", "read,write,execute";
- permission java.io.FilePermission "*", "read";
+grant codeBase "file:${test.classes}/*" {
permission java.net.SocketPermission "*:*", "connect, accept, listen, resolve";
- permission java.util.PropertyPermission "*", "read, write";
- permission java.lang.reflect.ReflectPermission "suppressAccessChecks";
- permission java.io.SerializablePermission "enableSubclassImplementation";
- permission java.lang.RuntimePermission "accessClassInPackage.jdk.internal.misc";
- permission java.lang.RuntimePermission "accessClassInPackage.sun.corba";
- permission java.lang.RuntimePermission "defineClassInPackage.sun.corba";
- permission java.lang.RuntimePermission "reflectionFactoryAccess";
- permission sun.corba.BridgePermission "getBridge";
- permission java.lang.RuntimePermission "accessClassInPackage.jdk.internal.reflect";
- permission java.util.PropertyPermission "*", "read, write";
- permission java.io.FilePermission "<<ALL FILES>>", "read,write,execute";
+ permission java.lang.RuntimePermission "accessClassInPackage.com.sun.jndi.cosnaming";
};
--- a/jdk/test/jdk/nio/zipfs/PathOps.java Fri Jan 20 10:28:34 2017 -0800
+++ b/jdk/test/jdk/nio/zipfs/PathOps.java Fri Jan 20 08:53:42 2017 -0800
@@ -31,7 +31,7 @@
/**
*
* @test
- * @bug 8038500 8040059 8139956 8146754
+ * @bug 8038500 8040059 8139956 8146754 8172921
* @summary Tests path operations for zip provider.
*
* @run main PathOps
@@ -180,6 +180,13 @@
return this;
}
+ PathOps resolvePath(String other, String expected) {
+ out.format("test resolve %s\n", other);
+ checkPath();
+ check(path.resolve(fs.getPath(other)), expected);
+ return this;
+ }
+
PathOps resolveSibling(String other, String expected) {
out.format("test resolveSibling %s\n", other);
checkPath();
@@ -384,6 +391,30 @@
.resolve("", "")
.resolve("foo", "foo")
.resolve("/foo", "/foo");
+ test("/")
+ .resolve("", "/")
+ .resolve("foo", "/foo")
+ .resolve("/foo", "/foo")
+ .resolve("/foo/", "/foo");
+
+ // resolve(Path)
+ test("/tmp")
+ .resolvePath("foo", "/tmp/foo")
+ .resolvePath("/foo", "/foo")
+ .resolvePath("", "/tmp");
+ test("tmp")
+ .resolvePath("foo", "tmp/foo")
+ .resolvePath("/foo", "/foo")
+ .resolvePath("", "tmp");
+ test("")
+ .resolvePath("", "")
+ .resolvePath("foo", "foo")
+ .resolvePath("/foo", "/foo");
+ test("/")
+ .resolvePath("", "/")
+ .resolvePath("foo", "/foo")
+ .resolvePath("/foo", "/foo")
+ .resolvePath("/foo/", "/foo");
// resolveSibling
test("foo")
--- a/jdk/test/sun/security/tools/jarsigner/concise_jarsigner.sh Fri Jan 20 10:28:34 2017 -0800
+++ b/jdk/test/sun/security/tools/jarsigner/concise_jarsigner.sh Fri Jan 20 08:53:42 2017 -0800
@@ -22,7 +22,7 @@
#
# @test
-# @bug 6802846
+# @bug 6802846 8172529
# @summary jarsigner needs enhanced cert validation(options)
#
# @run shell/timeout=240 concise_jarsigner.sh
@@ -52,7 +52,7 @@
KS=js.ks
KT="$TESTJAVA${FS}bin${FS}keytool ${TESTTOOLVMOPTS} -storepass changeit -keypass changeit -keystore $KS -keyalg rsa -keysize 1024"
JAR="$TESTJAVA${FS}bin${FS}jar ${TESTTOOLVMOPTS}"
-JARSIGNER="$TESTJAVA${FS}bin${FS}jarsigner ${TESTTOOLVMOPTS}"
+JARSIGNER="$TESTJAVA${FS}bin${FS}jarsigner ${TESTTOOLVMOPTS} -debug"
JAVAC="$TESTJAVA${FS}bin${FS}javac ${TESTTOOLVMOPTS} ${TESTJAVACOPTS}"
rm $KS
@@ -138,7 +138,7 @@
[ $LINES = 4 ] || exit $LINENO
# ==========================================================
-# Second part: exit code 2, 4, 8
+# Second part: exit code 2, 4, 8.
# 16 and 32 already covered in the first part
# ==========================================================
@@ -174,11 +174,14 @@
$JARSIGNER -strict -keystore $KS -storepass changeit a.jar goodeku
[ $? = 0 ] || exit $LINENO
-# badchain signed by ca, but ca is removed later
+# badchain signed by ca1, but ca1 is removed later
$KT -genkeypair -alias badchain -dname CN=badchain -validity 365
-$KT -certreq -alias badchain | $KT -gencert -alias ca -validity 365 | \
+$KT -genkeypair -alias ca1 -dname CN=ca1 -ext bc -validity 365
+$KT -certreq -alias badchain | $KT -gencert -alias ca1 -validity 365 | \
$KT -importcert -alias badchain
-$KT -delete -alias ca
+# save ca1.cert for easy replay
+$KT -exportcert -file ca1.cert -alias ca1
+$KT -delete -alias ca1
$JARSIGNER -strict -keystore $KS -storepass changeit a.jar badchain
[ $? = 4 ] || exit $LINENO
@@ -204,13 +207,41 @@
$JARSIGNER -strict -keystore $KS -storepass changeit -certchain certchain a.jar altchain
[ $? = 0 ] || exit $LINENO
-# but if ca2 is removed, -certchain does not work
+# if ca2 is removed, -certchain still work because altchain is a self-signed entry and
+# it is trusted by jarsigner
+# save ca2.cert for easy replay
+$KT -exportcert -file ca2.cert -alias ca2
$KT -delete -alias ca2
$JARSIGNER -strict -keystore $KS -storepass changeit -certchain certchain a.jar altchain
+[ $? = 0 ] || exit $LINENO
+
+# if cert is imported, -certchain won't work because this certificate entry is not trusted
+$KT -importcert -file certchain -alias altchain -noprompt
+$JARSIGNER -strict -keystore $KS -storepass changeit -certchain certchain a.jar altchain
[ $? = 4 ] || exit $LINENO
$JARSIGNER -verify a.jar
[ $? = 0 ] || exit $LINENO
+# ==========================================================
+# 8172529
+# ==========================================================
+
+$KT -genkeypair -alias ee -dname CN=ee
+$KT -genkeypair -alias caone -dname CN=caone
+$KT -genkeypair -alias catwo -dname CN=catwo
+
+$KT -certreq -alias ee | $KT -gencert -alias catwo -rfc > ee.cert
+$KT -certreq -alias catwo | $KT -gencert -alias caone -sigalg MD5withRSA -rfc > catwo.cert
+
+# This certchain contains a cross-signed weak catwo.cert
+cat ee.cert catwo.cert | $KT -importcert -alias ee
+
+$JAR cvf a.jar A1.class
+$JARSIGNER -strict -keystore $KS -storepass changeit a.jar ee
+[ $? = 0 ] || exit $LINENO
+$JARSIGNER -strict -keystore $KS -storepass changeit -verify a.jar
+[ $? = 0 ] || exit $LINENO
+
echo OK
exit 0
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/tools/jar/multiRelease/ApiValidatorTest.java Fri Jan 20 08:53:42 2017 -0800
@@ -0,0 +1,193 @@
+/*
+ * Copyright (c) 2017, 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
+ * @summary Tests for API validator.
+ * @library /test/lib /lib/testlibrary
+ * @modules java.base/jdk.internal.misc
+ * jdk.compiler
+ * jdk.jartool
+ * @build jdk.test.lib.JDKToolFinder jdk.test.lib.Utils jdk.test.lib.process.*
+ * @build jdk.testlibrary.FileUtils
+ * @build MRTestBase
+ * @run testng ApiValidatorTest
+ */
+
+import jdk.test.lib.process.OutputAnalyzer;
+import jdk.testlibrary.FileUtils;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import java.lang.reflect.Method;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+
+public class ApiValidatorTest extends MRTestBase {
+
+ @Test(dataProvider = "signatureChange")
+ public void changeMethodSignature(String sigBase, String sigV10,
+ boolean isAcceptable,
+ Method method) throws Throwable {
+ Path root = Paths.get(method.getName());
+ Path classes = root.resolve("classes");
+
+ String METHOD_SIG = "#SIG";
+ String classTemplate =
+ "public class C { \n" +
+ " " + METHOD_SIG + "{ throw new RuntimeException(); };\n" +
+ "}\n";
+ String base = classTemplate.replace(METHOD_SIG, sigBase);
+ String v10 = classTemplate.replace(METHOD_SIG, sigV10);
+
+ compileTemplate(classes.resolve("base"), base);
+ compileTemplate(classes.resolve("v10"), v10);
+
+ String jarfile = root.resolve("test.jar").toString();
+ OutputAnalyzer result = jar("cf", jarfile,
+ "-C", classes.resolve("base").toString(), ".",
+ "--release", "10", "-C", classes.resolve("v10").toString(),
+ ".");
+ if (isAcceptable) {
+ result.shouldHaveExitValue(SUCCESS)
+ .shouldBeEmpty();
+ } else {
+ result.shouldNotHaveExitValue(SUCCESS)
+ .shouldContain("contains a class with different api from earlier version");
+ }
+
+ FileUtils.deleteFileTreeWithRetry(root);
+ }
+
+ @DataProvider
+ Object[][] signatureChange() {
+ return new Object[][]{
+ {"public int m()", "protected int m()", false},
+ {"protected int m()", "public int m()", false},
+ {"public int m()", "int m()", false},
+ {"protected int m()", "private int m()", false},
+ {"private int m()", "int m()", true},
+ {"int m()", "private int m()", true},
+ {"int m()", "private int m(boolean b)", true},
+ {"public int m()", "public int m(int i)", false},
+ {"public int m()", "public int k()", false},
+ {"public int m()", "private int k()", false},
+// @ignore JDK-8172147 {"public int m()", "public boolean m()", false},
+// @ignore JDK-8172147 {"public boolean", "public Boolean", false},
+// @ignore JDK-8172147 {"public <T> T", "public <T extends String> T", false},
+ };
+ }
+
+ @Test(dataProvider = "publicAPI")
+ public void introducingPublicMembers(String publicAPI,
+ Method method) throws Throwable {
+ Path root = Paths.get(method.getName());
+ Path classes = root.resolve("classes");
+
+ String API = "#API";
+ String classTemplate =
+ "public class C { \n" +
+ " " + API + "\n" +
+ " public void method(){ };\n" +
+ "}\n";
+ String base = classTemplate.replace(API, "");
+ String v10 = classTemplate.replace(API, publicAPI);
+
+ compileTemplate(classes.resolve("base"), base);
+ compileTemplate(classes.resolve("v10"), v10);
+
+ String jarfile = root.resolve("test.jar").toString();
+ jar("cf", jarfile, "-C", classes.resolve("base").toString(), ".",
+ "--release", "10", "-C", classes.resolve("v10").toString(), ".")
+ .shouldNotHaveExitValue(SUCCESS)
+ .shouldContain("contains a class with different api from earlier version");
+
+ FileUtils.deleteFileTreeWithRetry(root);
+ }
+
+ @DataProvider
+ Object[][] publicAPI() {
+ return new Object[][]{
+// @ignore JDK-8172148 {"protected class Inner { public void m(){ } } "}, // protected inner class
+// @ignore JDK-8172148 {"public class Inner { public void m(){ } }"}, // public inner class
+// @ignore JDK-8172148 {"public enum E { A; }"}, // public enum
+ {"public void m(){ }"}, // public method
+ {"protected void m(){ }"}, // protected method
+ };
+ }
+
+ @Test(dataProvider = "privateAPI")
+ public void introducingPrivateMembers(String privateAPI,
+ Method method) throws Throwable {
+ Path root = Paths.get(method.getName());
+ Path classes = root.resolve("classes");
+
+ String API = "#API";
+ String classTemplate =
+ "public class C { \n" +
+ " " + API + "\n" +
+ " public void method(){ };\n" +
+ "}\n";
+ String base = classTemplate.replace(API, "");
+ String v10 = classTemplate.replace(API, privateAPI);
+
+ compileTemplate(classes.resolve("base"), base);
+ compileTemplate(classes.resolve("v10"), v10);
+
+ String jarfile = root.resolve("test.jar").toString();
+ jar("cf", jarfile, "-C", classes.resolve("base").toString(), ".",
+ "--release", "10", "-C", classes.resolve("v10").toString(), ".")
+ .shouldHaveExitValue(SUCCESS);
+ // add release
+ jar("uf", jarfile,
+ "--release", "11", "-C", classes.resolve("v10").toString(), ".")
+ .shouldHaveExitValue(SUCCESS);
+ // replace release
+ jar("uf", jarfile,
+ "--release", "11", "-C", classes.resolve("v10").toString(), ".")
+ .shouldHaveExitValue(SUCCESS);
+
+ FileUtils.deleteFileTreeWithRetry(root);
+ }
+
+ @DataProvider
+ Object[][] privateAPI() {
+ return new Object[][]{
+ {"private class Inner { public void m(){ } } "}, // private inner class
+ {"class Inner { public void m(){ } }"}, // package private inner class
+ {"enum E { A; }"}, // package private enum
+ // Local class and private method
+ {"private void m(){ class Inner { public void m(){} } Inner i = null; }"},
+ {"void m(){ }"}, // package private method
+ };
+ }
+
+ private void compileTemplate(Path classes, String template) throws Throwable {
+ Path classSourceFile = Files.createDirectories(
+ classes.getParent().resolve("src").resolve(classes.getFileName()))
+ .resolve("C.java");
+ Files.write(classSourceFile, template.getBytes());
+ javac(classes, classSourceFile);
+ }
+}
\ No newline at end of file
--- a/jdk/test/tools/jar/multiRelease/Basic.java Fri Jan 20 10:28:34 2017 -0800
+++ b/jdk/test/tools/jar/multiRelease/Basic.java Fri Jan 20 08:53:42 2017 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2017, 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
@@ -23,69 +23,59 @@
/*
* @test
- * @library /test/lib
+ * @library /test/lib /lib/testlibrary
* @modules java.base/jdk.internal.misc
* jdk.compiler
* jdk.jartool
- * @build jdk.test.lib.JDKToolFinder jdk.test.lib.Utils
+ * @build jdk.test.lib.JDKToolFinder jdk.test.lib.Utils jdk.test.lib.process.*
+ * @build jdk.testlibrary.FileUtils
+ * @build MRTestBase
* @run testng Basic
*/
import static org.testng.Assert.*;
+import jdk.testlibrary.FileUtils;
import org.testng.annotations.*;
-import java.io.*;
+import java.io.File;
import java.nio.file.*;
-import java.nio.file.attribute.*;
import java.util.*;
-import java.util.function.Consumer;
-import java.util.jar.*;
-import java.util.stream.Collectors;
-import java.util.stream.Stream;
-import java.util.zip.*;
+import java.util.jar.JarFile;
+import java.util.zip.ZipFile;
-import jdk.test.lib.JDKToolFinder;
-import jdk.test.lib.Utils;
-
-
-import static java.lang.String.format;
-import static java.lang.System.out;
-
-public class Basic {
- private final String src = System.getProperty("test.src", ".");
- private final String usr = System.getProperty("user.dir", ".");
+public class Basic extends MRTestBase {
@Test
// create a regular, non-multi-release jar
- public void test00() throws IOException {
+ public void test00() throws Throwable {
String jarfile = "test.jar";
compile("test01"); //use same data as test01
Path classes = Paths.get("classes");
jar("cf", jarfile, "-C", classes.resolve("base").toString(), ".")
- .assertSuccess();
+ .shouldHaveExitValue(SUCCESS);
checkMultiRelease(jarfile, false);
- Map<String,String[]> names = Map.of(
+ Map<String, String[]> names = Map.of(
"version/Main.class",
- new String[] {"base", "version", "Main.class"},
+ new String[]{"base", "version", "Main.class"},
"version/Version.class",
- new String[] {"base", "version", "Version.class"}
+ new String[]{"base", "version", "Version.class"}
);
compare(jarfile, names);
- delete(jarfile);
- deleteDir(Paths.get(usr, "classes"));
+ FileUtils.deleteFileIfExistsWithRetry(Paths.get(jarfile));
+ FileUtils.deleteFileTreeWithRetry(Paths.get(usr, "classes"));
}
@Test
// create a multi-release jar
- public void test01() throws IOException {
+ public void test01() throws Throwable {
String jarfile = "test.jar";
compile("test01");
@@ -94,68 +84,96 @@
jar("cf", jarfile, "-C", classes.resolve("base").toString(), ".",
"--release", "9", "-C", classes.resolve("v9").toString(), ".",
"--release", "10", "-C", classes.resolve("v10").toString(), ".")
- .assertSuccess();
+ .shouldHaveExitValue(SUCCESS);
checkMultiRelease(jarfile, true);
- Map<String,String[]> names = Map.of(
+ Map<String, String[]> names = Map.of(
"version/Main.class",
- new String[] {"base", "version", "Main.class"},
+ new String[]{"base", "version", "Main.class"},
"version/Version.class",
- new String[] {"base", "version", "Version.class"},
+ new String[]{"base", "version", "Version.class"},
"META-INF/versions/9/version/Version.class",
- new String[] {"v9", "version", "Version.class"},
+ new String[]{"v9", "version", "Version.class"},
"META-INF/versions/10/version/Version.class",
- new String[] {"v10", "version", "Version.class"}
+ new String[]{"v10", "version", "Version.class"}
);
compare(jarfile, names);
- delete(jarfile);
- deleteDir(Paths.get(usr, "classes"));
+ FileUtils.deleteFileIfExistsWithRetry(Paths.get(jarfile));
+ FileUtils.deleteFileTreeWithRetry(Paths.get(usr, "classes"));
+ }
+
+ @Test
+ public void versionFormat() throws Throwable {
+ String jarfile = "test.jar";
+
+ compile("test01");
+
+ Path classes = Paths.get("classes");
+
+ // valid
+ for (String release : List.of("10000", "09", "00010", "10")) {
+ jar("cf", jarfile, "-C", classes.resolve("base").toString(), ".",
+ "--release", release, "-C", classes.resolve("v10").toString(), ".")
+ .shouldHaveExitValue(SUCCESS)
+ .shouldBeEmpty();
+ }
+ // invalid
+ for (String release : List.of("9.0", "8", "v9",
+ "9v", "0", "-10")) {
+ jar("cf", jarfile, "-C", classes.resolve("base").toString(), ".",
+ "--release", release, "-C", classes.resolve("v10").toString(), ".")
+ .shouldNotHaveExitValue(SUCCESS)
+ .shouldContain("release " + release + " not valid");
+ }
+ FileUtils.deleteFileIfExistsWithRetry(Paths.get(jarfile));
+ FileUtils.deleteFileTreeWithRetry(Paths.get(usr, "classes"));
}
@Test
// update a regular jar to a multi-release jar
- public void test02() throws IOException {
+ public void test02() throws Throwable {
String jarfile = "test.jar";
compile("test01"); //use same data as test01
Path classes = Paths.get("classes");
jar("cf", jarfile, "-C", classes.resolve("base").toString(), ".")
- .assertSuccess();
+ .shouldHaveExitValue(SUCCESS);
checkMultiRelease(jarfile, false);
- jar("uf", jarfile, "--release", "9", "-C", classes.resolve("v9").toString(), ".")
- .assertSuccess();
+ jar("uf", jarfile,
+ "--release", "9", "-C", classes.resolve("v9").toString(), ".")
+ .shouldHaveExitValue(SUCCESS);
checkMultiRelease(jarfile, true);
- Map<String,String[]> names = Map.of(
+ Map<String, String[]> names = Map.of(
"version/Main.class",
- new String[] {"base", "version", "Main.class"},
+ new String[]{"base", "version", "Main.class"},
"version/Version.class",
- new String[] {"base", "version", "Version.class"},
+ new String[]{"base", "version", "Version.class"},
"META-INF/versions/9/version/Version.class",
- new String[] {"v9", "version", "Version.class"}
+ new String[]{"v9", "version", "Version.class"}
);
compare(jarfile, names);
- delete(jarfile);
- deleteDir(Paths.get(usr, "classes"));
+ FileUtils.deleteFileIfExistsWithRetry(Paths.get(jarfile));
+ FileUtils.deleteFileTreeWithRetry(Paths.get(usr, "classes"));
}
@Test
// replace a base entry and a versioned entry
- public void test03() throws IOException {
+ public void test03() throws Throwable {
String jarfile = "test.jar";
compile("test01"); //use same data as test01
@@ -163,19 +181,19 @@
Path classes = Paths.get("classes");
jar("cf", jarfile, "-C", classes.resolve("base").toString(), ".",
"--release", "9", "-C", classes.resolve("v9").toString(), ".")
- .assertSuccess();
+ .shouldHaveExitValue(SUCCESS);
checkMultiRelease(jarfile, true);
- Map<String,String[]> names = Map.of(
+ Map<String, String[]> names = Map.of(
"version/Main.class",
- new String[] {"base", "version", "Main.class"},
+ new String[]{"base", "version", "Main.class"},
"version/Version.class",
- new String[] {"base", "version", "Version.class"},
+ new String[]{"base", "version", "Version.class"},
"META-INF/versions/9/version/Version.class",
- new String[] {"v9", "version", "Version.class"}
+ new String[]{"v9", "version", "Version.class"}
);
compare(jarfile, names);
@@ -184,25 +202,25 @@
// version/Version.class entry in versions/9 section
jar("uf", jarfile, "-C", classes.resolve("v9").toString(), "version",
"--release", "9", "-C", classes.resolve("v10").toString(), ".")
- .assertSuccess();
+ .shouldHaveExitValue(SUCCESS);
checkMultiRelease(jarfile, true);
names = Map.of(
"version/Main.class",
- new String[] {"base", "version", "Main.class"},
+ new String[]{"base", "version", "Main.class"},
"version/Version.class",
- new String[] {"v9", "version", "Version.class"},
+ new String[]{"v9", "version", "Version.class"},
"META-INF/versions/9/version/Version.class",
- new String[] {"v10", "version", "Version.class"}
+ new String[]{"v10", "version", "Version.class"}
);
compare(jarfile, names);
- delete(jarfile);
- deleteDir(Paths.get(usr, "classes"));
+ FileUtils.deleteFileIfExistsWithRetry(Paths.get(jarfile));
+ FileUtils.deleteFileTreeWithRetry(Paths.get(usr, "classes"));
}
/*
@@ -211,7 +229,7 @@
@Test
// META-INF/versions/9 class has different api than base class
- public void test04() throws IOException {
+ public void test04() throws Throwable {
String jarfile = "test.jar";
compile("test01"); //use same data as test01
@@ -224,18 +242,16 @@
jar("cf", jarfile, "-C", classes.resolve("base").toString(), ".",
"--release", "9", "-C", classes.resolve("v9").toString(), ".")
- .assertFailure()
- .resultChecker(r ->
- assertTrue(r.output.contains("different api from earlier"), r.output)
- );
+ .shouldNotHaveExitValue(SUCCESS)
+ .shouldContain("different api from earlier");
- delete(jarfile);
- deleteDir(Paths.get(usr, "classes"));
+ FileUtils.deleteFileIfExistsWithRetry(Paths.get(jarfile));
+ FileUtils.deleteFileTreeWithRetry(Paths.get(usr, "classes"));
}
@Test
// META-INF/versions/9 contains an extra public class
- public void test05() throws IOException {
+ public void test05() throws Throwable {
String jarfile = "test.jar";
compile("test01"); //use same data as test01
@@ -248,18 +264,16 @@
jar("cf", jarfile, "-C", classes.resolve("base").toString(), ".",
"--release", "9", "-C", classes.resolve("v9").toString(), ".")
- .assertFailure()
- .resultChecker(r ->
- assertTrue(r.output.contains("contains a new public class"), r.output)
- );
+ .shouldNotHaveExitValue(SUCCESS)
+ .shouldContain("contains a new public class");
- delete(jarfile);
- deleteDir(Paths.get(usr, "classes"));
+ FileUtils.deleteFileIfExistsWithRetry(Paths.get(jarfile));
+ FileUtils.deleteFileTreeWithRetry(Paths.get(usr, "classes"));
}
@Test
// META-INF/versions/9 contains an extra package private class -- this is okay
- public void test06() throws IOException {
+ public void test06() throws Throwable {
String jarfile = "test.jar";
compile("test01"); //use same data as test01
@@ -272,16 +286,16 @@
jar("cf", jarfile, "-C", classes.resolve("base").toString(), ".",
"--release", "9", "-C", classes.resolve("v9").toString(), ".")
- .assertSuccess();
+ .shouldHaveExitValue(SUCCESS);
- delete(jarfile);
- deleteDir(Paths.get(usr, "classes"));
+ FileUtils.deleteFileIfExistsWithRetry(Paths.get(jarfile));
+ FileUtils.deleteFileTreeWithRetry(Paths.get(usr, "classes"));
}
@Test
// META-INF/versions/9 contains an identical class to base entry class
// this is okay but produces warning
- public void test07() throws IOException {
+ public void test07() throws Throwable {
String jarfile = "test.jar";
compile("test01"); //use same data as test01
@@ -294,19 +308,42 @@
jar("cf", jarfile, "-C", classes.resolve("base").toString(), ".",
"--release", "9", "-C", classes.resolve("v9").toString(), ".")
- .assertSuccess()
- .resultChecker(r ->
- assertTrue(r.outputContains("contains a class that is identical"), r.output)
- );
+ .shouldHaveExitValue(SUCCESS)
+ .shouldContain("contains a class that")
+ .shouldContain("is identical");
+
+ FileUtils.deleteFileIfExistsWithRetry(Paths.get(jarfile));
+ FileUtils.deleteFileTreeWithRetry(Paths.get(usr, "classes"));
+ }
+
+ @Test
+ // META-INF/versions/9 contains an identical class to previous version entry class
+ // this is okay but produces warning
+ public void identicalClassToPreviousVersion() throws Throwable {
+ String jarfile = "test.jar";
- delete(jarfile);
- deleteDir(Paths.get(usr, "classes"));
+ compile("test01"); //use same data as test01
+
+ Path classes = Paths.get("classes");
+
+ jar("cf", jarfile, "-C", classes.resolve("base").toString(), ".",
+ "--release", "9", "-C", classes.resolve("v9").toString(), ".")
+ .shouldHaveExitValue(SUCCESS)
+ .shouldBeEmpty();
+ jar("uf", jarfile,
+ "--release", "10", "-C", classes.resolve("v9").toString(), ".")
+ .shouldHaveExitValue(SUCCESS)
+ .shouldContain("contains a class that")
+ .shouldContain("is identical");
+
+ FileUtils.deleteFileIfExistsWithRetry(Paths.get(jarfile));
+ FileUtils.deleteFileTreeWithRetry(Paths.get(usr, "classes"));
}
@Test
// resources with same name in different versions
// this is okay but produces warning
- public void test08() throws IOException {
+ public void test08() throws Throwable {
String jarfile = "test.jar";
compile("test01"); //use same data as test01
@@ -320,10 +357,8 @@
jar("cf", jarfile, "-C", classes.resolve("base").toString(), ".",
"--release", "9", "-C", classes.resolve("v9").toString(), ".")
- .assertSuccess()
- .resultChecker(r ->
- assertTrue(r.output.isEmpty(), r.output)
- );
+ .shouldHaveExitValue(SUCCESS)
+ .shouldBeEmpty();
// now add a different resource with same name to META-INF/version/9
Files.copy(source.resolve("Main.java"), classes.resolve("v9")
@@ -331,18 +366,16 @@
jar("cf", jarfile, "-C", classes.resolve("base").toString(), ".",
"--release", "9", "-C", classes.resolve("v9").toString(), ".")
- .assertSuccess()
- .resultChecker(r ->
- assertTrue(r.output.contains("multiple resources with same name"), r.output)
- );
+ .shouldHaveExitValue(SUCCESS)
+ .shouldContain("multiple resources with same name");
- delete(jarfile);
- deleteDir(Paths.get(usr, "classes"));
+ FileUtils.deleteFileIfExistsWithRetry(Paths.get(jarfile));
+ FileUtils.deleteFileTreeWithRetry(Paths.get(usr, "classes"));
}
@Test
// a class with an internal name different from the external name
- public void test09() throws IOException {
+ public void test09() throws Throwable {
String jarfile = "test.jar";
compile("test01"); //use same data as test01
@@ -355,18 +388,16 @@
jar("cf", jarfile, "-C", classes.resolve("base").toString(), ".",
"--release", "9", "-C", classes.resolve("v9").toString(), ".")
- .assertFailure()
- .resultChecker(r ->
- assertTrue(r.output.contains("names do not match"), r.output)
- );
+ .shouldNotHaveExitValue(SUCCESS)
+ .shouldContain("names do not match");
- delete(jarfile);
- deleteDir(Paths.get(usr, "classes"));
+ FileUtils.deleteFileIfExistsWithRetry(Paths.get(jarfile));
+ FileUtils.deleteFileTreeWithRetry(Paths.get(usr, "classes"));
}
@Test
// assure that basic nested classes are acceptable
- public void test10() throws IOException {
+ public void test10() throws Throwable {
String jarfile = "test.jar";
compile("test01"); //use same data as test01
@@ -383,15 +414,15 @@
jar("cf", jarfile, "-C", classes.resolve("base").toString(), ".",
"--release", "9", "-C", classes.resolve("v9").toString(), ".")
- .assertSuccess();
+ .shouldHaveExitValue(SUCCESS);
- delete(jarfile);
- deleteDir(Paths.get(usr, "classes"));
+ FileUtils.deleteFileIfExistsWithRetry(Paths.get(jarfile));
+ FileUtils.deleteFileTreeWithRetry(Paths.get(usr, "classes"));
}
@Test
// a base entry contains a nested class that doesn't have a matching top level class
- public void test11() throws IOException {
+ public void test11() throws Throwable {
String jarfile = "test.jar";
compile("test01"); //use same data as test01
@@ -409,30 +440,29 @@
source = Paths.get(src, "data", "test10", "v9", "version");
javac(classes.resolve("v9"), source.resolve("Nested.java"));
- jar("cf", jarfile, "-C", classes.resolve("base").toString(), ".",
+ List<String> output = jar("cf", jarfile,
+ "-C", classes.resolve("base").toString(), ".",
"--release", "9", "-C", classes.resolve("v9").toString(), ".")
- .assertFailure()
- .resultChecker(r -> {
- String[] msg = r.output.split("\\R");
- // There should be 3 error messages, cascading from the first. Once we
- // remove the base top level class, the base nested class becomes isolated,
- // also the versioned top level class becomes a new public class, thus ignored
- // for subsequent checks, leading to the associated versioned nested class
- // becoming an isolated nested class
- assertTrue(msg.length == 4);
- assertTrue(msg[0].contains("an isolated nested class"), msg[0]);
- assertTrue(msg[1].contains("contains a new public class"), msg[1]);
- assertTrue(msg[2].contains("an isolated nested class"), msg[2]);
- assertTrue(msg[3].contains("invalid multi-release jar file"), msg[3]);
- });
+ .shouldNotHaveExitValue(SUCCESS)
+ .asLines();
- delete(jarfile);
- deleteDir(Paths.get(usr, "classes"));
+ assertTrue(output.size() == 4);
+ assertTrue(output.get(0).contains("an isolated nested class"),
+ output.get(0));
+ assertTrue(output.get(1).contains("contains a new public class"),
+ output.get(1));
+ assertTrue(output.get(2).contains("an isolated nested class"),
+ output.get(2));
+ assertTrue(output.get(3).contains("invalid multi-release jar file"),
+ output.get(3));
+
+ FileUtils.deleteFileIfExistsWithRetry(Paths.get(jarfile));
+ FileUtils.deleteFileTreeWithRetry(Paths.get(usr, "classes"));
}
@Test
// a versioned entry contains a nested class that doesn't have a matching top level class
- public void test12() throws IOException {
+ public void test12() throws Throwable {
String jarfile = "test.jar";
compile("test01"); //use same data as test01
@@ -452,178 +482,59 @@
jar("cf", jarfile, "-C", classes.resolve("base").toString(), ".",
"--release", "9", "-C", classes.resolve("v9").toString(), ".")
- .assertFailure()
- .resultChecker(r ->
- assertTrue(r.outputContains("an isolated nested class"), r.output)
- );
-
- delete(jarfile);
- deleteDir(Paths.get(usr, "classes"));
- }
-
- /*
- * Test Infrastructure
- */
- private void compile(String test) throws IOException {
- Path classes = Paths.get(usr, "classes", "base");
- Files.createDirectories(classes);
- Path source = Paths.get(src, "data", test, "base", "version");
- javac(classes, source.resolve("Main.java"), source.resolve("Version.java"));
-
- classes = Paths.get(usr, "classes", "v9");
- Files.createDirectories(classes);
- source = Paths.get(src, "data", test, "v9", "version");
- javac(classes, source.resolve("Version.java"));
-
- classes = Paths.get(usr, "classes", "v10");
- Files.createDirectories(classes);
- source = Paths.get(src, "data", test, "v10", "version");
- javac(classes, source.resolve("Version.java"));
- }
-
- private void checkMultiRelease(String jarFile, boolean expected) throws IOException {
- try (JarFile jf = new JarFile(new File(jarFile), true, ZipFile.OPEN_READ,
- JarFile.runtimeVersion())) {
- assertEquals(jf.isMultiRelease(), expected);
- }
- }
+ .shouldNotHaveExitValue(SUCCESS)
+ .shouldContain("an isolated nested class");
- // compares the bytes found in the jar entries with the bytes found in the
- // corresponding data files used to create the entries
- private void compare(String jarfile, Map<String,String[]> names) throws IOException {
- try (JarFile jf = new JarFile(jarfile)) {
- for (String name : names.keySet()) {
- Path path = Paths.get("classes", names.get(name));
- byte[] b1 = Files.readAllBytes(path);
- byte[] b2;
- JarEntry je = jf.getJarEntry(name);
- try (InputStream is = jf.getInputStream(je)) {
- b2 = is.readAllBytes();
- }
- assertEquals(b1,b2);
- }
- }
- }
-
- private void delete(String name) throws IOException {
- Files.deleteIfExists(Paths.get(usr, name));
- }
-
- private void deleteDir(Path dir) throws IOException {
- Files.walkFileTree(dir, new SimpleFileVisitor<Path>() {
- @Override
- public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
- Files.delete(file);
- return FileVisitResult.CONTINUE;
- }
-
- @Override
- public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException {
- Files.delete(dir);
- return FileVisitResult.CONTINUE;
- }
- });
+ FileUtils.deleteFileIfExistsWithRetry(Paths.get(jarfile));
+ FileUtils.deleteFileTreeWithRetry(Paths.get(usr, "classes"));
}
- /*
- * The following methods were taken from modular jar and other jar tests
- */
+ @Test
+ public void testCustomManifest() throws Throwable {
+ String jarfile = "test.jar";
- void javac(Path dest, Path... sourceFiles) throws IOException {
- String javac = JDKToolFinder.getJDKTool("javac");
+ compile("test01");
- List<String> commands = new ArrayList<>();
- commands.add(javac);
- String opts = System.getProperty("test.compiler.opts");
- if (!opts.isEmpty()) {
- commands.addAll(Arrays.asList(opts.split(" +")));
- }
- commands.add("-d");
- commands.add(dest.toString());
- Stream.of(sourceFiles).map(Object::toString).forEach(x -> commands.add(x));
+ Path classes = Paths.get("classes");
+ Path manifest = Paths.get("Manifest.txt");
- quickFail(run(new ProcessBuilder(commands)));
- }
+ // create
+ Files.write(manifest, "Class-Path: MyUtils.jar\n".getBytes());
- Result jarWithStdin(File stdinSource, String... args) {
- String jar = JDKToolFinder.getJDKTool("jar");
- List<String> commands = new ArrayList<>();
- commands.add(jar);
- commands.addAll(Utils.getForwardVmOptions());
- Stream.of(args).forEach(x -> commands.add(x));
- ProcessBuilder p = new ProcessBuilder(commands);
- if (stdinSource != null)
- p.redirectInput(stdinSource);
- return run(p);
- }
+ jar("cfm", jarfile, manifest.toString(),
+ "-C", classes.resolve("base").toString(), ".",
+ "--release", "10", "-C", classes.resolve("v10").toString(), ".")
+ .shouldHaveExitValue(SUCCESS)
+ .shouldBeEmpty();
- Result jar(String... args) {
- return jarWithStdin(null, args);
- }
-
- void quickFail(Result r) {
- if (r.ec != 0)
- throw new RuntimeException(r.output);
- }
-
- Result run(ProcessBuilder pb) {
- Process p;
- out.printf("Running: %s%n", pb.command());
- try {
- p = pb.start();
- } catch (IOException e) {
- throw new RuntimeException(
- format("Couldn't start process '%s'", pb.command()), e);
+ try (JarFile jf = new JarFile(new File(jarfile), true,
+ ZipFile.OPEN_READ, JarFile.runtimeVersion())) {
+ assertTrue(jf.isMultiRelease(), "Not multi-release jar");
+ assertEquals(jf.getManifest()
+ .getMainAttributes()
+ .getValue("Class-Path"),
+ "MyUtils.jar");
}
- String output;
- try {
- output = toString(p.getInputStream(), p.getErrorStream());
- } catch (IOException e) {
- throw new RuntimeException(
- format("Couldn't read process output '%s'", pb.command()), e);
+ // update
+ Files.write(manifest, "Multi-release: false\n".getBytes());
+
+ jar("ufm", jarfile, manifest.toString(),
+ "-C", classes.resolve("base").toString(), ".",
+ "--release", "9", "-C", classes.resolve("v10").toString(), ".")
+ .shouldHaveExitValue(SUCCESS)
+ .shouldContain("WARNING: Duplicate name in Manifest: Multi-release.");
+
+ try (JarFile jf = new JarFile(new File(jarfile), true,
+ ZipFile.OPEN_READ, JarFile.runtimeVersion())) {
+ assertTrue(jf.isMultiRelease(), "Not multi-release jar");
+ assertEquals(jf.getManifest()
+ .getMainAttributes()
+ .getValue("Class-Path"),
+ "MyUtils.jar");
}
- try {
- p.waitFor();
- } catch (InterruptedException e) {
- throw new RuntimeException(
- format("Process hasn't finished '%s'", pb.command()), e);
- }
- return new Result(p.exitValue(), output);
- }
-
- String toString(InputStream in1, InputStream in2) throws IOException {
- try (ByteArrayOutputStream dst = new ByteArrayOutputStream();
- InputStream concatenated = new SequenceInputStream(in1, in2)) {
- concatenated.transferTo(dst);
- return new String(dst.toByteArray(), "UTF-8");
- }
- }
-
- static class Result {
- final int ec;
- final String output;
-
- private Result(int ec, String output) {
- this.ec = ec;
- this.output = output;
- }
-
- boolean outputContains(String msg) {
- return Arrays.stream(output.split("\\R"))
- .collect(Collectors.joining(" "))
- .contains(msg);
- }
-
- Result assertSuccess() {
- assertTrue(ec == 0, format("ec: %d, output: %s", ec, output));
- return this;
- }
- Result assertFailure() {
- assertTrue(ec != 0, format("ec: %d, output: %s", ec, output));
- return this;
- }
- Result resultChecker(Consumer<Result> r) { r.accept(this); return this; }
+ FileUtils.deleteFileIfExistsWithRetry(Paths.get(jarfile));
+ FileUtils.deleteFileTreeWithRetry(Paths.get(usr, "classes"));
}
}
--- a/jdk/test/tools/jar/multiRelease/Basic1.java Fri Jan 20 10:28:34 2017 -0800
+++ b/jdk/test/tools/jar/multiRelease/Basic1.java Fri Jan 20 08:53:42 2017 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2017, 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
@@ -28,76 +28,65 @@
* jdk.compiler
* jdk.jartool
* @build jdk.test.lib.JDKToolFinder jdk.test.lib.Utils
+ * @build MRTestBase
* @run testng Basic1
*/
-import static org.testng.Assert.*;
-
import org.testng.annotations.*;
-import java.io.*;
import java.nio.file.*;
import java.util.*;
-import java.util.function.Consumer;
-import java.util.jar.*;
-import java.util.stream.Collectors;
-import java.util.stream.Stream;
-import java.util.zip.*;
-import jdk.test.lib.JDKToolFinder;
-import jdk.test.lib.Utils;
-
-
-import static java.lang.String.format;
-import static java.lang.System.out;
-
-public class Basic1 {
- private final String src = System.getProperty("test.src", ".");
+public class Basic1 extends MRTestBase {
@BeforeTest
- public void setup() throws IOException {
+ public void setup() throws Throwable {
String test = "test01";
- Path classes = Paths.get("classes", "base");
- Files.createDirectories(classes);
+ Path classes = Paths.get("classes");
+
+ Path base = classes.resolve("base");
+ Files.createDirectories(base);
Path source = Paths.get(src, "data", test, "base", "version");
- javac(classes, source.resolve("Main.java"), source.resolve("Version.java"));
+ javac(base, source.resolve("Main.java"), source.resolve("Version.java"));
- Path v9 = Paths.get("v9");
+ Path v9 = classes.resolve("v9");
Files.createDirectories(v9);
source = Paths.get(src, "data", test, "v9", "version");
javac(v9, source.resolve("Version.java"));
- Path v10 = Paths.get("v10");
+ Path v10 = classes.resolve("v10");
Files.createDirectories(v10);
source = Paths.get(src, "data", test, "v10", "version");
javac(v10, source.resolve("Version.java"));
- Path v10_1 = Paths.get("v10_1").resolve("META-INF").resolve("versions").resolve("v10");
+ Path v10_1 = classes.resolve("v10_1").resolve("META-INF").resolve("versions").resolve("v10");
Files.createDirectories(v10_1);
source = Paths.get(src, "data", test, "v10", "version");
javac(v10_1, source.resolve("Version.java"));
}
@Test
- public void test() throws IOException {
+ public void test() throws Throwable {
String jarfile = "test.jar";
Path classes = Paths.get("classes");
- Path v9 = Paths.get("v9");
- Path v10 = Paths.get("v10");
+
+ Path base = classes.resolve("base");
+ Path v9 = classes.resolve("v9");
+ Path v10 = classes.resolve("v10");
- jar("cf", jarfile, "-C", classes.resolve("base").toString(), ".",
- "--release", "9", "-C", v9.toString(), ".",
- "--release", "10", "-C", v10.toString(), ".")
- .assertSuccess();
+ jar("cf", jarfile, "-C", base.toString(), ".",
+ "--release", "9", "-C", v9.toString(), ".",
+ "--release", "10", "-C", v10.toString(), ".")
+ .shouldHaveExitValue(SUCCESS);
checkMultiRelease(jarfile, true);
- Map<String,String[]> names = Map.of(
- "version/Main.class",
- new String[] {"classes", "base", "version", "Main.class"},
+ Map<String, String[]> names = Map.of(
+ "version/Main.class",
+ new String[]{"base", "version", "Main.class"},
- "version/Version.class",
- new String[] {"classes", "base", "version", "Version.class"},
+ "version/Version.class",
+ new String[]{"base", "version", "Version.class"},
"META-INF/versions/9/version/Version.class",
new String[] {"v9", "version", "Version.class"},
@@ -109,144 +98,16 @@
compare(jarfile, names);
}
-
@Test
- public void testFail() throws IOException {
+ public void testFail() throws Throwable {
String jarfile = "test.jar";
Path classes = Paths.get("classes");
- Path v10 = Paths.get("v10_1");
-
- jar("cf", jarfile, "-C", classes.resolve("base").toString(), ".",
- "--release", "10", "-C", v10.toString(), ".")
- .assertFailure()
- .outputContains("unexpected versioned entry META-INF/versions/");
- }
-
-
-
- private void checkMultiRelease(String jarFile, boolean expected) throws IOException {
- try (JarFile jf = new JarFile(new File(jarFile), true, ZipFile.OPEN_READ,
- JarFile.runtimeVersion())) {
- assertEquals(jf.isMultiRelease(), expected);
- }
- }
-
- // compares the bytes found in the jar entries with the bytes found in the
- // corresponding data files used to create the entries
- private void compare(String jarfile, Map<String,String[]> names) throws IOException {
- try (JarFile jf = new JarFile(jarfile)) {
- for (String name : names.keySet()) {
- Path path = Paths.get("", names.get(name));
- byte[] b1 = Files.readAllBytes(path);
- byte[] b2;
- JarEntry je = jf.getJarEntry(name);
- try (InputStream is = jf.getInputStream(je)) {
- b2 = is.readAllBytes();
- }
- assertEquals(b1,b2);
- }
- }
- }
-
- /*
- * The following methods were taken from modular jar and other jar tests
- */
-
- void javac(Path dest, Path... sourceFiles) throws IOException {
- String javac = JDKToolFinder.getJDKTool("javac");
-
- List<String> commands = new ArrayList<>();
- commands.add(javac);
- String opts = System.getProperty("test.compiler.opts");
- if (!opts.isEmpty()) {
- commands.addAll(Arrays.asList(opts.split(" +")));
- }
- commands.add("-d");
- commands.add(dest.toString());
- Stream.of(sourceFiles).map(Object::toString).forEach(x -> commands.add(x));
-
- quickFail(run(new ProcessBuilder(commands)));
- }
-
- Result jarWithStdin(File stdinSource, String... args) {
- String jar = JDKToolFinder.getJDKTool("jar");
- List<String> commands = new ArrayList<>();
- commands.add(jar);
- commands.addAll(Utils.getForwardVmOptions());
- Stream.of(args).forEach(x -> commands.add(x));
- ProcessBuilder p = new ProcessBuilder(commands);
- if (stdinSource != null)
- p.redirectInput(stdinSource);
- return run(p);
- }
+ Path base = classes.resolve("base");
+ Path v10 = classes.resolve("v10_1");
- Result jar(String... args) {
- return jarWithStdin(null, args);
- }
-
- void quickFail(Result r) {
- if (r.ec != 0)
- throw new RuntimeException(r.output);
- }
-
- Result run(ProcessBuilder pb) {
- Process p;
- out.printf("Running: %s%n", pb.command());
- try {
- p = pb.start();
- } catch (IOException e) {
- throw new RuntimeException(
- format("Couldn't start process '%s'", pb.command()), e);
- }
-
- String output;
- try {
- output = toString(p.getInputStream(), p.getErrorStream());
- } catch (IOException e) {
- throw new RuntimeException(
- format("Couldn't read process output '%s'", pb.command()), e);
- }
-
- try {
- p.waitFor();
- } catch (InterruptedException e) {
- throw new RuntimeException(
- format("Process hasn't finished '%s'", pb.command()), e);
- }
- return new Result(p.exitValue(), output);
- }
-
- String toString(InputStream in1, InputStream in2) throws IOException {
- try (ByteArrayOutputStream dst = new ByteArrayOutputStream();
- InputStream concatenated = new SequenceInputStream(in1, in2)) {
- concatenated.transferTo(dst);
- return new String(dst.toByteArray(), "UTF-8");
- }
- }
-
- static class Result {
- final int ec;
- final String output;
-
- private Result(int ec, String output) {
- this.ec = ec;
- this.output = output;
- }
-
- boolean outputContains(String msg) {
- return Arrays.stream(output.split("\\R"))
- .collect(Collectors.joining(" "))
- .contains(msg);
- }
-
- Result assertSuccess() {
- assertTrue(ec == 0, format("ec: %d, output: %s", ec, output));
- return this;
- }
- Result assertFailure() {
- assertTrue(ec != 0, format("ec: %d, output: %s", ec, output));
- return this;
- }
- Result resultChecker(Consumer<Result> r) { r.accept(this); return this; }
+ jar("cf", jarfile, "-C", base.toString(), ".",
+ "--release", "10", "-C", v10.toString(), ".")
+ .shouldNotHaveExitValue(SUCCESS)
+ .shouldContain("unexpected versioned entry META-INF/versions/");
}
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/tools/jar/multiRelease/MRTestBase.java Fri Jan 20 08:53:42 2017 -0800
@@ -0,0 +1,130 @@
+/*
+ * Copyright (c) 2017, 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.
+ */
+
+import jdk.test.lib.JDKToolFinder;
+import jdk.test.lib.Utils;
+import jdk.test.lib.process.OutputAnalyzer;
+import jdk.test.lib.process.ProcessTools;
+
+import java.io.*;
+import java.nio.file.*;
+import java.nio.file.attribute.BasicFileAttributes;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+import java.util.jar.JarEntry;
+import java.util.jar.JarFile;
+import java.util.stream.Stream;
+import java.util.zip.ZipFile;
+
+import static org.testng.Assert.assertEquals;
+
+public class MRTestBase {
+
+ public static final int SUCCESS = 0;
+
+ protected final String src = System.getProperty("test.src", ".");
+ protected final String usr = System.getProperty("user.dir", ".");
+
+ protected void compile(String test) throws Throwable {
+ Path classes = Paths.get(usr, "classes", "base");
+ Files.createDirectories(classes);
+ Path source = Paths.get(src, "data", test, "base", "version");
+ javac(classes, source.resolve("Main.java"), source.resolve("Version.java"));
+
+ classes = Paths.get(usr, "classes", "v9");
+ Files.createDirectories(classes);
+ source = Paths.get(src, "data", test, "v9", "version");
+ javac(classes, source.resolve("Version.java"));
+
+ classes = Paths.get(usr, "classes", "v10");
+ Files.createDirectories(classes);
+ source = Paths.get(src, "data", test, "v10", "version");
+ javac(classes, source.resolve("Version.java"));
+ }
+
+ protected void checkMultiRelease(String jarFile,
+ boolean expected) throws IOException {
+ try (JarFile jf = new JarFile(new File(jarFile), true,
+ ZipFile.OPEN_READ, JarFile.runtimeVersion())) {
+ assertEquals(jf.isMultiRelease(), expected);
+ }
+ }
+
+ // compares the bytes found in the jar entries with the bytes found in the
+ // corresponding data files used to create the entries
+ protected void compare(String jarfile,
+ Map<String, String[]> names) throws IOException {
+ try (JarFile jf = new JarFile(jarfile)) {
+ for (String name : names.keySet()) {
+ Path path = Paths.get("classes", names.get(name));
+ byte[] b1 = Files.readAllBytes(path);
+ byte[] b2;
+ JarEntry je = jf.getJarEntry(name);
+ try (InputStream is = jf.getInputStream(je)) {
+ b2 = is.readAllBytes();
+ }
+ assertEquals(b1, b2);
+ }
+ }
+ }
+
+ void javac(Path dest, Path... sourceFiles) throws Throwable {
+ String javac = JDKToolFinder.getJDKTool("javac");
+
+ List<String> commands = new ArrayList<>();
+ commands.add(javac);
+ String opts = System.getProperty("test.compiler.opts");
+ if (!opts.isEmpty()) {
+ commands.addAll(Arrays.asList(opts.split(" +")));
+ }
+ commands.addAll(Utils.getForwardVmOptions());
+ commands.add("-d");
+ commands.add(dest.toString());
+ Stream.of(sourceFiles)
+ .map(Object::toString)
+ .forEach(x -> commands.add(x));
+
+ ProcessTools.executeCommand(new ProcessBuilder(commands))
+ .shouldHaveExitValue(SUCCESS);
+ }
+
+ OutputAnalyzer jarWithStdin(File stdinSource,
+ String... args) throws Throwable {
+
+ String jar = JDKToolFinder.getJDKTool("jar");
+ List<String> commands = new ArrayList<>();
+ commands.add(jar);
+ commands.addAll(Utils.getForwardVmOptions());
+ Stream.of(args).forEach(x -> commands.add(x));
+ ProcessBuilder p = new ProcessBuilder(commands);
+ if (stdinSource != null)
+ p.redirectInput(stdinSource);
+ return ProcessTools.executeCommand(p);
+ }
+
+ OutputAnalyzer jar(String... args) throws Throwable {
+ return jarWithStdin(null, args);
+ }
+}
\ No newline at end of file
--- a/jdk/test/tools/jar/multiRelease/data/test04/v9/version/Version.java Fri Jan 20 10:28:34 2017 -0800
+++ b/jdk/test/tools/jar/multiRelease/data/test04/v9/version/Version.java Fri Jan 20 08:53:42 2017 -0800
@@ -8,7 +8,7 @@
protected void doNothing() {
}
- // extra publc method
+ // extra public method
public void anyName() {
}
}
--- a/jdk/test/tools/jlink/DefaultProviderTest.java Fri Jan 20 10:28:34 2017 -0800
+++ b/jdk/test/tools/jlink/DefaultProviderTest.java Fri Jan 20 08:53:42 2017 -0800
@@ -44,6 +44,7 @@
* @modules java.base/jdk.internal.jimage
* jdk.jdeps/com.sun.tools.classfile
* jdk.jlink/jdk.tools.jlink.internal
+ * jdk.jlink/jdk.tools.jlink.plugin
* jdk.jlink/jdk.tools.jmod
* jdk.jlink/jdk.tools.jimage
* jdk.compiler
--- a/jdk/test/tools/jlink/ImageFileCreatorTest.java Fri Jan 20 10:28:34 2017 -0800
+++ b/jdk/test/tools/jlink/ImageFileCreatorTest.java Fri Jan 20 08:53:42 2017 -0800
@@ -48,6 +48,7 @@
* @author Jean-Francois Denise
* @modules jdk.jlink/jdk.tools.jlink.internal
* jdk.jlink/jdk.tools.jlink.builder
+ * jdk.jlink/jdk.tools.jlink.plugin
* java.base/jdk.internal.jimage
* @run main/othervm -verbose:gc -Xmx1g ImageFileCreatorTest
*/
--- a/jdk/test/tools/jlink/ImageFilePoolTest.java Fri Jan 20 10:28:34 2017 -0800
+++ b/jdk/test/tools/jlink/ImageFilePoolTest.java Fri Jan 20 08:53:42 2017 -0800
@@ -26,6 +26,7 @@
* @summary Test a pool containing external files.
* @author Andrei Eremeev
* @modules jdk.jlink/jdk.tools.jlink.internal
+ * jdk.jlink/jdk.tools.jlink.plugin
* @run build ImageFilePoolTest
* @run main ImageFilePoolTest
*/
--- a/jdk/test/tools/jlink/IntegrationTest.java Fri Jan 20 10:28:34 2017 -0800
+++ b/jdk/test/tools/jlink/IntegrationTest.java Fri Jan 20 08:53:42 2017 -0800
@@ -62,6 +62,7 @@
* jdk.jlink/jdk.tools.jlink.builder
* jdk.jlink/jdk.tools.jlink.internal
* jdk.jlink/jdk.tools.jlink.internal.plugins
+ * jdk.jlink/jdk.tools.jlink.plugin
* jdk.jlink/jdk.tools.jmod
* jdk.jlink/jdk.tools.jimage
* jdk.compiler
--- a/jdk/test/tools/jlink/JLink2Test.java Fri Jan 20 10:28:34 2017 -0800
+++ b/jdk/test/tools/jlink/JLink2Test.java Fri Jan 20 08:53:42 2017 -0800
@@ -29,6 +29,7 @@
* @modules java.base/jdk.internal.jimage
* jdk.jdeps/com.sun.tools.classfile
* jdk.jlink/jdk.tools.jlink.internal
+ * jdk.jlink/jdk.tools.jlink.plugin
* jdk.jlink/jdk.tools.jmod
* jdk.jlink/jdk.tools.jimage
* jdk.compiler
--- a/jdk/test/tools/jlink/JLinkOptionsTest.java Fri Jan 20 10:28:34 2017 -0800
+++ b/jdk/test/tools/jlink/JLinkOptionsTest.java Fri Jan 20 08:53:42 2017 -0800
@@ -39,6 +39,7 @@
* @modules java.base/jdk.internal.jimage
* jdk.jdeps/com.sun.tools.classfile
* jdk.jlink/jdk.tools.jlink.internal
+ * jdk.jlink/jdk.tools.jlink.plugin
* jdk.jlink/jdk.tools.jmod
* jdk.jlink/jdk.tools.jimage
* jdk.compiler
--- a/jdk/test/tools/jlink/JLinkPostProcessingTest.java Fri Jan 20 10:28:34 2017 -0800
+++ b/jdk/test/tools/jlink/JLinkPostProcessingTest.java Fri Jan 20 08:53:42 2017 -0800
@@ -46,6 +46,7 @@
* @modules java.base/jdk.internal.jimage
* jdk.jdeps/com.sun.tools.classfile
* jdk.jlink/jdk.tools.jlink.internal
+ * jdk.jlink/jdk.tools.jlink.plugin
* jdk.jlink/jdk.tools.jmod
* jdk.jlink/jdk.tools.jimage
* jdk.compiler
--- a/jdk/test/tools/jlink/JLinkTest.java Fri Jan 20 10:28:34 2017 -0800
+++ b/jdk/test/tools/jlink/JLinkTest.java Fri Jan 20 08:53:42 2017 -0800
@@ -48,6 +48,7 @@
* @modules java.base/jdk.internal.jimage
* jdk.jdeps/com.sun.tools.classfile
* jdk.jlink/jdk.tools.jlink.internal
+ * jdk.jlink/jdk.tools.jlink.plugin
* jdk.jlink/jdk.tools.jimage
* jdk.compiler
* @build tests.*
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/tools/jlink/ResourceDuplicateCheckTest.java Fri Jan 20 08:53:42 2017 -0800
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2017, 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 8168254
+ * @summary Detect duplicated resources in packaged modules
+ * @modules jdk.jlink/jdk.tools.jlink.builder
+ * jdk.jlink/jdk.tools.jlink.internal
+ * jdk.jlink/jdk.tools.jlink.plugin
+ * @run build ResourceDuplicateCheckTest
+ * @run main ResourceDuplicateCheckTest
+ */
+
+import java.net.URI;
+import java.nio.file.FileSystems;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.Collections;
+import jdk.tools.jlink.builder.DefaultImageBuilder;
+import jdk.tools.jlink.internal.ResourcePoolEntryFactory;
+import jdk.tools.jlink.internal.ResourcePoolManager;
+import jdk.tools.jlink.plugin.PluginException;
+import jdk.tools.jlink.plugin.ResourcePoolEntry;
+
+public class ResourceDuplicateCheckTest {
+ public static void main(String[] args) throws Exception {
+ new ResourceDuplicateCheckTest().test();
+ }
+
+ public void test() throws Exception {
+ ResourcePoolManager input = new ResourcePoolManager();
+ // need java.base module info because OS name is retrieved from it from storeFiles
+ input.add(ResourcePoolEntryFactory.create("/java.base/module-info.class",
+ ResourcePoolEntry.Type.CLASS_OR_RESOURCE, getJavaBaseModuleInfo()));
+
+ // same NATIVE_CMD from two different modules
+ input.add(newInMemoryImageFile("/com.acme/bin/myexec",
+ ResourcePoolEntry.Type.NATIVE_CMD, "mylib"));
+ input.add(newInMemoryImageFile("/com.foo/bin/myexec",
+ ResourcePoolEntry.Type.NATIVE_CMD, "mylib"));
+ Path root = Paths.get(System.getProperty("test.classes"));
+ DefaultImageBuilder writer = new DefaultImageBuilder(root, Collections.emptyMap());
+ try {
+ writer.storeFiles(input.resourcePool());
+ } catch (PluginException pe) {
+ if (! pe.getMessage().contains("Duplicate resources:")) {
+ throw new AssertionError("expected duplicate resources message");
+ }
+ }
+ }
+
+ private byte[] getJavaBaseModuleInfo() throws Exception {
+ Path path = FileSystems.
+ getFileSystem(URI.create("jrt:/")).
+ getPath("/modules/java.base/module-info.class");
+ return Files.readAllBytes(path);
+ }
+
+ private static ResourcePoolEntry newInMemoryImageFile(String path,
+ ResourcePoolEntry.Type type, String content) {
+ return ResourcePoolEntryFactory.create(path, type, content.getBytes());
+ }
+}
--- a/jdk/test/tools/jlink/ResourcePoolTest.java Fri Jan 20 10:28:34 2017 -0800
+++ b/jdk/test/tools/jlink/ResourcePoolTest.java Fri Jan 20 08:53:42 2017 -0800
@@ -26,6 +26,7 @@
* @summary Test a pool containing jimage resources and classes.
* @author Jean-Francois Denise
* @modules jdk.jlink/jdk.tools.jlink.internal
+ * jdk.jlink/jdk.tools.jlink.plugin
* @run build ResourcePoolTest
* @run main ResourcePoolTest
*/
--- a/jdk/test/tools/jlink/plugins/CompressorPluginTest.java Fri Jan 20 10:28:34 2017 -0800
+++ b/jdk/test/tools/jlink/plugins/CompressorPluginTest.java Fri Jan 20 08:53:42 2017 -0800
@@ -28,6 +28,7 @@
* @modules java.base/jdk.internal.jimage.decompressor
* jdk.jlink/jdk.tools.jlink.internal
* jdk.jlink/jdk.tools.jlink.internal.plugins
+ * jdk.jlink/jdk.tools.jlink.plugin
* @run main CompressorPluginTest
*/
import java.net.URI;
--- a/jdk/test/tools/jlink/plugins/ExcludeFilesPluginTest.java Fri Jan 20 10:28:34 2017 -0800
+++ b/jdk/test/tools/jlink/plugins/ExcludeFilesPluginTest.java Fri Jan 20 08:53:42 2017 -0800
@@ -27,6 +27,7 @@
* @author Jean-Francois Denise
* @modules jdk.jlink/jdk.tools.jlink.internal
* jdk.jlink/jdk.tools.jlink.internal.plugins
+ * jdk.jlink/jdk.tools.jlink.plugin
* @run main ExcludeFilesPluginTest
*/
--- a/jdk/test/tools/jlink/plugins/ExcludePluginTest.java Fri Jan 20 10:28:34 2017 -0800
+++ b/jdk/test/tools/jlink/plugins/ExcludePluginTest.java Fri Jan 20 08:53:42 2017 -0800
@@ -27,6 +27,7 @@
* @author Jean-Francois Denise
* @modules jdk.jlink/jdk.tools.jlink.internal
* jdk.jlink/jdk.tools.jlink.internal.plugins
+ * jdk.jlink/jdk.tools.jlink.plugin
* @run main ExcludePluginTest
*/
--- a/jdk/test/tools/jlink/plugins/ExcludeVMPluginTest.java Fri Jan 20 10:28:34 2017 -0800
+++ b/jdk/test/tools/jlink/plugins/ExcludeVMPluginTest.java Fri Jan 20 08:53:42 2017 -0800
@@ -27,6 +27,7 @@
* @author Jean-Francois Denise
* @modules jdk.jlink/jdk.tools.jlink.internal
* jdk.jlink/jdk.tools.jlink.internal.plugins
+ * jdk.jlink/jdk.tools.jlink.plugin
* @run main ExcludeVMPluginTest
*/
import java.io.ByteArrayInputStream;
--- a/jdk/test/tools/jlink/plugins/IncludeLocalesPluginTest.java Fri Jan 20 10:28:34 2017 -0800
+++ b/jdk/test/tools/jlink/plugins/IncludeLocalesPluginTest.java Fri Jan 20 08:53:42 2017 -0800
@@ -48,6 +48,7 @@
* jdk.jdeps/com.sun.tools.classfile
* jdk.jlink/jdk.tools.jlink.internal
* jdk.jlink/jdk.tools.jlink.internal.plugins
+ * jdk.jlink/jdk.tools.jlink.plugin
* jdk.jlink/jdk.tools.jmod
* jdk.jlink/jdk.tools.jimage
* jdk.compiler
--- a/jdk/test/tools/jlink/plugins/LastSorterTest.java Fri Jan 20 10:28:34 2017 -0800
+++ b/jdk/test/tools/jlink/plugins/LastSorterTest.java Fri Jan 20 08:53:42 2017 -0800
@@ -25,8 +25,9 @@
* @test
* @summary Test last sorter property
* @author Jean-Francois Denise
- * @modules jdk.jlink/jdk.tools.jlink.internal
- * jdk.jlink/jdk.tools.jlink
+ * @modules jdk.jlink/jdk.tools.jlink
+ * jdk.jlink/jdk.tools.jlink.internal
+ * jdk.jlink/jdk.tools.jlink.plugin
* @run main/othervm LastSorterTest
*/
--- a/jdk/test/tools/jlink/plugins/PluginsNegativeTest.java Fri Jan 20 10:28:34 2017 -0800
+++ b/jdk/test/tools/jlink/plugins/PluginsNegativeTest.java Fri Jan 20 08:53:42 2017 -0800
@@ -25,8 +25,9 @@
* @test
* @summary Negative test for ImagePluginStack.
* @author Andrei Eremeev
- * @modules jdk.jlink/jdk.tools.jlink.internal
- * jdk.jlink/jdk.tools.jlink
+ * @modules jdk.jlink/jdk.tools.jlink
+ * jdk.jlink/jdk.tools.jlink.internal
+ * jdk.jlink/jdk.tools.jlink.plugin
* @run main/othervm PluginsNegativeTest
*/
import java.lang.reflect.Layer;
--- a/jdk/test/tools/jlink/plugins/PrevisitorTest.java Fri Jan 20 10:28:34 2017 -0800
+++ b/jdk/test/tools/jlink/plugins/PrevisitorTest.java Fri Jan 20 08:53:42 2017 -0800
@@ -25,8 +25,9 @@
* @test
* @summary Test previsitor
* @author Andrei Eremeev
- * @modules jdk.jlink/jdk.tools.jlink.internal
- * jdk.jlink/jdk.tools.jlink
+ * @modules jdk.jlink/jdk.tools.jlink
+ * jdk.jlink/jdk.tools.jlink.internal
+ * jdk.jlink/jdk.tools.jlink.plugin
* @run main/othervm PrevisitorTest
*/
import java.nio.ByteOrder;
--- a/jdk/test/tools/jlink/plugins/StringSharingPluginTest.java Fri Jan 20 10:28:34 2017 -0800
+++ b/jdk/test/tools/jlink/plugins/StringSharingPluginTest.java Fri Jan 20 08:53:42 2017 -0800
@@ -30,6 +30,7 @@
* java.base/jdk.internal.jimage.decompressor
* jdk.jlink/jdk.tools.jlink.internal
* jdk.jlink/jdk.tools.jlink.internal.plugins
+ * jdk.jlink/jdk.tools.jlink.plugin
* jdk.jlink/jdk.tools.jmod
* jdk.jlink/jdk.tools.jimage
* jdk.jdeps/com.sun.tools.classfile
--- a/jdk/test/tools/jlink/plugins/StripDebugPluginTest.java Fri Jan 20 10:28:34 2017 -0800
+++ b/jdk/test/tools/jlink/plugins/StripDebugPluginTest.java Fri Jan 20 08:53:42 2017 -0800
@@ -30,6 +30,7 @@
* @modules java.base/jdk.internal.jimage
* jdk.jlink/jdk.tools.jlink.internal
* jdk.jlink/jdk.tools.jlink.internal.plugins
+ * jdk.jlink/jdk.tools.jlink.plugin
* jdk.jlink/jdk.tools.jimage
* jdk.jlink/jdk.tools.jmod
* jdk.jdeps/com.sun.tools.classfile
--- a/jdk/test/tools/jmod/JmodTest.java Fri Jan 20 10:28:34 2017 -0800
+++ b/jdk/test/tools/jmod/JmodTest.java Fri Jan 20 08:53:42 2017 -0800
@@ -29,7 +29,7 @@
* @modules jdk.compiler
* jdk.jlink
* @build jdk.testlibrary.FileUtils CompilerUtils
- * @run testng JmodTest
+ * @run testng/othervm -Djava.io.tmpdir=. JmodTest
*/
import java.io.*;
@@ -40,8 +40,10 @@
import java.util.function.Consumer;
import java.util.regex.Pattern;
import java.util.spi.ToolProvider;
+import java.util.stream.Collectors;
import java.util.stream.Stream;
import jdk.testlibrary.FileUtils;
+import jdk.testlibrary.JDKToolFinder;
import org.testng.annotations.BeforeTest;
import org.testng.annotations.Test;
@@ -593,9 +595,7 @@
findTmpFiles(filename).forEach(tmp -> {
try {
FileUtils.deleteFileIfExistsWithRetry(tmp);
- } catch (IOException e) {
- throw new UncheckedIOException(e);
- }
+ } catch (IOException e) {}
});
String cp = EXPLODED_DIR.resolve("foo").resolve("classes") + File.pathSeparator +
@@ -608,17 +608,25 @@
.assertFailure()
.resultChecker(r -> {
assertContains(r.output, "unnamed package");
- Set<Path> tmpfiles = findTmpFiles(filename).collect(toSet());
+ List<Path> tmpfiles = findTmpFiles(filename);
assertTrue(tmpfiles.isEmpty(), "Unexpected tmp file:" + tmpfiles);
});
}
- private Stream<Path> findTmpFiles(String prefix) {
- try {
- Path tmpdir = Paths.get(System.getProperty("java.io.tmpdir"));
- return Files.find(tmpdir, 1, (p, attrs) ->
- p.getFileName().toString().startsWith(prefix)
- && p.getFileName().toString().endsWith(".tmp"));
+ /*
+ * Returns the list of writeable tmp files with the given prefix.
+ *
+ * Ignore the non-writeable tmp files because this test is possibly
+ * running by another user.
+ */
+ private List<Path> findTmpFiles(String prefix) {
+ Path tmpdir = Paths.get(System.getProperty("java.io.tmpdir"));
+ try (Stream<Path> stream = Files.list(tmpdir)) {
+ return stream.filter(p -> {
+ String fn = p.getFileName().toString();
+ return Files.isWritable(p)
+ && fn.startsWith(prefix) && fn.endsWith(".tmp");
+ }).collect(Collectors.toList());
} catch (IOException e) {
throw new UncheckedIOException(e);
}
--- a/jdk/test/tools/pack200/Utils.java Fri Jan 20 10:28:34 2017 -0800
+++ b/jdk/test/tools/pack200/Utils.java Fri Jan 20 08:53:42 2017 -0800
@@ -111,6 +111,7 @@
compiler("-d",
XCLASSES.getName(),
+ "--add-modules=jdk.jdeps",
"--add-exports=jdk.jdeps/com.sun.tools.classfile=ALL-UNNAMED",
"@" + tmpFile.getAbsolutePath());