Commit 7eedcd76 authored by Philip Withnall's avatar Philip Withnall

gvariant: Check tuple offsets against serialised data length

As with the previous commit, when getting a child from a serialised
tuple, check its offset against the length of the serialised data of the
tuple (excluding the length of the offset table). The offset was already
checked against the length of the entire serialised tuple (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's avatarPhilip Withnall <withnall@endlessm.com>
parent 5e0b12df
......@@ -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;
......
......@@ -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);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment