diff --git a/glib/gvariant-serialiser.c b/glib/gvariant-serialiser.c index aa71d3c1c..643894919 100644 --- a/glib/gvariant-serialiser.c +++ b/glib/gvariant-serialiser.c @@ -870,7 +870,7 @@ gvs_tuple_get_child (GVariantSerialised value, const GVariantMemberInfo *member_info; GVariantSerialised child = { 0, }; gsize offset_size; - gsize start, end; + gsize start, end, last_end; member_info = g_variant_type_info_member_info (value.type_info, index_); child.type_info = g_variant_type_info_ref (member_info->type_info); @@ -940,7 +940,19 @@ gvs_tuple_get_child (GVariantSerialised value, offset_size * (member_info->i + 2), offset_size); - if (start < end && end <= value.size) + /* The child should not extend into the offset table. */ + if (index_ != g_variant_type_info_n_members (value.type_info) - 1) + { + GVariantSerialised last_child; + last_child = gvs_tuple_get_child (value, + g_variant_type_info_n_members (value.type_info) - 1); + last_end = last_child.data + last_child.size - value.data; + g_variant_type_info_unref (last_child.type_info); + } + else + last_end = end; + + 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 1ab535534..be9920c1e 100644 --- a/glib/tests/gvariant.c +++ b/glib/tests/gvariant.c @@ -4841,6 +4841,30 @@ test_normal_checking_array_offsets (void) g_variant_unref (variant); } +/* Test that a tuple with invalidly large values in its offset table is + * normalised successfully without looping infinitely. */ +static void +test_normal_checking_tuple_offsets (void) +{ + const guint8 data[] = { + 0x07, 0xe5, 0x00, 0x07, 0x00, 0x07, + '(', 'a', 's', 'a', 's', 'a', 's', 'a', 's', 'a', 's', 'a', 's', ')', + }; + 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) { @@ -4911,6 +4935,8 @@ main (int argc, char **argv) test_normal_checking_tuples); g_test_add_func ("/gvariant/normal-checking/array-offsets", test_normal_checking_array_offsets); + g_test_add_func ("/gvariant/normal-checking/tuple-offsets", + test_normal_checking_tuple_offsets); g_test_add_func ("/gvariant/recursion-limits/variant-in-variant", test_recursion_limits_variant_in_variant);