Skip to main content

luaur_analysis/methods/
recursion_limiter_recursion_limiter.rs

1use crate::records::internal_compiler_error::InternalCompilerError;
2use crate::records::recursion_counter::RecursionCounter;
3use crate::records::recursion_limit_exception::RecursionLimitException;
4use crate::records::recursion_limiter::RecursionLimiter;
5use alloc::format;
6use alloc::string::String;
7
8impl RecursionLimiter {
9    pub fn recursion_limiter_recursion_limiter(
10        &mut self,
11        system: &str,
12        count: *mut core::ffi::c_int,
13        limit: core::ffi::c_int,
14    ) {
15        unsafe {
16            core::ptr::write(
17                &mut self.base as *mut RecursionCounter,
18                RecursionCounter::recursion_counter_i32(count),
19            );
20        }
21
22        self.native_stack_guard.native_stack_guard();
23
24        if !self.native_stack_guard.is_ok() {
25            let err = InternalCompilerError::internal_compiler_error_string(format!(
26                "Stack overflow in {}",
27                system
28            ));
29            std::panic::panic_any(err);
30        }
31
32        if limit > 0 && unsafe { *self.base.count > limit } {
33            let err = RecursionLimitException::new(system);
34            // Panic with the exception's owned message String. The previous
35            // `CStr::from_ptr(err.base.what())` read the String's bytes as a
36            // NUL-terminated C string and over-ran past the end, so the surfaced
37            // message carried trailing garbage (e.g. "...in areEqual5\u{fffd}").
38            // luaD_rawrunprotected downcasts this String payload into a LUA_ERRRUN
39            // message, so a user type function that trips the limit reports
40            // "'<fn>' type function errored at runtime: Internal recursion counter
41            // limit exceeded in <system>" (type_function_user_udtf_areequal_*).
42            panic!("{}", err.base.message);
43        }
44    }
45}