import glib2-2.56.4-10.el8_4
This commit is contained in:
		
							parent
							
								
									5b5d052d1d
								
							
						
					
					
						commit
						5934bb6e61
					
				
							
								
								
									
										849
									
								
								SOURCES/CVE-2021-27219.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										849
									
								
								SOURCES/CVE-2021-27219.patch
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,849 @@ | ||||
| From 7b46597384de916b4027ebaff662d06ff3ea2bc8 Mon Sep 17 00:00:00 2001 | ||||
| From: Philip Withnall <pwithnall@endlessos.org> | ||||
| Date: Thu, 4 Feb 2021 13:30:52 +0000 | ||||
| Subject: [PATCH 1/6] gstrfuncs: Add internal g_memdup2() function | ||||
| MIME-Version: 1.0 | ||||
| Content-Type: text/plain; charset=UTF-8 | ||||
| Content-Transfer-Encoding: 8bit | ||||
| 
 | ||||
| This will replace the existing `g_memdup()` function for use within | ||||
| GLib. It has an unavoidable security flaw of taking its `byte_size` | ||||
| argument as a `guint` rather than as a `gsize`. Most callers will | ||||
| expect it to be a `gsize`, and may pass in large values which could | ||||
| silently be truncated, resulting in an undersize allocation compared | ||||
| to what the caller expects. | ||||
| 
 | ||||
| This could lead to a classic buffer overflow vulnerability for many | ||||
| callers of `g_memdup()`. | ||||
| 
 | ||||
| `g_memdup2()`, in comparison, takes its `byte_size` as a `gsize`. | ||||
| 
 | ||||
| Spotted by Kevin Backhouse of GHSL. | ||||
| 
 | ||||
| In GLib 2.68, `g_memdup2()` will be a new public API. In this version | ||||
| for backport to older stable releases, it’s a new `static inline` API | ||||
| in a private header, so that use of `g_memdup()` within GLib can be | ||||
| fixed without adding a new API in a stable release series. | ||||
| 
 | ||||
| Signed-off-by: Philip Withnall <pwithnall@endlessos.org> | ||||
| Helps: CVE-2021-27219 | ||||
| Helps: GHSL-2021-045 | ||||
| Helps: #2319 | ||||
| (cherry picked from commit 5e5f75a77e399c638be66d74e5daa8caeb433e00) | ||||
| ---
 | ||||
|  docs/reference/glib/meson.build |  1 + | ||||
|  glib/gstrfuncsprivate.h         | 55 +++++++++++++++++++++++++++++++++ | ||||
|  glib/meson.build                |  1 + | ||||
|  glib/tests/strfuncs.c           | 23 ++++++++++++++ | ||||
|  4 files changed, 80 insertions(+) | ||||
|  create mode 100644 glib/gstrfuncsprivate.h | ||||
| 
 | ||||
| diff --git a/docs/reference/glib/meson.build b/docs/reference/glib/meson.build
 | ||||
| index f0f915e96..1a3680941 100644
 | ||||
| --- a/docs/reference/glib/meson.build
 | ||||
| +++ b/docs/reference/glib/meson.build
 | ||||
| @@ -20,6 +20,7 @@ if get_option('gtk_doc')
 | ||||
|      'gprintfint.h', | ||||
|      'gmirroringtable.h', | ||||
|      'gscripttable.h', | ||||
| +    'gstrfuncsprivate.h',
 | ||||
|      'glib-mirroring-tab', | ||||
|      'gnulib', | ||||
|      'pcre', | ||||
| diff --git a/glib/gstrfuncsprivate.h b/glib/gstrfuncsprivate.h
 | ||||
| new file mode 100644 | ||||
| index 000000000..85c88328a
 | ||||
| --- /dev/null
 | ||||
| +++ b/glib/gstrfuncsprivate.h
 | ||||
| @@ -0,0 +1,55 @@
 | ||||
| +/* GLIB - Library of useful routines for C programming
 | ||||
| + * Copyright (C) 1995-1997  Peter Mattis, Spencer Kimball and Josh MacDonald
 | ||||
| + *
 | ||||
| + * This library is free software; you can redistribute it and/or
 | ||||
| + * modify it under the terms of the GNU Lesser General Public
 | ||||
| + * License as published by the Free Software Foundation; either
 | ||||
| + * version 2.1 of the License, or (at your option) any later version.
 | ||||
| + *
 | ||||
| + * This library is distributed in the hope that it will be useful,
 | ||||
| + * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | ||||
| + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 | ||||
| + * Lesser General Public License for more details.
 | ||||
| + *
 | ||||
| + * You should have received a copy of the GNU Lesser General Public
 | ||||
| + * License along with this library; if not, see <http://www.gnu.org/licenses/>.
 | ||||
| + */
 | ||||
| +
 | ||||
| +#include <glib.h>
 | ||||
| +#include <string.h>
 | ||||
| +
 | ||||
| +/*
 | ||||
| + * 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.
 | ||||
| + *
 | ||||
| + * This static inline version is a backport of the new public API from
 | ||||
| + * GLib 2.68, kept internal to GLib for backport to older stable releases.
 | ||||
| + * See https://gitlab.gnome.org/GNOME/glib/-/issues/2319.
 | ||||
| + *
 | ||||
| + * Returns: (nullable): a pointer to the newly-allocated copy of the memory,
 | ||||
| + *    or %NULL if @mem is %NULL.
 | ||||
| + * Since: 2.68
 | ||||
| + */
 | ||||
| +static inline 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;
 | ||||
| +}
 | ||||
| diff --git a/glib/meson.build b/glib/meson.build
 | ||||
| index a2f9da81c..481fd06ff 100644
 | ||||
| --- a/glib/meson.build
 | ||||
| +++ b/glib/meson.build
 | ||||
