From 3e7be91c46ac0c6942095c04cf435db8f400f17a Mon Sep 17 00:00:00 2001 From: Will Lillis Date: Sat, 29 Aug 2026 18:57:57 -0400 Subject: [PATCH] fix(rust): reject out-of-range node kind ids `node_kind_is_named`, `node_kind_is_visible` and `node_kind_is_supertype` forwarded their `u16` straight to `ts_language_symbol_type`, which indexes `symbol_metadata` unchecked. Bound the id by `node_kind_count()`. --- lib/binding_rust/lib.rs | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/lib/binding_rust/lib.rs b/lib/binding_rust/lib.rs index f84ac36fc..14bbe1cf5 100644 --- a/lib/binding_rust/lib.rs +++ b/lib/binding_rust/lib.rs @@ -620,24 +620,37 @@ impl Language { } } + /// Check whether `id` can be used to index this language's symbol tables. + /// + /// `ts_symbol_metadata` holds one entry per grammar symbol plus one per alias, + /// so [`Self::node_kind_count`] is an exact bound. `ERROR` and `_ERROR` sit + /// at the top of the `u16` range and are handled by the C library before any + /// table lookup. + fn node_kind_id_is_valid(&self, id: u16) -> bool { + (id as usize) < self.node_kind_count() || id >= u16::MAX - 1 + } + /// Check if the node type for the given numerical id is named (as opposed /// to an anonymous node type). #[must_use] pub fn node_kind_is_named(&self, id: u16) -> bool { - unsafe { ffi::ts_language_symbol_type(self.0, id) == ffi::TSSymbolTypeRegular } + self.node_kind_id_is_valid(id) + && unsafe { ffi::ts_language_symbol_type(self.0, id) == ffi::TSSymbolTypeRegular } } /// Check if the node type for the given numerical id is visible (as opposed /// to a hidden node type). #[must_use] pub fn node_kind_is_visible(&self, id: u16) -> bool { - unsafe { ffi::ts_language_symbol_type(self.0, id) <= ffi::TSSymbolTypeAnonymous } + self.node_kind_id_is_valid(id) + && unsafe { ffi::ts_language_symbol_type(self.0, id) <= ffi::TSSymbolTypeAnonymous } } /// Check if the node type for the given numerical id is a supertype. #[must_use] pub fn node_kind_is_supertype(&self, id: u16) -> bool { - unsafe { ffi::ts_language_symbol_type(self.0, id) == ffi::TSSymbolTypeSupertype } + self.node_kind_id_is_valid(id) + && unsafe { ffi::ts_language_symbol_type(self.0, id) == ffi::TSSymbolTypeSupertype } } /// Get the number of distinct field names in this language.