Subject: bug#68690: Segmentation fault building with native-comp

From: Gerd Möllmann <[email-masked]>
Date: Thu, 25 Jan 2024 09:33:45 +0100

Gerd Möllmann <[email-masked]> writes:

> Stefan Monnier via "Bug reports for GNU Emacs, the Swiss army knife of
> text editors" <[email-masked]> writes:
>
>>> Adding Stefan, who installed that commit.
>>
>> Oops, should be fixed now,
>>
>
> I wonder if a puthash while being in a DOHASH (which is the ASAN failure
> I showed) is something we should pursue. I don't think that's something
> that's guaranteed to work in a meaningful way. WDYT?

BTW, I'm using the code below for CL packages, which have a hash table.
A bit less hideous ;-).

/* Iterator for hash tables.  */

struct h_iter
{
  /* Hash table being iterated over.  */
  const struct Lisp_Hash_Table *h;

  /* Current index in key/value vector of H.  */
  ptrdiff_t i;

  /* Key and value at I, or nil.  */
  Lisp_Object key, value;
};

/* Return a freshly initialized iterator for iterating over hash table
   TABLE.  */

static struct h_iter
h_init (Lisp_Object table)
{
  struct Lisp_Hash_Table *h = check_hash_table (table);
  struct h_iter it = {.h = h, .i = 0, .key = Qnil, .value = Qnil};
  return it;
}

/* Value is true if iterator IT is on a valid poisition.  If it is,
   IT->key and IT->value are set to key and value at that
   position.  */

static bool
h_valid (struct h_iter *it)
{
  for (; it->i < HASH_TABLE_SIZE (it->h); ++it->i)
    if (!hash_unused_entry_key_p (HASH_KEY (it->h, it->i)))
      {
	it->key = HASH_KEY (it->h, it->i);
	it->value = HASH_VALUE (it->h, it->i);
	return true;
      }
  return false;
}

/* Advance to next element.  */

static void
h_next (struct h_iter *it)
{
  ++it->i;
}

/* Macrology.  IT is a variable name that is bound to an iterator over
   hash table TABLE for the duration of the loop.  */

#define FOR_EACH_KEY_VALUE(it, table) \
  for (struct h_iter it = h_init (table); h_valid (&it); h_next (&it))