[glib: 4/16] gvariant: Check tuple offsets against serialised data length
- From: Philip Withnall <pwithnall src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [glib: 4/16] gvariant: Check tuple offsets against serialised data length
- Date: Tue, 23 Oct 2018 04:30:56 +0000 (UTC)
commit 7eedcd76f7d5b8c98fa60013e1fe6e960bf19df3
Author: Philip Withnall <withnall endlessm com>
Date: Fri Sep 7 22:28:37 2018 +0100
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>
glib/gvariant-serialiser.c | 16 ++++++++++++++--
glib/tests/gvariant.c | 26 ++++++++++++++++++++++++++
2 files changed, 40 insertions(+), 2 deletions(-)
---
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);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]