mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2025-01-16 01:06:15 +01:00
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>
This commit is contained in:
parent
ca328615c8
commit
d2224b475d
@ -1528,6 +1528,8 @@ string_free (AST *ast)
|
|||||||
g_slice_free (String, string);
|
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
|
static gboolean
|
||||||
unicode_unescape (const gchar *src,
|
unicode_unescape (const gchar *src,
|
||||||
gint *src_ofs,
|
gint *src_ofs,
|
||||||
@ -1538,8 +1540,9 @@ unicode_unescape (const gchar *src,
|
|||||||
GError **error)
|
GError **error)
|
||||||
{
|
{
|
||||||
gchar buffer[9];
|
gchar buffer[9];
|
||||||
guint64 value;
|
guint64 value = 0;
|
||||||
gchar *end;
|
gchar *end;
|
||||||
|
gsize n_valid_chars;
|
||||||
|
|
||||||
(*src_ofs)++;
|
(*src_ofs)++;
|
||||||
|
|
||||||
@ -1547,11 +1550,22 @@ unicode_unescape (const gchar *src,
|
|||||||
strncpy (buffer, src + *src_ofs, length);
|
strncpy (buffer, src + *src_ofs, length);
|
||||||
buffer[length] = '\0';
|
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)
|
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,
|
G_VARIANT_PARSE_ERROR_INVALID_CHARACTER,
|
||||||
"invalid %" G_GSIZE_FORMAT "-character unicode escape", length);
|
"invalid %" G_GSIZE_FORMAT "-character unicode escape", length);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
@ -4039,6 +4039,22 @@ test_parse_failures (void)
|
|||||||
"b\"\\\"", "0-4:", "unterminated string constant",
|
"b\"\\\"", "0-4:", "unterminated string constant",
|
||||||
"b'\\'a", "0-5:", "unterminated string constant",
|
"b'\\'a", "0-5:", "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;
|
guint i;
|
||||||
|
|
||||||
@ -4674,8 +4690,8 @@ test_print_context (void)
|
|||||||
{ NULL, "[1, 2, 3, 'str']", " ^ ^^^^^" },
|
{ NULL, "[1, 2, 3, 'str']", " ^ ^^^^^" },
|
||||||
{ G_VARIANT_TYPE_UINT16, "{ 'abc':'def' }", " ^^^^^^^^^^^^^^^" },
|
{ G_VARIANT_TYPE_UINT16, "{ 'abc':'def' }", " ^^^^^^^^^^^^^^^" },
|
||||||
{ NULL, "<5", " ^" },
|
{ NULL, "<5", " ^" },
|
||||||
{ NULL, "'ab\\ux'", " ^^^^^^^" },
|
{ NULL, "'ab\\ux'", " ^ " },
|
||||||
{ NULL, "'ab\\U00efx'", " ^^^^^^^^^^^" }
|
{ NULL, "'ab\\U00efx'", " ^^^^ " }
|
||||||
};
|
};
|
||||||
GVariant *v;
|
GVariant *v;
|
||||||
gchar *s;
|
gchar *s;
|
||||||
|
Loading…
Reference in New Issue
Block a user