| @@ -167,6 +167,7 @@ glib_sources = files(
 | ||||
|    'gslist.c', | ||||
|    'gstdio.c', | ||||
|    'gstrfuncs.c', | ||||
| +  'gstrfuncsprivate.h',
 | ||||
|    'gstring.c', | ||||
|    'gstringchunk.c', | ||||
|    'gtestutils.c', | ||||
| diff --git a/glib/tests/strfuncs.c b/glib/tests/strfuncs.c
 | ||||
| index 7e031bdb1..2aa252946 100644
 | ||||
| --- a/glib/tests/strfuncs.c
 | ||||
| +++ b/glib/tests/strfuncs.c
 | ||||
| @@ -32,6 +32,8 @@
 | ||||
|  #include <string.h> | ||||
|  #include "glib.h" | ||||
|   | ||||
| +#include "gstrfuncsprivate.h"
 | ||||
| +
 | ||||
|  #if defined (_MSC_VER) && (_MSC_VER <= 1800) | ||||
|  #define isnan(x) _isnan(x) | ||||
|   | ||||
| @@ -199,6 +201,26 @@ test_is_to_digit (void)
 | ||||
|    #undef TEST_DIGIT | ||||
|  } | ||||
|   | ||||
| +/* 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);
 | ||||
| +}
 | ||||
| +
 | ||||
|  static void | ||||
|  test_strdup (void) | ||||
|  { | ||||
| @@ -1726,6 +1748,7 @@ main (int   argc,
 | ||||
|    g_test_init (&argc, &argv, NULL); | ||||
|   | ||||
|    g_test_add_func ("/strfuncs/test-is-to-digit", test_is_to_digit); | ||||
| +  g_test_add_func ("/strfuncs/memdup2", test_memdup2);
 | ||||
|    g_test_add_func ("/strfuncs/strdup", test_strdup); | ||||
|    g_test_add_func ("/strfuncs/strndup", test_strndup); | ||||
|    g_test_add_func ("/strfuncs/strdup-printf", test_strdup_printf); | ||||
| -- 
 | ||||
| 2.31.1 | ||||
| 
 | ||||
| From d6aab169954d9e6e77753dee68e1b3f5932f6dee Mon Sep 17 00:00:00 2001 | ||||
| From: Philip Withnall <pwithnall@endlessos.org> | ||||
| Date: Thu, 4 Feb 2021 13:41:21 +0000 | ||||
| Subject: [PATCH 2/6] glib: Use g_memdup2() instead of g_memdup() in obvious | ||||
|  places | ||||
| MIME-Version: 1.0 | ||||
| Content-Type: text/plain; charset=UTF-8 | ||||
| Content-Transfer-Encoding: 8bit | ||||
| 
 | ||||
| Convert all the call sites which use `g_memdup()`’s length argument | ||||
| trivially (for example, by passing a `sizeof()` or an existing `gsize` | ||||
| variable), so that they use `g_memdup2()` instead. | ||||
| 
 | ||||
| In almost all of these cases the use of `g_memdup()` would not have | ||||
| caused problems, but it will soon be deprecated, so best port away from | ||||
| it | ||||
| 
 | ||||
| In particular, this fixes an overflow within `g_bytes_new()`, identified | ||||
| as GHSL-2021-045 (aka CVE-2021-27219) by GHSL team member Kevin Backhouse. | ||||
| 
 | ||||
| Adapted for GLib 2.58 by Simon McVittie. | ||||
| 
 | ||||
| Signed-off-by: Philip Withnall <pwithnall@endlessos.org> | ||||
| Fixes: CVE-2021-27219 | ||||
| Fixes: GHSL-2021-045 | ||||
| Helps: #2319 | ||||
| (cherry picked from commit 0736b7c1e7cf4232c5d7eb2b0fbfe9be81bd3baa) | ||||
| [Backport to 2.58: Omit changes to ghash.c, will be a separate commit] | ||||
| [Backport to 2.58: Omit changes to giochannel.c, not needed in this branch] | ||||
| [Backport to 2.58: Omit changes to uri test, not needed in this branch] | ||||
| Signed-off-by: Simon McVittie <smcv@collabora.com> | ||||
| ---
 | ||||
|  glib/gbytes.c               | 6 ++++-- | ||||
|  glib/gdir.c                 | 3 ++- | ||||
|  glib/gslice.c               | 3 ++- | ||||
|  glib/gtestutils.c           | 3 ++- | ||||
|  glib/gvariant.c             | 7 ++++--- | ||||
|  glib/gvarianttype.c         | 3 ++- | ||||
|  glib/tests/array-test.c     | 2 +- | ||||
|  glib/tests/option-context.c | 6 ++++-- | ||||
|  8 files changed, 21 insertions(+), 12 deletions(-) | ||||
| 
 | ||||
| diff --git a/glib/gbytes.c b/glib/gbytes.c
 | ||||
| index 3b14a51cd..5141170d7 100644
 | ||||
| --- a/glib/gbytes.c
 | ||||
| +++ b/glib/gbytes.c
 | ||||
| @@ -33,6 +33,8 @@
 | ||||
|   | ||||
|  #include <string.h> | ||||
|   | ||||
| +#include "gstrfuncsprivate.h"
 | ||||
| +
 | ||||
|  /** | ||||
|   * GBytes: | ||||
|   * | ||||
| @@ -94,7 +96,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);
 | ||||
|  } | ||||
|   | ||||
|  /** | ||||
| @@ -490,7 +492,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 cb4ad0b2f..9d955d57f 100644
 | ||||
| --- a/glib/gdir.c
 | ||||
| +++ b/glib/gdir.c
 | ||||
| @@ -37,6 +37,7 @@
 | ||||
|  #include "gconvert.h" | ||||
|  #include "gfileutils.h" | ||||
|  #include "gstrfuncs.h" | ||||
| +#include "gstrfuncsprivate.h"
 | ||||
|  #include "gtestutils.h" | ||||
|  #include "glibintl.h" | ||||
|   | ||||
| @@ -113,7 +114,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/gslice.c b/glib/gslice.c
 | ||||
| index 454c8a602..8e2359515 100644
 | ||||
| --- a/glib/gslice.c
 | ||||
| +++ b/glib/gslice.c
 | ||||
| @@ -45,6 +45,7 @@
 | ||||
|  #include "gmain.h" | ||||
|  #include "gmem.h"               /* gslice.h */ | ||||
|  #include "gstrfuncs.h" | ||||
| +#include "gstrfuncsprivate.h"
 | ||||
|  #include "gutils.h" | ||||
|  #include "gtrashstack.h" | ||||
|  #include "gtestutils.h" | ||||
| @@ -352,7 +353,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/gtestutils.c b/glib/gtestutils.c
 | ||||
| index 0447dcda5..14e071fce 100644
 | ||||
| --- a/glib/gtestutils.c
 | ||||
| +++ b/glib/gtestutils.c
 | ||||
| @@ -49,6 +49,7 @@
 | ||||
|  #include "gpattern.h" | ||||
|  #include "grand.h" | ||||
|  #include "gstrfuncs.h" | ||||
| +#include "gstrfuncsprivate.h"
 | ||||
|  #include "gtimer.h" | ||||
|  #include "gslice.h" | ||||
|  #include "gspawn.h" | ||||
| @@ -3397,7 +3398,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 8be9ce798..45a1a73dc 100644
 | ||||
| --- a/glib/gvariant.c
 | ||||
| +++ b/glib/gvariant.c
 | ||||
| @@ -33,6 +33,7 @@
 | ||||
|   | ||||
|  #include <string.h> | ||||
|   | ||||
| +#include "gstrfuncsprivate.h"
 | ||||
