safety(codegen): debug_assert companion for every unsafe get_unchecked
Pair every codegen-emitted `unsafe { ... get_unchecked ... }` with a
debug_assert! that re-states the safety obligation as a runtime
predicate. Free in release (debug_assert! compiles to nothing); in
dev/test/miri builds, every dispatch through the 68 behavior tests
exercises these checks, so any future regression in the codegen's
invariants trips loudly.
Sites covered:
- step()'s __DISPATCH lookup (sync + async)
- apply_path()'s __PATH_RANGE +
__PATH_DATA[..] slice ranges (sync + async)
- follow_defaults()'s __DEFAULT_CHILD lookup (sync + async)
- do_terminate()'s __TERMINATE_RANGE +
__TERMINATE_DATA[..] slice ranges (sync + async)
Verification:
- cargo nextest: 68/68 pass (debug_assert! active)
- cargo +nightly miri test: 66/66 pass (UB detector)
- cargo bench --bench dispatch: zero release-mode regression
(asserts compile out as expected)
This commit is contained in:
1 file changed
+13
@@ -2691,6 +2691,11 @@ pub fn generate(ir: &Ir) -> TokenStream {
|
||||
// values < #n_states. __ev_id was checked != u16::MAX
|
||||
// and __event_to_id returns < #n_events otherwise.
|
||||
// Hence __dispatch_idx < #n_dispatch = __DISPATCH.len().
|
||||
// The debug_assert is the safety obligation
|
||||
// expressed at runtime in debug builds — every
|
||||
// hsmc behavior test exercises this site, so a
|
||||
// codegen invariant break trips it loudly.
|
||||
debug_assert!(__dispatch_idx < __DISPATCH.len());
|
||||
let (__handler_state, __actions, __target) = unsafe {
|
||||
*__DISPATCH.get_unchecked(__dispatch_idx)
|
||||
};
|
||||
@@ -2973,7 +2978,9 @@ pub fn generate(ir: &Ir) -> TokenStream {
|
||||
// The triple (s, m, e) was emitted at codegen with the
|
||||
// invariant 0 <= s <= m <= e <= __PATH_DATA.len(), so the
|
||||
// two slice ranges are in-bounds.
|
||||
debug_assert!(idx < __PATH_RANGE.len());
|
||||
let (s, m, e) = unsafe { *__PATH_RANGE.get_unchecked(idx) };
|
||||
debug_assert!((s as usize) <= (m as usize) && (m as usize) <= (e as usize) && (e as usize) <= __PATH_DATA.len());
|
||||
let exit_path = unsafe {
|
||||
__PATH_DATA.get_unchecked(s as usize..m as usize)
|
||||
};
|
||||
@@ -3107,6 +3114,7 @@ pub fn generate(ir: &Ir) -> TokenStream {
|
||||
while let Some(cur) = self.current {
|
||||
// SAFETY: cur is a state id < #n_states (codegen
|
||||
// invariant — see __DISPATCH lookup safety note).
|
||||
debug_assert!((cur as usize) < __DEFAULT_CHILD.len());
|
||||
let target = match unsafe { *__DEFAULT_CHILD.get_unchecked(cur as usize) } {
|
||||
Some(t) => t,
|
||||
None => return,
|
||||
@@ -3128,6 +3136,7 @@ pub fn generate(ir: &Ir) -> TokenStream {
|
||||
async fn follow_defaults(&mut self) {
|
||||
while let Some(cur) = self.current {
|
||||
// SAFETY: see sync branch — same invariant.
|
||||
debug_assert!((cur as usize) < __DEFAULT_CHILD.len());
|
||||
let target = match unsafe { *__DEFAULT_CHILD.get_unchecked(cur as usize) } {
|
||||
Some(t) => t,
|
||||
None => return,
|
||||
@@ -3208,7 +3217,9 @@ pub fn generate(ir: &Ir) -> TokenStream {
|
||||
if let Some(cur) = self.current {
|
||||
// SAFETY: cur < #n_states (codegen invariant). The
|
||||
// (s, e) tuple was emitted with 0 <= s <= e <= len.
|
||||
debug_assert!((cur as usize) < __TERMINATE_RANGE.len());
|
||||
let (s, e) = unsafe { *__TERMINATE_RANGE.get_unchecked(cur as usize) };
|
||||
debug_assert!((s as usize) <= (e as usize) && (e as usize) <= __TERMINATE_DATA.len());
|
||||
let path = unsafe {
|
||||
__TERMINATE_DATA.get_unchecked(s as usize..e as usize)
|
||||
};
|
||||
@@ -3226,7 +3237,9 @@ pub fn generate(ir: &Ir) -> TokenStream {
|
||||
async fn do_terminate(&mut self) {
|
||||
if let Some(cur) = self.current {
|
||||
// SAFETY: see sync branch — same invariant.
|
||||
debug_assert!((cur as usize) < __TERMINATE_RANGE.len());
|
||||
let (s, e) = unsafe { *__TERMINATE_RANGE.get_unchecked(cur as usize) };
|
||||
debug_assert!((s as usize) <= (e as usize) && (e as usize) <= __TERMINATE_DATA.len());
|
||||
let path = unsafe {
|
||||
__TERMINATE_DATA.get_unchecked(s as usize..e as usize)
|
||||
};
|
||||
|
||||
Reference in new issue
Block a user