From dc43481fbf967957d60429594607466c968558fb Mon Sep 17 00:00:00 2001 From: Stephen Chung Date: Thu, 23 May 2024 02:06:37 +0800 Subject: [PATCH] Fix stack overflow bug. --- CHANGELOG.md | 1 + src/func/call.rs | 8 ++++++++ tests/stack.rs | 17 +++++++++++++++++ 3 files changed, 26 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index ccff89562..4a7d3699a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,7 @@ Bug fixes * The `sync` feature now works properly in `no-std` builds (thanks [`@misssonder`](https://github.com/misssonder) [874](https://github.com/rhaiscript/rhai/pull/874)). * More data-race conditions are caught and returned as errors instead of panicking. * Missing `min` and `max` functions where both operands are floats or `Decimal` are added. +* Fixed stack overflow when calling closures recursively (thanks [`@MageWeiG`](https://github.com/MageWeiG) [880](https://github.com/rhaiscript/rhai/issues/880)). New features ------------ diff --git a/src/func/call.rs b/src/func/call.rs index 3ab5fe92c..3c002b89e 100644 --- a/src/func/call.rs +++ b/src/func/call.rs @@ -754,6 +754,8 @@ impl Engine { let scope = &mut Scope::new(); let environ = fn_ptr.environ.as_ref().map(<_>::as_ref); + defer! { let orig_level = global.level; global.level += 1 } + self.call_script_fn( global, caches, scope, None, environ, fn_def, args, true, pos, ) @@ -832,6 +834,8 @@ impl Engine { let this_ptr = Some(target.as_mut()); let environ = environ.as_deref(); + defer! { let orig_level = global.level; global.level += 1 } + self.call_script_fn( global, caches, scope, this_ptr, environ, &fn_def, args, true, pos, ) @@ -973,6 +977,8 @@ impl Engine { let this_ptr = Some(target.as_mut()); let args = &mut call_args.iter_mut().collect::>(); + defer! { let orig_level = global.level; global.level += 1 } + self.call_script_fn( global, caches, scope, this_ptr, environ, &fn_def, args, true, pos, ) @@ -1083,6 +1089,8 @@ impl Engine { let scope = &mut Scope::new(); let environ = environ.as_deref(); + defer! { let orig_level = global.level; global.level += 1 } + return self.call_script_fn( global, caches, scope, None, environ, &fn_def, args, true, pos, ); diff --git a/tests/stack.rs b/tests/stack.rs index 1128d2544..f3746abc5 100644 --- a/tests/stack.rs +++ b/tests/stack.rs @@ -32,6 +32,23 @@ fn test_stack_overflow_fn_calls() { .unwrap_err(), EvalAltResult::ErrorStackOverflow(..) )); + + #[cfg(not(feature = "no_function"))] + #[cfg(not(feature = "no_object"))] + assert!(matches!( + *engine + .run( + " + let obj1 = #{ + action: || this.action(), + update: |x| this.action() + }; + obj1.update(1) + " + ) + .unwrap_err(), + EvalAltResult::ErrorStackOverflow(..) + )); } #[test]