|   | ||||
|  /** | ||||
|   * SECTION:gvariant | ||||
| @@ -720,7 +721,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)); | ||||
|  } | ||||
|   | ||||
| @@ -1224,7 +1225,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); | ||||
| @@ -1901,7 +1902,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 c8433e65a..dbbf7d2d1 100644
 | ||||
| --- a/glib/gvarianttype.c
 | ||||
| +++ b/glib/gvarianttype.c
 | ||||
| @@ -28,6 +28,7 @@
 | ||||
|   | ||||
|  #include <string.h> | ||||
|   | ||||
| +#include "gstrfuncsprivate.h"
 | ||||
|   | ||||
|  /** | ||||
|   * SECTION:gvarianttype | ||||
| @@ -1174,7 +1175,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);
 | ||||
|  } | ||||
|   | ||||
|  /** | ||||
| -- 
 | ||||
| 2.31.1 | ||||
| 
 | ||||
| From 7e2c2a07508a97b9d75e402afe4749b02a34dd8b Mon Sep 17 00:00:00 2001 | ||||
| From: Simon McVittie <smcv@collabora.com> | ||||
| Date: Thu, 18 Mar 2021 10:31:00 +0000 | ||||
| Subject: [PATCH 3/6] ghash: Use g_memdup2() instead of g_memdup() | ||||
| 
 | ||||
| Backport of part of commit 0736b7c1e7cf4232c5d7eb2b0fbfe9be81bd3baa | ||||
| to the simpler structure of the GHashTable code in glib-2-58. | ||||
| 
 | ||||
| Helps: #2319 | ||||
| Signed-off-by: Simon McVittie <smcv@collabora.com> | ||||
| ---
 | ||||
|  glib/ghash.c | 3 ++- | ||||
|  1 file changed, 2 insertions(+), 1 deletion(-) | ||||
| 
 | ||||
| diff --git a/glib/ghash.c b/glib/ghash.c
 | ||||
| index 6bb04a50d..608d136f4 100644
 | ||||
| --- a/glib/ghash.c
 | ||||
| +++ b/glib/ghash.c
 | ||||
| @@ -34,6 +34,7 @@
 | ||||
|   | ||||
|  #include "glib-private.h" | ||||
|  #include "gstrfuncs.h" | ||||
| +#include "gstrfuncsprivate.h"
 | ||||
|  #include "gatomic.h" | ||||
|  #include "gtestutils.h" | ||||
|  #include "gslice.h" | ||||
| @@ -967,7 +968,7 @@ g_hash_table_insert_node (GHashTable *hash_table,
 | ||||
|     * split the table. | ||||
|     */ | ||||
|    if (G_UNLIKELY (hash_table->keys == hash_table->values && hash_table->keys[node_index] != new_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);
 | ||||
|   | ||||
|    /* Step 3: Actually do the write */ | ||||
|    hash_table->values[node_index] = new_value; | ||||
| -- 
 | ||||
| 2.31.1 | ||||
| 
 | ||||
| From 9e0c87610dccd1b0eaca28a3baa521ea6a24f46b Mon Sep 17 00:00:00 2001 | ||||
| From: Philip Withnall <pwithnall@endlessos.org> | ||||
| Date: Thu, 4 Feb 2021 13:39:25 +0000 | ||||
| Subject: [PATCH 4/6] gobject: Use g_memdup2() instead of g_memdup() in obvious | ||||
|  places | ||||
| MIME-Version: 1.0 | ||||
| Content-Type: text/plain; charset=UTF-8 | ||||
| Content-Transfer-Encoding: 8bit | ||||
| 
 | ||||
| Convert all the call sites which use `g_memdup()`’s length argument | ||||
| trivially (for example, by passing a `sizeof()`), so that they use | ||||
| `g_memdup2()` instead. | ||||
| 
 | ||||
| In almost all of these cases the use of `g_memdup()` would not have | ||||
| caused problems, but it will soon be deprecated, so best port away from | ||||
| it. | ||||
| 
 | ||||
| Signed-off-by: Philip Withnall <pwithnall@endlessos.org> | ||||
| Helps: #2319 | ||||
| (cherry picked from commit 6110caea45b235420b98cd41d845cc92238f6781) | ||||
| ---
 | ||||
|  gobject/gsignal.c     | 3 ++- | ||||
|  gobject/gtype.c       | 9 +++++---- | ||||
|  gobject/gtypemodule.c | 3 ++- | ||||
|  gobject/tests/param.c | 4 +++- | ||||
|  4 files changed, 12 insertions(+), 7 deletions(-) | ||||
| 
 | ||||
| diff --git a/gobject/gsignal.c b/gobject/gsignal.c
 | ||||
| index b22dfcca8..92555eb60 100644
 | ||||
| --- a/gobject/gsignal.c
 | ||||
| +++ b/gobject/gsignal.c
 | ||||
| @@ -28,6 +28,7 @@
 | ||||
|  #include <signal.h> | ||||
|   | ||||
|  #include "gsignal.h" | ||||
| +#include "gstrfuncsprivate.h"
 | ||||
|  #include "gtype-private.h" | ||||
|  #include "gbsearcharray.h" | ||||
|  #include "gvaluecollector.h" | ||||
| @@ -1724,7 +1725,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 275a8b60b..9e663ce52 100644
 | ||||
| --- a/gobject/gtype.c
 | ||||
| +++ b/gobject/gtype.c
 | ||||
| @@ -33,6 +33,7 @@
 | ||||
|   | ||||
|  #include "glib-private.h" | ||||
|  #include "gconstructor.h" | ||||
| +#include "gstrfuncsprivate.h"
 | ||||
|   | ||||
|  #ifdef G_OS_WIN32 | ||||
|  #include <windows.h> | ||||
| @@ -1471,7 +1472,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 */ | ||||
| @@ -1732,7 +1733,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 */ | ||||
| @@ -2013,10 +2014,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 c67f789b1..cf877bc0b 100644
 | ||||
| --- a/gobject/gtypemodule.c
 | ||||
| +++ b/gobject/gtypemodule.c
 | ||||
| @@ -19,6 +19,7 @@
 | ||||
|   | ||||
|  #include <stdlib.h> | ||||
|   | ||||
| +#include "gstrfuncsprivate.h"
 | ||||
|  #include "gtypeplugin.h" | ||||
|  #include "gtypemodule.h" | ||||
|   | ||||
| @@ -436,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 758289bf8..971cff162 100644
 | ||||
| --- a/gobject/tests/param.c
 | ||||
| +++ b/gobject/tests/param.c
 | ||||
| @@ -2,6 +2,8 @@
 | ||||
|  #include <glib-object.h> | ||||
|  #include <stdlib.h> | ||||
|   | ||||
| +#include "gstrfuncsprivate.h"
 | ||||
| +
 | ||||
|  static void | ||||
|  test_param_value (void) | ||||
|  { | ||||
| @@ -851,7 +853,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); | ||||
|            } | ||||
| -- 
 | ||||
