Skip to content

Commit e1741bd

Browse files
authored
Check raw entity IDs (#303)
1 parent 2a82770 commit e1741bd

File tree

4 files changed

+42
-3
lines changed

4 files changed

+42
-3
lines changed

vhdl_lang/src/analysis/root.rs

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1187,6 +1187,17 @@ impl DesignRoot {
11871187
pub fn symbols(&self) -> &Symbols {
11881188
self.symbols.as_ref()
11891189
}
1190+
1191+
/// Gets an entity-ID from a raw `usize` value and checks that the entity ID is
1192+
/// valid, i.e., points to an existing [AnyEnt].
1193+
pub fn entity_id_from_raw(&self, raw: usize) -> Option<EntityId> {
1194+
let id = EntityId::from_raw(raw);
1195+
if self.arenas.is_valid_id(id) {
1196+
Some(id)
1197+
} else {
1198+
None
1199+
}
1200+
}
11901201
}
11911202

11921203
fn get_all_affected(
@@ -1285,6 +1296,7 @@ fn public_symbols<'a>(ent: EntRef<'a>) -> Box<dyn Iterator<Item = EntRef<'a>> +
12851296
#[cfg(test)]
12861297
mod tests {
12871298
use super::*;
1299+
use crate::analysis::tests::{check_no_diagnostics, LibraryBuilder};
12881300
use crate::syntax::test::{check_diagnostics, Code};
12891301

12901302
fn new_library_with_diagnostics(code: &Code, name: &str) -> (Library, Vec<Diagnostic>) {
@@ -1443,4 +1455,17 @@ end configuration;
14431455
assert_eq!(library.units.len(), 2);
14441456
assert_eq!(library.duplicates.len(), 1);
14451457
}
1458+
1459+
#[test]
1460+
pub fn rejects_illegal_raw_id() {
1461+
let mut builder = LibraryBuilder::new();
1462+
let code = builder.in_declarative_region("signal foo : natural;");
1463+
let (root, diagnostics) = builder.get_analyzed_root();
1464+
check_no_diagnostics(&diagnostics);
1465+
let (_, ent) = root
1466+
.item_at_cursor(code.source(), code.s1("foo").start())
1467+
.unwrap();
1468+
assert_eq!(root.entity_id_from_raw(ent.id.to_raw()), Some(ent.id));
1469+
assert_eq!(root.entity_id_from_raw(0xFFFF << 32), None);
1470+
}
14461471
}

vhdl_lang/src/named_entity/arena.rs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,10 @@ impl LocalArena {
8282
std::mem::transmute(std::pin::Pin::into_inner(item) as *mut AnyEnt)
8383
}
8484

85+
pub fn contains(&self, id: LocalId) -> bool {
86+
(id.0 as usize) < self.items.len()
87+
}
88+
8589
fn panic_on_missing(&self, id: LocalId) {
8690
if (id.0 as usize) < self.items.len() {
8791
return;
@@ -115,6 +119,12 @@ impl<'a> FinalArena {
115119
}
116120
}
117121

122+
pub fn is_valid_id(&self, id: EntityId) -> bool {
123+
self.refs
124+
.get(&id.arena_id().0)
125+
.is_some_and(|local_arena| local_arena.contains(id.local_id()))
126+
}
127+
118128
pub fn link(&mut self, referenced: &FinalArena) {
119129
for (id, arena) in referenced.refs.iter() {
120130
self.refs.entry(*id).or_insert_with(|| arena.clone());
@@ -304,7 +314,7 @@ impl EntityId {
304314

305315
/// Returns an `EntityId` from a raw `usize` value
306316
/// for deserialization purposes.
307-
pub fn from_raw(id: usize) -> EntityId {
317+
pub(crate) fn from_raw(id: usize) -> EntityId {
308318
EntityId { id }
309319
}
310320

vhdl_lang/src/project.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -326,6 +326,10 @@ impl Project {
326326
) -> Vec<CompletionItem> {
327327
list_completion_options(&self.root, source, cursor)
328328
}
329+
330+
pub fn entity_id_from_raw(&self, raw: usize) -> Option<EntityId> {
331+
self.root.entity_id_from_raw(raw)
332+
}
329333
}
330334

331335
/// Multiply cloneable value by cloning

vhdl_ls/src/vhdl_server.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ use std::io;
1717
use std::io::ErrorKind;
1818
use std::path::{Path, PathBuf};
1919
use vhdl_lang::{
20-
kind_str, AnyEntKind, Concurrent, Config, Design, Diagnostic, EntHierarchy, EntRef, EntityId,
20+
kind_str, AnyEntKind, Concurrent, Config, Design, Diagnostic, EntHierarchy, EntRef,
2121
InterfaceEnt, Message, MessageHandler, Object, Overloaded, Project, Severity, SeverityMap,
2222
Source, SrcPos, Token, Type, VHDLStandard,
2323
};
@@ -466,7 +466,7 @@ impl VHDLServer {
466466
.data
467467
.clone()
468468
.and_then(|val| serde_json::from_value::<usize>(val).ok())
469-
.map(EntityId::from_raw);
469+
.and_then(|raw| self.project.entity_id_from_raw(raw));
470470
if let Some(id) = eid {
471471
if let Some(text) = self.project.format_entity(id) {
472472
params.documentation = Some(Documentation::MarkupContent(MarkupContent {

0 commit comments

Comments
 (0)