beanshell / beanshell

Beanshell scripting language
Apache License 2.0
815 stars 183 forks source link

Class/method access is broken on Zulu 11 #723

Closed TarCV closed 1 year ago

TarCV commented 1 year ago

Hi,

Issue On Zulu 11 simple code like this fails with the exception below:

        Interpreter interpreter = new Interpreter();
        interpreter.eval("import java.util.Scanner; new Scanner(\"jkl\")");
bsh.ReflectError: Can't find constructor: java.util.Scanner(String) in class: java.util.Scanner ``` bsh.EvalError: Sourced file: inline evaluation of: ``import java.util.Scanner; new Scanner("jkl")'' : Constructor error: Can't find constructor: java.util.Scanner(String) in class: java.util.Scanner : at Line: 1 : in file: inline evaluation of: ``import java.util.Scanner; new Scanner("jkl")'' : new Scanner ( "jkl" ) at bsh.BSHAllocationExpression.constructObject(BSHAllocationExpression.java:151) at bsh.BSHAllocationExpression.objectAllocation(BSHAllocationExpression.java:110) at bsh.BSHAllocationExpression.eval(BSHAllocationExpression.java:64) at bsh.BSHPrimaryExpression.eval(BSHPrimaryExpression.java:124) at bsh.BSHPrimaryExpression.eval(BSHPrimaryExpression.java:67) at bsh.BSHAssignment.eval(BSHAssignment.java:40) at bsh.Interpreter.eval(Interpreter.java:714) at bsh.Interpreter.eval(Interpreter.java:806) at bsh.Interpreter.eval(Interpreter.java:797) ... Caused by: bsh.ReflectError: Can't find constructor: java.util.Scanner(String) in class: java.util.Scanner at bsh.Reflect.cantFindConstructor(Reflect.java:962) at bsh.Reflect.constructObject(Reflect.java:486) at bsh.Reflect.constructObject(Reflect.java:467) at bsh.BSHAllocationExpression.constructObject(BSHAllocationExpression.java:148) ... 36 more ```

Probably the cause of it I think I was able to pinpoint the cause of this. On Zulu 11 (and probably some other JRE/JDKs) security property package.access contains one empty element (i.e. the property is sun.misc.,sun.reflect.,,com.azul.crs.client. ).

Relevant part of $JAVA_HOME/conf/security/java.security ```properties ... package.access=sun.misc.,\ sun.reflect.,\ ,\ com.azul.crs.client. ... ```

And bsh.Reflect uses that property to determine what classes it can access. The issue is that it assumes the property can't have empty items. In this particular case Reflect generates regex (sun.misc.|sun.reflect.||com.azul.crs.client.).*, which it later uses to look for unavailable classes, but unfortunately, this time, because of ||, the regex would match any class. So it thinks no classes are available for reflection.

From what I was able to gather, package.access is used by SecurityManager.checkPackageAccess. From its source code it looks like the method actually ignores empty items. And also the following code runs without exceptions on Zulu 11 - new SecurityManager().checkPackageAccess("java.util"). So I think it should be safe to ignore empty items in package.access in BeanShell too.

Proposed fix Basically, ignore empty items in package.access security property. So the following patch should fix this issue - https://github.com/beanshell/beanshell/commit/395db0df2813dbe994006f80296840cee181339c

import java.util.WeakHashMap;
+import java.util.stream.Collectors;
-        PACKAGE_ACCESS = Pattern.compile("(?:"+packageAccess.replace(',', '|')+").*");
+        String pattern = Stream.of(packageAccess.split(","))
+                .filter(s -> !s.isEmpty())
+                .collect(Collectors.joining("|", "(?:", ").*"));
+        PACKAGE_ACCESS = Pattern.compile(pattern);