From 9f8f2997c4fc7c9d0933aa8cacb09a258dfbc520 Mon Sep 17 00:00:00 2001 From: overlookmotel <557937+overlookmotel@users.noreply.github.com> Date: Tue, 6 Aug 2024 01:04:07 +0000 Subject: [PATCH] fix(syntax): prevent creating invalid u32 IDs (#4675) Panic if try to create an `AstNodeId`, `ReferenceId`, `ScopeId` or `SymbolId` from a `usize` which can't be stored as a `u32`. Previously we checked for `u32::MAX`, but didn't check for numbers larger than that. --- crates/oxc_syntax/src/node.rs | 4 +++- crates/oxc_syntax/src/reference.rs | 4 +++- crates/oxc_syntax/src/scope.rs | 4 +++- crates/oxc_syntax/src/symbol.rs | 4 +++- 4 files changed, 12 insertions(+), 4 deletions(-) diff --git a/crates/oxc_syntax/src/node.rs b/crates/oxc_syntax/src/node.rs index 8f8b1fe5bfa1c..d0d5288dedc4f 100644 --- a/crates/oxc_syntax/src/node.rs +++ b/crates/oxc_syntax/src/node.rs @@ -38,7 +38,9 @@ impl AstNodeId { impl Idx for AstNodeId { #[allow(clippy::cast_possible_truncation)] fn from_usize(idx: usize) -> Self { - Self(NonMaxU32::new(idx as u32).unwrap()) + assert!(idx < u32::MAX as usize); + // SAFETY: We just checked `idx` is valid for `NonMaxU32` + Self(unsafe { NonMaxU32::new_unchecked(idx as u32) }) } fn index(self) -> usize { diff --git a/crates/oxc_syntax/src/reference.rs b/crates/oxc_syntax/src/reference.rs index 5d1179ae6d1f1..b90dbfbe786f9 100644 --- a/crates/oxc_syntax/src/reference.rs +++ b/crates/oxc_syntax/src/reference.rs @@ -11,7 +11,9 @@ pub struct ReferenceId(NonMaxU32); impl Idx for ReferenceId { #[allow(clippy::cast_possible_truncation)] fn from_usize(idx: usize) -> Self { - Self(NonMaxU32::new(idx as u32).unwrap()) + assert!(idx < u32::MAX as usize); + // SAFETY: We just checked `idx` is valid for `NonMaxU32` + Self(unsafe { NonMaxU32::new_unchecked(idx as u32) }) } fn index(self) -> usize { diff --git a/crates/oxc_syntax/src/scope.rs b/crates/oxc_syntax/src/scope.rs index 323778e96631a..dd6e064d15248 100644 --- a/crates/oxc_syntax/src/scope.rs +++ b/crates/oxc_syntax/src/scope.rs @@ -35,7 +35,9 @@ impl ScopeId { impl Idx for ScopeId { #[allow(clippy::cast_possible_truncation)] fn from_usize(idx: usize) -> Self { - Self(NonMaxU32::new(idx as u32).unwrap()) + assert!(idx < u32::MAX as usize); + // SAFETY: We just checked `idx` is valid for `NonMaxU32` + Self(unsafe { NonMaxU32::new_unchecked(idx as u32) }) } fn index(self) -> usize { diff --git a/crates/oxc_syntax/src/symbol.rs b/crates/oxc_syntax/src/symbol.rs index ea2fed8839211..7dc08bcd1e863 100644 --- a/crates/oxc_syntax/src/symbol.rs +++ b/crates/oxc_syntax/src/symbol.rs @@ -11,7 +11,9 @@ pub struct SymbolId(NonMaxU32); impl Idx for SymbolId { #[allow(clippy::cast_possible_truncation)] fn from_usize(idx: usize) -> Self { - Self(NonMaxU32::new(idx as u32).unwrap()) + assert!(idx < u32::MAX as usize); + // SAFETY: We just checked `idx` is valid for `NonMaxU32` + Self(unsafe { NonMaxU32::new_unchecked(idx as u32) }) } fn index(self) -> usize {