Skip to content

Conversation

@dpolivaev
Copy link
Contributor

private static final ReflectPermission REFLECT_PERMISSION = new ReflectPermission("suppressAccessChecks");

static private void checkAccessPermission(Class<?> declaringClass, final int modifiers, boolean isAccessible) {
final SecurityManager securityManager = System.getSecurityManager();
Copy link
Contributor

Choose a reason for hiding this comment

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

Might be good to exit early if securityManager == null, then wont have to check again below.

Also, be good to change order to be private static void ....

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Signature changed. The check is performed only if (securityManager != null && isAccessible)

return declaringClass.getName().startsWith("java.");
}

static public void checkAccessPermission(Method method) {
Copy link
Contributor

Choose a reason for hiding this comment

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

public isn't needed

Copy link
Contributor Author

Choose a reason for hiding this comment

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

fixed

);
}

public static void checkAccessPermission(Field field) {
Copy link
Contributor

Choose a reason for hiding this comment

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

public isn't needed

Copy link
Contributor Author

Choose a reason for hiding this comment

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

fixed

try {
AccessPermissionChecker.checkAccessPermission(field);
}
catch (AccessControlException ex) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Any reason for using IllegalArgumentException? I think the following may be more appropriate:

throw new GroovyRuntimeException("Illegal access to field " + field.getName() + ".", ex);

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 use GroovyRuntimeException we need to patch also MetaClassImpl.getProperty . It was not possible with byte buddy, but as a groovy patch it is possible. I shall do it in a separate commit.

AccessPermissionChecker.checkAccessPermission(field);
}
catch (AccessControlException ex) {
throw new IllegalArgumentException("Illegal access to field" + " " + field.getName());
Copy link
Contributor

Choose a reason for hiding this comment

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

see above comment about GroovyRuntimeException

Copy link
Contributor Author

Choose a reason for hiding this comment

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

As above

try {
AccessPermissionChecker.checkAccessPermission(cachedMethod);
}
catch (AccessControlException ex) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Throwing an IllegalArgumentException could be confusing since it's not the arguments passed to the invoked method causing the problem. Maybe

throw new InvokerInvocationException(ex)

or

throw new InvokerInvocationException(
        new AccessControlException("Illegal access to method" + cachedMethod.getName(), ex)
)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

As above

AccessPermissionChecker.checkAccessPermission(cachedMethod);
}
catch (AccessControlException ex) {
throw new IllegalArgumentException("Illegal access to method" + cachedMethod.getName());
Copy link
Contributor

Choose a reason for hiding this comment

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

No arguments to this method so IllegalArgumentException doesn't seem right. Think it might be good to either just remove the try/catch or wrap in a GroovyRuntimeException (to capture cachedMethod.getName).

Copy link
Contributor Author

Choose a reason for hiding this comment

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

As above

AccessPermissionChecker.checkAccessPermission(cachedMethod);
}
catch (AccessControlException ex) {
throw new IllegalArgumentException("Illegal access to method" + cachedMethod.getName());
Copy link
Contributor

Choose a reason for hiding this comment

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

see comment on setAccessible

Copy link
Contributor Author

Choose a reason for hiding this comment

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

As above


import groovy.lang.GroovyObject;

class AccessPermissionChecker {
Copy link
Contributor

Choose a reason for hiding this comment

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

Might be good to add a private constructor to signal that no instances of this method are desired, since it only contains static methods.

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

@dpolivaev
Copy link
Contributor Author

mp = null;
} catch (GroovyRuntimeException e) {
// can't access the field directly but there may be a getter
mp = null;
Copy link
Contributor

Choose a reason for hiding this comment

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

I don't understand why this was added. Was there a test that failed because of the other changes that required this. I would have assumed an AccessControlException from CachedField.getProperty would be treated similar to the IllegalAccessException in the same method.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I do not have unit test to explain this catch block. I do have the integration test https://issues.apache.org/jira/browse/GROOVY-8163?focusedCommentId=16009695&page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel#comment-16009695. The problem is that for some classes C with private member called "name" class property C.class.name which corresponds to java calls C.class.getName() does not work unless this catch block is added.

} catch (IllegalArgumentException e) {
// can't access the field directly but there may be a getter
mp = null;
} catch (GroovyRuntimeException e) {
Copy link
Contributor

Choose a reason for hiding this comment

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

At this point mp should be a CachedField. Since AccessPermissionChecker.checkAccessPermission(field); may now throw a GroovyRuntimeException, we have here the requirement to catch it. Problem is, that mp might not be a CachedField. If we will call a user method here instead, this would lead to a wrong flow. Thus I think the GroovyRuntimeException usage is a bad idea. Better make a new Exception, that extends GroovyRuntimeException and throw that in AccessPermissionChecker, which we then can catch

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I think AccessPermissionChecker should only throw exceptions extending from AccessControlException. because it specifically checks access permissions.

So I suggest to introduce public class CacheAccessControlException extends AccessControlException

Copy link
Contributor Author

Choose a reason for hiding this comment

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

On the other side if it does not work because AccessControlExceptions are not handled by the calling code properly public class CacheAccessControlException extends GroovyRuntimeException could also be taken as a hack.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

How do you see it?

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

catch (AccessControlException ex) {
throw new InvokerInvocationException(new GroovyRuntimeException("Illegal access to method" + cachedMethod.getName()));
}
try {
Copy link
Contributor

Choose a reason for hiding this comment

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

can we move thos try-catch into checkAccessPermission ?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I think that InvokerInvocationException is specific to call of invoke() and it should be not thrown by AccessPermissionChecker directly.

@dpolivaev
Copy link
Contributor Author

Could you please review the changes I implemented on your behalf?

@blackdrag
Copy link
Contributor

+1

@jwagenleitner
Copy link
Contributor

@dpolivaev can you squash up the commits and change the tabs in AccessPermissionChecker to spaces? If not, just let me know and I can take care of it. In the future, it's helpful to create a separate branch for the PR to make it easier to rebase and avoid merge commits.

@blackdrag I would guess this is a candidate for 2_5_X and above, but maybe too much of a change for 2.4.12, though maybe not breaking in a code sense it could affect those running with security managers. Do you agree?

@blackdrag
Copy link
Contributor

agreed

@dpolivaev
Copy link
Contributor Author

Done

@asfgit asfgit closed this in ddecb50 Jun 4, 2017
asfgit pushed a commit that referenced this pull request Jun 4, 2017
asfgit pushed a commit that referenced this pull request Jun 4, 2017
@jwagenleitner
Copy link
Contributor

Thanks.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants