[
https://issues.apache.org/jira/browse/JEXL-323?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=17025163#comment-17025163
]
David Costanzo commented on JEXL-323:
-------------------------------------
{quote}The 'safe' flag has been introduced to mitigate several bugs where
JEXL(3.1) was not hard failing on nulls when it should have.
{quote}
Glad to hear it. For my purpose, I want JEXL to hard fail on nulls unless the
JEXL programmer explicitly handles null.
{quote}In 3.2, default scripting behaviour should be 'safe' disabled (and
'lexical' and 'lexicalShade' enabled).
{quote}
I build the JexlEngine using JexlBuilder and see opposite for the defaults. If
I understand the code, this comes from {{JexlOptions.DEFAULT}}.
{code:java}
private static int DEFAULT = 1 /*<< CANCELLABLE*/ | 1 << STRICT | 1 << ANTISH |
1 << SAFE;
{code}
Programmatically, each of the following tests fail:
{code:java}
Assert.assertTrue(new JexlBuilder().lexical());
Assert.assertTrue(new JexlBuilder().lexicalShade());
Assert.assertFalse(new JexlBuilder().safe());
{code}
Have I misunderstood the API? Am I building from the wrong branch?
To reproduce the problem mentioned in this ticket on 3.2, I had to explicitly
call "safe(false)" on my JexlBuilder (see the commented out "// on recent
code"). Without this, {{testNullAntVariable()}} passes on 3.2 (the bug is not
reproducible). I assumed this was because the "null" value returned was *not*
from the value of "ant.variable", but instead because the ant-style variable
name "ant.variable" was re-interpreted as a property access "ant.getVariable()"
and since "ant" is missing, safe browsing would say "ant.getVariable()" is null.
> Ant-style variables can throw exception when evaluated for their value
> ----------------------------------------------------------------------
>
> Key: JEXL-323
> URL: https://issues.apache.org/jira/browse/JEXL-323
> Project: Commons JEXL
> Issue Type: Bug
> Affects Versions: 3.1
> Reporter: David Costanzo
> Priority: Minor
>
> When try to evaluate an expression that is the name of a variable and the
> value is null, I get the value null. This is good. However, when I do the
> same thing with an ant-style variable name, a JexlException$Variable is
> thrown claiming that the variable is null. I think this is a bug because I
> would expect all variables to behave the same, regardless of their name.
> The reason for this behavior is evident in Interpreter.visit() and
> InterpreterBase.unsolvableVariable(). There is already special-case logic to
> detect when an ant variable is null versus when it's undefined, and this
> information is given to unsolvableVariable(), but it still throws an
> exception.
>
> {code:java}
> if (object == null && !isTernaryProtected(node)) {
> if (antish && ant != null) {
> // V--- NOTE: context.has() returns true, so undefined is false
> boolean undefined = !(context.has(ant.toString()) ||
> isLocalVariable(node, 0));
> // variable unknown in context and not a local
> return unsolvableVariable(node, ant.toString(), undefined); //
> <-- still throws exception
> } else if (!pty) {
> return unsolvableProperty(node, "<null>.<?>", null);
> }
> }
> {code}
> In in unsolvableVariable():
>
> {code:java}
> protected Object unsolvableVariable(JexlNode node, String var, boolean undef)
> {
> // V-- NOTE: both my engine and arithmetic are strict, so this evaluates
> to true
> if (isStrictEngine() && (undef || arithmetic.isStrict())) {
> throw new JexlException.Variable(node, var, undef);
> } else if (logger.isDebugEnabled()) {
> logger.debug(JexlException.variableError(node, var, undef));
> }
> return null;
> }
> {code}
>
>
> h3. Steps to Reproduce:
>
> {code:java}
> @Test
> public void testNullAntVariable() throws IOException {
> // Create or retrieve an engine
> JexlEngine jexl = new JexlBuilder().create();
> // on recent code: JexlEngine jexl = new
> JexlBuilder().safe(false).create();
> // Populate to identical global variables
> JexlContext jc = new MapContext();
> jc.set("NormalVariable", null);
> jc.set("ant.variable", null);
> // Evaluate the value of the normal variable
> JexlExpression expression1 = jexl.createExpression("NormalVariable");
> Object o1 = expression1.evaluate(jc);
> Assert.assertEquals(null, o1);
> // Evaluate the value of the ant-style variable
> JexlExpression expression2 = jexl.createExpression("ant.variable");
> Object o2 = expression2.evaluate(jc); // <-- BUG: throws exception
> instead of returning null
> Assert.assertEquals(null, o2);
> }
> {code}
>
>
> h3. What Happens:
> "expression2.evaluate(jc)" throws an JexlException$Variable exception with
> text like "variable 'ant.variable' is null".
> h3. Expected Result:
> expression2.evaluate(jc) returns the value of 'ant.variable', which is null.
> h3.
> Note:
> This was found on JEXL 3.1, the latest official release. I reproduced it on a
> snapshot of JEXL 3.2 built from github source, but had to disable "safe".
> h3.
> Impact:
> My organization uses JEXL to build datasets for clinical trials. In our
> domain, it's very common to have an expression that is simply the name of a
> variable whose value is desired. In our domain, we want any sloppy
> expressions to be a hard error, so we we use strict engines and will use
> "safe=false" when we update to JEXL 3.2. In our domain, "null" has a specific
> meaning (it means "missing"). A missing value is distinct from an "undefined
> variable", which is always an error to reference. Because of this bug, we had
> to ban using "." in names of "global" variables (variables populated in the
> JexlContext).
--
This message was sent by Atlassian Jira
(v8.3.4#803005)