From a75acc5b29cd4940a1a25a65bcee7432ed8ba2c1 Mon Sep 17 00:00:00 2001 From: Philip Withnall Date: Sun, 29 Mar 2026 19:10:41 +0100 Subject: [PATCH 1/2] gvariant: Fix an off-by-one error in an offset comparison MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This allows a single byte out-of-bounds read off the end of the (potentially untrusted) byte array backing a `GVariant` when it’s being checked for normal form. I can’t see how this could practically be exploited, but it’s certainly a security bug as the `GVariant` normal form checking code is supposed to be robust to malicious inputs. Spotted by linhlhq as #YWH-PGM9867-190, and fix and reproducer provided by them too, thanks. Confirmed and turned into a unit test by me. Signed-off-by: Philip Withnall Fixes: #3915 --- glib/gvariant-serialiser.c | 2 +- glib/tests/gvariant.c | 48 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 49 insertions(+), 1 deletion(-) diff --git a/glib/gvariant-serialiser.c b/glib/gvariant-serialiser.c index 9a2975b33..85f28cdce 100644 --- a/glib/gvariant-serialiser.c +++ b/glib/gvariant-serialiser.c @@ -1248,7 +1248,7 @@ gvs_tuple_is_normal (GVariantSerialised value) while (offset & alignment) { - if (offset > value.size || value.data[offset] != '\0') + if (offset >= value.size || value.data[offset] != '\0') return FALSE; offset++; } diff --git a/glib/tests/gvariant.c b/glib/tests/gvariant.c index c24cd2f3e..0d59779ed 100644 --- a/glib/tests/gvariant.c +++ b/glib/tests/gvariant.c @@ -5646,6 +5646,52 @@ test_normal_checking_tuple_offsets5 (void) g_variant_unref (variant); } +/* This is a regression test that looping over the padding bytes in a short + * (non-normal) tuple doesn’t overflow the input data. + * + * See https://gitlab.gnome.org/GNOME/glib/-/issues/3915 */ +static void +test_normal_checking_tuple_offsets6 (void) +{ + /* + * Type: (ynqiuxthdsog) — 12 members, first member 'y' (byte) has + * alignment 0, second 'n' (int16) has alignment 1. + * With 1 byte of data (0x28), after reading the first byte member, + * offset=1, alignment check for 'n' requires offset to be even, + * so the while loop checks value.data[1] — but size is only 1. + * + * Use heap allocation via GBytes so ASan reports heap-buffer-overflow. + */ + uint8_t *heap_data = NULL; + GBytes *bytes = NULL; + const GVariantType *data_type = G_VARIANT_TYPE ("(ynqiuxthdsog)"); + GVariant *variant = NULL; + GVariant *normal_variant = NULL; + GVariant *expected = NULL; + + g_test_bug ("https://gitlab.gnome.org/GNOME/glib/-/issues/3915"); + + heap_data = g_malloc (1); + heap_data[0] = 0x28; + bytes = g_bytes_new_take (heap_data, 1); + + variant = g_variant_new_from_bytes (data_type, bytes, FALSE); + g_assert_nonnull (variant); + + g_assert_false (g_variant_is_normal_form (variant)); + + normal_variant = g_variant_get_normal_form (variant); + g_assert_nonnull (normal_variant); + + expected = g_variant_new_parsed ("(byte 0x28, int16 0, uint16 0, 0, uint32 0, int64 0, uint64 0, handle 0, 0.0, '', objectpath '/', signature '')"); + g_assert_cmpvariant (expected, variant); + g_assert_cmpvariant (expected, normal_variant); + + g_variant_unref (expected); + g_variant_unref (normal_variant); + g_variant_unref (variant); +} + /* Test that an otherwise-valid serialised GVariant is considered non-normal if * its offset table entries are too wide. * @@ -5899,6 +5945,8 @@ main (int argc, char **argv) test_normal_checking_tuple_offsets4); g_test_add_func ("/gvariant/normal-checking/tuple-offsets5", test_normal_checking_tuple_offsets5); + g_test_add_func ("/gvariant/normal-checking/tuple-offsets6", + test_normal_checking_tuple_offsets6); g_test_add_func ("/gvariant/normal-checking/tuple-offsets/minimal-sized", test_normal_checking_tuple_offsets_minimal_sized); g_test_add_func ("/gvariant/normal-checking/empty-object-path", From bccf3bf4cad47dd7de29f41bde7a7cfdd5f77cbc Mon Sep 17 00:00:00 2001 From: RHEL Packaging Agent Date: Mon, 20 Jul 2026 07:02:55 +0000 Subject: [PATCH 2/2] Fix uint8_t -> guint8 for compatibility with GLib 2.80.x The upstream commit used uint8_t which requires , but glib/tests/gvariant.c does not include it. Use guint8 (GLib's equivalent type) instead, consistent with the rest of the file. --- glib/tests/gvariant.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/glib/tests/gvariant.c b/glib/tests/gvariant.c index 0d59779ed..637bd07bc 100644 --- a/glib/tests/gvariant.c +++ b/glib/tests/gvariant.c @@ -5662,7 +5662,7 @@ test_normal_checking_tuple_offsets6 (void) * * Use heap allocation via GBytes so ASan reports heap-buffer-overflow. */ - uint8_t *heap_data = NULL; + guint8 *heap_data = NULL; GBytes *bytes = NULL; const GVariantType *data_type = G_VARIANT_TYPE ("(ynqiuxthdsog)"); GVariant *variant = NULL;