77 lines
2.5 KiB
Diff
77 lines
2.5 KiB
Diff
|
|
From d2224b475d20b544cf782ce046183209d419a012 Mon Sep 17 00:00:00 2001
|
|||
|
|
From: Philip Withnall <withnall@endlessm.com>
|
|||
|
|
Date: Tue, 4 Dec 2018 12:55:21 +0000
|
|||
|
|
Subject: [PATCH 325/682] gvariant: Fix error handling for parsing Unicode
|
|||
|
|
escapes
|
|||
|
|
MIME-Version: 1.0
|
|||
|
|
Content-Type: text/plain; charset=UTF-8
|
|||
|
|
Content-Transfer-Encoding: 8bit
|
|||
|
|
|
|||
|
|
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 %d-character unicode escape", length);
|
|||
|
|
return FALSE;
|