ghash: Perform shift calculations unsigned

Having unsigned values guarantees that g_hash_table_find_closest_shift
will never loop endlessly. Also make sure that it's impossible to
evade the sanity check of size in g_hash_table_set_shift. Since the
value will be an index, do not allow negative values.

Helps: #672
This commit is contained in:
Tobias Stoeckmann
2025-09-06 21:47:07 +02:00
parent b5edef8200
commit 4414a42c42

View File

@@ -293,7 +293,7 @@ static const gint prime_mod [] =
}; };
static void static void
g_hash_table_set_shift (GHashTable *hash_table, gint shift) g_hash_table_set_shift (GHashTable *hash_table, guint shift)
{ {
if (shift > 31) if (shift > 31)
g_error ("adding more entries to hash table would overflow"); g_error ("adding more entries to hash table would overflow");
@@ -309,10 +309,10 @@ g_hash_table_set_shift (GHashTable *hash_table, gint shift)
hash_table->mask = hash_table->size - 1; hash_table->mask = hash_table->size - 1;
} }
static gint static guint
g_hash_table_find_closest_shift (gint n) g_hash_table_find_closest_shift (guint n)
{ {
gint i; guint i;
for (i = 0; n; i++) for (i = 0; n; i++)
n >>= 1; n >>= 1;
@@ -321,9 +321,9 @@ g_hash_table_find_closest_shift (gint n)
} }
static void static void
g_hash_table_set_shift_from_size (GHashTable *hash_table, gint size) g_hash_table_set_shift_from_size (GHashTable *hash_table, guint size)
{ {
gint shift; guint shift;
shift = g_hash_table_find_closest_shift (size); shift = g_hash_table_find_closest_shift (size);
shift = MAX (shift, HASH_TABLE_MIN_SHIFT); shift = MAX (shift, HASH_TABLE_MIN_SHIFT);
@@ -827,7 +827,7 @@ g_hash_table_resize (GHashTable *hash_table)
* Immediately after growing, the load factor will be in the range * Immediately after growing, the load factor will be in the range
* .375 .. .469. After shrinking, it will be exactly .5. */ * .375 .. .469. After shrinking, it will be exactly .5. */
g_hash_table_set_shift_from_size (hash_table, (gint) (hash_table->nnodes + hash_table->nnodes / 3)); g_hash_table_set_shift_from_size (hash_table, hash_table->nnodes + hash_table->nnodes / 3);
if (hash_table->size > old_size) if (hash_table->size > old_size)
{ {