[glib: 4/5] gvariant: Fix error handling for parsing Unicode escapes
- From: Philip Withnall <pwithnall src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [glib: 4/5] gvariant: Fix error handling for parsing Unicode escapes
- Date: Thu, 6 Dec 2018 11:15:57 +0000 (UTC)
commit d2224b475d20b544cf782ce046183209d419a012
Author: Philip Withnall <withnall endlessm com>
Date: Tue Dec 4 12:55:21 2018 +0000
gvariant: Fix error handling for parsing Unicode escapes
When parsing an escaped Unicode character in a text format GVariant
string, such as '\U0001F415', the code uses g_ascii_strtoull(). This,
unexpectedly, accepts minus signs, which can cause an assertion failure
when input like '\u-FF4' is presented for parsing.
Validate that there are no leading sign characters when parsing.
This shouldn’t be considered a security bug, because the GVariant text
format parser should not be used on untrusted input.
oss-fuzz#11576
Signed-off-by: Philip Withnall <withnall endlessm com>
glib/gvariant-parser.c | 20 +++++++++++++++++---
glib/tests/gvariant.c | 20 ++++++++++++++++++--
2 files changed, 35 insertions(+), 5 deletions(-)
---
diff --git a/glib/gvariant-parser.c b/glib/gvariant-parser.c
index 44e341965..b860d42f4 100644
--- a/glib/gvariant-parser.c
+++ b/glib/gvariant-parser.c
@@ -1528,6 +1528,8 @@ string_free (AST *ast)
g_slice_free (String, string);
}
+/* Accepts exactly @length hexadecimal digits. No leading sign or `0x`/`0X` prefix allowed.
+ * No leading/trailing space allowed. */
static gboolean
unicode_unescape (const gchar *src,
gint *src_ofs,
@@ -1538,8 +1540,9 @@ unicode_unescape (const gchar *src,
GError **error)
{
gchar buffer[9];
- guint64 value;
+ guint64 value = 0;
gchar *end;
+ gsize n_valid_chars;
(*src_ofs)++;
@@ -1547,11 +1550,22 @@ unicode_unescape (const gchar *src,
strncpy (buffer, src + *src_ofs, length);
buffer[length] = '\0';
- value = g_ascii_strtoull (buffer, &end, 0x10);
+ for (n_valid_chars = 0; n_valid_chars < length; n_valid_chars++)
+ if (!g_ascii_isxdigit (buffer[n_valid_chars]))
+ break;
+
+ if (n_valid_chars == length)
+ value = g_ascii_strtoull (buffer, &end, 0x10);
if (value == 0 || end != buffer + length)
{
- parser_set_error (error, ref, NULL,
+ SourceRef escape_ref;
+
+ escape_ref = *ref;
+ escape_ref.start += *src_ofs;
+ escape_ref.end = escape_ref.start + n_valid_chars;
+
+ parser_set_error (error, &escape_ref, NULL,
G_VARIANT_PARSE_ERROR_INVALID_CHARACTER,
"invalid %" G_GSIZE_FORMAT "-character unicode escape", length);
return FALSE;
diff --git a/glib/tests/gvariant.c b/glib/tests/gvariant.c
index 827e47532..bf86b3c88 100644
--- a/glib/tests/gvariant.c
+++ b/glib/tests/gvariant.c
@@ -4039,6 +4039,22 @@ test_parse_failures (void)
"b\"\\\"", "0-4:", "unterminated string constant",
"b'\\'a", "0-5:", "unterminated string constant",
"b\"\\\"a", "0-5:", "unterminated string constant",
+ "'\\u-ff4'", "3:", "invalid 4-character unicode escape",
+ "'\\u+ff4'", "3:", "invalid 4-character unicode escape",
+ "'\\u'", "3:", "invalid 4-character unicode escape",
+ "'\\u0'", "3-4:", "invalid 4-character unicode escape",
+ "'\\uHELLO'", "3:", "invalid 4-character unicode escape",
+ "'\\u ff4'", "3:", "invalid 4-character unicode escape",
+ "'\\u012'", "3-6:", "invalid 4-character unicode escape",
+ "'\\u0xff4'", "3-4:", "invalid 4-character unicode escape",
+ "'\\U-ff4'", "3:", "invalid 8-character unicode escape",
+ "'\\U+ff4'", "3:", "invalid 8-character unicode escape",
+ "'\\U'", "3:", "invalid 8-character unicode escape",
+ "'\\U0'", "3-4:", "invalid 8-character unicode escape",
+ "'\\UHELLO'", "3:", "invalid 8-character unicode escape",
+ "'\\U ff4'", "3:", "invalid 8-character unicode escape",
+ "'\\U0123456'", "3-10:", "invalid 8-character unicode escape",
+ "'\\U0xff4'", "3-4:", "invalid 8-character unicode escape",
};
guint i;
@@ -4674,8 +4690,8 @@ test_print_context (void)
{ NULL, "[1, 2, 3, 'str']", " ^ ^^^^^" },
{ G_VARIANT_TYPE_UINT16, "{ 'abc':'def' }", " ^^^^^^^^^^^^^^^" },
{ NULL, "<5", " ^" },
- { NULL, "'ab\\ux'", " ^^^^^^^" },
- { NULL, "'ab\\U00efx'", " ^^^^^^^^^^^" }
+ { NULL, "'ab\\ux'", " ^ " },
+ { NULL, "'ab\\U00efx'", " ^^^^ " }
};
GVariant *v;
gchar *s;
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]