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 <[email protected]>
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"));
+ }
+
+ }
+
}