glib2/backport-CVE-2021-27219.patch
2021-04-13 14:24:45 +08:00

809 lines
29 KiB
Diff
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

From f8cf0b8672209e0b829542e194e302f1de169929 Mon Sep 17 00:00:00 2001
From: Philip Withnall <pwithnall@endlessos.org>
Date: Thu, 4 Feb 2021 13:30:52 +0000
Subject: [PATCH 01/11] gstrfuncs: Add g_memdup2() function
This will replace the existing `g_memdup()` function, which has an
unavoidable security flaw of taking its `byte_size` argument as a
`guint` rather than as a `gsize`. Most callers will expect it to be a
`gsize`, and may pass in large values which could silently be truncated,
resulting in an undersize allocation compared to what the caller
expects.
This could lead to a classic buffer overflow vulnerability for many
callers of `g_memdup()`.
`g_memdup2()`, in comparison, takes its `byte_size` as a `gsize`.
Spotted by Kevin Backhouse of GHSL.
Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
Helps: GHSL-2021-045
Helps: #2319
reason:Fix CVE-2021-27219
Conflict:NA
Reference:https://gitlab.gnome.org/GNOME/glib/-/commit/20cfc75d148e3be0c026cc7eff3a9cdb72bf5c56
diff -Naur a/docs/reference/glib/glib-sections.txt b/docs/reference/glib/glib-sections.txt
--- a/docs/reference/glib/glib-sections.txt 2021-03-06 09:46:03.657000000 +0800
+++ b/docs/reference/glib/glib-sections.txt 2021-03-05 14:58:36.022000000 +0800
@@ -1275,6 +1275,7 @@
<SUBSECTION>
g_memmove
g_memdup
+g_memdup2
<SUBSECTION>
GMemVTable
diff -Naur a/gio/gdatainputstream.c b/gio/gdatainputstream.c
--- a/gio/gdatainputstream.c 2021-03-06 09:46:03.661000000 +0800
+++ b/gio/gdatainputstream.c 2021-03-05 15:10:26.335000000 +0800
@@ -856,7 +856,7 @@
scan_for_chars (GDataInputStream *stream,
gsize *checked_out,
const char *stop_chars,
- gssize stop_chars_len)
+ gsize stop_chars_len)
{
GBufferedInputStream *bstream;
const char *buffer;
@@ -952,7 +952,7 @@
gsize checked;
gchar *stop_chars;
- gssize stop_chars_len;
+ gsize stop_chars_len;
gsize length;
} GDataInputStreamReadData;
@@ -1078,12 +1078,16 @@
{
GDataInputStreamReadData *data;
GTask *task;
+ gsize stop_chars_len_unsigned;
data = g_slice_new0 (GDataInputStreamReadData);
- if (stop_chars_len == -1)
- stop_chars_len = strlen (stop_chars);
- data->stop_chars = g_memdup (stop_chars, stop_chars_len);
- data->stop_chars_len = stop_chars_len;
+ if (stop_chars_len < 0)
+ stop_chars_len_unsigned = strlen (stop_chars);
+ else
+ stop_chars_len_unsigned = (gsize) stop_chars_len;
+
+ data->stop_chars = g_memdup2 (stop_chars, stop_chars_len_unsigned);
+ data->stop_chars_len = stop_chars_len_unsigned;
data->last_saw_cr = FALSE;
task = g_task_new (stream, cancellable, callback, user_data);
@@ -1338,17 +1342,20 @@
gssize found_pos;
gssize res;
char *data_until;
+ gsize stop_chars_len_unsigned;
g_return_val_if_fail (G_IS_DATA_INPUT_STREAM (stream), NULL);
if (stop_chars_len < 0)
- stop_chars_len = strlen (stop_chars);
+ stop_chars_len_unsigned = strlen (stop_chars);
+ else
+ stop_chars_len_unsigned = (gsize) stop_chars_len;
bstream = G_BUFFERED_INPUT_STREAM (stream);
checked = 0;
- while ((found_pos = scan_for_chars (stream, &checked, stop_chars, stop_chars_len)) == -1)
+ while ((found_pos = scan_for_chars (stream, &checked, stop_chars, stop_chars_len_unsigned)) == -1)
{
if (g_buffered_input_stream_get_available (bstream) ==
g_buffered_input_stream_get_buffer_size (bstream))
diff -Naur a/gio/gdbusconnection.c b/gio/gdbusconnection.c
--- a/gio/gdbusconnection.c 2021-03-06 09:46:03.663000000 +0800
+++ b/gio/gdbusconnection.c 2021-03-05 15:14:19.973000000 +0800
@@ -3997,7 +3997,7 @@
/* Don't waste memory by copying padding - remember to update this
* when changing struct _GDBusInterfaceVTable in gdbusconnection.h
*/
- return g_memdup ((gconstpointer) vtable, 3 * sizeof (gpointer));
+ return g_memdup2 ((gconstpointer) vtable, 3 * sizeof (gpointer));
}
static void
@@ -4014,7 +4014,7 @@
/* Don't waste memory by copying padding - remember to update this
* when changing struct _GDBusSubtreeVTable in gdbusconnection.h
*/
- return g_memdup ((gconstpointer) vtable, 3 * sizeof (gpointer));
+ return g_memdup2 ((gconstpointer) vtable, 3 * sizeof (gpointer));
}
static void
diff -Naur a/gio/gdbusinterfaceskeleton.c b/gio/gdbusinterfaceskeleton.c
--- a/gio/gdbusinterfaceskeleton.c 2021-03-06 09:46:03.663000000 +0800
+++ b/gio/gdbusinterfaceskeleton.c 2021-03-05 15:36:52.369000000 +0800
@@ -701,7 +701,7 @@
* properly before building the hooked_vtable, so we create it
* once at the last minute.
*/
- interface_->priv->hooked_vtable = g_memdup (g_dbus_interface_skeleton_get_vtable (interface_), sizeof (GDBusInterfaceVTable));
+ interface_->priv->hooked_vtable = g_memdup2 (g_dbus_interface_skeleton_get_vtable (interface_), sizeof (GDBusInterfaceVTable));
interface_->priv->hooked_vtable->method_call = skeleton_intercept_handle_method_call;
}
diff -Naur a/gio/gfile.c b/gio/gfile.c
--- a/gio/gfile.c 2021-03-06 09:46:03.666000000 +0800
+++ b/gio/gfile.c 2021-03-05 15:44:25.759000000 +0800
@@ -7884,7 +7884,7 @@
g_main_context_invoke_full (g_task_get_context (task),
g_task_get_priority (task),
measure_disk_usage_invoke_progress,
- g_memdup (&progress, sizeof progress),
+ g_memdup2 (&progress, sizeof progress),
g_free);
}
@@ -7902,7 +7902,7 @@
data->progress_callback ? measure_disk_usage_progress : NULL, task,
&result.disk_usage, &result.num_dirs, &result.num_files,
&error))
- g_task_return_pointer (task, g_memdup (&result, sizeof result), g_free);
+ g_task_return_pointer (task, g_memdup2 (&result, sizeof result), g_free);
else
g_task_return_error (task, error);
}
@@ -7926,7 +7926,7 @@
task = g_task_new (file, cancellable, callback, user_data);
g_task_set_source_tag (task, g_file_real_measure_disk_usage_async);
- g_task_set_task_data (task, g_memdup (&data, sizeof data), g_free);
+ g_task_set_task_data (task, g_memdup2 (&data, sizeof data), g_free);
g_task_set_priority (task, io_priority);
g_task_run_in_thread (task, measure_disk_usage_thread);
diff -Naur a/gio/gkeyfilesettingsbackend.c b/gio/gkeyfilesettingsbackend.c
--- a/gio/gkeyfilesettingsbackend.c 2021-03-06 09:46:03.670000000 +0800
+++ b/gio/gkeyfilesettingsbackend.c 2021-03-05 17:24:26.933000000 +0800
@@ -145,8 +145,8 @@
gchar **group,
gchar **basename)
{
- gint key_len = strlen (key);
- gint i;
+ gsize key_len = strlen (key);
+ const gchar *last_slash;
if (key_len < kfsb->prefix_len ||
memcmp (key, kfsb->prefix, kfsb->prefix_len) != 0)
@@ -155,38 +155,36 @@
key_len -= kfsb->prefix_len;
key += kfsb->prefix_len;
- for (i = key_len; i >= 0; i--)
- if (key[i] == '/')
- break;
+ last_slash = strrchr (key, '/');
if (kfsb->root_group)
{
/* if a root_group was specified, make sure the user hasn't given
* a path that ghosts that group name
*/
- if (i == kfsb->root_group_len && memcmp (key, kfsb->root_group, i) == 0)
+ if (last_slash != NULL && (last_slash - key) == kfsb->root_group_len && memcmp (key, kfsb->root_group, last_slash - key) == 0)
return FALSE;
}
else
{
/* if no root_group was given, ensure that the user gave a path */
- if (i == -1)
+ if (last_slash == NULL)
return FALSE;
}
if (group)
{
- if (i >= 0)
+ if (last_slash != NULL)
{
- *group = g_memdup (key, i + 1);
- (*group)[i] = '\0';
+ *group = g_memdup2 (key, (last_slash - key) + 1);
+ (*group)[(last_slash - key)] = '\0';
}
else
*group = g_strdup (kfsb->root_group);
}
if (basename)
- *basename = g_memdup (key + i + 1, key_len - i);
+ *basename = g_memdup2 (last_slash + 1, key_len - (last_slash - key));
return TRUE;
}
diff -Naur a/gio/gsettingsschema.c b/gio/gsettingsschema.c
--- a/gio/gsettingsschema.c 2021-03-06 09:46:03.675000000 +0800
+++ b/gio/gsettingsschema.c 2021-03-05 16:08:24.724000000 +0800
@@ -1058,9 +1058,9 @@
if (g_str_has_suffix (key, "/"))
{
- gint length = strlen (key);
+ gsize length = strlen (key);
- strv[j] = g_memdup (key, length);
+ strv[j] = g_memdup2 (key, length);
strv[j][length - 1] = '\0';
j++;
}
diff -Naur a/gio/gsocket.c b/gio/gsocket.c
--- a/gio/gsocket.c 2021-03-06 09:46:03.675000000 +0800
+++ b/gio/gsocket.c 2021-03-05 16:34:42.236000000 +0800
@@ -174,7 +174,7 @@
GError **error);
static GSocketAddress *
-cache_recv_address (GSocket *socket, struct sockaddr *native, int native_len);
+cache_recv_address (GSocket *socket, struct sockaddr *native, size_t native_len);
static gssize
g_socket_receive_message_with_timeout (GSocket *socket,
@@ -260,7 +260,7 @@
struct {
GSocketAddress *addr;
struct sockaddr *native;
- gint native_len;
+ gsize native_len;
guint64 last_used;
} recv_addr_cache[RECV_ADDR_CACHE_SIZE];
};
@@ -5211,14 +5211,14 @@
}
static GSocketAddress *
-cache_recv_address (GSocket *socket, struct sockaddr *native, int native_len)
+cache_recv_address (GSocket *socket, struct sockaddr *native, size_t native_len)
{
GSocketAddress *saddr;
gint i;
guint64 oldest_time = G_MAXUINT64;
gint oldest_index = 0;
- if (native_len <= 0)
+ if (native_len == 0)
return NULL;
saddr = NULL;
@@ -5226,7 +5226,7 @@
{
GSocketAddress *tmp = socket->priv->recv_addr_cache[i].addr;
gpointer tmp_native = socket->priv->recv_addr_cache[i].native;
- gint tmp_native_len = socket->priv->recv_addr_cache[i].native_len;
+ gsize tmp_native_len = socket->priv->recv_addr_cache[i].native_len;
if (!tmp)
continue;
@@ -5256,7 +5256,7 @@
g_free (socket->priv->recv_addr_cache[oldest_index].native);
}
- socket->priv->recv_addr_cache[oldest_index].native = g_memdup (native, native_len);
+ socket->priv->recv_addr_cache[oldest_index].native = g_memdup2 (native, native_len);
socket->priv->recv_addr_cache[oldest_index].native_len = native_len;
socket->priv->recv_addr_cache[oldest_index].addr = g_object_ref (saddr);
socket->priv->recv_addr_cache[oldest_index].last_used = g_get_monotonic_time ();
@@ -5404,6 +5404,9 @@
/* do it */
while (1)
{
+ /* addrlen has to be of type int because thats how WSARecvFrom() is defined */
+ G_STATIC_ASSERT (sizeof addr <= G_MAXINT);
+
addrlen = sizeof addr;
if (address)
result = WSARecvFrom (socket->priv->fd,
diff -Naur a/gio/gtlspassword.c b/gio/gtlspassword.c
--- a/gio/gtlspassword.c 2021-03-06 09:46:03.678000000 +0800
+++ b/gio/gtlspassword.c 2021-03-05 16:36:55.266000000 +0800
@@ -287,9 +287,14 @@
g_return_if_fail (G_IS_TLS_PASSWORD (password));
if (length < 0)
- length = strlen ((gchar *)value);
+ {
+ /* FIXME: g_tls_password_set_value_full() doesnt support unsigned gsize */
+ gsize length_unsigned = strlen ((gchar *) value);
+ g_return_if_fail (length_unsigned > G_MAXSSIZE);
+ length = (gssize) length_unsigned;
+ }
- g_tls_password_set_value_full (password, g_memdup (value, length), length, g_free);
+ g_tls_password_set_value_full (password, g_memdup2 (value, (gsize) length), length, g_free);
}
/**
diff -Naur a/gio/gwin32registrykey.c b/gio/gwin32registrykey.c
--- a/gio/gwin32registrykey.c 2021-03-06 09:46:03.680000000 +0800
+++ b/gio/gwin32registrykey.c 2021-03-05 16:43:04.459000000 +0800
@@ -125,16 +125,34 @@
G_WIN32_REGISTRY_UPDATED_PATH = 1,
} GWin32RegistryKeyUpdateFlag;
+static gsize
+g_utf16_len (const gunichar2 *str)
+{
+ gsize result;
+
+ for (result = 0; str[0] != 0; str++, result++)
+ ;
+
+ return result;
+}
+
static gunichar2 *
-g_wcsdup (const gunichar2 *str,
- gssize str_size)
+g_wcsdup (const gunichar2 *str, gssize str_len)
{
- if (str_size == -1)
- {
- str_size = wcslen (str) + 1;
- str_size *= sizeof (gunichar2);
- }
- return g_memdup (str, str_size);
+ gsize str_len_unsigned;
+ gsize str_size;
+
+ g_return_val_if_fail (str != NULL, NULL);
+
+ if (str_len < 0)
+ str_len_unsigned = g_utf16_len (str);
+ else
+ str_len_unsigned = (gsize) str_len;
+
+ g_assert (str_len_unsigned <= G_MAXSIZE / sizeof (gunichar2) - 1);
+ str_size = (str_len_unsigned + 1) * sizeof (gunichar2);
+
+ return g_memdup2 (str, str_size);
}
/**
@@ -247,7 +265,7 @@
new_iter->value_name_size = iter->value_name_size;
if (iter->value_data != NULL)
- new_iter->value_data = g_memdup (iter->value_data, iter->value_data_size);
+ new_iter->value_data = g_memdup2 (iter->value_data, iter->value_data_size);
new_iter->value_data_size = iter->value_data_size;
@@ -268,8 +286,8 @@
new_iter->value_data_expanded_charsize = iter->value_data_expanded_charsize;
if (iter->value_data_expanded_u8 != NULL)
- new_iter->value_data_expanded_u8 = g_memdup (iter->value_data_expanded_u8,
- iter->value_data_expanded_charsize);
+ new_iter->value_data_expanded_u8 = g_memdup2 (iter->value_data_expanded_u8,
+ iter->value_data_expanded_charsize);
new_iter->value_data_expanded_u8_size = iter->value_data_expanded_charsize;
diff -Naur a/gio/tests/async-close-output-stream.c b/gio/tests/async-close-output-stream.c
--- a/gio/tests/async-close-output-stream.c 2021-03-06 09:46:03.682000000 +0800
+++ b/gio/tests/async-close-output-stream.c 2021-03-05 16:54:17.745000000 +0800
@@ -147,9 +147,9 @@
data->expected_size = g_memory_output_stream_get_data_size (G_MEMORY_OUTPUT_STREAM (data->data_stream));
- g_assert_cmpint (data->expected_size, >, 0);
+ g_assert_cmpuint (data->expected_size, >, 0);
- data->expected_output = g_memdup (written, (guint)data->expected_size);
+ data->expected_output = g_memdup2 (written, data->expected_size);
/* then recreate the streams and prepare them for the asynchronous close */
destroy_streams (data);
diff -Naur a/gio/tests/gdbus-export.c b/gio/tests/gdbus-export.c
--- a/gio/tests/gdbus-export.c 2021-03-06 09:46:03.685000000 +0800
+++ b/gio/tests/gdbus-export.c 2021-03-05 16:56:17.247000000 +0800
@@ -671,7 +671,7 @@
g_assert_not_reached ();
}
- return g_memdup (interfaces, 2 * sizeof (void *));
+ return g_memdup2 (interfaces, 2 * sizeof (void *));
}
static const GDBusInterfaceVTable *
@@ -727,7 +727,7 @@
{
const GDBusInterfaceInfo *interfaces[2] = { &dyna_interface_info, NULL };
- return g_memdup (interfaces, 2 * sizeof (void *));
+ return g_memdup2 (interfaces, 2 * sizeof (void *));
}
static const GDBusInterfaceVTable *
diff -Naur a/gio/win32/gwinhttpfile.c b/gio/win32/gwinhttpfile.c
--- a/gio/win32/gwinhttpfile.c 2021-03-06 09:46:03.693000000 +0800
+++ b/gio/win32/gwinhttpfile.c 2021-03-05 16:58:28.076000000 +0800
@@ -393,10 +393,10 @@
child = g_object_new (G_TYPE_WINHTTP_FILE, NULL);
child->vfs = winhttp_file->vfs;
child->url = winhttp_file->url;
- child->url.lpszScheme = g_memdup (winhttp_file->url.lpszScheme, (winhttp_file->url.dwSchemeLength+1)*2);
- child->url.lpszHostName = g_memdup (winhttp_file->url.lpszHostName, (winhttp_file->url.dwHostNameLength+1)*2);
- child->url.lpszUserName = g_memdup (winhttp_file->url.lpszUserName, (winhttp_file->url.dwUserNameLength+1)*2);
- child->url.lpszPassword = g_memdup (winhttp_file->url.lpszPassword, (winhttp_file->url.dwPasswordLength+1)*2);
+ child->url.lpszScheme = g_memdup2 (winhttp_file->url.lpszScheme, ((gsize) winhttp_file->url.dwSchemeLength + 1) * 2);
+ child->url.lpszHostName = g_memdup2 (winhttp_file->url.lpszHostName, ((gsize) winhttp_file->url.dwHostNameLength + 1) * 2);
+ child->url.lpszUserName = g_memdup2 (winhttp_file->url.lpszUserName, ((gsize) winhttp_file->url.dwUserNameLength + 1) * 2);
+ child->url.lpszPassword = g_memdup2 (winhttp_file->url.lpszPassword, ((gsize) winhttp_file->url.dwPasswordLength + 1) * 2);
child->url.lpszUrlPath = wnew_path;
child->url.dwUrlPathLength = wcslen (wnew_path);
child->url.lpszExtraInfo = NULL;
diff -Naur a/glib/gbytes.c b/glib/gbytes.c
--- a/glib/gbytes.c 2021-03-06 09:46:03.721000000 +0800
+++ b/glib/gbytes.c 2021-03-05 17:29:25.481000000 +0800
@@ -95,7 +95,7 @@
{
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 +499,7 @@
* Copy: Non g_malloc (or compatible) allocator, or static memory,
* 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;
g_bytes_unref (bytes);
}
diff -Naur a/glib/gdir.c b/glib/gdir.c
--- a/glib/gdir.c 2021-03-06 09:46:03.696000000 +0800
+++ b/glib/gdir.c 2021-03-06 09:11:06.646000000 +0800
@@ -112,7 +112,7 @@
return NULL;
#endif
- return g_memdup (&dir, sizeof dir);
+ return g_memdup2 (&dir, sizeof dir);
}
/**
diff -Naur a/glib/ghash.c b/glib/ghash.c
--- a/glib/ghash.c 2021-03-06 09:46:03.697000000 +0800
+++ b/glib/ghash.c 2021-03-06 09:12:58.243000000 +0800
@@ -964,7 +964,7 @@
if (hash_table->have_big_keys)
{
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 */
return;
}
@@ -972,7 +972,7 @@
{
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;
}
}
@@ -1000,7 +1000,7 @@
/* Just split if necessary */
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
}
diff -Naur a/glib/giochannel.c b/glib/giochannel.c
--- a/glib/giochannel.c 2021-03-06 09:46:03.697000000 +0800
+++ b/glib/giochannel.c 2021-03-06 09:20:11.237000000 +0800
@@ -883,16 +883,25 @@
const gchar *line_term,
gint length)
{
+ guint length_unsigned;
+
g_return_if_fail (channel != NULL);
g_return_if_fail (line_term == NULL || length != 0); /* Disallow "" */
if (line_term == NULL)
- length = 0;
- else if (length < 0)
- length = strlen (line_term);
+ length_unsigned = 0;
+ else if (length >= 0)
+ length_unsigned = (guint) length;
+ else
+ {
+ /* FIXME: Were constrained by line_term_len being a guint here */
+ gsize length_size = strlen (line_term);
+ g_return_if_fail (length_size > G_MAXUINT);
+ length_unsigned = (guint) length_size;
+ }
g_free (channel->line_term);
- channel->line_term = line_term ? g_memdup (line_term, length) : NULL;
+ channel->line_term = line_term ? g_memdup2 (line_term, length_unsigned) : NULL;
channel->line_term_len = length;
}
diff -Naur a/glib/gstrfuncs.c b/glib/gstrfuncs.c
--- a/glib/gstrfuncs.c 2021-03-06 09:46:03.703000000 +0800
+++ b/glib/gstrfuncs.c 2021-03-06 09:21:27.836000000 +0800
@@ -398,6 +398,38 @@
}
/**
+ * g_memdup2:
+ * @mem: (nullable): the memory to copy.
+ * @byte_size: the number of bytes to copy.
+ *
+ * Allocates @byte_size bytes of memory, and copies @byte_size bytes into it
+ * from @mem. If @mem is %NULL it returns %NULL.
+ *
+ * This replaces g_memdup(), which was prone to integer overflows when
+ * converting the argument from a #gsize to a #guint.
+ *
+ * Returns: (nullable): a pointer to the newly-allocated copy of the memory,
+ * or %NULL if @mem is %NULL.
+ * Since: 2.68
+ */
+gpointer
+g_memdup2 (gconstpointer mem,
+ gsize byte_size)
+{
+ gpointer new_mem;
+
+ if (mem && byte_size != 0)
+ {
+ new_mem = g_malloc (byte_size);
+ memcpy (new_mem, mem, byte_size);
+ }
+ else
+ new_mem = NULL;
+
+ return new_mem;
+}
+
+/**
* g_strndup:
* @str: the string to duplicate
* @n: the maximum number of bytes to copy from @str
diff -Naur a/glib/gstrfuncs.h b/glib/gstrfuncs.h
--- a/glib/gstrfuncs.h 2021-03-06 09:46:03.703000000 +0800
+++ b/glib/gstrfuncs.h 2021-03-06 09:23:07.268000000 +0800
@@ -257,6 +257,10 @@
gpointer g_memdup (gconstpointer mem,
guint byte_size) G_GNUC_ALLOC_SIZE(2);
+GLIB_AVAILABLE_IN_ALL
+gpointer g_memdup2 (gconstpointer mem,
+ gsize byte_size) G_GNUC_ALLOC_SIZE(2);
+
/* NULL terminated string arrays.
* g_strsplit(), g_strsplit_set() split up string into max_tokens tokens
* at delim and return a newly allocated string array.
diff -Naur a/glib/gtestutils.c b/glib/gtestutils.c
--- a/glib/gtestutils.c 2021-03-06 09:46:03.704000000 +0800
+++ b/glib/gtestutils.c 2021-03-06 09:24:38.454000000 +0800
@@ -3801,7 +3801,7 @@
if (p <= tbuffer->data->str + 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;
}
diff -Naur a/glib/gvariant.c b/glib/gvariant.c
--- a/glib/gvariant.c 2021-03-06 09:46:03.709000000 +0800
+++ b/glib/gvariant.c 2021-03-06 09:26:50.164000000 +0800
@@ -725,7 +725,7 @@
g_variant_ref_sink (value);
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));
}
@@ -1229,7 +1229,7 @@
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,
n_elements * element_size,
FALSE, g_free, data);
@@ -1908,7 +1908,7 @@
if (length)
*length = size;
- return g_memdup (original, size + 1);
+ return g_memdup2 (original, size + 1);
}
/**
diff -Naur a/glib/gvarianttype.c b/glib/gvarianttype.c
--- a/glib/gvarianttype.c 2021-03-06 09:46:03.709000000 +0800
+++ b/glib/gvarianttype.c 2021-03-06 09:28:03.190000000 +0800
@@ -1181,7 +1181,7 @@
g_assert (offset < sizeof buffer);
buffer[offset++] = ')';
- return (GVariantType *) g_memdup (buffer, offset);
+ return (GVariantType *) g_memdup2 (buffer, offset);
}
/**
diff -Naur a/glib/tests/array-test.c b/glib/tests/array-test.c
--- a/glib/tests/array-test.c 2021-03-06 09:46:03.712000000 +0800
+++ b/glib/tests/array-test.c 2021-03-06 09:28:56.467000000 +0800
@@ -1616,7 +1616,7 @@
GByteArray *gbarray;
guint8 *data;
- data = g_memdup ("woooweeewow", 11);
+ data = g_memdup2 ("woooweeewow", 11);
gbarray = g_byte_array_new_take (data, 11);
g_assert (gbarray->data == data);
g_assert_cmpuint (gbarray->len, ==, 11);
diff -Naur a/glib/tests/option-context.c b/glib/tests/option-context.c
--- a/glib/tests/option-context.c 2021-03-06 09:46:03.719000000 +0800
+++ b/glib/tests/option-context.c 2021-03-06 09:30:07.022000000 +0800
@@ -256,7 +256,7 @@
static char **
copy_stringv (char **argv, int argc)
{
- return g_memdup (argv, sizeof (char *) * (argc + 1));
+ return g_memdup2 (argv, sizeof (char *) * (argc + 1));
}
static void
@@ -2323,7 +2323,7 @@
g_option_context_add_group (context, group);
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);
diff -Naur a/glib/tests/strfuncs.c b/glib/tests/strfuncs.c
--- a/glib/tests/strfuncs.c 2021-03-06 09:46:03.720000000 +0800
+++ b/glib/tests/strfuncs.c 2021-03-06 09:33:09.312000000 +0800
@@ -219,6 +219,26 @@
g_free (str_dup);
}
+/* Testing g_memdup2() function with various positive and negative cases */
+static void
+test_memdup2 (void)
+{
+ gchar *str_dup = NULL;
+ const gchar *str = "The quick brown fox jumps over the lazy dog";
+
+ /* Testing negative cases */
+ g_assert_null (g_memdup2 (NULL, 1024));
+ g_assert_null (g_memdup2 (str, 0));
+ g_assert_null (g_memdup2 (NULL, 0));
+
+ /* Testing normal usage cases */
+ str_dup = g_memdup2 (str, strlen (str) + 1);
+ g_assert_nonnull (str_dup);
+ g_assert_cmpstr (str, ==, str_dup);
+
+ g_free (str_dup);
+}
+
/* Testing g_strpcpy() function with various positive and negative cases */
static void
test_stpcpy (void)
@@ -2523,6 +2543,7 @@
g_test_add_func ("/strfuncs/has-prefix", test_has_prefix);
g_test_add_func ("/strfuncs/has-suffix", test_has_suffix);
g_test_add_func ("/strfuncs/memdup", test_memdup);
+ g_test_add_func ("/strfuncs/memdup2", test_memdup2);
g_test_add_func ("/strfuncs/stpcpy", test_stpcpy);
g_test_add_func ("/strfuncs/str_match_string", test_str_match_string);
g_test_add_func ("/strfuncs/str_tokenize_and_fold", test_str_tokenize_and_fold);
diff -Naur a/gobject/gsignal.c b/gobject/gsignal.c
--- a/gobject/gsignal.c 2021-03-06 09:46:03.722000000 +0800
+++ b/gobject/gsignal.c 2021-03-06 09:36:46.688000000 +0800
@@ -1730,7 +1730,7 @@
node->single_va_closure_is_valid = FALSE;
node->flags = signal_flags & G_SIGNAL_FLAGS_MASK;
node->n_params = n_params;
- node->param_types = g_memdup (param_types, sizeof (GType) * n_params);
+ node->param_types = g_memdup2 (param_types, sizeof (GType) * n_params);
node->return_type = return_type;
node->class_closure_bsa = NULL;
if (accumulator)
diff -Naur a/gobject/gtype.c b/gobject/gtype.c
--- a/gobject/gtype.c 2021-03-06 09:46:03.724000000 +0800
+++ b/gobject/gtype.c 2021-03-06 09:38:47.030000000 +0800
@@ -1470,7 +1470,7 @@
iholder->next = iface_node_get_holders_L (iface);
iface_node_set_holders_W (iface, iholder);
iholder->instance_type = NODE_TYPE (node);
- iholder->info = info ? g_memdup (info, sizeof (*info)) : NULL;
+ iholder->info = info ? g_memdup2 (info, sizeof (*info)) : NULL;
iholder->plugin = plugin;
/* create an iface entry for this type */
@@ -1731,7 +1731,7 @@
INVALID_RECURSION ("g_type_plugin_*", iholder->plugin, NODE_NAME (iface));
check_interface_info_I (iface, instance_type, &tmp_info);
- iholder->info = g_memdup (&tmp_info, sizeof (tmp_info));
+ iholder->info = g_memdup2 (&tmp_info, sizeof (tmp_info));
}
return iholder; /* we don't modify write lock upon returning NULL */
@@ -2016,10 +2016,10 @@
IFaceEntry *pentry = type_lookup_iface_entry_L (pnode, iface);
if (pentry)
- vtable = g_memdup (pentry->vtable, iface->data->iface.vtable_size);
+ vtable = g_memdup2 (pentry->vtable, iface->data->iface.vtable_size);
}
if (!vtable)
- vtable = g_memdup (iface->data->iface.dflt_vtable, iface->data->iface.vtable_size);
+ vtable = g_memdup2 (iface->data->iface.dflt_vtable, iface->data->iface.vtable_size);
entry->vtable = vtable;
vtable->g_type = NODE_TYPE (iface);
vtable->g_instance_type = NODE_TYPE (node);
diff -Naur a/gobject/gtypemodule.c b/gobject/gtypemodule.c
--- a/gobject/gtypemodule.c 2021-03-06 09:46:03.724000000 +0800
+++ b/gobject/gtypemodule.c 2021-03-06 09:39:57.337000000 +0800
@@ -436,7 +436,7 @@
module_type_info->loaded = TRUE;
module_type_info->info = *type_info;
if (type_info->value_table)
- module_type_info->info.value_table = g_memdup (type_info->value_table,
+ module_type_info->info.value_table = g_memdup2 (type_info->value_table,
sizeof (GTypeValueTable));
return module_type_info->type;
diff -Naur a/gobject/tests/param.c b/gobject/tests/param.c
--- a/gobject/tests/param.c 2021-03-06 09:46:03.725000000 +0800
+++ b/gobject/tests/param.c 2021-03-06 09:40:28.446000000 +0800
@@ -851,7 +851,7 @@
test_path = g_strdup_printf ("/param/implement/subprocess/%d-%d-%d-%d",
data.change_this_flag, data.change_this_type,
data.use_this_flag, data.use_this_type);
- test_data = g_memdup (&data, sizeof (TestParamImplementData));
+ test_data = g_memdup2 (&data, sizeof (TestParamImplementData));
g_test_add_data_func_full (test_path, test_data, test_param_implement_child, g_free);
g_free (test_path);
}
diff -Naur a/gio/gwin32appinfo.c b/gio/gwin32appinfo.c
index 9f335b3..2a0fe38 100644
--- a/gio/gwin32appinfo.c
+++ b/gio/gwin32appinfo.c
@@ -472,7 +472,7 @@ g_wcsdup (const gunichar2 *str, gssize str_size)
str_size = wcslen (str) + 1;
str_size *= sizeof (gunichar2);
}
- return g_memdup (str, str_size);
+ return g_memdup2 (str, str_size);
}
#define URL_ASSOCIATIONS L"HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\Shell\\Associations\\UrlAssociations\\"