This is an automated email from the ASF dual-hosted git repository.

henrib pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/commons-jexl.git


The following commit(s) were added to refs/heads/master by this push:
     new c70235e  JEXL-275: lexical shade does not trigger undefined var if 
safe mode is true Task #JEXL-275 - Allow safe navigation as option
c70235e is described below

commit c70235e2ff12371bed4aca356de4abdf7d7bf64c
Author: henrib <hen...@apache.org>
AuthorDate: Wed Jun 10 13:50:00 2020 +0200

    JEXL-275: lexical shade does not trigger undefined var if safe mode is true
    Task #JEXL-275 - Allow safe navigation as option
---
 .../org/apache/commons/jexl3/JexlException.java    |  8 ++-
 .../apache/commons/jexl3/internal/Interpreter.java |  2 +-
 .../commons/jexl3/internal/InterpreterBase.java    | 12 +++--
 .../org/apache/commons/jexl3/Issues200Test.java    | 15 ++++++
 .../java/org/apache/commons/jexl3/JXLTTest.java    | 62 ++++++++++++++++++----
 5 files changed, 83 insertions(+), 16 deletions(-)

diff --git a/src/main/java/org/apache/commons/jexl3/JexlException.java 
b/src/main/java/org/apache/commons/jexl3/JexlException.java
index 01b2018..5ed8a6e 100644
--- a/src/main/java/org/apache/commons/jexl3/JexlException.java
+++ b/src/main/java/org/apache/commons/jexl3/JexlException.java
@@ -1031,9 +1031,13 @@ public class JexlException extends RuntimeException {
      * @param xinvoke the invocation exception
      * @return a JexlException
      */
-    public static RuntimeException tryFailed(InvocationTargetException 
xinvoke) {
-        return new JexlException.TryFailed(xinvoke); // fail
+    public static JexlException tryFailed(InvocationTargetException xinvoke) {
+        Throwable cause = xinvoke.getCause();
+        return cause instanceof JexlException
+                ? (JexlException) cause 
+                : new JexlException.TryFailed(xinvoke); // fail
     }
+
     
     /**
      * Detailed info message about this error.
diff --git a/src/main/java/org/apache/commons/jexl3/internal/Interpreter.java 
b/src/main/java/org/apache/commons/jexl3/internal/Interpreter.java
index 07cc421..10679ac 100644
--- a/src/main/java/org/apache/commons/jexl3/internal/Interpreter.java
+++ b/src/main/java/org/apache/commons/jexl3/internal/Interpreter.java
@@ -1703,7 +1703,7 @@ public class Interpreter extends InterpreterBase {
                     ? null
                     : unsolvableMethod(node, methodName, argv);
         } catch (JexlException.TryFailed xany) {
-            throw invocationException(node, methodName, xany.getCause());
+            throw invocationException(node, methodName, xany);
         } catch (JexlException xthru) {
             throw xthru;
         } catch (Exception xany) {
diff --git 
a/src/main/java/org/apache/commons/jexl3/internal/InterpreterBase.java 
b/src/main/java/org/apache/commons/jexl3/internal/InterpreterBase.java
index cee0905..0b05b4d 100644
--- a/src/main/java/org/apache/commons/jexl3/internal/InterpreterBase.java
+++ b/src/main/java/org/apache/commons/jexl3/internal/InterpreterBase.java
@@ -290,10 +290,14 @@ public abstract class InterpreterBase extends 
ParserVisitor {
         }
         String name = identifier.getName();
         Object value = context.get(name);
-        if (value == null && !context.has(name)
-            && !(identifier.jjtGetParent() instanceof ASTAssignment && 
isSafe())
-            && !(identifier.jjtGetParent() instanceof ASTReference)) {
-            return unsolvableVariable(identifier, name, true); // undefined
+        if (value == null && !context.has(name)) {
+            boolean ignore = (isSafe()
+                    && (symbol >= 0
+                    || identifier.jjtGetParent() instanceof ASTAssignment))
+                    || (identifier.jjtGetParent() instanceof ASTReference);
+            if (!ignore) {
+                return unsolvableVariable(identifier, name, true); // undefined
+            }
         }
         return value;
     }
diff --git a/src/test/java/org/apache/commons/jexl3/Issues200Test.java 
b/src/test/java/org/apache/commons/jexl3/Issues200Test.java
index 3045efd..cdc72f2 100644
--- a/src/test/java/org/apache/commons/jexl3/Issues200Test.java
+++ b/src/test/java/org/apache/commons/jexl3/Issues200Test.java
@@ -651,6 +651,21 @@ public class Issues200Test extends JexlTestCase {
     }
 
     @Test
+    public void test275d() throws Exception {
+        JexlContext ctxt = new MapContext();
+        ctxt.set("out", System.out);
+        JexlEngine jexl = new JexlBuilder().strict(true).safe(true).create();
+
+        JexlScript e = jexl.createScript("{ var xyz = 42 } out.println(xyz)");
+        try {
+            Object o = e.execute(ctxt);
+            Assert.assertNull(o);
+        } catch (JexlException.Variable xvar) {
+            Assert.fail("should not have thrown" + xvar);
+        }
+    }
+    
+    @Test
     public void test278() throws Exception {
         String[] srcs = new String[]{
             "return union x143('arg',5,6) ",
diff --git a/src/test/java/org/apache/commons/jexl3/JXLTTest.java 
b/src/test/java/org/apache/commons/jexl3/JXLTTest.java
index cbea516..f68894b 100644
--- a/src/test/java/org/apache/commons/jexl3/JXLTTest.java
+++ b/src/test/java/org/apache/commons/jexl3/JXLTTest.java
@@ -46,30 +46,30 @@ public class JXLTTest extends JexlTestCase {
     private static final Log LOGGER = LogFactory.getLog(JxltEngine.class);
     private final MapContext vars = new MapContext();
     private JexlEvalContext context = null;
+    private final JexlBuilder BUILDER;
     private final JexlEngine ENGINE;
     private final JxltEngine JXLT;
     
-    public JXLTTest(JexlEngine jexl) {
+    public JXLTTest(JexlBuilder builder) {
         super("JXLTTest");
-        ENGINE = jexl;
+        BUILDER = builder;
+        ENGINE = BUILDER.create();
         JXLT = ENGINE.createJxltEngine();
     }
    
 
    @Parameterized.Parameters
-   public static List<JexlEngine> engines() {
+   public static List<JexlBuilder> engines() {
        JexlFeatures f = new JexlFeatures();
        f.lexical(true).lexicalShade(true);
-      return Arrays.<JexlEngine>asList(new JexlEngine[] {
+      return Arrays.<JexlBuilder>asList(new JexlBuilder[] {
          new JexlBuilder().silent(false)
             .lexical(true).lexicalShade(true)
-            .cache(128).strict(true).create(),
-          
+            .cache(128).strict(true),
          new JexlBuilder().features(f).silent(false)
-            .cache(128).strict(true).create(),
-         
+            .cache(128).strict(true),
          new JexlBuilder().silent(false)
-            .cache(128).strict(true).create(),
+            .cache(128).strict(true),
       });
    }
     
@@ -1088,4 +1088,48 @@ public class JXLTTest extends JexlTestCase {
             Assert.assertFalse(xvar.isUndefined());
         }
     }
+    
+    @Test
+    public void testTemplateOutOfScope() throws Exception {
+        JexlOptions opts = new JexlOptions();
+        opts.setCancellable(false);
+        opts.setStrict(false);
+        opts.setLexical(false);
+        opts.setLexicalShade(false);
+        opts.setSharedInstance(true);
+        JexlContext ctxt = new PragmaticContext(opts);
+        String src = "$$if (false) { var tab = 42; }\n"
+                + "${tab}";
+        JxltEngine.Template tmplt;
+        JexlFeatures features = BUILDER.features();
+        try {
+            tmplt = JXLT.createTemplate("$$", new StringReader(src));
+        } catch (JexlException xparse) {
+            if (features != null && features.isLexicalShade()) {
+                return;
+            }
+            throw xparse;
+        }
+        Writer strw = new StringWriter();
+        opts.setSafe(true);
+        try {
+            tmplt.evaluate(ctxt, strw);
+            Assert.assertTrue(strw.toString().isEmpty());
+        } catch (JexlException.Variable xvar) {
+            Assert.fail("safe should prevent local shade");
+        }
+        opts.setStrict(true);
+        opts.setSafe(false);
+        try {
+            tmplt.evaluate(ctxt, strw);
+            Assert.fail("tab var is undefined");
+        } catch (JexlException.Variable xvar) {
+            Assert.assertTrue("tab".equals(xvar.getVariable()));
+            Assert.assertTrue(xvar.isUndefined());
+        } catch (JexlException xany) {
+            Assert.assertTrue(xany.getMessage().contains("tab"));
+        }
+
+    }
+
 }

Reply via email to