diff --git a/glib/gvariant-parser.c b/glib/gvariant-parser.c index 2f1d3db9f..1b1ddd654 100644 --- a/glib/gvariant-parser.c +++ b/glib/gvariant-parser.c @@ -91,7 +91,9 @@ g_variant_parser_get_error_quark (void) typedef struct { - gint start, end; + /* Offsets from the start of the input, in bytes. Can be equal when referring + * to a point rather than a range. The invariant `end >= start` always holds. */ + size_t start, end; } SourceRef; G_GNUC_PRINTF(5, 0) @@ -106,14 +108,16 @@ parser_set_error_va (GError **error, GString *msg = g_string_new (NULL); if (location->start == location->end) - g_string_append_printf (msg, "%d", location->start); + g_string_append_printf (msg, "%" G_GSIZE_FORMAT, location->start); else - g_string_append_printf (msg, "%d-%d", location->start, location->end); + g_string_append_printf (msg, "%" G_GSIZE_FORMAT "-%" G_GSIZE_FORMAT, + location->start, location->end); if (other != NULL) { g_assert (other->start != other->end); - g_string_append_printf (msg, ",%d-%d", other->start, other->end); + g_string_append_printf (msg, ",%" G_GSIZE_FORMAT "-%" G_GSIZE_FORMAT, + other->start, other->end); } g_string_append_c (msg, ':'); @@ -140,11 +144,15 @@ parser_set_error (GError **error, typedef struct { + /* We should always have the following ordering constraint: + * start <= this <= stream <= end + * Additionally, unless in an error or EOF state, `this < stream`. + */ const gchar *start; const gchar *stream; const gchar *end; - const gchar *this; + const gchar *this; /* (nullable) */ } TokenStream; @@ -175,7 +183,7 @@ token_stream_set_error (TokenStream *stream, static gboolean token_stream_prepare (TokenStream *stream) { - gint brackets = 0; + gssize brackets = 0; const gchar *end; if (stream->this != NULL) @@ -407,7 +415,7 @@ static void pattern_copy (gchar **out, const gchar **in) { - gint brackets = 0; + gssize brackets = 0; while (**in == 'a' || **in == 'm' || **in == 'M') *(*out)++ = *(*in)++; @@ -609,7 +617,7 @@ ast_resolve (AST *ast, { GVariant *value; gchar *pattern; - gint i, j = 0; + size_t i, j = 0; pattern = ast_get_pattern (ast, error); @@ -662,9 +670,9 @@ static AST *parse (TokenStream *stream, GError **error); static void -ast_array_append (AST ***array, - gint *n_items, - AST *ast) +ast_array_append (AST ***array, + size_t *n_items, + AST *ast) { if ((*n_items & (*n_items - 1)) == 0) *array = g_renew (AST *, *array, *n_items ? 2 ** n_items : 1); @@ -673,10 +681,10 @@ ast_array_append (AST ***array, } static void -ast_array_free (AST **array, - gint n_items) +ast_array_free (AST **array, + size_t n_items) { - gint i; + size_t i; for (i = 0; i < n_items; i++) ast_free (array[i]); @@ -685,11 +693,11 @@ ast_array_free (AST **array, static gchar * ast_array_get_pattern (AST **array, - gint n_items, + size_t n_items, GError **error) { gchar *pattern; - gint i; + size_t i; /* Find the pattern which applies to all children in the array, by l-folding a * coalesce operation. @@ -721,7 +729,7 @@ ast_array_get_pattern (AST **array, * pair of values. */ { - int j = 0; + size_t j = 0; while (TRUE) { @@ -969,7 +977,7 @@ typedef struct AST ast; AST **children; - gint n_children; + size_t n_children; } Array; static gchar * @@ -1002,7 +1010,7 @@ array_get_value (AST *ast, Array *array = (Array *) ast; const GVariantType *childtype; GVariantBuilder builder; - gint i; + size_t i; if (!g_variant_type_is_array (type)) return ast_type_error (ast, type, error); @@ -1088,7 +1096,7 @@ typedef struct AST ast; AST **children; - gint n_children; + size_t n_children; } Tuple; static gchar * @@ -1098,7 +1106,7 @@ tuple_get_pattern (AST *ast, Tuple *tuple = (Tuple *) ast; gchar *result = NULL; gchar **parts; - gint i; + size_t i; parts = g_new (gchar *, tuple->n_children + 4); parts[tuple->n_children + 1] = (gchar *) ")"; @@ -1128,7 +1136,7 @@ tuple_get_value (AST *ast, Tuple *tuple = (Tuple *) ast; const GVariantType *childtype; GVariantBuilder builder; - gint i; + size_t i; if (!g_variant_type_is_tuple (type)) return ast_type_error (ast, type, error); @@ -1320,9 +1328,16 @@ typedef struct AST **keys; AST **values; - gint n_children; + + /* Iff this is DICTIONARY_N_CHILDREN_FREESTANDING_ENTRY then this struct + * represents a single freestanding dict entry (`{1, "one"}`) rather than a + * full dict. In the freestanding case, @keys and @values have exactly one + * member each. */ + size_t n_children; } Dictionary; +#define DICTIONARY_N_CHILDREN_FREESTANDING_ENTRY ((size_t) -1) + static gchar * dictionary_get_pattern (AST *ast, GError **error) @@ -1337,7 +1352,7 @@ dictionary_get_pattern (AST *ast, return g_strdup ("Ma{**}"); key_pattern = ast_array_get_pattern (dict->keys, - abs (dict->n_children), + (dict->n_children == DICTIONARY_N_CHILDREN_FREESTANDING_ENTRY) ? 1 : dict->n_children, error); if (key_pattern == NULL) @@ -1368,7 +1383,7 @@ dictionary_get_pattern (AST *ast, return NULL; result = g_strdup_printf ("M%s{%c%s}", - dict->n_children > 0 ? "a" : "", + (dict->n_children > 0 && dict->n_children != DICTIONARY_N_CHILDREN_FREESTANDING_ENTRY) ? "a" : "", key_char, value_pattern); g_free (value_pattern); @@ -1382,7 +1397,7 @@ dictionary_get_value (AST *ast, { Dictionary *dict = (Dictionary *) ast; - if (dict->n_children == -1) + if (dict->n_children == DICTIONARY_N_CHILDREN_FREESTANDING_ENTRY) { const GVariantType *subtype; GVariantBuilder builder; @@ -1415,7 +1430,7 @@ dictionary_get_value (AST *ast, { const GVariantType *entry, *key, *val; GVariantBuilder builder; - gint i; + size_t i; if (!g_variant_type_is_subtype_of (type, G_VARIANT_TYPE_DICTIONARY)) return ast_type_error (ast, type, error); @@ -1456,12 +1471,12 @@ static void dictionary_free (AST *ast) { Dictionary *dict = (Dictionary *) ast; - gint n_children; + size_t n_children; - if (dict->n_children > -1) - n_children = dict->n_children; - else + if (dict->n_children == DICTIONARY_N_CHILDREN_FREESTANDING_ENTRY) n_children = 1; + else + n_children = dict->n_children; ast_array_free (dict->keys, n_children); ast_array_free (dict->values, n_children); @@ -1479,7 +1494,7 @@ dictionary_parse (TokenStream *stream, maybe_wrapper, dictionary_get_value, dictionary_free }; - gint n_keys, n_values; + size_t n_keys, n_values; gboolean only_one; Dictionary *dict; AST *first; @@ -1522,7 +1537,7 @@ dictionary_parse (TokenStream *stream, goto error; g_assert (n_keys == 1 && n_values == 1); - dict->n_children = -1; + dict->n_children = DICTIONARY_N_CHILDREN_FREESTANDING_ENTRY; return (AST *) dict; } @@ -1555,6 +1570,7 @@ dictionary_parse (TokenStream *stream, } g_assert (n_keys == n_values); + g_assert (n_keys != DICTIONARY_N_CHILDREN_FREESTANDING_ENTRY); dict->n_children = n_keys; return (AST *) dict; @@ -1637,9 +1653,9 @@ string_free (AST *ast) */ static gboolean unicode_unescape (const gchar *src, - gint *src_ofs, + size_t *src_ofs, gchar *dest, - gint *dest_ofs, + size_t *dest_ofs, gsize length, SourceRef *ref, GError **error) @@ -1700,7 +1716,7 @@ string_parse (TokenStream *stream, gsize length; gchar quote; gchar *str; - gint i, j; + size_t i, j; token_stream_start_ref (stream, &ref); token = token_stream_get (stream); @@ -1833,7 +1849,7 @@ bytestring_parse (TokenStream *stream, gsize length; gchar quote; gchar *str; - gint i, j; + size_t i, j; token_stream_start_ref (stream, &ref); token = token_stream_get (stream); @@ -2757,7 +2773,7 @@ g_variant_builder_add_parsed (GVariantBuilder *builder, static gboolean parse_num (const gchar *num, const gchar *limit, - guint *result) + size_t *result) { gchar *endptr; gint64 bignum; @@ -2767,10 +2783,12 @@ parse_num (const gchar *num, if (endptr != limit) return FALSE; + /* The upper bound here is more restrictive than it technically needs to be, + * but should be enough for any practical situation: */ if (bignum < 0 || bignum > G_MAXINT) return FALSE; - *result = (guint) bignum; + *result = (size_t) bignum; return TRUE; } @@ -2781,7 +2799,7 @@ add_last_line (GString *err, { const gchar *last_nl; gchar *chomped; - gint i; + size_t i; /* This is an error at the end of input. If we have a file * with newlines, that's probably the empty string after the @@ -2926,7 +2944,7 @@ g_variant_parse_error_print_context (GError *error, if (dash == NULL || colon < dash) { - guint point; + size_t point; /* we have a single point */ if (!parse_num (error->message, colon, &point)) @@ -2944,7 +2962,7 @@ g_variant_parse_error_print_context (GError *error, /* We have one or two ranges... */ if (comma && comma < colon) { - guint start1, end1, start2, end2; + size_t start1, end1, start2, end2; const gchar *dash2; /* Two ranges */ @@ -2960,7 +2978,7 @@ g_variant_parse_error_print_context (GError *error, } else { - guint start, end; + size_t start, end; /* One range */ if (!parse_num (error->message, dash, &start) || !parse_num (dash + 1, colon, &end))