On Tuesday, 12 September 2017 14:29:15 CEST Richard W.M. Jones wrote:
+/**
+ * Test if the QMP schema contains a particular C<(key, value)> pair
+ * (anywhere). QMP is almost impossible to parse sanely so this is
+ * the minimum we need to detect if C<"locking"> is supported.
+ */
+static int
+qmp_schema_contains (yajl_val tree, const char *key, const char *value)
+{
+ size_t i;
+
+ if (YAJL_IS_OBJECT (tree)) {
+ for (i = 0; i < YAJL_GET_OBJECT(tree)->len; ++i) {
+ const char *k;
+ yajl_val v;
+
+ k = YAJL_GET_OBJECT(tree)->keys[i];
+ v = YAJL_GET_OBJECT(tree)->values[i];
+
+ if (STREQ (k, key) &&
+ YAJL_IS_STRING (v) && STREQ (YAJL_GET_STRING (v), value))
+ return 1;
+ if (qmp_schema_contains (v, key, value))
+ return 1;
+ }
+ }
+ else if (YAJL_IS_ARRAY (tree)) {
+ for (i = 0; i < YAJL_GET_ARRAY(tree)->len; ++i) {
+ yajl_val v;
+
+ v = YAJL_GET_ARRAY(tree)->values[i];
+
+ if (qmp_schema_contains (v, key, value))
+ return 1;
+ }
+ }
+
+ return 0;
+}
This can easily exhaust the stack when trying to parse some
badly-formatted JSON snippet; considering the user can change the
hypervisor, then it can easily become a mild local DoS. A simple
workaround can be to limit the recursion depth, like done in the OCaml
binding to yajl_parse_tree (builder/yajl-c.c).
If the path to the key is known in advance (e.g. root object ->
"return" key -> list -> object with "name" key equal to
"locking"),
then IMHO would be better to just look for that.
--
Pino Toscano