glib: Use g_memdup2() instead of g_memdup() in obvious places

Convert all the call sites which use `g_memdup()`’s length argument
trivially (for example, by passing a `sizeof()` or an existing `gsize`
variable), so that they use `g_memdup2()` instead.

In almost all of these cases the use of `g_memdup()` would not have
caused problems, but it will soon be deprecated, so best port away from
it

In particular, this fixes an overflow within `g_bytes_new()`, identified
as GHSL-2021-045 by GHSL team member Kevin Backhouse.

Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
Fixes: GHSL-2021-045
Helps: #2319
This commit is contained in:
Philip Withnall 2021-02-04 13:41:21 +00:00
parent 6110caea45
commit 0736b7c1e7
11 changed files with 35 additions and 20 deletions

View File

@ -34,6 +34,8 @@
#include <string.h> #include <string.h>
#include "gstrfuncsprivate.h"
/** /**
* GBytes: * GBytes:
* *
@ -95,7 +97,7 @@ g_bytes_new (gconstpointer data,
{ {
g_return_val_if_fail (data != NULL || size == 0, NULL); g_return_val_if_fail (data != NULL || size == 0, NULL);
return g_bytes_new_take (g_memdup (data, size), size); return g_bytes_new_take (g_memdup2 (data, size), size);
} }
/** /**
@ -499,7 +501,7 @@ g_bytes_unref_to_data (GBytes *bytes,
* Copy: Non g_malloc (or compatible) allocator, or static memory, * Copy: Non g_malloc (or compatible) allocator, or static memory,
* so we have to copy, and then unref. * so we have to copy, and then unref.
*/ */
result = g_memdup (bytes->data, bytes->size); result = g_memdup2 (bytes->data, bytes->size);
*size = bytes->size; *size = bytes->size;
g_bytes_unref (bytes); g_bytes_unref (bytes);
} }

View File

@ -37,6 +37,7 @@
#include "gconvert.h" #include "gconvert.h"
#include "gfileutils.h" #include "gfileutils.h"
#include "gstrfuncs.h" #include "gstrfuncs.h"
#include "gstrfuncsprivate.h"
#include "gtestutils.h" #include "gtestutils.h"
#include "glibintl.h" #include "glibintl.h"
@ -112,7 +113,7 @@ g_dir_open_with_errno (const gchar *path,
return NULL; return NULL;
#endif #endif
return g_memdup (&dir, sizeof dir); return g_memdup2 (&dir, sizeof dir);
} }
/** /**

View File

@ -34,6 +34,7 @@
#include "gmacros.h" #include "gmacros.h"
#include "glib-private.h" #include "glib-private.h"
#include "gstrfuncs.h" #include "gstrfuncs.h"
#include "gstrfuncsprivate.h"
#include "gatomic.h" #include "gatomic.h"
#include "gtestutils.h" #include "gtestutils.h"
#include "gslice.h" #include "gslice.h"
@ -963,7 +964,7 @@ g_hash_table_ensure_keyval_fits (GHashTable *hash_table, gpointer key, gpointer
if (hash_table->have_big_keys) if (hash_table->have_big_keys)
{ {
if (key != value) if (key != value)
hash_table->values = g_memdup (hash_table->keys, sizeof (gpointer) * hash_table->size); hash_table->values = g_memdup2 (hash_table->keys, sizeof (gpointer) * hash_table->size);
/* Keys and values are both big now, so no need for further checks */ /* Keys and values are both big now, so no need for further checks */
return; return;
} }
@ -971,7 +972,7 @@ g_hash_table_ensure_keyval_fits (GHashTable *hash_table, gpointer key, gpointer
{ {
if (key != value) if (key != value)
{ {
hash_table->values = g_memdup (hash_table->keys, sizeof (guint) * hash_table->size); hash_table->values = g_memdup2 (hash_table->keys, sizeof (guint) * hash_table->size);
is_a_set = FALSE; is_a_set = FALSE;
} }
} }
@ -999,7 +1000,7 @@ g_hash_table_ensure_keyval_fits (GHashTable *hash_table, gpointer key, gpointer
/* Just split if necessary */ /* Just split if necessary */
if (is_a_set && key != value) if (is_a_set && key != value)
hash_table->values = g_memdup (hash_table->keys, sizeof (gpointer) * hash_table->size); hash_table->values = g_memdup2 (hash_table->keys, sizeof (gpointer) * hash_table->size);
#endif #endif
} }

View File

