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