Skip to content

Commit

Permalink
Merge pull request #18264 from babsingh/fix_mt_desc_string
Browse files Browse the repository at this point in the history
[JDK11] Fix AccessControlException in resolveInvokeDynamic
  • Loading branch information
tajila committed Oct 13, 2023
2 parents 2645298 + 570b507 commit e0018c0
Show file tree
Hide file tree
Showing 2 changed files with 116 additions and 83 deletions.
84 changes: 2 additions & 82 deletions jcl/src/java.base/share/classes/java/lang/invoke/MethodType.java
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
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

0 comments on commit e0018c0

Please sign in to comment.