mirror of
https://github.com/odin-lang/Odin.git
synced 2026-10-09 14:22:18 -04:00
fix(checker): keep entity iteration valid across a scope map rehash
`check_scope_decls` iterates a scope's entity map while `check_entity_decl` can insert into that same scope: a procedure alias (`f :: e`) goes through `override_entity_in_scope`, which calls `scope_map_insert`. The map grows at 75% load (12 of 16 slots, then 24 of 32), and `scope_map_insert` grows before it probes for the key, so even an alias that only replaces an existing value rehashes and reallocates the table in the middle of the iteration. `ScopeMapIterator` re-read its map on every step while `end` had captured the capacity at loop start, so the walk continued over the new table under the old sentinel: it ran past the end of the reallocated table and dereferenced whatever followed it as an `Entity *` - a nullptr dereference for a procedure scope holding exactly 12 or 24 entities - or it stopped at the stale end index and silently skipped every declaration that the rehash had moved behind it, which left unused declarations without any diagnostic at all. The iterator now snapshots the table pointer and capacity when it is constructed, so iteration is invariant under any insert or grow and cannot leave the table it began on. A scope that does not grow behaves exactly as before: the snapshot points at the same table. Refs #7598
This commit is contained in:
1 parent
7c63405593
commit
23cc994255
5 files changed
+393
-9
No files matched your search
@@ -366,6 +366,9 @@ gb_internal void check_scope_decls(CheckerContext *c, Slice<Ast *> const &nodes,
|
||||
|
||||
check_collect_entities(c, nodes);
|
||||
|
||||
// NOTE: checking a declaration can insert entities into this very scope - a procedure alias
|
||||
// goes through `override_entity_in_scope`, which inserts into the scope being iterated - so
|
||||
// the iteration must not be invalidated by `s->elements` growing; see ScopeMapIterator.
|
||||
for (auto const &entry : s->elements) {
|
||||
Entity *e = entry.value;\
|
||||
switch (e->kind) {
|
||||
|
||||
Reference in new issue
Block a user