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
|
||
|