Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix checking method handle access #3592

Merged
merged 2 commits into from
Jan 15, 2019

Conversation

pdbain-ibm
Copy link
Contributor

@pdbain-ibm pdbain-ibm commented Nov 7, 2018

Use the defining class of a class member or the target class of the lookup as
appropriate. Also reinstate missing external message definition and replace duplicated
code with a common method.

Fixes #3301

Signed-off-by: Peter Bain peter_bain@ca.ibm.com

@pdbain-ibm pdbain-ibm changed the title Fix checking method handle access WIP Fix checking method handle access Nov 14, 2018
@pdbain-ibm
Copy link
Contributor Author

Will update to show the correspondence with bytecode behaviour.

@pdbain-ibm
Copy link
Contributor Author

resolveField.cpp:findFieldAndCheckVisibility() calls checkVisibility() on the defining class of the target field (ca. line 324). visible.c:checkVisibility() succeeds if the target field is private and in the same class as the access class (ca. line 134). This corresponds to MethodHandles.checkAccess() ca. line 435.

checkVisibility() passes if the field is protected and in a superclass of the access class (ca. line 159). This corresponds to MethodHandles.checkAccess() ca. line 460.

Minor tweak to commit, tested with JTReg test and Jsr292 tests.
Would a committer please run sanity and extended builds. Any platform will do.
Thank you

@pdbain-ibm pdbain-ibm changed the title WIP Fix checking method handle access Fix checking method handle access Nov 14, 2018
@pdbain-ibm
Copy link
Contributor Author

This fixes #3301 JTReg test fail : java/lang/invoke/ProtectedMemberDifferentPackage/Test.java. Would @pshipton or other committer please run a pull request build?

@pdbain-ibm
Copy link
Contributor Author

Updating and retesting this...

@pdbain-ibm
Copy link
Contributor Author

Ready for review @DanHeidinga

* @return true if accessMode is INTERNAL_PRIVILEGED
* @throws IllegalAccessException if accessMode is NO_ACCESS
*/
private boolean isNonPrivilegedAccessThrowOnNoAccess() throws IllegalAccessException {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Given this is PR is a change to code that's both historically messy and a source of bugs, can you revert the unnecessary parts so it is easier to determine what is required?

It'll make it much easier to understand the history of this in the future.

@@ -407,7 +409,7 @@ 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 {
private void checkAccess(Class<?> targetClass, Class<?> definingClass, String name, int memberModifiers, MethodHandle handle, boolean skipAccessCheckPara) throws IllegalAccessException {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I really dislike changing the meaning of the variable name here as it makes it hard to review whether changes were deliberate or not.

@DanHeidinga
Copy link
Member

Sorry, just realized I hadn't completed the review yet. It's been sitting in a pending state for the last few days

@pdbain-ibm pdbain-ibm force-pushed the checkaccess branch 2 times, most recently from 7894681 to bb0faa6 Compare December 11, 2018 17:33
@pdbain-ibm
Copy link
Contributor Author

@DanHeidinga
Thanks for the feedback. I reverted non-essential changes and renamed the argument for clarity.
Tested on the jtreg testcase.

Copy link

@ChengJin01 ChengJin01 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The existing implementation of checkClassAccess() is intended to check the defining class but I am not sure whether it is correct or sufficient to check the reference class rather than the defining class.

In addition, such check (for the reference class) might only apply to the situation when the reference class is the same as or a subclass of the defining class but there is no change reflecting the relationship.

/* The only methods array classes have are defined on Object and thus accessible */
return;
}

if (isSamePackage(accessClass, targetClass)) {
if (isSamePackage(accessClass, referenceClass)) {
Copy link

@ChengJin01 ChengJin01 Jan 11, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The API Spec says at https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/lang/invoke/MethodHandles.Lookup.html

Access Checking
...
If the desired member is protected, the usual JVM rules apply, including the requirement that the lookup class must be either be in the same package as the desired member, 
or must inherit that member.  (See the Java Virtual Machine Specification, sections 4.9.2, 5.4.3.5, and 6.4.) 
In addition, if the desired member is a non-static field or method in a different package, 
the resulting method handle may only be applied to  objects of the lookup class or one of its subclasses. 

So changing to referenceClass seems incorrect at this point.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In this case, the method is not public, so we need to check for package access. Consider the case where the lookup class is in the same package as the reference class, but a different package from the defining class. If we check against the defining class we would fail, even though the method is visible via the reference class.

Note also that the reference class may broaden the visibility of the method.

@@ -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)){
Copy link

@ChengJin01 ChengJin01 Jan 11, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not too sure whether it is correct to change to referenceClass if referenceClass is not a subclass of targetClass

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

referenceClass must be a subtype of definingClass in order to inherit the method.

@ChengJin01
Copy link

ChengJin01 commented Jan 11, 2019

Introducing the reference class to checkAccess() is logically correct to address the case but how to deal with the relationship between the defining class and the reference class is up to us as the API Spec doesn't explain in details at this point.

@pdbain-ibm
Copy link
Contributor Author

In reply to
#3592 (comment), most of the uses of definingClass pertain to private methods or access via inheritance from the defining class to the lookup class in cases where the lookup class does not extend the reference class.

Copy link

@ChengJin01 ChengJin01 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have no more comment as the relationship between the reference class and the defining class is confirmative as explained above at this point.

@pdbain-ibm pdbain-ibm changed the title Fix checking method handle access WIP Fix checking method handle access Jan 11, 2019
@pdbain-ibm
Copy link
Contributor Author

pdbain-ibm commented Jan 11, 2019

Found an issue when testing with a VarHandles test case: the reference class can sometimes be null.
Will update the changeset.

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 <peter_bain@ca.ibm.com>
The reference class may be null in the case of varhandles.

Signed-off-by: Peter Bain <peter_bain@ca.ibm.com>
@pdbain-ibm
Copy link
Contributor Author

I added a second commit to fix the null reference class problem. I will squash it when this is approved.

@pdbain-ibm pdbain-ibm changed the title WIP Fix checking method handle access Fix checking method handle access Jan 14, 2019
@DanHeidinga
Copy link
Member

Jenkins test all xlinux jdk11,jdk8

@DanHeidinga
Copy link
Member

Jenkins test sanity xlinux jdk11

@DanHeidinga
Copy link
Member

Jenkins test extended xlinux jdk11

@DanHeidinga DanHeidinga merged commit 9578b8e into eclipse-openj9:master Jan 15, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants