Uploaded image for project: 'Commons JEXL'
  1. Commons JEXL
  2. JEXL-323

Ant-style variables can throw exception when evaluated for their value

    XMLWordPrintableJSON

Details

    • Bug
    • Status: Closed
    • Minor
    • Resolution: Fixed
    • 3.1
    • 3.2
    • None

    Description

      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.

       

          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);
              }
          }
       

      In in unsolvableVariable():

       

      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;
      }
       

       

       

      Steps to Reproduce:

       

      @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);
      }
      
      

       

       

      What Happens:

      "expression2.evaluate(jc)" throws an JexlException$Variable exception with text like "variable 'ant.variable' is null".

      Expected Result:

      expression2.evaluate(jc) returns the value of 'ant.variable', which is null.

       

      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".

       

      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).

      Attachments

        Activity

          People

            henrib Henri Biestro
            david_costanzo David Costanzo
            Votes:
            0 Vote for this issue
            Watchers:
            3 Start watching this issue

            Dates

              Created:
              Updated:
              Resolved: