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;