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

Check module visibility in method handles #1801

Merged
merged 1 commit into from
May 22, 2018

Conversation

pdbain-ibm
Copy link
Contributor

Ensure target classes, paramater types, and return types are visible.

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

@pdbain-ibm
Copy link
Contributor Author

FYI @DanHeidinga @pshipton

@DanHeidinga
Copy link
Member

The PR only adds this check to findVirtual. What about the other find{static,special,bind,setter,getter} methods? Do they need the module access checks as well?

@pdbain-ibm pdbain-ibm changed the title WIP Check module visibility in method handles Check module visibility in method handles Apr 30, 2018
@pdbain-ibm
Copy link
Contributor Author

@dan The personal build has nearly finished and shows no errors so far. Would you kindly run a Jenkins sanity build?

@@ -47,7 +47,7 @@
import com.ibm.oti.vm.VM;
import com.ibm.oti.vm.VMLangAccess;

/*[IF Sidecar19-SE]
/*[IF Sidecar19-SE]*/
Copy link
Member

Choose a reason for hiding this comment

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

why this change?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

To reduce the syntax errors when editing in the new code in Eclipse.

Copy link
Member

Choose a reason for hiding this comment

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

Doesn't that just move the syntax error from 9 to 8?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

No: this change eliminates most of the syntax errors in the unprocessed code.

