summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPhilip Withnall <philip@tecnocode.co.uk>2021-02-04 17:12:36 +0000
committerPhilip Withnall <philip@tecnocode.co.uk>2021-02-04 17:12:36 +0000
commit20cfc75d148e3be0c026cc7eff3a9cdb72bf5c56 (patch)
treeef8934dd4d6333a52d90e21be4baa84449c552fe
parente41a36784c8cc646e92f2a4cfa8cd316b9df05a7 (diff)
parent0cc11f745e43ebeec340917b8cbc69d4c9f4ed58 (diff)
downloadglib-20cfc75d148e3be0c026cc7eff3a9cdb72bf5c56.tar.gz
Merge branch '2319-memdup' into 'master'
Add g_memdup2() Closes #2319 See merge request GNOME/glib!1926
-rw-r--r--docs/reference/glib/glib-sections.txt1
-rw-r--r--gio/gdatainputstream.c24
-rw-r--r--gio/gdbusconnection.c4
-rw-r--r--gio/gdbusinterfaceskeleton.c2
-rw-r--r--gio/gfile.c6
-rw-r--r--gio/giowin32-private.c19
-rw-r--r--gio/gkeyfilesettingsbackend.c20
-rw-r--r--gio/gsettingsschema.c4
-rw-r--r--gio/gsocket.c15
-rw-r--r--gio/gtlspassword.c9
-rwxr-xr-xgio/gwin32packageparser.c19
-rw-r--r--gio/gwin32registrykey.c40
-rw-r--r--gio/tests/async-close-output-stream.c4
-rw-r--r--gio/tests/gdbus-export.c4
-rw-r--r--gio/win32/gwinhttpfile.c8
-rw-r--r--glib/gbytes.c4
-rw-r--r--glib/gdir.c2
-rw-r--r--glib/ghash.c6
-rw-r--r--glib/giochannel.c21
-rw-r--r--glib/gslice.c2
-rw-r--r--glib/gstrfuncs.c32
-rw-r--r--glib/gstrfuncs.h4
-rw-r--r--glib/gtestutils.c2
-rw-r--r--glib/gvariant.c6
-rw-r--r--glib/gvarianttype.c2
-rw-r--r--glib/tests/array-test.c2
-rw-r--r--glib/tests/option-context.c4
-rw-r--r--glib/tests/strfuncs.c21
-rw-r--r--glib/tests/uri.c6
-rw-r--r--gobject/gsignal.c2
-rw-r--r--gobject/gtype.c8
-rw-r--r--gobject/gtypemodule.c2
-rw-r--r--gobject/tests/param.c2
33 files changed, 206 insertions, 101 deletions
diff --git a/docs/reference/glib/glib-sections.txt b/docs/reference/glib/glib-sections.txt
index d0121801a..2e219cf0c 100644
--- a/docs/reference/glib/glib-sections.txt
+++ b/docs/reference/glib/glib-sections.txt
@@ -1341,6 +1341,7 @@ g_newa
<SUBSECTION>
g_memmove
g_memdup
+g_memdup2
<SUBSECTION>
GMemVTable
diff --git a/gio/gdatainputstream.c b/gio/gdatainputstream.c
index 676c6ae22..edbead103 100644
--- a/gio/gdatainputstream.c
+++ b/gio/gdatainputstream.c
@@ -856,7 +856,7 @@ static gssize
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 @@ typedef struct
gsize checked;
gchar *stop_chars;
- gssize stop_chars_len;
+ gsize stop_chars_len;
gsize length;
} GDataInputStreamReadData;
@@ -1078,12 +1078,17 @@ g_data_input_stream_read_async (GDataInputStream *stream,
{
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 +1343,20 @@ g_data_input_stream_read_upto (GDataInputStream *stream,
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 --git a/gio/gdbusconnection.c b/gio/gdbusconnection.c
index 776289340..520a9eca2 100644
--- a/gio/gdbusconnection.c
+++ b/gio/gdbusconnection.c
@@ -4016,7 +4016,7 @@ _g_dbus_interface_vtable_copy (const GDBusInterfaceVTable *vtable)
/* 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
@@ -4033,7 +4033,7 @@ _g_dbus_subtree_vtable_copy (const GDBusSubtreeVTable *vtable)
/* 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 --git a/gio/gdbusinterfaceskeleton.c b/gio/gdbusinterfaceskeleton.c
index 76398df36..878c14599 100644
--- a/gio/gdbusinterfaceskeleton.c
+++ b/gio/gdbusinterfaceskeleton.c
@@ -702,7 +702,7 @@ add_connection_locked (GDBusInterfaceSkeleton *interface_,
* 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 --git a/gio/gfile.c b/gio/gfile.c
index ca6456544..1f2a3e850 100644
--- a/gio/gfile.c
+++ b/gio/gfile.c
@@ -7903,7 +7903,7 @@ measure_disk_usage_progress (gboolean reporting,
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);
}
@@ -7921,7 +7921,7 @@ measure_disk_usage_thread (GTask *task,
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);
}
@@ -7945,7 +7945,7 @@ g_file_real_measure_disk_usage_async (GFile *file,
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 --git a/gio/giowin32-private.c b/gio/giowin32-private.c
index 7120ae0ea..6e1926daa 100644
--- a/gio/giowin32-private.c
+++ b/gio/giowin32-private.c
@@ -17,10 +17,10 @@
*/
-static gssize
+static gsize
g_utf16_len (const gunichar2 *str)
{
- gssize result;
+ gsize result;
for (result = 0; str[0] != 0; str++, result++)
;
@@ -31,17 +31,20 @@ g_utf16_len (const gunichar2 *str)
static gunichar2 *
g_wcsdup (const gunichar2 *str, gssize str_len)
{
- gssize str_size;
+ gsize str_len_unsigned;
+ gsize str_size;
g_return_val_if_fail (str != NULL, NULL);
- if (str_len == -1)
- str_len = g_utf16_len (str);
+ if (str_len < 0)
+ str_len_unsigned = g_utf16_len (str);
+ else
+ str_len_unsigned = (gsize) str_len;
- g_assert (str_len <= G_MAXSIZE / sizeof (gunichar2) - 1);
- str_size = (str_len + 1) * sizeof (gunichar2);
+ g_assert (str_len_unsigned <= G_MAXSIZE / sizeof (gunichar2) - 1);
+ str_size = (str_len_unsigned + 1) * sizeof (gunichar2);
- return g_memdup (str, str_size);
+ return g_memdup2 (str, str_size);
}
static const gunichar2 *
diff --git a/gio/gkeyfilesettingsbackend.c b/gio/gkeyfilesettingsbackend.c
index 60f0cc921..793eed02a 100644
--- a/gio/gkeyfilesettingsbackend.c
+++ b/gio/gkeyfilesettingsbackend.c
@@ -149,8 +149,8 @@ convert_path (GKeyfileSettingsBackend *kfsb,
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)
@@ -159,38 +159,36 @@ convert_path (GKeyfileSettingsBackend *kfsb,
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 --git a/gio/gsettingsschema.c b/gio/gsettingsschema.c
index 26b9a65ad..ed2a7a560 100644
--- a/gio/gsettingsschema.c
+++ b/gio/gsettingsschema.c
@@ -1071,9 +1071,9 @@ g_settings_schema_list_children (GSettingsSchema *schema)
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 --git a/gio/gsocket.c b/gio/gsocket.c
index a4f363f25..a7ba27d0c 100644
--- a/gio/gsocket.c
+++ b/gio/gsocket.c
@@ -169,7 +169,7 @@ static gboolean g_socket_datagram_based_condition_wait (GDatagramBased
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,
@@ -255,7 +255,7 @@ struct _GSocketPrivate
struct {
GSocketAddress *addr;
struct sockaddr *native;
- gint native_len;
+ gsize native_len;
guint64 last_used;
} recv_addr_cache[RECV_ADDR_CACHE_SIZE];
};
@@ -5339,14 +5339,14 @@ g_socket_send_messages_with_timeout (GSocket *socket,
}
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;
@@ -5354,7 +5354,7 @@ cache_recv_address (GSocket *socket, struct sockaddr *native, int native_len)
{
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;
@@ -5384,7 +5384,7 @@ cache_recv_address (GSocket *socket, struct sockaddr *native, int native_len)
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 ();
@@ -5532,6 +5532,9 @@ g_socket_receive_message_with_timeout (GSocket *socket,
/* do it */
while (1)
{
+ /* addrlen has to be of type int because that’s how WSARecvFrom() is defined */
+ G_STATIC_ASSERT (sizeof addr <= G_MAXINT);
+
addrlen = sizeof addr;
if (address)
result = WSARecvFrom (socket->priv->fd,
diff --git a/gio/gtlspassword.c b/gio/gtlspassword.c
index 1e437a7b6..f5e02a1a8 100644
--- a/gio/gtlspassword.c
+++ b/gio/gtlspassword.c
@@ -287,9 +287,14 @@ g_tls_password_set_value (GTlsPassword *password,
g_return_if_fail (G_IS_TLS_PASSWORD (password));
if (length < 0)
- length = strlen ((gchar *)value);
+ {
+ /* FIXME: g_tls_password_set_value_full() doesn’t 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 --git a/gio/gwin32packageparser.c b/gio/gwin32packageparser.c
index 745f1f522..ad5302270 100755
--- a/gio/gwin32packageparser.c
+++ b/gio/gwin32packageparser.c
@@ -62,10 +62,10 @@ typedef HRESULT (STDAPICALLTYPE *CreateXmlReader_func)(REFIID riid, void **ppvOb
#define sax_CreateXmlReader sax->CreateXmlReader
#endif
-static gssize
+static gsize
g_utf16_len (const gunichar2 *str)
{
- gssize result;
+ gsize result;
for (result = 0; str[0] != 0; str++, result++)
;
@@ -76,17 +76,20 @@ g_utf16_len (const gunichar2 *str)
static gunichar2 *
g_wcsdup (const gunichar2 *str, gssize str_len)
{
- gssize str_size;
+ gsize str_len_unsigned;
+ gsize str_size;
g_return_val_if_fail (str != NULL, NULL);
- if (str_len == -1)
- str_len = g_utf16_len (str);
+ if (str_len < 0)
+ str_len_unsigned = g_utf16_len (str);
+ else
+ str_len_unsigned = (gsize) str_len;
- g_assert (str_len <= G_MAXSIZE / sizeof (gunichar2) - 1);
- str_size = (str_len + 1) * sizeof (gunichar2);
+ g_assert (str_len_unsigned <= G_MAXSIZE / sizeof (gunichar2) - 1);
+ str_size = (str_len_unsigned + 1) * sizeof (gunichar2);
- return g_memdup (str, str_size);
+ return g_memdup2 (str, str_size);
}
static BOOL
diff --git a/gio/gwin32registrykey.c b/gio/gwin32registrykey.c
index 29895217d..398d8f45b 100644
--- a/gio/gwin32registrykey.c
+++ b/gio/gwin32registrykey.c
@@ -125,16 +125,34 @@ typedef enum
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 @@ g_win32_registry_value_iter_copy (const GWin32RegistryValueIter *iter)
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 @@ g_win32_registry_value_iter_copy (const GWin32RegistryValueIter *iter)
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 --git a/gio/tests/async-close-output-stream.c b/gio/tests/async-close-output-stream.c
index 5f6620275..00e068766 100644
--- a/gio/tests/async-close-output-stream.c
+++ b/gio/tests/async-close-output-stream.c
@@ -147,9 +147,9 @@ prepare_data (SetupData *data,
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 --git a/gio/tests/gdbus-export.c b/gio/tests/gdbus-export.c
index ba5388600..61d47e90a 100644
--- a/gio/tests/gdbus-export.c
+++ b/gio/tests/gdbus-export.c
@@ -671,7 +671,7 @@ subtree_introspect (GDBusConnection *connection,
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 @@ dynamic_subtree_introspect (GDBusConnection *connection,
{
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 --git a/gio/win32/gwinhttpfile.c b/gio/win32/gwinhttpfile.c
index 509cdeb33..5b8dcfe0b 100644
--- a/gio/win32/gwinhttpfile.c
+++ b/gio/win32/gwinhttpfile.c
@@ -409,10 +409,10 @@ g_winhttp_file_resolve_relative_path (GFile *file,
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 --git a/glib/gbytes.c b/glib/gbytes.c
index ec6923188..00fd79155 100644
--- a/glib/gbytes.c
+++ b/glib/gbytes.c
@@ -95,7 +95,7 @@ g_bytes_new (gconstpointer data,
{
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 @@ g_bytes_unref_to_data (GBytes *bytes,
* 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 --git a/glib/gdir.c b/glib/gdir.c
index 6b85e99c8..c26edc1dc 100644
--- a/glib/gdir.c
+++ b/glib/gdir.c
@@ -112,7 +112,7 @@ g_dir_open_with_errno (const gchar *path,
return NULL;
#endif
- return g_memdup (&dir, sizeof dir);
+ return g_memdup2 (&dir, sizeof dir);
}
/**
diff --git a/glib/ghash.c b/glib/ghash.c
index f3ed0f3b9..cc2d00087 100644
--- a/glib/ghash.c
+++ b/glib/ghash.c
@@ -962,7 +962,7 @@ g_hash_table_ensure_keyval_fits (GHashTable *hash_table, gpointer key, gpointer
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;
}
@@ -970,7 +970,7 @@ g_hash_table_ensure_keyval_fits (GHashTable *hash_table, gpointer key, gpointer
{
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;
}
}
@@ -998,7 +998,7 @@ g_hash_table_ensure_keyval_fits (GHashTable *hash_table, gpointer key, gpointer
/* 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 --git a/glib/giochannel.c b/glib/giochannel.c
index d977b769e..4c5e081ed 100644
--- a/glib/giochannel.c
+++ b/glib/giochannel.c
@@ -886,16 +886,25 @@ g_io_channel_set_line_term (GIOChannel *channel,
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: We’re 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;
}
@@ -1673,10 +1682,10 @@ g_io_channel_read_line (GIOChannel *channel,
/* Copy the read bytes (including any embedded nuls) and nul-terminate.
* `USE_BUF (channel)->str` is guaranteed to be nul-terminated as it’s a
- * #GString, so it’s safe to call g_memdup() with +1 length to allocate
+ * #GString, so it’s safe to call g_memdup2() with +1 length to allocate
* a nul-terminator. */
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';
*str_return = g_steal_pointer (&line);
g_string_erase (USE_BUF (channel), 0, got_length);
diff --git a/glib/gslice.c b/glib/gslice.c
index 589619080..d6335c9dd 100644
--- a/glib/gslice.c
+++ b/glib/gslice.c
@@ -351,7 +351,7 @@ g_slice_get_config_state (GSliceConfig ckey,
array[i++] = allocator->contention_counters[address];
array[i++] = allocator_get_magazine_threshold (allocator, address);
*n_values = i;
- return g_memdup (array, sizeof (array[0]) * *n_values);
+ return g_memdup2 (array, sizeof (array[0]) * *n_values);
default:
return NULL;
}
diff --git a/glib/gstrfuncs.c b/glib/gstrfuncs.c
index afedf4f78..9ee9459e7 100644
--- a/glib/gstrfuncs.c
+++ b/glib/gstrfuncs.c
@@ -399,6 +399,38 @@ g_memdup (gconstpointer mem,
}
/**
+ * 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 --git a/glib/gstrfuncs.h b/glib/gstrfuncs.h
index fc88cc1c5..47cdb0adb 100644
--- a/glib/gstrfuncs.h
+++ b/glib/gstrfuncs.h
@@ -257,6 +257,10 @@ GLIB_AVAILABLE_IN_ALL
gpointer g_memdup (gconstpointer mem,
guint byte_size) G_GNUC_ALLOC_SIZE(2);
+GLIB_AVAILABLE_IN_2_68
+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 --git a/glib/gtestutils.c b/glib/gtestutils.c
index 5660fc8be..d24c6e186 100644
--- a/glib/gtestutils.c
+++ b/glib/gtestutils.c
@@ -3966,7 +3966,7 @@ g_test_log_extract (GTestLogBuffer *tbuffer)
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 --git a/glib/gvariant.c b/glib/gvariant.c
index 5584614c6..e48dec1ad 100644
--- a/glib/gvariant.c
+++ b/glib/gvariant.c
@@ -725,7 +725,7 @@ g_variant_new_variant (GVariant *value)
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 @@ g_variant_new_fixed_array (const GVariantType *element_type,
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);
@@ -1912,7 +1912,7 @@ g_variant_dup_bytestring (GVariant *value,
if (length)
*length = size;
- return g_memdup (original, size + 1);
+ return g_memdup2 (original, size + 1);
}
/**
diff --git a/glib/gvarianttype.c b/glib/gvarianttype.c
index 831fed4bf..cc97235f3 100644
--- a/glib/gvarianttype.c
+++ b/glib/gvarianttype.c
@@ -1181,7 +1181,7 @@ g_variant_type_new_tuple (const GVariantType * const *items,
g_assert (offset < sizeof buffer);
buffer[offset++] = ')';
- return (GVariantType *) g_memdup (buffer, offset);
+ return (GVariantType *) g_memdup2 (buffer, offset);
}
/**
diff --git a/glib/tests/array-test.c b/glib/tests/array-test.c
index adedfc19f..fef63f672 100644
--- a/glib/tests/array-test.c
+++ b/glib/tests/array-test.c
@@ -1933,7 +1933,7 @@ byte_array_new_take (void)
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 --git a/glib/tests/option-context.c b/glib/tests/option-context.c
index ec66e6f94..042b130af 100644
--- a/glib/tests/option-context.c
+++ b/glib/tests/option-context.c
@@ -257,7 +257,7 @@ join_stringv (int argc, char **argv)
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
@@ -2324,7 +2324,7 @@ test_group_parse (void)
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 --git a/glib/tests/strfuncs.c b/glib/tests/strfuncs.c
index 37cbc5a8a..d6eaee385 100644
--- a/glib/tests/strfuncs.c
+++ b/glib/tests/strfuncs.c
@@ -221,6 +221,26 @@ test_memdup (void)
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)
@@ -2539,6 +2559,7 @@ main (int argc,
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 --git a/glib/tests/uri.c b/glib/tests/uri.c
index 2c610382b..1f3209f97 100644
--- a/glib/tests/uri.c
+++ b/glib/tests/uri.c
@@ -410,7 +410,7 @@ test_uri_unescape_bytes (gconstpointer test_data)
else
{
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);
@@ -1591,7 +1591,7 @@ test_uri_iter_params (gconstpointer test_data)
else
{
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. */
@@ -1658,7 +1658,7 @@ test_uri_parse_params (gconstpointer test_data)
else
{
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);
diff --git a/gobject/gsignal.c b/gobject/gsignal.c
index 726185b95..8e10f40d2 100644
--- a/gobject/gsignal.c
+++ b/gobject/gsignal.c
@@ -1797,7 +1797,7 @@ g_signal_newv (const gchar *signal_name,
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 --git a/gobject/gtype.c b/gobject/gtype.c
index 0c530ec9b..94e23b814 100644
--- a/gobject/gtype.c
+++ b/gobject/gtype.c
@@ -1476,7 +1476,7 @@ type_add_interface_Wm (TypeNode *node,
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 */
@@ -1785,7 +1785,7 @@ type_iface_retrieve_holder_info_Wm (TypeNode *iface,
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 */
@@ -2070,10 +2070,10 @@ type_iface_vtable_base_init_Wm (TypeNode *iface,
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 --git a/gobject/gtypemodule.c b/gobject/gtypemodule.c
index dcbd73467..014b5fc3c 100644
--- a/gobject/gtypemodule.c
+++ b/gobject/gtypemodule.c
@@ -437,7 +437,7 @@ g_type_module_register_type (GTypeModule *module,
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 --git a/gobject/tests/param.c b/gobject/tests/param.c
index 1bfdaff87..3ab87ef77 100644
--- a/gobject/tests/param.c
+++ b/gobject/tests/param.c
@@ -903,7 +903,7 @@ main (int argc, char *argv[])
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);
}