From f856ca2b86dcbfd8983fed7b6e9b43cf3ae2a5ad Mon Sep 17 00:00:00 2001 From: Philip Withnall Date: Tue, 25 Nov 2025 19:25:58 +0000 Subject: [PATCH] gvariant-parser: Convert error handling code to use size_t The error handling code allows for printing out the range of input bytes related to a parsing error. This was previously done using `gint`, but the input could be longer than `INT_MAX`, so it should really be done using `size_t`. Spotted while working on #3834. CVE: CVE-2025-14087 Upstream: https://gitlab.gnome.org/GNOME/glib/-/commit/dd333a40aa95819720a01caf6de564cd8a4a6310 Signed-off-by: Philip Withnall (cherry picked from commit dd333a40aa95819720a01caf6de564cd8a4a6310) Signed-off-by: Peter Korsgaard --- glib/gvariant-parser.c | 36 +++++++++++++++++++++++------------- 1 file changed, 23 insertions(+), 13 deletions(-) diff --git a/glib/gvariant-parser.c b/glib/gvariant-parser.c index 6d20db7ef..163e2b586 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) @@ -405,7 +413,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)++; @@ -2743,7 +2751,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; @@ -2753,10 +2761,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; } @@ -2767,7 +2777,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 @@ -2912,7 +2922,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)) @@ -2930,7 +2940,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 */ @@ -2946,7 +2956,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)) -- 2.43.0