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()`.
This commit is contained in:
Will Lillis 2026-08-29 18:57:57 -04:00
parent f47170927d
commit 3e7be91c46

View file

@ -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.