diff options
| author | Mattias EngdegÄrd | 2024-01-18 18:45:16 +0100 |
|---|---|---|
| committer | Mattias EngdegÄrd | 2024-01-18 18:56:26 +0100 |
| commit | ef01250ef9c22aa1ac2ecff3136aabf79b2a677b (patch) | |
| tree | ecbbbd985351cb27c10ad9b7414408eba44a5067 | |
| parent | 2c887f497c723c2397888e2f406faa4de3a8208a (diff) | |
| download | emacs-ef01250ef9c22aa1ac2ecff3136aabf79b2a677b.tar.gz emacs-ef01250ef9c22aa1ac2ecff3136aabf79b2a677b.zip | |
Only use a hash index size of 1 for tables with size 0 (bug#68244)
This invariant was intended but insufficiently enforced which could
lead to an assertion failure.
* src/fns.c (hash_index_size): Assume size>0, and return a value >1.
(make_hash_table): Only use hash_index_size for size>0.
| -rw-r--r-- | src/fns.c | 15 |
1 files changed, 10 insertions, 5 deletions
| @@ -4525,9 +4525,14 @@ hash_index_size (ptrdiff_t size) | |||
| 4525 | ptrdiff_t upper_bound = min (MOST_POSITIVE_FIXNUM, | 4525 | ptrdiff_t upper_bound = min (MOST_POSITIVE_FIXNUM, |
| 4526 | min (TYPE_MAXIMUM (hash_idx_t), | 4526 | min (TYPE_MAXIMUM (hash_idx_t), |
| 4527 | PTRDIFF_MAX / sizeof (ptrdiff_t))); | 4527 | PTRDIFF_MAX / sizeof (ptrdiff_t))); |
| 4528 | ptrdiff_t index_size = size + (size >> 2); /* 1.25x larger */ | 4528 | /* Single-element index vectors are used iff size=0. */ |
| 4529 | eassert (size > 0); | ||
| 4530 | ptrdiff_t lower_bound = 2; | ||
| 4531 | ptrdiff_t index_size = size + max (size >> 2, 1); /* 1.25x larger */ | ||
| 4529 | if (index_size < upper_bound) | 4532 | if (index_size < upper_bound) |
| 4530 | index_size = next_almost_prime (index_size); | 4533 | index_size = (index_size < lower_bound |
| 4534 | ? lower_bound | ||
| 4535 | : next_almost_prime (index_size)); | ||
| 4531 | if (index_size > upper_bound) | 4536 | if (index_size > upper_bound) |
| 4532 | error ("Hash table too large"); | 4537 | error ("Hash table too large"); |
| 4533 | return index_size; | 4538 | return index_size; |
| @@ -4565,15 +4570,13 @@ make_hash_table (const struct hash_table_test *test, EMACS_INT size, | |||
| 4565 | h->weakness = weak; | 4570 | h->weakness = weak; |
| 4566 | h->count = 0; | 4571 | h->count = 0; |
| 4567 | h->table_size = size; | 4572 | h->table_size = size; |
| 4568 | int index_size = hash_index_size (size); | ||
| 4569 | h->index_size = index_size; | ||
| 4570 | 4573 | ||
| 4571 | if (size == 0) | 4574 | if (size == 0) |
| 4572 | { | 4575 | { |
| 4573 | h->key_and_value = NULL; | 4576 | h->key_and_value = NULL; |
| 4574 | h->hash = NULL; | 4577 | h->hash = NULL; |
| 4575 | h->next = NULL; | 4578 | h->next = NULL; |
| 4576 | eassert (index_size == 1); | 4579 | h->index_size = 1; |
| 4577 | h->index = (hash_idx_t *)empty_hash_index_vector; | 4580 | h->index = (hash_idx_t *)empty_hash_index_vector; |
| 4578 | h->next_free = -1; | 4581 | h->next_free = -1; |
| 4579 | } | 4582 | } |
| @@ -4591,6 +4594,8 @@ make_hash_table (const struct hash_table_test *test, EMACS_INT size, | |||
| 4591 | h->next[i] = i + 1; | 4594 | h->next[i] = i + 1; |
| 4592 | h->next[size - 1] = -1; | 4595 | h->next[size - 1] = -1; |
| 4593 | 4596 | ||
| 4597 | int index_size = hash_index_size (size); | ||
| 4598 | h->index_size = index_size; | ||
| 4594 | h->index = hash_table_alloc_bytes (index_size * sizeof *h->index); | 4599 | h->index = hash_table_alloc_bytes (index_size * sizeof *h->index); |
| 4595 | for (ptrdiff_t i = 0; i < index_size; i++) | 4600 | for (ptrdiff_t i = 0; i < index_size; i++) |
| 4596 | h->index[i] = -1; | 4601 | h->index[i] = -1; |