Re: seg fault with EXTRA_PREREQS

Shim Manning <[email protected]>
Newsgroups gmane.comp.gnu.make.bugs
Message-ID <CAPN3a96jF1Teu7KJe5CUH=OB01x8VCrgSqQDq111gQTYNc2DKg@mail.gmail.com>
Minimal test.  Generates a list of 1000 prerequisites.

list := $(shell for n in $$(seq 1 1000); do echo file_$$n; done)
all: .EXTRA_PREREQS := $(list)
all:
echo "fin"

And tes making a copy of the table appears to fix it

On Sat, Apr 19, 2025 at 9:26 PM Dmitry Goncharov <[email protected]>
wrote:

> On Fri, Apr 18, 2025 at 11:12 PM Shim Manning <[email protected]>
> 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
>
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.