mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2025-01-27 06:26:15 +01:00
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 <withnall@endlessm.com>
This commit is contained in:
parent
5e0b12df1a
commit
7eedcd76f7
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user