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

[JDK11] Fix AccessControlException in resolveInvokeDynamic #18264

Merged
merged 1 commit into from
Oct 13, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
84 changes: 2 additions & 82 deletions jcl/src/java.base/share/classes/java/lang/invoke/MethodType.java
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,6 @@
import java.util.WeakHashMap;

import com.ibm.oti.util.Msg;
import com.ibm.oti.vm.VM;

/*[IF CRIU_SUPPORT]*/
import openj9.internal.criu.NotCheckpointSafe;
Expand Down Expand Up @@ -337,43 +336,7 @@ public MethodType erase() {
*/
@VMCONSTANTPOOL_METHOD
public static MethodType fromMethodDescriptorString(String methodDescriptor, ClassLoader loader) {
ClassLoader classLoader = loader;
if (classLoader == null) {
/*[IF JAVA_SPEC_VERSION >= 14]*/
@SuppressWarnings("removal")
SecurityManager security = System.getSecurityManager();
if (security != null) {
security.checkPermission(sun.security.util.SecurityConstants.GET_CLASSLOADER_PERMISSION);
}
/*[ENDIF] JAVA_SPEC_VERSION >= 14 */
classLoader = ClassLoader.getSystemClassLoader();
}

// Check cache
Map<String, MethodType> classLoaderMethodTypeCache = VM.getVMLangAccess().getMethodTypeCache(classLoader);
MethodType mt = classLoaderMethodTypeCache != null ? classLoaderMethodTypeCache.get(methodDescriptor) : null;

// MethodDescriptorString is not in cache
if (null == mt) {
// ensure '.' is not included in the descriptor
if (methodDescriptor.indexOf((int)'.') != -1) {
throw new IllegalArgumentException(methodDescriptor);
}

// split descriptor into classes - last one is the return type
ArrayList<Class<?>> classes = parseIntoClasses(methodDescriptor, classLoader);
if (classes.size() == 0) {
throw new IllegalArgumentException(methodDescriptor);
}

Class<?> returnType = classes.remove(classes.size() - 1);
mt = methodType(returnType, classes);
if (classLoaderMethodTypeCache != null) {
classLoaderMethodTypeCache.put(mt.methodDescriptor, mt);
}
}

return mt;
return MethodTypeHelper.fromMethodDescriptorStringInternal(methodDescriptor, loader);
}

/**
Expand All @@ -385,7 +348,7 @@ public static MethodType fromMethodDescriptorString(String methodDescriptor, Cla
*/
@SuppressWarnings("unused") /* Used by native code */
private static final MethodType fromMethodDescriptorStringAppendArg(String methodDescriptor, ClassLoader loader, Class<?> appendArgumentType) {
List<Class<?>> types = parseIntoClasses(methodDescriptor, loader);
List<Class<?>> types = MethodTypeHelper.parseIntoClasses(methodDescriptor, loader);
Class<?> returnType = types.remove(types.size() - 1);
types.add(appendArgumentType);

Expand All @@ -412,49 +375,6 @@ private static final Throwable throwNoClassDefFoundError(TypeNotPresentException
}
throw e;
}

/*
* Parse the MethodDescriptor string into a list of Class objects. The last class in the list
* is the return type.
*/
private static final ArrayList<Class<?>> parseIntoClasses(String methodDescriptor, ClassLoader classLoader) {
int length = methodDescriptor.length();
if (length == 0) {
/*[MSG "K05d3", "invalid descriptor: {0}"]*/
throw new IllegalArgumentException(Msg.getString("K05d3", methodDescriptor)); //$NON-NLS-1$
}

char[] signature = new char[length];
methodDescriptor.getChars(0, length, signature, 0);
int index = 0;
boolean closeBracket = false;

if (signature[index] != '(') {
/*[MSG "K05d4", "missing opening '(': {0}"]*/
throw new IllegalArgumentException(Msg.getString("K05d4", methodDescriptor)); //$NON-NLS-1$
}
index++;

ArrayList<Class<?>> args = new ArrayList<Class<?>>();

while(index < length) {
/* Ensure we only see one ')' closing bracket */
if ((signature[index] == ')')) {
if (closeBracket) {
/*[MSG "K05d5", "too many ')': {0}"]*/
throw new IllegalArgumentException(Msg.getString("K05d5", methodDescriptor)); //$NON-NLS-1$
}
closeBracket = true;
index++;
continue;
}

index = MethodTypeHelper.parseIntoClass(signature, index, args, classLoader, methodDescriptor);
index++;
}
return args;
}


/**
* Convenience method to convert all types to Object.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,10 @@
import jdk.internal.value.PrimitiveClass;
/*[ENDIF] INLINE-TYPES */

import java.util.Map;

import com.ibm.oti.util.Msg;
import com.ibm.oti.vm.VM;

/**
* MethodTypeHelper - static methods
Expand Down Expand Up @@ -270,6 +273,116 @@ static final int parseIntoClass(char[] signature, int index, ArrayList<Class<?>>
return index;
}

/**
* Parse the MethodDescriptor string into a list of Class objects. The last class in the list
* is the return type.
*
* @param methodDescriptor the method descriptor string
* @param classLoader the ClassLoader to be used or null for System ClassLoader
* @return list of classes representing the parameters and return type
* @throws IllegalArgumentException if the string is not well-formed
*/
static final ArrayList<Class<?>> parseIntoClasses(String methodDescriptor, ClassLoader classLoader) {
int length = methodDescriptor.length();
if (length == 0) {
/*[MSG "K05d3", "invalid descriptor: {0}"]*/
throw new IllegalArgumentException(Msg.getString("K05d3", methodDescriptor)); //$NON-NLS-1$
}

char[] signature = new char[length];
methodDescriptor.getChars(0, length, signature, 0);
int index = 0;
boolean closeBracket = false;

if (signature[index] != '(') {
/*[MSG "K05d4", "missing opening '(': {0}"]*/
throw new IllegalArgumentException(Msg.getString("K05d4", methodDescriptor)); //$NON-NLS-1$
}
index++;

ArrayList<Class<?>> args = new ArrayList<Class<?>>();

while(index < length) {
/* Ensure we only see one ')' closing bracket */
if ((signature[index] == ')')) {
if (closeBracket) {
/*[MSG "K05d5", "too many ')': {0}"]*/
throw new IllegalArgumentException(Msg.getString("K05d5", methodDescriptor)); //$NON-NLS-1$
}
closeBracket = true;
index++;
continue;
}

index = parseIntoClass(signature, index, args, classLoader, methodDescriptor);
index++;
}
return args;
}

/**
* Convenience Method to create a MethodType from bytecode-level method descriptor.
* (See JVM Spec 2nd Ed. section 4.4.3).
*
* All of the classes used in the method descriptor string must be reachable from a
* common ClassLoader or an exception will result.
*
* The ClassLoader parameter may be null, in which case the System ClassLoader will be used.
*
* Note, the Class names must use JVM syntax in the method descriptor String and therefore
* java.lang.Class will be represented as Ljava/lang/Class;
*
* Example method descriptors:
* (II)V - method taking two ints and return void
* (I)Ljava/lang/Integer; - method taking an int and returning an Integer
* ([I)I - method taking an array of ints and returning an int
*
* @param methodDescriptor the method descriptor string
* @param loader the ClassLoader to be used or null for System ClassLoader
* @return a MethodType object representing the method descriptor string
* @throws IllegalArgumentException if the string is not well-formed
* @throws TypeNotPresentException if a named type cannot be found
*/
static MethodType fromMethodDescriptorStringInternal(String methodDescriptor, ClassLoader loader) {
ClassLoader classLoader = loader;
if (classLoader == null) {
/*[IF JAVA_SPEC_VERSION >= 14]*/
@SuppressWarnings("removal")
SecurityManager security = System.getSecurityManager();
if (security != null) {
security.checkPermission(sun.security.util.SecurityConstants.GET_CLASSLOADER_PERMISSION);
}
/*[ENDIF] JAVA_SPEC_VERSION >= 14 */
classLoader = ClassLoader.getSystemClassLoader();
}

// Check cache
Map<String, MethodType> classLoaderMethodTypeCache = VM.getVMLangAccess().getMethodTypeCache(classLoader);
MethodType mt = classLoaderMethodTypeCache != null ? classLoaderMethodTypeCache.get(methodDescriptor) : null;

// MethodDescriptorString is not in cache
if (null == mt) {
// ensure '.' is not included in the descriptor
if (methodDescriptor.indexOf((int)'.') != -1) {
throw new IllegalArgumentException(methodDescriptor);
}

// split descriptor into classes - last one is the return type
ArrayList<Class<?>> classes = parseIntoClasses(methodDescriptor, classLoader);
if (classes.size() == 0) {
throw new IllegalArgumentException(methodDescriptor);
}

Class<?> returnType = classes.remove(classes.size() - 1);
mt = MethodType.methodType(returnType, classes);
if (classLoaderMethodTypeCache != null) {
classLoaderMethodTypeCache.put(mt.toMethodDescriptorString(), mt);
}
}

return mt;
}

/**
* This helper calls MethodType.fromMethodDescriptorString(...) or
* MethodType.fromMethodDescriptorStringAppendArg(...) but throws
Expand All @@ -287,7 +400,7 @@ static final int parseIntoClass(char[] signature, int index, ArrayList<Class<?>>
*/
static final MethodType vmResolveFromMethodDescriptorString(String methodDescriptor, ClassLoader loader, Class<?> appendArgumentType) throws Throwable {
try {
MethodType result = MethodType.fromMethodDescriptorString(methodDescriptor, loader);
MethodType result = fromMethodDescriptorStringInternal(methodDescriptor, loader);
if (null != appendArgumentType) {
result = result.appendParameterTypes(appendArgumentType);
}
Expand Down