From 9a05abd6a9ca3c95e28f8e07bb2ba59c22124964 Mon Sep 17 00:00:00 2001 From: Peter Bain Date: Mon, 5 Nov 2018 14:38:15 -0500 Subject: [PATCH 1/2] Fix checking method handle access Use the defining class of a class member or the reference class of the lookup as appropriate. Also reinstate missing external message definition. Signed-off-by: Peter Bain --- .../ExternalMessages-MasterIndex.properties | 1 + .../java/lang/invoke/MethodHandles.java | 36 ++++++++++++------- 2 files changed, 24 insertions(+), 13 deletions(-) diff --git a/jcl/src/java.base/share/classes/com/ibm/oti/util/ExternalMessages-MasterIndex.properties b/jcl/src/java.base/share/classes/com/ibm/oti/util/ExternalMessages-MasterIndex.properties index 4c28554c32b..ee04f879cdb 100644 --- a/jcl/src/java.base/share/classes/com/ibm/oti/util/ExternalMessages-MasterIndex.properties +++ b/jcl/src/java.base/share/classes/com/ibm/oti/util/ExternalMessages-MasterIndex.properties @@ -1038,6 +1038,7 @@ K0584="The target is not a direct handle" K0585="{0} could not access {1} - private access required" K0586="Lookup class ({0}) must be the same as or subclass of the current class ({1})" +K0587= '{0}' no access to: '{1}' K0588="Illegal Lookup object - originated from java.lang.invoke: {0}" K0589="Caller-sensitive method cannot be looked up using a restricted lookup object" K0590="Can't unreflect @SignaturePolymorphic method: {0}" diff --git a/jcl/src/java.base/share/classes/java/lang/invoke/MethodHandles.java b/jcl/src/java.base/share/classes/java/lang/invoke/MethodHandles.java index 0b60da064d7..a590b7de6fd 100644 --- a/jcl/src/java.base/share/classes/java/lang/invoke/MethodHandles.java +++ b/jcl/src/java.base/share/classes/java/lang/invoke/MethodHandles.java @@ -364,7 +364,12 @@ void checkAccess(MethodHandle handle, boolean skipAccessCheckPara) throws Illega throw new IllegalAccessException(this.toString()); } - checkAccess(handle.getDefc(), handle.getMethodName(), handle.getModifiers(), handle, skipAccessCheckPara); + /* defc (defining class) may be a superclass of the references class. + * Note that we need to check against the requested class, which may have inherited + * the method from an inaccessible class. Protected members of a subclass are accessible to + * a superclass provided they are inherited from the superclass. + */ + checkAccess(handle.getDefc(), handle.getReferenceClass(), handle.getMethodName(), handle.getModifiers(), handle, skipAccessCheckPara); } /*[IF Sidecar19-SE]*/ @@ -378,7 +383,8 @@ void checkAccess(VarHandle handle, boolean skipAccessCheckPara) throws IllegalAc throw new IllegalAccessException(this.toString()); } - checkAccess(handle.getDefiningClass(), handle.getFieldName(), handle.getModifiers(), null, skipAccessCheckPara); + final Class definingClass = handle.getDefiningClass(); + checkAccess(definingClass, definingClass, handle.getFieldName(), handle.getModifiers(), null, skipAccessCheckPara); } void checkAccess(Class clazz) throws IllegalAccessException { @@ -396,10 +402,11 @@ void checkAccess(Class clazz) throws IllegalAccessException { /*[ENDIF]*/ /** - * Checks whether {@link #accessClass} can access a specific member of the {@code targetClass}. + * Checks whether {@link #accessClass} can access a specific member of the {@code referenceClass}. * Equivalent of visible.c checkVisibility(); * - * @param targetClass The {@link Class} that owns the member being accessed. + * @param definingClass The {@link Class} that defines the member being accessed. + * @param referenceClass The {@link Class} class through which the the member is accessed, which may be a subtype of the defining class. * @param name The name of member being accessed. * @param memberModifiers The modifiers of the member being accessed. * @param handle A handle object (e.g. {@link MethodHandle} or {@link VarHandle}), if applicable. @@ -410,8 +417,8 @@ void checkAccess(Class clazz) throws IllegalAccessException { * @throws IllegalAccessException If the member is not accessible. * @throws IllegalAccessError If a handle argument or return type is not accessible. */ - private void checkAccess(Class targetClass, String name, int memberModifiers, MethodHandle handle, boolean skipAccessCheckPara) throws IllegalAccessException { - checkClassAccess(targetClass); + private void checkAccess(Class definingClass, Class referenceClass, String name, int memberModifiers, MethodHandle handle, boolean skipAccessCheckPara) throws IllegalAccessException { + checkClassAccess(referenceClass); /*[IF Sidecar19-SE]*/ if (null != handle && !skipAccessCheckPara) { @@ -434,9 +441,9 @@ private void checkAccess(Class targetClass, String name, int memberModifiers, /* checkClassAccess already determined that we have more than "no access" (public access) */ return; } else if (Modifier.isPrivate(memberModifiers)) { - if (Modifier.isPrivate(accessMode) && ((targetClass == accessClass) + if (Modifier.isPrivate(accessMode) && ((definingClass == accessClass) /*[IF Java11]*/ - || targetClass.isNestmateOf(accessClass) + || definingClass.isNestmateOf(accessClass) /*[ENDIF] Java11*/ )) { return; @@ -444,12 +451,12 @@ private void checkAccess(Class targetClass, String name, int memberModifiers, } else if (Modifier.isProtected(memberModifiers)) { /* Ensure that the accessMode is not restricted (public-only) */ if (PUBLIC != accessMode) { - if (targetClass.isArray()) { + if (definingClass.isArray()) { /* The only methods array classes have are defined on Object and thus accessible */ return; } - if (isSamePackage(accessClass, targetClass)) { + if (isSamePackage(accessClass, referenceClass)) { /* Package access is enough if the classes are in the same package */ return; } @@ -459,7 +466,9 @@ private void checkAccess(Class targetClass, String name, int memberModifiers, * protected methods in java.lang.Object as subclasses. */ /*[ENDIF]*/ - if (!accessClass.isInterface() && Modifier.isProtected(accessMode) && targetClass.isAssignableFrom(accessClass)) { + if (!accessClass.isInterface() && Modifier.isProtected(accessMode) + && definingClass.isAssignableFrom(accessClass) + ) { /* Special handling for MethodHandles */ if (null != handle) { byte kind = handle.kind; @@ -497,7 +506,7 @@ private void checkAccess(Class targetClass, String name, int memberModifiers, } } else { /* default (package access) */ - if ((PACKAGE == (accessMode & PACKAGE)) && isSamePackage(accessClass, targetClass)){ + if ((PACKAGE == (accessMode & PACKAGE)) && isSamePackage(accessClass, referenceClass)){ return; } } @@ -509,7 +518,8 @@ private void checkAccess(Class targetClass, String name, int memberModifiers, } else { extraInfo = "." + name; //$NON-NLS-1$ } - String errorMessage = com.ibm.oti.util.Msg.getString("K0587", this.toString(), targetClass.getName() + extraInfo); //$NON-NLS-1$ + /*[MSG "K0587", "'{0}' no access to: '{1}'"]*/ + String errorMessage = com.ibm.oti.util.Msg.getString("K0587", this.toString(), definingClass.getName() + extraInfo); //$NON-NLS-1$ throw new IllegalAccessException(errorMessage); } From e628544966f5a1c7542cc5fdbff88d457bb13e86 Mon Sep 17 00:00:00 2001 From: Peter Bain Date: Mon, 14 Jan 2019 09:01:08 -0500 Subject: [PATCH 2/2] MethodHandles.checkAccess: null check referenceClass The reference class may be null in the case of varhandles. Signed-off-by: Peter Bain --- .../oti/util/ExternalMessages-MasterIndex.properties | 2 +- .../share/classes/java/lang/invoke/MethodHandles.java | 10 +++++++--- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/jcl/src/java.base/share/classes/com/ibm/oti/util/ExternalMessages-MasterIndex.properties b/jcl/src/java.base/share/classes/com/ibm/oti/util/ExternalMessages-MasterIndex.properties index ee04f879cdb..5aa7b6ebd88 100644 --- a/jcl/src/java.base/share/classes/com/ibm/oti/util/ExternalMessages-MasterIndex.properties +++ b/jcl/src/java.base/share/classes/com/ibm/oti/util/ExternalMessages-MasterIndex.properties @@ -1,6 +1,6 @@ /*[INCLUDE-IF]*/ # -# Copyright (c) 1998, 2018 IBM Corp. and others +# Copyright (c) 1998, 2019 IBM Corp. and others # # This program and the accompanying materials are made available under # the terms of the Eclipse Public License 2.0 which accompanies this diff --git a/jcl/src/java.base/share/classes/java/lang/invoke/MethodHandles.java b/jcl/src/java.base/share/classes/java/lang/invoke/MethodHandles.java index a590b7de6fd..42851a85a89 100644 --- a/jcl/src/java.base/share/classes/java/lang/invoke/MethodHandles.java +++ b/jcl/src/java.base/share/classes/java/lang/invoke/MethodHandles.java @@ -383,8 +383,8 @@ void checkAccess(VarHandle handle, boolean skipAccessCheckPara) throws IllegalAc throw new IllegalAccessException(this.toString()); } - final Class definingClass = handle.getDefiningClass(); - checkAccess(definingClass, definingClass, handle.getFieldName(), handle.getModifiers(), null, skipAccessCheckPara); + /* VarHandles have no reference class */ + checkAccess(handle.getDefiningClass(), null, handle.getFieldName(), handle.getModifiers(), null, skipAccessCheckPara); } void checkAccess(Class clazz) throws IllegalAccessException { @@ -406,7 +406,8 @@ void checkAccess(Class clazz) throws IllegalAccessException { * Equivalent of visible.c checkVisibility(); * * @param definingClass The {@link Class} that defines the member being accessed. - * @param referenceClass The {@link Class} class through which the the member is accessed, which may be a subtype of the defining class. + * @param referenceClass The {@link Class} class through which the the member is accessed, + * which must be the defining class or a subtype. May be null. * @param name The name of member being accessed. * @param memberModifiers The modifiers of the member being accessed. * @param handle A handle object (e.g. {@link MethodHandle} or {@link VarHandle}), if applicable. @@ -418,6 +419,9 @@ void checkAccess(Class clazz) throws IllegalAccessException { * @throws IllegalAccessError If a handle argument or return type is not accessible. */ private void checkAccess(Class definingClass, Class referenceClass, String name, int memberModifiers, MethodHandle handle, boolean skipAccessCheckPara) throws IllegalAccessException { + if (null == referenceClass) { + referenceClass = definingClass; + } checkClassAccess(referenceClass); /*[IF Sidecar19-SE]*/