From b0860ae9d41bb9c27acfc7697eb9b3c4815f83eb Mon Sep 17 00:00:00 2001 From: Tobias Stoeckmann Date: Tue, 15 Jul 2025 21:19:02 +0200 Subject: [PATCH] garray: Add more element_size > 0 checks The functions g_array_new and g_array_sized_new already protect themselves against a zero element size. Do the same in g_array_new_take and g_array_new_take_zero_terminated to avoid a NULL pointer dereference and an endless loop. --- glib/garray.c | 4 ++-- glib/tests/array-test.c | 30 +++++++++++++++++++++++++++++- 2 files changed, 31 insertions(+), 3 deletions(-) diff --git a/glib/garray.c b/glib/garray.c index 0701f3391..728794a54 100644 --- a/glib/garray.c +++ b/glib/garray.c @@ -185,7 +185,7 @@ g_array_new_take (gpointer data, g_return_val_if_fail (data != NULL || len == 0, NULL); g_return_val_if_fail (len <= G_MAXUINT, NULL); - g_return_val_if_fail (element_size <= G_MAXUINT, NULL); + g_return_val_if_fail (element_size > 0 && element_size <= G_MAXUINT, NULL); array = g_array_sized_new (FALSE, clear, element_size, 0); rarray = (GRealArray *) array; @@ -237,7 +237,7 @@ g_array_new_take_zero_terminated (gpointer data, GArray *array; gsize len = 0; - g_return_val_if_fail (element_size <= G_MAXUINT, NULL); + g_return_val_if_fail (element_size > 0 && element_size <= G_MAXUINT, NULL); if (data != NULL) { diff --git a/glib/tests/array-test.c b/glib/tests/array-test.c index 4bcbae705..97b8141a2 100644 --- a/glib/tests/array-test.c +++ b/glib/tests/array-test.c @@ -321,6 +321,21 @@ array_new_take_zero_terminated (void) g_clear_pointer (&old_data_copy, g_free); } +/* Check that zero terminated arrays with zero size elements are not allowed. */ +static void +array_new_take_zero_terminated_zero_size (void) +{ + gpointer str = g_strdup ("not null"); + + g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL, + "*assertion 'element_size > 0 && element_size <= G_MAXUINT' failed"); + g_assert_null ( + g_array_new_take_zero_terminated (str, FALSE, 0)); + g_test_assert_expected_messages (); + + g_free (str); +} + /* Check that a non-existing array becomes a zero-terminated one when requested. */ static void array_new_take_zero_terminated_null (void) @@ -357,13 +372,24 @@ array_new_take_overflow (void) g_test_assert_expected_messages (); g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL, - "*assertion 'element_size <= G_MAXUINT' failed"); + "*assertion 'element_size > 0 && element_size <= G_MAXUINT' failed"); g_assert_null ( g_array_new_take (NULL, 0, FALSE, (gsize) G_MAXUINT + 1)); g_test_assert_expected_messages (); #endif } +/* Check that arrays with zero size elements are not allowed. */ +static void +array_new_take_zero_size (void) +{ + g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL, + "*assertion 'element_size > 0 && element_size <= G_MAXUINT' failed"); + g_assert_null ( + g_array_new_take (NULL, 0, FALSE, 0)); + g_test_assert_expected_messages (); +} + /* Check g_array_steal() function */ static void array_steal (void) @@ -3240,7 +3266,9 @@ main (int argc, char *argv[]) g_test_add_func ("/array/new/take", array_new_take); g_test_add_func ("/array/new/take/empty", array_new_take_empty); g_test_add_func ("/array/new/take/overflow", array_new_take_overflow); + g_test_add_func ("/array/new/take/zero-size", array_new_take_zero_size); g_test_add_func ("/array/new/take-zero-terminated", array_new_take_zero_terminated); + g_test_add_func ("/array/new/take-zero-terminated/zero-size", array_new_take_zero_terminated_zero_size); g_test_add_func ("/array/new/take-zero-terminated/null", array_new_take_zero_terminated_null); g_test_add_func ("/array/ref-count", array_ref_count); g_test_add_func ("/array/steal", array_steal);