Blame SOURCES/0001-gstrfuncs-Add-internal-g_memdup2-function.patch

e5da31
From e23bf51c6a898f5c395ffb388a0287575a3017cb Mon Sep 17 00:00:00 2001
e5da31
From: Philip Withnall <pwithnall@endlessos.org>
e5da31
Date: Thu, 4 Feb 2021 13:30:52 +0000
e5da31
Subject: [PATCH 01/12] gstrfuncs: Add internal g_memdup2() function
e5da31
MIME-Version: 1.0
e5da31
Content-Type: text/plain; charset=UTF-8
e5da31
Content-Transfer-Encoding: 8bit
e5da31
e5da31
This will replace the existing `g_memdup()` function for use within
e5da31
GLib. It has an unavoidable security flaw of taking its `byte_size`
e5da31
argument as a `guint` rather than as a `gsize`. Most callers will
e5da31
expect it to be a `gsize`, and may pass in large values which could
e5da31
silently be truncated, resulting in an undersize allocation compared
e5da31
to what the caller expects.
e5da31
e5da31
This could lead to a classic buffer overflow vulnerability for many
e5da31
callers of `g_memdup()`.
e5da31
e5da31
`g_memdup2()`, in comparison, takes its `byte_size` as a `gsize`.
e5da31
e5da31
Spotted by Kevin Backhouse of GHSL.
e5da31
e5da31
In GLib 2.68, `g_memdup2()` will be a new public API. In this version
e5da31
for backport to older stable releases, it’s a new `static inline` API
e5da31
in a private header, so that use of `g_memdup()` within GLib can be
e5da31
fixed without adding a new API in a stable release series.
e5da31
e5da31
Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
e5da31
Helps: GHSL-2021-045
e5da31
Helps: #2319
e5da31
---
e5da31
 docs/reference/glib/meson.build |  1 +
e5da31
 glib/gstrfuncsprivate.h         | 55 +++++++++++++++++++++++++++++++++
e5da31
 glib/meson.build                |  1 +
e5da31
 glib/tests/strfuncs.c           | 23 ++++++++++++++
e5da31
 4 files changed, 80 insertions(+)
e5da31
 create mode 100644 glib/gstrfuncsprivate.h
e5da31
e5da31
diff --git a/docs/reference/glib/meson.build b/docs/reference/glib/meson.build
e5da31
index f0f915e96..1a3680941 100644
e5da31
--- a/docs/reference/glib/meson.build
e5da31
+++ b/docs/reference/glib/meson.build
e5da31
@@ -20,6 +20,7 @@ if get_option('gtk_doc')
e5da31
     'gprintfint.h',
e5da31
     'gmirroringtable.h',
e5da31
     'gscripttable.h',
e5da31
+    'gstrfuncsprivate.h',
e5da31
     'glib-mirroring-tab',
e5da31
     'gnulib',
e5da31
     'pcre',
e5da31
diff --git a/glib/gstrfuncsprivate.h b/glib/gstrfuncsprivate.h
e5da31
new file mode 100644
e5da31
index 000000000..85c88328a
e5da31
--- /dev/null
e5da31
+++ b/glib/gstrfuncsprivate.h
e5da31
@@ -0,0 +1,55 @@
e5da31
+/* GLIB - Library of useful routines for C programming
e5da31
+ * Copyright (C) 1995-1997  Peter Mattis, Spencer Kimball and Josh MacDonald
e5da31
+ *
e5da31
+ * This library is free software; you can redistribute it and/or
e5da31
+ * modify it under the terms of the GNU Lesser General Public
e5da31
+ * License as published by the Free Software Foundation; either
e5da31
+ * version 2.1 of the License, or (at your option) any later version.
e5da31
+ *
e5da31
+ * This library is distributed in the hope that it will be useful,
e5da31
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
e5da31
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
e5da31
+ * Lesser General Public License for more details.
e5da31
+ *
e5da31
+ * You should have received a copy of the GNU Lesser General Public
e5da31
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
e5da31
+ */
e5da31
+
e5da31
+#include <glib.h>
e5da31
+#include <string.h>
e5da31
+
e5da31
+/*
e5da31
+ * g_memdup2:
e5da31
+ * @mem: (nullable): the memory to copy.
e5da31
+ * @byte_size: the number of bytes to copy.
e5da31
+ *
e5da31
+ * Allocates @byte_size bytes of memory, and copies @byte_size bytes into it
e5da31
+ * from @mem. If @mem is %NULL it returns %NULL.
e5da31
+ *
e5da31
+ * This replaces g_memdup(), which was prone to integer overflows when
e5da31
+ * converting the argument from a #gsize to a #guint.
e5da31
+ *
e5da31
+ * This static inline version is a backport of the new public API from
e5da31
+ * GLib 2.68, kept internal to GLib for backport to older stable releases.
e5da31
+ * See https://gitlab.gnome.org/GNOME/glib/-/issues/2319.
e5da31
+ *
e5da31
+ * Returns: (nullable): a pointer to the newly-allocated copy of the memory,
e5da31
+ *    or %NULL if @mem is %NULL.
e5da31
+ * Since: 2.68
e5da31
+ */
e5da31
+static inline gpointer
e5da31
+g_memdup2 (gconstpointer mem,
e5da31
+           gsize         byte_size)
e5da31
+{
e5da31
+  gpointer new_mem;
e5da31
+
e5da31
+  if (mem && byte_size != 0)
e5da31
+    {
e5da31
+      new_mem = g_malloc (byte_size);
e5da31
+      memcpy (new_mem, mem, byte_size);
e5da31
+    }
e5da31
+  else
e5da31
+    new_mem = NULL;
e5da31
+
e5da31
+  return new_mem;
e5da31
+}
e5da31
diff --git a/glib/meson.build b/glib/meson.build
e5da31
index a2f9da81c..481fd06ff 100644
e5da31
--- a/glib/meson.build
e5da31
+++ b/glib/meson.build
e5da31
@@ -167,6 +167,7 @@ glib_sources = files(
e5da31
   'gslist.c',
e5da31
   'gstdio.c',
e5da31
   'gstrfuncs.c',
e5da31
+  'gstrfuncsprivate.h',
e5da31
   'gstring.c',
e5da31
   'gstringchunk.c',
e5da31
   'gtestutils.c',
e5da31
diff --git a/glib/tests/strfuncs.c b/glib/tests/strfuncs.c
e5da31
index 7e031bdb1..2aa252946 100644
e5da31
--- a/glib/tests/strfuncs.c
e5da31
+++ b/glib/tests/strfuncs.c
e5da31
@@ -32,6 +32,8 @@
e5da31
 #include <string.h>
e5da31
 #include "glib.h"
e5da31
 
e5da31
+#include "gstrfuncsprivate.h"
e5da31
+
e5da31
 #if defined (_MSC_VER) && (_MSC_VER <= 1800)
e5da31
 #define isnan(x) _isnan(x)
e5da31
 
e5da31
@@ -199,6 +201,26 @@ test_is_to_digit (void)
e5da31
   #undef TEST_DIGIT
e5da31
 }
e5da31
 
e5da31
+/* Testing g_memdup2() function with various positive and negative cases */
e5da31
+static void
e5da31
+test_memdup2 (void)
e5da31
+{
e5da31
+  gchar *str_dup = NULL;
e5da31
+  const gchar *str = "The quick brown fox jumps over the lazy dog";
e5da31
+
e5da31
+  /* Testing negative cases */
e5da31
+  g_assert_null (g_memdup2 (NULL, 1024));
e5da31
+  g_assert_null (g_memdup2 (str, 0));
e5da31
+  g_assert_null (g_memdup2 (NULL, 0));
e5da31
+
e5da31
+  /* Testing normal usage cases */
e5da31
+  str_dup = g_memdup2 (str, strlen (str) + 1);
e5da31
+  g_assert_nonnull (str_dup);
e5da31
+  g_assert_cmpstr (str, ==, str_dup);
e5da31
+
e5da31
+  g_free (str_dup);
e5da31
+}
e5da31
+
e5da31
 static void
e5da31
 test_strdup (void)
e5da31
 {
e5da31
@@ -1726,6 +1748,7 @@ main (int   argc,
e5da31
   g_test_init (&argc, &argv, NULL);
e5da31
 
e5da31
   g_test_add_func ("/strfuncs/test-is-to-digit", test_is_to_digit);
e5da31
+  g_test_add_func ("/strfuncs/memdup2", test_memdup2);
e5da31
   g_test_add_func ("/strfuncs/strdup", test_strdup);
e5da31
   g_test_add_func ("/strfuncs/strndup", test_strndup);
e5da31
   g_test_add_func ("/strfuncs/strdup-printf", test_strdup_printf);
e5da31
-- 
e5da31
2.31.1
e5da31