| 2.31.1 | ||||
| 
 | ||||
| From d3f7a79540fc1e85eb82c2987e9f7e2dbd93ff74 Mon Sep 17 00:00:00 2001 | ||||
| From: Philip Withnall <pwithnall@endlessos.org> | ||||
| Date: Thu, 4 Feb 2021 13:37:56 +0000 | ||||
| Subject: [PATCH 5/6] gio: Use g_memdup2() instead of g_memdup() in obvious | ||||
|  places | ||||
| MIME-Version: 1.0 | ||||
| Content-Type: text/plain; charset=UTF-8 | ||||
| Content-Transfer-Encoding: 8bit | ||||
| 
 | ||||
| Convert all the call sites which use `g_memdup()`’s length argument | ||||
| trivially (for example, by passing a `sizeof()`), so that they use | ||||
| `g_memdup2()` instead. | ||||
| 
 | ||||
| In almost all of these cases the use of `g_memdup()` would not have | ||||
| caused problems, but it will soon be deprecated, so best port away from | ||||
| it. | ||||
| 
 | ||||
| Signed-off-by: Philip Withnall <pwithnall@endlessos.org> | ||||
| Helps: #2319 | ||||
| (cherry picked from commit be8834340a2d928ece82025463ae23dee2c333d0) | ||||
| ---
 | ||||
|  gio/gdbusconnection.c                 | 5 +++-- | ||||
|  gio/gdbusinterfaceskeleton.c          | 3 ++- | ||||
|  gio/gfile.c                           | 7 ++++--- | ||||
|  gio/gsettingsschema.c                 | 5 +++-- | ||||
|  gio/gwin32registrykey.c               | 8 +++++--- | ||||
|  gio/tests/async-close-output-stream.c | 6 ++++-- | ||||
|  gio/tests/gdbus-export.c              | 5 +++-- | ||||
|  gio/win32/gwinhttpfile.c              | 9 +++++---- | ||||
|  8 files changed, 29 insertions(+), 19 deletions(-) | ||||
| 
 | ||||
| diff --git a/gio/gdbusconnection.c b/gio/gdbusconnection.c
 | ||||
| index 6f7e5fefc..117c8df35 100644
 | ||||
| --- a/gio/gdbusconnection.c
 | ||||
| +++ b/gio/gdbusconnection.c
 | ||||
| @@ -119,6 +119,7 @@
 | ||||
|  #include "gasyncinitable.h" | ||||
|  #include "giostream.h" | ||||
|  #include "gasyncresult.h" | ||||
| +#include "gstrfuncsprivate.h"
 | ||||
|  #include "gtask.h" | ||||
|   | ||||
|  #ifdef G_OS_UNIX | ||||
| @@ -3970,7 +3971,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 | ||||
| @@ -3987,7 +3988,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 96bd520aa..672604c49 100644
 | ||||
| --- a/gio/gdbusinterfaceskeleton.c
 | ||||
| +++ b/gio/gdbusinterfaceskeleton.c
 | ||||
| @@ -27,6 +27,7 @@
 | ||||
|  #include "gdbusprivate.h" | ||||
|  #include "gdbusmethodinvocation.h" | ||||
|  #include "gdbusconnection.h" | ||||
| +#include "gstrfuncsprivate.h"
 | ||||
|  #include "gtask.h" | ||||
|  #include "gioerror.h" | ||||
|   | ||||
| @@ -697,7 +698,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 ff313ebf8..29ebaaa62 100644
 | ||||
| --- a/gio/gfile.c
 | ||||
| +++ b/gio/gfile.c
 | ||||
| @@ -60,6 +60,7 @@
 | ||||
|  #include "gasyncresult.h" | ||||
|  #include "gioerror.h" | ||||
|  #include "glibintl.h" | ||||
| +#include "gstrfuncsprivate.h"
 | ||||
|   | ||||
|   | ||||
|  /** | ||||
| @@ -7734,7 +7735,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); | ||||
|  } | ||||
|   | ||||
| @@ -7752,7 +7753,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); | ||||
|  } | ||||
| @@ -7776,7 +7777,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/gsettingsschema.c b/gio/gsettingsschema.c
 | ||||
| index 17b7e3b01..499944395 100644
 | ||||
| --- a/gio/gsettingsschema.c
 | ||||
| +++ b/gio/gsettingsschema.c
 | ||||
| @@ -20,6 +20,7 @@
 | ||||
|   | ||||
|  #include "gsettingsschema-internal.h" | ||||
|  #include "gsettings.h" | ||||
| +#include "gstrfuncsprivate.h"
 | ||||
|   | ||||
|  #include "gvdb/gvdb-reader.h" | ||||
|  #include "strinfo.c" | ||||
| @@ -1054,9 +1055,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/gwin32registrykey.c b/gio/gwin32registrykey.c
 | ||||
| index c19fede4e..619fd48af 100644
 | ||||
| --- a/gio/gwin32registrykey.c
 | ||||
| +++ b/gio/gwin32registrykey.c
 | ||||
| @@ -28,6 +28,8 @@
 | ||||
|  #include <ntstatus.h> | ||||
|  #include <winternl.h> | ||||
|   | ||||
| +#include "gstrfuncsprivate.h"
 | ||||
| +
 | ||||
|  #ifndef _WDMDDK_ | ||||
|  typedef enum _KEY_INFORMATION_CLASS { | ||||
|    KeyBasicInformation, | ||||
| @@ -247,7 +249,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 +270,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..d3f97a119 100644
 | ||||
| --- a/gio/tests/async-close-output-stream.c
 | ||||
| +++ b/gio/tests/async-close-output-stream.c
 | ||||
| @@ -24,6 +24,8 @@
 | ||||
|  #include <stdlib.h> | ||||
|  #include <string.h> | ||||
|   | ||||
| +#include "gstrfuncsprivate.h"
 | ||||
| +
 | ||||
|  #define DATA_TO_WRITE "Hello world\n" | ||||
|   | ||||
|  typedef struct | ||||
| @@ -147,9 +149,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 ef0dddeee..a3c842360 100644
 | ||||
| --- a/gio/tests/gdbus-export.c
 | ||||
| +++ b/gio/tests/gdbus-export.c
 | ||||
| @@ -23,6 +23,7 @@
 | ||||
|  #include <string.h> | ||||
|   | ||||
|  #include "gdbus-tests.h" | ||||
| +#include "gstrfuncsprivate.h"
 | ||||
|   | ||||
|  /* all tests rely on a shared mainloop */ | ||||
|  static GMainLoop *loop = NULL; | ||||
| @@ -652,7 +653,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 * | ||||
| @@ -708,7 +709,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 d5df16d91..f424d21cc 100644
 | ||||
