mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2024-12-25 23:16:14 +01:00
gvariant: Fix checking arithmetic for tuple element ends
When checking whether a serialised GVariant tuple is in normal form, it’s possible for `offset_ptr -= offset_size` to underflow and wrap around, resulting in gvs_read_unaligned_le() reading memory outside the serialised GVariant bounds. See §(Tuples) in gvariant-serialiser.c for the documentation on how tuples are serialised. Briefly, all variable-length elements in the tuple have an offset to their end stored in an array of offsets at the end of the tuple. The width of each offset is in offset_size. offset_ptr is added to the start of the serialised tuple to get the offset which is currently being examined. The offset array is in reverse order compared to the tuple elements, hence the subtraction. The bug can be triggered if a tuple contains a load of variable-length elements, each of whose length is actually zero (i.e. empty arrays). Includes a unit test. oss-fuzz#9801 Signed-off-by: Philip Withnall <withnall@endlessm.com>
This commit is contained in:
parent
da512adc34
commit
eb7c9adc3b
@ -1065,6 +1065,9 @@ gvs_tuple_is_normal (GVariantSerialised value)
|
||||
break;
|
||||
|
||||
case G_VARIANT_MEMBER_ENDING_OFFSET:
|
||||
if (offset_ptr < offset_size)
|
||||
return FALSE;
|
||||
|
||||
offset_ptr -= offset_size;
|
||||
|
||||
if (offset_ptr < offset)
|
||||
|
@ -4631,6 +4631,30 @@ test_stack_dict_init (void)
|
||||
g_variant_unref (variant);
|
||||
}
|
||||
|
||||
/* Test checking arbitrary binary data for normal form. This time, it’s a tuple
|
||||
* with invalid element ends. */
|
||||
static void
|
||||
test_normal_checking_tuples (void)
|
||||
{
|
||||
const guint8 data[] = {
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00,
|
||||
'a', '(', 'a', 'o', 'a', 'o', 'a', 'a', 'o', 'a', 'a', 'o', ')'
|
||||
};
|
||||
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)
|
||||
{
|
||||
@ -4692,5 +4716,9 @@ main (int argc, char **argv)
|
||||
|
||||
g_test_add_func ("/gvariant/stack-builder-init", test_stack_builder_init);
|
||||
g_test_add_func ("/gvariant/stack-dict-init", test_stack_dict_init);
|
||||
|
||||
g_test_add_func ("/gvariant/normal-checking/tuples",
|
||||
test_normal_checking_tuples);
|
||||
|
||||
return g_test_run ();
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user