mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2025-07-24 10:57:53 +02:00
garray: Avoid exponential growth in g_array_copy
The g_array_copy function uses elt_capacity as length argument for g_array_sized_new. With a zero terminated array, this effectively means that the next allocation is doubled in size. Avoid this by doing the same as g_ptr_array_copy, i.e. use the length. This makes sure that elt_capacity is roughly the same (only differs if the copied array has unallocated data in it).
This commit is contained in:
@@ -1589,8 +1589,8 @@ g_array_copy (GArray *array)
|
||||
g_return_val_if_fail (rarray != NULL, NULL);
|
||||
|
||||
new_rarray =
|
||||
(GRealArray *) g_array_sized_new (rarray->zero_terminated, rarray->clear,
|
||||
rarray->elt_size, rarray->elt_capacity);
|
||||
(GRealArray *) g_array_sized_new (rarray->zero_terminated, rarray->clear,
|
||||
rarray->elt_size, rarray->len);
|
||||
new_rarray->len = rarray->len;
|
||||
if (rarray->len > 0)
|
||||
memcpy (new_rarray->data, rarray->data, g_array_elt_len (rarray, rarray->len));
|
||||
|
@@ -1112,6 +1112,26 @@ test_array_copy_sized (void)
|
||||
g_array_unref (array1);
|
||||
}
|
||||
|
||||
/* Check that copying does not exponentially grow array size. */
|
||||
static void
|
||||
test_array_copy_zero_terminated (void)
|
||||
{
|
||||
GArray *array;
|
||||
|
||||
array = g_array_new_take_zero_terminated (NULL, FALSE, 1);
|
||||
|
||||
for (gint i = 0; i < 32; i++)
|
||||
{
|
||||
GArray *next;
|
||||
|
||||
next = g_array_copy (array);
|
||||
g_array_unref (array);
|
||||
array = next;
|
||||
}
|
||||
|
||||
g_array_unref (array);
|
||||
}
|
||||
|
||||
static void
|
||||
array_overflow_append_vals (void)
|
||||
{
|
||||
@@ -3276,7 +3296,8 @@ main (int argc, char *argv[])
|
||||
g_test_add_func ("/array/steal", array_steal);
|
||||
g_test_add_func ("/array/clear-func", array_clear_func);
|
||||
g_test_add_func ("/array/binary-search", test_array_binary_search);
|
||||
g_test_add_func ("/array/copy-sized", test_array_copy_sized);
|
||||
g_test_add_func ("/array/copy/sized", test_array_copy_sized);
|
||||
g_test_add_func ("/array/copy/zero-terminated", test_array_copy_zero_terminated);
|
||||
g_test_add_func ("/array/overflow-append-vals", array_overflow_append_vals);
|
||||
g_test_add_func ("/array/overflow-set-size", array_overflow_set_size);
|
||||
g_test_add_func ("/array/remove-range/zero-terminated-null", array_remove_range_zero_terminated_null);
|
||||
|
Reference in New Issue
Block a user