diff options
author | Ben Bridle <ben@derelict.engineering> | 2025-10-15 13:25:28 +1300 |
---|---|---|
committer | Ben Bridle <ben@derelict.engineering> | 2025-10-15 13:25:28 +1300 |
commit | a4c2b3ae304dc53e8e52cc952383b5171ce00b99 (patch) | |
tree | 9f893524673a4a028c9a744b84a624ca0d79ac89 | |
parent | c62da877b370392accfbd8a1087ad5673b6f55e4 (diff) | |
download | torque-asm-a4c2b3ae304dc53e8e52cc952383b5171ce00b99.zip |
Raise an error if recursion depth exceeds a maximum value
This is preferable to having the assembler crash with a stack overflow
error, because the user can now see which invocation caused the
overflow.
-rw-r--r-- | src/lib.rs | 1 | ||||
-rw-r--r-- | src/stages/intermediate.rs | 6 | ||||
-rw-r--r-- | src/stages/intermediate_tokens.rs | 3 |
3 files changed, 10 insertions, 0 deletions
@@ -1,4 +1,5 @@ const MAX_ITERATIONS_TO_STABILISE: usize = 4; +const MAX_RECURSION_DEPTH: usize = 1024; mod stages; mod types; diff --git a/src/stages/intermediate.rs b/src/stages/intermediate.rs index 07773a0..8cabe26 100644 --- a/src/stages/intermediate.rs +++ b/src/stages/intermediate.rs @@ -438,6 +438,12 @@ impl IntermediateParser { unreachable!("Uncaught duplicate macro argument name '{name}'"); }; } + // Test the current recursion depth. + if self.environment_stack.len() == MAX_RECURSION_DEPTH { + let error = IntermediateError::MaxRecursionDepthExceeded; + self.errors.push(Tracked::from(error, source.clone())); + return None; + } // Invoke the macro once. let env = Environment { arguments: argument_map, id: next_id!() }; self.environment_stack.push(env); diff --git a/src/stages/intermediate_tokens.rs b/src/stages/intermediate_tokens.rs index 2fb29fa..d796299 100644 --- a/src/stages/intermediate_tokens.rs +++ b/src/stages/intermediate_tokens.rs @@ -77,6 +77,7 @@ pub enum IntermediateError { /// expected, received ValueTooWide(u32, u32), LabelNeverStabilised(String), + MaxRecursionDepthExceeded, } pub fn report_intermediate_errors(errors: &[Tracked<IntermediateError>], source_code: &str) { @@ -116,6 +117,8 @@ fn report_intermediate_error(error: &Tracked<IntermediateError>, source_code: &s IntermediateError::LabelNeverStabilised(name) => &format!("Label '{name}' never stabilised"), + IntermediateError::MaxRecursionDepthExceeded => + &format!("Macro invocation exceededs the maximum recursion depth of {MAX_RECURSION_DEPTH}"), }; report_source_issue(LogLevel::Error, &context, message); |