diff options
| author | Anatol Belski <anbelski@linux.microsoft.com> | 2021-03-15 13:29:42 +0000 |
|---|---|---|
| committer | Richard Purdie <richard.purdie@linuxfoundation.org> | 2021-03-28 22:31:55 +0100 |
| commit | a633251fc8b2e09959f98bcca037d77d8ed3105d (patch) | |
| tree | 4cacde467886444d16e0c0c1fc1cabb26628edd1 | |
| parent | 9b9bcb844399310905c6e635390fc4c46f1dce01 (diff) | |
| download | poky-a633251fc8b2e09959f98bcca037d77d8ed3105d.tar.gz | |
glib-2.0: Fix CVE-2021-27219
The upstream patches are only in glib >= 2.66.6 and >= 2.67.3 and won't
be backported. This patch is developed based on the upstream patch set
and consulting teh backports recently made by Ubuntu for the 2.64.6
series.
(From OE-Core rev: 513d2a82cc9574983d017a2c0b2de87e181befa5)
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Signed-off-by: Anuj Mittal <anuj.mittal@intel.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
| -rw-r--r-- | meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-27219.patch | 1444 | ||||
| -rw-r--r-- | meta/recipes-core/glib-2.0/glib-2.0_2.64.5.bb | 1 |
2 files changed, 1445 insertions, 0 deletions
diff --git a/meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-27219.patch b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-27219.patch new file mode 100644 index 0000000000..a4ec01134a --- /dev/null +++ b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-27219.patch | |||
| @@ -0,0 +1,1444 @@ | |||
| 1 | commit b70039028b4a39ea071f6ed368a58ad5b5b90ba3 | ||
| 2 | Author: Anatol Belski <anbelski@microsoft.com> | ||
| 3 | Date: Sun Mar 14 17:51:53 2021 +0000 | ||
| 4 | |||
| 5 | backport: 2.64.5_CVE-2021-27219 | ||
| 6 | |||
| 7 | CVE: CVE-2021-27219 | ||
| 8 | Upstream-Status: Backport | ||
| 9 | [https://gitlab.gnome.org/GNOME/glib/-/merge_requests/1926] | ||
| 10 | |||
| 11 | Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com> | ||
| 12 | |||
| 13 | diff --git a/docs/reference/glib/meson.build b/docs/reference/glib/meson.build | ||
| 14 | index 62d95f78d..7eebb04ac 100644 | ||
| 15 | --- a/docs/reference/glib/meson.build | ||
| 16 | +++ b/docs/reference/glib/meson.build | ||
| 17 | @@ -22,6 +22,7 @@ if get_option('gtk_doc') | ||
| 18 | 'gprintfint.h', | ||
| 19 | 'gmirroringtable.h', | ||
| 20 | 'gscripttable.h', | ||
| 21 | + 'gstrfuncsprivate.h', | ||
| 22 | 'glib-mirroring-tab', | ||
| 23 | 'gnulib', | ||
| 24 | 'pcre', | ||
| 25 | diff --git a/gio/gdatainputstream.c b/gio/gdatainputstream.c | ||
| 26 | index 2e7750cb5..2cdcbda19 100644 | ||
| 27 | --- a/gio/gdatainputstream.c | ||
| 28 | +++ b/gio/gdatainputstream.c | ||
| 29 | @@ -27,6 +27,7 @@ | ||
| 30 | #include "gioenumtypes.h" | ||
| 31 | #include "gioerror.h" | ||
| 32 | #include "glibintl.h" | ||
| 33 | +#include "gstrfuncsprivate.h" | ||
| 34 | |||
| 35 | #include <string.h> | ||
| 36 | |||
| 37 | @@ -856,7 +857,7 @@ static gssize | ||
| 38 | scan_for_chars (GDataInputStream *stream, | ||
| 39 | gsize *checked_out, | ||
| 40 | const char *stop_chars, | ||
| 41 | - gssize stop_chars_len) | ||
| 42 | + gsize stop_chars_len) | ||
| 43 | { | ||
| 44 | GBufferedInputStream *bstream; | ||
| 45 | const char *buffer; | ||
| 46 | @@ -952,7 +953,7 @@ typedef struct | ||
| 47 | gsize checked; | ||
| 48 | |||
| 49 | gchar *stop_chars; | ||
| 50 | - gssize stop_chars_len; | ||
| 51 | + gsize stop_chars_len; | ||
| 52 | gsize length; | ||
| 53 | } GDataInputStreamReadData; | ||
| 54 | |||
| 55 | @@ -1078,12 +1079,17 @@ g_data_input_stream_read_async (GDataInputStream *stream, | ||
| 56 | { | ||
| 57 | GDataInputStreamReadData *data; | ||
| 58 | GTask *task; | ||
| 59 | + gsize stop_chars_len_unsigned; | ||
| 60 | |||
| 61 | data = g_slice_new0 (GDataInputStreamReadData); | ||
| 62 | - if (stop_chars_len == -1) | ||
| 63 | - stop_chars_len = strlen (stop_chars); | ||
| 64 | - data->stop_chars = g_memdup (stop_chars, stop_chars_len); | ||
| 65 | - data->stop_chars_len = stop_chars_len; | ||
| 66 | + | ||
| 67 | + if (stop_chars_len < 0) | ||
| 68 | + stop_chars_len_unsigned = strlen (stop_chars); | ||
| 69 | + else | ||
| 70 | + stop_chars_len_unsigned = (gsize) stop_chars_len; | ||
| 71 | + | ||
| 72 | + data->stop_chars = g_memdup2 (stop_chars, stop_chars_len_unsigned); | ||
| 73 | + data->stop_chars_len = stop_chars_len_unsigned; | ||
| 74 | data->last_saw_cr = FALSE; | ||
| 75 | |||
| 76 | task = g_task_new (stream, cancellable, callback, user_data); | ||
| 77 | @@ -1338,17 +1344,20 @@ g_data_input_stream_read_upto (GDataInputStream *stream, | ||
| 78 | gssize found_pos; | ||
| 79 | gssize res; | ||
| 80 | char *data_until; | ||
| 81 | + gsize stop_chars_len_unsigned; | ||
| 82 | |||
| 83 | g_return_val_if_fail (G_IS_DATA_INPUT_STREAM (stream), NULL); | ||
| 84 | |||
| 85 | if (stop_chars_len < 0) | ||
| 86 | - stop_chars_len = strlen (stop_chars); | ||
| 87 | + stop_chars_len_unsigned = strlen (stop_chars); | ||
| 88 | + else | ||
| 89 | + stop_chars_len_unsigned = (gsize) stop_chars_len; | ||
| 90 | |||
| 91 | bstream = G_BUFFERED_INPUT_STREAM (stream); | ||
| 92 | |||
| 93 | checked = 0; | ||
| 94 | |||
| 95 | - while ((found_pos = scan_for_chars (stream, &checked, stop_chars, stop_chars_len)) == -1) | ||
| 96 | + while ((found_pos = scan_for_chars (stream, &checked, stop_chars, stop_chars_len_unsigned)) == -1) | ||
| 97 | { | ||
| 98 | if (g_buffered_input_stream_get_available (bstream) == | ||
| 99 | g_buffered_input_stream_get_buffer_size (bstream)) | ||
| 100 | diff --git a/gio/gdbusconnection.c b/gio/gdbusconnection.c | ||
| 101 | index 1a4dae3bd..9de661bde 100644 | ||
| 102 | --- a/gio/gdbusconnection.c | ||
| 103 | +++ b/gio/gdbusconnection.c | ||
| 104 | @@ -110,6 +110,7 @@ | ||
| 105 | #include "gasyncinitable.h" | ||
| 106 | #include "giostream.h" | ||
| 107 | #include "gasyncresult.h" | ||
| 108 | +#include "gstrfuncsprivate.h" | ||
| 109 | #include "gtask.h" | ||
| 110 | #include "gmarshal-internal.h" | ||
| 111 | |||
| 112 | @@ -4007,7 +4008,7 @@ _g_dbus_interface_vtable_copy (const GDBusInterfaceVTable *vtable) | ||
| 113 | /* Don't waste memory by copying padding - remember to update this | ||
| 114 | * when changing struct _GDBusInterfaceVTable in gdbusconnection.h | ||
| 115 | */ | ||
| 116 | - return g_memdup ((gconstpointer) vtable, 3 * sizeof (gpointer)); | ||
| 117 | + return g_memdup2 ((gconstpointer) vtable, 3 * sizeof (gpointer)); | ||
| 118 | } | ||
| 119 | |||
| 120 | static void | ||
| 121 | @@ -4024,7 +4025,7 @@ _g_dbus_subtree_vtable_copy (const GDBusSubtreeVTable *vtable) | ||
| 122 | /* Don't waste memory by copying padding - remember to update this | ||
| 123 | * when changing struct _GDBusSubtreeVTable in gdbusconnection.h | ||
| 124 | */ | ||
| 125 | - return g_memdup ((gconstpointer) vtable, 3 * sizeof (gpointer)); | ||
| 126 | + return g_memdup2 ((gconstpointer) vtable, 3 * sizeof (gpointer)); | ||
| 127 | } | ||
| 128 | |||
| 129 | static void | ||
| 130 | diff --git a/gio/gdbusinterfaceskeleton.c b/gio/gdbusinterfaceskeleton.c | ||
| 131 | index 4a06516c1..4a4b719a5 100644 | ||
| 132 | --- a/gio/gdbusinterfaceskeleton.c | ||
| 133 | +++ b/gio/gdbusinterfaceskeleton.c | ||
| 134 | @@ -28,6 +28,7 @@ | ||
| 135 | #include "gdbusmethodinvocation.h" | ||
| 136 | #include "gdbusconnection.h" | ||
| 137 | #include "gmarshal-internal.h" | ||
| 138 | +#include "gstrfuncsprivate.h" | ||
| 139 | #include "gtask.h" | ||
| 140 | #include "gioerror.h" | ||
| 141 | |||
| 142 | @@ -701,7 +702,7 @@ add_connection_locked (GDBusInterfaceSkeleton *interface_, | ||
| 143 | * properly before building the hooked_vtable, so we create it | ||
| 144 | * once at the last minute. | ||
| 145 | */ | ||
| 146 | - interface_->priv->hooked_vtable = g_memdup (g_dbus_interface_skeleton_get_vtable (interface_), sizeof (GDBusInterfaceVTable)); | ||
| 147 | + interface_->priv->hooked_vtable = g_memdup2 (g_dbus_interface_skeleton_get_vtable (interface_), sizeof (GDBusInterfaceVTable)); | ||
| 148 | interface_->priv->hooked_vtable->method_call = skeleton_intercept_handle_method_call; | ||
| 149 | } | ||
| 150 | |||
| 151 | diff --git a/gio/gfile.c b/gio/gfile.c | ||
| 152 | index a2ded14ea..25930435f 100644 | ||
| 153 | --- a/gio/gfile.c | ||
| 154 | +++ b/gio/gfile.c | ||
| 155 | @@ -60,6 +60,7 @@ | ||
| 156 | #include "gasyncresult.h" | ||
| 157 | #include "gioerror.h" | ||
| 158 | #include "glibintl.h" | ||
| 159 | +#include "gstrfuncsprivate.h" | ||
| 160 | |||
| 161 | |||
| 162 | /** | ||
| 163 | @@ -7854,7 +7855,7 @@ measure_disk_usage_progress (gboolean reporting, | ||
| 164 | g_main_context_invoke_full (g_task_get_context (task), | ||
| 165 | g_task_get_priority (task), | ||
| 166 | measure_disk_usage_invoke_progress, | ||
| 167 | - g_memdup (&progress, sizeof progress), | ||
| 168 | + g_memdup2 (&progress, sizeof progress), | ||
| 169 | g_free); | ||
| 170 | } | ||
| 171 | |||
| 172 | @@ -7872,7 +7873,7 @@ measure_disk_usage_thread (GTask *task, | ||
| 173 | data->progress_callback ? measure_disk_usage_progress : NULL, task, | ||
| 174 | &result.disk_usage, &result.num_dirs, &result.num_files, | ||
| 175 | &error)) | ||
| 176 | - g_task_return_pointer (task, g_memdup (&result, sizeof result), g_free); | ||
| 177 | + g_task_return_pointer (task, g_memdup2 (&result, sizeof result), g_free); | ||
| 178 | else | ||
| 179 | g_task_return_error (task, error); | ||
| 180 | } | ||
| 181 | @@ -7896,7 +7897,7 @@ g_file_real_measure_disk_usage_async (GFile *file, | ||
| 182 | |||
| 183 | task = g_task_new (file, cancellable, callback, user_data); | ||
| 184 | g_task_set_source_tag (task, g_file_real_measure_disk_usage_async); | ||
| 185 | - g_task_set_task_data (task, g_memdup (&data, sizeof data), g_free); | ||
| 186 | + g_task_set_task_data (task, g_memdup2 (&data, sizeof data), g_free); | ||
| 187 | g_task_set_priority (task, io_priority); | ||
| 188 | |||
| 189 | g_task_run_in_thread (task, measure_disk_usage_thread); | ||
| 190 | diff --git a/gio/giowin32-private.c b/gio/giowin32-private.c | ||
| 191 | index 7120ae0ea..47e840805 100644 | ||
| 192 | --- a/gio/giowin32-private.c | ||
| 193 | +++ b/gio/giowin32-private.c | ||
| 194 | @@ -16,11 +16,12 @@ | ||
| 195 | * along with this library; if not, see <http://www.gnu.org/licenses/>. | ||
| 196 | */ | ||
| 197 | |||
| 198 | +#include "gstrfuncsprivate.h" | ||
| 199 | |||
| 200 | -static gssize | ||
| 201 | +static gsize | ||
| 202 | g_utf16_len (const gunichar2 *str) | ||
| 203 | { | ||
| 204 | - gssize result; | ||
| 205 | + gsize result; | ||
| 206 | |||
| 207 | for (result = 0; str[0] != 0; str++, result++) | ||
| 208 | ; | ||
| 209 | @@ -31,17 +32,20 @@ g_utf16_len (const gunichar2 *str) | ||
| 210 | static gunichar2 * | ||
| 211 | g_wcsdup (const gunichar2 *str, gssize str_len) | ||
| 212 | { | ||
| 213 | - gssize str_size; | ||
| 214 | + gsize str_len_unsigned; | ||
| 215 | + gsize str_size; | ||
| 216 | |||
| 217 | g_return_val_if_fail (str != NULL, NULL); | ||
| 218 | |||
| 219 | - if (str_len == -1) | ||
| 220 | - str_len = g_utf16_len (str); | ||
| 221 | + if (str_len < 0) | ||
| 222 | + str_len_unsigned = g_utf16_len (str); | ||
| 223 | + else | ||
| 224 | + str_len_unsigned = (gsize) str_len; | ||
| 225 | |||
| 226 | - g_assert (str_len <= G_MAXSIZE / sizeof (gunichar2) - 1); | ||
| 227 | - str_size = (str_len + 1) * sizeof (gunichar2); | ||
| 228 | + g_assert (str_len_unsigned <= G_MAXSIZE / sizeof (gunichar2) - 1); | ||
| 229 | + str_size = (str_len_unsigned + 1) * sizeof (gunichar2); | ||
| 230 | |||
| 231 | - return g_memdup (str, str_size); | ||
| 232 | + return g_memdup2 (str, str_size); | ||
| 233 | } | ||
| 234 | |||
| 235 | static const gunichar2 * | ||
| 236 | diff --git a/gio/gkeyfilesettingsbackend.c b/gio/gkeyfilesettingsbackend.c | ||
| 237 | index cd5765afd..de216e615 100644 | ||
| 238 | --- a/gio/gkeyfilesettingsbackend.c | ||
| 239 | +++ b/gio/gkeyfilesettingsbackend.c | ||
| 240 | @@ -33,6 +33,7 @@ | ||
| 241 | #include "gfilemonitor.h" | ||
| 242 | #include "gsimplepermission.h" | ||
| 243 | #include "gsettingsbackendinternal.h" | ||
| 244 | +#include "gstrfuncsprivate.h" | ||
| 245 | #include "giomodule-priv.h" | ||
| 246 | #include "gportalsupport.h" | ||
| 247 | |||
| 248 | @@ -145,8 +146,8 @@ convert_path (GKeyfileSettingsBackend *kfsb, | ||
| 249 | gchar **group, | ||
| 250 | gchar **basename) | ||
| 251 | { | ||
| 252 | - gint key_len = strlen (key); | ||
| 253 | - gint i; | ||
| 254 | + gsize key_len = strlen (key); | ||
| 255 | + const gchar *last_slash; | ||
| 256 | |||
| 257 | if (key_len < kfsb->prefix_len || | ||
| 258 | memcmp (key, kfsb->prefix, kfsb->prefix_len) != 0) | ||
| 259 | @@ -155,38 +156,48 @@ convert_path (GKeyfileSettingsBackend *kfsb, | ||
| 260 | key_len -= kfsb->prefix_len; | ||
| 261 | key += kfsb->prefix_len; | ||
| 262 | |||
| 263 | - for (i = key_len; i >= 0; i--) | ||
| 264 | - if (key[i] == '/') | ||
| 265 | - break; | ||
| 266 | + last_slash = strrchr (key, '/'); | ||
| 267 | + | ||
| 268 | + /* Disallow empty group names or key names */ | ||
| 269 | + if (key_len == 0 || | ||
| 270 | + (last_slash != NULL && | ||
| 271 | + (*(last_slash + 1) == '\0' || | ||
| 272 | + last_slash == key))) | ||
| 273 | + return FALSE; | ||
| 274 | |||
| 275 | if (kfsb->root_group) | ||
| 276 | { | ||
| 277 | /* if a root_group was specified, make sure the user hasn't given | ||
| 278 | * a path that ghosts that group name | ||
| 279 | */ | ||
| 280 | - if (i == kfsb->root_group_len && memcmp (key, kfsb->root_group, i) == 0) | ||
| 281 | + if (last_slash != NULL && (last_slash - key) == kfsb->root_group_len && memcmp (key, kfsb->root_group, last_slash - key) == 0) | ||
| 282 | return FALSE; | ||
| 283 | } | ||
| 284 | else | ||
| 285 | { | ||
| 286 | /* if no root_group was given, ensure that the user gave a path */ | ||
| 287 | - if (i == -1) | ||
| 288 | + if (last_slash == NULL) | ||
| 289 | return FALSE; | ||
| 290 | } | ||
| 291 | |||
| 292 | if (group) | ||
| 293 | { | ||
| 294 | - if (i >= 0) | ||
| 295 | + if (last_slash != NULL) | ||
| 296 | { | ||
| 297 | - *group = g_memdup (key, i + 1); | ||
| 298 | - (*group)[i] = '\0'; | ||
| 299 | + *group = g_memdup2 (key, (last_slash - key) + 1); | ||
| 300 | + (*group)[(last_slash - key)] = '\0'; | ||
| 301 | } | ||
| 302 | else | ||
| 303 | *group = g_strdup (kfsb->root_group); | ||
| 304 | } | ||
| 305 | |||
| 306 | if (basename) | ||
| 307 | - *basename = g_memdup (key + i + 1, key_len - i); | ||
| 308 | + { | ||
| 309 | + if (last_slash != NULL) | ||
| 310 | + *basename = g_memdup2 (last_slash + 1, key_len - (last_slash - key)); | ||
| 311 | + else | ||
| 312 | + *basename = g_strdup (key); | ||
| 313 | + } | ||
| 314 | |||
| 315 | return TRUE; | ||
| 316 | } | ||
| 317 | diff --git a/gio/gsettingsschema.c b/gio/gsettingsschema.c | ||
| 318 | index 0b94f76f6..eb5a3b846 100644 | ||
| 319 | --- a/gio/gsettingsschema.c | ||
| 320 | +++ b/gio/gsettingsschema.c | ||
| 321 | @@ -20,6 +20,7 @@ | ||
| 322 | |||
| 323 | #include "gsettingsschema-internal.h" | ||
| 324 | #include "gsettings.h" | ||
| 325 | +#include "gstrfuncsprivate.h" | ||
| 326 | |||
| 327 | #include "gvdb/gvdb-reader.h" | ||
| 328 | #include "strinfo.c" | ||
| 329 | @@ -1067,9 +1068,9 @@ g_settings_schema_list_children (GSettingsSchema *schema) | ||
| 330 | |||
| 331 | if (g_str_has_suffix (key, "/")) | ||
| 332 | { | ||
| 333 | - gint length = strlen (key); | ||
| 334 | + gsize length = strlen (key); | ||
| 335 | |||
| 336 | - strv[j] = g_memdup (key, length); | ||
| 337 | + strv[j] = g_memdup2 (key, length); | ||
| 338 | strv[j][length - 1] = '\0'; | ||
| 339 | j++; | ||
| 340 | } | ||
| 341 | diff --git a/gio/gsocket.c b/gio/gsocket.c | ||
| 342 | index 2a15bdd22..554af026b 100644 | ||
| 343 | --- a/gio/gsocket.c | ||
| 344 | +++ b/gio/gsocket.c | ||
| 345 | @@ -75,6 +75,7 @@ | ||
| 346 | #include "gcredentialsprivate.h" | ||
| 347 | #include "glibintl.h" | ||
| 348 | #include "gioprivate.h" | ||
| 349 | +#include "gstrfuncsprivate.h" | ||
| 350 | |||
| 351 | #ifdef G_OS_WIN32 | ||
| 352 | /* For Windows XP runtime compatibility, but use the system's if_nametoindex() if available */ | ||
| 353 | @@ -174,7 +175,7 @@ static gboolean g_socket_datagram_based_condition_wait (GDatagramBased | ||
| 354 | GError **error); | ||
| 355 | |||
| 356 | static GSocketAddress * | ||
| 357 | -cache_recv_address (GSocket *socket, struct sockaddr *native, int native_len); | ||
| 358 | +cache_recv_address (GSocket *socket, struct sockaddr *native, size_t native_len); | ||
| 359 | |||
| 360 | static gssize | ||
| 361 | g_socket_receive_message_with_timeout (GSocket *socket, | ||
| 362 | @@ -260,7 +261,7 @@ struct _GSocketPrivate | ||
| 363 | struct { | ||
| 364 | GSocketAddress *addr; | ||
| 365 | struct sockaddr *native; | ||
| 366 | - gint native_len; | ||
| 367 | + gsize native_len; | ||
| 368 | guint64 last_used; | ||
| 369 | } recv_addr_cache[RECV_ADDR_CACHE_SIZE]; | ||
| 370 | }; | ||
| 371 | @@ -5259,14 +5260,14 @@ g_socket_send_messages_with_timeout (GSocket *socket, | ||
| 372 | } | ||
| 373 | |||
| 374 | static GSocketAddress * | ||
| 375 | -cache_recv_address (GSocket *socket, struct sockaddr *native, int native_len) | ||
| 376 | +cache_recv_address (GSocket *socket, struct sockaddr *native, size_t native_len) | ||
| 377 | { | ||
| 378 | GSocketAddress *saddr; | ||
| 379 | gint i; | ||
| 380 | guint64 oldest_time = G_MAXUINT64; | ||
| 381 | gint oldest_index = 0; | ||
| 382 | |||
| 383 | - if (native_len <= 0) | ||
| 384 | + if (native_len == 0) | ||
| 385 | return NULL; | ||
| 386 | |||
| 387 | saddr = NULL; | ||
| 388 | @@ -5274,7 +5275,7 @@ cache_recv_address (GSocket *socket, struct sockaddr *native, int native_len) | ||
| 389 | { | ||
| 390 | GSocketAddress *tmp = socket->priv->recv_addr_cache[i].addr; | ||
| 391 | gpointer tmp_native = socket->priv->recv_addr_cache[i].native; | ||
| 392 | - gint tmp_native_len = socket->priv->recv_addr_cache[i].native_len; | ||
| 393 | + gsize tmp_native_len = socket->priv->recv_addr_cache[i].native_len; | ||
| 394 | |||
| 395 | if (!tmp) | ||
| 396 | continue; | ||
| 397 | @@ -5304,7 +5305,7 @@ cache_recv_address (GSocket *socket, struct sockaddr *native, int native_len) | ||
| 398 | g_free (socket->priv->recv_addr_cache[oldest_index].native); | ||
| 399 | } | ||
| 400 | |||
| 401 | - socket->priv->recv_addr_cache[oldest_index].native = g_memdup (native, native_len); | ||
| 402 | + socket->priv->recv_addr_cache[oldest_index].native = g_memdup2 (native, native_len); | ||
| 403 | socket->priv->recv_addr_cache[oldest_index].native_len = native_len; | ||
| 404 | socket->priv->recv_addr_cache[oldest_index].addr = g_object_ref (saddr); | ||
| 405 | socket->priv->recv_addr_cache[oldest_index].last_used = g_get_monotonic_time (); | ||
| 406 | @@ -5452,6 +5453,9 @@ g_socket_receive_message_with_timeout (GSocket *socket, | ||
| 407 | /* do it */ | ||
| 408 | while (1) | ||
| 409 | { | ||
| 410 | + /* addrlen has to be of type int because that’s how WSARecvFrom() is defined */ | ||
| 411 | + G_STATIC_ASSERT (sizeof addr <= G_MAXINT); | ||
| 412 | + | ||
| 413 | addrlen = sizeof addr; | ||
| 414 | if (address) | ||
| 415 | result = WSARecvFrom (socket->priv->fd, | ||
| 416 | diff --git a/gio/gtlspassword.c b/gio/gtlspassword.c | ||
| 417 | index 1e437a7b6..bd86a6dfe 100644 | ||
| 418 | --- a/gio/gtlspassword.c | ||
| 419 | +++ b/gio/gtlspassword.c | ||
| 420 | @@ -23,6 +23,7 @@ | ||
| 421 | #include "glibintl.h" | ||
| 422 | |||
| 423 | #include "gioenumtypes.h" | ||
| 424 | +#include "gstrfuncsprivate.h" | ||
| 425 | #include "gtlspassword.h" | ||
| 426 | |||
| 427 | #include <string.h> | ||
| 428 | @@ -287,9 +288,14 @@ g_tls_password_set_value (GTlsPassword *password, | ||
| 429 | g_return_if_fail (G_IS_TLS_PASSWORD (password)); | ||
| 430 | |||
| 431 | if (length < 0) | ||
| 432 | - length = strlen ((gchar *)value); | ||
| 433 | + { | ||
| 434 | + /* FIXME: g_tls_password_set_value_full() doesn’t support unsigned gsize */ | ||
| 435 | + gsize length_unsigned = strlen ((gchar *) value); | ||
| 436 | + g_return_if_fail (length_unsigned <= G_MAXSSIZE); | ||
| 437 | + length = (gssize) length_unsigned; | ||
| 438 | + } | ||
| 439 | |||
| 440 | - g_tls_password_set_value_full (password, g_memdup (value, length), length, g_free); | ||
| 441 | + g_tls_password_set_value_full (password, g_memdup2 (value, (gsize) length), length, g_free); | ||
| 442 | } | ||
| 443 | |||
| 444 | /** | ||
| 445 | diff --git a/gio/gwin32registrykey.c b/gio/gwin32registrykey.c | ||
| 446 | index aa7819294..efb9ae713 100644 | ||
| 447 | --- a/gio/gwin32registrykey.c | ||
| 448 | +++ b/gio/gwin32registrykey.c | ||
| 449 | @@ -28,6 +28,8 @@ | ||
| 450 | #include <ntstatus.h> | ||
| 451 | #include <winternl.h> | ||
| 452 | |||
| 453 | +#include "gstrfuncsprivate.h" | ||
| 454 | + | ||
| 455 | #ifndef _WDMDDK_ | ||
| 456 | typedef enum _KEY_INFORMATION_CLASS { | ||
| 457 | KeyBasicInformation, | ||
| 458 | @@ -125,16 +127,34 @@ typedef enum | ||
| 459 | G_WIN32_REGISTRY_UPDATED_PATH = 1, | ||
| 460 | } GWin32RegistryKeyUpdateFlag; | ||
| 461 | |||
| 462 | +static gsize | ||
| 463 | +g_utf16_len (const gunichar2 *str) | ||
| 464 | +{ | ||
| 465 | + gsize result; | ||
| 466 | + | ||
| 467 | + for (result = 0; str[0] != 0; str++, result++) | ||
| 468 | + ; | ||
| 469 | + | ||
| 470 | + return result; | ||
| 471 | +} | ||
| 472 | + | ||
| 473 | static gunichar2 * | ||
| 474 | -g_wcsdup (const gunichar2 *str, | ||
| 475 | - gssize str_size) | ||
| 476 | +g_wcsdup (const gunichar2 *str, gssize str_len) | ||
| 477 | { | ||
| 478 | - if (str_size == -1) | ||
| 479 | - { | ||
| 480 | - str_size = wcslen (str) + 1; | ||
| 481 | - str_size *= sizeof (gunichar2); | ||
| 482 | - } | ||
| 483 | - return g_memdup (str, str_size); | ||
| 484 | + gsize str_len_unsigned; | ||
| 485 | + gsize str_size; | ||
| 486 | + | ||
| 487 | + g_return_val_if_fail (str != NULL, NULL); | ||
| 488 | + | ||
| 489 | + if (str_len < 0) | ||
| 490 | + str_len_unsigned = g_utf16_len (str); | ||
| 491 | + else | ||
| 492 | + str_len_unsigned = (gsize) str_len; | ||
| 493 | + | ||
| 494 | + g_assert (str_len_unsigned <= G_MAXSIZE / sizeof (gunichar2) - 1); | ||
| 495 | + str_size = (str_len_unsigned + 1) * sizeof (gunichar2); | ||
| 496 | + | ||
| 497 | + return g_memdup2 (str, str_size); | ||
| 498 | } | ||
| 499 | |||
| 500 | /** | ||
| 501 | @@ -247,7 +267,7 @@ g_win32_registry_value_iter_copy (const GWin32RegistryValueIter *iter) | ||
| 502 | new_iter->value_name_size = iter->value_name_size; | ||
| 503 | |||
| 504 | if (iter->value_data != NULL) | ||
| 505 | - new_iter->value_data = g_memdup (iter->value_data, iter->value_data_size); | ||
| 506 | + new_iter->value_data = g_memdup2 (iter->value_data, iter->value_data_size); | ||
| 507 | |||
| 508 | new_iter->value_data_size = iter->value_data_size; | ||
| 509 | |||
| 510 | @@ -268,8 +288,8 @@ g_win32_registry_value_iter_copy (const GWin32RegistryValueIter *iter) | ||
| 511 | new_iter->value_data_expanded_charsize = iter->value_data_expanded_charsize; | ||
| 512 | |||
| 513 | if (iter->value_data_expanded_u8 != NULL) | ||
| 514 | - new_iter->value_data_expanded_u8 = g_memdup (iter->value_data_expanded_u8, | ||
| 515 | - iter->value_data_expanded_charsize); | ||
| 516 | + new_iter->value_data_expanded_u8 = g_memdup2 (iter->value_data_expanded_u8, | ||
| 517 | + iter->value_data_expanded_charsize); | ||
| 518 | |||
| 519 | new_iter->value_data_expanded_u8_size = iter->value_data_expanded_charsize; | ||
| 520 | |||
| 521 | diff --git a/gio/tests/async-close-output-stream.c b/gio/tests/async-close-output-stream.c | ||
| 522 | index 5f6620275..d3f97a119 100644 | ||
| 523 | --- a/gio/tests/async-close-output-stream.c | ||
| 524 | +++ b/gio/tests/async-close-output-stream.c | ||
| 525 | @@ -24,6 +24,8 @@ | ||
| 526 | #include <stdlib.h> | ||
| 527 | #include <string.h> | ||
| 528 | |||
| 529 | +#include "gstrfuncsprivate.h" | ||
| 530 | + | ||
| 531 | #define DATA_TO_WRITE "Hello world\n" | ||
| 532 | |||
| 533 | typedef struct | ||
| 534 | @@ -147,9 +149,9 @@ prepare_data (SetupData *data, | ||
| 535 | |||
| 536 | data->expected_size = g_memory_output_stream_get_data_size (G_MEMORY_OUTPUT_STREAM (data->data_stream)); | ||
| 537 | |||
| 538 | - g_assert_cmpint (data->expected_size, >, 0); | ||
| 539 | + g_assert_cmpuint (data->expected_size, >, 0); | ||
| 540 | |||
| 541 | - data->expected_output = g_memdup (written, (guint)data->expected_size); | ||
| 542 | + data->expected_output = g_memdup2 (written, data->expected_size); | ||
| 543 | |||
| 544 | /* then recreate the streams and prepare them for the asynchronous close */ | ||
| 545 | destroy_streams (data); | ||
| 546 | diff --git a/gio/tests/gdbus-export.c b/gio/tests/gdbus-export.c | ||
| 547 | index fda654c44..10dd6d82f 100644 | ||
| 548 | --- a/gio/tests/gdbus-export.c | ||
| 549 | +++ b/gio/tests/gdbus-export.c | ||
| 550 | @@ -23,6 +23,7 @@ | ||
| 551 | #include <string.h> | ||
| 552 | |||
| 553 | #include "gdbus-tests.h" | ||
| 554 | +#include "gstrfuncsprivate.h" | ||
| 555 | |||
| 556 | /* all tests rely on a shared mainloop */ | ||
| 557 | static GMainLoop *loop = NULL; | ||
| 558 | @@ -671,7 +672,7 @@ subtree_introspect (GDBusConnection *connection, | ||
| 559 | g_assert_not_reached (); | ||
| 560 | } | ||
| 561 | |||
| 562 | - return g_memdup (interfaces, 2 * sizeof (void *)); | ||
| 563 | + return g_memdup2 (interfaces, 2 * sizeof (void *)); | ||
| 564 | } | ||
| 565 | |||
| 566 | static const GDBusInterfaceVTable * | ||
| 567 | @@ -727,7 +728,7 @@ dynamic_subtree_introspect (GDBusConnection *connection, | ||
| 568 | { | ||
| 569 | const GDBusInterfaceInfo *interfaces[2] = { &dyna_interface_info, NULL }; | ||
| 570 | |||
| 571 | - return g_memdup (interfaces, 2 * sizeof (void *)); | ||
| 572 | + return g_memdup2 (interfaces, 2 * sizeof (void *)); | ||
| 573 | } | ||
| 574 | |||
| 575 | static const GDBusInterfaceVTable * | ||
| 576 | diff --git a/gio/tests/gsettings.c b/gio/tests/gsettings.c | ||
| 577 | index baadca8f5..afe594a23 100644 | ||
| 578 | --- a/gio/tests/gsettings.c | ||
| 579 | +++ b/gio/tests/gsettings.c | ||
| 580 | @@ -1,3 +1,4 @@ | ||
| 581 | +#include <errno.h> | ||
| 582 | #include <stdlib.h> | ||
| 583 | #include <locale.h> | ||
| 584 | #include <libintl.h> | ||
| 585 | @@ -1740,6 +1741,14 @@ key_changed_cb (GSettings *settings, const gchar *key, gpointer data) | ||
| 586 | (*b) = TRUE; | ||
| 587 | } | ||
| 588 | |||
| 589 | +typedef struct | ||
| 590 | +{ | ||
| 591 | + const gchar *path; | ||
| 592 | + const gchar *root_group; | ||
| 593 | + const gchar *keyfile_group; | ||
| 594 | + const gchar *root_path; | ||
| 595 | +} KeyfileTestData; | ||
| 596 | + | ||
| 597 | /* | ||
| 598 | * Test that using a keyfile works | ||
| 599 | */ | ||
| 600 | @@ -1834,7 +1843,11 @@ test_keyfile (Fixture *fixture, | ||
| 601 | g_free (str); | ||
| 602 | |||
| 603 | g_settings_set (settings, "farewell", "s", "cheerio"); | ||
| 604 | - | ||
| 605 | + | ||
| 606 | + /* Check that empty keys/groups are not allowed. */ | ||
| 607 | + g_assert_false (g_settings_is_writable (settings, "")); | ||
| 608 | + g_assert_false (g_settings_is_writable (settings, "/")); | ||
| 609 | + | ||
| 610 | /* When executing as root, changing the mode of the keyfile will have | ||
| 611 | * no effect on the writability of the settings. | ||
| 612 | */ | ||
| 613 | @@ -1866,6 +1879,149 @@ test_keyfile (Fixture *fixture, | ||
| 614 | g_free (keyfile_path); | ||
| 615 | } | ||
| 616 | |||
| 617 | +/* | ||
| 618 | + * Test that using a keyfile works with a schema with no path set. | ||
| 619 | + */ | ||
| 620 | +static void | ||
| 621 | +test_keyfile_no_path (Fixture *fixture, | ||
| 622 | + gconstpointer user_data) | ||
| 623 | +{ | ||
| 624 | + const KeyfileTestData *test_data = user_data; | ||
| 625 | + GSettingsBackend *kf_backend; | ||
| 626 | + GSettings *settings; | ||
| 627 | + GKeyFile *keyfile; | ||
| 628 | + gboolean writable; | ||
| 629 | + gchar *key = NULL; | ||
| 630 | + GError *error = NULL; | ||
| 631 | + gchar *keyfile_path = NULL, *store_path = NULL; | ||
| 632 | + | ||
| 633 | + keyfile_path = g_build_filename (fixture->tmp_dir, "keyfile", NULL); | ||
| 634 | + store_path = g_build_filename (keyfile_path, "gsettings.store", NULL); | ||
| 635 | + kf_backend = g_keyfile_settings_backend_new (store_path, test_data->root_path, test_data->root_group); | ||
| 636 | + settings = g_settings_new_with_backend_and_path ("org.gtk.test.no-path", kf_backend, test_data->path); | ||
| 637 | + g_object_unref (kf_backend); | ||
| 638 | + | ||
| 639 | + g_settings_reset (settings, "test-boolean"); | ||
| 640 | + g_assert_true (g_settings_get_boolean (settings, "test-boolean")); | ||
| 641 | + | ||
| 642 | + writable = g_settings_is_writable (settings, "test-boolean"); | ||
| 643 | + g_assert_true (writable); | ||
| 644 | + g_settings_set (settings, "test-boolean", "b", FALSE); | ||
| 645 | + | ||
| 646 | + g_assert_false (g_settings_get_boolean (settings, "test-boolean")); | ||
| 647 | + | ||
| 648 | + g_settings_delay (settings); | ||
| 649 | + g_settings_set (settings, "test-boolean", "b", TRUE); | ||
| 650 | + g_settings_apply (settings); | ||
| 651 | + | ||
| 652 | + keyfile = g_key_file_new (); | ||
| 653 | + g_assert_true (g_key_file_load_from_file (keyfile, store_path, 0, NULL)); | ||
| 654 | + | ||
| 655 | + g_assert_true (g_key_file_get_boolean (keyfile, test_data->keyfile_group, "test-boolean", NULL)); | ||
| 656 | + | ||
| 657 | + g_key_file_free (keyfile); | ||
| 658 | + | ||
| 659 | + g_settings_reset (settings, "test-boolean"); | ||
| 660 | + g_settings_apply (settings); | ||
| 661 | + keyfile = g_key_file_new (); | ||
| 662 | + g_assert_true (g_key_file_load_from_file (keyfile, store_path, 0, NULL)); | ||
| 663 | + | ||
| 664 | + g_assert_false (g_key_file_get_string (keyfile, test_data->keyfile_group, "test-boolean", &error)); | ||
| 665 | + g_assert_error (error, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_KEY_NOT_FOUND); | ||
| 666 | + g_clear_error (&error); | ||
| 667 | + | ||
| 668 | + /* Check that empty keys/groups are not allowed. */ | ||
| 669 | + g_assert_false (g_settings_is_writable (settings, "")); | ||
| 670 | + g_assert_false (g_settings_is_writable (settings, "/")); | ||
| 671 | + | ||
| 672 | + /* Keys which ghost the root group name are not allowed. This can only be | ||
| 673 | + * tested when the path is `/` as otherwise it acts as a prefix and prevents | ||
| 674 | + * any ghosting. */ | ||
| 675 | + if (g_str_equal (test_data->path, "/")) | ||
| 676 | + { | ||
| 677 | + key = g_strdup_printf ("%s/%s", test_data->root_group, ""); | ||
| 678 | + g_assert_false (g_settings_is_writable (settings, key)); | ||
| 679 | + g_free (key); | ||
| 680 | + | ||
| 681 | + key = g_strdup_printf ("%s/%s", test_data->root_group, "/"); | ||
| 682 | + g_assert_false (g_settings_is_writable (settings, key)); | ||
| 683 | + g_free (key); | ||
| 684 | + | ||
| 685 | + key = g_strdup_printf ("%s/%s", test_data->root_group, "test-boolean"); | ||
| 686 | + g_assert_false (g_settings_is_writable (settings, key)); | ||
| 687 | + g_free (key); | ||
| 688 | + } | ||
| 689 | + | ||
| 690 | + g_key_file_free (keyfile); | ||
| 691 | + g_object_unref (settings); | ||
| 692 | + | ||
| 693 | + /* Clean up the temporary directory. */ | ||
| 694 | + g_assert_cmpint (g_chmod (keyfile_path, 0777) == 0 ? 0 : errno, ==, 0); | ||
| 695 | + g_assert_cmpint (g_remove (store_path) == 0 ? 0 : errno, ==, 0); | ||
| 696 | + g_assert_cmpint (g_rmdir (keyfile_path) == 0 ? 0 : errno, ==, 0); | ||
| 697 | + g_free (store_path); | ||
| 698 | + g_free (keyfile_path); | ||
| 699 | +} | ||
| 700 | + | ||
| 701 | +/* | ||
| 702 | + * Test that a keyfile rejects writes to keys outside its root path. | ||
| 703 | + */ | ||
| 704 | +static void | ||
| 705 | +test_keyfile_outside_root_path (Fixture *fixture, | ||
| 706 | + gconstpointer user_data) | ||
| 707 | +{ | ||
| 708 | + GSettingsBackend *kf_backend; | ||
| 709 | + GSettings *settings; | ||
| 710 | + gchar *keyfile_path = NULL, *store_path = NULL; | ||
| 711 | + | ||
| 712 | + keyfile_path = g_build_filename (fixture->tmp_dir, "keyfile", NULL); | ||
| 713 | + store_path = g_build_filename (keyfile_path, "gsettings.store", NULL); | ||
| 714 | + kf_backend = g_keyfile_settings_backend_new (store_path, "/tests/basic-types/", "root"); | ||
| 715 | + settings = g_settings_new_with_backend_and_path ("org.gtk.test.no-path", kf_backend, "/tests/"); | ||
| 716 | + g_object_unref (kf_backend); | ||
| 717 | + | ||
| 718 | + g_assert_false (g_settings_is_writable (settings, "test-boolean")); | ||
| 719 | + | ||
| 720 | + g_object_unref (settings); | ||
| 721 | + | ||
| 722 | + /* Clean up the temporary directory. The keyfile probably doesn’t exist, so | ||
| 723 | + * don’t error on failure. */ | ||
| 724 | + g_remove (store_path); | ||
| 725 | + g_assert_cmpint (g_rmdir (keyfile_path) == 0 ? 0 : errno, ==, 0); | ||
| 726 | + g_free (store_path); | ||
| 727 | + g_free (keyfile_path); | ||
| 728 | +} | ||
| 729 | + | ||
| 730 | +/* | ||
| 731 | + * Test that a keyfile rejects writes to keys in the root if no root group is set. | ||
| 732 | + */ | ||
| 733 | +static void | ||
| 734 | +test_keyfile_no_root_group (Fixture *fixture, | ||
| 735 | + gconstpointer user_data) | ||
| 736 | +{ | ||
| 737 | + GSettingsBackend *kf_backend; | ||
| 738 | + GSettings *settings; | ||
| 739 | + gchar *keyfile_path = NULL, *store_path = NULL; | ||
| 740 | + | ||
| 741 | + keyfile_path = g_build_filename (fixture->tmp_dir, "keyfile", NULL); | ||
| 742 | + store_path = g_build_filename (keyfile_path, "gsettings.store", NULL); | ||
| 743 | + kf_backend = g_keyfile_settings_backend_new (store_path, "/", NULL); | ||
| 744 | + settings = g_settings_new_with_backend_and_path ("org.gtk.test.no-path", kf_backend, "/"); | ||
| 745 | + g_object_unref (kf_backend); | ||
| 746 | + | ||
| 747 | + g_assert_false (g_settings_is_writable (settings, "test-boolean")); | ||
| 748 | + g_assert_true (g_settings_is_writable (settings, "child/test-boolean")); | ||
| 749 | + | ||
| 750 | + g_object_unref (settings); | ||
| 751 | + | ||
| 752 | + /* Clean up the temporary directory. The keyfile probably doesn’t exist, so | ||
| 753 | + * don’t error on failure. */ | ||
| 754 | + g_remove (store_path); | ||
| 755 | + g_assert_cmpint (g_rmdir (keyfile_path) == 0 ? 0 : errno, ==, 0); | ||
| 756 | + g_free (store_path); | ||
| 757 | + g_free (keyfile_path); | ||
| 758 | +} | ||
| 759 | + | ||
| 760 | /* Test that getting child schemas works | ||
| 761 | */ | ||
| 762 | static void | ||
| 763 | @@ -2844,6 +3000,14 @@ main (int argc, char *argv[]) | ||
| 764 | gchar *override_text; | ||
| 765 | gchar *enums; | ||
| 766 | gint result; | ||
| 767 | + const KeyfileTestData keyfile_test_data_explicit_path = { "/tests/", "root", "tests", "/" }; | ||
| 768 | + const KeyfileTestData keyfile_test_data_empty_path = { "/", "root", "root", "/" }; | ||
| 769 | + const KeyfileTestData keyfile_test_data_long_path = { | ||
| 770 | + "/tests/path/is/very/long/and/this/makes/some/comparisons/take/a/different/branch/", | ||
| 771 | + "root", | ||
| 772 | + "tests/path/is/very/long/and/this/makes/some/comparisons/take/a/different/branch", | ||
| 773 | + "/" | ||
| 774 | + }; | ||
| 775 | |||
| 776 | /* Meson build sets this */ | ||
| 777 | #ifdef TEST_LOCALE_PATH | ||
| 778 | @@ -2967,6 +3131,11 @@ main (int argc, char *argv[]) | ||
| 779 | } | ||
| 780 | |||
| 781 | g_test_add ("/gsettings/keyfile", Fixture, NULL, setup, test_keyfile, teardown); | ||
| 782 | + g_test_add ("/gsettings/keyfile/explicit-path", Fixture, &keyfile_test_data_explicit_path, setup, test_keyfile_no_path, teardown); | ||
| 783 | + g_test_add ("/gsettings/keyfile/empty-path", Fixture, &keyfile_test_data_empty_path, setup, test_keyfile_no_path, teardown); | ||
| 784 | + g_test_add ("/gsettings/keyfile/long-path", Fixture, &keyfile_test_data_long_path, setup, test_keyfile_no_path, teardown); | ||
| 785 | + g_test_add ("/gsettings/keyfile/outside-root-path", Fixture, NULL, setup, test_keyfile_outside_root_path, teardown); | ||
| 786 | + g_test_add ("/gsettings/keyfile/no-root-group", Fixture, NULL, setup, test_keyfile_no_root_group, teardown); | ||
| 787 | g_test_add_func ("/gsettings/child-schema", test_child_schema); | ||
| 788 | g_test_add_func ("/gsettings/strinfo", test_strinfo); | ||
| 789 | g_test_add_func ("/gsettings/enums", test_enums); | ||
| 790 | diff --git a/gio/tests/tls-interaction.c b/gio/tests/tls-interaction.c | ||
| 791 | index 4f0737d7e..5661e8e0d 100644 | ||
| 792 | --- a/gio/tests/tls-interaction.c | ||
| 793 | +++ b/gio/tests/tls-interaction.c | ||
| 794 | @@ -174,6 +174,38 @@ test_interaction_ask_password_finish_failure (GTlsInteraction *interaction, | ||
| 795 | } | ||
| 796 | |||
| 797 | |||
| 798 | +/* Return a copy of @str that is allocated in a silly way, to exercise | ||
| 799 | + * custom free-functions. The returned pointer points to a copy of @str | ||
| 800 | + * in a buffer of the form "BEFORE \0 str \0 AFTER". */ | ||
| 801 | +static guchar * | ||
| 802 | +special_dup (const char *str) | ||
| 803 | +{ | ||
| 804 | + GString *buf = g_string_new ("BEFORE"); | ||
| 805 | + guchar *ret; | ||
| 806 | + | ||
| 807 | + g_string_append_c (buf, '\0'); | ||
| 808 | + g_string_append (buf, str); | ||
| 809 | + g_string_append_c (buf, '\0'); | ||
| 810 | + g_string_append (buf, "AFTER"); | ||
| 811 | + ret = (guchar *) g_string_free (buf, FALSE); | ||
| 812 | + return ret + strlen ("BEFORE") + 1; | ||
| 813 | +} | ||
| 814 | + | ||
| 815 | + | ||
| 816 | +/* Free a copy of @str that was made with special_dup(), after asserting | ||
| 817 | + * that it has not been corrupted. */ | ||
| 818 | +static void | ||
| 819 | +special_free (gpointer p) | ||
| 820 | +{ | ||
| 821 | + gchar *s = p; | ||
| 822 | + gchar *buf = s - strlen ("BEFORE") - 1; | ||
| 823 | + | ||
| 824 | + g_assert_cmpstr (buf, ==, "BEFORE"); | ||
| 825 | + g_assert_cmpstr (s + strlen (s) + 1, ==, "AFTER"); | ||
| 826 | + g_free (buf); | ||
| 827 | +} | ||
| 828 | + | ||
| 829 | + | ||
| 830 | static GTlsInteractionResult | ||
| 831 | test_interaction_ask_password_sync_success (GTlsInteraction *interaction, | ||
| 832 | GTlsPassword *password, | ||
| 833 | @@ -181,6 +213,8 @@ test_interaction_ask_password_sync_success (GTlsInteraction *interaction, | ||
| 834 | GError **error) | ||
| 835 | { | ||
| 836 | TestInteraction *self; | ||
| 837 | + const guchar *value; | ||
| 838 | + gsize len; | ||
| 839 | |||
| 840 | g_assert (TEST_IS_INTERACTION (interaction)); | ||
| 841 | self = TEST_INTERACTION (interaction); | ||
| 842 | @@ -192,6 +226,27 @@ test_interaction_ask_password_sync_success (GTlsInteraction *interaction, | ||
| 843 | g_assert (error != NULL); | ||
| 844 | g_assert (*error == NULL); | ||
| 845 | |||
| 846 | + /* Exercise different ways to set the value */ | ||
| 847 | + g_tls_password_set_value (password, (const guchar *) "foo", 4); | ||
| 848 | + len = 0; | ||
| 849 | + value = g_tls_password_get_value (password, &len); | ||
| 850 | + g_assert_cmpmem (value, len, "foo", 4); | ||
| 851 | + | ||
| 852 | + g_tls_password_set_value (password, (const guchar *) "bar", -1); | ||
| 853 | + len = 0; | ||
| 854 | + value = g_tls_password_get_value (password, &len); | ||
| 855 | + g_assert_cmpmem (value, len, "bar", 3); | ||
| 856 | + | ||
| 857 | + g_tls_password_set_value_full (password, special_dup ("baa"), 4, special_free); | ||
| 858 | + len = 0; | ||
| 859 | + value = g_tls_password_get_value (password, &len); | ||
| 860 | + g_assert_cmpmem (value, len, "baa", 4); | ||
| 861 | + | ||
| 862 | + g_tls_password_set_value_full (password, special_dup ("baz"), -1, special_free); | ||
| 863 | + len = 0; | ||
| 864 | + value = g_tls_password_get_value (password, &len); | ||
| 865 | + g_assert_cmpmem (value, len, "baz", 3); | ||
| 866 | + | ||
| 867 | /* Don't do this in real life. Include a null terminator for testing */ | ||
| 868 | g_tls_password_set_value (password, (const guchar *)"the password", 13); | ||
| 869 | return G_TLS_INTERACTION_HANDLED; | ||
| 870 | diff --git a/gio/win32/gwinhttpfile.c b/gio/win32/gwinhttpfile.c | ||
| 871 | index cf5eed31d..246ec0578 100644 | ||
| 872 | --- a/gio/win32/gwinhttpfile.c | ||
| 873 | +++ b/gio/win32/gwinhttpfile.c | ||
| 874 | @@ -29,6 +29,7 @@ | ||
| 875 | #include "gio/gfile.h" | ||
| 876 | #include "gio/gfileattribute.h" | ||
| 877 | #include "gio/gfileinfo.h" | ||
| 878 | +#include "gstrfuncsprivate.h" | ||
| 879 | #include "gwinhttpfile.h" | ||
| 880 | #include "gwinhttpfileinputstream.h" | ||
| 881 | #include "gwinhttpfileoutputstream.h" | ||
| 882 | @@ -393,10 +394,10 @@ g_winhttp_file_resolve_relative_path (GFile *file, | ||
| 883 | child = g_object_new (G_TYPE_WINHTTP_FILE, NULL); | ||
| 884 | child->vfs = winhttp_file->vfs; | ||
| 885 | child->url = winhttp_file->url; | ||
| 886 | - child->url.lpszScheme = g_memdup (winhttp_file->url.lpszScheme, (winhttp_file->url.dwSchemeLength+1)*2); | ||
| 887 | - child->url.lpszHostName = g_memdup (winhttp_file->url.lpszHostName, (winhttp_file->url.dwHostNameLength+1)*2); | ||
| 888 | - child->url.lpszUserName = g_memdup (winhttp_file->url.lpszUserName, (winhttp_file->url.dwUserNameLength+1)*2); | ||
| 889 | - child->url.lpszPassword = g_memdup (winhttp_file->url.lpszPassword, (winhttp_file->url.dwPasswordLength+1)*2); | ||
| 890 | + child->url.lpszScheme = g_memdup2 (winhttp_file->url.lpszScheme, ((gsize) winhttp_file->url.dwSchemeLength + 1) * 2); | ||
| 891 | + child->url.lpszHostName = g_memdup2 (winhttp_file->url.lpszHostName, ((gsize) winhttp_file->url.dwHostNameLength + 1) * 2); | ||
| 892 | + child->url.lpszUserName = g_memdup2 (winhttp_file->url.lpszUserName, ((gsize) winhttp_file->url.dwUserNameLength + 1) * 2); | ||
| 893 | + child->url.lpszPassword = g_memdup2 (winhttp_file->url.lpszPassword, ((gsize) winhttp_file->url.dwPasswordLength + 1) * 2); | ||
| 894 | child->url.lpszUrlPath = wnew_path; | ||
| 895 | child->url.dwUrlPathLength = wcslen (wnew_path); | ||
| 896 | child->url.lpszExtraInfo = NULL; | ||
| 897 | diff --git a/glib/gbytes.c b/glib/gbytes.c | ||
| 898 | index ec6923188..6f17d104c 100644 | ||
| 899 | --- a/glib/gbytes.c | ||
| 900 | +++ b/glib/gbytes.c | ||
| 901 | @@ -34,6 +34,8 @@ | ||
| 902 | |||
| 903 | #include <string.h> | ||
| 904 | |||
| 905 | +#include "gstrfuncsprivate.h" | ||
| 906 | + | ||
| 907 | /** | ||
| 908 | * GBytes: | ||
| 909 | * | ||
| 910 | @@ -95,7 +97,7 @@ g_bytes_new (gconstpointer data, | ||
| 911 | { | ||
| 912 | g_return_val_if_fail (data != NULL || size == 0, NULL); | ||
| 913 | |||
| 914 | - return g_bytes_new_take (g_memdup (data, size), size); | ||
| 915 | + return g_bytes_new_take (g_memdup2 (data, size), size); | ||
| 916 | } | ||
| 917 | |||
| 918 | /** | ||
| 919 | @@ -499,7 +501,7 @@ g_bytes_unref_to_data (GBytes *bytes, | ||
| 920 | * Copy: Non g_malloc (or compatible) allocator, or static memory, | ||
| 921 | * so we have to copy, and then unref. | ||
| 922 | */ | ||
| 923 | - result = g_memdup (bytes->data, bytes->size); | ||
| 924 | + result = g_memdup2 (bytes->data, bytes->size); | ||
| 925 | *size = bytes->size; | ||
| 926 | g_bytes_unref (bytes); | ||
| 927 | } | ||
| 928 | diff --git a/glib/gdir.c b/glib/gdir.c | ||
| 929 | index 6b85e99c8..6747a8c6f 100644 | ||
| 930 | --- a/glib/gdir.c | ||
| 931 | +++ b/glib/gdir.c | ||
| 932 | @@ -37,6 +37,7 @@ | ||
| 933 | #include "gconvert.h" | ||
| 934 | #include "gfileutils.h" | ||
| 935 | #include "gstrfuncs.h" | ||
| 936 | +#include "gstrfuncsprivate.h" | ||
| 937 | #include "gtestutils.h" | ||
| 938 | #include "glibintl.h" | ||
| 939 | |||
| 940 | @@ -112,7 +113,7 @@ g_dir_open_with_errno (const gchar *path, | ||
| 941 | return NULL; | ||
| 942 | #endif | ||
| 943 | |||
| 944 | - return g_memdup (&dir, sizeof dir); | ||
| 945 | + return g_memdup2 (&dir, sizeof dir); | ||
| 946 | } | ||
| 947 | |||
| 948 | /** | ||
| 949 | diff --git a/glib/ghash.c b/glib/ghash.c | ||
| 950 | index 0f1562a06..c1e15c957 100644 | ||
| 951 | --- a/glib/ghash.c | ||
| 952 | +++ b/glib/ghash.c | ||
| 953 | @@ -34,6 +34,7 @@ | ||
| 954 | #include "gmacros.h" | ||
| 955 | #include "glib-private.h" | ||
| 956 | #include "gstrfuncs.h" | ||
| 957 | +#include "gstrfuncsprivate.h" | ||
| 958 | #include "gatomic.h" | ||
| 959 | #include "gtestutils.h" | ||
| 960 | #include "gslice.h" | ||
| 961 | @@ -962,7 +963,7 @@ g_hash_table_ensure_keyval_fits (GHashTable *hash_table, gpointer key, gpointer | ||
| 962 | if (hash_table->have_big_keys) | ||
| 963 | { | ||
| 964 | if (key != value) | ||
| 965 | - hash_table->values = g_memdup (hash_table->keys, sizeof (gpointer) * hash_table->size); | ||
| 966 | + hash_table->values = g_memdup2 (hash_table->keys, sizeof (gpointer) * hash_table->size); | ||
| 967 | /* Keys and values are both big now, so no need for further checks */ | ||
| 968 | return; | ||
| 969 | } | ||
| 970 | @@ -970,7 +971,7 @@ g_hash_table_ensure_keyval_fits (GHashTable *hash_table, gpointer key, gpointer | ||
| 971 | { | ||
| 972 | if (key != value) | ||
| 973 | { | ||
| 974 | - hash_table->values = g_memdup (hash_table->keys, sizeof (guint) * hash_table->size); | ||
| 975 | + hash_table->values = g_memdup2 (hash_table->keys, sizeof (guint) * hash_table->size); | ||
| 976 | is_a_set = FALSE; | ||
| 977 | } | ||
| 978 | } | ||
| 979 | @@ -998,7 +999,7 @@ g_hash_table_ensure_keyval_fits (GHashTable *hash_table, gpointer key, gpointer | ||
| 980 | |||
| 981 | /* Just split if necessary */ | ||
| 982 | if (is_a_set && key != value) | ||
| 983 | - hash_table->values = g_memdup (hash_table->keys, sizeof (gpointer) * hash_table->size); | ||
| 984 | + hash_table->values = g_memdup2 (hash_table->keys, sizeof (gpointer) * hash_table->size); | ||
| 985 | |||
| 986 | #endif | ||
| 987 | } | ||
| 988 | diff --git a/glib/giochannel.c b/glib/giochannel.c | ||
| 989 | index d16399846..b41381d38 100644 | ||
| 990 | --- a/glib/giochannel.c | ||
| 991 | +++ b/glib/giochannel.c | ||
| 992 | @@ -37,6 +37,7 @@ | ||
| 993 | #include "giochannel.h" | ||
| 994 | |||
| 995 | #include "gstrfuncs.h" | ||
| 996 | +#include "gstrfuncsprivate.h" | ||
| 997 | #include "gtestutils.h" | ||
| 998 | #include "glibintl.h" | ||
| 999 | |||
| 1000 | @@ -886,17 +887,26 @@ g_io_channel_set_line_term (GIOChannel *channel, | ||
| 1001 | const gchar *line_term, | ||
| 1002 | gint length) | ||
| 1003 | { | ||
| 1004 | + guint length_unsigned; | ||
| 1005 | + | ||
| 1006 | g_return_if_fail (channel != NULL); | ||
| 1007 | g_return_if_fail (line_term == NULL || length != 0); /* Disallow "" */ | ||
| 1008 | |||
| 1009 | if (line_term == NULL) | ||
| 1010 | - length = 0; | ||
| 1011 | - else if (length < 0) | ||
| 1012 | - length = strlen (line_term); | ||
| 1013 | + length_unsigned = 0; | ||
| 1014 | + else if (length >= 0) | ||
| 1015 | + length_unsigned = (guint) length; | ||
| 1016 | + else | ||
| 1017 | + { | ||
| 1018 | + /* FIXME: We’re constrained by line_term_len being a guint here */ | ||
| 1019 | + gsize length_size = strlen (line_term); | ||
| 1020 | + g_return_if_fail (length_size <= G_MAXUINT); | ||
| 1021 | + length_unsigned = (guint) length_size; | ||
| 1022 | + } | ||
| 1023 | |||
| 1024 | g_free (channel->line_term); | ||
| 1025 | - channel->line_term = line_term ? g_memdup (line_term, length) : NULL; | ||
| 1026 | - channel->line_term_len = length; | ||
| 1027 | + channel->line_term = line_term ? g_memdup2 (line_term, length_unsigned) : NULL; | ||
| 1028 | + channel->line_term_len = length_unsigned; | ||
| 1029 | } | ||
| 1030 | |||
| 1031 | /** | ||
| 1032 | @@ -1673,10 +1683,10 @@ g_io_channel_read_line (GIOChannel *channel, | ||
| 1033 | |||
| 1034 | /* Copy the read bytes (including any embedded nuls) and nul-terminate. | ||
| 1035 | * `USE_BUF (channel)->str` is guaranteed to be nul-terminated as it’s a | ||
| 1036 | - * #GString, so it’s safe to call g_memdup() with +1 length to allocate | ||
| 1037 | + * #GString, so it’s safe to call g_memdup2() with +1 length to allocate | ||
| 1038 | * a nul-terminator. */ | ||
| 1039 | g_assert (USE_BUF (channel)); | ||
| 1040 | - line = g_memdup (USE_BUF (channel)->str, got_length + 1); | ||
| 1041 | + line = g_memdup2 (USE_BUF (channel)->str, got_length + 1); | ||
| 1042 | line[got_length] = '\0'; | ||
| 1043 | *str_return = g_steal_pointer (&line); | ||
| 1044 | g_string_erase (USE_BUF (channel), 0, got_length); | ||
| 1045 | diff --git a/glib/gslice.c b/glib/gslice.c | ||
| 1046 | index 4c758c3be..bcdbb8853 100644 | ||
| 1047 | --- a/glib/gslice.c | ||
| 1048 | +++ b/glib/gslice.c | ||
| 1049 | @@ -41,6 +41,7 @@ | ||
| 1050 | #include "gmain.h" | ||
| 1051 | #include "gmem.h" /* gslice.h */ | ||
| 1052 | #include "gstrfuncs.h" | ||
| 1053 | +#include "gstrfuncsprivate.h" | ||
| 1054 | #include "gutils.h" | ||
| 1055 | #include "gtrashstack.h" | ||
| 1056 | #include "gtestutils.h" | ||
| 1057 | @@ -350,7 +351,7 @@ g_slice_get_config_state (GSliceConfig ckey, | ||
| 1058 | array[i++] = allocator->contention_counters[address]; | ||
| 1059 | array[i++] = allocator_get_magazine_threshold (allocator, address); | ||
| 1060 | *n_values = i; | ||
| 1061 | - return g_memdup (array, sizeof (array[0]) * *n_values); | ||
| 1062 | + return g_memdup2 (array, sizeof (array[0]) * *n_values); | ||
| 1063 | default: | ||
| 1064 | return NULL; | ||
| 1065 | } | ||
| 1066 | diff --git a/glib/gstrfuncsprivate.h b/glib/gstrfuncsprivate.h | ||
| 1067 | new file mode 100644 | ||
| 1068 | index 000000000..85c88328a | ||
| 1069 | --- /dev/null | ||
| 1070 | +++ b/glib/gstrfuncsprivate.h | ||
| 1071 | @@ -0,0 +1,55 @@ | ||
| 1072 | +/* GLIB - Library of useful routines for C programming | ||
| 1073 | + * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald | ||
| 1074 | + * | ||
| 1075 | + * This library is free software; you can redistribute it and/or | ||
| 1076 | + * modify it under the terms of the GNU Lesser General Public | ||
| 1077 | + * License as published by the Free Software Foundation; either | ||
| 1078 | + * version 2.1 of the License, or (at your option) any later version. | ||
| 1079 | + * | ||
| 1080 | + * This library is distributed in the hope that it will be useful, | ||
| 1081 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 1082 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
| 1083 | + * Lesser General Public License for more details. | ||
| 1084 | + * | ||
| 1085 | + * You should have received a copy of the GNU Lesser General Public | ||
| 1086 | + * License along with this library; if not, see <http://www.gnu.org/licenses/>. | ||
| 1087 | + */ | ||
| 1088 | + | ||
| 1089 | +#include <glib.h> | ||
| 1090 | +#include <string.h> | ||
| 1091 | + | ||
| 1092 | +/* | ||
| 1093 | + * g_memdup2: | ||
| 1094 | + * @mem: (nullable): the memory to copy. | ||
| 1095 | + * @byte_size: the number of bytes to copy. | ||
| 1096 | + * | ||
| 1097 | + * Allocates @byte_size bytes of memory, and copies @byte_size bytes into it | ||
| 1098 | + * from @mem. If @mem is %NULL it returns %NULL. | ||
| 1099 | + * | ||
| 1100 | + * This replaces g_memdup(), which was prone to integer overflows when | ||
| 1101 | + * converting the argument from a #gsize to a #guint. | ||
| 1102 | + * | ||
| 1103 | + * This static inline version is a backport of the new public API from | ||
| 1104 | + * GLib 2.68, kept internal to GLib for backport to older stable releases. | ||
| 1105 | + * See https://gitlab.gnome.org/GNOME/glib/-/issues/2319. | ||
| 1106 | + * | ||
| 1107 | + * Returns: (nullable): a pointer to the newly-allocated copy of the memory, | ||
| 1108 | + * or %NULL if @mem is %NULL. | ||
| 1109 | + * Since: 2.68 | ||
| 1110 | + */ | ||
| 1111 | +static inline gpointer | ||
| 1112 | +g_memdup2 (gconstpointer mem, | ||
| 1113 | + gsize byte_size) | ||
| 1114 | +{ | ||
| 1115 | + gpointer new_mem; | ||
| 1116 | + | ||
| 1117 | + if (mem && byte_size != 0) | ||
| 1118 | + { | ||
| 1119 | + new_mem = g_malloc (byte_size); | ||
| 1120 | + memcpy (new_mem, mem, byte_size); | ||
| 1121 | + } | ||
| 1122 | + else | ||
| 1123 | + new_mem = NULL; | ||
| 1124 | + | ||
| 1125 | + return new_mem; | ||
| 1126 | +} | ||
| 1127 | diff --git a/glib/gtestutils.c b/glib/gtestutils.c | ||
| 1128 | index 18b117285..26d46ad75 100644 | ||
| 1129 | --- a/glib/gtestutils.c | ||
| 1130 | +++ b/glib/gtestutils.c | ||
| 1131 | @@ -49,6 +49,7 @@ | ||
| 1132 | #include "gpattern.h" | ||
| 1133 | #include "grand.h" | ||
| 1134 | #include "gstrfuncs.h" | ||
| 1135 | +#include "gstrfuncsprivate.h" | ||
| 1136 | #include "gtimer.h" | ||
| 1137 | #include "gslice.h" | ||
| 1138 | #include "gspawn.h" | ||
| 1139 | @@ -3803,7 +3804,7 @@ g_test_log_extract (GTestLogBuffer *tbuffer) | ||
| 1140 | if (p <= tbuffer->data->str + mlength) | ||
| 1141 | { | ||
| 1142 | g_string_erase (tbuffer->data, 0, mlength); | ||
| 1143 | - tbuffer->msgs = g_slist_prepend (tbuffer->msgs, g_memdup (&msg, sizeof (msg))); | ||
| 1144 | + tbuffer->msgs = g_slist_prepend (tbuffer->msgs, g_memdup2 (&msg, sizeof (msg))); | ||
| 1145 | return TRUE; | ||
| 1146 | } | ||
| 1147 | |||
| 1148 | diff --git a/glib/gvariant.c b/glib/gvariant.c | ||
| 1149 | index 77d7e746b..ef4257f6d 100644 | ||
| 1150 | --- a/glib/gvariant.c | ||
| 1151 | +++ b/glib/gvariant.c | ||
| 1152 | @@ -33,6 +33,7 @@ | ||
| 1153 | |||
| 1154 | #include <string.h> | ||
| 1155 | |||
| 1156 | +#include "gstrfuncsprivate.h" | ||
| 1157 | |||
| 1158 | /** | ||
| 1159 | * SECTION:gvariant | ||
| 1160 | @@ -725,7 +726,7 @@ g_variant_new_variant (GVariant *value) | ||
| 1161 | g_variant_ref_sink (value); | ||
| 1162 | |||
| 1163 | return g_variant_new_from_children (G_VARIANT_TYPE_VARIANT, | ||
| 1164 | - g_memdup (&value, sizeof value), | ||
| 1165 | + g_memdup2 (&value, sizeof value), | ||
| 1166 | 1, g_variant_is_trusted (value)); | ||
| 1167 | } | ||
| 1168 | |||
| 1169 | @@ -1229,7 +1230,7 @@ g_variant_new_fixed_array (const GVariantType *element_type, | ||
| 1170 | return NULL; | ||
| 1171 | } | ||
| 1172 | |||
| 1173 | - data = g_memdup (elements, n_elements * element_size); | ||
| 1174 | + data = g_memdup2 (elements, n_elements * element_size); | ||
| 1175 | value = g_variant_new_from_data (array_type, data, | ||
| 1176 | n_elements * element_size, | ||
| 1177 | FALSE, g_free, data); | ||
| 1178 | @@ -1908,7 +1909,7 @@ g_variant_dup_bytestring (GVariant *value, | ||
| 1179 | if (length) | ||
| 1180 | *length = size; | ||
| 1181 | |||
| 1182 | - return g_memdup (original, size + 1); | ||
| 1183 | + return g_memdup2 (original, size + 1); | ||
| 1184 | } | ||
| 1185 | |||
| 1186 | /** | ||
| 1187 | diff --git a/glib/gvarianttype.c b/glib/gvarianttype.c | ||
| 1188 | index c46f1a2c6..585e29ab2 100644 | ||
| 1189 | --- a/glib/gvarianttype.c | ||
| 1190 | +++ b/glib/gvarianttype.c | ||
| 1191 | @@ -28,6 +28,7 @@ | ||
| 1192 | |||
| 1193 | #include <string.h> | ||
| 1194 | |||
| 1195 | +#include "gstrfuncsprivate.h" | ||
| 1196 | |||
| 1197 | /** | ||
| 1198 | * SECTION:gvarianttype | ||
| 1199 | @@ -1181,7 +1182,7 @@ g_variant_type_new_tuple (const GVariantType * const *items, | ||
| 1200 | g_assert (offset < sizeof buffer); | ||
| 1201 | buffer[offset++] = ')'; | ||
| 1202 | |||
| 1203 | - return (GVariantType *) g_memdup (buffer, offset); | ||
| 1204 | + return (GVariantType *) g_memdup2 (buffer, offset); | ||
| 1205 | } | ||
| 1206 | |||
| 1207 | /** | ||
| 1208 | diff --git a/glib/meson.build b/glib/meson.build | ||
| 1209 | index 456e0c2a1..2e5cd77bb 100644 | ||
| 1210 | --- a/glib/meson.build | ||
| 1211 | +++ b/glib/meson.build | ||
| 1212 | @@ -268,6 +268,7 @@ glib_sources = files( | ||
| 1213 | 'gslist.c', | ||
| 1214 | 'gstdio.c', | ||
| 1215 | 'gstrfuncs.c', | ||
| 1216 | + 'gstrfuncsprivate.h', | ||
| 1217 | 'gstring.c', | ||
| 1218 | 'gstringchunk.c', | ||
| 1219 | 'gtestutils.c', | ||
| 1220 | diff --git a/glib/tests/array-test.c b/glib/tests/array-test.c | ||
| 1221 | index 1da514a3e..88f22de80 100644 | ||
| 1222 | --- a/glib/tests/array-test.c | ||
| 1223 | +++ b/glib/tests/array-test.c | ||
| 1224 | @@ -29,6 +29,8 @@ | ||
| 1225 | #include <string.h> | ||
| 1226 | #include "glib.h" | ||
| 1227 | |||
| 1228 | +#include "gstrfuncsprivate.h" | ||
| 1229 | + | ||
| 1230 | /* Test data to be passed to any function which calls g_array_new(), providing | ||
| 1231 | * the parameters for that call. Most #GArray tests should be repeated for all | ||
| 1232 | * possible values of #ArrayTestData. */ | ||
| 1233 | @@ -1917,7 +1919,7 @@ byte_array_new_take (void) | ||
| 1234 | GByteArray *gbarray; | ||
| 1235 | guint8 *data; | ||
| 1236 | |||
| 1237 | - data = g_memdup ("woooweeewow", 11); | ||
| 1238 | + data = g_memdup2 ("woooweeewow", 11); | ||
| 1239 | gbarray = g_byte_array_new_take (data, 11); | ||
| 1240 | g_assert (gbarray->data == data); | ||
| 1241 | g_assert_cmpuint (gbarray->len, ==, 11); | ||
| 1242 | diff --git a/glib/tests/io-channel.c b/glib/tests/io-channel.c | ||
| 1243 | index ff53fcef7..4a1b10876 100644 | ||
| 1244 | --- a/glib/tests/io-channel.c | ||
| 1245 | +++ b/glib/tests/io-channel.c | ||
| 1246 | @@ -49,8 +49,10 @@ test_read_line_embedded_nuls (void) | ||
| 1247 | channel = g_io_channel_new_file (filename, "r", &local_error); | ||
| 1248 | g_assert_no_error (local_error); | ||
| 1249 | |||
| 1250 | - /* Only break on newline characters, not nuls. */ | ||
| 1251 | - g_io_channel_set_line_term (channel, "\n", 1); | ||
| 1252 | + /* Only break on newline characters, not nuls. | ||
| 1253 | + * Use length -1 here to exercise glib#2323; the case where length > 0 | ||
| 1254 | + * is covered in glib/tests/protocol.c. */ | ||
| 1255 | + g_io_channel_set_line_term (channel, "\n", -1); | ||
| 1256 | g_io_channel_set_encoding (channel, NULL, &local_error); | ||
| 1257 | g_assert_no_error (local_error); | ||
| 1258 | |||
| 1259 | diff --git a/glib/tests/option-context.c b/glib/tests/option-context.c | ||
| 1260 | index 149d22353..88d2b80d1 100644 | ||
| 1261 | --- a/glib/tests/option-context.c | ||
| 1262 | +++ b/glib/tests/option-context.c | ||
| 1263 | @@ -27,6 +27,8 @@ | ||
| 1264 | #include <string.h> | ||
| 1265 | #include <locale.h> | ||
| 1266 | |||
| 1267 | +#include "gstrfuncsprivate.h" | ||
| 1268 | + | ||
| 1269 | static GOptionEntry main_entries[] = { | ||
| 1270 | { "main-switch", 0, 0, | ||
| 1271 | G_OPTION_ARG_NONE, NULL, | ||
| 1272 | @@ -256,7 +258,7 @@ join_stringv (int argc, char **argv) | ||
| 1273 | static char ** | ||
| 1274 | copy_stringv (char **argv, int argc) | ||
| 1275 | { | ||
| 1276 | - return g_memdup (argv, sizeof (char *) * (argc + 1)); | ||
| 1277 | + return g_memdup2 (argv, sizeof (char *) * (argc + 1)); | ||
| 1278 | } | ||
| 1279 | |||
| 1280 | static void | ||
| 1281 | @@ -2323,7 +2325,7 @@ test_group_parse (void) | ||
| 1282 | g_option_context_add_group (context, group); | ||
| 1283 | |||
| 1284 | argv = split_string ("program --test arg1 -f arg2 --group-test arg3 --frob arg4 -z arg5", &argc); | ||
| 1285 | - orig_argv = g_memdup (argv, (argc + 1) * sizeof (char *)); | ||
| 1286 | + orig_argv = g_memdup2 (argv, (argc + 1) * sizeof (char *)); | ||
| 1287 | |||
| 1288 | retval = g_option_context_parse (context, &argc, &argv, &error); | ||
| 1289 | |||
| 1290 | diff --git a/glib/tests/strfuncs.c b/glib/tests/strfuncs.c | ||
| 1291 | index e1f9619c7..d968afff9 100644 | ||
| 1292 | --- a/glib/tests/strfuncs.c | ||
| 1293 | +++ b/glib/tests/strfuncs.c | ||
| 1294 | @@ -32,6 +32,8 @@ | ||
| 1295 | #include <string.h> | ||
| 1296 | #include "glib.h" | ||
| 1297 | |||
| 1298 | +#include "gstrfuncsprivate.h" | ||
| 1299 | + | ||
| 1300 | #if defined (_MSC_VER) && (_MSC_VER <= 1800) | ||
| 1301 | #define isnan(x) _isnan(x) | ||
| 1302 | |||
| 1303 | @@ -219,6 +221,26 @@ test_memdup (void) | ||
| 1304 | g_free (str_dup); | ||
| 1305 | } | ||
| 1306 | |||
| 1307 | +/* Testing g_memdup2() function with various positive and negative cases */ | ||
| 1308 | +static void | ||
| 1309 | +test_memdup2 (void) | ||
| 1310 | +{ | ||
| 1311 | + gchar *str_dup = NULL; | ||
| 1312 | + const gchar *str = "The quick brown fox jumps over the lazy dog"; | ||
| 1313 | + | ||
| 1314 | + /* Testing negative cases */ | ||
| 1315 | + g_assert_null (g_memdup2 (NULL, 1024)); | ||
| 1316 | + g_assert_null (g_memdup2 (str, 0)); | ||
| 1317 | + g_assert_null (g_memdup2 (NULL, 0)); | ||
| 1318 | + | ||
| 1319 | + /* Testing normal usage cases */ | ||
| 1320 | + str_dup = g_memdup2 (str, strlen (str) + 1); | ||
| 1321 | + g_assert_nonnull (str_dup); | ||
| 1322 | + g_assert_cmpstr (str, ==, str_dup); | ||
| 1323 | + | ||
| 1324 | + g_free (str_dup); | ||
| 1325 | +} | ||
| 1326 | + | ||
| 1327 | /* Testing g_strpcpy() function with various positive and negative cases */ | ||
| 1328 | static void | ||
| 1329 | test_stpcpy (void) | ||
| 1330 | @@ -2523,6 +2545,7 @@ main (int argc, | ||
| 1331 | g_test_add_func ("/strfuncs/has-prefix", test_has_prefix); | ||
| 1332 | g_test_add_func ("/strfuncs/has-suffix", test_has_suffix); | ||
| 1333 | g_test_add_func ("/strfuncs/memdup", test_memdup); | ||
| 1334 | + g_test_add_func ("/strfuncs/memdup2", test_memdup2); | ||
| 1335 | g_test_add_func ("/strfuncs/stpcpy", test_stpcpy); | ||
| 1336 | g_test_add_func ("/strfuncs/str_match_string", test_str_match_string); | ||
| 1337 | g_test_add_func ("/strfuncs/str_tokenize_and_fold", test_str_tokenize_and_fold); | ||
| 1338 | diff --git a/gobject/gsignal.c b/gobject/gsignal.c | ||
| 1339 | index 45effa92d..effbfec62 100644 | ||
| 1340 | --- a/gobject/gsignal.c | ||
| 1341 | +++ b/gobject/gsignal.c | ||
| 1342 | @@ -28,6 +28,7 @@ | ||
| 1343 | #include <signal.h> | ||
| 1344 | |||
| 1345 | #include "gsignal.h" | ||
| 1346 | +#include "gstrfuncsprivate.h" | ||
| 1347 | #include "gtype-private.h" | ||
| 1348 | #include "gbsearcharray.h" | ||
| 1349 | #include "gvaluecollector.h" | ||
| 1350 | @@ -1809,7 +1810,7 @@ g_signal_newv (const gchar *signal_name, | ||
| 1351 | node->single_va_closure_is_valid = FALSE; | ||
| 1352 | node->flags = signal_flags & G_SIGNAL_FLAGS_MASK; | ||
| 1353 | node->n_params = n_params; | ||
| 1354 | - node->param_types = g_memdup (param_types, sizeof (GType) * n_params); | ||
| 1355 | + node->param_types = g_memdup2 (param_types, sizeof (GType) * n_params); | ||
| 1356 | node->return_type = return_type; | ||
| 1357 | node->class_closure_bsa = NULL; | ||
| 1358 | if (accumulator) | ||
| 1359 | diff --git a/gobject/gtype.c b/gobject/gtype.c | ||
| 1360 | index b5ef2d11e..8d152dccc 100644 | ||
| 1361 | --- a/gobject/gtype.c | ||
| 1362 | +++ b/gobject/gtype.c | ||
| 1363 | @@ -33,6 +33,7 @@ | ||
| 1364 | |||
| 1365 | #include "glib-private.h" | ||
| 1366 | #include "gconstructor.h" | ||
| 1367 | +#include "gstrfuncsprivate.h" | ||
| 1368 | |||
| 1369 | #ifdef G_OS_WIN32 | ||
| 1370 | #include <windows.h> | ||
| 1371 | @@ -1470,7 +1471,7 @@ type_add_interface_Wm (TypeNode *node, | ||
| 1372 | iholder->next = iface_node_get_holders_L (iface); | ||
| 1373 | iface_node_set_holders_W (iface, iholder); | ||
| 1374 | iholder->instance_type = NODE_TYPE (node); | ||
| 1375 | - iholder->info = info ? g_memdup (info, sizeof (*info)) : NULL; | ||
| 1376 | + iholder->info = info ? g_memdup2 (info, sizeof (*info)) : NULL; | ||
| 1377 | iholder->plugin = plugin; | ||
| 1378 | |||
| 1379 | /* create an iface entry for this type */ | ||
| 1380 | @@ -1731,7 +1732,7 @@ type_iface_retrieve_holder_info_Wm (TypeNode *iface, | ||
| 1381 | INVALID_RECURSION ("g_type_plugin_*", iholder->plugin, NODE_NAME (iface)); | ||
| 1382 | |||
| 1383 | check_interface_info_I (iface, instance_type, &tmp_info); | ||
| 1384 | - iholder->info = g_memdup (&tmp_info, sizeof (tmp_info)); | ||
| 1385 | + iholder->info = g_memdup2 (&tmp_info, sizeof (tmp_info)); | ||
| 1386 | } | ||
| 1387 | |||
| 1388 | return iholder; /* we don't modify write lock upon returning NULL */ | ||
| 1389 | @@ -2016,10 +2017,10 @@ type_iface_vtable_base_init_Wm (TypeNode *iface, | ||
| 1390 | IFaceEntry *pentry = type_lookup_iface_entry_L (pnode, iface); | ||
| 1391 | |||
| 1392 | if (pentry) | ||
| 1393 | - vtable = g_memdup (pentry->vtable, iface->data->iface.vtable_size); | ||
| 1394 | + vtable = g_memdup2 (pentry->vtable, iface->data->iface.vtable_size); | ||
| 1395 | } | ||
| 1396 | if (!vtable) | ||
| 1397 | - vtable = g_memdup (iface->data->iface.dflt_vtable, iface->data->iface.vtable_size); | ||
| 1398 | + vtable = g_memdup2 (iface->data->iface.dflt_vtable, iface->data->iface.vtable_size); | ||
| 1399 | entry->vtable = vtable; | ||
| 1400 | vtable->g_type = NODE_TYPE (iface); | ||
| 1401 | vtable->g_instance_type = NODE_TYPE (node); | ||
| 1402 | diff --git a/gobject/gtypemodule.c b/gobject/gtypemodule.c | ||
| 1403 | index 4ecaf8c88..20911fafd 100644 | ||
| 1404 | --- a/gobject/gtypemodule.c | ||
| 1405 | +++ b/gobject/gtypemodule.c | ||
| 1406 | @@ -19,6 +19,7 @@ | ||
| 1407 | |||
| 1408 | #include <stdlib.h> | ||
| 1409 | |||
| 1410 | +#include "gstrfuncsprivate.h" | ||
| 1411 | #include "gtypeplugin.h" | ||
| 1412 | #include "gtypemodule.h" | ||
| 1413 | |||
| 1414 | @@ -436,7 +437,7 @@ g_type_module_register_type (GTypeModule *module, | ||
| 1415 | module_type_info->loaded = TRUE; | ||
| 1416 | module_type_info->info = *type_info; | ||
| 1417 | if (type_info->value_table) | ||
| 1418 | - module_type_info->info.value_table = g_memdup (type_info->value_table, | ||
| 1419 | + module_type_info->info.value_table = g_memdup2 (type_info->value_table, | ||
| 1420 | sizeof (GTypeValueTable)); | ||
| 1421 | |||
| 1422 | return module_type_info->type; | ||
| 1423 | diff --git a/gobject/tests/param.c b/gobject/tests/param.c | ||
| 1424 | index 93c3f4b94..0a77e51b7 100644 | ||
| 1425 | --- a/gobject/tests/param.c | ||
| 1426 | +++ b/gobject/tests/param.c | ||
| 1427 | @@ -2,6 +2,8 @@ | ||
| 1428 | #include <glib-object.h> | ||
| 1429 | #include <stdlib.h> | ||
| 1430 | |||
| 1431 | +#include "gstrfuncsprivate.h" | ||
| 1432 | + | ||
| 1433 | static void | ||
| 1434 | test_param_value (void) | ||
| 1435 | { | ||
| 1436 | @@ -874,7 +876,7 @@ main (int argc, char *argv[]) | ||
| 1437 | test_path = g_strdup_printf ("/param/implement/subprocess/%d-%d-%d-%d", | ||
| 1438 | data.change_this_flag, data.change_this_type, | ||
| 1439 | data.use_this_flag, data.use_this_type); | ||
| 1440 | - test_data = g_memdup (&data, sizeof (TestParamImplementData)); | ||
| 1441 | + test_data = g_memdup2 (&data, sizeof (TestParamImplementData)); | ||
| 1442 | g_test_add_data_func_full (test_path, test_data, test_param_implement_child, g_free); | ||
| 1443 | g_free (test_path); | ||
| 1444 | } | ||
diff --git a/meta/recipes-core/glib-2.0/glib-2.0_2.64.5.bb b/meta/recipes-core/glib-2.0/glib-2.0_2.64.5.bb index b9462bc945..ed7b649dc6 100644 --- a/meta/recipes-core/glib-2.0/glib-2.0_2.64.5.bb +++ b/meta/recipes-core/glib-2.0/glib-2.0_2.64.5.bb | |||
| @@ -18,6 +18,7 @@ SRC_URI = "${GNOME_MIRROR}/glib/${SHRT_VER}/glib-${PV}.tar.xz \ | |||
| 18 | file://0001-gio-tests-resources.c-comment-out-a-build-host-only-.patch \ | 18 | file://0001-gio-tests-resources.c-comment-out-a-build-host-only-.patch \ |
| 19 | file://tzdata-update.patch \ | 19 | file://tzdata-update.patch \ |
| 20 | file://CVE-2020-35457.patch \ | 20 | file://CVE-2020-35457.patch \ |
| 21 | file://CVE-2021-27219.patch \ | ||
| 21 | " | 22 | " |
| 22 | 23 | ||
| 23 | SRC_URI_append_class-native = " file://relocate-modules.patch" | 24 | SRC_URI_append_class-native = " file://relocate-modules.patch" |