@ -37,6 +37,7 @@
#include "giochannel.h" #include "giochannel.h"
#include "gstrfuncs.h" #include "gstrfuncs.h"
#include "gstrfuncsprivate.h"
#include "gtestutils.h" #include "gtestutils.h"
#include "glibintl.h" #include "glibintl.h"
@ -1673,10 +1674,10 @@ g_io_channel_read_line (GIOChannel *channel,
/* Copy the read bytes (including any embedded nuls) and nul-terminate. /* Copy the read bytes (including any embedded nuls) and nul-terminate.
* `USE_BUF (channel)->str` is guaranteed to be nul-terminated as its a * `USE_BUF (channel)->str` is guaranteed to be nul-terminated as its a
* #GString, so its safe to call g_memdup() with +1 length to allocate * #GString, so its safe to call g_memdup2() with +1 length to allocate
* a nul-terminator. */ * a nul-terminator. */
g_assert (USE_BUF (channel)); g_assert (USE_BUF (channel));
line = g_memdup (USE_BUF (channel)->str, got_length + 1); line = g_memdup2 (USE_BUF (channel)->str, got_length + 1);
line[got_length] = '\0'; line[got_length] = '\0';
*str_return = g_steal_pointer (&line); *str_return = g_steal_pointer (&line);
g_string_erase (USE_BUF (channel), 0, got_length); g_string_erase (USE_BUF (channel), 0, got_length);

View File

@ -41,6 +41,7 @@
#include "gmain.h" #include "gmain.h"
#include "gmem.h" /* gslice.h */ #include "gmem.h" /* gslice.h */
#include "gstrfuncs.h" #include "gstrfuncs.h"
#include "gstrfuncsprivate.h"
#include "gutils.h" #include "gutils.h"
#include "gtrashstack.h" #include "gtrashstack.h"
#include "gtestutils.h" #include "gtestutils.h"
@ -351,7 +352,7 @@ g_slice_get_config_state (GSliceConfig ckey,
array[i++] = allocator->contention_counters[address]; array[i++] = allocator->contention_counters[address];
array[i++] = allocator_get_magazine_threshold (allocator, address); array[i++] = allocator_get_magazine_threshold (allocator, address);
*n_values = i; *n_values = i;
return g_memdup (array, sizeof (array[0]) * *n_values); return g_memdup2 (array, sizeof (array[0]) * *n_values);
default: default:
return NULL; return NULL;
} }

View File

@ -49,6 +49,7 @@
#include "gpattern.h" #include "gpattern.h"
#include "grand.h" #include "grand.h"
#include "gstrfuncs.h" #include "gstrfuncs.h"
#include "gstrfuncsprivate.h"
#include "gtimer.h" #include "gtimer.h"
#include "gslice.h" #include "gslice.h"
#include "gspawn.h" #include "gspawn.h"
@ -3825,7 +3826,7 @@ g_test_log_extract (GTestLogBuffer *tbuffer)
if (p <= tbuffer->data->str + mlength) if (p <= tbuffer->data->str + mlength)
{ {
g_string_erase (tbuffer->data, 0, mlength); g_string_erase (tbuffer->data, 0, mlength);
tbuffer->msgs = g_slist_prepend (tbuffer->msgs, g_memdup (&msg, sizeof (msg))); tbuffer->msgs = g_slist_prepend (tbuffer->msgs, g_memdup2 (&msg, sizeof (msg)));
return TRUE; return TRUE;
} }

View File

@ -33,6 +33,7 @@
#include <string.h> #include <string.h>
#include "gstrfuncsprivate.h"
/** /**
* SECTION:gvariant * SECTION:gvariant
@ -725,7 +726,7 @@ g_variant_new_variant (GVariant *value)
g_variant_ref_sink (value); g_variant_ref_sink (value);
return g_variant_new_from_children (G_VARIANT_TYPE_VARIANT, return g_variant_new_from_children (G_VARIANT_TYPE_VARIANT,
g_memdup (&value, sizeof value), g_memdup2 (&value, sizeof value),
1, g_variant_is_trusted (value)); 1, g_variant_is_trusted (value));
} }
@ -1229,7 +1230,7 @@ g_variant_new_fixed_array (const GVariantType *element_type,
return NULL; return NULL;
} }
data = g_memdup (elements, n_elements * element_size); data = g_memdup2 (elements, n_elements * element_size);
value = g_variant_new_from_data (array_type, data, value = g_variant_new_from_data (array_type, data,
n_elements * element_size, n_elements * element_size,
FALSE, g_free, data); FALSE, g_free, data);
@ -1912,7 +1913,7 @@ g_variant_dup_bytestring (GVariant *value,
if (length) if (length)
*length = size; *length = size;
return g_memdup (original, size + 1); return g_memdup2 (original, size + 1);
} }
/** /**

View File

@ -28,6 +28,7 @@
#include <string.h> #include <string.h>
#include "gstrfuncsprivate.h"
/** /**
* SECTION:gvarianttype * SECTION:gvarianttype
@ -1181,7 +1182,7 @@ g_variant_type_new_tuple (const GVariantType * const *items,
g_assert (offset < sizeof buffer); g_assert (offset < sizeof buffer);
buffer[offset++] = ')'; buffer[offset++] = ')';
return (GVariantType *) g_memdup (buffer, offset); return (GVariantType *) g_memdup2 (buffer, offset);
} }
/** /**

View File

@ -29,6 +29,8 @@
#include <string.h> #include <string.h>
#include "glib.h" #include "glib.h"
#include "gstrfuncsprivate.h"
/* Test data to be passed to any function which calls g_array_new(), providing /* Test data to be passed to any function which calls g_array_new(), providing
* the parameters for that call. Most #GArray tests should be repeated for all * the parameters for that call. Most #GArray tests should be repeated for all
* possible values of #ArrayTestData. */ * possible values of #ArrayTestData. */
@ -1933,7 +1935,7 @@ byte_array_new_take (void)
GByteArray *gbarray; GByteArray *gbarray;
guint8 *data; guint8 *data;
data = g_memdup ("woooweeewow", 11); data = g_memdup2 ("woooweeewow", 11);
gbarray = g_byte_array_new_take (data, 11); gbarray = g_byte_array_new_take (data, 11);
g_assert (gbarray->data == data); g_assert (gbarray->data == data);
g_assert_cmpuint (gbarray->len, ==, 11); g_assert_cmpuint (gbarray->len, ==, 11);

