LUCENE-5207: Add checks for classloader, so all methods in the Map are accessible

git-svn-id: https://svn.apache.org/repos/asf/lucene/dev/branches/lucene5207@1523315 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Uwe Schindler 2013-09-14 20:31:52 +00:00
parent 691e3fc234
commit e6c0692d4b
1 changed files with 24 additions and 4 deletions

View File

@ -171,12 +171,17 @@ public class JavascriptCompiler {
* *
* @param sourceText The expression to compile * @param sourceText The expression to compile
* @param functions map of String names to functions * @param functions map of String names to functions
* @param parent a {@code ClassLoader} that should be used as the parent of the loaded class.
* It must contain all classes referred to by the given {@code functions}.
* @return A new compiled expression * @return A new compiled expression
* @throws ParseException on failure to compile * @throws ParseException on failure to compile
*/ */
public static Expression compile(String sourceText, Map<String,Method> functions, ClassLoader parent) throws ParseException { public static Expression compile(String sourceText, Map<String,Method> functions, ClassLoader parent) throws ParseException {
if (parent == null) {
throw new NullPointerException("A parent ClassLoader must be given.");
}
for (Method m : functions.values()) { for (Method m : functions.values()) {
checkFunction(m); checkFunction(m, parent);
} }
return new JavascriptCompiler(sourceText, functions).compileExpression(parent); return new JavascriptCompiler(sourceText, functions).compileExpression(parent);
} }
@ -698,7 +703,7 @@ public class JavascriptCompiler {
@SuppressWarnings({"rawtypes", "unchecked"}) Class[] args = new Class[arity]; @SuppressWarnings({"rawtypes", "unchecked"}) Class[] args = new Class[arity];
Arrays.fill(args, double.class); Arrays.fill(args, double.class);
Method method = clazz.getMethod(methodName, args); Method method = clazz.getMethod(methodName, args);
checkFunction(method); checkFunction(method, JavascriptCompiler.class.getClassLoader());
map.put(call, method); map.put(call, method);
} }
} catch (NoSuchMethodException | ClassNotFoundException | IOException e) { } catch (NoSuchMethodException | ClassNotFoundException | IOException e) {
@ -707,8 +712,23 @@ public class JavascriptCompiler {
DEFAULT_FUNCTIONS = Collections.unmodifiableMap(map); DEFAULT_FUNCTIONS = Collections.unmodifiableMap(map);
} }
/* do some checks if the signature is "compatible" */ private static void checkFunction(Method method, ClassLoader parent) {
private static void checkFunction(Method method) { // We can only call the function if the given parent class loader of our compiled class has access to the method:
final ClassLoader functionClassloader = method.getDeclaringClass().getClassLoader();
if (functionClassloader != null) { // it is a system class iff null!
boolean found = false;
while (parent != null) {
if (parent == functionClassloader) {
found = true;
break;
}
parent = parent.getParent();
}
if (!found) {
throw new IllegalArgumentException(method + " is not declared by a class which is accessible by the given parent ClassLoader.");
}
}
// do some checks if the signature is "compatible":
if (!Modifier.isStatic(method.getModifiers())) { if (!Modifier.isStatic(method.getModifiers())) {
throw new IllegalArgumentException(method + " is not static."); throw new IllegalArgumentException(method + " is not static.");
} }