Commit | Line | Data |
---|---|---|
21b3b755 MW |
1 | Backport of: |
2 | ||
3 | From 5e5f75a77e399c638be66d74e5daa8caeb433e00 Mon Sep 17 00:00:00 2001 | |
4 | From: Philip Withnall <pwithnall@endlessos.org> | |
5 | Date: Thu, 4 Feb 2021 13:30:52 +0000 | |
6 | Subject: [PATCH 01/11] gstrfuncs: Add internal g_memdup2() function | |
7 | MIME-Version: 1.0 | |
8 | Content-Type: text/plain; charset=UTF-8 | |
9 | Content-Transfer-Encoding: 8bit | |
10 | ||
11 | This will replace the existing `g_memdup()` function for use within | |
12 | GLib. It has an unavoidable security flaw of taking its `byte_size` | |
13 | argument as a `guint` rather than as a `gsize`. Most callers will | |
14 | expect it to be a `gsize`, and may pass in large values which could | |
15 | silently be truncated, resulting in an undersize allocation compared | |
16 | to what the caller expects. | |
17 | ||
18 | This could lead to a classic buffer overflow vulnerability for many | |
19 | callers of `g_memdup()`. | |
20 | ||
21 | `g_memdup2()`, in comparison, takes its `byte_size` as a `gsize`. | |
22 | ||
23 | Spotted by Kevin Backhouse of GHSL. | |
24 | ||
25 | In GLib 2.68, `g_memdup2()` will be a new public API. In this version | |
26 | for backport to older stable releases, it’s a new `static inline` API | |
27 | in a private header, so that use of `g_memdup()` within GLib can be | |
28 | fixed without adding a new API in a stable release series. | |
29 | ||
30 | Signed-off-by: Philip Withnall <pwithnall@endlessos.org> | |
31 | Helps: GHSL-2021-045 | |
32 | Helps: #2319 | |
33 | --- | |
34 | docs/reference/glib/meson.build | 1 + | |
35 | glib/gstrfuncsprivate.h | 55 +++++++++++++++++++++++++++++++++ | |
36 | glib/meson.build | 1 + | |
37 | glib/tests/strfuncs.c | 23 ++++++++++++++ | |
38 | 4 files changed, 80 insertions(+) | |
39 | create mode 100644 glib/gstrfuncsprivate.h | |
40 | ||
41 | diff --git a/docs/reference/glib/meson.build b/docs/reference/glib/meson.build | |
42 | index bba7649f0..ee39f6d04 100644 | |
43 | --- a/docs/reference/glib/meson.build | |
44 | +++ b/docs/reference/glib/meson.build | |
45 | @@ -22,6 +22,7 @@ if get_option('gtk_doc') | |
46 | 'gprintfint.h', | |
47 | 'gmirroringtable.h', | |
48 | 'gscripttable.h', | |
49 | + 'gstrfuncsprivate.h', | |
50 | 'glib-mirroring-tab', | |
51 | 'gnulib', | |
52 | 'pcre', | |
53 | diff --git a/glib/gstrfuncsprivate.h b/glib/gstrfuncsprivate.h | |
54 | new file mode 100644 | |
55 | index 000000000..85c88328a | |
56 | --- /dev/null | |
57 | +++ b/glib/gstrfuncsprivate.h | |
58 | @@ -0,0 +1,55 @@ | |
59 | +/* GLIB - Library of useful routines for C programming | |
60 | + * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald | |
61 | + * | |
62 | + * This library is free software; you can redistribute it and/or | |
63 | + * modify it under the terms of the GNU Lesser General Public | |
64 | + * License as published by the Free Software Foundation; either | |
65 | + * version 2.1 of the License, or (at your option) any later version. | |
66 | + * | |
67 | + * This library is distributed in the hope that it will be useful, | |
68 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
69 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
70 | + * Lesser General Public License for more details. | |
71 | + * | |
72 | + * You should have received a copy of the GNU Lesser General Public | |
73 | + * License along with this library; if not, see <http://www.gnu.org/licenses/>. | |
74 | + */ | |
75 | + | |
76 | +#include <glib.h> | |
77 | +#include <string.h> | |
78 | + | |
79 | +/* | |
80 | + * g_memdup2: | |
81 | + * @mem: (nullable): the memory to copy. | |
82 | + * @byte_size: the number of bytes to copy. | |
83 | + * | |
84 | + * Allocates @byte_size bytes of memory, and copies @byte_size bytes into it | |
85 | + * from @mem. If @mem is %NULL it returns %NULL. | |
86 | + * | |
87 | + * This replaces g_memdup(), which was prone to integer overflows when | |
88 | + * converting the argument from a #gsize to a #guint. | |
89 | + * | |
90 | + * This static inline version is a backport of the new public API from | |
91 | + * GLib 2.68, kept internal to GLib for backport to older stable releases. | |
92 | + * See https://gitlab.gnome.org/GNOME/glib/-/issues/2319. | |
93 | + * | |
94 | + * Returns: (nullable): a pointer to the newly-allocated copy of the memory, | |
95 | + * or %NULL if @mem is %NULL. | |
96 | + * Since: 2.68 | |
97 | + */ | |
98 | +static inline gpointer | |
99 | +g_memdup2 (gconstpointer mem, | |
100 | + gsize byte_size) | |
101 | +{ | |
102 | + gpointer new_mem; | |
103 | + | |
104 | + if (mem && byte_size != 0) | |
105 | + { | |
106 | + new_mem = g_malloc (byte_size); | |
107 | + memcpy (new_mem, mem, byte_size); | |
108 | + } | |
109 | + else | |
110 | + new_mem = NULL; | |
111 | + | |
112 | + return new_mem; | |
113 | +} | |
114 | diff --git a/glib/meson.build b/glib/meson.build | |
115 | index aaf5f00f5..5a6eea397 100644 | |
116 | --- a/glib/meson.build | |
117 | +++ b/glib/meson.build | |
118 | @@ -268,6 +268,7 @@ glib_sources = files( | |
119 | 'gslist.c', | |
120 | 'gstdio.c', | |
121 | 'gstrfuncs.c', | |
122 | + 'gstrfuncsprivate.h', | |
123 | 'gstring.c', | |
124 | 'gstringchunk.c', | |
125 | 'gtestutils.c', | |
126 | diff --git a/glib/tests/strfuncs.c b/glib/tests/strfuncs.c | |
127 | index e1f9619c7..d968afff9 100644 | |
128 | --- a/glib/tests/strfuncs.c | |
129 | +++ b/glib/tests/strfuncs.c | |
130 | @@ -32,6 +32,8 @@ | |
131 | #include <string.h> | |
132 | #include "glib.h" | |
133 | ||
134 | +#include "gstrfuncsprivate.h" | |
135 | + | |
136 | #if defined (_MSC_VER) && (_MSC_VER <= 1800) | |
137 | #define isnan(x) _isnan(x) | |
138 | ||
139 | @@ -219,6 +221,26 @@ test_memdup (void) | |
140 | g_free (str_dup); | |
141 | } | |
142 | ||
143 | +/* Testing g_memdup2() function with various positive and negative cases */ | |
144 | +static void | |
145 | +test_memdup2 (void) | |
146 | +{ | |
147 | + gchar *str_dup = NULL; | |
148 | + const gchar *str = "The quick brown fox jumps over the lazy dog"; | |
149 | + | |
150 | + /* Testing negative cases */ | |
151 | + g_assert_null (g_memdup2 (NULL, 1024)); | |
152 | + g_assert_null (g_memdup2 (str, 0)); | |
153 | + g_assert_null (g_memdup2 (NULL, 0)); | |
154 | + | |
155 | + /* Testing normal usage cases */ | |
156 | + str_dup = g_memdup2 (str, strlen (str) + 1); | |
157 | + g_assert_nonnull (str_dup); | |
158 | + g_assert_cmpstr (str, ==, str_dup); | |
159 | + | |
160 | + g_free (str_dup); | |
161 | +} | |
162 | + | |
163 | /* Testing g_strpcpy() function with various positive and negative cases */ | |
164 | static void | |
165 | test_stpcpy (void) | |
166 | @@ -2523,6 +2545,7 @@ main (int argc, | |
167 | g_test_add_func ("/strfuncs/has-prefix", test_has_prefix); | |
168 | g_test_add_func ("/strfuncs/has-suffix", test_has_suffix); | |
169 | g_test_add_func ("/strfuncs/memdup", test_memdup); | |
170 | + g_test_add_func ("/strfuncs/memdup2", test_memdup2); | |
171 | g_test_add_func ("/strfuncs/stpcpy", test_stpcpy); | |
172 | g_test_add_func ("/strfuncs/str_match_string", test_str_match_string); | |
173 | g_test_add_func ("/strfuncs/str_tokenize_and_fold", test_str_tokenize_and_fold); | |
174 | -- | |
175 | 2.30.1 | |
176 |