From a0002b6d4179847d18a7630b640ba6a7435fb53a Mon Sep 17 00:00:00 2001 From: Duy Tran Date: Fri, 24 May 2024 03:25:19 +0700 Subject: [PATCH] Check recursion limit in `VisitorLevelSpecification` (#991) Check recursion limit in `VisitorLevelSpecification` instead of relying on Java's StackOverflowError. The current implementation may not work, JVM may kill the process when StackOverflowError occurs. ``` default IExpr acceptChecked(IVisitor visitor) { try { return accept(visitor); } catch (StackOverflowError soe) { RecursionLimitExceeded.throwIt(Integer.MAX_VALUE, this); } return F.NIL; } ``` Co-authored-by: Duy Tran --- .../core/visit/VisitorLevelSpecification.java | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/symja_android_library/matheclipse-core/src/main/java/org/matheclipse/core/visit/VisitorLevelSpecification.java b/symja_android_library/matheclipse-core/src/main/java/org/matheclipse/core/visit/VisitorLevelSpecification.java index 480b7b3b3f..6d569c36dd 100644 --- a/symja_android_library/matheclipse-core/src/main/java/org/matheclipse/core/visit/VisitorLevelSpecification.java +++ b/symja_android_library/matheclipse-core/src/main/java/org/matheclipse/core/visit/VisitorLevelSpecification.java @@ -1,7 +1,10 @@ package org.matheclipse.core.visit; import java.util.function.Function; + +import org.matheclipse.core.basic.Config; import org.matheclipse.core.eval.EvalEngine; +import org.matheclipse.core.eval.exception.RecursionLimitExceeded; import org.matheclipse.core.eval.exception.SymjaMathException; import org.matheclipse.core.expression.F; import org.matheclipse.core.interfaces.IASTMutable; @@ -188,6 +191,7 @@ public IExpr visit(IAssociation assoc) { int[] minDepth = new int[] {0}; try { fCurrentLevel++; + checkRecursionLimit(assoc); if (fIncludeHeads) { // no include head for associations } @@ -228,6 +232,7 @@ public IExpr visit(IASTMutable ast) { int[] minDepth = new int[] {0}; try { fCurrentLevel++; + checkRecursionLimit(ast); if (fIncludeHeads) { final IExpr temp = ast.get(0).accept(this); if (temp.isPresent()) { @@ -270,6 +275,12 @@ public IExpr visit(IASTMutable ast) { return result[0]; } + private void checkRecursionLimit(IExpr expr) { + if (this.fCurrentLevel > EvalEngine.get().getRecursionLimit()) { + RecursionLimitExceeded.throwIt(this.fCurrentLevel, expr); + } + } + /** * Can be overridden in derived visitors. *