diff mbox

[v2,4/4] RFC: qapi: Drop support for qobject_from_jsonf("%"PRId64)

Message ID 1479922617-4400-5-git-send-email-eblake@redhat.com (mailing list archive)
State New, archived
Headers show

Commit Message

Eric Blake Nov. 23, 2016, 5:36 p.m. UTC
The qobject_from_jsonf() function implements a pseudo-printf
language for creating a QObject; however, it is hard-coded to
only parse a subset of formats understood by printf().  In
particular, any use of an int64_t integer works only if the
system's definition of PRId64 matches what the parser expects;
which works on glibc (%lld or %ld depending on 32- vs. 64-bit)
and mingw (%I64d), but not on Mac OS (%qd).  Rather than
enhance the parser, we have already eliminated all clients
that were using int64_t, and therefore all uses of %I64d.  No
one should be using long (%ld), since the size of that type
differs between 32- and 64-bit.

Therefore, reducing the parser to accept ONLY %lld allows us to
still accept 64-bit integers (passed in as long long, not
int64_t), while removing %ld and %I64d support gives us a few
more platforms (more than just the infrequent Mac OS' %qd) that
will fail if a later use picks an unrecognized format string.
There are few enough uses of qobject_from_json[fv]() that it is
easy to audit that all callers in the main code body are
correct, and all remaining callers in the testsuite are covered
by a successful 'make check'.  This patch gives confidence that
the earlier patches are appropriate for 2.8 on Mac OS, but this
particular patch is not hard freeze material, and should be
deferred to 2.9 (or else dynamic JSON pseudo-printf ripped out
in its entirety, rather than just unused formats).

Reported by: G 3 <programmingkidx@gmail.com>
Signed-off-by: Eric Blake <eblake@redhat.com>
---
 qobject/json-lexer.c  | 17 -----------------
 qobject/json-parser.c |  9 ++++-----
 2 files changed, 4 insertions(+), 22 deletions(-)
diff mbox

Patch

diff --git a/qobject/json-lexer.c b/qobject/json-lexer.c
index af4a75e..a5e6570 100644
--- a/qobject/json-lexer.c
+++ b/qobject/json-lexer.c
@@ -61,9 +61,6 @@  enum json_lexer_state {
     IN_ESCAPE,
     IN_ESCAPE_L,
     IN_ESCAPE_LL,
-    IN_ESCAPE_I,
-    IN_ESCAPE_I6,
-    IN_ESCAPE_I64,
     IN_WHITESPACE,
     IN_START,
 };
@@ -230,22 +227,9 @@  static const uint8_t json_lexer[][256] =  {
     },

     [IN_ESCAPE_L] = {
-        ['d'] = JSON_ESCAPE,
         ['l'] = IN_ESCAPE_LL,
     },

-    [IN_ESCAPE_I64] = {
-        ['d'] = JSON_ESCAPE,
-    },
-
-    [IN_ESCAPE_I6] = {
-        ['4'] = IN_ESCAPE_I64,
-    },
-
-    [IN_ESCAPE_I] = {
-        ['6'] = IN_ESCAPE_I6,
-    },
-
     [IN_ESCAPE] = {
         ['d'] = JSON_ESCAPE,
         ['i'] = JSON_ESCAPE,
@@ -253,7 +237,6 @@  static const uint8_t json_lexer[][256] =  {
         ['s'] = JSON_ESCAPE,
         ['f'] = JSON_ESCAPE,
         ['l'] = IN_ESCAPE_L,
-        ['I'] = IN_ESCAPE_I,
     },

     /* top level rule */
diff --git a/qobject/json-parser.c b/qobject/json-parser.c
index c18e48a..86b9d7f 100644
--- a/qobject/json-parser.c
+++ b/qobject/json-parser.c
@@ -461,23 +461,22 @@  static QObject *parse_escape(JSONParserContext *ctxt, va_list *ap)
     token = parser_context_pop_token(ctxt);
     assert(token && token->type == JSON_ESCAPE);

+    /* We only accept a fixed subset of printf. In particular, PRId64
+     * is not guaranteed to work; use long long instead of int64_t. */
     if (!strcmp(token->str, "%p")) {
         return va_arg(*ap, QObject *);
     } else if (!strcmp(token->str, "%i")) {
         return QOBJECT(qbool_from_bool(va_arg(*ap, int)));
     } else if (!strcmp(token->str, "%d")) {
         return QOBJECT(qint_from_int(va_arg(*ap, int)));
-    } else if (!strcmp(token->str, "%ld")) {
-        return QOBJECT(qint_from_int(va_arg(*ap, long)));
-    } else if (!strcmp(token->str, "%lld") ||
-               !strcmp(token->str, "%I64d")) {
+    } else if (!strcmp(token->str, "%lld")) {
         return QOBJECT(qint_from_int(va_arg(*ap, long long)));
     } else if (!strcmp(token->str, "%s")) {
         return QOBJECT(qstring_from_str(va_arg(*ap, const char *)));
     } else if (!strcmp(token->str, "%f")) {
         return QOBJECT(qfloat_from_double(va_arg(*ap, double)));
     }
-    return NULL;
+    assert(false);
 }

 static QObject *parse_literal(JSONParserContext *ctxt)