Commit 24b94469 authored by Philip Withnall's avatar Philip Withnall Committed by Simon McVittie
Browse files

gstrfuncs: Add internal g_memdup2() function



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's avatarPhilip Withnall <pwithnall@endlessos.org>
Helps: CVE-2021-27219
Helps: GHSL-2021-045
Helps: #2319
(cherry picked from commit 5e5f75a7)
parent c1a66787
......@@ -20,6 +20,7 @@ if get_option('gtk_doc')
'gprintfint.h',
'gmirroringtable.h',
'gscripttable.h',
'gstrfuncsprivate.h',
'glib-mirroring-tab',
'gnulib',
'pcre',
......
/* 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;
}
......@@ -182,6 +182,7 @@ glib_sources = files(
'gslist.c',
'gstdio.c',
'gstrfuncs.c',
'gstrfuncsprivate.h',
'gstring.c',
'gstringchunk.c',
'gtestutils.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)
{
......@@ -1731,6 +1753,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);
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment