From d90352a43dd15b1f0999ceee3c7c79f3c55ecee7 Mon Sep 17 00:00:00 2001 From: Tobias Stoeckmann Date: Fri, 18 Jul 2025 18:11:42 +0200 Subject: [PATCH] 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). --- glib/garray.c | 4 ++-- glib/tests/array-test.c | 23 ++++++++++++++++++++++- 2 files changed, 24 insertions(+), 3 deletions(-) diff --git a/glib/garray.c b/glib/garray.c index 728794a54..61f16a85d 100644 --- a/glib/garray.c +++ b/glib/garray.c @@ -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)); diff --git a/glib/tests/array-test.c b/glib/tests/array-test.c index 2648e0cde..5f57779e3 100644 --- a/glib/tests/array-test.c +++ b/glib/tests/array-test.c @@ -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);