From 9e3f35384fe7e1a56289a4ad0e2e557cb77d4943 Mon Sep 17 00:00:00 2001 From: Luna712 <142361265+Luna712@users.noreply.github.com> Date: Thu, 18 Jun 2026 16:20:24 -0600 Subject: [PATCH 1/6] Try depth fix --- .../kotlin/com/lagradost/cloudstream3/utils/JsInterpreter.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/src/commonMain/kotlin/com/lagradost/cloudstream3/utils/JsInterpreter.kt b/library/src/commonMain/kotlin/com/lagradost/cloudstream3/utils/JsInterpreter.kt index 5bb5457f324..28030834f05 100644 --- a/library/src/commonMain/kotlin/com/lagradost/cloudstream3/utils/JsInterpreter.kt +++ b/library/src/commonMain/kotlin/com/lagradost/cloudstream3/utils/JsInterpreter.kt @@ -844,7 +844,7 @@ private class JsInterpreter { last } catch (r: ReturnSignal) { r.value - } catch (e: Throwable) { + } catch (e: Exception) { logError(e) Unit } From c63789f58b115e2a013bf3385918b16ba5c7003f Mon Sep 17 00:00:00 2001 From: Luna712 <142361265+Luna712@users.noreply.github.com> Date: Thu, 18 Jun 2026 18:38:42 -0600 Subject: [PATCH 2/6] Add check --- .../lagradost/cloudstream3/utils/JsInterpreter.kt | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/library/src/commonMain/kotlin/com/lagradost/cloudstream3/utils/JsInterpreter.kt b/library/src/commonMain/kotlin/com/lagradost/cloudstream3/utils/JsInterpreter.kt index 28030834f05..9c9f2ae661d 100644 --- a/library/src/commonMain/kotlin/com/lagradost/cloudstream3/utils/JsInterpreter.kt +++ b/library/src/commonMain/kotlin/com/lagradost/cloudstream3/utils/JsInterpreter.kt @@ -269,6 +269,8 @@ private data class TryCatch(val body: List, val catchParam: String?, val c private data class ThrowStmt(val expr: Node) : Node() private class Parser(private val lex: Lexer) { + private var depth = 0 + private val maxDepth = 500 fun parseProgram(): List { val stmts = mutableListOf() @@ -594,7 +596,9 @@ private class Parser(private val lex: Lexer) { TT.STRING -> { lex.consume(); StrLit(tok.raw) } TT.LPAREN -> { lex.consume() + if (++depth > maxDepth) { depth--; return UndefinedLit } val expr = parseSeq() + depth-- lex.expect(TT.RPAREN) expr } @@ -743,6 +747,8 @@ private class Scope(val parent: Scope? = null) { private class JsInterpreter { private val globalScope = Scope() + private var evalDepth = 0 + private val maxEvalDepth = 500 init { installGlobals() } @@ -929,7 +935,14 @@ private class JsInterpreter { else -> evalExpr(node, scope) } - private fun evalExpr(node: Node, scope: Scope): Any? = when (node) { + private fun evalExpr(node: Node, scope: Scope): Any? { + if (++evalDepth > maxEvalDepth) { evalDepth--; return Unit } + val result = evalExprInner(node, scope) + evalDepth-- + return result + } + + private fun evalExprInner(node: Node, scope: Scope): Any? = when (node) { is NumLit -> node.v is StrLit -> node.v is BoolLit -> node.v From 01572c02ef2850608af65ef69361fe30f845cb66 Mon Sep 17 00:00:00 2001 From: Luna712 <142361265+Luna712@users.noreply.github.com> Date: Thu, 18 Jun 2026 18:47:50 -0600 Subject: [PATCH 3/6] Add tests --- .../cloudstream3/utils/JsInterpreterTest.kt | 45 +++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/library/src/commonTest/kotlin/com/lagradost/cloudstream3/utils/JsInterpreterTest.kt b/library/src/commonTest/kotlin/com/lagradost/cloudstream3/utils/JsInterpreterTest.kt index 4d0f01b5a60..462a2810068 100644 --- a/library/src/commonTest/kotlin/com/lagradost/cloudstream3/utils/JsInterpreterTest.kt +++ b/library/src/commonTest/kotlin/com/lagradost/cloudstream3/utils/JsInterpreterTest.kt @@ -1832,4 +1832,49 @@ class JsInterpreterTest { fun bitwiseTruncationPattern() { assertEquals(5.0, num("(11/2)|0")) } + + @Test + fun deeplyNestedParenthesesDoesNotStackOverflow() { + val open = "(".repeat(600) + val close = ")".repeat(600) + val result = evalJs("${open}42${close}") + assertTrue(result == Unit || result == 42.0) + } + + @Test + fun extremelyDeeplyNestedParenthesesDoesNotStackOverflow() { + val open = "(".repeat(2000) + val close = ")".repeat(2000) + val result = evalJs("${open}1${close}") + assertTrue(result == Unit || result == 1.0) + } + + @Test + fun deeplyRecursiveFunctionDoesNotStackOverflow() { + val code = """ + function f(n) { return n <= 0 ? 0 : f(n-1) + 1; } + f(600) + """.trimIndent() + val result = evalJs(code) + assertTrue(result == Unit || result is Double) + } + + @Test + fun infiniteRecursionDoesNotStackOverflow() { + val code = """ + function inf() { return inf(); } + inf() + """.trimIndent() + val result = evalJs(code) + assertTrue(result == Unit || result is Double) + } + + @Test + fun deeplyNestedFunctionCallsDoNotStackOverflow() { + val depth = 300 + val decls = (1..depth).joinToString("\n") { "function f$it(x){return x+1;}" } + val call = (1 until depth).fold("f${depth}(0)") { acc, i -> "f$i($acc)" } + val result = evalJs("$decls\n$call") + assertTrue(result == Unit || result is Double) + } } From 63abad7af0209b467def8690215d205b90dd437b Mon Sep 17 00:00:00 2001 From: Luna712 <142361265+Luna712@users.noreply.github.com> Date: Thu, 18 Jun 2026 18:51:51 -0600 Subject: [PATCH 4/6] Fix --- .../lagradost/cloudstream3/utils/JsInterpreter.kt | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/library/src/commonMain/kotlin/com/lagradost/cloudstream3/utils/JsInterpreter.kt b/library/src/commonMain/kotlin/com/lagradost/cloudstream3/utils/JsInterpreter.kt index 9c9f2ae661d..91610938e13 100644 --- a/library/src/commonMain/kotlin/com/lagradost/cloudstream3/utils/JsInterpreter.kt +++ b/library/src/commonMain/kotlin/com/lagradost/cloudstream3/utils/JsInterpreter.kt @@ -270,7 +270,7 @@ private data class ThrowStmt(val expr: Node) : Node() private class Parser(private val lex: Lexer) { private var depth = 0 - private val maxDepth = 500 + private val maxDepth = 25 fun parseProgram(): List { val stmts = mutableListOf() @@ -748,7 +748,7 @@ private class Scope(val parent: Scope? = null) { private class JsInterpreter { private val globalScope = Scope() private var evalDepth = 0 - private val maxEvalDepth = 500 + private val maxEvalDepth = 200 init { installGlobals() } @@ -859,7 +859,14 @@ private class JsInterpreter { fun getVar(name: String): Any? = globalScope.get(name).let { if (it is Unit) null else it } fun setVar(name: String, value: Any?) = globalScope.define(name, value) - private fun execNode(node: Node, scope: Scope): Any? = when (node) { + private fun execNode(node: Node, scope: Scope): Any? { + if (++evalDepth > maxEvalDepth) { evalDepth--; return Unit } + val result = execNodeInner(node, scope) + evalDepth-- + return result + } + + private fun execNodeInner(node: Node, scope: Scope): Any? = when (node) { is VarDecl -> { for ((name, init) in node.decls) scope.define(name, init?.let { evalExpr(it, scope) }) Unit From 217e414e64dc499a996359031f5752606940eeb5 Mon Sep 17 00:00:00 2001 From: Luna712 <142361265+Luna712@users.noreply.github.com> Date: Thu, 18 Jun 2026 18:55:24 -0600 Subject: [PATCH 5/6] Fix --- .../kotlin/com/lagradost/cloudstream3/utils/JsInterpreter.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/library/src/commonMain/kotlin/com/lagradost/cloudstream3/utils/JsInterpreter.kt b/library/src/commonMain/kotlin/com/lagradost/cloudstream3/utils/JsInterpreter.kt index 91610938e13..1b0409dc69c 100644 --- a/library/src/commonMain/kotlin/com/lagradost/cloudstream3/utils/JsInterpreter.kt +++ b/library/src/commonMain/kotlin/com/lagradost/cloudstream3/utils/JsInterpreter.kt @@ -440,7 +440,9 @@ private class Parser(private val lex: Lexer) { } private fun parseAssign(): Node { + if (++depth > maxDepth) { depth--; return UndefinedLit } val left = parseTernary() + depth-- val op = when (lex.peek().type) { TT.EQ -> "="; TT.PLUSEQ -> "+="; TT.MINUSEQ -> "-="; TT.STAREQ -> "*="; TT.SLASHEQ -> "/="; TT.PERCENTEQ -> "%=" else -> return left @@ -596,9 +598,7 @@ private class Parser(private val lex: Lexer) { TT.STRING -> { lex.consume(); StrLit(tok.raw) } TT.LPAREN -> { lex.consume() - if (++depth > maxDepth) { depth--; return UndefinedLit } val expr = parseSeq() - depth-- lex.expect(TT.RPAREN) expr } From 0e8cceea6f7821bff6a3d66fcf455bd3a311a8aa Mon Sep 17 00:00:00 2001 From: Luna712 <142361265+Luna712@users.noreply.github.com> Date: Thu, 18 Jun 2026 19:07:45 -0600 Subject: [PATCH 6/6] - --- .../com/lagradost/cloudstream3/utils/JsInterpreter.kt | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/library/src/commonMain/kotlin/com/lagradost/cloudstream3/utils/JsInterpreter.kt b/library/src/commonMain/kotlin/com/lagradost/cloudstream3/utils/JsInterpreter.kt index 1b0409dc69c..4cd96ae6489 100644 --- a/library/src/commonMain/kotlin/com/lagradost/cloudstream3/utils/JsInterpreter.kt +++ b/library/src/commonMain/kotlin/com/lagradost/cloudstream3/utils/JsInterpreter.kt @@ -859,14 +859,7 @@ private class JsInterpreter { fun getVar(name: String): Any? = globalScope.get(name).let { if (it is Unit) null else it } fun setVar(name: String, value: Any?) = globalScope.define(name, value) - private fun execNode(node: Node, scope: Scope): Any? { - if (++evalDepth > maxEvalDepth) { evalDepth--; return Unit } - val result = execNodeInner(node, scope) - evalDepth-- - return result - } - - private fun execNodeInner(node: Node, scope: Scope): Any? = when (node) { + private fun execNode(node: Node, scope: Scope): Any? = when (node) { is VarDecl -> { for ((name, init) in node.decls) scope.define(name, init?.let { evalExpr(it, scope) }) Unit