-
Notifications
You must be signed in to change notification settings - Fork 720
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
Conversation
Will update to show the correspondence with bytecode behaviour. |
23932af
to
91dd131
Compare
checkVisibility() passes if the field is Minor tweak to commit, tested with JTReg test and Jsr292 tests. |
Updating and retesting this... |
91dd131
to
513a119
Compare
Ready for review @DanHeidinga |
* @return true if accessMode is INTERNAL_PRIVILEGED | ||
* @throws IllegalAccessException if accessMode is NO_ACCESS | ||
*/ | ||
private boolean isNonPrivilegedAccessThrowOnNoAccess() throws IllegalAccessException { |
There was a problem hiding this comment.
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 { |
There was a problem hiding this comment.
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.
Sorry, just realized I hadn't completed the review yet. It's been sitting in a pending state for the last few days |
7894681
to
bb0faa6
Compare
@DanHeidinga |
There was a problem hiding this 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)) { |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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)){ |
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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.
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. |
In reply to |
There was a problem hiding this 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.
bb0faa6
to
9a98c29
Compare
Found an issue when testing with a VarHandles test case: the reference class can sometimes be null. |
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>
9a98c29
to
617e34c
Compare
The reference class may be null in the case of varhandles. Signed-off-by: Peter Bain <peter_bain@ca.ibm.com>
617e34c
to
e628544
Compare
I added a second commit to fix the null reference class problem. I will squash it when this is approved. |
Jenkins test all xlinux jdk11,jdk8 |
Jenkins test sanity xlinux jdk11 |
Jenkins test extended xlinux jdk11 |
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