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 2023/08/30 18:48:30 UTC
[commons-jexl] branch master updated: JEXL-405: avoid corrupting frame by ensuring auto-capture of recursive function variable is only called at definition time;
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 37fda79e JEXL-405: avoid corrupting frame by ensuring auto-capture of recursive function variable is only called at definition time;
new d59714b4 Merge remote-tracking branch 'origin/master'
37fda79e is described below
commit 37fda79ec11d236e745a5dbfadeacf7c61c6819f
Author: henrib <he...@apache.org>
AuthorDate: Wed Aug 30 20:44:45 2023 +0200
JEXL-405: avoid corrupting frame by ensuring auto-capture of recursive function variable is only called at definition time;
---
.../org/apache/commons/jexl3/internal/Closure.java | 7 +++++
.../apache/commons/jexl3/internal/Interpreter.java | 8 ++++--
.../org/apache/commons/jexl3/internal/Scope.java | 4 +++
.../org/apache/commons/jexl3/Issues400Test.java | 32 ++++++++++++++++++++++
4 files changed, 49 insertions(+), 2 deletions(-)
diff --git a/src/main/java/org/apache/commons/jexl3/internal/Closure.java b/src/main/java/org/apache/commons/jexl3/internal/Closure.java
index aeaaac34..733ef85a 100644
--- a/src/main/java/org/apache/commons/jexl3/internal/Closure.java
+++ b/src/main/java/org/apache/commons/jexl3/internal/Closure.java
@@ -150,4 +150,11 @@ public class Closure extends Script {
}
};
}
+
+ boolean hasParent(Scope scope) {
+ Scope s = frame != null? frame.getScope() : null;
+ return scope != null && s != null
+ ? scope == s.getParent()
+ : false;
+ }
}
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 5b6ffdf1..80397f5e 100644
--- a/src/main/java/org/apache/commons/jexl3/internal/Interpreter.java
+++ b/src/main/java/org/apache/commons/jexl3/internal/Interpreter.java
@@ -1069,7 +1069,7 @@ public class Interpreter extends InterpreterBase {
this.visit(variable, data);
final int symbol = variable.getSymbol();
frame.set(symbol, closure);
- // make the closure accessible to itself, ie capture the currently set variable after frame creation
+ // make the closure accessible to itself, ie capture the 'function' variable after frame creation
closure.setCaptured(symbol, closure);
}
return closure;
@@ -1428,7 +1428,11 @@ public class Interpreter extends InterpreterBase {
if (assignop == null) {
// make the closure accessible to itself, ie capture the currently set variable after frame creation
if (right instanceof Closure) {
- ((Closure) right).setCaptured(symbol, right);
+ Closure closure = (Closure) right;
+ // the variable scope must be the parent of the lambdas
+ if (closure.hasParent(frame.getScope())) {
+ closure.setCaptured(symbol, right);
+ }
}
frame.set(symbol, right);
} else {
diff --git a/src/main/java/org/apache/commons/jexl3/internal/Scope.java b/src/main/java/org/apache/commons/jexl3/internal/Scope.java
index 3f71c888..3d7028a0 100644
--- a/src/main/java/org/apache/commons/jexl3/internal/Scope.java
+++ b/src/main/java/org/apache/commons/jexl3/internal/Scope.java
@@ -349,4 +349,8 @@ public final class Scope {
return locals.toArray(new String[0]);
}
+
+ Scope getParent() {
+ return parent;
+ }
}
diff --git a/src/test/java/org/apache/commons/jexl3/Issues400Test.java b/src/test/java/org/apache/commons/jexl3/Issues400Test.java
index f760dae7..b988ff02 100644
--- a/src/test/java/org/apache/commons/jexl3/Issues400Test.java
+++ b/src/test/java/org/apache/commons/jexl3/Issues400Test.java
@@ -155,4 +155,36 @@ public class Issues400Test {
result = script.execute(null, a);
Assert.assertEquals(1042, result);
}
+
+ @Test
+ public void test405a() {
+ final JexlEngine jexl = new JexlBuilder()
+ .cache(64)
+ .strict(true)
+ .safe(false)
+ .create();
+ String libSrc = "var tfn = pfn -> { var fn = pfn; fn() }; { 'theFunction' : tfn }";
+ String src1 = "var v0 = 42; var v1 = -42; lib.theFunction(()->{ v1 + v0 }) ";
+ JexlScript libMap = jexl.createScript(libSrc);
+ Object theLib = libMap.execute(null);
+ JexlScript f1 = jexl.createScript(src1, "lib");
+ Object result = f1.execute(null, theLib);
+ Assert.assertEquals(0, result);
+ }
+
+ @Test
+ public void test405b() {
+ final JexlEngine jexl = new JexlBuilder()
+ .cache(64)
+ .strict(true)
+ .safe(false)
+ .create();
+ String libSrc = "function tfn(pfn) { var fn = pfn; fn() }; { 'theFunction' : tfn }";
+ String src1 = "var v0 = 42; var v1 = -42; lib.theFunction(()->{ v1 + v0 }) ";
+ JexlScript libMap = jexl.createScript(libSrc);
+ Object theLib = libMap.execute(null);
+ JexlScript f1 = jexl.createScript(src1, "lib");
+ Object result = f1.execute(null, theLib);
+ Assert.assertEquals(0, result);
+ }
}