Skip to main content

Module recursion_guard

Module recursion_guard 

Source
Expand description

Bounded-depth guard for the re-lowering walks.

Both crate::extract_call_sites and crate::extract_table_accesses descend through control-flow statements (IF / LOOP / nested block) by re-lowering the captured raw body text and recursing into the result. This is sound only while the captured slice strictly shrinks on each pass. On a malformed / parser-recovered unit (e.g. an IF whose END IF is missing, so the text-scanner’s rfind("END IF") falls back to text.len() and the arm body re-captures almost the whole input) the slice fails to shrink and the mutual recursion is unbounded — a real stack-overflow / SIGABRT seen on the bundled public fixture corpus/synthetic/l1.

The guard caps recursion depth. Hitting the cap is not silently swallowed: the walk records that it degraded a nested body, the caller surfaces a typed plsql_core::UnknownReason::AnalysisRecursionLimit + Diagnostic with provenance, and the rest of the analysis continues (R13: honest degradation, never crash, never hide uncertainty — the anti-pattern is not to cap silently).

Structs§

RecursionOutcome
Outcome of a bounded re-lowering walk: whether the depth cap was hit (so the caller can emit a typed degradation) and how many distinct nested bodies were truncated.

Constants§

MAX_RELOWER_DEPTH
Maximum re-lowering recursion depth. Real well-formed PL/SQL nests far below this (the deepest private-estate control-flow body re-lowered is < 30 levels); the cap exists only to make a non-shrinking malformed slice terminate. Chosen high enough that it never clips genuine extraction on well-formed input and low enough that 128 stack frames of the walk cannot overflow the default 8 MiB main-thread stack.