Details
-
Bug
-
Status: Closed
-
Minor
-
Resolution: Fixed
-
3.1
-
None
Description
Using a JexlSandbox, even if it's a whitebox sandbox that allows everything, makes all array-syntax lookup by integer in a Map fail. The array lookup syntax for a String key still works.
For example
{'key' : 'value'}.['key']
can find 'value', but
{1 : 'value'}[1]
evaluates to null, instead of 'value'.
The problem seems to be that SandboxUberspect converts the property 1 to a String "1" when determining the name of the property and then, when it attempts to look up the value, it uses the String. The problem exists for getting and setting by array syntax.
Steps to Reproduce:
This can be seen with a simple program:
public class Main { public static void main(String[] arguments) { JexlEngine simpleJexlEngine = new JexlBuilder().create(); JexlExpression simpleExpression = simpleJexlEngine.createExpression( "{1:'one'}[1]"); Object value = simpleExpression.evaluate(new MapContext()); assert "one".equals(value); JexlEngine sandboxedJexlEngine = new JexlBuilder(). sandbox(new JexlSandbox(true)). // add a whitebox sandbox create(); JexlExpression sandboxedExpression = sandboxedJexlEngine.createExpression( "{1:'one'}[1]"); Object sandboxedValue = sandboxedExpression.evaluate(new MapContext()); assert "one".equals(sandboxedValue); // <--- fails } }
Work-around
As the Java developer, I was able to work around this problem by creating a custom Uberspect that's a copy of SandboxUberspect, but has a different implementation for getPropertySet() and getPropertyGet(). Instead of passing in "actual" to uberspect.getPropertySet() and uberspect.getPropertyGet() (which has been converted to a String), it passes in "identifier", which is the original object. I don't understand the JEXL internals well enough to know if this is correct, though.
As a JEXL programmer, I could only work around this by calling "get" and "put" on the Map object, instead of using the array syntax.