| --- a/gio/win32/gwinhttpfile.c
 | ||||
| +++ b/gio/win32/gwinhttpfile.c
 | ||||
| @@ -29,6 +29,7 @@
 | ||||
|  #include "gio/gfile.h" | ||||
|  #include "gio/gfileattribute.h" | ||||
|  #include "gio/gfileinfo.h" | ||||
| +#include "gstrfuncsprivate.h"
 | ||||
|  #include "gwinhttpfile.h" | ||||
|  #include "gwinhttpfileinputstream.h" | ||||
|  #include "gwinhttpfileoutputstream.h" | ||||
| @@ -393,10 +394,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, (winhttp_file->url.dwSchemeLength+1)*2);
 | ||||
| +  child->url.lpszHostName = g_memdup2 (winhttp_file->url.lpszHostName, (winhttp_file->url.dwHostNameLength+1)*2);
 | ||||
| +  child->url.lpszUserName = g_memdup2 (winhttp_file->url.lpszUserName, (winhttp_file->url.dwUserNameLength+1)*2);
 | ||||
| +  child->url.lpszPassword = g_memdup2 (winhttp_file->url.lpszPassword, (winhttp_file->url.dwPasswordLength+1)*2);
 | ||||
|    child->url.lpszUrlPath = wnew_path; | ||||
|    child->url.dwUrlPathLength = wcslen (wnew_path); | ||||
|    child->url.lpszExtraInfo = NULL; | ||||
| -- 
 | ||||
| 2.31.1 | ||||
| 
 | ||||
| From 661f5edc901219a1a99bb51f171be13063878bd6 Mon Sep 17 00:00:00 2001 | ||||
| From: Michael Catanzaro <mcatanzaro@redhat.com> | ||||
| Date: Thu, 20 May 2021 15:58:53 -0500 | ||||
| Subject: [PATCH 6/6] gdatainputstream: replace easy use of g_memdup() | ||||
| 
 | ||||
| This code is passing a gsize, so might as well switch this to g_memdup2(). | ||||
| 
 | ||||
| This is the only use of g_memdup() in GLib 2.56 that is not part of GLib | ||||
| 2.58. All other uses analyzed in glib!2000. | ||||
| ---
 | ||||
|  gio/gdatainputstream.c | 3 ++- | ||||
|  1 file changed, 2 insertions(+), 1 deletion(-) | ||||
| 
 | ||||
| diff --git a/gio/gdatainputstream.c b/gio/gdatainputstream.c
 | ||||
| index 9f207b158..ebef7c797 100644
 | ||||
| --- a/gio/gdatainputstream.c
 | ||||
| +++ b/gio/gdatainputstream.c
 | ||||
| @@ -27,6 +27,7 @@
 | ||||
|  #include "gioenumtypes.h" | ||||
|  #include "gioerror.h" | ||||
|  #include "glibintl.h" | ||||
| +#include "gstrfuncsprivate.h"
 | ||||
