mirror of
https://github.com/microsoft/regorus.git
synced 2026-08-05 02:16:11 +00:00
chore(rvm): add debug-mode invariant assertions (#737)
Encode VM stack/context/register lifecycle invariants as debug_assert!s. Zero cost in release; surfaces violations during debug-mode tests and CI. Invariants covered: - reset_execution_state postcondition: all stacks empty, registers resized to base and Undefined, rule_cache reset, pc/executed counters zeroed, builtins_cache cleared, execution_state Ready. - Per-opcode invariant check (assert_vm_invariants) invoked at the top of run_stackless_loop and jump_to iterations: state is Ready/Running, registers non-empty, rule_cache sized to program, execution stack bounded by a debug-only sanity ceiling (DEBUG_MAX_EXECUTION_STACK_DEPTH = 4096; not a production limit). - resume() precondition: execution_state is Suspended. - execute_suspendable_entry precondition: clean state (callers reset immediately before). - Rule finalize: call_rule_stack pop matches the finalized rule_index. - IterationState::advance: Single iterator not advanced past consumption, Array index not at usize::MAX before saturating_add. All assertions are gated by #[cfg(debug_assertions)] (directly or via debug_assert!) so release builds are unaffected. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
committed by
GitHub
parent
ba7d29b134
commit
5b7010ba16
@@ -54,6 +54,14 @@ impl IterationState {
|
||||
pub(super) const fn advance(&mut self) {
|
||||
match *self {
|
||||
Self::Array { ref mut index, .. } => {
|
||||
// Array iteration uses `usize` as the cursor and advances via
|
||||
// `saturating_add(1)`. A cursor already at `usize::MAX` here
|
||||
// means a stuck (non-progressing) iteration was emitted by
|
||||
// malformed bytecode; assert in debug to surface it loudly.
|
||||
debug_assert!(
|
||||
*index < usize::MAX,
|
||||
"IterationState::Array index already at usize::MAX on advance"
|
||||
);
|
||||
*index = index.saturating_add(1);
|
||||
}
|
||||
Self::Object {
|
||||
@@ -69,6 +77,12 @@ impl IterationState {
|
||||
Self::Single {
|
||||
ref mut consumed, ..
|
||||
} => {
|
||||
// `Single` yields exactly once; advancing a consumed Single
|
||||
// means the compiler emitted a redundant LoopNext.
|
||||
debug_assert!(
|
||||
!*consumed,
|
||||
"IterationState::Single advanced after consumption"
|
||||
);
|
||||
*consumed = true;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user