Skip to content

Commit

Permalink
Merge pull request #3978 from ChengJin01/access_check_interface_findS…
Browse files Browse the repository at this point in the history
…pecial

Fix the access check in findSpecial
  • Loading branch information
DanHeidinga committed Jan 15, 2019
2 parents c0196f5 + 83a377d commit a577adf
Show file tree
Hide file tree
Showing 3 changed files with 82 additions and 8 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -549,12 +549,19 @@ private void checkClassAccess(Class<?> targetClass) throws IllegalAccessExceptio
throw new IllegalAccessException(com.ibm.oti.util.Msg.getString("K0680", accessClass.getName(), targetClass.getName())); //$NON-NLS-1$
}

private void checkSpecialAccess(Class<?> callerClass) throws IllegalAccessException {
private void checkSpecialAccess(Class<?> declaringClass, Class<?> callerClass) throws IllegalAccessException {
if (INTERNAL_PRIVILEGED == accessMode) {
// Full access for use by MH implementation.
return;
}
if (isWeakenedLookup() || accessClass != callerClass) {
/* Given that findSpecial emulates the behavior of invokespecial,
* calling interface methods of declaringClass should be allowed as long as
* declaringClass is an interface and callerClass can be assigned to it when
* callerClass is not the same as the lookup class.
*/
if (isWeakenedLookup()
|| ((accessClass != callerClass) && !(declaringClass.isInterface() && declaringClass.isAssignableFrom(callerClass)))
) {
/*[MSG "K0585", "{0} could not access {1} - private access required"]*/
throw new IllegalAccessException(com.ibm.oti.util.Msg.getString("K0585", accessClass.getName(), callerClass.getName())); //$NON-NLS-1$
}
Expand All @@ -580,12 +587,15 @@ private void checkSpecialAccess(Class<?> callerClass) throws IllegalAccessExcept
*/
public MethodHandle findSpecial(Class<?> clazz, String methodName, MethodType type, Class<?> specialToken) throws IllegalAccessException, NoSuchMethodException, SecurityException, NullPointerException {
nullCheck(clazz, methodName, type, specialToken);
checkSpecialAccess(specialToken); /* Must happen before method resolution */
checkSpecialAccess(clazz, specialToken); /* Must happen before method resolution */
MethodHandle handle = null;
try {
handle = findSpecialImpl(clazz, methodName, type, specialToken);
Class<?> handleDefc = handle.getDefc();
if ((handleDefc != accessClass) && !handleDefc.isAssignableFrom(accessClass)) {
/* Check the relationship between the lookup class and the current class
* only when the requested caller class is the same as or subclass of the lookup class.
*/
if (accessClass.isAssignableFrom(specialToken) && !handleDefc.isAssignableFrom(accessClass)) {
/*[MSG "K0586", "Lookup class ({0}) must be the same as or subclass of the current class ({1})"]*/
throw new IllegalAccessException(com.ibm.oti.util.Msg.getString("K0586", accessClass, handleDefc)); //$NON-NLS-1$
}
Expand Down Expand Up @@ -1401,9 +1411,10 @@ public MethodHandle findConstructor(Class<?> declaringClass, MethodType type) th
*/
public MethodHandle unreflectSpecial(Method method, Class<?> specialToken) throws IllegalAccessException {
nullCheck(method, specialToken);
checkSpecialAccess(specialToken); /* Must happen before method resolution */
Class<?> clazz = method.getDeclaringClass();
checkSpecialAccess(clazz, specialToken); /* Must happen before method resolution */
String methodName = method.getName();
Map<CacheKey, WeakReference<MethodHandle>> cache = HandleCache.getSpecialCache(method.getDeclaringClass());
Map<CacheKey, WeakReference<MethodHandle>> cache = HandleCache.getSpecialCache(clazz);
MethodType type = MethodType.methodType(method.getReturnType(), method.getParameterTypes());
MethodHandle handle = HandleCache.getMethodWithSpecialCallerFromPerClassCache(cache, methodName, type, specialToken);
if (handle == null) {
Expand All @@ -1420,7 +1431,7 @@ public MethodHandle unreflectSpecial(Method method, Class<?> specialToken) throw
}

handle = SecurityFrameInjector.wrapHandleWithInjectedSecurityFrameIfRequired(this, handle);

return handle;
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2001, 2018 IBM Corp. and others
* Copyright (c) 2001, 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
Expand Down Expand Up @@ -36,6 +36,7 @@
import com.ibm.j9.jsr292.SamePackageExample.SamePackageInnerClass.SamePackageInnerClass_Nested_Level2;

import examples.PackageExamples;
import examples.CrossPackageDefaultMethodInterface;
import examples.PackageExamples.CrossPackageInnerClass;

/**
Expand Down Expand Up @@ -2098,6 +2099,33 @@ public void test_FindSpecial_Public_CrossPackage_InnerClass() throws Throwable {
AssertJUnit.assertEquals( 3, out );
}

/**
* findSpecial test using a default method of an interface where the class (the resultant
* method handle will be bound to) is in a different package.
* @throws Throwable
*/
@Test(groups = { "level.extended" })
public void test_FindSpecial_Default_CrossPackage_Interface() throws Throwable {
MethodHandle example = MethodHandles.lookup().findSpecial(CrossPackageDefaultMethodInterface.class, "addDefault", MethodType.methodType(int.class, int.class, int.class), CrossPackageDefaultMethodInterface.class);
}

/**
* Negative findSpecial test using a public method of a class where the class (the resultant
* method handle will be bound to) is in a different package.
* Note: when the lookup class is not equal to the caller class, the declaring class
* must be an interface which the caller class can be assigned to.
* @throws Throwable
*/
@Test(groups = { "level.extended" })
public void test_FindSpecial_Public_CrossPackage_Not_Interface() throws Throwable {
try {
MethodHandles.lookup().findSpecial(PackageExamples.class, "addPublic", MethodType.methodType(int.class, int.class, int.class), PackageExamples.class);
Assert.fail("No exception thrown finding a public method of a class in a different package");
} catch(IllegalAccessException e) {
// Exception expected, test passed
}
}

/**
* Negative findSpecial test involving a private method
* @throws Throwable
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/*******************************************************************************
* Copyright (c) 2019, 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
* distribution and is available at https://www.eclipse.org/legal/epl-2.0/
* or the Apache License, Version 2.0 which accompanies this distribution and
* is available at https://www.apache.org/licenses/LICENSE-2.0.
*
* This Source Code may also be made available under the following
* Secondary Licenses when the conditions for such availability set
* forth in the Eclipse Public License, v. 2.0 are satisfied: GNU
* General Public License, version 2 with the GNU Classpath
* Exception [1] and GNU General Public License, version 2 with the
* OpenJDK Assembly Exception [2].
*
* [1] https://www.gnu.org/software/classpath/license.html
* [2] http://openjdk.java.net/legal/assembly-exception.html
*
* SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception
*******************************************************************************/
package examples;

/**
* Cross-package default method interface example used by LookupAPITests_Find
* @author jincheng
*
*/
public interface CrossPackageDefaultMethodInterface {

default int addDefault(int a, int b) {
return (a + b);
}

}

0 comments on commit a577adf

Please sign in to comment.