garray: Fix integer overflows in element capacity calculations

Integer overflows in size calculations of buffers (GArray and GPtrArray)
allow subsequent buffer overflows. This happens due to conversions
between gsize and guint.

Proof of concept demonstrations of the overflows can be found in issue
2578. They are not being added as unit tests as they require too much
memory to test.

This will affect `GArray`s which are 4GB in size, or `GPtrArray`s which
are 48GB in size.

Fixes: #2578
This commit is contained in:
Tobias Stoeckmann 2022-01-18 13:45:13 +00:00 committed by Philip Withnall
parent c74177337d
commit 374a1895b6

View File

@ -1001,7 +1001,7 @@ g_array_maybe_expand (GRealArray *array,
memset (g_array_elt_pos (array, array->elt_capacity), 0, memset (g_array_elt_pos (array, array->elt_capacity), 0,
g_array_elt_len (array, want_len - array->elt_capacity)); g_array_elt_len (array, want_len - array->elt_capacity));
array->elt_capacity = want_alloc / array->elt_size; array->elt_capacity = MIN (want_alloc / array->elt_size, G_MAXUINT);
} }
} }
@ -1518,9 +1518,10 @@ g_ptr_array_maybe_expand (GRealPtrArray *array,
if ((array->len + len) > array->alloc) if ((array->len + len) > array->alloc)
{ {
guint old_alloc = array->alloc; guint old_alloc = array->alloc;
array->alloc = g_nearest_pow (array->len + len); gsize want_alloc = g_nearest_pow (sizeof (gpointer) * (array->len + len));
array->alloc = MAX (array->alloc, MIN_ARRAY_SIZE); want_alloc = MAX (want_alloc, MIN_ARRAY_SIZE);
array->pdata = g_realloc (array->pdata, sizeof (gpointer) * array->alloc); array->alloc = MIN (want_alloc / sizeof (gpointer), G_MAXUINT);
array->pdata = g_realloc (array->pdata, want_alloc);
if (G_UNLIKELY (g_mem_gc_friendly)) if (G_UNLIKELY (g_mem_gc_friendly))
for ( ; old_alloc < array->alloc; old_alloc++) for ( ; old_alloc < array->alloc; old_alloc++)
array->pdata [old_alloc] = NULL; array->pdata [old_alloc] = NULL;