You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by he...@apache.org on 2019/01/10 14:25:48 UTC
[commons-jexl] 01/02: JEXL-279: safe navigation was not working on
function call followed by array dereference (call()[0])
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
commit d60c3f610420c5326adbbaa885aceabaf19a4363
Author: henrib <he...@apache.org>
AuthorDate: Thu Jan 10 15:21:31 2019 +0100
JEXL-279: safe navigation was not working on function call followed by array dereference (call()[0])
---
.../apache/commons/jexl3/internal/Interpreter.java | 23 ++++++++++++++++------
.../commons/jexl3/internal/InterpreterBase.java | 2 +-
.../internal/introspection/MapSetExecutor.java | 4 ++--
.../org/apache/commons/jexl3/parser/JexlNode.java | 3 +++
4 files changed, 23 insertions(+), 9 deletions(-)
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 ac48721..17a404a 100644
--- a/src/main/java/org/apache/commons/jexl3/internal/Interpreter.java
+++ b/src/main/java/org/apache/commons/jexl3/internal/Interpreter.java
@@ -1041,6 +1041,16 @@ public class Interpreter extends InterpreterBase {
}
/**
+ * Checks whether a reference child node holds a function call.
+ * @param node the reference node
+ * @return true if child is function call, false otherwise
+ */
+ protected boolean isFunctionCall(ASTReference node) {
+ return (node.jjtGetNumChildren() > 0
+ && node.jjtGetChild(0) instanceof ASTFunctionNode);
+ }
+
+ /**
* Evaluates an access identifier based on the 2 main implementations;
* static (name or numbered identifier) or dynamic (jxlt).
* @param node the identifier access node
@@ -1090,7 +1100,7 @@ public class Interpreter extends InterpreterBase {
final JexlNode parent = node.jjtGetParent();
// pass first piece of data in and loop through children
Object object = null;
- JexlNode objectNode;
+ JexlNode objectNode = null;
JexlNode ptyNode = null;
StringBuilder ant = null;
boolean antish = !(parent instanceof ASTReference);
@@ -1127,7 +1137,7 @@ public class Interpreter extends InterpreterBase {
} else {
antish = false;
}
- }
+ }
// attempt to evaluate the property within the object (visit(ASTIdentifierAccess node))
object = objectNode.jjtAccept(this, object);
cancelCheck(node);
@@ -1179,15 +1189,16 @@ public class Interpreter extends InterpreterBase {
// am I the left-hand side of a safe op ?
return ptyNode.isSafeLhs(jexl.safe)
? null
- : unsolvableProperty(node, stringifyProperty(ptyNode), false, null);
+ : unsolvableProperty(node, stringifyProperty(ptyNode), ptyNode == objectNode, null);
}
if (antish) {
- String aname = ant != null? ant.toString() : stringifyProperty(node);
- boolean undefined = !(context.has(aname) || isLocalVariable(node, 0));
+ String pstr = stringifyProperty(node);
+ String aname = ant != null? ant.toString() : pstr;
+ boolean undefined = !(context.has(aname) || isLocalVariable(node, 0) || isFunctionCall(node));
// variable unknown in context and not a local
return node.isSafeLhs(jexl.safe)
? null
- : unsolvableVariable(node, undefined? stringifyProperty(node) : aname, undefined);
+ : unsolvableVariable(node, undefined? pstr : aname, undefined);
}
}
return object;
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 b5d44fc..cc3e975 100644
--- a/src/main/java/org/apache/commons/jexl3/internal/InterpreterBase.java
+++ b/src/main/java/org/apache/commons/jexl3/internal/InterpreterBase.java
@@ -252,7 +252,7 @@ public abstract class InterpreterBase extends ParserVisitor {
return ((ASTIdentifier) node).getName();
}
if (node instanceof ASTReference) {
- return stringifyPropertyValue(node.jjtGetChild(0));
+ return stringifyProperty(node.jjtGetChild(0));
}
return stringifyPropertyValue(node);
}
diff --git a/src/main/java/org/apache/commons/jexl3/internal/introspection/MapSetExecutor.java b/src/main/java/org/apache/commons/jexl3/internal/introspection/MapSetExecutor.java
index 6a881f8..77180d8 100644
--- a/src/main/java/org/apache/commons/jexl3/internal/introspection/MapSetExecutor.java
+++ b/src/main/java/org/apache/commons/jexl3/internal/introspection/MapSetExecutor.java
@@ -55,10 +55,10 @@ public final class MapSetExecutor extends AbstractExecutor.Set {
* @param key the key to use as 1st argument to the set method
* @param value the value to use as 2nd argument to the set method
*/
- private MapSetExecutor(Class<?> clazz, java.lang.reflect.Method method, Object key, Object arg) {
+ private MapSetExecutor(Class<?> clazz, java.lang.reflect.Method method, Object key, Object value) {
super(clazz, method);
property = key;
- valueClass = classOf(arg);
+ valueClass = classOf(value);
}
@Override
diff --git a/src/main/java/org/apache/commons/jexl3/parser/JexlNode.java b/src/main/java/org/apache/commons/jexl3/parser/JexlNode.java
index 2a91f5e..7033178 100644
--- a/src/main/java/org/apache/commons/jexl3/parser/JexlNode.java
+++ b/src/main/java/org/apache/commons/jexl3/parser/JexlNode.java
@@ -227,6 +227,9 @@ public abstract class JexlNode extends SimpleNode {
&& (((ASTIdentifierAccess) rsibling).isSafe() || safe)) {
return true;
}
+ if (rsibling instanceof ASTArrayAccess) {
+ return safe;
+ }
}
return false;
}