mirror of
https://github.com/danbulant/oxc
synced 2026-05-25 04:42:10 +00:00
docs(traverse): document soundness hole (#7515)
Document the remaining (small) soundness hole in `Traverse`.
This commit is contained in:
parent
f2f31a8d7a
commit
4d157c583b
1 changed files with 20 additions and 0 deletions
|
|
@ -39,6 +39,26 @@ const INITIAL_STACK_CAPACITY: usize = 64; // 64 entries = 1 KiB
|
||||||
/// - `TraverseAncestry::new` and `TraverseCtx::new` are private.
|
/// - `TraverseAncestry::new` and `TraverseCtx::new` are private.
|
||||||
/// b. cannot obtain an owned `TraverseAncestry` from a `&TraverseAncestry`
|
/// b. cannot obtain an owned `TraverseAncestry` from a `&TraverseAncestry`
|
||||||
/// - `TraverseAncestry` is not `Clone`.
|
/// - `TraverseAncestry` is not `Clone`.
|
||||||
|
///
|
||||||
|
/// ## Soundness hole
|
||||||
|
///
|
||||||
|
/// Strictly speaking, there is still room to abuse the API and cause UB as follows:
|
||||||
|
///
|
||||||
|
/// * Initiate a 2nd traversal of a different AST inside a `Traverse` visitor method.
|
||||||
|
/// * `mem::swap` the 2 x `&mut TraverseCtx`s from the 2 different traversals.
|
||||||
|
///
|
||||||
|
/// The 2 ASTs would have to be different, but borrowed for same lifetime, so I (@overlookmotel) don't
|
||||||
|
/// think it's possible by this method to produce aliasing violations, or to over-extend AST node
|
||||||
|
/// lifetimes to cause a use-after-free.
|
||||||
|
/// But it *could* produce buffer underrun in `pop_stack`, when it tries to pop from a stack which
|
||||||
|
/// is already empty.
|
||||||
|
///
|
||||||
|
/// In practice, this would be a completely bizarre thing to do, and would basically require you to
|
||||||
|
/// write malicious code specifically designed to cause UB. So it's not a particularly real risk.
|
||||||
|
///
|
||||||
|
/// To close this hole and make the API 100% sound, we'd need branded lifetimes so that all
|
||||||
|
/// `TraverseCtx`s have unique lifetimes, and so cannot be swapped for any other without
|
||||||
|
/// the borrow-checker complaining.
|
||||||
pub struct TraverseAncestry<'a> {
|
pub struct TraverseAncestry<'a> {
|
||||||
stack: NonEmptyStack<Ancestor<'a, 'static>>,
|
stack: NonEmptyStack<Ancestor<'a, 'static>>,
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue