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 <hen...@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);
+  }
 }

Reply via email to