|   | ||||
|  #include <string.h> | ||||
|   | ||||
| @@ -1082,7 +1083,7 @@ g_data_input_stream_read_async (GDataInputStream    *stream,
 | ||||
|    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 = g_memdup2 (stop_chars, stop_chars_len);
 | ||||
|    data->stop_chars_len = stop_chars_len; | ||||
|    data->last_saw_cr = FALSE; | ||||
|   | ||||
| -- 
 | ||||
| 2.31.1 | ||||
							
								
								
									
										386
									
								
								SOURCES/gmain-corruption.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										386
									
								
								SOURCES/gmain-corruption.patch
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,386 @@ | ||||
| From 2bad3cb3bf8f0cc3f45057061f9a538ecf7742b6 Mon Sep 17 00:00:00 2001 | ||||
| From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= <sebastian@centricular.com> | ||||
| Date: Thu, 14 Feb 2019 17:46:33 +0200 | ||||
| Subject: [PATCH 1/5] Use atomic reference counting for GSource | ||||
| 
 | ||||
| If attached to a context already it would use a mutex instead but at | ||||
| least before that the reference counting is not thread-safe currently. | ||||
| ---
 | ||||
|  glib/gmain.c | 50 +++++++++++++++----------------------------------- | ||||
|  1 file changed, 15 insertions(+), 35 deletions(-) | ||||
| 
 | ||||
| diff --git a/glib/gmain.c b/glib/gmain.c
 | ||||
| index 26e68823d..5b91c3117 100644
 | ||||
| --- a/glib/gmain.c
 | ||||
| +++ b/glib/gmain.c
 | ||||
| @@ -374,15 +374,6 @@ typedef struct _GSourceIter
 | ||||
|  #define SOURCE_DESTROYED(source) (((source)->flags & G_HOOK_FLAG_ACTIVE) == 0) | ||||
|  #define SOURCE_BLOCKED(source) (((source)->flags & G_SOURCE_BLOCKED) != 0) | ||||
|   | ||||
| -#define SOURCE_UNREF(source, context)                       \
 | ||||
| -   G_STMT_START {                                           \
 | ||||
| -    if ((source)->ref_count > 1)                            \
 | ||||
| -      (source)->ref_count--;                                \
 | ||||
| -    else                                                    \
 | ||||
| -      g_source_unref_internal ((source), (context), TRUE);  \
 | ||||
| -   } G_STMT_END
 | ||||
| -
 | ||||
| -
 | ||||
|  /* Forward declarations */ | ||||
|   | ||||
|  static void g_source_unref_internal             (GSource      *source, | ||||
| @@ -977,10 +968,10 @@ g_source_iter_next (GSourceIter *iter, GSource **source)
 | ||||
|     */ | ||||
|   | ||||
|    if (iter->source && iter->may_modify) | ||||
| -    SOURCE_UNREF (iter->source, iter->context);
 | ||||
| +    g_source_unref_internal (iter->source, iter->context, TRUE);
 | ||||
|    iter->source = next_source; | ||||
|    if (iter->source && iter->may_modify) | ||||
| -    iter->source->ref_count++;
 | ||||
| +    g_source_ref (iter->source);
 | ||||
|   | ||||
|    *source = iter->source; | ||||
|    return *source != NULL; | ||||
| @@ -994,7 +985,7 @@ g_source_iter_clear (GSourceIter *iter)
 | ||||
|  { | ||||
|    if (iter->source && iter->may_modify) | ||||
|      { | ||||
| -      SOURCE_UNREF (iter->source, iter->context);
 | ||||
| +      g_source_unref_internal (iter->source, iter->context, TRUE);
 | ||||
|        iter->source = NULL; | ||||
|      } | ||||
|  } | ||||
| @@ -1135,7 +1126,7 @@ g_source_attach_unlocked (GSource      *source,
 | ||||
|   | ||||
|    source->context = context; | ||||
|    source->source_id = id; | ||||
| -  source->ref_count++;
 | ||||
| +  g_source_ref (source);
 | ||||
|   | ||||
|    g_hash_table_insert (context->sources, GUINT_TO_POINTER (id), source); | ||||
|   | ||||
| @@ -1675,7 +1666,7 @@ g_source_set_funcs (GSource     *source,
 | ||||
|  { | ||||
|    g_return_if_fail (source != NULL); | ||||
|    g_return_if_fail (source->context == NULL); | ||||
| -  g_return_if_fail (source->ref_count > 0);
 | ||||
| +  g_return_if_fail (g_atomic_int_get (&source->ref_count) > 0);
 | ||||
|    g_return_if_fail (funcs != NULL); | ||||
|   | ||||
|    source->source_funcs = funcs; | ||||
| @@ -2050,19 +2041,9 @@ g_source_set_name_by_id (guint           tag,
 | ||||
|  GSource * | ||||
|  g_source_ref (GSource *source) | ||||
|  { | ||||
| -  GMainContext *context;
 | ||||
| -  
 | ||||
|    g_return_val_if_fail (source != NULL, NULL); | ||||
|   | ||||
| -  context = source->context;
 | ||||
| -
 | ||||
| -  if (context)
 | ||||
| -    LOCK_CONTEXT (context);
 | ||||
| -
 | ||||
| -  source->ref_count++;
 | ||||
| -
 | ||||
| -  if (context)
 | ||||
| -    UNLOCK_CONTEXT (context);
 | ||||
| +  g_atomic_int_inc (&source->ref_count);
 | ||||
|   | ||||
|    return source; | ||||
|  } | ||||
| @@ -2078,12 +2059,11 @@ g_source_unref_internal (GSource      *source,
 | ||||
|    GSourceCallbackFuncs *old_cb_funcs = NULL; | ||||
|   | ||||
|    g_return_if_fail (source != NULL); | ||||
| -  
 | ||||
| +
 | ||||
|    if (!have_lock && context) | ||||
|      LOCK_CONTEXT (context); | ||||
|   | ||||
| -  source->ref_count--;
 | ||||
| -  if (source->ref_count == 0)
 | ||||
| +  if (g_atomic_int_dec_and_test (&source->ref_count))
 | ||||
|      { | ||||
|        TRACE (GLIB_SOURCE_BEFORE_FREE (source, context, | ||||
|                                        source->source_funcs->finalize)); | ||||
| @@ -2107,20 +2087,20 @@ g_source_unref_internal (GSource      *source,
 | ||||
|  	{ | ||||
|            /* Temporarily increase the ref count again so that GSource methods | ||||
|             * can be called from finalize(). */ | ||||
| -          source->ref_count++;
 | ||||
| +          g_atomic_int_inc (&source->ref_count);
 | ||||
|  	  if (context) | ||||
|  	    UNLOCK_CONTEXT (context); | ||||
|  	  source->source_funcs->finalize (source); | ||||
|  	  if (context) | ||||
|  	    LOCK_CONTEXT (context); | ||||
| -          source->ref_count--;
 | ||||
| +          g_atomic_int_add (&source->ref_count, -1);
 | ||||
|  	} | ||||
|   | ||||
|        if (old_cb_funcs) | ||||
|          { | ||||
|            /* Temporarily increase the ref count again so that GSource methods | ||||
|             * can be called from callback_funcs.unref(). */ | ||||
| -          source->ref_count++;
 | ||||
| +          g_atomic_int_inc (&source->ref_count);
 | ||||
|            if (context) | ||||
|              UNLOCK_CONTEXT (context); | ||||
|   | ||||
| @@ -2128,7 +2108,7 @@ g_source_unref_internal (GSource      *source,
 | ||||
|   | ||||
|            if (context) | ||||
|              LOCK_CONTEXT (context); | ||||
| -          source->ref_count--;
 | ||||
| +          g_atomic_int_add (&source->ref_count, -1);
 | ||||
|          } | ||||
|   | ||||
|        g_free (source->name); | ||||
| @@ -3201,7 +3181,7 @@ g_main_dispatch (GMainContext *context)
 | ||||
|  	    } | ||||
|  	} | ||||
|         | ||||
| -      SOURCE_UNREF (source, context);
 | ||||
| +      g_source_unref_internal (source, context, TRUE);
 | ||||
|      } | ||||
|   | ||||
|    g_ptr_array_set_size (context->pending_dispatches, 0); | ||||
| @@ -3440,7 +3420,7 @@ g_main_context_prepare (GMainContext *context,
 | ||||
|    for (i = 0; i < context->pending_dispatches->len; i++) | ||||
|      { | ||||
|        if (context->pending_dispatches->pdata[i]) | ||||
| -	SOURCE_UNREF ((GSource *)context->pending_dispatches->pdata[i], context);
 | ||||
| +        g_source_unref_internal ((GSource *)context->pending_dispatches->pdata[i], context, TRUE);
 | ||||
|      } | ||||
|    g_ptr_array_set_size (context->pending_dispatches, 0); | ||||
|     | ||||
| @@ -3788,7 +3768,7 @@ g_main_context_check (GMainContext *context,
 | ||||
|   | ||||
|        if (source->flags & G_SOURCE_READY) | ||||
|  	{ | ||||
| -	  source->ref_count++;
 | ||||
| +          g_source_ref (source);
 | ||||
|  	  g_ptr_array_add (context->pending_dispatches, source); | ||||
|   | ||||
|  	  n_ready++; | ||||
| -- 
 | ||||
| 2.31.1 | ||||
| 
 | ||||
| From 323d0c7658a9a44efc327840c0667044a4b98f89 Mon Sep 17 00:00:00 2001 | ||||
| From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= <sebastian@centricular.com> | ||||
| Date: Mon, 3 Feb 2020 15:38:28 +0200 | ||||
| Subject: [PATCH 2/5] GMainContext - Fix GSource iterator if iteration can | ||||
|  modify the list | ||||
| 
 | ||||
| We first have to ref the next source and then unref the previous one. | ||||
| This might be the last reference to the previous source, and freeing the | ||||
| previous source might unref and free the next one which would then leave | ||||
| use with a dangling pointer here. | ||||
| 
 | ||||
| Fixes https://gitlab.gnome.org/GNOME/glib/issues/2031 | ||||
| ---
 | ||||
|  glib/gmain.c | 8 ++++++-- | ||||
|  1 file changed, 6 insertions(+), 2 deletions(-) | ||||
| 
 | ||||
| diff --git a/glib/gmain.c b/glib/gmain.c
 | ||||
| index 5b91c3117..a3ea1d36c 100644
 | ||||
| --- a/glib/gmain.c
 | ||||
| +++ b/glib/gmain.c
 | ||||
| @@ -965,13 +965,17 @@ g_source_iter_next (GSourceIter *iter, GSource **source)
 | ||||
|     * GSourceList to be removed from source_lists (if iter->source is | ||||
|     * the only source in its list, and it is destroyed), so we have to | ||||
|     * keep it reffed until after we advance iter->current_list, above. | ||||
| +   *
 | ||||
| +   * Also we first have to ref the next source before unreffing the
 | ||||
| +   * previous one as unreffing the previous source can potentially
 | ||||
| +   * free the next one.
 | ||||
|     */ | ||||
| +  if (next_source && iter->may_modify)
 | ||||
| +    g_source_ref (next_source);
 | ||||
|   | ||||
|    if (iter->source && iter->may_modify) | ||||
|      g_source_unref_internal (iter->source, iter->context, TRUE); | ||||
|    iter->source = next_source; | ||||
| -  if (iter->source && iter->may_modify)
 | ||||
| -    g_source_ref (iter->source);
 | ||||
|   | ||||
|    *source = iter->source; | ||||
|    return *source != NULL; | ||||
| -- 
 | ||||
| 2.31.1 | ||||
| 
 | ||||
| From fc051ec83d8894dd754bf364562ba9be9ff999fc Mon Sep 17 00:00:00 2001 | ||||
| From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= <sebastian@centricular.com> | ||||
| Date: Mon, 3 Feb 2020 15:35:51 +0200 | ||||
| Subject: [PATCH 3/5] GMainContext - Fix memory leaks and memory corruption | ||||
|  when freeing sources while freeing a context | ||||
| 
 | ||||
| Instead of destroying sources directly while freeing the context, and | ||||
| potentially freeing them if this was the last reference to them, collect | ||||
| new references of all sources in a separate list before and at the same | ||||
| time invalidate their context so that they can't access it anymore. Only | ||||
| once all sources have their context invalidated, destroy them while | ||||
| still keeping a reference to them. Once all sources are destroyed we get | ||||
| rid of the additional references and free them if nothing else keeps a | ||||
| reference to them anymore. | ||||
| 
 | ||||
| This fixes a regression introduced by 26056558be in 2012. | ||||
| 
 | ||||
| The previous code that invalidated the context of each source and then | ||||
| destroyed it before going to the next source without keeping an | ||||
| additional reference caused memory leaks or memory corruption depending | ||||
| on the order of the sources in the sources lists. | ||||
| 
 | ||||
| If a source was destroyed it might happen that this was the last | ||||
| reference to this source, and it would then be freed. This would cause | ||||
| the finalize function to be called, which might destroy and unref | ||||
| another source and potentially free it. This other source would then | ||||
| either | ||||
| - go through the normal free logic and change the intern linked list
 | ||||
|   between the sources, while other sources that are unreffed as part of | ||||
|   the main context freeing would not. As such the list would be in an | ||||
|   inconsistent state and we might dereference freed memory. | ||||
| - go through the normal destroy and free logic but because the context
 | ||||
|   pointer was already invalidated it would simply mark the source as | ||||
|   destroyed without actually removing it from the context. This would | ||||
|   then cause a memory leak because the reference owned by the context is | ||||
|   not freed. | ||||
| 
 | ||||
| Fixes https://github.com/gtk-rs/glib/issues/583 while still keeping | ||||
| https://bugzilla.gnome.org/show_bug.cgi?id=661767 fixes. | ||||
| ---
 | ||||
|  glib/gmain.c | 35 ++++++++++++++++++++++++++++++++++- | ||||
|  1 file changed, 34 insertions(+), 1 deletion(-) | ||||
| 
 | ||||
| diff --git a/glib/gmain.c b/glib/gmain.c
 | ||||
| index a3ea1d36c..1c249ad02 100644
 | ||||
| --- a/glib/gmain.c
 | ||||
| +++ b/glib/gmain.c
 | ||||
| @@ -534,6 +534,7 @@ g_main_context_unref (GMainContext *context)
 | ||||
|    GSourceIter iter; | ||||
|    GSource *source; | ||||
|    GList *sl_iter; | ||||
| +  GSList *s_iter, *remaining_sources = NULL;
 | ||||
|    GSourceList *list; | ||||
|    guint i; | ||||
|   | ||||
| @@ -553,10 +554,30 @@ g_main_context_unref (GMainContext *context)
 | ||||
|   | ||||
|    /* g_source_iter_next() assumes the context is locked. */ | ||||
|    LOCK_CONTEXT (context); | ||||
| -  g_source_iter_init (&iter, context, TRUE);
 | ||||
| +
 | ||||
| +  /* First collect all remaining sources from the sources lists and store a
 | ||||
| +   * new reference in a separate list. Also set the context of the sources
 | ||||
| +   * to NULL so that they can't access a partially destroyed context anymore.
 | ||||
| +   *
 | ||||
| +   * We have to do this first so that we have a strong reference to all
 | ||||
| +   * sources and destroying them below does not also free them, and so that
 | ||||
| +   * none of the sources can access the context from their finalize/dispose
 | ||||
| +   * functions. */
 | ||||
| +  g_source_iter_init (&iter, context, FALSE);
 | ||||
|    while (g_source_iter_next (&iter, &source)) | ||||
|      { | ||||
|        source->context = NULL; | ||||
| +      remaining_sources = g_slist_prepend (remaining_sources, g_source_ref (source));
 | ||||
| +    }
 | ||||
| +  g_source_iter_clear (&iter);
 | ||||
| +
 | ||||
| +  /* Next destroy all sources. As we still hold a reference to all of them,
 | ||||
| +   * this won't cause any of them to be freed yet and especially prevents any
 | ||||
| +   * source that unrefs another source from its finalize function to be freed.
 | ||||
| +   */
 | ||||
| +  for (s_iter = remaining_sources; s_iter; s_iter = s_iter->next)
 | ||||
| +    {
 | ||||
| +      source = s_iter->data;
 | ||||
|        g_source_destroy_internal (source, context, TRUE); | ||||
|      } | ||||
|    UNLOCK_CONTEXT (context); | ||||
| @@ -581,6 +602,18 @@ g_main_context_unref (GMainContext *context)
 | ||||
|    g_cond_clear (&context->cond); | ||||
|   | ||||
|    g_free (context); | ||||
| +
 | ||||
| +  /* And now finally get rid of our references to the sources. This will cause
 | ||||
| +   * them to be freed unless something else still has a reference to them. Due
 | ||||
| +   * to setting the context pointers in the sources to NULL above, this won't
 | ||||
| +   * ever access the context or the internal linked list inside the GSource.
 | ||||
| +   * We already removed the sources completely from the context above. */
 | ||||
| +  for (s_iter = remaining_sources; s_iter; s_iter = s_iter->next)
 | ||||
| +    {
 | ||||
| +      source = s_iter->data;
 | ||||
| +      g_source_unref_internal (source, NULL, FALSE);
 | ||||
| +    }
 | ||||
| +  g_slist_free (remaining_sources);
 | ||||
|  } | ||||
|   | ||||
|  /* Helper function used by mainloop/overflow test. | ||||
| -- 
 | ||||
| 2.31.1 | ||||
| 
 | ||||
| From 1d16e92028f235ed9cd786070832d5bd71017661 Mon Sep 17 00:00:00 2001 | ||||
| From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= <sebastian@centricular.com> | ||||
| Date: Tue, 11 Feb 2020 09:34:38 +0200 | ||||
| Subject: [PATCH 4/5] GMainContext - Move mutex unlocking in destructor right | ||||
|  before freeing the mutex | ||||
| 
 | ||||
| This does not have any behaviour changes but is cleaner. The mutex is | ||||
| only unlocked now after all operations on the context are done and right | ||||
| before freeing the mutex and the context itself. | ||||
| ---
 | ||||
|  glib/gmain.c | 2 +- | ||||
|  1 file changed, 1 insertion(+), 1 deletion(-) | ||||
| 
 | ||||
| diff --git a/glib/gmain.c b/glib/gmain.c
 | ||||
| index 1c249ad02..44e6ed0c3 100644
 | ||||
| --- a/glib/gmain.c
 | ||||
| +++ b/glib/gmain.c
 | ||||
| @@ -580,7 +580,6 @@ g_main_context_unref (GMainContext *context)
 | ||||
|        source = s_iter->data; | ||||
|        g_source_destroy_internal (source, context, TRUE); | ||||
|      } | ||||
| -  UNLOCK_CONTEXT (context);
 | ||||
|   | ||||
|    for (sl_iter = context->source_lists; sl_iter; sl_iter = sl_iter->next) | ||||
|      { | ||||
| @@ -591,6 +590,7 @@ g_main_context_unref (GMainContext *context)
 | ||||
|   | ||||
|    g_hash_table_destroy (context->sources); | ||||
|   | ||||
| +  UNLOCK_CONTEXT (context);
 | ||||
|    g_mutex_clear (&context->mutex); | ||||
|   | ||||
|    g_ptr_array_free (context->pending_dispatches, TRUE); | ||||
| -- 
 | ||||
| 2.31.1 | ||||
| 
 | ||||
| From 02ad7294ad5895178df73a6cd8546c6e67097493 Mon Sep 17 00:00:00 2001 | ||||
| From: Benjamin Berg <bberg@redhat.com> | ||||
| Date: Tue, 13 Oct 2020 15:09:43 +0200 | ||||
| Subject: [PATCH 5/5] gmain: Fix possible locking issue in source unref | ||||
| 
 | ||||
| When unref'ing child sources, the lock is already held. But instead of | ||||
| passing TRUE to g_source_unref_internal it currently passes whether the | ||||
| lock was already held outside of the current invocation. Just pass TRUE | ||||
| to fix this possible issue. | ||||
| ---
 | ||||
|  glib/gmain.c | 2 +- | ||||
|  1 file changed, 1 insertion(+), 1 deletion(-) | ||||
| 
 | ||||
| diff --git a/glib/gmain.c b/glib/gmain.c
 | ||||
| index 44e6ed0c3..95992253d 100644
 | ||||
| --- a/glib/gmain.c
 | ||||
| +++ b/glib/gmain.c
 | ||||
| @@ -2164,7 +2164,7 @@ g_source_unref_internal (GSource      *source,
 | ||||
|              g_slist_remove (source->priv->child_sources, child_source); | ||||
|            child_source->priv->parent_source = NULL; | ||||
|   | ||||
| -          g_source_unref_internal (child_source, context, have_lock);
 | ||||
| +          g_source_unref_internal (child_source, context, TRUE);
 | ||||
|          } | ||||
|   | ||||
|        g_slice_free (GSourcePrivate, source->priv); | ||||
| -- 
 | ||||
| 2.31.1 | ||||
| @ -5,7 +5,7 @@ | ||||
| 
 | ||||
| Name: glib2 | ||||
| Version: 2.56.4 | ||||
| Release: 9%{?dist} | ||||
| Release: 10%{?dist} | ||||
| Summary: A library of handy utility functions | ||||
| 
 | ||||
| License: LGPLv2+ | ||||
| @ -70,6 +70,16 @@ Patch60: keyfile-backend.patch | ||||
| # https://gitlab.gnome.org/GNOME/glib/-/issues/1658 | ||||
| Patch61: CVE-2019-13012.patch | ||||
| 
 | ||||
| # https://gitlab.gnome.org/GNOME/glib/-/merge_requests/1927 | ||||
| # https://gitlab.gnome.org/GNOME/glib/-/merge_requests/2000 | ||||
| Patch70: CVE-2021-27219.patch | ||||
| 
 | ||||
| # https://bugzilla.redhat.com/show_bug.cgi?id=1948988 | ||||
| # https://gitlab.gnome.org/GNOME/glib/-/merge_requests/873 | ||||
| # https://gitlab.gnome.org/GNOME/glib/-/merge_requests/1353 | ||||
| # https://gitlab.gnome.org/GNOME/glib/-/merge_requests/1691 | ||||
| Patch80: gmain-corruption.patch | ||||
| 
 | ||||
| %description | ||||
| GLib is the low-level core library that forms the basis for projects | ||||
| such as GTK+ and GNOME. It provides data structure handling for C, | ||||
| @ -267,6 +277,12 @@ glib-compile-schemas %{_datadir}/glib-2.0/schemas &> /dev/null || : | ||||
| %{_datadir}/installed-tests | ||||
| 
 | ||||
| %changelog | ||||
| * Thu May 20 2021 Michael Catanzaro <mcatanzaro@redhat.com> - 2.56.4-10 | ||||
| - Fix various problems in GMainContext | ||||
|   Resolves: #1953553 | ||||
| - Fix CVE-2021-27219 | ||||
|   Resolves: #1960600 | ||||
| 
 | ||||
| * Tue Nov 10 2020 Michael Catanzaro <mcatanzaro@redhat.com> - 2.56.4-9 | ||||
| - Update GHmac patch to implement g_hmac_copy() | ||||
|   Resolves: #1786538 | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user