Merge branch 'ossfuzz-11576-variant-text-unicode-unescape' into 'master'

gvariant: Fix error handling for parsing Unicode escapes

See merge request GNOME/glib!511
This commit is contained in:
Philip Withnall 2018-12-06 11:15:24 +00:00
commit 3469faf15c
4 changed files with 45 additions and 8 deletions

View File

@ -1140,6 +1140,11 @@ g_parse_long_long (const gchar *nptr,
* changing the current locale, since that would not be * changing the current locale, since that would not be
* thread-safe. * thread-safe.
* *
* Note that input with a leading minus sign (`-`) is accepted, and will return
* the negation of the parsed number, unless that would overflow a #guint64.
* Critically, this means you cannot assume that a short fixed length input will
* never result in a low return value, as the input could have a leading `-`.
*
* This function is typically used when reading configuration * This function is typically used when reading configuration
* files or other non-user input that should be locale independent. * files or other non-user input that should be locale independent.
* To handle input from the user you should normally use the * To handle input from the user you should normally use the
@ -3304,7 +3309,8 @@ g_ascii_string_to_signed (const gchar *str,
* @base that is within inclusive bounds limited by @min and @max. If * @base that is within inclusive bounds limited by @min and @max. If
* this is true, then the converted number is stored in @out_num. An * this is true, then the converted number is stored in @out_num. An
* empty string is not a valid input. A string with leading or * empty string is not a valid input. A string with leading or
* trailing whitespace is also an invalid input. * trailing whitespace is also an invalid input. A string with a leading sign
* (`-` or `+`) is not a valid input for the unsigned parser.
* *
* @base can be between 2 and 36 inclusive. Hexadecimal numbers must * @base can be between 2 and 36 inclusive. Hexadecimal numbers must
* not be prefixed with "0x" or "0X". Such a problem does not exist * not be prefixed with "0x" or "0X". Such a problem does not exist

View File

@ -1528,18 +1528,21 @@ 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,
gchar *dest, gchar *dest,
gint *dest_ofs, gint *dest_ofs,
gint length, gsize length,
SourceRef *ref, SourceRef *ref,
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,13 +1550,24 @@ 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 %d-character unicode escape", length); "invalid %" G_GSIZE_FORMAT "-character unicode escape", length);
return FALSE; return FALSE;
} }

View File

@ -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;

View File

@ -1098,6 +1098,7 @@ test_strtoll (void)
check_uint64 ("18446744073709551616", "", 10, G_MAXUINT64, ERANGE); check_uint64 ("18446744073709551616", "", 10, G_MAXUINT64, ERANGE);
check_uint64 ("20xyz", "xyz", 10, 20, 0); check_uint64 ("20xyz", "xyz", 10, 20, 0);
check_uint64 ("-1", "", 10, G_MAXUINT64, 0); check_uint64 ("-1", "", 10, G_MAXUINT64, 0);
check_uint64 ("-FF4", "", 16, -((guint64) 0xFF4), 0);
check_int64 ("0", "", 10, 0, 0); check_int64 ("0", "", 10, 0, 0);
check_int64 ("9223372036854775807", "", 10, G_MAXINT64, 0); check_int64 ("9223372036854775807", "", 10, G_MAXINT64, 0);