On Fri, Apr 18, 2025 at 11:12 PM Shim Manning <shimmann...@gmail.com> wrote: > > Seems that using .EXTRA_PREREQS can cause a segfault under the right > conditions. ... > snap_deps > hash_map_arg (loop happens here) > snap_file > expand_extra_prereqs > enter_file > hash_insert_at > hash_rehash (loop no longer valid) > > causes a fairly consistent crash. I'm working on a minimal reproduction if > it's necessary, but allowing the table to be rehashed while iterating seems > like a problem.
Thank you for your report. A test case to reproduce would be good. We'll need to add a test along with a fix. Given that you have a setup that crashes consistently, let me ask you to try out this fix and tell us if this helps. diff --git a/src/hash.c b/src/hash.c index 41e16895..23d6cd4d 100644 --- a/src/hash.c +++ b/src/hash.c @@ -235,14 +235,16 @@ hash_map (struct hash_table *ht, hash_map_func_t map) void hash_map_arg (struct hash_table *ht, hash_map_arg_func_t map, void *arg) { - void **slot; - void **end = &ht->ht_vec[ht->ht_size]; - - for (slot = ht->ht_vec; slot < end; slot++) - { - if (!HASH_VACANT (*slot)) - (*map) (*slot, arg); - } + /* Need to call 'map' for each item in 'ht'. + Cannot iterate through 'ht', because 'map' can attempt to insert to 'ht' + and cause 'ht' to be rehashed. Copy all items from 'ht' to a temporary + array 't' and then iterate through the temporary array. */ + const struct file **t; + t = alloca (sizeof (const struct file *) * (ht->ht_fill + 1)); + hash_dump (ht, (void **) t, 0); + /* t is null terminated. */ + for (; *t; ++t) + (*map) (*t, arg); } /* Double the size of the hash table in the event of overflow... */ regards, Dmitry