From fe9564fedaeee59e413946884786694c5bda971d Mon Sep 17 00:00:00 2001 From: Philip Withnall Date: Fri, 7 Sep 2018 22:26:05 +0100 Subject: [PATCH] gvariant: Check array offsets against serialised data length MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When getting a child from a serialised variable array, check its offset against the length of the serialised data of the array (excluding the length of the offset table). The offset was already checked against the length of the entire serialised array (including the offset table) — but a child should not be able to start inside the offset table. A test is included. oss-fuzz#9803 Signed-off-by: Philip Withnall --- glib/gvariant-serialiser.c | 2 +- glib/tests/gvariant.c | 26 ++++++++++++++++++++++++++ 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/glib/gvariant-serialiser.c b/glib/gvariant-serialiser.c index fe0bcf0aa..aa71d3c1c 100644 --- a/glib/gvariant-serialiser.c +++ b/glib/gvariant-serialiser.c @@ -694,7 +694,7 @@ gvs_variable_sized_array_get_child (GVariantSerialised value, (offset_size * index_), offset_size); - if (start < end && end <= value.size) + if (start < end && end <= value.size && end <= last_end) { child.data = value.data + start; child.size = end - start; diff --git a/glib/tests/gvariant.c b/glib/tests/gvariant.c index 0d996ae72..673ec676e 100644 --- a/glib/tests/gvariant.c +++ b/glib/tests/gvariant.c @@ -4785,6 +4785,30 @@ test_recursion_limits_array_in_variant (void) g_variant_unref (wrapper_variant); } +/* Test that an array with invalidly large values in its offset table is + * normalised successfully without looping infinitely. */ +static void +test_normal_checking_array_offsets (void) +{ + const guint8 data[] = { + 0x07, 0xe5, 0x00, 0x07, 0x00, 0x07, 0x00, 0x00, + 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'g', + }; + gsize size = sizeof (data); + GVariant *variant = NULL; + GVariant *normal_variant = NULL; + + variant = g_variant_new_from_data (G_VARIANT_TYPE_VARIANT, data, size, + FALSE, NULL, NULL); + g_assert_nonnull (variant); + + normal_variant = g_variant_get_normal_form (variant); + g_assert_nonnull (normal_variant); + + g_variant_unref (normal_variant); + g_variant_unref (variant); +} + int main (int argc, char **argv) { @@ -4853,6 +4877,8 @@ main (int argc, char **argv) g_test_add_func ("/gvariant/normal-checking/tuples", test_normal_checking_tuples); + g_test_add_func ("/gvariant/normal-checking/array-offsets", + test_normal_checking_array_offsets); g_test_add_func ("/gvariant/recursion-limits/variant-in-variant", test_recursion_limits_variant_in_variant);