@@ -634,14 +636,26 @@ public MethodHandle findStatic(Class<?> clazz, String methodName, MethodType typ
* @param methodName - the name of the method
* @param type - the type of the method
* @return a MethodHandle that will do virtual dispatch on the first argument
* @throws IllegalAccessException - if method is static or access is refused
* @throws IllegalAccessException - if method is static or access is refused or clazz's package is not exported to the current module
Copy link
Member

Choose a reason for hiding this comment

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

This javadoc will be generated for both 8 & 9+. Module should only be mentioned for 9

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Will fix.

@@ -634,14 +636,26 @@ public MethodHandle findStatic(Class<?> clazz, String methodName, MethodType typ
* @param methodName - the name of the method
* @param type - the type of the method
* @return a MethodHandle that will do virtual dispatch on the first argument
* @throws IllegalAccessException - if method is static or access is refused
* @throws IllegalAccessException - if method is static or access is refused or clazz's package is not exported to the current module
* @throws IllegalAccessError - if the type's packages are not exported to the current module
Copy link
Member

Choose a reason for hiding this comment

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

module mentioned in 8

* @throws NullPointerException - if clazz, methodName or type is null
* @throws NoSuchMethodException - if clazz has no virtual method named methodName with signature matching type
* @throws SecurityException - if any installed SecurityManager denies access to the method
*/
public MethodHandle findVirtual(Class<?> clazz, String methodName, MethodType type) throws IllegalAccessException, NoSuchMethodException {
nullCheck(clazz, methodName, type);

/*[IF Sidecar19-SE]*/
if (INTERNAL_PRIVILEGED != accessMode) {
Copy link
Member

Choose a reason for hiding this comment

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

shouldn't this be added to checkAccess()?

@pdbain-ibm
Copy link
Contributor Author

What about the other find{static,special,bind,setter,getter} methods?

Possibly. We don't have tests for these yet.

@pdbain-ibm pdbain-ibm force-pushed the modularity_functional branch from 1682dda to b8a104d Compare May 1, 2018 12:14
@pdbain-ibm
Copy link
Contributor Author

find{static,special,bind,setter,getter} methods

Working on tests for those.

MethodType type = handle.type();
Module accessModule = accessClass.getModule();
checkClassModuleVisibility(accessModule, targetClass, false);
checkClassModuleVisibility(accessModule, type.returnType, true);
Copy link
Member

Choose a reason for hiding this comment

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

There are two calls to checkClassModuleVisibility, one setting throwError to false while the other says true. Which is intended?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The throwable depends on the context. If the target class is not visible, we need to throw an IllegalAccessException. If the parameter or return types are not visible, we need to throw a IllegalAccessError.

/*[MSG "K0664", "{0} is not in an exported package"]*/
String message = Msg.getString("K0664", targetClass.getPackageName()); //$NON-NLS-1$
if (throwError) {
throw new IllegalAccessError(message);
Copy link
Member

Choose a reason for hiding this comment

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

likely better to only throw one exception and let the code that needs the Error wrap the Exception.

@@ -1160,6 +1160,7 @@ K0660="Internal error while obtaining private constructor."
K0661="Internal error while obtaining GcInfo instance."
K0662="maxDepth must not be negative."
K0663="Invalid or unsupported dump agent option, cannot be triggered."
K0664="{0} is not in an exported package"
Copy link
Member

Choose a reason for hiding this comment

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

Is there no existing message that can be reused?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes. Fixed.

Module accessModule = accessClass.getModule();
checkClassModuleVisibility(accessModule, targetClass, false);
checkClassModuleVisibility(accessModule, type.returnType, true);
for (Class<?> c: type.parameterArray()) {
Copy link
Member

Choose a reason for hiding this comment

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

type.parameterArray() allocates a new array - since this code is in the j.l.i package and we know it won't modify the array, better to use type.arguments directly

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Okay.

* @throws IllegalAccessError thrown if throwError is true
* @throws IllegalAccessException thrown if throwError is false
*/
static void checkClassModuleVisibility(Module accessModule, Class<?> targetClass, boolean throwError)
Copy link
Member

Choose a reason for hiding this comment

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

Please put the throw clauses on the same line.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Okay.

if (!Objects.equals(accessModule, targetModule)
&& !(targetModule.isExported(targetClass.getPackageName(), accessModule)
&& accessModule.canRead(targetModule))) {
/*[MSG "K0664", "{0} is not in an exported package"]*/
Copy link
Member

Choose a reason for hiding this comment

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

Can you add the two modules to this message? It will be easier for a user to resolve an access failure if they get the module info in the exception.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done.

static void checkClassModuleVisibility(Module accessModule, Class<?> targetClass, boolean throwError)
throws IllegalAccessError, IllegalAccessException {
Module targetModule = targetClass.getModule();
if (!Objects.equals(accessModule, targetModule)
Copy link
Member

Choose a reason for hiding this comment

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

Can you rewrite this as positive conditions?

@pdbain-ibm pdbain-ibm force-pushed the modularity_functional branch from b8a104d to 1ea8a4b Compare May 7, 2018 20:28
@pdbain-ibm pdbain-ibm changed the title Check module visibility in method handles WIP Check module visibility in method handles May 7, 2018
@pdbain-ibm
Copy link
Contributor Author

Passes designer tests. Will run a larger regression suite tomorrow.

@pdbain-ibm pdbain-ibm changed the title WIP Check module visibility in method handles Check module visibility in method handles May 8, 2018
@pdbain-ibm
Copy link
Contributor Author

pdbain-ibm commented May 8, 2018

JCL tests pass. @DanHeidinga or @pshipton could you take another look at the code?

checkClassModuleVisibility(accessModule, c);
}
} catch (IllegalAccessException e) {
throw new IllegalAccessError(e.getMessage());
Copy link
Member

Choose a reason for hiding this comment

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

It's better to chain the exceptions by setting the IllegalAccessException as the cause - either by initCause() or through an appropriate constructor - so the original stack trace is preserved.

Copy link
Member

Choose a reason for hiding this comment

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

This method is used a lot of places. Is IllegalAccessError expected by the callers? Wouldn't it be more consistent to have this function throw IAException and only callers that expect IAError to do the transformation?

/* The following access checking is for a normal class (non-member class) */

/* The following access checking is for a normal class (non-member class) */
Copy link
Member

Choose a reason for hiding this comment

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

This comment applies to the else if block, if it applies to anything at all, and should have kept its original indentation

* @param type - the type of the method
* @return a MethodHandle that will do virtual dispatch on the first argument
* @throws IllegalAccessException - if method is static or access is refused or clazz's package is not exported to the current module
* @throws IllegalAccessError - if the type's packages are not exported to the current module
Copy link
Member

Choose a reason for hiding this comment

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

Has the RI thrown IAError from findVirtual?

The convention is usually that the VM throws IllegalAccessError and reflective style operations throw Exceptions. We're using the same code to do double duty as the VM is calling into Java for these lookups.

I would expect exception / error conversion to happen at the boundaries.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Has the RI thrown IAError from findVirtual?

Yes. This matches the behaviour of the reference implementation.

/*[MSG "K0587", "'{0}' no access to: '{1}'"]*/
throw new IllegalAccessException(com.ibm.oti.util.Msg.getString("K0587", accessClass.getName(), targetClass.getName())); //$NON-NLS-1$
}

void checkLookupVisibility(Class<?> targetClass) throws IllegalAccessException, IllegalAccessError {
if (this.equals(PUBLIC_LOOKUP)) {
Copy link
Member

Choose a reason for hiding this comment

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

Rather than checking is identically PUBLIC_LOOKUP, we should check for the UNCONDITIONAL mode access bit - see https://docs.oracle.com/javase/9/docs/api/java/lang/invoke/MethodHandles.html#publicLookup--

* @param targetClass Class which the referring class is accessing
* @throws IllegalAccessException if the targetClass is not visible
*/
static void checkClassModuleVisibility(Module accessModule, Class<?> targetClass) throws IllegalAccessError, IllegalAccessException {
Copy link
Member

Choose a reason for hiding this comment

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

This probably also needs to take the UNCONDITIONAL access bit into account (ie: public lookup)

@pshipton pshipton added this to the Release 0.9.0 milestone May 9, 2018
@pdbain-ibm pdbain-ibm force-pushed the modularity_functional branch from 1ea8a4b to 032fe21 Compare May 9, 2018 14:45
@pdbain-ibm
Copy link
Contributor Author

The current change causes a regression in another test. I am investigating.

@pdbain-ibm pdbain-ibm force-pushed the modularity_functional branch from 032fe21 to 19f688c Compare May 11, 2018 15:40
Check that the target class, parameter types, and return types of a method
handle are obey module access restrictions.

Signed-off-by: Peter Bain <peter_bain@ca.ibm.com>
@pdbain-ibm pdbain-ibm force-pushed the modularity_functional branch from 19f688c to d137536 Compare May 11, 2018 16:35
@pdbain-ibm
Copy link
Contributor Author

Regression was due to stale base code.
@DanHeidinga or @pshipton would you kindly review and run a PR build?

@pdbain-ibm
Copy link
Contributor Author

@DanHeidinga or @pshipton do you have any comments on this PR? If not, could you
please run a sanity build?

Thank you.

@DanHeidinga
Copy link
Member

Jenkins test sanity plinux jdk8,jdk9

@DanHeidinga DanHeidinga self-assigned this May 22, 2018
@DanHeidinga DanHeidinga merged commit 286d0a3 into eclipse-openj9:master May 22, 2018
@pdbain-ibm pdbain-ibm deleted the modularity_functional branch May 22, 2018 14:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants