All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Marc-André Lureau" <marcandre.lureau@redhat.com>
To: qemu-devel@nongnu.org
Cc: eblake@redhat.com, armbru@redhat.com,
	"Marc-André Lureau" <marcandre.lureau@redhat.com>
Subject: [Qemu-devel] [PATCH 07/17] json: learn to parse uint64 numbers
Date: Tue,  9 May 2017 20:35:49 +0300	[thread overview]
Message-ID: <20170509173559.31598-8-marcandre.lureau@redhat.com> (raw)
In-Reply-To: <20170509173559.31598-1-marcandre.lureau@redhat.com>

Switch strtoll() usage to qemu_strtoi64() helper while at it.

Replace temporarily the error in qnum_get_int() with values >INT64_MAX
until the visitor is updated.

Add a few tests for large numbers.

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
 qobject/json-lexer.c               |  4 ++++
 qobject/json-parser.c              | 30 ++++++++++++++++++++++--------
 qobject/qnum.c                     |  4 ++--
 tests/check-qjson.c                | 28 ++++++++++++++++++++++++++++
 tests/check-qnum.c                 |  9 +++++----
 tests/test-qobject-input-visitor.c |  7 ++-----
 6 files changed, 63 insertions(+), 19 deletions(-)

diff --git a/qobject/json-lexer.c b/qobject/json-lexer.c
index af4a75e05b..a0beb0b106 100644
--- a/qobject/json-lexer.c
+++ b/qobject/json-lexer.c
@@ -227,15 +227,18 @@ static const uint8_t json_lexer[][256] =  {
     /* escape */
     [IN_ESCAPE_LL] = {
         ['d'] = JSON_ESCAPE,
+        ['u'] = JSON_ESCAPE,
     },
 
     [IN_ESCAPE_L] = {
         ['d'] = JSON_ESCAPE,
+        ['u'] = JSON_ESCAPE,
         ['l'] = IN_ESCAPE_LL,
     },
 
     [IN_ESCAPE_I64] = {
         ['d'] = JSON_ESCAPE,
+        ['u'] = JSON_ESCAPE,
     },
 
     [IN_ESCAPE_I6] = {
@@ -247,6 +250,7 @@ static const uint8_t json_lexer[][256] =  {
     },
 
     [IN_ESCAPE] = {
+        ['u'] = JSON_ESCAPE,
         ['d'] = JSON_ESCAPE,
         ['i'] = JSON_ESCAPE,
         ['p'] = JSON_ESCAPE,
diff --git a/qobject/json-parser.c b/qobject/json-parser.c
index f431854ba1..fa15c762d3 100644
--- a/qobject/json-parser.c
+++ b/qobject/json-parser.c
@@ -12,6 +12,7 @@
  */
 
 #include "qemu/osdep.h"
+#include "qemu/cutils.h"
 #include "qapi/error.h"
 #include "qemu-common.h"
 #include "qapi/qmp/types.h"
@@ -472,6 +473,13 @@ static QObject *parse_escape(JSONParserContext *ctxt, va_list *ap)
     } else if (!strcmp(token->str, "%lld") ||
                !strcmp(token->str, "%I64d")) {
         return QOBJECT(qnum_from_int(va_arg(*ap, long long)));
+    } else if (!strcmp(token->str, "%u")) {
+        return QOBJECT(qnum_from_uint(va_arg(*ap, unsigned int)));
+    } else if (!strcmp(token->str, "%lu")) {
+        return QOBJECT(qnum_from_uint(va_arg(*ap, unsigned long)));
+    } else if (!strcmp(token->str, "%llu") ||
+               !strcmp(token->str, "%I64u")) {
+        return QOBJECT(qnum_from_uint(va_arg(*ap, unsigned long long)));
     } else if (!strcmp(token->str, "%s")) {
         return QOBJECT(qstring_from_str(va_arg(*ap, const char *)));
     } else if (!strcmp(token->str, "%f")) {
@@ -494,22 +502,28 @@ static QObject *parse_literal(JSONParserContext *ctxt)
         /* A possibility exists that this is a whole-valued float where the
          * fractional part was left out due to being 0 (.0). It's not a big
          * deal to treat these as ints in the parser, so long as users of the
-         * resulting QObject know to expect a QNum in place of a QNum in
-         * cases like these.
+         * resulting QObject know to expect a QNum that will handle
+         * implicit conversions to the expected type.
          *
-         * However, in some cases these values will overflow/underflow a
-         * QNum/int64 container, thus we should assume these are to be handled
-         * as QNums/doubles rather than silently changing their values.
+         * However, in some cases these values will overflow/underflow
+         * a QNum/int64 container, thus we should assume these are to
+         * be handled as QNum/uint64 or QNums/doubles rather than
+         * silently changing their values.
          *
-         * strtoll() indicates these instances by setting errno to ERANGE
+         * qemu_strto*() indicates these instances by setting errno to ERANGE
          */
         int64_t value;
+        uint64_t uvalue;
 
-        errno = 0; /* strtoll doesn't set errno on success */
-        value = strtoll(token->str, NULL, 10);
+        qemu_strtoi64(token->str, NULL, 10, &value);
         if (errno != ERANGE) {
             return QOBJECT(qnum_from_int(value));
         }
+
+        qemu_strtou64(token->str, NULL, 10, &uvalue);
+        if (errno != ERANGE) {
+            return QOBJECT(qnum_from_uint(uvalue));
+        }
         /* fall through to JSON_FLOAT */
     }
     case JSON_FLOAT:
diff --git a/qobject/qnum.c b/qobject/qnum.c
index be6307accf..2f87952db8 100644
--- a/qobject/qnum.c
+++ b/qobject/qnum.c
@@ -76,8 +76,8 @@ int64_t qnum_get_int(const QNum *qn, Error **errp)
         return qn->u.i64;
     case QNUM_U64:
         if (qn->u.u64 > INT64_MAX) {
-            error_setg(errp, "The number is too large, use qnum_get_uint()");
-            return 0;
+            /* temporarily accepts to cast to i64 until visitor is switched */
+            error_report("The number is too large, use qnum_get_uint()");
         }
         return qn->u.u64;
     case QNUM_DOUBLE:
diff --git a/tests/check-qjson.c b/tests/check-qjson.c
index c432aebf13..57c2366dc3 100644
--- a/tests/check-qjson.c
+++ b/tests/check-qjson.c
@@ -904,6 +904,33 @@ static void simple_number(void)
     }
 }
 
+static void large_number(void)
+{
+    const char *maxu64 = "18446744073709551615"; /* 2^64-1 */
+    const char *gtu64 = "18446744073709551616"; /* 2^64 */
+    QNum *qnum;
+    QString *str;
+
+    qnum = qobject_to_qnum(qobject_from_json(maxu64, &error_abort));
+    g_assert(qnum);
+    g_assert_cmpuint(qnum_get_uint(qnum, &error_abort),
+                     ==, 18446744073709551615U);
+
+    str = qobject_to_json(QOBJECT(qnum));
+    g_assert_cmpstr(qstring_get_str(str), ==, maxu64);
+    QDECREF(str);
+    QDECREF(qnum);
+
+    qnum = qobject_to_qnum(qobject_from_json(gtu64, &error_abort));
+    g_assert(qnum);
+    g_assert_cmpfloat(qnum_get_double(qnum), ==, 18446744073709551616.0);
+
+    str = qobject_to_json(QOBJECT(qnum));
+    g_assert_cmpstr(qstring_get_str(str), ==, gtu64);
+    QDECREF(str);
+    QDECREF(qnum);
+}
+
 static void float_number(void)
 {
     int i;
@@ -1468,6 +1495,7 @@ int main(int argc, char **argv)
     g_test_add_func("/literals/string/vararg", vararg_string);
 
     g_test_add_func("/literals/number/simple", simple_number);
+    g_test_add_func("/literals/number/large", large_number);
     g_test_add_func("/literals/number/float", float_number);
     g_test_add_func("/literals/number/vararg", vararg_number);
 
diff --git a/tests/check-qnum.c b/tests/check-qnum.c
index 8199546f99..9a22af3d0e 100644
--- a/tests/check-qnum.c
+++ b/tests/check-qnum.c
@@ -107,10 +107,11 @@ static void qnum_get_uint_test(void)
     error_free_or_abort(&err);
     QDECREF(qn);
 
-    qn = qnum_from_uint(-1ULL);
-    qnum_get_int(qn, &err);
-    error_free_or_abort(&err);
-    QDECREF(qn);
+    /* temporarily disabled until visitor is switched */
+    /* qn = qnum_from_uint(-1ULL); */
+    /* qnum_get_int(qn, &err); */
+    /* error_free_or_abort(&err); */
+    /* QDECREF(qn); */
 
     /* invalid case */
     qn = qnum_from_double(0.42);
diff --git a/tests/test-qobject-input-visitor.c b/tests/test-qobject-input-visitor.c
index 5df62c4f9e..276a6b4427 100644
--- a/tests/test-qobject-input-visitor.c
+++ b/tests/test-qobject-input-visitor.c
@@ -119,7 +119,6 @@ static void test_visitor_in_int(TestInputVisitorData *data,
 static void test_visitor_in_uint(TestInputVisitorData *data,
                                 const void *unused)
 {
-    Error *err = NULL;
     uint64_t res = 0;
     int value = 42;
     Visitor *v;
@@ -136,12 +135,10 @@ static void test_visitor_in_uint(TestInputVisitorData *data,
     visit_type_uint64(v, NULL, &res, &error_abort);
     g_assert_cmpuint(res, ==, (uint64_t)-value);
 
-    /* BUG: value between INT64_MAX+1 and UINT64_MAX rejected */
-
     v = visitor_input_test_init(data, "18446744073709551574");
 
-    visit_type_uint64(v, NULL, &res, &err);
-    error_free_or_abort(&err);
+    visit_type_uint64(v, NULL, &res, &error_abort);
+    g_assert_cmpuint(res, ==, 18446744073709551574U);
 }
 
 static void test_visitor_in_int_overflow(TestInputVisitorData *data,
-- 
2.13.0.rc1.16.gd80b50c3f

  parent reply	other threads:[~2017-05-09 17:38 UTC|newest]

Thread overview: 70+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-05-09 17:35 [Qemu-devel] [PATCH 00/17] qobject/qapi: add uint type Marc-André Lureau
2017-05-09 17:35 ` [Qemu-devel] [PATCH 01/17] qdev: remove PropertyInfo.qtype field Marc-André Lureau
2017-05-09 18:40   ` Eric Blake
2017-05-11 11:59     ` Markus Armbruster
2017-05-11 12:07       ` Paolo Bonzini
2017-05-09 17:35 ` [Qemu-devel] [PATCH 02/17] object: fix potential leak in getters Marc-André Lureau
2017-05-09 18:44   ` Eric Blake
2017-05-09 17:35 ` [Qemu-devel] [PATCH 03/17] tests: remove alt num-int cases Marc-André Lureau
2017-05-09 18:51   ` Eric Blake
2017-05-11 12:34     ` Markus Armbruster
2017-05-22 17:03   ` Markus Armbruster
2017-05-30  3:40     ` Fam Zheng
2017-05-30 14:17       ` Eric Blake
2017-05-09 17:35 ` [Qemu-devel] [PATCH 04/17] qapi: merge QInt and QFloat in QNum Marc-André Lureau
2017-05-11 14:29   ` Markus Armbruster
2017-05-11 15:09     ` Eric Blake
2017-05-30  7:32     ` Marc-André Lureau
2017-05-30 14:19       ` Eric Blake
2017-05-30 14:23       ` Markus Armbruster
2017-05-30 15:36         ` Marc-André Lureau
2017-06-02  6:30           ` Markus Armbruster
2017-06-02 11:18             ` Marc-André Lureau
2017-05-12  6:30   ` Markus Armbruster
2017-05-12 13:00     ` Luiz Capitulino
2017-05-15  7:00       ` Markus Armbruster
2017-05-12  7:37   ` Markus Armbruster
2017-05-12 13:03     ` Luiz Capitulino
2017-05-15  6:35       ` Markus Armbruster
2017-05-09 17:35 ` [Qemu-devel] [PATCH 05/17] qapi: remove promote_int Marc-André Lureau
2017-05-11 17:30   ` Markus Armbruster
2017-05-09 17:35 ` [Qemu-devel] [PATCH 06/17] qnum: add uint type Marc-André Lureau
2017-05-15  7:27   ` Markus Armbruster
2017-05-09 17:35 ` Marc-André Lureau [this message]
2017-05-15 13:59   ` [Qemu-devel] [PATCH 07/17] json: learn to parse uint64 numbers Markus Armbruster
2017-05-30 11:35     ` Marc-André Lureau
2017-05-30 14:22       ` Eric Blake
2017-05-31  7:38         ` Marc-André Lureau
2017-05-31 10:08       ` Markus Armbruster
2017-05-31 10:53         ` Marc-André Lureau
2017-05-09 17:35 ` [Qemu-devel] [PATCH 08/17] qapi: update the qobject visitor to use QUInt Marc-André Lureau
2017-05-16 17:31   ` Markus Armbruster
2017-05-17 16:26     ` Markus Armbruster
2017-05-30 12:28     ` Marc-André Lureau
2017-05-31 13:10       ` Markus Armbruster
2017-05-09 17:35 ` [Qemu-devel] [PATCH 09/17] qnum: fix get_int() with values > INT64_MAX Marc-André Lureau
2017-05-16 17:35   ` Markus Armbruster
2017-05-09 17:35 ` [Qemu-devel] [PATCH 10/17] object: add uint property setter/getter Marc-André Lureau
2017-05-16 17:41   ` Markus Armbruster
2017-05-09 17:35 ` [Qemu-devel] [PATCH 11/17] object: use more specific property type names Marc-André Lureau
2017-05-17  8:49   ` Markus Armbruster
2017-05-30 13:58     ` Marc-André Lureau
2017-05-31 13:18       ` Markus Armbruster
2017-05-09 17:35 ` [Qemu-devel] [PATCH 12/17] qdev: use int and uint properties as appropriate Marc-André Lureau
2017-05-17 11:09   ` Markus Armbruster
2017-05-09 17:35 ` [Qemu-devel] [PATCH 13/17] qdev: use appropriate getter/setters type Marc-André Lureau
2017-05-17 17:42   ` Markus Armbruster
2017-05-09 17:35 ` [Qemu-devel] [PATCH 14/17] acpi: fix s3/s4 disabled type Marc-André Lureau
2017-05-13 20:49   ` Philippe Mathieu-Daudé
2017-05-18 12:57   ` Markus Armbruster
2017-05-31 11:10     ` Marc-André Lureau
2017-05-31 13:23       ` Markus Armbruster
2017-05-31 13:26         ` Marc-André Lureau
2017-05-09 17:35 ` [Qemu-devel] [PATCH 15/17] Use uint property getter/setter where appropriate Marc-André Lureau
2017-05-18 15:20   ` Markus Armbruster
2017-05-31 12:22     ` Marc-André Lureau
2017-05-09 17:35 ` [Qemu-devel] [PATCH 16/17] RFC: qdict: add uint Marc-André Lureau
2017-05-18 15:27   ` Markus Armbruster
2017-05-09 17:35 ` [Qemu-devel] [PATCH 17/17] qobject: move dump_qobject() from block/ to qobject/ Marc-André Lureau
2017-05-13 21:41 ` [Qemu-devel] [PATCH 00/17] qobject/qapi: add uint type no-reply
2017-05-18 15:39 ` Markus Armbruster

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20170509173559.31598-8-marcandre.lureau@redhat.com \
    --to=marcandre.lureau@redhat.com \
    --cc=armbru@redhat.com \
    --cc=eblake@redhat.com \
    --cc=qemu-devel@nongnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.