From 7801e977776e400f528fdec8e9c236daf2f4576a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Andreas=20F=C3=A4rber?= <afaerber@suse.de>
Date: Thu, 24 Sep 2015 19:21:11 +0200
Subject: [PATCH] string-input-visitor: Fix uint64 parsing
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

All integers would get parsed by strtoll(), not handling the case of
UINT64 properties with the most significient bit set.

Implement a .type_uint64 visitor callback, reusing the existing
parse_str() code through a new argument, using strtoull().

As this is a bug fix, it intentionally ignores checkpatch warnings to
prefer the use of qemu_strto[u]ll() over strto[u]ll().

Cc: qemu-stable@nongnu.org
Signed-off-by: Andreas Färber <afaerber@suse.de>
[AF: Changed back argument order from SP2, reverted to DO_UPCAST()]
Signed-off-by: Andreas Färber <afaerber@suse.de>
---
 qapi/string-input-visitor.c | 61 ++++++++++++++++++++++++++++++++++---
 1 file changed, 56 insertions(+), 5 deletions(-)

diff --git a/qapi/string-input-visitor.c b/qapi/string-input-visitor.c
index d8a8db02ed..1f5cf706d1 100644
--- a/qapi/string-input-visitor.c
+++ b/qapi/string-input-visitor.c
@@ -37,7 +37,7 @@ static void free_range(void *range, void *dummy)
     g_free(range);
 }
 
-static void parse_str(StringInputVisitor *siv, Error **errp)
+static void parse_str(StringInputVisitor *siv, bool u64, Error **errp)
 {
     char *str = (char *) siv->string;
     long long start, end;
@@ -50,7 +50,11 @@ static void parse_str(StringInputVisitor *siv, Error **errp)
 
     do {
         errno = 0;
-        start = strtoll(str, &endptr, 0);
+        if (u64) {
+            start = strtoull(str, &endptr, 0);
+        } else {
+            start = strtoll(str, &endptr, 0);
+        }
         if (errno == 0 && endptr > str) {
             if (*endptr == '\0') {
                 cur = g_malloc0(sizeof(*cur));
@@ -63,7 +67,11 @@ static void parse_str(StringInputVisitor *siv, Error **errp)
             } else if (*endptr == '-') {
                 str = endptr + 1;
                 errno = 0;
-                end = strtoll(str, &endptr, 0);
+                if (u64) {
+                    end = strtoull(str, &endptr, 0);
+                } else {
+                    end = strtoll(str, &endptr, 0);
+                }
                 if (errno == 0 && endptr > str && start <= end &&
                     (start > INT64_MAX - 65536 ||
                      end < start + 65536)) {
@@ -122,7 +130,7 @@ start_list(Visitor *v, const char *name, Error **errp)
 {
     StringInputVisitor *siv = DO_UPCAST(StringInputVisitor, visitor, v);
 
-    parse_str(siv, errp);
+    parse_str(siv, false, errp);
 
     siv->cur_range = g_list_first(siv->ranges);
     if (siv->cur_range) {
@@ -190,7 +198,7 @@ static void parse_type_int(Visitor *v, int64_t *obj, const char *name,
         return;
     }
 
-    parse_str(siv, errp);
+    parse_str(siv, false, errp);
 
     if (!siv->ranges) {
         goto error;
@@ -221,6 +229,48 @@ error:
               "an int64 value or range");
 }
 
+static void parse_type_uint64(Visitor *v, uint64_t *obj, const char *name,
+                              Error **errp)
+{
+    StringInputVisitor *siv = DO_UPCAST(StringInputVisitor, visitor, v);
+
+    if (!siv->string) {
+        error_setg(errp, QERR_INVALID_PARAMETER_TYPE, name ? name : "null",
+                   "integer");
+        return;
+    }
+
+    parse_str(siv, true, errp);
+
+    if (!siv->ranges) {
+        goto error;
+    }
+
+    if (!siv->cur_range) {
+        Range *r;
+
+        siv->cur_range = g_list_first(siv->ranges);
+        if (!siv->cur_range) {
+            goto error;
+        }
+
+        r = siv->cur_range->data;
+        if (!r) {
+            goto error;
+        }
+
+        siv->cur = r->begin;
+    }
+
+    *obj = siv->cur;
+    siv->cur++;
+    return;
+
+error:
+    error_setg(errp, QERR_INVALID_PARAMETER_VALUE, name,
+               "a uint64 value or range");
+}
+
 static void parse_type_size(Visitor *v, uint64_t *obj, const char *name,
                             Error **errp)
 {
@@ -332,6 +382,7 @@ StringInputVisitor *string_input_visitor_new(const char *str)
 
     v->visitor.type_enum = input_type_enum;
     v->visitor.type_int = parse_type_int;
+    v->visitor.type_uint64 = parse_type_uint64;
     v->visitor.type_size = parse_type_size;
     v->visitor.type_bool = parse_type_bool;
     v->visitor.type_str = parse_type_str;
