89 lines
3.5 KiB
Diff
89 lines
3.5 KiB
Diff
|
|
From c927c59a8426be62f9e9b19e40c862f88b4c17be Mon Sep 17 00:00:00 2001
|
|||
|
|
From: Philip Withnall <withnall@endlessm.com>
|
|||
|
|
Date: Tue, 5 Feb 2019 15:50:15 +0000
|
|||
|
|
Subject: [PATCH 563/682] gvariant-parser: Fix error handling when type
|
|||
|
|
coalescing fails
|
|||
|
|
|
|||
|
|
When parsing GVariant text format strings, we do a limited form of type
|
|||
|
|
inference. The algorithm for type inference for nested array child types
|
|||
|
|
is not complete, however (and making it complete, at least with a naive
|
|||
|
|
implementation, would make it O(N^2), which is not worth it) and so some
|
|||
|
|
text format arrays were triggering an assertion failure in the error
|
|||
|
|
handling code.
|
|||
|
|
|
|||
|
|
Fix that by making the error handling code a little more relaxed, in the
|
|||
|
|
knowledge that our type inference algorithm is not complete. See the
|
|||
|
|
comment added to the code.
|
|||
|
|
|
|||
|
|
This includes a test case, provided by oss-fuzz.
|
|||
|
|
|
|||
|
|
oss-fuzz#11578
|
|||
|
|
|
|||
|
|
Signed-off-by: Philip Withnall <withnall@endlessm.com>
|
|||
|
|
---
|
|||
|
|
glib/gvariant-parser.c | 28 ++++++++++++++++++++++++++--
|
|||
|
|
glib/tests/gvariant.c | 1 +
|
|||
|
|
2 files changed, 27 insertions(+), 2 deletions(-)
|
|||
|
|
|
|||
|
|
diff --git a/glib/gvariant-parser.c b/glib/gvariant-parser.c
|
|||
|
|
index 2b02ec90f..3b4956a9c 100644
|
|||
|
|
--- a/glib/gvariant-parser.c
|
|||
|
|
+++ b/glib/gvariant-parser.c
|
|||
|
|
@@ -671,6 +671,20 @@ ast_array_get_pattern (AST **array,
|
|||
|
|
gchar *pattern;
|
|||
|
|
gint i;
|
|||
|
|
|
|||
|
|
+ /* Find the pattern which applies to all children in the array, by l-folding a
|
|||
|
|
+ * coalesce operation. This will not always work: for example, the GVariant:
|
|||
|
|
+ * [[0], [], [nothing]]
|
|||
|
|
+ * has patterns:
|
|||
|
|
+ * MaMN, Ma*, Mam*
|
|||
|
|
+ * which pairwise coalesce as:
|
|||
|
|
+ * MaMN + Ma* = MaN
|
|||
|
|
+ * MaN + Mam* = (doesn’t coalesce)
|
|||
|
|
+ *
|
|||
|
|
+ * However, the pattern MamN coalesces with all three child patterns. Finding
|
|||
|
|
+ * this pattern would require trying all O(n_items^2) pairs, though, which is
|
|||
|
|
+ * expensive. Just let it fail, and require the user to provide type
|
|||
|
|
+ * annotations.
|
|||
|
|
+ */
|
|||
|
|
pattern = ast_get_pattern (array[0], error);
|
|||
|
|
|
|||
|
|
if (pattern == NULL)
|
|||
|
|
@@ -705,8 +719,18 @@ ast_array_get_pattern (AST **array,
|
|||
|
|
gchar *tmp2;
|
|||
|
|
gchar *m;
|
|||
|
|
|
|||
|
|
- /* if 'j' reaches 'i' then we failed to find the pair */
|
|||
|
|
- g_assert (j < i);
|
|||
|
|
+ /* if 'j' reaches 'i' then we failed to find the pair, which can
|
|||
|
|
+ * happen due to only trying pairwise coalesces in order rather
|
|||
|
|
+ * than between all pairs (see above). so just report an error
|
|||
|
|
+ * for i. */
|
|||
|
|
+ if (j >= i)
|
|||
|
|
+ {
|
|||
|
|
+ ast_set_error (array[i], error, NULL,
|
|||
|
|
+ G_VARIANT_PARSE_ERROR_NO_COMMON_TYPE,
|
|||
|
|
+ "unable to find a common type");
|
|||
|
|
+ g_free (tmp);
|
|||
|
|
+ return NULL;
|
|||
|
|
+ }
|
|||
|
|
|
|||
|
|
tmp2 = ast_get_pattern (array[j], NULL);
|
|||
|
|
g_assert (tmp2 != NULL);
|
|||
|
|
diff --git a/glib/tests/gvariant.c b/glib/tests/gvariant.c
|
|||
|
|
index 33caaf04a..80bc7caf4 100644
|
|||
|
|
--- a/glib/tests/gvariant.c
|
|||
|
|
+++ b/glib/tests/gvariant.c
|
|||
|
|
@@ -3943,6 +3943,7 @@ test_parse_failures (void)
|
|||
|
|
"[4, 5, '']", "1-2,7-9:", "common type",
|
|||
|
|
"[[4], [], ['']]", "1-4,10-14:", "common type",
|
|||
|
|
"[[], [4], ['']]", "5-8,10-14:", "common type",
|
|||
|
|
+ "[[0], [], [nothing]]", "10-19:", "common type",
|
|||
|
|
"just", "4:", "expected value",
|
|||
|
|
"nothing", "0-7:", "unable to infer",
|
|||
|
|
"just [4, '']", "6-7,9-11:", "common type",
|
|||
|
|
--
|
|||
|
|
2.19.1
|
|||
|
|
|