View File

@ -27,6 +27,8 @@
#include <string.h> #include <string.h>
#include <locale.h> #include <locale.h>
#include "gstrfuncsprivate.h"
static GOptionEntry main_entries[] = { static GOptionEntry main_entries[] = {
{ "main-switch", 0, 0, { "main-switch", 0, 0,
G_OPTION_ARG_NONE, NULL, G_OPTION_ARG_NONE, NULL,
@ -256,7 +258,7 @@ join_stringv (int argc, char **argv)
static char ** static char **
copy_stringv (char **argv, int argc) copy_stringv (char **argv, int argc)
{ {
return g_memdup (argv, sizeof (char *) * (argc + 1)); return g_memdup2 (argv, sizeof (char *) * (argc + 1));
} }
static void static void
@ -2323,7 +2325,7 @@ test_group_parse (void)
g_option_context_add_group (context, group); g_option_context_add_group (context, group);
argv = split_string ("program --test arg1 -f arg2 --group-test arg3 --frob arg4 -z arg5", &argc); argv = split_string ("program --test arg1 -f arg2 --group-test arg3 --frob arg4 -z arg5", &argc);
orig_argv = g_memdup (argv, (argc + 1) * sizeof (char *)); orig_argv = g_memdup2 (argv, (argc + 1) * sizeof (char *));
retval = g_option_context_parse (context, &argc, &argv, &error); retval = g_option_context_parse (context, &argc, &argv, &error);

View File

@ -27,6 +27,8 @@
#include <string.h> #include <string.h>
#include <stdlib.h> #include <stdlib.h>
#include "gstrfuncsprivate.h"
typedef struct typedef struct
{ {
char *filename; char *filename;
@ -409,7 +411,7 @@ test_uri_unescape_bytes (gconstpointer test_data)
else else
{ {
escaped_len = strlen (tests[i].escaped); /* no trailing nul */ escaped_len = strlen (tests[i].escaped); /* no trailing nul */
escaped = g_memdup (tests[i].escaped, escaped_len); escaped = g_memdup2 (tests[i].escaped, escaped_len);
} }
bytes = g_uri_unescape_bytes (escaped, escaped_len, tests[i].illegal, &error); bytes = g_uri_unescape_bytes (escaped, escaped_len, tests[i].illegal, &error);
@ -1506,7 +1508,7 @@ test_uri_iter_params (gconstpointer test_data)
else else
{ {
uri_len = strlen (params_tests[i].uri); /* no trailing nul */ uri_len = strlen (params_tests[i].uri); /* no trailing nul */
uri = g_memdup (params_tests[i].uri, uri_len); uri = g_memdup2 (params_tests[i].uri, uri_len);
} }
/* Run once without extracting the attr or value, just to check the numbers. */ /* Run once without extracting the attr or value, just to check the numbers. */
@ -1573,7 +1575,7 @@ test_uri_parse_params (gconstpointer test_data)
else else
{ {
uri_len = strlen (params_tests[i].uri); /* no trailing nul */ uri_len = strlen (params_tests[i].uri); /* no trailing nul */
uri = g_memdup (params_tests[i].uri, uri_len); uri = g_memdup2 (params_tests[i].uri, uri_len);
} }
params = g_uri_parse_params (uri, uri_len, params_tests[i].separators, params_tests[i].flags, &err); params = g_uri_parse_params (uri, uri_len, params_tests[i].separators, params_tests[i].flags, &err);