All of lore.kernel.org
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH 00/24] QemuOpts util/cutils: Fix and clean up number conversions
@ 2017-02-14 10:25 Markus Armbruster
  2017-02-14 10:25 ` [Qemu-devel] [PATCH 01/24] tests/test-qemu-opts: Cover qemu_opts_parse() Markus Armbruster
                   ` (25 more replies)
  0 siblings, 26 replies; 79+ messages in thread
From: Markus Armbruster @ 2017-02-14 10:25 UTC (permalink / raw)
  To: qemu-devel

QemuOpts has its own code to convert strings to numbers, and being
QemuOpts, it gets it wrong.  util/cutils is less wrong.  Fix it up
some, and reuse it for QemuOpts.

Markus Armbruster (24):
  tests/test-qemu-opts: Cover qemu_opts_parse()
  QemuOpts: Assert value string isn't null
  tests/test-cutils: Add missing qemu_strtol()... endptr checks
  tests/test-cutils: Clean up qemu_strtoul() result checks
  util/cutils: Rewrite documentation of qemu_strtol() & friends
  util/cutils: Rename qemu_strtoll(), qemu_strtoull()
  util/cutils: Clean up variable names around qemu_strtol()
  util/cutils: Clean up control flow around qemu_strtol() a bit
  QemuOpts: Fix to reject numbers that overflow uint64_t
  tests/test-cutils: Add missing qemu_strtosz()... endptr checks
  tests/test-cutils: Cover qemu_strtosz() invalid input
  tests/test-cutils: Cover qemu_strtosz() with trailing crap
  tests/test-cutils: Cover qemu_strtosz() around range limits
  util/cutils: New qemu_strtosz_metric()
  util/cutils: Rename qemu_strtosz() to qemu_strtosz_mebi()
  util/cutils: New qemu_strtosz()
  util/cutils: Drop QEMU_STRTOSZ_DEFSUFFIX_* macros
  tests/test-cutils: Use qemu_strtosz() more often
  tests/test-cutils: Drop suffix from test_qemu_strtosz_simple()
  qemu-img: Wrap cvtnum() around qemu_strtosz()
  util/cutils: Let qemu_strtosz*() optionally reject trailing crap
  util/cutils: Return qemu_strtosz*() error and value separately
  util/cutils: Change qemu_strtosz*() from int64_t to uint64_t
  QemuOpts: Fix checking of sizes for overflow and trailing crap

 hmp.c                  |  11 +-
 hw/misc/ivshmem.c      |   9 +-
 include/qemu/cutils.h  |  29 +--
 monitor.c              |   7 +-
 qapi/opts-visitor.c    |  11 +-
 qemu-img.c             |  62 ++---
 qemu-io-cmds.c         |  16 +-
 qobject/qdict.c        |   2 +-
 qtest.c                |  34 +--
 target/i386/cpu.c      |   9 +-
 tests/test-cutils.c    | 642 ++++++++++++++++++++++++++++++++-----------------
 tests/test-qemu-opts.c | 289 +++++++++++++++++++++-
 util/cutils.c          | 239 +++++++++---------
 util/log.c             |   4 +-
 util/qemu-option.c     |  87 +++----
 15 files changed, 959 insertions(+), 492 deletions(-)

-- 
2.7.4

^ permalink raw reply	[flat|nested] 79+ messages in thread

* [Qemu-devel] [PATCH 01/24] tests/test-qemu-opts: Cover qemu_opts_parse()
  2017-02-14 10:25 [Qemu-devel] [PATCH 00/24] QemuOpts util/cutils: Fix and clean up number conversions Markus Armbruster
@ 2017-02-14 10:25 ` Markus Armbruster
  2017-02-14 19:48   ` Eric Blake
  2017-02-14 10:25 ` [Qemu-devel] [PATCH 02/24] QemuOpts: Assert value string isn't null Markus Armbruster
                   ` (24 subsequent siblings)
  25 siblings, 1 reply; 79+ messages in thread
From: Markus Armbruster @ 2017-02-14 10:25 UTC (permalink / raw)
  To: qemu-devel

The new tests demonstrate a few bugs, all clearly marked.

Signed-off-by: Markus Armbruster <armbru@redhat.com>
---
 tests/test-qemu-opts.c | 294 ++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 292 insertions(+), 2 deletions(-)

diff --git a/tests/test-qemu-opts.c b/tests/test-qemu-opts.c
index a505a3e..f4426bb 100644
--- a/tests/test-qemu-opts.c
+++ b/tests/test-qemu-opts.c
@@ -8,6 +8,7 @@
  */
 
 #include "qemu/osdep.h"
+#include "qemu/cutils.h"
 #include "qapi/error.h"
 #include "qapi/qmp/qstring.h"
 #include "qemu/config-file.h"
@@ -29,6 +30,9 @@ static QemuOptsList opts_list_01 = {
         },{
             .name = "number1",
             .type = QEMU_OPT_NUMBER,
+        },{
+            .name = "number2",
+            .type = QEMU_OPT_NUMBER,
         },
         { /* end of list */ }
     },
@@ -42,14 +46,23 @@ static QemuOptsList opts_list_02 = {
             .name = "str1",
             .type = QEMU_OPT_STRING,
         },{
+            .name = "str2",
+            .type = QEMU_OPT_STRING,
+        },{
             .name = "bool1",
             .type = QEMU_OPT_BOOL,
         },{
-            .name = "str2",
-            .type = QEMU_OPT_STRING,
+            .name = "bool2",
+            .type = QEMU_OPT_BOOL,
         },{
             .name = "size1",
             .type = QEMU_OPT_SIZE,
+        },{
+            .name = "size2",
+            .type = QEMU_OPT_SIZE,
+        },{
+            .name = "size3",
+            .type = QEMU_OPT_SIZE,
         },
         { /* end of list */ }
     },
@@ -57,6 +70,7 @@ static QemuOptsList opts_list_02 = {
 
 static QemuOptsList opts_list_03 = {
     .name = "opts_list_03",
+    .implied_opt_name = "implied",
     .head = QTAILQ_HEAD_INITIALIZER(opts_list_03.head),
     .desc = {
         /* no elements => accept any params */
@@ -421,6 +435,278 @@ static void test_qemu_opts_set(void)
     g_assert(opts == NULL);
 }
 
+static int opts_count_iter(void *opaque, const char *name, const char *value,
+                           Error **errp)
+{
+    (*(size_t *)opaque)++;
+    return 0;
+}
+
+static size_t opts_count(QemuOpts *opts)
+{
+    size_t n = 0;
+
+    qemu_opt_foreach(opts, opts_count_iter, &n, NULL);
+    return n;
+}
+
+static void test_opts_parse(void)
+{
+    Error *err = NULL;
+    QemuOpts *opts;
+    char long_key[129];
+    char *params;
+
+    /* Nothing */
+    opts = qemu_opts_parse(&opts_list_03, "", false, &error_abort);
+    g_assert_cmpuint(opts_count(opts), ==, 0);
+
+    /* Empty key */
+    opts = qemu_opts_parse(&opts_list_03, "=val", false, &error_abort);
+    g_assert_cmpuint(opts_count(opts), ==, 1);
+    g_assert_cmpstr(qemu_opt_get(opts, ""), ==, "val");
+
+    /* Long key */
+    memset(long_key, 'a', 127);
+    long_key[127] = 'z';
+    long_key[128] = 0;
+    params = g_strdup_printf("%s=v", long_key);
+    opts = qemu_opts_parse(&opts_list_03, params + 1, NULL, &error_abort);
+    g_assert_cmpuint(opts_count(opts), ==, 1);
+    g_assert_cmpstr(qemu_opt_get(opts, long_key + 1), ==, "v");
+
+    /* Overlong key gets truncated */
+    opts = qemu_opts_parse(&opts_list_03, params, NULL, &error_abort);
+    g_assert(opts_count(opts) == 1);
+    long_key[127] = 0;
+    g_assert_cmpstr(qemu_opt_get(opts, long_key), ==, "v");
+    g_free(params);
+
+    /* Multiple keys, last one wins */
+    opts = qemu_opts_parse(&opts_list_03, "a=1,b=2,,x,a=3",
+                           false, &error_abort);
+    g_assert_cmpuint(opts_count(opts), ==, 3);
+    g_assert_cmpstr(qemu_opt_get(opts, "a"), ==, "3");
+    g_assert_cmpstr(qemu_opt_get(opts, "b"), ==, "2,x");
+
+    /* Except when it doesn't */
+    opts = qemu_opts_parse(&opts_list_03, "id=foo,id=bar",
+                           false, &error_abort);
+    g_assert_cmpuint(opts_count(opts), ==, 0);
+    g_assert_cmpstr(qemu_opts_id(opts), ==, "foo");
+
+    /* Implied value */
+    opts = qemu_opts_parse(&opts_list_03, "an,noaus,noaus=",
+                           false, &error_abort);
+    g_assert_cmpuint(opts_count(opts), ==, 3);
+    g_assert_cmpstr(qemu_opt_get(opts, "an"), ==, "on");
+    g_assert_cmpstr(qemu_opt_get(opts, "aus"), ==, "off");
+    g_assert_cmpstr(qemu_opt_get(opts, "noaus"), ==, "");
+
+    /* Implied key */
+    opts = qemu_opts_parse(&opts_list_03, "an,noaus,noaus=", true,
+                           &error_abort);
+    g_assert_cmpuint(opts_count(opts), ==, 3);
+    g_assert_cmpstr(qemu_opt_get(opts, "implied"), ==, "an");
+    g_assert_cmpstr(qemu_opt_get(opts, "aus"), ==, "off");
+    g_assert_cmpstr(qemu_opt_get(opts, "noaus"), ==, "");
+
+    /* Trailing comma is ignored */
+    opts = qemu_opts_parse(&opts_list_03, "x=y,", false, &error_abort);
+    g_assert_cmpuint(opts_count(opts), ==, 1);
+    g_assert_cmpstr(qemu_opt_get(opts, "x"), ==, "y");
+
+    /* Except when it isn't */
+    opts = qemu_opts_parse(&opts_list_03, ",", false, &error_abort);
+    g_assert_cmpuint(opts_count(opts), ==, 1);
+    g_assert_cmpstr(qemu_opt_get(opts, ""), ==, "on");
+
+    /* Duplicate ID */
+    opts = qemu_opts_parse(&opts_list_03, "x=y,id=foo", false, &err);
+    error_free_or_abort(&err);
+    g_assert(!opts);
+    /* TODO Cover .merge_lists = true */
+
+    /* Buggy ID recognition */
+    opts = qemu_opts_parse(&opts_list_03, "x=,,id=bar", false, &error_abort);
+    g_assert_cmpuint(opts_count(opts), ==, 1);
+    g_assert_cmpstr(qemu_opts_id(opts), ==, "bar"); /* BUG */
+    g_assert_cmpstr(qemu_opt_get(opts, "x"), ==, ",id=bar");
+
+    /* Anti-social ID */
+    opts = qemu_opts_parse(&opts_list_01, "id=666", false, &err);
+    error_free_or_abort(&err);
+    g_assert(!opts);
+
+    /* Unknown key */
+    opts = qemu_opts_parse(&opts_list_01, "nonexistent=", false, &err);
+    error_free_or_abort(&err);
+    g_assert(!opts);
+
+    qemu_opts_reset(&opts_list_01);
+    qemu_opts_reset(&opts_list_03);
+}
+
+static void test_opts_parse_bool(void)
+{
+    Error *err = NULL;
+    QemuOpts *opts;
+
+    opts = qemu_opts_parse(&opts_list_02, "bool1=on,bool2=off",
+                           false, &error_abort);
+    g_assert_cmpuint(opts_count(opts), ==, 2);
+    g_assert(qemu_opt_get_bool(opts, "bool1", false));
+    g_assert(!qemu_opt_get_bool(opts, "bool2", true));
+
+    opts = qemu_opts_parse(&opts_list_02, "bool1=offer", false, &err);
+    error_free_or_abort(&err);
+    g_assert(!opts);
+
+    qemu_opts_reset(&opts_list_02);
+}
+
+static void test_opts_parse_number(void)
+{
+    Error *err = NULL;
+    QemuOpts *opts;
+
+    /* Lower limit zero */
+    opts = qemu_opts_parse(&opts_list_01, "number1=0", false, &error_abort);
+    g_assert_cmpuint(opts_count(opts), ==, 1);
+    g_assert_cmpuint(qemu_opt_get_number(opts, "number1", 1), ==, 0);
+
+    /* Upper limit 2^64-1 */
+    opts = qemu_opts_parse(&opts_list_01,
+                           "number1=18446744073709551615,number2=-1",
+                           false, &error_abort);
+    g_assert_cmpuint(opts_count(opts), ==, 2);
+    g_assert_cmpuint(qemu_opt_get_number(opts, "number1", 1), ==, UINT64_MAX);
+    g_assert_cmpuint(qemu_opt_get_number(opts, "number2", 0), ==, UINT64_MAX);
+
+    /* Above upper limit */
+    opts = qemu_opts_parse(&opts_list_01, "number1=18446744073709551616",
+                           false, &error_abort);
+    /* BUG: should reject */
+    g_assert_cmpuint(opts_count(opts), ==, 1);
+    g_assert_cmpuint(qemu_opt_get_number(opts, "number1", 1), ==, UINT64_MAX);
+
+    /* Below lower limit */
+    opts = qemu_opts_parse(&opts_list_01, "number1=-18446744073709551616",
+                           false, &error_abort);
+    /* BUG: should reject */
+    g_assert_cmpuint(opts_count(opts), ==, 1);
+    g_assert_cmpuint(qemu_opt_get_number(opts, "number1", 1), ==, UINT64_MAX);
+
+    /* Hex and octal */
+    opts = qemu_opts_parse(&opts_list_01, "number1=0x2a,number2=052",
+                           false, &error_abort);
+    g_assert_cmpuint(opts_count(opts), ==, 2);
+    g_assert_cmpuint(qemu_opt_get_number(opts, "number1", 1), ==, 42);
+    g_assert_cmpuint(qemu_opt_get_number(opts, "number2", 0), ==, 42);
+
+    /* Trailing crap */
+    opts = qemu_opts_parse(&opts_list_01, "number1=3.14", false, &err);
+    error_free_or_abort(&err);
+    g_assert(!opts);
+    opts = qemu_opts_parse(&opts_list_01, "number1=08", false, &err);
+    error_free_or_abort(&err);
+    g_assert(!opts);
+
+    qemu_opts_reset(&opts_list_01);
+}
+
+static void test_opts_parse_size(void)
+{
+    Error *err = NULL;
+    QemuOpts *opts;
+
+    /* Lower limit zero */
+    opts = qemu_opts_parse(&opts_list_02, "size1=0", false, &error_abort);
+    g_assert_cmpuint(opts_count(opts), ==, 1);
+    g_assert_cmpuint(qemu_opt_get_size(opts, "size1", 1), ==, 0);
+
+    /* Note: precision is 53 bits since we're parsing with strtod() */
+
+    /* Around limit of precision: 2^53-1, 2^53, 2^54 */
+    opts = qemu_opts_parse(&opts_list_02,
+                           "size1=9007199254740991,"
+                           "size2=9007199254740992,"
+                           "size3=9007199254740993",
+                           false, &error_abort);
+    g_assert_cmpuint(opts_count(opts), ==, 3);
+    g_assert_cmpuint(qemu_opt_get_size(opts, "size1", 1),
+                     ==, 0x1fffffffffffff);
+    g_assert_cmpuint(qemu_opt_get_size(opts, "size2", 1),
+                     ==, 0x20000000000000);
+    g_assert_cmpuint(qemu_opt_get_size(opts, "size3", 1),
+                     ==, 0x20000000000000);
+
+    /* Close to signed upper limit 0x7ffffffffffffc00 (53 msbs set) */
+    opts = qemu_opts_parse(&opts_list_02,
+                           "size1=9223372036854774784," /* 7ffffffffffffc00 */
+                           "size2=9223372036854775295", /* 7ffffffffffffdff */
+                           false, &error_abort);
+    g_assert_cmpuint(opts_count(opts), ==, 2);
+    g_assert_cmpuint(qemu_opt_get_size(opts, "size1", 1),
+                     ==, 0x7ffffffffffffc00);
+    g_assert_cmpuint(qemu_opt_get_size(opts, "size2", 1),
+                     ==, 0x7ffffffffffffc00);
+
+    /* Close to actual upper limit 0xfffffffffffff800 (53 msbs set) */
+    opts = qemu_opts_parse(&opts_list_02,
+                           "size1=18446744073709549568," /* fffffffffffff800 */
+                           "size2=18446744073709550591", /* fffffffffffffbff */
+                           false, &error_abort);
+    g_assert_cmpuint(opts_count(opts), ==, 2);
+    g_assert_cmpuint(qemu_opt_get_size(opts, "size1", 1),
+                     ==, 0xfffffffffffff800);
+    g_assert_cmpuint(qemu_opt_get_size(opts, "size2", 1),
+                     ==, 0xfffffffffffff800);
+
+    /* Above upper limit */
+    opts = qemu_opts_parse(&opts_list_02, "size1=-1", false, &err);
+    error_free_or_abort(&err);
+    g_assert(!opts);
+    opts = qemu_opts_parse(&opts_list_02,
+                           "size1=18446744073709550592", /* fffffffffffffc00 */
+                           false, &error_abort);
+    /* BUG: should reject */
+    g_assert_cmpuint(opts_count(opts), ==, 1);
+    g_assert_cmpuint(qemu_opt_get_size(opts, "size1", 1), ==, 0);
+
+    /* Suffixes */
+    opts = qemu_opts_parse(&opts_list_02, "size1=8b,size2=1.5k,size3=2M",
+                           false, &error_abort);
+    g_assert_cmpuint(opts_count(opts), ==, 3);
+    g_assert_cmpuint(qemu_opt_get_size(opts, "size1", 0), ==, 8);
+    g_assert_cmpuint(qemu_opt_get_size(opts, "size2", 0), ==, 1536);
+    g_assert_cmpuint(qemu_opt_get_size(opts, "size3", 0), ==, 2 * M_BYTE);
+    opts = qemu_opts_parse(&opts_list_02, "size1=0.1G,size2=16777215T",
+                           false, &error_abort);
+    g_assert_cmpuint(opts_count(opts), ==, 2);
+    g_assert_cmpuint(qemu_opt_get_size(opts, "size1", 0), ==, G_BYTE / 10);
+    g_assert_cmpuint(qemu_opt_get_size(opts, "size2", 0),
+                     ==, 16777215 * T_BYTE);
+
+    /* Beyond limit with suffix */
+    opts = qemu_opts_parse(&opts_list_02, "size1=16777216T",
+                           false, &error_abort);
+    /* BUG: should reject */
+    g_assert_cmpuint(opts_count(opts), ==, 1);
+    g_assert_cmpuint(qemu_opt_get_size(opts, "size1", 1), ==, 0);
+
+    /* Trailing crap */
+    opts = qemu_opts_parse(&opts_list_02, "size1=16E", false, &err);
+    error_free_or_abort(&err);
+    g_assert(!opts);
+    opts = qemu_opts_parse(&opts_list_02, "size1=16Gi", false, &error_abort);
+    /* BUG: should reject */
+    g_assert_cmpuint(opts_count(opts), ==, 1);
+    g_assert_cmpuint(qemu_opt_get_size(opts, "size1", 1), ==, 16 * G_BYTE);
+
+    qemu_opts_reset(&opts_list_02);
+}
+
 int main(int argc, char *argv[])
 {
     register_opts();
@@ -435,6 +721,10 @@ int main(int argc, char *argv[])
     g_test_add_func("/qemu-opts/opt_unset", test_qemu_opt_unset);
     g_test_add_func("/qemu-opts/opts_reset", test_qemu_opts_reset);
     g_test_add_func("/qemu-opts/opts_set", test_qemu_opts_set);
+    g_test_add_func("/qemu-opts/opts_parse/general", test_opts_parse);
+    g_test_add_func("/qemu-opts/opts_parse/bool", test_opts_parse_bool);
+    g_test_add_func("/qemu-opts/opts_parse/number", test_opts_parse_number);
+    g_test_add_func("/qemu-opts/opts_parse/size", test_opts_parse_size);
     g_test_run();
     return 0;
 }
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 79+ messages in thread

* [Qemu-devel] [PATCH 02/24] QemuOpts: Assert value string isn't null
  2017-02-14 10:25 [Qemu-devel] [PATCH 00/24] QemuOpts util/cutils: Fix and clean up number conversions Markus Armbruster
  2017-02-14 10:25 ` [Qemu-devel] [PATCH 01/24] tests/test-qemu-opts: Cover qemu_opts_parse() Markus Armbruster
@ 2017-02-14 10:25 ` Markus Armbruster
  2017-02-14 20:10   ` Eric Blake
  2017-02-14 10:25 ` [Qemu-devel] [PATCH 03/24] tests/test-cutils: Add missing qemu_strtol()... endptr checks Markus Armbruster
                   ` (23 subsequent siblings)
  25 siblings, 1 reply; 79+ messages in thread
From: Markus Armbruster @ 2017-02-14 10:25 UTC (permalink / raw)
  To: qemu-devel

Plenty of code relies on QemuOpt member @str not being null, including
qemu_opts_print(), qemu_opts_to_qdict(), and callbacks passed to
qemu_opt_foreach().

Begs the question whether it can be null.  Only opt_set() creates
QemuOpt.  It sets member @str to its argument @value.  Passing null
for @value would plant a time bomb.  Callers:

* opts_do_parse() can't pass null.

* qemu_opt_set() passes its argument @value.  Callers:

  - qemu_opts_from_qdict_1() can't pass null

  - qemu_opts_set() passes its argument @value, but none of its
    callers pass null.

  - Many more outside qemu-option.c, but they shouldn't pass null,
    either.

Assert member @str isn't null, so that misuse is caught right away.

Simplify parse_option_bool(), parse_option_number() and
parse_option_size() accordingly.  Best viewed with whitespace changes
ignored.

Signed-off-by: Markus Armbruster <armbru@redhat.com>
---
 util/qemu-option.c | 89 ++++++++++++++++++++++++------------------------------
 1 file changed, 39 insertions(+), 50 deletions(-)

diff --git a/util/qemu-option.c b/util/qemu-option.c
index 3467dc2..2b4e0c9 100644
--- a/util/qemu-option.c
+++ b/util/qemu-option.c
@@ -128,17 +128,13 @@ int get_param_value(char *buf, int buf_size,
 static void parse_option_bool(const char *name, const char *value, bool *ret,
                               Error **errp)
 {
-    if (value != NULL) {
-        if (!strcmp(value, "on")) {
-            *ret = 1;
-        } else if (!strcmp(value, "off")) {
-            *ret = 0;
-        } else {
-            error_setg(errp, QERR_INVALID_PARAMETER_VALUE,
-                       name, "'on' or 'off'");
-        }
-    } else {
+    if (!strcmp(value, "on")) {
         *ret = 1;
+    } else if (!strcmp(value, "off")) {
+        *ret = 0;
+    } else {
+        error_setg(errp, QERR_INVALID_PARAMETER_VALUE,
+                   name, "'on' or 'off'");
     }
 }
 
@@ -148,16 +144,12 @@ static void parse_option_number(const char *name, const char *value,
     char *postfix;
     uint64_t number;
 
-    if (value != NULL) {
-        number = strtoull(value, &postfix, 0);
-        if (*postfix != '\0') {
-            error_setg(errp, QERR_INVALID_PARAMETER_VALUE, name, "a number");
-            return;
-        }
-        *ret = number;
-    } else {
+    number = strtoull(value, &postfix, 0);
+    if (*postfix != '\0') {
         error_setg(errp, QERR_INVALID_PARAMETER_VALUE, name, "a number");
+        return;
     }
+    *ret = number;
 }
 
 static const QemuOptDesc *find_desc_by_name(const QemuOptDesc *desc,
@@ -180,39 +172,35 @@ void parse_option_size(const char *name, const char *value,
     char *postfix;
     double sizef;
 
-    if (value != NULL) {
-        sizef = strtod(value, &postfix);
-        if (sizef < 0 || sizef > UINT64_MAX) {
-            error_setg(errp, QERR_INVALID_PARAMETER_VALUE, name,
-                             "a non-negative number below 2^64");
-            return;
-        }
-        switch (*postfix) {
-        case 'T':
-            sizef *= 1024;
-            /* fall through */
-        case 'G':
-            sizef *= 1024;
-            /* fall through */
-        case 'M':
-            sizef *= 1024;
-            /* fall through */
-        case 'K':
-        case 'k':
-            sizef *= 1024;
-            /* fall through */
-        case 'b':
-        case '\0':
-            *ret = (uint64_t) sizef;
-            break;
-        default:
-            error_setg(errp, QERR_INVALID_PARAMETER_VALUE, name, "a size");
-            error_append_hint(errp, "You may use k, M, G or T suffixes for "
-                    "kilobytes, megabytes, gigabytes and terabytes.\n");
-            return;
-        }
-    } else {
+    sizef = strtod(value, &postfix);
+    if (sizef < 0 || sizef > UINT64_MAX) {
+        error_setg(errp, QERR_INVALID_PARAMETER_VALUE, name,
+                   "a non-negative number below 2^64");
+        return;
+    }
+    switch (*postfix) {
+    case 'T':
+        sizef *= 1024;
+        /* fall through */
+    case 'G':
+        sizef *= 1024;
+        /* fall through */
+    case 'M':
+        sizef *= 1024;
+        /* fall through */
+    case 'K':
+    case 'k':
+        sizef *= 1024;
+        /* fall through */
+    case 'b':
+    case '\0':
+        *ret = (uint64_t) sizef;
+        break;
+    default:
         error_setg(errp, QERR_INVALID_PARAMETER_VALUE, name, "a size");
+        error_append_hint(errp, "You may use k, M, G or T suffixes for "
+                          "kilobytes, megabytes, gigabytes and terabytes.\n");
+        return;
     }
 }
 
@@ -547,6 +535,7 @@ static void opt_set(QemuOpts *opts, const char *name, const char *value,
     }
     opt->desc = desc;
     opt->str = g_strdup(value);
+    assert(opt->str);
     qemu_opt_parse(opt, &local_err);
     if (local_err) {
         error_propagate(errp, local_err);
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 79+ messages in thread

* [Qemu-devel] [PATCH 03/24] tests/test-cutils: Add missing qemu_strtol()... endptr checks
  2017-02-14 10:25 [Qemu-devel] [PATCH 00/24] QemuOpts util/cutils: Fix and clean up number conversions Markus Armbruster
  2017-02-14 10:25 ` [Qemu-devel] [PATCH 01/24] tests/test-qemu-opts: Cover qemu_opts_parse() Markus Armbruster
  2017-02-14 10:25 ` [Qemu-devel] [PATCH 02/24] QemuOpts: Assert value string isn't null Markus Armbruster
@ 2017-02-14 10:25 ` Markus Armbruster
  2017-02-14 20:11   ` Eric Blake
  2017-02-19  4:12   ` Philippe Mathieu-Daudé
  2017-02-14 10:25 ` [Qemu-devel] [PATCH 04/24] tests/test-cutils: Clean up qemu_strtoul() result checks Markus Armbruster
                   ` (22 subsequent siblings)
  25 siblings, 2 replies; 79+ messages in thread
From: Markus Armbruster @ 2017-02-14 10:25 UTC (permalink / raw)
  To: qemu-devel

Signed-off-by: Markus Armbruster <armbru@redhat.com>
---
 tests/test-cutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/tests/test-cutils.c b/tests/test-cutils.c
index 20b0f59..71681dc 100644
--- a/tests/test-cutils.c
+++ b/tests/test-cutils.c
@@ -262,6 +262,7 @@ static void test_qemu_strtol_empty(void)
     err = qemu_strtol(str, &endptr, 0, &res);
 
     g_assert_cmpint(err, ==, -EINVAL);
+    g_assert(endptr == str);
 }
 
 static void test_qemu_strtol_whitespace(void)
@@ -275,6 +276,7 @@ static void test_qemu_strtol_whitespace(void)
     err = qemu_strtol(str, &endptr, 0, &res);
 
     g_assert_cmpint(err, ==, -EINVAL);
+    g_assert(endptr == str);
 }
 
 static void test_qemu_strtol_invalid(void)
@@ -288,6 +290,7 @@ static void test_qemu_strtol_invalid(void)
     err = qemu_strtol(str, &endptr, 0, &res);
 
     g_assert_cmpint(err, ==, -EINVAL);
+    g_assert(endptr == str);
 }
 
 static void test_qemu_strtol_trailing(void)
@@ -548,6 +551,7 @@ static void test_qemu_strtoul_empty(void)
     err = qemu_strtoul(str, &endptr, 0, &res);
 
     g_assert_cmpint(err, ==, -EINVAL);
+    g_assert(endptr == str);
 }
 
 static void test_qemu_strtoul_whitespace(void)
@@ -561,6 +565,7 @@ static void test_qemu_strtoul_whitespace(void)
     err = qemu_strtoul(str, &endptr, 0, &res);
 
     g_assert_cmpint(err, ==, -EINVAL);
+    g_assert(endptr == str);
 }
 
 static void test_qemu_strtoul_invalid(void)
@@ -574,6 +579,7 @@ static void test_qemu_strtoul_invalid(void)
     err = qemu_strtoul(str, &endptr, 0, &res);
 
     g_assert_cmpint(err, ==, -EINVAL);
+    g_assert(endptr == str);
 }
 
 static void test_qemu_strtoul_trailing(void)
@@ -829,6 +835,7 @@ static void test_qemu_strtoll_empty(void)
     err = qemu_strtoll(str, &endptr, 0, &res);
 
     g_assert_cmpint(err, ==, -EINVAL);
+    g_assert(endptr == str);
 }
 
 static void test_qemu_strtoll_whitespace(void)
@@ -842,6 +849,7 @@ static void test_qemu_strtoll_whitespace(void)
     err = qemu_strtoll(str, &endptr, 0, &res);
 
     g_assert_cmpint(err, ==, -EINVAL);
+    g_assert(endptr == str);
 }
 
 static void test_qemu_strtoll_invalid(void)
@@ -855,6 +863,7 @@ static void test_qemu_strtoll_invalid(void)
     err = qemu_strtoll(str, &endptr, 0, &res);
 
     g_assert_cmpint(err, ==, -EINVAL);
+    g_assert(endptr == str);
 }
 
 static void test_qemu_strtoll_trailing(void)
@@ -1113,6 +1122,7 @@ static void test_qemu_strtoull_empty(void)
     err = qemu_strtoull(str, &endptr, 0, &res);
 
     g_assert_cmpint(err, ==, -EINVAL);
+    g_assert(endptr == str);
 }
 
 static void test_qemu_strtoull_whitespace(void)
@@ -1126,6 +1136,7 @@ static void test_qemu_strtoull_whitespace(void)
     err = qemu_strtoull(str, &endptr, 0, &res);
 
     g_assert_cmpint(err, ==, -EINVAL);
+    g_assert(endptr == str);
 }
 
 static void test_qemu_strtoull_invalid(void)
@@ -1139,6 +1150,7 @@ static void test_qemu_strtoull_invalid(void)
     err = qemu_strtoull(str, &endptr, 0, &res);
 
     g_assert_cmpint(err, ==, -EINVAL);
+    g_assert(endptr == str);
 }
 
 static void test_qemu_strtoull_trailing(void)
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 79+ messages in thread

* [Qemu-devel] [PATCH 04/24] tests/test-cutils: Clean up qemu_strtoul() result checks
  2017-02-14 10:25 [Qemu-devel] [PATCH 00/24] QemuOpts util/cutils: Fix and clean up number conversions Markus Armbruster
                   ` (2 preceding siblings ...)
  2017-02-14 10:25 ` [Qemu-devel] [PATCH 03/24] tests/test-cutils: Add missing qemu_strtol()... endptr checks Markus Armbruster
@ 2017-02-14 10:25 ` Markus Armbruster
  2017-02-14 21:28   ` Eric Blake
  2017-02-14 10:25 ` [Qemu-devel] [PATCH 05/24] util/cutils: Rewrite documentation of qemu_strtol() & friends Markus Armbruster
                   ` (21 subsequent siblings)
  25 siblings, 1 reply; 79+ messages in thread
From: Markus Armbruster @ 2017-02-14 10:25 UTC (permalink / raw)
  To: qemu-devel

Use unsigned comparisons to check the result of qemu_strtoul() and
strtoull().

Signed-off-by: Markus Armbruster <armbru@redhat.com>
---
 tests/test-cutils.c | 60 ++++++++++++++++++++++++++---------------------------
 1 file changed, 30 insertions(+), 30 deletions(-)

diff --git a/tests/test-cutils.c b/tests/test-cutils.c
index 71681dc..ef76792 100644
--- a/tests/test-cutils.c
+++ b/tests/test-cutils.c
@@ -523,7 +523,7 @@ static void test_qemu_strtoul_correct(void)
     err = qemu_strtoul(str, &endptr, 0, &res);
 
     g_assert_cmpint(err, ==, 0);
-    g_assert_cmpint(res, ==, 12345);
+    g_assert_cmpuint(res, ==, 12345);
     g_assert(endptr == str + 5);
 }
 
@@ -593,7 +593,7 @@ static void test_qemu_strtoul_trailing(void)
     err = qemu_strtoul(str, &endptr, 0, &res);
 
     g_assert_cmpint(err, ==, 0);
-    g_assert_cmpint(res, ==, 123);
+    g_assert_cmpuint(res, ==, 123);
     g_assert(endptr == str + 3);
 }
 
@@ -608,7 +608,7 @@ static void test_qemu_strtoul_octal(void)
     err = qemu_strtoul(str, &endptr, 8, &res);
 
     g_assert_cmpint(err, ==, 0);
-    g_assert_cmpint(res, ==, 0123);
+    g_assert_cmpuint(res, ==, 0123);
     g_assert(endptr == str + strlen(str));
 
     res = 999;
@@ -616,7 +616,7 @@ static void test_qemu_strtoul_octal(void)
     err = qemu_strtoul(str, &endptr, 0, &res);
 
     g_assert_cmpint(err, ==, 0);
-    g_assert_cmpint(res, ==, 0123);
+    g_assert_cmpuint(res, ==, 0123);
     g_assert(endptr == str + strlen(str));
 }
 
@@ -631,7 +631,7 @@ static void test_qemu_strtoul_decimal(void)
     err = qemu_strtoul(str, &endptr, 10, &res);
 
     g_assert_cmpint(err, ==, 0);
-    g_assert_cmpint(res, ==, 123);
+    g_assert_cmpuint(res, ==, 123);
     g_assert(endptr == str + strlen(str));
 
     str = "123";
@@ -640,7 +640,7 @@ static void test_qemu_strtoul_decimal(void)
     err = qemu_strtoul(str, &endptr, 0, &res);
 
     g_assert_cmpint(err, ==, 0);
-    g_assert_cmpint(res, ==, 123);
+    g_assert_cmpuint(res, ==, 123);
     g_assert(endptr == str + strlen(str));
 }
 
@@ -655,7 +655,7 @@ static void test_qemu_strtoul_hex(void)
     err = qemu_strtoul(str, &endptr, 16, &res);
 
     g_assert_cmpint(err, ==, 0);
-    g_assert_cmpint(res, ==, 0x123);
+    g_assert_cmpuint(res, ==, 0x123);
     g_assert(endptr == str + strlen(str));
 
     str = "0x123";
@@ -664,7 +664,7 @@ static void test_qemu_strtoul_hex(void)
     err = qemu_strtoul(str, &endptr, 0, &res);
 
     g_assert_cmpint(err, ==, 0);
-    g_assert_cmpint(res, ==, 0x123);
+    g_assert_cmpuint(res, ==, 0x123);
     g_assert(endptr == str + strlen(str));
 }
 
@@ -679,7 +679,7 @@ static void test_qemu_strtoul_max(void)
     err = qemu_strtoul(str, &endptr, 0, &res);
 
     g_assert_cmpint(err, ==, 0);
-    g_assert_cmpint(res, ==, ULONG_MAX);
+    g_assert_cmpuint(res, ==, ULONG_MAX);
     g_assert(endptr == str + strlen(str));
     g_free(str);
 }
@@ -695,7 +695,7 @@ static void test_qemu_strtoul_overflow(void)
     err = qemu_strtoul(str, &endptr, 0, &res);
 
     g_assert_cmpint(err, ==, -ERANGE);
-    g_assert_cmpint(res, ==, ULONG_MAX);
+    g_assert_cmpuint(res, ==, ULONG_MAX);
     g_assert(endptr == str + strlen(str));
 }
 
@@ -710,7 +710,7 @@ static void test_qemu_strtoul_underflow(void)
     err  = qemu_strtoul(str, &endptr, 0, &res);
 
     g_assert_cmpint(err, ==, -ERANGE);
-    g_assert_cmpint(res, ==, -1ul);
+    g_assert_cmpuint(res, ==, -1ul);
     g_assert(endptr == str + strlen(str));
 }
 
@@ -725,7 +725,7 @@ static void test_qemu_strtoul_negative(void)
     err = qemu_strtoul(str, &endptr, 0, &res);
 
     g_assert_cmpint(err, ==, 0);
-    g_assert_cmpint(res, ==, -321ul);
+    g_assert_cmpuint(res, ==, -321ul);
     g_assert(endptr == str + strlen(str));
 }
 
@@ -738,7 +738,7 @@ static void test_qemu_strtoul_full_correct(void)
     err = qemu_strtoul(str, NULL, 0, &res);
 
     g_assert_cmpint(err, ==, 0);
-    g_assert_cmpint(res, ==, 123);
+    g_assert_cmpuint(res, ==, 123);
 }
 
 static void test_qemu_strtoul_full_null(void)
@@ -769,7 +769,7 @@ static void test_qemu_strtoul_full_negative(void)
 
     err = qemu_strtoul(str, NULL, 0, &res);
     g_assert_cmpint(err, ==, 0);
-    g_assert_cmpint(res, ==, -321ul);
+    g_assert_cmpuint(res, ==, -321ul);
 }
 
 static void test_qemu_strtoul_full_trailing(void)
@@ -792,7 +792,7 @@ static void test_qemu_strtoul_full_max(void)
     err = qemu_strtoul(str, NULL, 0, &res);
 
     g_assert_cmpint(err, ==, 0);
-    g_assert_cmpint(res, ==, ULONG_MAX);
+    g_assert_cmpuint(res, ==, ULONG_MAX);
     g_free(str);
 }
 
@@ -1094,7 +1094,7 @@ static void test_qemu_strtoull_correct(void)
     err = qemu_strtoull(str, &endptr, 0, &res);
 
     g_assert_cmpint(err, ==, 0);
-    g_assert_cmpint(res, ==, 12345);
+    g_assert_cmpuint(res, ==, 12345);
     g_assert(endptr == str + 5);
 }
 
@@ -1164,7 +1164,7 @@ static void test_qemu_strtoull_trailing(void)
     err = qemu_strtoull(str, &endptr, 0, &res);
 
     g_assert_cmpint(err, ==, 0);
-    g_assert_cmpint(res, ==, 123);
+    g_assert_cmpuint(res, ==, 123);
     g_assert(endptr == str + 3);
 }
 
@@ -1179,7 +1179,7 @@ static void test_qemu_strtoull_octal(void)
     err = qemu_strtoull(str, &endptr, 8, &res);
 
     g_assert_cmpint(err, ==, 0);
-    g_assert_cmpint(res, ==, 0123);
+    g_assert_cmpuint(res, ==, 0123);
     g_assert(endptr == str + strlen(str));
 
     endptr = &f;
@@ -1187,7 +1187,7 @@ static void test_qemu_strtoull_octal(void)
     err = qemu_strtoull(str, &endptr, 0, &res);
 
     g_assert_cmpint(err, ==, 0);
-    g_assert_cmpint(res, ==, 0123);
+    g_assert_cmpuint(res, ==, 0123);
     g_assert(endptr == str + strlen(str));
 }
 
@@ -1202,7 +1202,7 @@ static void test_qemu_strtoull_decimal(void)
     err = qemu_strtoull(str, &endptr, 10, &res);
 
     g_assert_cmpint(err, ==, 0);
-    g_assert_cmpint(res, ==, 123);
+    g_assert_cmpuint(res, ==, 123);
     g_assert(endptr == str + strlen(str));
 
     str = "123";
@@ -1211,7 +1211,7 @@ static void test_qemu_strtoull_decimal(void)
     err = qemu_strtoull(str, &endptr, 0, &res);
 
     g_assert_cmpint(err, ==, 0);
-    g_assert_cmpint(res, ==, 123);
+    g_assert_cmpuint(res, ==, 123);
     g_assert(endptr == str + strlen(str));
 }
 
@@ -1226,7 +1226,7 @@ static void test_qemu_strtoull_hex(void)
     err = qemu_strtoull(str, &endptr, 16, &res);
 
     g_assert_cmpint(err, ==, 0);
-    g_assert_cmpint(res, ==, 0x123);
+    g_assert_cmpuint(res, ==, 0x123);
     g_assert(endptr == str + strlen(str));
 
     str = "0x123";
@@ -1235,7 +1235,7 @@ static void test_qemu_strtoull_hex(void)
     err = qemu_strtoull(str, &endptr, 0, &res);
 
     g_assert_cmpint(err, ==, 0);
-    g_assert_cmpint(res, ==, 0x123);
+    g_assert_cmpuint(res, ==, 0x123);
     g_assert(endptr == str + strlen(str));
 }
 
@@ -1250,7 +1250,7 @@ static void test_qemu_strtoull_max(void)
     err = qemu_strtoull(str, &endptr, 0, &res);
 
     g_assert_cmpint(err, ==, 0);
-    g_assert_cmpint(res, ==, ULLONG_MAX);
+    g_assert_cmpuint(res, ==, ULLONG_MAX);
     g_assert(endptr == str + strlen(str));
     g_free(str);
 }
@@ -1266,7 +1266,7 @@ static void test_qemu_strtoull_overflow(void)
     err = qemu_strtoull(str, &endptr, 0, &res);
 
     g_assert_cmpint(err, ==, -ERANGE);
-    g_assert_cmpint(res, ==, ULLONG_MAX);
+    g_assert_cmpuint(res, ==, ULLONG_MAX);
     g_assert(endptr == str + strlen(str));
 }
 
@@ -1281,7 +1281,7 @@ static void test_qemu_strtoull_underflow(void)
     err  = qemu_strtoull(str, &endptr, 0, &res);
 
     g_assert_cmpint(err, ==, -ERANGE);
-    g_assert_cmpint(res, ==, -1);
+    g_assert_cmpuint(res, ==, (uint64_t)-1);
     g_assert(endptr == str + strlen(str));
 }
 
@@ -1296,7 +1296,7 @@ static void test_qemu_strtoull_negative(void)
     err = qemu_strtoull(str, &endptr, 0, &res);
 
     g_assert_cmpint(err, ==, 0);
-    g_assert_cmpint(res, ==, -321);
+    g_assert_cmpuint(res, ==, (uint64_t)-321);
     g_assert(endptr == str + strlen(str));
 }
 
@@ -1309,7 +1309,7 @@ static void test_qemu_strtoull_full_correct(void)
     err = qemu_strtoull(str, NULL, 0, &res);
 
     g_assert_cmpint(err, ==, 0);
-    g_assert_cmpint(res, ==, 18446744073709551614LLU);
+    g_assert_cmpuint(res, ==, 18446744073709551614LLU);
 }
 
 static void test_qemu_strtoull_full_null(void)
@@ -1342,7 +1342,7 @@ static void test_qemu_strtoull_full_negative(void)
     err = qemu_strtoull(str, NULL, 0, &res);
 
     g_assert_cmpint(err, ==, 0);
-    g_assert_cmpint(res, ==, 18446744073709551295LLU);
+    g_assert_cmpuint(res, ==, 18446744073709551295LLU);
 }
 
 static void test_qemu_strtoull_full_trailing(void)
@@ -1365,7 +1365,7 @@ static void test_qemu_strtoull_full_max(void)
     err = qemu_strtoull(str, NULL, 0, &res);
 
     g_assert_cmpint(err, ==, 0);
-    g_assert_cmpint(res, ==, ULLONG_MAX);
+    g_assert_cmpuint(res, ==, ULLONG_MAX);
     g_free(str);
 }
 
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 79+ messages in thread

* [Qemu-devel] [PATCH 05/24] util/cutils: Rewrite documentation of qemu_strtol() & friends
  2017-02-14 10:25 [Qemu-devel] [PATCH 00/24] QemuOpts util/cutils: Fix and clean up number conversions Markus Armbruster
                   ` (3 preceding siblings ...)
  2017-02-14 10:25 ` [Qemu-devel] [PATCH 04/24] tests/test-cutils: Clean up qemu_strtoul() result checks Markus Armbruster
@ 2017-02-14 10:25 ` Markus Armbruster
  2017-02-14 21:32   ` Eric Blake
  2017-02-19  4:12   ` Philippe Mathieu-Daudé
  2017-02-14 10:25 ` [Qemu-devel] [PATCH 06/24] util/cutils: Rename qemu_strtoll(), qemu_strtoull() Markus Armbruster
                   ` (20 subsequent siblings)
  25 siblings, 2 replies; 79+ messages in thread
From: Markus Armbruster @ 2017-02-14 10:25 UTC (permalink / raw)
  To: qemu-devel

Fixes the following documentation bugs:

* Fails to document that null @nptr is safe.

* Fails to document that we return -EINVAL when no conversion could be
  performed (commit 47d4be1).

* Confuses long long with int64_t, and unsigned long long with
  uint64_t.

* Claims the unsigned conversions can underflow.  They can't.

While there, mark problematic assumptions that int64_t is long long,
and uint64_t is unsigned long long with FIXME comments.

Signed-off-by: Markus Armbruster <armbru@redhat.com>
---
 util/cutils.c | 80 +++++++++++++++++++++++++++++++++--------------------------
 1 file changed, 45 insertions(+), 35 deletions(-)

diff --git a/util/cutils.c b/util/cutils.c
index 4fefcf3..1ae2a08 100644
--- a/util/cutils.c
+++ b/util/cutils.c
@@ -265,9 +265,6 @@ int64_t qemu_strtosz(const char *nptr, char **end)
 static int check_strtox_error(const char *p, char *endptr, const char **next,
                               int err)
 {
-    /* If no conversion was performed, prefer BSD behavior over glibc
-     * behavior.
-     */
     if (err == 0 && endptr == p) {
         err = EINVAL;
     }
@@ -281,30 +278,28 @@ static int check_strtox_error(const char *p, char *endptr, const char **next,
 }
 
 /**
- * QEMU wrappers for strtol(), strtoll(), strtoul(), strotull() C functions.
+ * Convert string @nptr to a long integer, and store it in @result.
  *
- * Convert ASCII string @nptr to a long integer value
- * from the given @base. Parameters @nptr, @endptr, @base
- * follows same semantics as strtol() C function.
+ * This is a wrapper around strtol() that is harder to misuse.
+ * Semantics of @nptr, @endptr, @base match strtol() with differences
+ * noted below.
  *
- * Unlike from strtol() function, if @endptr is not NULL, this
- * function will return -EINVAL whenever it cannot fully convert
- * the string in @nptr with given @base to a long. This function returns
- * the result of the conversion only through the @result parameter.
+ * @nptr may be null, and no conversion is performed then.
  *
- * If NULL is passed in @endptr, then the whole string in @ntpr
- * is a number otherwise it returns -EINVAL.
+ * If no conversion is performed, store @nptr in *@endptr and return
+ * -EINVAL.
  *
- * RETURN VALUE
- * Unlike from strtol() function, this wrapper returns either
- * -EINVAL or the errno set by strtol() function (e.g -ERANGE).
- * If the conversion overflows, -ERANGE is returned, and @result
- * is set to the max value of the desired type
- * (e.g. LONG_MAX, LLONG_MAX, ULONG_MAX, ULLONG_MAX). If the case
- * of underflow, -ERANGE is returned, and @result is set to the min
- * value of the desired type. For strtol(), strtoll(), @result is set to
- * LONG_MIN, LLONG_MIN, respectively, and for strtoul(), strtoull() it
- * is set to 0.
+ * If @endptr is null, and the string isn't fully converted, return
+ * -EINVAL.  This is the case when the pointer that would be stored in
+ * a non-null @endptr points to a character other than '\0'.
+ *
+ * If the conversion overflows @result, store LONG_MAX in @result,
+ * and return -ERANGE.
+ *
+ * If the conversion underflows @result, store LONG_MIN in @result,
+ * and return -ERANGE.
+ *
+ * Else store the converted value in @result, and return zero.
  */
 int qemu_strtol(const char *nptr, const char **endptr, int base,
                 long *result)
@@ -325,17 +320,29 @@ int qemu_strtol(const char *nptr, const char **endptr, int base,
 }
 
 /**
- * Converts ASCII string to an unsigned long integer.
+ * Convert string @nptr to an unsigned long, and store it in @result.
  *
- * If string contains a negative number, value will be converted to
- * the unsigned representation of the signed value, unless the original
- * (nonnegated) value would overflow, in this case, it will set @result
- * to ULONG_MAX, and return ERANGE.
+ * This is a wrapper around strtoul() that is harder to misuse.
+ * Semantics of @nptr, @endptr, @base match strtoul() with differences
+ * noted below.
  *
- * The same behavior holds, for qemu_strtoull() but sets @result to
- * ULLONG_MAX instead of ULONG_MAX.
+ * @nptr may be null, and no conversion is performed then.
  *
- * See qemu_strtol() documentation for more info.
+ * If no conversion is performed, store @nptr in *@endptr and return
+ * -EINVAL.
+ *
+ * If @endptr is null, and the string isn't fully converted, return
+ * -EINVAL.  This is the case when the pointer that would be stored in
+ * a non-null @endptr points to a character other than '\0'.
+ *
+ * If the conversion overflows @result, store ULONG_MAX in @result,
+ * and return -ERANGE.
+ *
+ * Else store the converted value in @result, and return zero.
+ *
+ * Note that a number with a leading minus sign gets converted without
+ * the minus sign, checked for overflow (see above), then negated (in
+ * @result's type).  This is exactly how strtoul() works.
  */
 int qemu_strtoul(const char *nptr, const char **endptr, int base,
                  unsigned long *result)
@@ -360,9 +367,10 @@ int qemu_strtoul(const char *nptr, const char **endptr, int base,
 }
 
 /**
- * Converts ASCII string to a long long integer.
+ * Convert string @nptr to an int64_t.
  *
- * See qemu_strtol() documentation for more info.
+ * Works like qemu_strtol(), except it stores INT64_MAX on overflow,
+ * and INT_MIN on underflow.
  */
 int qemu_strtoll(const char *nptr, const char **endptr, int base,
                  int64_t *result)
@@ -376,6 +384,7 @@ int qemu_strtoll(const char *nptr, const char **endptr, int base,
         err = -EINVAL;
     } else {
         errno = 0;
+        /* FIXME This assumes int64_t is long long */
         *result = strtoll(nptr, &p, base);
         err = check_strtox_error(nptr, p, endptr, errno);
     }
@@ -383,9 +392,9 @@ int qemu_strtoll(const char *nptr, const char **endptr, int base,
 }
 
 /**
- * Converts ASCII string to an unsigned long long integer.
+ * Convert string @nptr to an uint64_t.
  *
- * See qemu_strtol() documentation for more info.
+ * Works like qemu_strtoul(), except it stores UINT64_MAX on overflow.
  */
 int qemu_strtoull(const char *nptr, const char **endptr, int base,
                   uint64_t *result)
@@ -399,6 +408,7 @@ int qemu_strtoull(const char *nptr, const char **endptr, int base,
         err = -EINVAL;
     } else {
         errno = 0;
+        /* FIXME This assumes uint64_t is unsigned long long */
         *result = strtoull(nptr, &p, base);
         /* Windows returns 1 for negative out-of-range values.  */
         if (errno == ERANGE) {
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 79+ messages in thread

* [Qemu-devel] [PATCH 06/24] util/cutils: Rename qemu_strtoll(), qemu_strtoull()
  2017-02-14 10:25 [Qemu-devel] [PATCH 00/24] QemuOpts util/cutils: Fix and clean up number conversions Markus Armbruster
                   ` (4 preceding siblings ...)
  2017-02-14 10:25 ` [Qemu-devel] [PATCH 05/24] util/cutils: Rewrite documentation of qemu_strtol() & friends Markus Armbruster
@ 2017-02-14 10:25 ` Markus Armbruster
  2017-02-14 21:34   ` Eric Blake
  2017-02-19  4:14   ` Philippe Mathieu-Daudé
  2017-02-14 10:25 ` [Qemu-devel] [PATCH 07/24] util/cutils: Clean up variable names around qemu_strtol() Markus Armbruster
                   ` (19 subsequent siblings)
  25 siblings, 2 replies; 79+ messages in thread
From: Markus Armbruster @ 2017-02-14 10:25 UTC (permalink / raw)
  To: qemu-devel

The name qemu_strtoll() suggests conversion to long long, but it
actually converts to int64_t.  Rename to qemu_strtoi64().

The name qemu_strtoull() suggests conversion to unsigned long long,
but it actually converts to uint64_t.  Rename to qemu_strtou64().

Signed-off-by: Markus Armbruster <armbru@redhat.com>
---
 include/qemu/cutils.h |   6 +-
 qobject/qdict.c       |   2 +-
 qtest.c               |  34 ++---
 tests/test-cutils.c   | 366 +++++++++++++++++++++++++++-----------------------
 util/cutils.c         |   4 +-
 util/log.c            |   4 +-
 6 files changed, 224 insertions(+), 192 deletions(-)

diff --git a/include/qemu/cutils.h b/include/qemu/cutils.h
index 8033929..f922223 100644
--- a/include/qemu/cutils.h
+++ b/include/qemu/cutils.h
@@ -130,9 +130,9 @@ int qemu_strtol(const char *nptr, const char **endptr, int base,
                 long *result);
 int qemu_strtoul(const char *nptr, const char **endptr, int base,
                  unsigned long *result);
-int qemu_strtoll(const char *nptr, const char **endptr, int base,
-                 int64_t *result);
-int qemu_strtoull(const char *nptr, const char **endptr, int base,
+int qemu_strtoi64(const char *nptr, const char **endptr, int base,
+                  int64_t *result);
+int qemu_strtou64(const char *nptr, const char **endptr, int base,
                   uint64_t *result);
 
 int parse_uint(const char *s, unsigned long long *value, char **endptr,
diff --git a/qobject/qdict.c b/qobject/qdict.c
index 197b0fb..4be7d3e 100644
--- a/qobject/qdict.c
+++ b/qobject/qdict.c
@@ -767,7 +767,7 @@ static int qdict_is_list(QDict *maybe_list, Error **errp)
     for (ent = qdict_first(maybe_list); ent != NULL;
          ent = qdict_next(maybe_list, ent)) {
 
-        if (qemu_strtoll(ent->key, NULL, 10, &val) == 0) {
+        if (qemu_strtoi64(ent->key, NULL, 10, &val) == 0) {
             if (is_list == -1) {
                 is_list = 1;
             } else if (!is_list) {
diff --git a/qtest.c b/qtest.c
index 1446719..a685827 100644
--- a/qtest.c
+++ b/qtest.c
@@ -373,8 +373,8 @@ static void qtest_process_command(CharBackend *chr, gchar **words)
         uint64_t value;
 
         g_assert(words[1] && words[2]);
-        g_assert(qemu_strtoull(words[1], NULL, 0, &addr) == 0);
-        g_assert(qemu_strtoull(words[2], NULL, 0, &value) == 0);
+        g_assert(qemu_strtou64(words[1], NULL, 0, &addr) == 0);
+        g_assert(qemu_strtou64(words[2], NULL, 0, &value) == 0);
 
         if (words[0][5] == 'b') {
             uint8_t data = value;
@@ -402,7 +402,7 @@ static void qtest_process_command(CharBackend *chr, gchar **words)
         uint64_t value = UINT64_C(-1);
 
         g_assert(words[1]);
-        g_assert(qemu_strtoull(words[1], NULL, 0, &addr) == 0);
+        g_assert(qemu_strtou64(words[1], NULL, 0, &addr) == 0);
 
         if (words[0][4] == 'b') {
             uint8_t data;
@@ -428,8 +428,8 @@ static void qtest_process_command(CharBackend *chr, gchar **words)
         char *enc;
 
         g_assert(words[1] && words[2]);
-        g_assert(qemu_strtoull(words[1], NULL, 0, &addr) == 0);
-        g_assert(qemu_strtoull(words[2], NULL, 0, &len) == 0);
+        g_assert(qemu_strtou64(words[1], NULL, 0, &addr) == 0);
+        g_assert(qemu_strtou64(words[2], NULL, 0, &len) == 0);
         /* We'd send garbage to libqtest if len is 0 */
         g_assert(len);
 
@@ -452,8 +452,8 @@ static void qtest_process_command(CharBackend *chr, gchar **words)
         gchar *b64_data;
 
         g_assert(words[1] && words[2]);
-        g_assert(qemu_strtoull(words[1], NULL, 0, &addr) == 0);
-        g_assert(qemu_strtoull(words[2], NULL, 0, &len) == 0);
+        g_assert(qemu_strtou64(words[1], NULL, 0, &addr) == 0);
+        g_assert(qemu_strtou64(words[2], NULL, 0, &len) == 0);
 
         data = g_malloc(len);
         cpu_physical_memory_read(addr, data, len);
@@ -469,8 +469,8 @@ static void qtest_process_command(CharBackend *chr, gchar **words)
         size_t data_len;
 
         g_assert(words[1] && words[2] && words[3]);
-        g_assert(qemu_strtoull(words[1], NULL, 0, &addr) == 0);
-        g_assert(qemu_strtoull(words[2], NULL, 0, &len) == 0);
+        g_assert(qemu_strtou64(words[1], NULL, 0, &addr) == 0);
+        g_assert(qemu_strtou64(words[2], NULL, 0, &len) == 0);
 
         data_len = strlen(words[3]);
         if (data_len < 3) {
@@ -498,8 +498,8 @@ static void qtest_process_command(CharBackend *chr, gchar **words)
         unsigned long pattern;
 
         g_assert(words[1] && words[2] && words[3]);
-        g_assert(qemu_strtoull(words[1], NULL, 0, &addr) == 0);
-        g_assert(qemu_strtoull(words[2], NULL, 0, &len) == 0);
+        g_assert(qemu_strtou64(words[1], NULL, 0, &addr) == 0);
+        g_assert(qemu_strtou64(words[2], NULL, 0, &len) == 0);
         g_assert(qemu_strtoul(words[3], NULL, 0, &pattern) == 0);
 
         if (len) {
@@ -518,8 +518,8 @@ static void qtest_process_command(CharBackend *chr, gchar **words)
         gsize out_len;
 
         g_assert(words[1] && words[2] && words[3]);
-        g_assert(qemu_strtoull(words[1], NULL, 0, &addr) == 0);
-        g_assert(qemu_strtoull(words[2], NULL, 0, &len) == 0);
+        g_assert(qemu_strtou64(words[1], NULL, 0, &addr) == 0);
+        g_assert(qemu_strtou64(words[2], NULL, 0, &len) == 0);
 
         data_len = strlen(words[3]);
         if (data_len < 3) {
@@ -552,9 +552,9 @@ static void qtest_process_command(CharBackend *chr, gchar **words)
         unsigned long nargs, nret;
 
         g_assert(qemu_strtoul(words[2], NULL, 0, &nargs) == 0);
-        g_assert(qemu_strtoull(words[3], NULL, 0, &args) == 0);
+        g_assert(qemu_strtou64(words[3], NULL, 0, &args) == 0);
         g_assert(qemu_strtoul(words[4], NULL, 0, &nret) == 0);
-        g_assert(qemu_strtoull(words[5], NULL, 0, &ret) == 0);
+        g_assert(qemu_strtou64(words[5], NULL, 0, &ret) == 0);
         res = qtest_rtas_call(words[1], nargs, args, nret, ret);
 
         qtest_send_prefix(chr);
@@ -564,7 +564,7 @@ static void qtest_process_command(CharBackend *chr, gchar **words)
         int64_t ns;
 
         if (words[1]) {
-            g_assert(qemu_strtoll(words[1], NULL, 0, &ns) == 0);
+            g_assert(qemu_strtoi64(words[1], NULL, 0, &ns) == 0);
         } else {
             ns = qemu_clock_deadline_ns_all(QEMU_CLOCK_VIRTUAL);
         }
@@ -576,7 +576,7 @@ static void qtest_process_command(CharBackend *chr, gchar **words)
         int64_t ns;
 
         g_assert(words[1]);
-        g_assert(qemu_strtoll(words[1], NULL, 0, &ns) == 0);
+        g_assert(qemu_strtoi64(words[1], NULL, 0, &ns) == 0);
         qtest_clock_warp(ns);
         qtest_send_prefix(chr);
         qtest_sendf(chr, "OK %"PRIi64"\n",
diff --git a/tests/test-cutils.c b/tests/test-cutils.c
index ef76792..47cc8a4 100644
--- a/tests/test-cutils.c
+++ b/tests/test-cutils.c
@@ -796,7 +796,7 @@ static void test_qemu_strtoul_full_max(void)
     g_free(str);
 }
 
-static void test_qemu_strtoll_correct(void)
+static void test_qemu_strtoi64_correct(void)
 {
     const char *str = "12345 foo";
     char f = 'X';
@@ -804,27 +804,27 @@ static void test_qemu_strtoll_correct(void)
     int64_t res = 999;
     int err;
 
-    err = qemu_strtoll(str, &endptr, 0, &res);
+    err = qemu_strtoi64(str, &endptr, 0, &res);
 
     g_assert_cmpint(err, ==, 0);
     g_assert_cmpint(res, ==, 12345);
     g_assert(endptr == str + 5);
 }
 
-static void test_qemu_strtoll_null(void)
+static void test_qemu_strtoi64_null(void)
 {
     char f = 'X';
     const char *endptr = &f;
     int64_t res = 999;
     int err;
 
-    err = qemu_strtoll(NULL, &endptr, 0, &res);
+    err = qemu_strtoi64(NULL, &endptr, 0, &res);
 
     g_assert_cmpint(err, ==, -EINVAL);
     g_assert(endptr == NULL);
 }
 
-static void test_qemu_strtoll_empty(void)
+static void test_qemu_strtoi64_empty(void)
 {
     const char *str = "";
     char f = 'X';
@@ -832,13 +832,13 @@ static void test_qemu_strtoll_empty(void)
     int64_t res = 999;
     int err;
 
-    err = qemu_strtoll(str, &endptr, 0, &res);
+    err = qemu_strtoi64(str, &endptr, 0, &res);
 
     g_assert_cmpint(err, ==, -EINVAL);
     g_assert(endptr == str);
 }
 
-static void test_qemu_strtoll_whitespace(void)
+static void test_qemu_strtoi64_whitespace(void)
 {
     const char *str = "  \t  ";
     char f = 'X';
@@ -846,13 +846,13 @@ static void test_qemu_strtoll_whitespace(void)
     int64_t res = 999;
     int err;
 
-    err = qemu_strtoll(str, &endptr, 0, &res);
+    err = qemu_strtoi64(str, &endptr, 0, &res);
 
     g_assert_cmpint(err, ==, -EINVAL);
     g_assert(endptr == str);
 }
 
-static void test_qemu_strtoll_invalid(void)
+static void test_qemu_strtoi64_invalid(void)
 {
     const char *str = "   xxxx  \t abc";
     char f = 'X';
@@ -860,13 +860,13 @@ static void test_qemu_strtoll_invalid(void)
     int64_t res = 999;
     int err;
 
-    err = qemu_strtoll(str, &endptr, 0, &res);
+    err = qemu_strtoi64(str, &endptr, 0, &res);
 
     g_assert_cmpint(err, ==, -EINVAL);
     g_assert(endptr == str);
 }
 
-static void test_qemu_strtoll_trailing(void)
+static void test_qemu_strtoi64_trailing(void)
 {
     const char *str = "123xxx";
     char f = 'X';
@@ -874,14 +874,14 @@ static void test_qemu_strtoll_trailing(void)
     int64_t res = 999;
     int err;
 
-    err = qemu_strtoll(str, &endptr, 0, &res);
+    err = qemu_strtoi64(str, &endptr, 0, &res);
 
     g_assert_cmpint(err, ==, 0);
     g_assert_cmpint(res, ==, 123);
     g_assert(endptr == str + 3);
 }
 
-static void test_qemu_strtoll_octal(void)
+static void test_qemu_strtoi64_octal(void)
 {
     const char *str = "0123";
     char f = 'X';
@@ -889,7 +889,7 @@ static void test_qemu_strtoll_octal(void)
     int64_t res = 999;
     int err;
 
-    err = qemu_strtoll(str, &endptr, 8, &res);
+    err = qemu_strtoi64(str, &endptr, 8, &res);
 
     g_assert_cmpint(err, ==, 0);
     g_assert_cmpint(res, ==, 0123);
@@ -897,14 +897,14 @@ static void test_qemu_strtoll_octal(void)
 
     endptr = &f;
     res = 999;
-    err = qemu_strtoll(str, &endptr, 0, &res);
+    err = qemu_strtoi64(str, &endptr, 0, &res);
 
     g_assert_cmpint(err, ==, 0);
     g_assert_cmpint(res, ==, 0123);
     g_assert(endptr == str + strlen(str));
 }
 
-static void test_qemu_strtoll_decimal(void)
+static void test_qemu_strtoi64_decimal(void)
 {
     const char *str = "0123";
     char f = 'X';
@@ -912,7 +912,7 @@ static void test_qemu_strtoll_decimal(void)
     int64_t res = 999;
     int err;
 
-    err = qemu_strtoll(str, &endptr, 10, &res);
+    err = qemu_strtoi64(str, &endptr, 10, &res);
 
     g_assert_cmpint(err, ==, 0);
     g_assert_cmpint(res, ==, 123);
@@ -921,14 +921,14 @@ static void test_qemu_strtoll_decimal(void)
     str = "123";
     endptr = &f;
     res = 999;
-    err = qemu_strtoll(str, &endptr, 0, &res);
+    err = qemu_strtoi64(str, &endptr, 0, &res);
 
     g_assert_cmpint(err, ==, 0);
     g_assert_cmpint(res, ==, 123);
     g_assert(endptr == str + strlen(str));
 }
 
-static void test_qemu_strtoll_hex(void)
+static void test_qemu_strtoi64_hex(void)
 {
     const char *str = "0123";
     char f = 'X';
@@ -936,7 +936,7 @@ static void test_qemu_strtoll_hex(void)
     int64_t res = 999;
     int err;
 
-    err = qemu_strtoll(str, &endptr, 16, &res);
+    err = qemu_strtoi64(str, &endptr, 16, &res);
 
     g_assert_cmpint(err, ==, 0);
     g_assert_cmpint(res, ==, 0x123);
@@ -945,14 +945,14 @@ static void test_qemu_strtoll_hex(void)
     str = "0x123";
     endptr = &f;
     res = 999;
-    err = qemu_strtoll(str, &endptr, 0, &res);
+    err = qemu_strtoi64(str, &endptr, 0, &res);
 
     g_assert_cmpint(err, ==, 0);
     g_assert_cmpint(res, ==, 0x123);
     g_assert(endptr == str + strlen(str));
 }
 
-static void test_qemu_strtoll_max(void)
+static void test_qemu_strtoi64_max(void)
 {
     char *str = g_strdup_printf("%lld", LLONG_MAX);
     char f = 'X';
@@ -960,7 +960,7 @@ static void test_qemu_strtoll_max(void)
     int64_t res = 999;
     int err;
 
-    err = qemu_strtoll(str, &endptr, 0, &res);
+    err = qemu_strtoi64(str, &endptr, 0, &res);
 
     g_assert_cmpint(err, ==, 0);
     g_assert_cmpint(res, ==, LLONG_MAX);
@@ -968,7 +968,7 @@ static void test_qemu_strtoll_max(void)
     g_free(str);
 }
 
-static void test_qemu_strtoll_overflow(void)
+static void test_qemu_strtoi64_overflow(void)
 {
     const char *str = "99999999999999999999999999999999999999999999";
     char f = 'X';
@@ -976,14 +976,14 @@ static void test_qemu_strtoll_overflow(void)
     int64_t res = 999;
     int err;
 
-    err = qemu_strtoll(str, &endptr, 0, &res);
+    err = qemu_strtoi64(str, &endptr, 0, &res);
 
     g_assert_cmpint(err, ==, -ERANGE);
     g_assert_cmpint(res, ==, LLONG_MAX);
     g_assert(endptr == str + strlen(str));
 }
 
-static void test_qemu_strtoll_underflow(void)
+static void test_qemu_strtoi64_underflow(void)
 {
     const char *str = "-99999999999999999999999999999999999999999999";
     char f = 'X';
@@ -991,14 +991,14 @@ static void test_qemu_strtoll_underflow(void)
     int64_t res = 999;
     int err;
 
-    err  = qemu_strtoll(str, &endptr, 0, &res);
+    err  = qemu_strtoi64(str, &endptr, 0, &res);
 
     g_assert_cmpint(err, ==, -ERANGE);
     g_assert_cmpint(res, ==, LLONG_MIN);
     g_assert(endptr == str + strlen(str));
 }
 
-static void test_qemu_strtoll_negative(void)
+static void test_qemu_strtoi64_negative(void)
 {
     const char *str = "  \t -321";
     char f = 'X';
@@ -1006,84 +1006,84 @@ static void test_qemu_strtoll_negative(void)
     int64_t res = 999;
     int err;
 
-    err = qemu_strtoll(str, &endptr, 0, &res);
+    err = qemu_strtoi64(str, &endptr, 0, &res);
 
     g_assert_cmpint(err, ==, 0);
     g_assert_cmpint(res, ==, -321);
     g_assert(endptr == str + strlen(str));
 }
 
-static void test_qemu_strtoll_full_correct(void)
+static void test_qemu_strtoi64_full_correct(void)
 {
     const char *str = "123";
     int64_t res = 999;
     int err;
 
-    err = qemu_strtoll(str, NULL, 0, &res);
+    err = qemu_strtoi64(str, NULL, 0, &res);
 
     g_assert_cmpint(err, ==, 0);
     g_assert_cmpint(res, ==, 123);
 }
 
-static void test_qemu_strtoll_full_null(void)
+static void test_qemu_strtoi64_full_null(void)
 {
     int64_t res = 999;
     int err;
 
-    err = qemu_strtoll(NULL, NULL, 0, &res);
+    err = qemu_strtoi64(NULL, NULL, 0, &res);
 
     g_assert_cmpint(err, ==, -EINVAL);
 }
 
-static void test_qemu_strtoll_full_empty(void)
+static void test_qemu_strtoi64_full_empty(void)
 {
     const char *str = "";
     int64_t res = 999;
     int err;
 
-    err = qemu_strtoll(str, NULL, 0, &res);
+    err = qemu_strtoi64(str, NULL, 0, &res);
 
     g_assert_cmpint(err, ==, -EINVAL);
 }
 
-static void test_qemu_strtoll_full_negative(void)
+static void test_qemu_strtoi64_full_negative(void)
 {
     const char *str = " \t -321";
     int64_t res = 999;
     int err;
 
-    err = qemu_strtoll(str, NULL, 0, &res);
+    err = qemu_strtoi64(str, NULL, 0, &res);
 
     g_assert_cmpint(err, ==, 0);
     g_assert_cmpint(res, ==, -321);
 }
 
-static void test_qemu_strtoll_full_trailing(void)
+static void test_qemu_strtoi64_full_trailing(void)
 {
     const char *str = "123xxx";
     int64_t res = 999;
     int err;
 
-    err = qemu_strtoll(str, NULL, 0, &res);
+    err = qemu_strtoi64(str, NULL, 0, &res);
 
     g_assert_cmpint(err, ==, -EINVAL);
 }
 
-static void test_qemu_strtoll_full_max(void)
+static void test_qemu_strtoi64_full_max(void)
 {
 
     char *str = g_strdup_printf("%lld", LLONG_MAX);
     int64_t res;
     int err;
 
-    err = qemu_strtoll(str, NULL, 0, &res);
+    err = qemu_strtoi64(str, NULL, 0, &res);
 
     g_assert_cmpint(err, ==, 0);
     g_assert_cmpint(res, ==, LLONG_MAX);
     g_free(str);
 }
 
-static void test_qemu_strtoull_correct(void)
+static void test_qemu_strtou64_correct(void)
 {
     const char *str = "12345 foo";
     char f = 'X';
@@ -1091,27 +1091,27 @@ static void test_qemu_strtoull_correct(void)
     uint64_t res = 999;
     int err;
 
-    err = qemu_strtoull(str, &endptr, 0, &res);
+    err = qemu_strtou64(str, &endptr, 0, &res);
 
     g_assert_cmpint(err, ==, 0);
     g_assert_cmpuint(res, ==, 12345);
     g_assert(endptr == str + 5);
 }
 
-static void test_qemu_strtoull_null(void)
+static void test_qemu_strtou64_null(void)
 {
     char f = 'X';
     const char *endptr = &f;
     uint64_t res = 999;
     int err;
 
-    err = qemu_strtoull(NULL, &endptr, 0, &res);
+    err = qemu_strtou64(NULL, &endptr, 0, &res);
 
     g_assert_cmpint(err, ==, -EINVAL);
     g_assert(endptr == NULL);
 }
 
-static void test_qemu_strtoull_empty(void)
+static void test_qemu_strtou64_empty(void)
 {
     const char *str = "";
     char f = 'X';
@@ -1119,13 +1119,13 @@ static void test_qemu_strtoull_empty(void)
     uint64_t res = 999;
     int err;
 
-    err = qemu_strtoull(str, &endptr, 0, &res);
+    err = qemu_strtou64(str, &endptr, 0, &res);
 
     g_assert_cmpint(err, ==, -EINVAL);
     g_assert(endptr == str);
 }
 
-static void test_qemu_strtoull_whitespace(void)
+static void test_qemu_strtou64_whitespace(void)
 {
     const char *str = "  \t  ";
     char f = 'X';
@@ -1133,13 +1133,13 @@ static void test_qemu_strtoull_whitespace(void)
     uint64_t res = 999;
     int err;
 
-    err = qemu_strtoull(str, &endptr, 0, &res);
+    err = qemu_strtou64(str, &endptr, 0, &res);
 
     g_assert_cmpint(err, ==, -EINVAL);
     g_assert(endptr == str);
 }
 
-static void test_qemu_strtoull_invalid(void)
+static void test_qemu_strtou64_invalid(void)
 {
     const char *str = "   xxxx  \t abc";
     char f = 'X';
@@ -1147,13 +1147,13 @@ static void test_qemu_strtoull_invalid(void)
     uint64_t res = 999;
     int err;
 
-    err = qemu_strtoull(str, &endptr, 0, &res);
+    err = qemu_strtou64(str, &endptr, 0, &res);
 
     g_assert_cmpint(err, ==, -EINVAL);
     g_assert(endptr == str);
 }
 
-static void test_qemu_strtoull_trailing(void)
+static void test_qemu_strtou64_trailing(void)
 {
     const char *str = "123xxx";
     char f = 'X';
@@ -1161,14 +1161,14 @@ static void test_qemu_strtoull_trailing(void)
     uint64_t res = 999;
     int err;
 
-    err = qemu_strtoull(str, &endptr, 0, &res);
+    err = qemu_strtou64(str, &endptr, 0, &res);
 
     g_assert_cmpint(err, ==, 0);
     g_assert_cmpuint(res, ==, 123);
     g_assert(endptr == str + 3);
 }
 
-static void test_qemu_strtoull_octal(void)
+static void test_qemu_strtou64_octal(void)
 {
     const char *str = "0123";
     char f = 'X';
@@ -1176,7 +1176,7 @@ static void test_qemu_strtoull_octal(void)
     uint64_t res = 999;
     int err;
 
-    err = qemu_strtoull(str, &endptr, 8, &res);
+    err = qemu_strtou64(str, &endptr, 8, &res);
 
     g_assert_cmpint(err, ==, 0);
     g_assert_cmpuint(res, ==, 0123);
@@ -1184,14 +1184,14 @@ static void test_qemu_strtoull_octal(void)
 
     endptr = &f;
     res = 999;
-    err = qemu_strtoull(str, &endptr, 0, &res);
+    err = qemu_strtou64(str, &endptr, 0, &res);
 
     g_assert_cmpint(err, ==, 0);
     g_assert_cmpuint(res, ==, 0123);
     g_assert(endptr == str + strlen(str));
 }
 
-static void test_qemu_strtoull_decimal(void)
+static void test_qemu_strtou64_decimal(void)
 {
     const char *str = "0123";
     char f = 'X';
@@ -1199,7 +1199,7 @@ static void test_qemu_strtoull_decimal(void)
     uint64_t res = 999;
     int err;
 
-    err = qemu_strtoull(str, &endptr, 10, &res);
+    err = qemu_strtou64(str, &endptr, 10, &res);
 
     g_assert_cmpint(err, ==, 0);
     g_assert_cmpuint(res, ==, 123);
@@ -1208,14 +1208,14 @@ static void test_qemu_strtoull_decimal(void)
     str = "123";
     endptr = &f;
     res = 999;
-    err = qemu_strtoull(str, &endptr, 0, &res);
+    err = qemu_strtou64(str, &endptr, 0, &res);
 
     g_assert_cmpint(err, ==, 0);
     g_assert_cmpuint(res, ==, 123);
     g_assert(endptr == str + strlen(str));
 }
 
-static void test_qemu_strtoull_hex(void)
+static void test_qemu_strtou64_hex(void)
 {
     const char *str = "0123";
     char f = 'X';
@@ -1223,7 +1223,7 @@ static void test_qemu_strtoull_hex(void)
     uint64_t res = 999;
     int err;
 
-    err = qemu_strtoull(str, &endptr, 16, &res);
+    err = qemu_strtou64(str, &endptr, 16, &res);
 
     g_assert_cmpint(err, ==, 0);
     g_assert_cmpuint(res, ==, 0x123);
@@ -1232,14 +1232,14 @@ static void test_qemu_strtoull_hex(void)
     str = "0x123";
     endptr = &f;
     res = 999;
-    err = qemu_strtoull(str, &endptr, 0, &res);
+    err = qemu_strtou64(str, &endptr, 0, &res);
 
     g_assert_cmpint(err, ==, 0);
     g_assert_cmpuint(res, ==, 0x123);
     g_assert(endptr == str + strlen(str));
 }
 
-static void test_qemu_strtoull_max(void)
+static void test_qemu_strtou64_max(void)
 {
     char *str = g_strdup_printf("%llu", ULLONG_MAX);
     char f = 'X';
@@ -1247,7 +1247,7 @@ static void test_qemu_strtoull_max(void)
     uint64_t res = 999;
     int err;
 
-    err = qemu_strtoull(str, &endptr, 0, &res);
+    err = qemu_strtou64(str, &endptr, 0, &res);
 
     g_assert_cmpint(err, ==, 0);
     g_assert_cmpuint(res, ==, ULLONG_MAX);
@@ -1255,7 +1255,7 @@ static void test_qemu_strtoull_max(void)
     g_free(str);
 }
 
-static void test_qemu_strtoull_overflow(void)
+static void test_qemu_strtou64_overflow(void)
 {
     const char *str = "99999999999999999999999999999999999999999999";
     char f = 'X';
@@ -1263,14 +1263,14 @@ static void test_qemu_strtoull_overflow(void)
     uint64_t res = 999;
     int err;
 
-    err = qemu_strtoull(str, &endptr, 0, &res);
+    err = qemu_strtou64(str, &endptr, 0, &res);
 
     g_assert_cmpint(err, ==, -ERANGE);
     g_assert_cmpuint(res, ==, ULLONG_MAX);
     g_assert(endptr == str + strlen(str));
 }
 
-static void test_qemu_strtoull_underflow(void)
+static void test_qemu_strtou64_underflow(void)
 {
     const char *str = "-99999999999999999999999999999999999999999999";
     char f = 'X';
@@ -1278,14 +1278,14 @@ static void test_qemu_strtoull_underflow(void)
     uint64_t res = 999;
     int err;
 
-    err  = qemu_strtoull(str, &endptr, 0, &res);
+    err  = qemu_strtou64(str, &endptr, 0, &res);
 
     g_assert_cmpint(err, ==, -ERANGE);
     g_assert_cmpuint(res, ==, (uint64_t)-1);
     g_assert(endptr == str + strlen(str));
 }
 
-static void test_qemu_strtoull_negative(void)
+static void test_qemu_strtou64_negative(void)
 {
     const char *str = "  \t -321";
     char f = 'X';
@@ -1293,76 +1293,76 @@ static void test_qemu_strtoull_negative(void)
     uint64_t res = 999;
     int err;
 
-    err = qemu_strtoull(str, &endptr, 0, &res);
+    err = qemu_strtou64(str, &endptr, 0, &res);
 
     g_assert_cmpint(err, ==, 0);
     g_assert_cmpuint(res, ==, (uint64_t)-321);
     g_assert(endptr == str + strlen(str));
 }
 
-static void test_qemu_strtoull_full_correct(void)
+static void test_qemu_strtou64_full_correct(void)
 {
     const char *str = "18446744073709551614";
     uint64_t res = 999;
     int err;
 
-    err = qemu_strtoull(str, NULL, 0, &res);
+    err = qemu_strtou64(str, NULL, 0, &res);
 
     g_assert_cmpint(err, ==, 0);
     g_assert_cmpuint(res, ==, 18446744073709551614LLU);
 }
 
-static void test_qemu_strtoull_full_null(void)
+static void test_qemu_strtou64_full_null(void)
 {
     uint64_t res = 999;
     int err;
 
-    err = qemu_strtoull(NULL, NULL, 0, &res);
+    err = qemu_strtou64(NULL, NULL, 0, &res);
 
     g_assert_cmpint(err, ==, -EINVAL);
 }
 
-static void test_qemu_strtoull_full_empty(void)
+static void test_qemu_strtou64_full_empty(void)
 {
     const char *str = "";
     uint64_t res = 999;
     int err;
 
-    err = qemu_strtoull(str, NULL, 0, &res);
+    err = qemu_strtou64(str, NULL, 0, &res);
 
     g_assert_cmpint(err, ==, -EINVAL);
 }
 
-static void test_qemu_strtoull_full_negative(void)
+static void test_qemu_strtou64_full_negative(void)
 {
     const char *str = " \t -321";
     uint64_t res = 999;
     int err;
 
-    err = qemu_strtoull(str, NULL, 0, &res);
+    err = qemu_strtou64(str, NULL, 0, &res);
 
     g_assert_cmpint(err, ==, 0);
     g_assert_cmpuint(res, ==, 18446744073709551295LLU);
 }
 
-static void test_qemu_strtoull_full_trailing(void)
+static void test_qemu_strtou64_full_trailing(void)
 {
     const char *str = "18446744073709551614xxxxxx";
     uint64_t res = 999;
     int err;
 
-    err = qemu_strtoull(str, NULL, 0, &res);
+    err = qemu_strtou64(str, NULL, 0, &res);
 
     g_assert_cmpint(err, ==, -EINVAL);
 }
 
-static void test_qemu_strtoull_full_max(void)
+static void test_qemu_strtou64_full_max(void)
 {
     char *str = g_strdup_printf("%lld", ULLONG_MAX);
     uint64_t res = 999;
     int err;
 
-    err = qemu_strtoull(str, NULL, 0, &res);
+    err = qemu_strtou64(str, NULL, 0, &res);
 
     g_assert_cmpint(err, ==, 0);
     g_assert_cmpuint(res, ==, ULLONG_MAX);
@@ -1471,21 +1471,32 @@ int main(int argc, char **argv)
                     test_parse_uint_full_correct);
 
     /* qemu_strtol() tests */
-    g_test_add_func("/cutils/qemu_strtol/correct", test_qemu_strtol_correct);
-    g_test_add_func("/cutils/qemu_strtol/null", test_qemu_strtol_null);
-    g_test_add_func("/cutils/qemu_strtol/empty", test_qemu_strtol_empty);
+    g_test_add_func("/cutils/qemu_strtol/correct",
+                    test_qemu_strtol_correct);
+    g_test_add_func("/cutils/qemu_strtol/null",
+                    test_qemu_strtol_null);
+    g_test_add_func("/cutils/qemu_strtol/empty",
+                    test_qemu_strtol_empty);
     g_test_add_func("/cutils/qemu_strtol/whitespace",
                     test_qemu_strtol_whitespace);
-    g_test_add_func("/cutils/qemu_strtol/invalid", test_qemu_strtol_invalid);
-    g_test_add_func("/cutils/qemu_strtol/trailing", test_qemu_strtol_trailing);
-    g_test_add_func("/cutils/qemu_strtol/octal", test_qemu_strtol_octal);
-    g_test_add_func("/cutils/qemu_strtol/decimal", test_qemu_strtol_decimal);
-    g_test_add_func("/cutils/qemu_strtol/hex", test_qemu_strtol_hex);
-    g_test_add_func("/cutils/qemu_strtol/max", test_qemu_strtol_max);
-    g_test_add_func("/cutils/qemu_strtol/overflow", test_qemu_strtol_overflow);
+    g_test_add_func("/cutils/qemu_strtol/invalid",
+                    test_qemu_strtol_invalid);
+    g_test_add_func("/cutils/qemu_strtol/trailing",
+                    test_qemu_strtol_trailing);
+    g_test_add_func("/cutils/qemu_strtol/octal",
+                    test_qemu_strtol_octal);
+    g_test_add_func("/cutils/qemu_strtol/decimal",
+                    test_qemu_strtol_decimal);
+    g_test_add_func("/cutils/qemu_strtol/hex",
+                    test_qemu_strtol_hex);
+    g_test_add_func("/cutils/qemu_strtol/max",
+                    test_qemu_strtol_max);
+    g_test_add_func("/cutils/qemu_strtol/overflow",
+                    test_qemu_strtol_overflow);
     g_test_add_func("/cutils/qemu_strtol/underflow",
                     test_qemu_strtol_underflow);
-    g_test_add_func("/cutils/qemu_strtol/negative", test_qemu_strtol_negative);
+    g_test_add_func("/cutils/qemu_strtol/negative",
+                    test_qemu_strtol_negative);
     g_test_add_func("/cutils/qemu_strtol_full/correct",
                     test_qemu_strtol_full_correct);
     g_test_add_func("/cutils/qemu_strtol_full/null",
@@ -1500,18 +1511,26 @@ int main(int argc, char **argv)
                     test_qemu_strtol_full_max);
 
     /* qemu_strtoul() tests */
-    g_test_add_func("/cutils/qemu_strtoul/correct", test_qemu_strtoul_correct);
-    g_test_add_func("/cutils/qemu_strtoul/null", test_qemu_strtoul_null);
-    g_test_add_func("/cutils/qemu_strtoul/empty", test_qemu_strtoul_empty);
+    g_test_add_func("/cutils/qemu_strtoul/correct",
+                    test_qemu_strtoul_correct);
+    g_test_add_func("/cutils/qemu_strtoul/null",
+                    test_qemu_strtoul_null);
+    g_test_add_func("/cutils/qemu_strtoul/empty",
+                    test_qemu_strtoul_empty);
     g_test_add_func("/cutils/qemu_strtoul/whitespace",
                     test_qemu_strtoul_whitespace);
-    g_test_add_func("/cutils/qemu_strtoul/invalid", test_qemu_strtoul_invalid);
+    g_test_add_func("/cutils/qemu_strtoul/invalid",
+                    test_qemu_strtoul_invalid);
     g_test_add_func("/cutils/qemu_strtoul/trailing",
                     test_qemu_strtoul_trailing);
-    g_test_add_func("/cutils/qemu_strtoul/octal", test_qemu_strtoul_octal);
-    g_test_add_func("/cutils/qemu_strtoul/decimal", test_qemu_strtoul_decimal);
-    g_test_add_func("/cutils/qemu_strtoul/hex", test_qemu_strtoul_hex);
-    g_test_add_func("/cutils/qemu_strtoul/max", test_qemu_strtoul_max);
+    g_test_add_func("/cutils/qemu_strtoul/octal",
+                    test_qemu_strtoul_octal);
+    g_test_add_func("/cutils/qemu_strtoul/decimal",
+                    test_qemu_strtoul_decimal);
+    g_test_add_func("/cutils/qemu_strtoul/hex",
+                    test_qemu_strtoul_hex);
+    g_test_add_func("/cutils/qemu_strtoul/max",
+                    test_qemu_strtoul_max);
     g_test_add_func("/cutils/qemu_strtoul/overflow",
                     test_qemu_strtoul_overflow);
     g_test_add_func("/cutils/qemu_strtoul/underflow",
@@ -1531,73 +1550,86 @@ int main(int argc, char **argv)
     g_test_add_func("/cutils/qemu_strtoul_full/max",
                     test_qemu_strtoul_full_max);
 
-    /* qemu_strtoll() tests */
-    g_test_add_func("/cutils/qemu_strtoll/correct", test_qemu_strtoll_correct);
-    g_test_add_func("/cutils/qemu_strtoll/null", test_qemu_strtoll_null);
-    g_test_add_func("/cutils/qemu_strtoll/empty", test_qemu_strtoll_empty);
-    g_test_add_func("/cutils/qemu_strtoll/whitespace",
-                    test_qemu_strtoll_whitespace);
-    g_test_add_func("/cutils/qemu_strtoll/invalid", test_qemu_strtoll_invalid);
-    g_test_add_func("/cutils/qemu_strtoll/trailing",
-                    test_qemu_strtoll_trailing);
-    g_test_add_func("/cutils/qemu_strtoll/octal", test_qemu_strtoll_octal);
-    g_test_add_func("/cutils/qemu_strtoll/decimal", test_qemu_strtoll_decimal);
-    g_test_add_func("/cutils/qemu_strtoll/hex", test_qemu_strtoll_hex);
-    g_test_add_func("/cutils/qemu_strtoll/max", test_qemu_strtoll_max);
-    g_test_add_func("/cutils/qemu_strtoll/overflow",
-                    test_qemu_strtoll_overflow);
-    g_test_add_func("/cutils/qemu_strtoll/underflow",
-                    test_qemu_strtoll_underflow);
-    g_test_add_func("/cutils/qemu_strtoll/negative",
-                    test_qemu_strtoll_negative);
-    g_test_add_func("/cutils/qemu_strtoll_full/correct",
-                    test_qemu_strtoll_full_correct);
-    g_test_add_func("/cutils/qemu_strtoll_full/null",
-                    test_qemu_strtoll_full_null);
-    g_test_add_func("/cutils/qemu_strtoll_full/empty",
-                    test_qemu_strtoll_full_empty);
-    g_test_add_func("/cutils/qemu_strtoll_full/negative",
-                    test_qemu_strtoll_full_negative);
-    g_test_add_func("/cutils/qemu_strtoll_full/trailing",
-                    test_qemu_strtoll_full_trailing);
-    g_test_add_func("/cutils/qemu_strtoll_full/max",
-                    test_qemu_strtoll_full_max);
+    /* qemu_strtoi64() tests */
+    g_test_add_func("/cutils/qemu_strtoi64/correct",
+                    test_qemu_strtoi64_correct);
+    g_test_add_func("/cutils/qemu_strtoi64/null",
+                    test_qemu_strtoi64_null);
+    g_test_add_func("/cutils/qemu_strtoi64/empty",
+                    test_qemu_strtoi64_empty);
+    g_test_add_func("/cutils/qemu_strtoi64/whitespace",
+                    test_qemu_strtoi64_whitespace);
+    g_test_add_func("/cutils/qemu_strtoi64/invalid"
+                    ,
+                    test_qemu_strtoi64_invalid);
+    g_test_add_func("/cutils/qemu_strtoi64/trailing",
+                    test_qemu_strtoi64_trailing);
+    g_test_add_func("/cutils/qemu_strtoi64/octal",
+                    test_qemu_strtoi64_octal);
+    g_test_add_func("/cutils/qemu_strtoi64/decimal",
+                    test_qemu_strtoi64_decimal);
+    g_test_add_func("/cutils/qemu_strtoi64/hex",
+                    test_qemu_strtoi64_hex);
+    g_test_add_func("/cutils/qemu_strtoi64/max",
+                    test_qemu_strtoi64_max);
+    g_test_add_func("/cutils/qemu_strtoi64/overflow",
+                    test_qemu_strtoi64_overflow);
+    g_test_add_func("/cutils/qemu_strtoi64/underflow",
+                    test_qemu_strtoi64_underflow);
+    g_test_add_func("/cutils/qemu_strtoi64/negative",
+                    test_qemu_strtoi64_negative);
+    g_test_add_func("/cutils/qemu_strtoi64_full/correct",
+                    test_qemu_strtoi64_full_correct);
+    g_test_add_func("/cutils/qemu_strtoi64_full/null",
+                    test_qemu_strtoi64_full_null);
+    g_test_add_func("/cutils/qemu_strtoi64_full/empty",
+                    test_qemu_strtoi64_full_empty);
+    g_test_add_func("/cutils/qemu_strtoi64_full/negative",
+                    test_qemu_strtoi64_full_negative);
+    g_test_add_func("/cutils/qemu_strtoi64_full/trailing",
+                    test_qemu_strtoi64_full_trailing);
+    g_test_add_func("/cutils/qemu_strtoi64_full/max",
+                    test_qemu_strtoi64_full_max);
 
-    /* qemu_strtoull() tests */
-    g_test_add_func("/cutils/qemu_strtoull/correct",
-                    test_qemu_strtoull_correct);
-    g_test_add_func("/cutils/qemu_strtoull/null",
-                    test_qemu_strtoull_null);
-    g_test_add_func("/cutils/qemu_strtoull/empty", test_qemu_strtoull_empty);
-    g_test_add_func("/cutils/qemu_strtoull/whitespace",
-                    test_qemu_strtoull_whitespace);
-    g_test_add_func("/cutils/qemu_strtoull/invalid",
-                    test_qemu_strtoull_invalid);
-    g_test_add_func("/cutils/qemu_strtoull/trailing",
-                    test_qemu_strtoull_trailing);
-    g_test_add_func("/cutils/qemu_strtoull/octal", test_qemu_strtoull_octal);
-    g_test_add_func("/cutils/qemu_strtoull/decimal",
-                    test_qemu_strtoull_decimal);
-    g_test_add_func("/cutils/qemu_strtoull/hex", test_qemu_strtoull_hex);
-    g_test_add_func("/cutils/qemu_strtoull/max", test_qemu_strtoull_max);
-    g_test_add_func("/cutils/qemu_strtoull/overflow",
-                    test_qemu_strtoull_overflow);
-    g_test_add_func("/cutils/qemu_strtoull/underflow",
-                    test_qemu_strtoull_underflow);
-    g_test_add_func("/cutils/qemu_strtoull/negative",
-                    test_qemu_strtoull_negative);
-    g_test_add_func("/cutils/qemu_strtoull_full/correct",
-                    test_qemu_strtoull_full_correct);
-    g_test_add_func("/cutils/qemu_strtoull_full/null",
-                    test_qemu_strtoull_full_null);
-    g_test_add_func("/cutils/qemu_strtoull_full/empty",
-                    test_qemu_strtoull_full_empty);
-    g_test_add_func("/cutils/qemu_strtoull_full/negative",
-                    test_qemu_strtoull_full_negative);
-    g_test_add_func("/cutils/qemu_strtoull_full/trailing",
-                    test_qemu_strtoull_full_trailing);
-    g_test_add_func("/cutils/qemu_strtoull_full/max",
-                    test_qemu_strtoull_full_max);
+    /* qemu_strtou64() tests */
+    g_test_add_func("/cutils/qemu_strtou64/correct",
+                    test_qemu_strtou64_correct);
+    g_test_add_func("/cutils/qemu_strtou64/null",
+                    test_qemu_strtou64_null);
+    g_test_add_func("/cutils/qemu_strtou64/empty",
+                    test_qemu_strtou64_empty);
+    g_test_add_func("/cutils/qemu_strtou64/whitespace",
+                    test_qemu_strtou64_whitespace);
+    g_test_add_func("/cutils/qemu_strtou64/invalid",
+                    test_qemu_strtou64_invalid);
+    g_test_add_func("/cutils/qemu_strtou64/trailing",
+                    test_qemu_strtou64_trailing);
+    g_test_add_func("/cutils/qemu_strtou64/octal",
+                    test_qemu_strtou64_octal);
+    g_test_add_func("/cutils/qemu_strtou64/decimal",
+                    test_qemu_strtou64_decimal);
+    g_test_add_func("/cutils/qemu_strtou64/hex",
+                    test_qemu_strtou64_hex);
+    g_test_add_func("/cutils/qemu_strtou64/max",
+                    test_qemu_strtou64_max);
+    g_test_add_func("/cutils/qemu_strtou64/overflow",
+                    test_qemu_strtou64_overflow);
+    g_test_add_func("/cutils/qemu_strtou64/underflow",
+                    test_qemu_strtou64_underflow);
+    g_test_add_func("/cutils/qemu_strtou64/negative",
+                    test_qemu_strtou64_negative);
+    g_test_add_func("/cutils/qemu_strtou64_full/correct",
+                    test_qemu_strtou64_full_correct);
+    g_test_add_func("/cutils/qemu_strtou64_full/null",
+                    test_qemu_strtou64_full_null);
+    g_test_add_func("/cutils/qemu_strtou64_full/empty",
+                    test_qemu_strtou64_full_empty);
+    g_test_add_func("/cutils/qemu_strtou64_full/negative",
+                    test_qemu_strtou64_full_negative);
+    g_test_add_func("/cutils/qemu_strtou64_full/trailing",
+                    test_qemu_strtou64_full_trailing);
+    g_test_add_func("/cutils/qemu_strtou64_full/max",
+                    test_qemu_strtou64_full_max);
 
     g_test_add_func("/cutils/strtosz/simple",
                     test_qemu_strtosz_simple);
diff --git a/util/cutils.c b/util/cutils.c
index 1ae2a08..0dc9b28 100644
--- a/util/cutils.c
+++ b/util/cutils.c
@@ -372,7 +372,7 @@ int qemu_strtoul(const char *nptr, const char **endptr, int base,
  * Works like qemu_strtol(), except it stores INT64_MAX on overflow,
  * and INT_MIN on underflow.
  */
-int qemu_strtoll(const char *nptr, const char **endptr, int base,
+int qemu_strtoi64(const char *nptr, const char **endptr, int base,
                  int64_t *result)
 {
     char *p;
@@ -396,7 +396,7 @@ int qemu_strtoll(const char *nptr, const char **endptr, int base,
  *
  * Works like qemu_strtoul(), except it stores UINT64_MAX on overflow.
  */
-int qemu_strtoull(const char *nptr, const char **endptr, int base,
+int qemu_strtou64(const char *nptr, const char **endptr, int base,
                   uint64_t *result)
 {
     char *p;
diff --git a/util/log.c b/util/log.c
index e077340..96f30dd 100644
--- a/util/log.c
+++ b/util/log.c
@@ -183,13 +183,13 @@ void qemu_set_dfilter_ranges(const char *filter_spec, Error **errp)
             goto out;
         }
 
-        if (qemu_strtoull(r, &e, 0, &r1val)
+        if (qemu_strtou64(r, &e, 0, &r1val)
             || e != range_op) {
             error_setg(errp, "Invalid number to the left of %.*s",
                        (int)(r2 - range_op), range_op);
             goto out;
         }
-        if (qemu_strtoull(r2, NULL, 0, &r2val)) {
+        if (qemu_strtou64(r2, NULL, 0, &r2val)) {
             error_setg(errp, "Invalid number to the right of %.*s",
                        (int)(r2 - range_op), range_op);
             goto out;
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 79+ messages in thread

* [Qemu-devel] [PATCH 07/24] util/cutils: Clean up variable names around qemu_strtol()
  2017-02-14 10:25 [Qemu-devel] [PATCH 00/24] QemuOpts util/cutils: Fix and clean up number conversions Markus Armbruster
                   ` (5 preceding siblings ...)
  2017-02-14 10:25 ` [Qemu-devel] [PATCH 06/24] util/cutils: Rename qemu_strtoll(), qemu_strtoull() Markus Armbruster
@ 2017-02-14 10:25 ` Markus Armbruster
  2017-02-14 12:33   ` Paolo Bonzini
  2017-02-14 21:37   ` Eric Blake
  2017-02-14 10:25 ` [Qemu-devel] [PATCH 08/24] util/cutils: Clean up control flow around qemu_strtol() a bit Markus Armbruster
                   ` (18 subsequent siblings)
  25 siblings, 2 replies; 79+ messages in thread
From: Markus Armbruster @ 2017-02-14 10:25 UTC (permalink / raw)
  To: qemu-devel

Name same things the same, different things differently.

* qemu_strtol()'s parameter @nptr is called @p in
  check_strtox_error().  Rename the latter.

* qemu_strtol()'s parameter @endptr is called @next in
  check_strtox_error().  Rename the latter.

* qemu_strtol()'s variable @p is called @endptr in
  check_strtox_error().  Rename both to @ep.

* qemu_strtol()'s variable @err is *negative* errno,
  check_strtox_error()'s parameter @err is *positive*.  Rename the
  latter to @eno.

Same for qemu_strtoul(), qemu_strtoi64(), qemu_strtou64(), of course.

Signed-off-by: Markus Armbruster <armbru@redhat.com>
---
 util/cutils.c | 42 +++++++++++++++++++++---------------------
 1 file changed, 21 insertions(+), 21 deletions(-)

diff --git a/util/cutils.c b/util/cutils.c
index 0dc9b28..7d165bc 100644
--- a/util/cutils.c
+++ b/util/cutils.c
@@ -260,21 +260,21 @@ int64_t qemu_strtosz(const char *nptr, char **end)
 }
 
 /**
- * Helper function for qemu_strto*l() functions.
+ * Helper function for error checking after strtol() and the like
  */
-static int check_strtox_error(const char *p, char *endptr, const char **next,
-                              int err)
+static int check_strtox_error(const char *nptr, char *ep,
+                              const char **endptr, int eno)
 {
-    if (err == 0 && endptr == p) {
-        err = EINVAL;
+    if (eno == 0 && ep == nptr) {
+        eno = EINVAL;
     }
-    if (!next && *endptr) {
+    if (!endptr && *ep) {
         return -EINVAL;
     }
-    if (next) {
-        *next = endptr;
+    if (endptr) {
+        *endptr = ep;
     }
-    return -err;
+    return -eno;
 }
 
 /**
@@ -304,7 +304,7 @@ static int check_strtox_error(const char *p, char *endptr, const char **next,
 int qemu_strtol(const char *nptr, const char **endptr, int base,
                 long *result)
 {
-    char *p;
+    char *ep;
     int err = 0;
     if (!nptr) {
         if (endptr) {
@@ -313,8 +313,8 @@ int qemu_strtol(const char *nptr, const char **endptr, int base,
         err = -EINVAL;
     } else {
         errno = 0;
-        *result = strtol(nptr, &p, base);
-        err = check_strtox_error(nptr, p, endptr, errno);
+        *result = strtol(nptr, &ep, base);
+        err = check_strtox_error(nptr, ep, endptr, errno);
     }
     return err;
 }
@@ -347,7 +347,7 @@ int qemu_strtol(const char *nptr, const char **endptr, int base,
 int qemu_strtoul(const char *nptr, const char **endptr, int base,
                  unsigned long *result)
 {
-    char *p;
+    char *ep;
     int err = 0;
     if (!nptr) {
         if (endptr) {
@@ -356,12 +356,12 @@ int qemu_strtoul(const char *nptr, const char **endptr, int base,
         err = -EINVAL;
     } else {
         errno = 0;
-        *result = strtoul(nptr, &p, base);
+        *result = strtoul(nptr, &ep, base);
         /* Windows returns 1 for negative out-of-range values.  */
         if (errno == ERANGE) {
             *result = -1;
         }
-        err = check_strtox_error(nptr, p, endptr, errno);
+        err = check_strtox_error(nptr, ep, endptr, errno);
     }
     return err;
 }
@@ -375,7 +375,7 @@ int qemu_strtoul(const char *nptr, const char **endptr, int base,
 int qemu_strtoi64(const char *nptr, const char **endptr, int base,
                  int64_t *result)
 {
-    char *p;
+    char *ep;
     int err = 0;
     if (!nptr) {
         if (endptr) {
@@ -385,8 +385,8 @@ int qemu_strtoi64(const char *nptr, const char **endptr, int base,
     } else {
         errno = 0;
         /* FIXME This assumes int64_t is long long */
-        *result = strtoll(nptr, &p, base);
-        err = check_strtox_error(nptr, p, endptr, errno);
+        *result = strtoll(nptr, &ep, base);
+        err = check_strtox_error(nptr, ep, endptr, errno);
     }
     return err;
 }
@@ -399,7 +399,7 @@ int qemu_strtoi64(const char *nptr, const char **endptr, int base,
 int qemu_strtou64(const char *nptr, const char **endptr, int base,
                   uint64_t *result)
 {
-    char *p;
+    char *ep;
     int err = 0;
     if (!nptr) {
         if (endptr) {
@@ -409,12 +409,12 @@ int qemu_strtou64(const char *nptr, const char **endptr, int base,
     } else {
         errno = 0;
         /* FIXME This assumes uint64_t is unsigned long long */
-        *result = strtoull(nptr, &p, base);
+        *result = strtoull(nptr, &ep, base);
         /* Windows returns 1 for negative out-of-range values.  */
         if (errno == ERANGE) {
             *result = -1;
         }
-        err = check_strtox_error(nptr, p, endptr, errno);
+        err = check_strtox_error(nptr, ep, endptr, errno);
     }
     return err;
 }
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 79+ messages in thread

* [Qemu-devel] [PATCH 08/24] util/cutils: Clean up control flow around qemu_strtol() a bit
  2017-02-14 10:25 [Qemu-devel] [PATCH 00/24] QemuOpts util/cutils: Fix and clean up number conversions Markus Armbruster
                   ` (6 preceding siblings ...)
  2017-02-14 10:25 ` [Qemu-devel] [PATCH 07/24] util/cutils: Clean up variable names around qemu_strtol() Markus Armbruster
@ 2017-02-14 10:25 ` Markus Armbruster
  2017-02-14 10:53   ` Peter Maydell
  2017-02-14 21:40   ` Eric Blake
  2017-02-14 10:25 ` [Qemu-devel] [PATCH 09/24] QemuOpts: Fix to reject numbers that overflow uint64_t Markus Armbruster
                   ` (17 subsequent siblings)
  25 siblings, 2 replies; 79+ messages in thread
From: Markus Armbruster @ 2017-02-14 10:25 UTC (permalink / raw)
  To: qemu-devel

Reorder check_strtox_error() to make it obvious that we always store
through a non-null @endptr.

Transform

    if (some error) {
        error case ...
        err = value for error case;
    } else {
        normal case ...
        err = value for normal case;
    }
    return err;

to

    if (some error) {
        error case ...
        return value for error case;
    }
    normal case ...
    return value for normal case;

Signed-off-by: Markus Armbruster <armbru@redhat.com>
---
 util/cutils.c | 89 ++++++++++++++++++++++++++++++-----------------------------
 1 file changed, 45 insertions(+), 44 deletions(-)

diff --git a/util/cutils.c b/util/cutils.c
index 7d165bc..7442d46 100644
--- a/util/cutils.c
+++ b/util/cutils.c
@@ -265,15 +265,20 @@ int64_t qemu_strtosz(const char *nptr, char **end)
 static int check_strtox_error(const char *nptr, char *ep,
                               const char **endptr, int eno)
 {
-    if (eno == 0 && ep == nptr) {
-        eno = EINVAL;
-    }
-    if (!endptr && *ep) {
-        return -EINVAL;
-    }
     if (endptr) {
         *endptr = ep;
     }
+
+    /* Turn "no conversion" into an error */
+    if (eno == 0 && ep == nptr) {
+        return -EINVAL;
+    }
+
+    /* Fail when we're expected to consume the string, but didn't */
+    if (!endptr && *ep) {
+        return -EINVAL;
+    }
+
     return -eno;
 }
 
@@ -305,18 +310,17 @@ int qemu_strtol(const char *nptr, const char **endptr, int base,
                 long *result)
 {
     char *ep;
-    int err = 0;
+
     if (!nptr) {
         if (endptr) {
             *endptr = nptr;
         }
-        err = -EINVAL;
-    } else {
-        errno = 0;
-        *result = strtol(nptr, &ep, base);
-        err = check_strtox_error(nptr, ep, endptr, errno);
+        return -EINVAL;
     }
-    return err;
+
+    errno = 0;
+    *result = strtol(nptr, &ep, base);
+    return check_strtox_error(nptr, ep, endptr, errno);
 }
 
 /**
@@ -348,22 +352,21 @@ int qemu_strtoul(const char *nptr, const char **endptr, int base,
                  unsigned long *result)
 {
     char *ep;
-    int err = 0;
+
     if (!nptr) {
         if (endptr) {
             *endptr = nptr;
         }
-        err = -EINVAL;
-    } else {
-        errno = 0;
-        *result = strtoul(nptr, &ep, base);
-        /* Windows returns 1 for negative out-of-range values.  */
-        if (errno == ERANGE) {
-            *result = -1;
-        }
-        err = check_strtox_error(nptr, ep, endptr, errno);
+        return -EINVAL;
     }
-    return err;
+
+    errno = 0;
+    *result = strtoul(nptr, &ep, base);
+    /* Windows returns 1 for negative out-of-range values.  */
+    if (errno == ERANGE) {
+        *result = -1;
+    }
+    return check_strtox_error(nptr, ep, endptr, errno);
 }
 
 /**
@@ -376,19 +379,18 @@ int qemu_strtoi64(const char *nptr, const char **endptr, int base,
                  int64_t *result)
 {
     char *ep;
-    int err = 0;
+
     if (!nptr) {
         if (endptr) {
             *endptr = nptr;
         }
-        err = -EINVAL;
-    } else {
-        errno = 0;
-        /* FIXME This assumes int64_t is long long */
-        *result = strtoll(nptr, &ep, base);
-        err = check_strtox_error(nptr, ep, endptr, errno);
+        return -EINVAL;
     }
-    return err;
+
+    errno = 0;
+    /* FIXME This assumes int64_t is long long */
+    *result = strtoll(nptr, &ep, base);
+    return check_strtox_error(nptr, ep, endptr, errno);
 }
 
 /**
@@ -400,23 +402,22 @@ int qemu_strtou64(const char *nptr, const char **endptr, int base,
                   uint64_t *result)
 {
     char *ep;
-    int err = 0;
+
     if (!nptr) {
         if (endptr) {
             *endptr = nptr;
         }
-        err = -EINVAL;
-    } else {
-        errno = 0;
-        /* FIXME This assumes uint64_t is unsigned long long */
-        *result = strtoull(nptr, &ep, base);
-        /* Windows returns 1 for negative out-of-range values.  */
-        if (errno == ERANGE) {
-            *result = -1;
-        }
-        err = check_strtox_error(nptr, ep, endptr, errno);
+        return -EINVAL;
     }
-    return err;
+
+    errno = 0;
+    /* FIXME This assumes uint64_t is unsigned long long */
+    *result = strtoull(nptr, &ep, base);
+    /* Windows returns 1 for negative out-of-range values.  */
+    if (errno == ERANGE) {
+        *result = -1;
+    }
+    return check_strtox_error(nptr, ep, endptr, errno);
 }
 
 /**
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 79+ messages in thread

* [Qemu-devel] [PATCH 09/24] QemuOpts: Fix to reject numbers that overflow uint64_t
  2017-02-14 10:25 [Qemu-devel] [PATCH 00/24] QemuOpts util/cutils: Fix and clean up number conversions Markus Armbruster
                   ` (7 preceding siblings ...)
  2017-02-14 10:25 ` [Qemu-devel] [PATCH 08/24] util/cutils: Clean up control flow around qemu_strtol() a bit Markus Armbruster
@ 2017-02-14 10:25 ` Markus Armbruster
  2017-02-14 21:48   ` Eric Blake
  2017-02-14 10:25 ` [Qemu-devel] [PATCH 10/24] tests/test-cutils: Add missing qemu_strtosz()... endptr checks Markus Armbruster
                   ` (16 subsequent siblings)
  25 siblings, 1 reply; 79+ messages in thread
From: Markus Armbruster @ 2017-02-14 10:25 UTC (permalink / raw)
  To: qemu-devel

parse_option_number() fails to check for overflow after strtoull().
Has always been broken.  Fix that.

Signed-off-by: Markus Armbruster <armbru@redhat.com>
---
 tests/test-qemu-opts.c | 14 ++++++--------
 util/qemu-option.c     | 11 ++++++++---
 2 files changed, 14 insertions(+), 11 deletions(-)

diff --git a/tests/test-qemu-opts.c b/tests/test-qemu-opts.c
index f4426bb..6a9d3c5 100644
--- a/tests/test-qemu-opts.c
+++ b/tests/test-qemu-opts.c
@@ -585,17 +585,15 @@ static void test_opts_parse_number(void)
 
     /* Above upper limit */
     opts = qemu_opts_parse(&opts_list_01, "number1=18446744073709551616",
-                           false, &error_abort);
-    /* BUG: should reject */
-    g_assert_cmpuint(opts_count(opts), ==, 1);
-    g_assert_cmpuint(qemu_opt_get_number(opts, "number1", 1), ==, UINT64_MAX);
+                           false, &err);
+    error_free_or_abort(&err);
+    g_assert(!opts);
 
     /* Below lower limit */
     opts = qemu_opts_parse(&opts_list_01, "number1=-18446744073709551616",
-                           false, &error_abort);
-    /* BUG: should reject */
-    g_assert_cmpuint(opts_count(opts), ==, 1);
-    g_assert_cmpuint(qemu_opt_get_number(opts, "number1", 1), ==, UINT64_MAX);
+                           false, &err);
+    error_free_or_abort(&err);
+    g_assert(!opts);
 
     /* Hex and octal */
     opts = qemu_opts_parse(&opts_list_01, "number1=0x2a,number2=052",
diff --git a/util/qemu-option.c b/util/qemu-option.c
index 2b4e0c9..5d82327 100644
--- a/util/qemu-option.c
+++ b/util/qemu-option.c
@@ -141,11 +141,16 @@ static void parse_option_bool(const char *name, const char *value, bool *ret,
 static void parse_option_number(const char *name, const char *value,
                                 uint64_t *ret, Error **errp)
 {
-    char *postfix;
     uint64_t number;
+    int err;
 
-    number = strtoull(value, &postfix, 0);
-    if (*postfix != '\0') {
+    err = qemu_strtou64(value, NULL, 0, &number);
+    if (err == -ERANGE) {
+        error_setg(errp, "Value '%s' is too large for parameter '%s'",
+                   value, name);
+        return;
+    }
+    if (err) {
         error_setg(errp, QERR_INVALID_PARAMETER_VALUE, name, "a number");
         return;
     }
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 79+ messages in thread

* [Qemu-devel] [PATCH 10/24] tests/test-cutils: Add missing qemu_strtosz()... endptr checks
  2017-02-14 10:25 [Qemu-devel] [PATCH 00/24] QemuOpts util/cutils: Fix and clean up number conversions Markus Armbruster
                   ` (8 preceding siblings ...)
  2017-02-14 10:25 ` [Qemu-devel] [PATCH 09/24] QemuOpts: Fix to reject numbers that overflow uint64_t Markus Armbruster
@ 2017-02-14 10:25 ` Markus Armbruster
  2017-02-14 22:26   ` Eric Blake
  2017-02-19  4:16   ` Philippe Mathieu-Daudé
  2017-02-14 10:25 ` [Qemu-devel] [PATCH 11/24] tests/test-cutils: Cover qemu_strtosz() invalid input Markus Armbruster
                   ` (15 subsequent siblings)
  25 siblings, 2 replies; 79+ messages in thread
From: Markus Armbruster @ 2017-02-14 10:25 UTC (permalink / raw)
  To: qemu-devel

Signed-off-by: Markus Armbruster <armbru@redhat.com>
---
 tests/test-cutils.c | 37 ++++++++++++++++++++++++++-----------
 1 file changed, 26 insertions(+), 11 deletions(-)

diff --git a/tests/test-cutils.c b/tests/test-cutils.c
index 47cc8a4..2dc6832 100644
--- a/tests/test-cutils.c
+++ b/tests/test-cutils.c
@@ -1393,60 +1393,75 @@ static void test_qemu_strtosz_units(void)
     const char *t = "1T";
     const char *p = "1P";
     const char *e = "1E";
+    char *endptr = NULL;
     int64_t res;
 
     /* default is M */
-    res = qemu_strtosz(none, NULL);
+    res = qemu_strtosz(none, &endptr);
     g_assert_cmpint(res, ==, M_BYTE);
+    g_assert(endptr == none + 1);
 
-    res = qemu_strtosz(b, NULL);
+    res = qemu_strtosz(b, &endptr);
     g_assert_cmpint(res, ==, 1);
+    g_assert(endptr == b + 2);
 
-    res = qemu_strtosz(k, NULL);
+    res = qemu_strtosz(k, &endptr);
     g_assert_cmpint(res, ==, K_BYTE);
+    g_assert(endptr == k + 2);
 
-    res = qemu_strtosz(m, NULL);
+    res = qemu_strtosz(m, &endptr);
     g_assert_cmpint(res, ==, M_BYTE);
+    g_assert(endptr == m + 2);
 
-    res = qemu_strtosz(g, NULL);
+    res = qemu_strtosz(g, &endptr);
     g_assert_cmpint(res, ==, G_BYTE);
+    g_assert(endptr == g + 2);
 
-    res = qemu_strtosz(t, NULL);
+    res = qemu_strtosz(t, &endptr);
     g_assert_cmpint(res, ==, T_BYTE);
+    g_assert(endptr == t + 2);
 
-    res = qemu_strtosz(p, NULL);
+    res = qemu_strtosz(p, &endptr);
     g_assert_cmpint(res, ==, P_BYTE);
+    g_assert(endptr == p + 2);
 
-    res = qemu_strtosz(e, NULL);
+    res = qemu_strtosz(e, &endptr);
     g_assert_cmpint(res, ==, E_BYTE);
+    g_assert(endptr == e + 2);
 }
 
 static void test_qemu_strtosz_float(void)
 {
     const char *str = "12.345M";
+    char *endptr = NULL;
     int64_t res;
 
-    res = qemu_strtosz(str, NULL);
+    res = qemu_strtosz(str, &endptr);
     g_assert_cmpint(res, ==, 12.345 * M_BYTE);
+    g_assert(endptr == str + 7);
 }
 
 static void test_qemu_strtosz_erange(void)
 {
     const char *str = "10E";
+    char *endptr = NULL;
     int64_t res;
 
-    res = qemu_strtosz(str, NULL);
+    res = qemu_strtosz(str, &endptr);
     g_assert_cmpint(res, ==, -ERANGE);
+    g_assert(endptr == str + 3);
 }
 
 static void test_qemu_strtosz_suffix_unit(void)
 {
     const char *str = "12345";
+    char *endptr = NULL;
     int64_t res;
 
-    res = qemu_strtosz_suffix_unit(str, NULL,
+    res = qemu_strtosz_suffix_unit(str, &endptr,
                                    QEMU_STRTOSZ_DEFSUFFIX_KB, 1000);
     g_assert_cmpint(res, ==, 12345000);
+    g_assert(endptr == str + 5);
 }
 
 int main(int argc, char **argv)
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 79+ messages in thread

* [Qemu-devel] [PATCH 11/24] tests/test-cutils: Cover qemu_strtosz() invalid input
  2017-02-14 10:25 [Qemu-devel] [PATCH 00/24] QemuOpts util/cutils: Fix and clean up number conversions Markus Armbruster
                   ` (9 preceding siblings ...)
  2017-02-14 10:25 ` [Qemu-devel] [PATCH 10/24] tests/test-cutils: Add missing qemu_strtosz()... endptr checks Markus Armbruster
@ 2017-02-14 10:25 ` Markus Armbruster
  2017-02-14 22:53   ` Eric Blake
  2017-02-14 10:25 ` [Qemu-devel] [PATCH 12/24] tests/test-cutils: Cover qemu_strtosz() with trailing crap Markus Armbruster
                   ` (14 subsequent siblings)
  25 siblings, 1 reply; 79+ messages in thread
From: Markus Armbruster @ 2017-02-14 10:25 UTC (permalink / raw)
  To: qemu-devel

Signed-off-by: Markus Armbruster <armbru@redhat.com>
---
 tests/test-cutils.c | 24 ++++++++++++++++++++++++
 1 file changed, 24 insertions(+)

diff --git a/tests/test-cutils.c b/tests/test-cutils.c
index 2dc6832..3dcd4c1 100644
--- a/tests/test-cutils.c
+++ b/tests/test-cutils.c
@@ -1441,6 +1441,28 @@ static void test_qemu_strtosz_float(void)
     g_assert(endptr == str + 7);
 }
 
+static void test_qemu_strtosz_invalid(void)
+{
+    const char *str;
+    char *endptr = NULL;
+    int64_t res;
+
+    str = "";
+    res = qemu_strtosz(str, &endptr);
+    g_assert_cmpint(res, ==, -EINVAL);
+    g_assert(endptr == str);
+
+    str = " \t ";
+    res = qemu_strtosz(str, &endptr);
+    g_assert_cmpint(res, ==, -EINVAL);
+    g_assert(endptr == str);
+
+    str = "crap";
+    res = qemu_strtosz(str, &endptr);
+    g_assert_cmpint(res, ==, -EINVAL);
+    g_assert(endptr == str);
+}
+
 static void test_qemu_strtosz_erange(void)
 {
     const char *str = "10E";
@@ -1652,6 +1674,8 @@ int main(int argc, char **argv)
                     test_qemu_strtosz_units);
     g_test_add_func("/cutils/strtosz/float",
                     test_qemu_strtosz_float);
+    g_test_add_func("/cutils/strtosz/invalid",
+                    test_qemu_strtosz_invalid);
     g_test_add_func("/cutils/strtosz/erange",
                     test_qemu_strtosz_erange);
     g_test_add_func("/cutils/strtosz/suffix-unit",
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 79+ messages in thread

* [Qemu-devel] [PATCH 12/24] tests/test-cutils: Cover qemu_strtosz() with trailing crap
  2017-02-14 10:25 [Qemu-devel] [PATCH 00/24] QemuOpts util/cutils: Fix and clean up number conversions Markus Armbruster
                   ` (10 preceding siblings ...)
  2017-02-14 10:25 ` [Qemu-devel] [PATCH 11/24] tests/test-cutils: Cover qemu_strtosz() invalid input Markus Armbruster
@ 2017-02-14 10:25 ` Markus Armbruster
  2017-02-14 22:58   ` Eric Blake
  2017-02-14 10:26 ` [Qemu-devel] [PATCH 13/24] tests/test-cutils: Cover qemu_strtosz() around range limits Markus Armbruster
                   ` (13 subsequent siblings)
  25 siblings, 1 reply; 79+ messages in thread
From: Markus Armbruster @ 2017-02-14 10:25 UTC (permalink / raw)
  To: qemu-devel

Signed-off-by: Markus Armbruster <armbru@redhat.com>
---
 tests/test-cutils.c | 19 +++++++++++++++++++
 1 file changed, 19 insertions(+)

diff --git a/tests/test-cutils.c b/tests/test-cutils.c
index 3dcd4c1..ec65d27 100644
--- a/tests/test-cutils.c
+++ b/tests/test-cutils.c
@@ -1463,6 +1463,23 @@ static void test_qemu_strtosz_invalid(void)
     g_assert(endptr == str);
 }
 
+static void test_qemu_strtosz_trailing(void)
+{
+    const char *str;
+    char *endptr = NULL;
+    int64_t res;
+
+    str = "123xxx";
+    res = qemu_strtosz(str, &endptr);
+    g_assert_cmpint(res, ==, 123 * M_BYTE);
+    g_assert(endptr == str + 3);
+
+    str = "1kiB";
+    res = qemu_strtosz(str, &endptr);
+    g_assert_cmpint(res, ==, 1024);
+    g_assert(endptr == str + 2);
+}
+
 static void test_qemu_strtosz_erange(void)
 {
     const char *str = "10E";
@@ -1676,6 +1693,8 @@ int main(int argc, char **argv)
                     test_qemu_strtosz_float);
     g_test_add_func("/cutils/strtosz/invalid",
                     test_qemu_strtosz_invalid);
+    g_test_add_func("/cutils/strtosz/trailing",
+                    test_qemu_strtosz_trailing);
     g_test_add_func("/cutils/strtosz/erange",
                     test_qemu_strtosz_erange);
     g_test_add_func("/cutils/strtosz/suffix-unit",
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 79+ messages in thread

* [Qemu-devel] [PATCH 13/24] tests/test-cutils: Cover qemu_strtosz() around range limits
  2017-02-14 10:25 [Qemu-devel] [PATCH 00/24] QemuOpts util/cutils: Fix and clean up number conversions Markus Armbruster
                   ` (11 preceding siblings ...)
  2017-02-14 10:25 ` [Qemu-devel] [PATCH 12/24] tests/test-cutils: Cover qemu_strtosz() with trailing crap Markus Armbruster
@ 2017-02-14 10:26 ` Markus Armbruster
  2017-02-14 23:14   ` Eric Blake
  2017-02-14 10:26 ` [Qemu-devel] [PATCH 14/24] util/cutils: New qemu_strtosz_metric() Markus Armbruster
                   ` (12 subsequent siblings)
  25 siblings, 1 reply; 79+ messages in thread
From: Markus Armbruster @ 2017-02-14 10:26 UTC (permalink / raw)
  To: qemu-devel

Signed-off-by: Markus Armbruster <armbru@redhat.com>
---
 tests/test-cutils.c | 61 +++++++++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 59 insertions(+), 2 deletions(-)

diff --git a/tests/test-cutils.c b/tests/test-cutils.c
index ec65d27..af52ac5 100644
--- a/tests/test-cutils.c
+++ b/tests/test-cutils.c
@@ -1371,16 +1371,52 @@ static void test_qemu_strtou64_full_max(void)
 
 static void test_qemu_strtosz_simple(void)
 {
-    const char *str = "12345M";
+    const char *str;
     char *endptr = NULL;
     int64_t res;
 
+    str = "0";
+    res = qemu_strtosz(str, &endptr);
+    g_assert_cmpint(res, ==, 0);
+    g_assert(endptr == str + 1);
+
+    str = "12345M";
     res = qemu_strtosz(str, &endptr);
     g_assert_cmpint(res, ==, 12345 * M_BYTE);
     g_assert(endptr == str + 6);
 
     res = qemu_strtosz(str, NULL);
     g_assert_cmpint(res, ==, 12345 * M_BYTE);
+
+    /* Note: precision is 53 bits since we're parsing with strtod() */
+
+    str = "9007199254740991"; /* 2^53-1 */
+    res = qemu_strtosz_suffix(str, &endptr, QEMU_STRTOSZ_DEFSUFFIX_B);
+    g_assert_cmpint(res, ==, 0x1fffffffffffff);
+    g_assert(endptr == str + 16);
+
+    str = "9007199254740992"; /* 2^53 */
+    res = qemu_strtosz_suffix(str, &endptr, QEMU_STRTOSZ_DEFSUFFIX_B);
+    g_assert_cmpint(res, ==, 0x20000000000000);
+    g_assert(endptr == str + 16);
+
+    str = "9007199254740993"; /* 2^53+1 */
+    res = qemu_strtosz_suffix(str, &endptr, QEMU_STRTOSZ_DEFSUFFIX_B);
+    g_assert_cmpint(res, ==, 0x20000000000000); /* rounded to 53 bits */
+    g_assert(endptr == str + 16);
+
+    str = "9223372036854774784"; /* 0x7ffffffffffffc00 (53 msbs set) */
+    res = qemu_strtosz_suffix(str, &endptr, QEMU_STRTOSZ_DEFSUFFIX_B);
+    g_assert_cmpint(res, ==, 0x7ffffffffffffc00);
+    g_assert(endptr == str + 19);
+
+    str = "9223372036854775295"; /* 0x7ffffffffffffdff */
+    res = qemu_strtosz_suffix(str, &endptr, QEMU_STRTOSZ_DEFSUFFIX_B);
+    g_assert_cmpint(res, ==, 0x7ffffffffffffc00); /* rounded to 53 bits */
+    g_assert(endptr == str + 19);
+
+    /* 0x7ffffffffffffe00..0x7fffffffffffffff get rounded to
+     * 0x8000000000000000, thus -ERANGE; see test_qemu_strtosz_erange() */
 }
 
 static void test_qemu_strtosz_units(void)
@@ -1482,10 +1518,31 @@ static void test_qemu_strtosz_trailing(void)
 
 static void test_qemu_strtosz_erange(void)
 {
-    const char *str = "10E";
+    const char *str;
     char *endptr = NULL;
     int64_t res;
 
+    str = "-1";
+    res = qemu_strtosz(str, &endptr);
+    g_assert_cmpint(res, ==, -ERANGE);
+    g_assert(endptr == str + 2);
+
+    str = "9223372036854775296"; /* 0x7ffffffffffffe00 */
+    res = qemu_strtosz_suffix(str, &endptr, QEMU_STRTOSZ_DEFSUFFIX_B);
+    g_assert_cmpint(res, ==, -ERANGE);
+    g_assert(endptr == str + 19);
+
+    str = "9223372036854775807"; /* 2^63-1 */
+    res = qemu_strtosz_suffix(str, &endptr, QEMU_STRTOSZ_DEFSUFFIX_B);
+    g_assert_cmpint(res, ==, -ERANGE);
+    g_assert(endptr == str + 19);
+
+    str = "9223372036854775808"; /* 2^63 */
+    res = qemu_strtosz_suffix(str, &endptr, QEMU_STRTOSZ_DEFSUFFIX_B);
+    g_assert_cmpint(res, ==, -ERANGE);
+    g_assert(endptr == str + 19);
+
+    str = "10E";
     res = qemu_strtosz(str, &endptr);
     g_assert_cmpint(res, ==, -ERANGE);
     g_assert(endptr == str + 3);
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 79+ messages in thread

* [Qemu-devel] [PATCH 14/24] util/cutils: New qemu_strtosz_metric()
  2017-02-14 10:25 [Qemu-devel] [PATCH 00/24] QemuOpts util/cutils: Fix and clean up number conversions Markus Armbruster
                   ` (12 preceding siblings ...)
  2017-02-14 10:26 ` [Qemu-devel] [PATCH 13/24] tests/test-cutils: Cover qemu_strtosz() around range limits Markus Armbruster
@ 2017-02-14 10:26 ` Markus Armbruster
  2017-02-17 20:44   ` Eric Blake
  2017-02-14 10:26 ` [Qemu-devel] [PATCH 15/24] util/cutils: Rename qemu_strtosz() to qemu_strtosz_mebi() Markus Armbruster
                   ` (11 subsequent siblings)
  25 siblings, 1 reply; 79+ messages in thread
From: Markus Armbruster @ 2017-02-14 10:26 UTC (permalink / raw)
  To: qemu-devel

To parse numbers with metric suffixes, we use

    qemu_strtosz_suffix_unit(nptr, &eptr, QEMU_STRTOSZ_DEFSUFFIX_B, 1000)

Capture this in a new function for legibility:

    qemu_strtosz_metric(nptr, &eptr)

Replace test_qemu_strtosz_suffix_unit() by test_qemu_strtosz_metric().

Rename qemu_strtosz_suffix_unit() to do_strtosz() and give it internal
linkage.

Signed-off-by: Markus Armbruster <armbru@redhat.com>
---
 include/qemu/cutils.h |  4 ++--
 target/i386/cpu.c     |  3 +--
 tests/test-cutils.c   | 13 ++++++-------
 util/cutils.c         | 11 ++++++++---
 4 files changed, 17 insertions(+), 14 deletions(-)

diff --git a/include/qemu/cutils.h b/include/qemu/cutils.h
index f922223..81613d0 100644
--- a/include/qemu/cutils.h
+++ b/include/qemu/cutils.h
@@ -156,8 +156,8 @@ int parse_uint_full(const char *s, unsigned long long *value, int base);
 int64_t qemu_strtosz(const char *nptr, char **end);
 int64_t qemu_strtosz_suffix(const char *nptr, char **end,
                             const char default_suffix);
-int64_t qemu_strtosz_suffix_unit(const char *nptr, char **end,
-                            const char default_suffix, int64_t unit);
+int64_t qemu_strtosz_metric(const char *nptr, char **end);
+
 #define K_BYTE     (1ULL << 10)
 #define M_BYTE     (1ULL << 20)
 #define G_BYTE     (1ULL << 30)
diff --git a/target/i386/cpu.c b/target/i386/cpu.c
index eb49980..3a8d72d 100644
--- a/target/i386/cpu.c
+++ b/target/i386/cpu.c
@@ -2036,8 +2036,7 @@ static void x86_cpu_parse_featurestr(const char *typename, char *features,
             int64_t tsc_freq;
             char *err;
 
-            tsc_freq = qemu_strtosz_suffix_unit(val, &err,
-                                           QEMU_STRTOSZ_DEFSUFFIX_B, 1000);
+            tsc_freq = qemu_strtosz_metric(val, &err);
             if (tsc_freq < 0 || *err) {
                 error_setg(errp, "bad numerical value %s", val);
                 return;
diff --git a/tests/test-cutils.c b/tests/test-cutils.c
index af52ac5..383f812 100644
--- a/tests/test-cutils.c
+++ b/tests/test-cutils.c
@@ -1548,16 +1548,15 @@ static void test_qemu_strtosz_erange(void)
     g_assert(endptr == str + 3);
 }
 
-static void test_qemu_strtosz_suffix_unit(void)
+static void test_qemu_strtosz_metric(void)
 {
-    const char *str = "12345";
+    const char *str = "12345k";
     char *endptr = NULL;
     int64_t res;
 
-    res = qemu_strtosz_suffix_unit(str, &endptr,
-                                   QEMU_STRTOSZ_DEFSUFFIX_KB, 1000);
+    res = qemu_strtosz_metric(str, &endptr);
     g_assert_cmpint(res, ==, 12345000);
-    g_assert(endptr == str + 5);
+    g_assert(endptr == str + 6);
 }
 
 int main(int argc, char **argv)
@@ -1754,8 +1753,8 @@ int main(int argc, char **argv)
                     test_qemu_strtosz_trailing);
     g_test_add_func("/cutils/strtosz/erange",
                     test_qemu_strtosz_erange);
-    g_test_add_func("/cutils/strtosz/suffix-unit",
-                    test_qemu_strtosz_suffix_unit);
+    g_test_add_func("/cutils/strtosz/metric",
+                    test_qemu_strtosz_metric);
 
     return g_test_run();
 }
diff --git a/util/cutils.c b/util/cutils.c
index 7442d46..8a506e7 100644
--- a/util/cutils.c
+++ b/util/cutils.c
@@ -205,8 +205,8 @@ static int64_t suffix_mul(char suffix, int64_t unit)
  * in *end, if not NULL. Return -ERANGE on overflow, Return -EINVAL on
  * other error.
  */
-int64_t qemu_strtosz_suffix_unit(const char *nptr, char **end,
-                            const char default_suffix, int64_t unit)
+static int64_t do_strtosz(const char *nptr, char **end,
+                          const char default_suffix, int64_t unit)
 {
     int64_t retval = -EINVAL;
     char *endptr;
@@ -251,7 +251,7 @@ fail:
 int64_t qemu_strtosz_suffix(const char *nptr, char **end,
                             const char default_suffix)
 {
-    return qemu_strtosz_suffix_unit(nptr, end, default_suffix, 1024);
+    return do_strtosz(nptr, end, default_suffix, 1024);
 }
 
 int64_t qemu_strtosz(const char *nptr, char **end)
@@ -259,6 +259,11 @@ int64_t qemu_strtosz(const char *nptr, char **end)
     return qemu_strtosz_suffix(nptr, end, QEMU_STRTOSZ_DEFSUFFIX_MB);
 }
 
+int64_t qemu_strtosz_metric(const char *nptr, char **end)
+{
+    return do_strtosz(nptr, end, QEMU_STRTOSZ_DEFSUFFIX_B, 1000);
+}
+
 /**
  * Helper function for error checking after strtol() and the like
  */
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 79+ messages in thread

* [Qemu-devel] [PATCH 15/24] util/cutils: Rename qemu_strtosz() to qemu_strtosz_mebi()
  2017-02-14 10:25 [Qemu-devel] [PATCH 00/24] QemuOpts util/cutils: Fix and clean up number conversions Markus Armbruster
                   ` (13 preceding siblings ...)
  2017-02-14 10:26 ` [Qemu-devel] [PATCH 14/24] util/cutils: New qemu_strtosz_metric() Markus Armbruster
@ 2017-02-14 10:26 ` Markus Armbruster
  2017-02-14 12:35   ` Paolo Bonzini
  2017-02-17 20:45   ` Eric Blake
  2017-02-14 10:26 ` [Qemu-devel] [PATCH 16/24] util/cutils: New qemu_strtosz() Markus Armbruster
                   ` (10 subsequent siblings)
  25 siblings, 2 replies; 79+ messages in thread
From: Markus Armbruster @ 2017-02-14 10:26 UTC (permalink / raw)
  To: qemu-devel

With qemu_strtosz(), no suffix means mebibytes.  It's used rarely.
I'm going to add a similar function where no suffix means bytes.
Rename qemu_strtosz() to qemu_strtosz_mebi() to make the name
qemu_strtosz() available for the new function.

Signed-off-by: Markus Armbruster <armbru@redhat.com>
---
 hmp.c                 |  2 +-
 hw/misc/ivshmem.c     |  2 +-
 include/qemu/cutils.h |  2 +-
 monitor.c             |  2 +-
 tests/test-cutils.c   | 38 +++++++++++++++++++-------------------
 util/cutils.c         |  2 +-
 6 files changed, 24 insertions(+), 24 deletions(-)

diff --git a/hmp.c b/hmp.c
index 2bc4f06..6d0d05b 100644
--- a/hmp.c
+++ b/hmp.c
@@ -1379,7 +1379,7 @@ void hmp_migrate_set_parameter(Monitor *mon, const QDict *qdict)
                 break;
             case MIGRATION_PARAMETER_MAX_BANDWIDTH:
                 p.has_max_bandwidth = true;
-                valuebw = qemu_strtosz(valuestr, &endp);
+                valuebw = qemu_strtosz_mebi(valuestr, &endp);
                 if (valuebw < 0 || (size_t)valuebw != valuebw
                     || *endp != '\0') {
                     error_setg(&err, "Invalid size %s", valuestr);
diff --git a/hw/misc/ivshmem.c b/hw/misc/ivshmem.c
index bf57e63..382dd8b 100644
--- a/hw/misc/ivshmem.c
+++ b/hw/misc/ivshmem.c
@@ -1268,7 +1268,7 @@ static void ivshmem_realize(PCIDevice *dev, Error **errp)
         s->legacy_size = 4 << 20; /* 4 MB default */
     } else {
         char *end;
-        int64_t size = qemu_strtosz(s->sizearg, &end);
+        int64_t size = qemu_strtosz_mebi(s->sizearg, &end);
         if (size < 0 || (size_t)size != size || *end != '\0'
             || !is_power_of_2(size)) {
             error_setg(errp, "Invalid size %s", s->sizearg);
diff --git a/include/qemu/cutils.h b/include/qemu/cutils.h
index 81613d0..5f4e138 100644
--- a/include/qemu/cutils.h
+++ b/include/qemu/cutils.h
@@ -153,9 +153,9 @@ int parse_uint_full(const char *s, unsigned long long *value, int base);
 #define QEMU_STRTOSZ_DEFSUFFIX_MB 'M'
 #define QEMU_STRTOSZ_DEFSUFFIX_KB 'K'
 #define QEMU_STRTOSZ_DEFSUFFIX_B 'B'
-int64_t qemu_strtosz(const char *nptr, char **end);
 int64_t qemu_strtosz_suffix(const char *nptr, char **end,
                             const char default_suffix);
+int64_t qemu_strtosz_mebi(const char *nptr, char **end);
 int64_t qemu_strtosz_metric(const char *nptr, char **end);
 
 #define K_BYTE     (1ULL << 10)
diff --git a/monitor.c b/monitor.c
index 3cd72a9..1f8c031 100644
--- a/monitor.c
+++ b/monitor.c
@@ -2785,7 +2785,7 @@ static QDict *monitor_parse_arguments(Monitor *mon,
                         break;
                     }
                 }
-                val = qemu_strtosz(p, &end);
+                val = qemu_strtosz_mebi(p, &end);
                 if (val < 0) {
                     monitor_printf(mon, "invalid size\n");
                     goto fail;
diff --git a/tests/test-cutils.c b/tests/test-cutils.c
index 383f812..86d36b7 100644
--- a/tests/test-cutils.c
+++ b/tests/test-cutils.c
@@ -1376,16 +1376,16 @@ static void test_qemu_strtosz_simple(void)
     int64_t res;
 
     str = "0";
-    res = qemu_strtosz(str, &endptr);
+    res = qemu_strtosz_mebi(str, &endptr);
     g_assert_cmpint(res, ==, 0);
     g_assert(endptr == str + 1);
 
     str = "12345M";
-    res = qemu_strtosz(str, &endptr);
+    res = qemu_strtosz_mebi(str, &endptr);
     g_assert_cmpint(res, ==, 12345 * M_BYTE);
     g_assert(endptr == str + 6);
 
-    res = qemu_strtosz(str, NULL);
+    res = qemu_strtosz_mebi(str, NULL);
     g_assert_cmpint(res, ==, 12345 * M_BYTE);
 
     /* Note: precision is 53 bits since we're parsing with strtod() */
@@ -1433,35 +1433,35 @@ static void test_qemu_strtosz_units(void)
     int64_t res;
 
     /* default is M */
-    res = qemu_strtosz(none, &endptr);
+    res = qemu_strtosz_mebi(none, &endptr);
     g_assert_cmpint(res, ==, M_BYTE);
     g_assert(endptr == none + 1);
 
-    res = qemu_strtosz(b, &endptr);
+    res = qemu_strtosz_mebi(b, &endptr);
     g_assert_cmpint(res, ==, 1);
     g_assert(endptr == b + 2);
 
-    res = qemu_strtosz(k, &endptr);
+    res = qemu_strtosz_mebi(k, &endptr);
     g_assert_cmpint(res, ==, K_BYTE);
     g_assert(endptr == k + 2);
 
-    res = qemu_strtosz(m, &endptr);
+    res = qemu_strtosz_mebi(m, &endptr);
     g_assert_cmpint(res, ==, M_BYTE);
     g_assert(endptr == m + 2);
 
-    res = qemu_strtosz(g, &endptr);
+    res = qemu_strtosz_mebi(g, &endptr);
     g_assert_cmpint(res, ==, G_BYTE);
     g_assert(endptr == g + 2);
 
-    res = qemu_strtosz(t, &endptr);
+    res = qemu_strtosz_mebi(t, &endptr);
     g_assert_cmpint(res, ==, T_BYTE);
     g_assert(endptr == t + 2);
 
-    res = qemu_strtosz(p, &endptr);
+    res = qemu_strtosz_mebi(p, &endptr);
     g_assert_cmpint(res, ==, P_BYTE);
     g_assert(endptr == p + 2);
 
-    res = qemu_strtosz(e, &endptr);
+    res = qemu_strtosz_mebi(e, &endptr);
     g_assert_cmpint(res, ==, E_BYTE);
     g_assert(endptr == e + 2);
 }
@@ -1472,7 +1472,7 @@ static void test_qemu_strtosz_float(void)
     char *endptr = NULL;
     int64_t res;
 
-    res = qemu_strtosz(str, &endptr);
+    res = qemu_strtosz_mebi(str, &endptr);
     g_assert_cmpint(res, ==, 12.345 * M_BYTE);
     g_assert(endptr == str + 7);
 }
@@ -1484,17 +1484,17 @@ static void test_qemu_strtosz_invalid(void)
     int64_t res;
 
     str = "";
-    res = qemu_strtosz(str, &endptr);
+    res = qemu_strtosz_mebi(str, &endptr);
     g_assert_cmpint(res, ==, -EINVAL);
     g_assert(endptr == str);
 
     str = " \t ";
-    res = qemu_strtosz(str, &endptr);
+    res = qemu_strtosz_mebi(str, &endptr);
     g_assert_cmpint(res, ==, -EINVAL);
     g_assert(endptr == str);
 
     str = "crap";
-    res = qemu_strtosz(str, &endptr);
+    res = qemu_strtosz_mebi(str, &endptr);
     g_assert_cmpint(res, ==, -EINVAL);
     g_assert(endptr == str);
 }
@@ -1506,12 +1506,12 @@ static void test_qemu_strtosz_trailing(void)
     int64_t res;
 
     str = "123xxx";
-    res = qemu_strtosz(str, &endptr);
+    res = qemu_strtosz_mebi(str, &endptr);
     g_assert_cmpint(res, ==, 123 * M_BYTE);
     g_assert(endptr == str + 3);
 
     str = "1kiB";
-    res = qemu_strtosz(str, &endptr);
+    res = qemu_strtosz_mebi(str, &endptr);
     g_assert_cmpint(res, ==, 1024);
     g_assert(endptr == str + 2);
 }
@@ -1523,7 +1523,7 @@ static void test_qemu_strtosz_erange(void)
     int64_t res;
 
     str = "-1";
-    res = qemu_strtosz(str, &endptr);
+    res = qemu_strtosz_mebi(str, &endptr);
     g_assert_cmpint(res, ==, -ERANGE);
     g_assert(endptr == str + 2);
 
@@ -1543,7 +1543,7 @@ static void test_qemu_strtosz_erange(void)
     g_assert(endptr == str + 19);
 
     str = "10E";
-    res = qemu_strtosz(str, &endptr);
+    res = qemu_strtosz_mebi(str, &endptr);
     g_assert_cmpint(res, ==, -ERANGE);
     g_assert(endptr == str + 3);
 }
diff --git a/util/cutils.c b/util/cutils.c
index 8a506e7..0315d5d 100644
--- a/util/cutils.c
+++ b/util/cutils.c
@@ -254,7 +254,7 @@ int64_t qemu_strtosz_suffix(const char *nptr, char **end,
     return do_strtosz(nptr, end, default_suffix, 1024);
 }
 
-int64_t qemu_strtosz(const char *nptr, char **end)
+int64_t qemu_strtosz_mebi(const char *nptr, char **end)
 {
     return qemu_strtosz_suffix(nptr, end, QEMU_STRTOSZ_DEFSUFFIX_MB);
 }
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 79+ messages in thread

* [Qemu-devel] [PATCH 16/24] util/cutils: New qemu_strtosz()
  2017-02-14 10:25 [Qemu-devel] [PATCH 00/24] QemuOpts util/cutils: Fix and clean up number conversions Markus Armbruster
                   ` (14 preceding siblings ...)
  2017-02-14 10:26 ` [Qemu-devel] [PATCH 15/24] util/cutils: Rename qemu_strtosz() to qemu_strtosz_mebi() Markus Armbruster
@ 2017-02-14 10:26 ` Markus Armbruster
  2017-02-17 20:48   ` Eric Blake
  2017-02-14 10:26 ` [Qemu-devel] [PATCH 17/24] util/cutils: Drop QEMU_STRTOSZ_DEFSUFFIX_* macros Markus Armbruster
                   ` (9 subsequent siblings)
  25 siblings, 1 reply; 79+ messages in thread
From: Markus Armbruster @ 2017-02-14 10:26 UTC (permalink / raw)
  To: qemu-devel

Most callers of qemu_strtosz_suffix() pass QEMU_STRTOSZ_DEFSUFFIX_B.
Capture the pattern in new qemu_strtosz().

Inline qemu_strtosz_suffix() into its only remaining caller.

Signed-off-by: Markus Armbruster <armbru@redhat.com>
---
 include/qemu/cutils.h | 17 +----------------
 qapi/opts-visitor.c   |  3 +--
 qemu-img.c            | 18 ++++++++----------
 qemu-io-cmds.c        |  2 +-
 tests/test-cutils.c   | 16 ++++++++--------
 util/cutils.c         | 15 +++++++++++----
 6 files changed, 30 insertions(+), 41 deletions(-)

diff --git a/include/qemu/cutils.h b/include/qemu/cutils.h
index 5f4e138..4184851 100644
--- a/include/qemu/cutils.h
+++ b/include/qemu/cutils.h
@@ -139,22 +139,7 @@ int parse_uint(const char *s, unsigned long long *value, char **endptr,
                int base);
 int parse_uint_full(const char *s, unsigned long long *value, int base);
 
-/*
- * qemu_strtosz() suffixes used to specify the default treatment of an
- * argument passed to qemu_strtosz() without an explicit suffix.
- * These should be defined using upper case characters in the range
- * A-Z, as qemu_strtosz() will use qemu_toupper() on the given argument
- * prior to comparison.
- */
-#define QEMU_STRTOSZ_DEFSUFFIX_EB 'E'
-#define QEMU_STRTOSZ_DEFSUFFIX_PB 'P'
-#define QEMU_STRTOSZ_DEFSUFFIX_TB 'T'
-#define QEMU_STRTOSZ_DEFSUFFIX_GB 'G'
-#define QEMU_STRTOSZ_DEFSUFFIX_MB 'M'
-#define QEMU_STRTOSZ_DEFSUFFIX_KB 'K'
-#define QEMU_STRTOSZ_DEFSUFFIX_B 'B'
-int64_t qemu_strtosz_suffix(const char *nptr, char **end,
-                            const char default_suffix);
+int64_t qemu_strtosz(const char *nptr, char **end);
 int64_t qemu_strtosz_mebi(const char *nptr, char **end);
 int64_t qemu_strtosz_metric(const char *nptr, char **end);
 
diff --git a/qapi/opts-visitor.c b/qapi/opts-visitor.c
index 1048bbc..360d337 100644
--- a/qapi/opts-visitor.c
+++ b/qapi/opts-visitor.c
@@ -489,8 +489,7 @@ opts_type_size(Visitor *v, const char *name, uint64_t *obj, Error **errp)
         return;
     }
 
-    val = qemu_strtosz_suffix(opt->str ? opt->str : "", &endptr,
-                         QEMU_STRTOSZ_DEFSUFFIX_B);
+    val = qemu_strtosz(opt->str ? opt->str : "", &endptr);
     if (val < 0 || *endptr) {
         error_setg(errp, QERR_INVALID_PARAMETER_VALUE, opt->name,
                    "a size value representible as a non-negative int64");
diff --git a/qemu-img.c b/qemu-img.c
index 74e3362..4407244 100644
--- a/qemu-img.c
+++ b/qemu-img.c
@@ -462,8 +462,7 @@ static int img_create(int argc, char **argv)
     if (optind < argc) {
         int64_t sval;
         char *end;
-        sval = qemu_strtosz_suffix(argv[optind++], &end,
-                                   QEMU_STRTOSZ_DEFSUFFIX_B);
+        sval = qemu_strtosz(argv[optind++], &end);
         if (sval < 0 || *end) {
             if (sval == -ERANGE) {
                 error_report("Image size must be less than 8 EiB!");
@@ -1863,7 +1862,7 @@ static int img_convert(int argc, char **argv)
         {
             int64_t sval;
             char *end;
-            sval = qemu_strtosz_suffix(optarg, &end, QEMU_STRTOSZ_DEFSUFFIX_B);
+            sval = qemu_strtosz(optarg, &end);
             if (sval < 0 || *end) {
                 error_report("Invalid minimum zero buffer size for sparse output specified");
                 ret = -1;
@@ -3651,8 +3650,7 @@ static int img_bench(int argc, char **argv)
         {
             char *end;
             errno = 0;
-            offset = qemu_strtosz_suffix(optarg, &end,
-                                         QEMU_STRTOSZ_DEFSUFFIX_B);
+            offset = qemu_strtosz(optarg, &end);
             if (offset < 0|| *end) {
                 error_report("Invalid offset specified");
                 return 1;
@@ -3668,7 +3666,7 @@ static int img_bench(int argc, char **argv)
             int64_t sval;
             char *end;
 
-            sval = qemu_strtosz_suffix(optarg, &end, QEMU_STRTOSZ_DEFSUFFIX_B);
+            sval = qemu_strtosz(optarg, &end);
             if (sval < 0 || sval > INT_MAX || *end) {
                 error_report("Invalid buffer size specified");
                 return 1;
@@ -3682,7 +3680,7 @@ static int img_bench(int argc, char **argv)
             int64_t sval;
             char *end;
 
-            sval = qemu_strtosz_suffix(optarg, &end, QEMU_STRTOSZ_DEFSUFFIX_B);
+            sval = qemu_strtosz(optarg, &end);
             if (sval < 0 || sval > INT_MAX || *end) {
                 error_report("Invalid step size specified");
                 return 1;
@@ -3845,7 +3843,7 @@ static int img_dd_bs(const char *arg,
     char *end;
     int64_t res;
 
-    res = qemu_strtosz_suffix(arg, &end, QEMU_STRTOSZ_DEFSUFFIX_B);
+    res = qemu_strtosz(arg, &end);
 
     if (res <= 0 || res > INT_MAX || *end) {
         error_report("invalid number: '%s'", arg);
@@ -3862,7 +3860,7 @@ static int img_dd_count(const char *arg,
 {
     char *end;
 
-    dd->count = qemu_strtosz_suffix(arg, &end, QEMU_STRTOSZ_DEFSUFFIX_B);
+    dd->count = qemu_strtosz(arg, &end);
 
     if (dd->count < 0 || *end) {
         error_report("invalid number: '%s'", arg);
@@ -3896,7 +3894,7 @@ static int img_dd_skip(const char *arg,
 {
     char *end;
 
-    in->offset = qemu_strtosz_suffix(arg, &end, QEMU_STRTOSZ_DEFSUFFIX_B);
+    in->offset = qemu_strtosz(arg, &end);
 
     if (in->offset < 0 || *end) {
         error_report("invalid number: '%s'", arg);
diff --git a/qemu-io-cmds.c b/qemu-io-cmds.c
index 95bcde1..6b7a89c 100644
--- a/qemu-io-cmds.c
+++ b/qemu-io-cmds.c
@@ -140,7 +140,7 @@ static int64_t cvtnum(const char *s)
     char *end;
     int64_t ret;
 
-    ret = qemu_strtosz_suffix(s, &end, QEMU_STRTOSZ_DEFSUFFIX_B);
+    ret = qemu_strtosz(s, &end);
     if (*end != '\0') {
         /* Detritus at the end of the string */
         return -EINVAL;
diff --git a/tests/test-cutils.c b/tests/test-cutils.c
index 86d36b7..e28151b 100644
--- a/tests/test-cutils.c
+++ b/tests/test-cutils.c
@@ -1391,27 +1391,27 @@ static void test_qemu_strtosz_simple(void)
     /* Note: precision is 53 bits since we're parsing with strtod() */
 
     str = "9007199254740991"; /* 2^53-1 */
-    res = qemu_strtosz_suffix(str, &endptr, QEMU_STRTOSZ_DEFSUFFIX_B);
+    res = qemu_strtosz(str, &endptr);
     g_assert_cmpint(res, ==, 0x1fffffffffffff);
     g_assert(endptr == str + 16);
 
     str = "9007199254740992"; /* 2^53 */
-    res = qemu_strtosz_suffix(str, &endptr, QEMU_STRTOSZ_DEFSUFFIX_B);
+    res = qemu_strtosz(str, &endptr);
     g_assert_cmpint(res, ==, 0x20000000000000);
     g_assert(endptr == str + 16);
 
     str = "9007199254740993"; /* 2^53+1 */
-    res = qemu_strtosz_suffix(str, &endptr, QEMU_STRTOSZ_DEFSUFFIX_B);
+    res = qemu_strtosz(str, &endptr);
     g_assert_cmpint(res, ==, 0x20000000000000); /* rounded to 53 bits */
     g_assert(endptr == str + 16);
 
     str = "9223372036854774784"; /* 0x7ffffffffffffc00 (53 msbs set) */
-    res = qemu_strtosz_suffix(str, &endptr, QEMU_STRTOSZ_DEFSUFFIX_B);
+    res = qemu_strtosz(str, &endptr);
     g_assert_cmpint(res, ==, 0x7ffffffffffffc00);
     g_assert(endptr == str + 19);
 
     str = "9223372036854775295"; /* 0x7ffffffffffffdff */
-    res = qemu_strtosz_suffix(str, &endptr, QEMU_STRTOSZ_DEFSUFFIX_B);
+    res = qemu_strtosz(str, &endptr);
     g_assert_cmpint(res, ==, 0x7ffffffffffffc00); /* rounded to 53 bits */
     g_assert(endptr == str + 19);
 
@@ -1528,17 +1528,17 @@ static void test_qemu_strtosz_erange(void)
     g_assert(endptr == str + 2);
 
     str = "9223372036854775296"; /* 0x7ffffffffffffe00 */
-    res = qemu_strtosz_suffix(str, &endptr, QEMU_STRTOSZ_DEFSUFFIX_B);
+    res = qemu_strtosz(str, &endptr);
     g_assert_cmpint(res, ==, -ERANGE);
     g_assert(endptr == str + 19);
 
     str = "9223372036854775807"; /* 2^63-1 */
-    res = qemu_strtosz_suffix(str, &endptr, QEMU_STRTOSZ_DEFSUFFIX_B);
+    res = qemu_strtosz(str, &endptr);
     g_assert_cmpint(res, ==, -ERANGE);
     g_assert(endptr == str + 19);
 
     str = "9223372036854775808"; /* 2^63 */
-    res = qemu_strtosz_suffix(str, &endptr, QEMU_STRTOSZ_DEFSUFFIX_B);
+    res = qemu_strtosz(str, &endptr);
     g_assert_cmpint(res, ==, -ERANGE);
     g_assert(endptr == str + 19);
 
diff --git a/util/cutils.c b/util/cutils.c
index 0315d5d..ef658bb 100644
--- a/util/cutils.c
+++ b/util/cutils.c
@@ -178,6 +178,14 @@ int fcntl_setfl(int fd, int flag)
 }
 #endif
 
+#define QEMU_STRTOSZ_DEFSUFFIX_EB 'E'
+#define QEMU_STRTOSZ_DEFSUFFIX_PB 'P'
+#define QEMU_STRTOSZ_DEFSUFFIX_TB 'T'
+#define QEMU_STRTOSZ_DEFSUFFIX_GB 'G'
+#define QEMU_STRTOSZ_DEFSUFFIX_MB 'M'
+#define QEMU_STRTOSZ_DEFSUFFIX_KB 'K'
+#define QEMU_STRTOSZ_DEFSUFFIX_B 'B'
+
 static int64_t suffix_mul(char suffix, int64_t unit)
 {
     switch (qemu_toupper(suffix)) {
@@ -248,15 +256,14 @@ fail:
     return retval;
 }
 
-int64_t qemu_strtosz_suffix(const char *nptr, char **end,
-                            const char default_suffix)
+int64_t qemu_strtosz(const char *nptr, char **end)
 {
-    return do_strtosz(nptr, end, default_suffix, 1024);
+    return do_strtosz(nptr, end, QEMU_STRTOSZ_DEFSUFFIX_B, 1024);
 }
 
 int64_t qemu_strtosz_mebi(const char *nptr, char **end)
 {
-    return qemu_strtosz_suffix(nptr, end, QEMU_STRTOSZ_DEFSUFFIX_MB);
+    return do_strtosz(nptr, end, QEMU_STRTOSZ_DEFSUFFIX_MB, 1024);
 }
 
 int64_t qemu_strtosz_metric(const char *nptr, char **end)
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 79+ messages in thread

* [Qemu-devel] [PATCH 17/24] util/cutils: Drop QEMU_STRTOSZ_DEFSUFFIX_* macros
  2017-02-14 10:25 [Qemu-devel] [PATCH 00/24] QemuOpts util/cutils: Fix and clean up number conversions Markus Armbruster
                   ` (15 preceding siblings ...)
  2017-02-14 10:26 ` [Qemu-devel] [PATCH 16/24] util/cutils: New qemu_strtosz() Markus Armbruster
@ 2017-02-14 10:26 ` Markus Armbruster
  2017-02-17 20:51   ` Eric Blake
  2017-02-19  4:21   ` Philippe Mathieu-Daudé
  2017-02-14 10:26 ` [Qemu-devel] [PATCH 18/24] tests/test-cutils: Use qemu_strtosz() more often Markus Armbruster
                   ` (8 subsequent siblings)
  25 siblings, 2 replies; 79+ messages in thread
From: Markus Armbruster @ 2017-02-14 10:26 UTC (permalink / raw)
  To: qemu-devel

Writing QEMU_STRTOSZ_DEFSUFFIX_* instead of '*' gains nothing.  Get
rid of these eyesores.

Signed-off-by: Markus Armbruster <armbru@redhat.com>
---
 util/cutils.c | 28 ++++++++++------------------
 1 file changed, 10 insertions(+), 18 deletions(-)

diff --git a/util/cutils.c b/util/cutils.c
index ef658bb..4a290ea 100644
--- a/util/cutils.c
+++ b/util/cutils.c
@@ -178,30 +178,22 @@ int fcntl_setfl(int fd, int flag)
 }
 #endif
 
-#define QEMU_STRTOSZ_DEFSUFFIX_EB 'E'
-#define QEMU_STRTOSZ_DEFSUFFIX_PB 'P'
-#define QEMU_STRTOSZ_DEFSUFFIX_TB 'T'
-#define QEMU_STRTOSZ_DEFSUFFIX_GB 'G'
-#define QEMU_STRTOSZ_DEFSUFFIX_MB 'M'
-#define QEMU_STRTOSZ_DEFSUFFIX_KB 'K'
-#define QEMU_STRTOSZ_DEFSUFFIX_B 'B'
-
 static int64_t suffix_mul(char suffix, int64_t unit)
 {
     switch (qemu_toupper(suffix)) {
-    case QEMU_STRTOSZ_DEFSUFFIX_B:
+    case 'B':
         return 1;
-    case QEMU_STRTOSZ_DEFSUFFIX_KB:
+    case 'K':
         return unit;
-    case QEMU_STRTOSZ_DEFSUFFIX_MB:
+    case 'M':
         return unit * unit;
-    case QEMU_STRTOSZ_DEFSUFFIX_GB:
+    case 'G':
         return unit * unit * unit;
-    case QEMU_STRTOSZ_DEFSUFFIX_TB:
+    case 'T':
         return unit * unit * unit * unit;
-    case QEMU_STRTOSZ_DEFSUFFIX_PB:
+    case 'P':
         return unit * unit * unit * unit * unit;
-    case QEMU_STRTOSZ_DEFSUFFIX_EB:
+    case 'E':
         return unit * unit * unit * unit * unit * unit;
     }
     return -1;
@@ -258,17 +250,17 @@ fail:
 
 int64_t qemu_strtosz(const char *nptr, char **end)
 {
-    return do_strtosz(nptr, end, QEMU_STRTOSZ_DEFSUFFIX_B, 1024);
+    return do_strtosz(nptr, end, 'B', 1024);
 }
 
 int64_t qemu_strtosz_mebi(const char *nptr, char **end)
 {
-    return do_strtosz(nptr, end, QEMU_STRTOSZ_DEFSUFFIX_MB, 1024);
+    return do_strtosz(nptr, end, 'M', 1024);
 }
 
 int64_t qemu_strtosz_metric(const char *nptr, char **end)
 {
-    return do_strtosz(nptr, end, QEMU_STRTOSZ_DEFSUFFIX_B, 1000);
+    return do_strtosz(nptr, end, 'B', 1000);
 }
 
 /**
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 79+ messages in thread

* [Qemu-devel] [PATCH 18/24] tests/test-cutils: Use qemu_strtosz() more often
  2017-02-14 10:25 [Qemu-devel] [PATCH 00/24] QemuOpts util/cutils: Fix and clean up number conversions Markus Armbruster
                   ` (16 preceding siblings ...)
  2017-02-14 10:26 ` [Qemu-devel] [PATCH 17/24] util/cutils: Drop QEMU_STRTOSZ_DEFSUFFIX_* macros Markus Armbruster
@ 2017-02-14 10:26 ` Markus Armbruster
  2017-02-17 20:55   ` Eric Blake
  2017-02-14 10:26 ` [Qemu-devel] [PATCH 19/24] tests/test-cutils: Drop suffix from test_qemu_strtosz_simple() Markus Armbruster
                   ` (7 subsequent siblings)
  25 siblings, 1 reply; 79+ messages in thread
From: Markus Armbruster @ 2017-02-14 10:26 UTC (permalink / raw)
  To: qemu-devel

Use qemu_strtosz() instead of qemu_strtosz_mebi() where it doesn't
really make a difference.

Signed-off-by: Markus Armbruster <armbru@redhat.com>
---
 tests/test-cutils.c | 34 +++++++++++++++++-----------------
 1 file changed, 17 insertions(+), 17 deletions(-)

diff --git a/tests/test-cutils.c b/tests/test-cutils.c
index e28151b..ebef377 100644
--- a/tests/test-cutils.c
+++ b/tests/test-cutils.c
@@ -1376,16 +1376,16 @@ static void test_qemu_strtosz_simple(void)
     int64_t res;
 
     str = "0";
-    res = qemu_strtosz_mebi(str, &endptr);
+    res = qemu_strtosz(str, &endptr);
     g_assert_cmpint(res, ==, 0);
     g_assert(endptr == str + 1);
 
     str = "12345M";
-    res = qemu_strtosz_mebi(str, &endptr);
+    res = qemu_strtosz(str, &endptr);
     g_assert_cmpint(res, ==, 12345 * M_BYTE);
     g_assert(endptr == str + 6);
 
-    res = qemu_strtosz_mebi(str, NULL);
+    res = qemu_strtosz(str, NULL);
     g_assert_cmpint(res, ==, 12345 * M_BYTE);
 
     /* Note: precision is 53 bits since we're parsing with strtod() */
@@ -1437,31 +1437,31 @@ static void test_qemu_strtosz_units(void)
     g_assert_cmpint(res, ==, M_BYTE);
     g_assert(endptr == none + 1);
 
-    res = qemu_strtosz_mebi(b, &endptr);
+    res = qemu_strtosz(b, &endptr);
     g_assert_cmpint(res, ==, 1);
     g_assert(endptr == b + 2);
 
-    res = qemu_strtosz_mebi(k, &endptr);
+    res = qemu_strtosz(k, &endptr);
     g_assert_cmpint(res, ==, K_BYTE);
     g_assert(endptr == k + 2);
 
-    res = qemu_strtosz_mebi(m, &endptr);
+    res = qemu_strtosz(m, &endptr);
     g_assert_cmpint(res, ==, M_BYTE);
     g_assert(endptr == m + 2);
 
-    res = qemu_strtosz_mebi(g, &endptr);
+    res = qemu_strtosz(g, &endptr);
     g_assert_cmpint(res, ==, G_BYTE);
     g_assert(endptr == g + 2);
 
-    res = qemu_strtosz_mebi(t, &endptr);
+    res = qemu_strtosz(t, &endptr);
     g_assert_cmpint(res, ==, T_BYTE);
     g_assert(endptr == t + 2);
 
-    res = qemu_strtosz_mebi(p, &endptr);
+    res = qemu_strtosz(p, &endptr);
     g_assert_cmpint(res, ==, P_BYTE);
     g_assert(endptr == p + 2);
 
-    res = qemu_strtosz_mebi(e, &endptr);
+    res = qemu_strtosz(e, &endptr);
     g_assert_cmpint(res, ==, E_BYTE);
     g_assert(endptr == e + 2);
 }
@@ -1472,7 +1472,7 @@ static void test_qemu_strtosz_float(void)
     char *endptr = NULL;
     int64_t res;
 
-    res = qemu_strtosz_mebi(str, &endptr);
+    res = qemu_strtosz(str, &endptr);
     g_assert_cmpint(res, ==, 12.345 * M_BYTE);
     g_assert(endptr == str + 7);
 }
@@ -1484,17 +1484,17 @@ static void test_qemu_strtosz_invalid(void)
     int64_t res;
 
     str = "";
-    res = qemu_strtosz_mebi(str, &endptr);
+    res = qemu_strtosz(str, &endptr);
     g_assert_cmpint(res, ==, -EINVAL);
     g_assert(endptr == str);
 
     str = " \t ";
-    res = qemu_strtosz_mebi(str, &endptr);
+    res = qemu_strtosz(str, &endptr);
     g_assert_cmpint(res, ==, -EINVAL);
     g_assert(endptr == str);
 
     str = "crap";
-    res = qemu_strtosz_mebi(str, &endptr);
+    res = qemu_strtosz(str, &endptr);
     g_assert_cmpint(res, ==, -EINVAL);
     g_assert(endptr == str);
 }
@@ -1511,7 +1511,7 @@ static void test_qemu_strtosz_trailing(void)
     g_assert(endptr == str + 3);
 
     str = "1kiB";
-    res = qemu_strtosz_mebi(str, &endptr);
+    res = qemu_strtosz(str, &endptr);
     g_assert_cmpint(res, ==, 1024);
     g_assert(endptr == str + 2);
 }
@@ -1523,7 +1523,7 @@ static void test_qemu_strtosz_erange(void)
     int64_t res;
 
     str = "-1";
-    res = qemu_strtosz_mebi(str, &endptr);
+    res = qemu_strtosz(str, &endptr);
     g_assert_cmpint(res, ==, -ERANGE);
     g_assert(endptr == str + 2);
 
@@ -1543,7 +1543,7 @@ static void test_qemu_strtosz_erange(void)
     g_assert(endptr == str + 19);
 
     str = "10E";
-    res = qemu_strtosz_mebi(str, &endptr);
+    res = qemu_strtosz(str, &endptr);
     g_assert_cmpint(res, ==, -ERANGE);
     g_assert(endptr == str + 3);
 }
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 79+ messages in thread

* [Qemu-devel] [PATCH 19/24] tests/test-cutils: Drop suffix from test_qemu_strtosz_simple()
  2017-02-14 10:25 [Qemu-devel] [PATCH 00/24] QemuOpts util/cutils: Fix and clean up number conversions Markus Armbruster
                   ` (17 preceding siblings ...)
  2017-02-14 10:26 ` [Qemu-devel] [PATCH 18/24] tests/test-cutils: Use qemu_strtosz() more often Markus Armbruster
@ 2017-02-14 10:26 ` Markus Armbruster
  2017-02-17 20:58   ` Eric Blake
  2017-02-14 10:26 ` [Qemu-devel] [PATCH 20/24] qemu-img: Wrap cvtnum() around qemu_strtosz() Markus Armbruster
                   ` (6 subsequent siblings)
  25 siblings, 1 reply; 79+ messages in thread
From: Markus Armbruster @ 2017-02-14 10:26 UTC (permalink / raw)
  To: qemu-devel

Leave testing unit suffixes to test_qemu_strtosz_units().

Signed-off-by: Markus Armbruster <armbru@redhat.com>
---
 tests/test-cutils.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/tests/test-cutils.c b/tests/test-cutils.c
index ebef377..585912b 100644
--- a/tests/test-cutils.c
+++ b/tests/test-cutils.c
@@ -1380,13 +1380,13 @@ static void test_qemu_strtosz_simple(void)
     g_assert_cmpint(res, ==, 0);
     g_assert(endptr == str + 1);
 
-    str = "12345M";
+    str = "12345";
     res = qemu_strtosz(str, &endptr);
-    g_assert_cmpint(res, ==, 12345 * M_BYTE);
-    g_assert(endptr == str + 6);
+    g_assert_cmpint(res, ==, 12345);
+    g_assert(endptr == str + 5);
 
     res = qemu_strtosz(str, NULL);
-    g_assert_cmpint(res, ==, 12345 * M_BYTE);
+    g_assert_cmpint(res, ==, 12345);
 
     /* Note: precision is 53 bits since we're parsing with strtod() */
 
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 79+ messages in thread

* [Qemu-devel] [PATCH 20/24] qemu-img: Wrap cvtnum() around qemu_strtosz()
  2017-02-14 10:25 [Qemu-devel] [PATCH 00/24] QemuOpts util/cutils: Fix and clean up number conversions Markus Armbruster
                   ` (18 preceding siblings ...)
  2017-02-14 10:26 ` [Qemu-devel] [PATCH 19/24] tests/test-cutils: Drop suffix from test_qemu_strtosz_simple() Markus Armbruster
@ 2017-02-14 10:26 ` Markus Armbruster
  2017-02-17 21:10   ` Eric Blake
  2017-02-14 10:26 ` [Qemu-devel] [PATCH 21/24] util/cutils: Let qemu_strtosz*() optionally reject trailing crap Markus Armbruster
                   ` (5 subsequent siblings)
  25 siblings, 1 reply; 79+ messages in thread
From: Markus Armbruster @ 2017-02-14 10:26 UTC (permalink / raw)
  To: qemu-devel; +Cc: Kevin Wolf, Max Reitz, qemu-block

Cc: Kevin Wolf <kwolf@redhat.com>
Cc: Max Reitz <mreitz@redhat.com>
Cc: qemu-block@nongnu.org
Signed-off-by: Markus Armbruster <armbru@redhat.com>
---
 qemu-img.c | 58 +++++++++++++++++++++++++++++++---------------------------
 1 file changed, 31 insertions(+), 27 deletions(-)

diff --git a/qemu-img.c b/qemu-img.c
index 4407244..2a47966 100644
--- a/qemu-img.c
+++ b/qemu-img.c
@@ -368,6 +368,19 @@ static int add_old_style_options(const char *fmt, QemuOpts *opts,
     return 0;
 }
 
+static int64_t cvtnum(const char *s)
+{
+    char *end;
+    int64_t ret;
+
+    ret = qemu_strtosz(s, &end);
+    if (*end != '\0') {
+        /* Detritus at the end of the string */
+        return -EINVAL;
+    }
+    return ret;
+}
+
 static int img_create(int argc, char **argv)
 {
     int c;
@@ -461,9 +474,9 @@ static int img_create(int argc, char **argv)
     /* Get image size, if specified */
     if (optind < argc) {
         int64_t sval;
-        char *end;
-        sval = qemu_strtosz(argv[optind++], &end);
-        if (sval < 0 || *end) {
+
+        sval = cvtnum(argv[optind++]);
+        if (sval < 0) {
             if (sval == -ERANGE) {
                 error_report("Image size must be less than 8 EiB!");
             } else {
@@ -1861,9 +1874,9 @@ static int img_convert(int argc, char **argv)
         case 'S':
         {
             int64_t sval;
-            char *end;
-            sval = qemu_strtosz(optarg, &end);
-            if (sval < 0 || *end) {
+
+            sval = cvtnum(optarg);
+            if (sval < 0) {
                 error_report("Invalid minimum zero buffer size for sparse output specified");
                 ret = -1;
                 goto fail_getopt;
@@ -3648,10 +3661,8 @@ static int img_bench(int argc, char **argv)
             break;
         case 'o':
         {
-            char *end;
-            errno = 0;
-            offset = qemu_strtosz(optarg, &end);
-            if (offset < 0|| *end) {
+            offset = cvtnum(optarg);
+            if (offset < 0) {
                 error_report("Invalid offset specified");
                 return 1;
             }
@@ -3664,10 +3675,9 @@ static int img_bench(int argc, char **argv)
         case 's':
         {
             int64_t sval;
-            char *end;
 
-            sval = qemu_strtosz(optarg, &end);
-            if (sval < 0 || sval > INT_MAX || *end) {
+            sval = cvtnum(optarg);
+            if (sval < 0 || sval > INT_MAX) {
                 error_report("Invalid buffer size specified");
                 return 1;
             }
@@ -3678,10 +3688,9 @@ static int img_bench(int argc, char **argv)
         case 'S':
         {
             int64_t sval;
-            char *end;
 
-            sval = qemu_strtosz(optarg, &end);
-            if (sval < 0 || sval > INT_MAX || *end) {
+            sval = cvtnum(optarg);
+            if (sval < 0 || sval > INT_MAX) {
                 error_report("Invalid step size specified");
                 return 1;
             }
@@ -3840,12 +3849,11 @@ static int img_dd_bs(const char *arg,
                      struct DdIo *in, struct DdIo *out,
                      struct DdInfo *dd)
 {
-    char *end;
     int64_t res;
 
-    res = qemu_strtosz(arg, &end);
+    res = cvtnum(arg);
 
-    if (res <= 0 || res > INT_MAX || *end) {
+    if (res <= 0 || res > INT_MAX) {
         error_report("invalid number: '%s'", arg);
         return 1;
     }
@@ -3858,11 +3866,9 @@ static int img_dd_count(const char *arg,
                         struct DdIo *in, struct DdIo *out,
                         struct DdInfo *dd)
 {
-    char *end;
+    dd->count = cvtnum(arg);
 
-    dd->count = qemu_strtosz(arg, &end);
-
-    if (dd->count < 0 || *end) {
+    if (dd->count < 0) {
         error_report("invalid number: '%s'", arg);
         return 1;
     }
@@ -3892,11 +3898,9 @@ static int img_dd_skip(const char *arg,
                        struct DdIo *in, struct DdIo *out,
                        struct DdInfo *dd)
 {
-    char *end;
+    in->offset = cvtnum(arg);
 
-    in->offset = qemu_strtosz(arg, &end);
-
-    if (in->offset < 0 || *end) {
+    if (in->offset < 0) {
         error_report("invalid number: '%s'", arg);
         return 1;
     }
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 79+ messages in thread

* [Qemu-devel] [PATCH 21/24] util/cutils: Let qemu_strtosz*() optionally reject trailing crap
  2017-02-14 10:25 [Qemu-devel] [PATCH 00/24] QemuOpts util/cutils: Fix and clean up number conversions Markus Armbruster
                   ` (19 preceding siblings ...)
  2017-02-14 10:26 ` [Qemu-devel] [PATCH 20/24] qemu-img: Wrap cvtnum() around qemu_strtosz() Markus Armbruster
@ 2017-02-14 10:26 ` Markus Armbruster
  2017-02-17 21:21   ` Eric Blake
  2017-02-20 19:34   ` Dr. David Alan Gilbert
  2017-02-14 10:26 ` [Qemu-devel] [PATCH 22/24] util/cutils: Return qemu_strtosz*() error and value separately Markus Armbruster
                   ` (4 subsequent siblings)
  25 siblings, 2 replies; 79+ messages in thread
From: Markus Armbruster @ 2017-02-14 10:26 UTC (permalink / raw)
  To: qemu-devel
  Cc: Dr . David Alan Gilbert, Eduardo Habkost, Kevin Wolf, Max Reitz,
	open list:Block layer core

Change the qemu_strtosz() & friends to return -EINVAL when @endptr is
null and the conversion doesn't consume the string completely.
Matches how qemu_strtol() & friends work.

Only test_qemu_strtosz_simple() passes a null @endptr.  No functional
change there, because its conversion consumes the string.

Simplify callers that use @endptr only to fail when it doesn't point
to '\0' to pass a null @endptr instead.

Cc: Dr. David Alan Gilbert <dgilbert@redhat.com>
Cc: Eduardo Habkost <ehabkost@redhat.com> (maintainer:X86)
Cc: Kevin Wolf <kwolf@redhat.com> (supporter:Block layer core)
Cc: Max Reitz <mreitz@redhat.com> (supporter:Block layer core)
Cc: qemu-block@nongnu.org (open list:Block layer core)
Signed-off-by: Markus Armbruster <armbru@redhat.com>
---
 hmp.c               |  6 ++----
 hw/misc/ivshmem.c   |  6 ++----
 qapi/opts-visitor.c |  5 ++---
 qemu-img.c          |  7 +------
 qemu-io-cmds.c      |  7 +------
 target/i386/cpu.c   |  5 ++---
 tests/test-cutils.c |  6 ++++++
 util/cutils.c       | 14 +++++++++-----
 8 files changed, 25 insertions(+), 31 deletions(-)

diff --git a/hmp.c b/hmp.c
index 6d0d05b..0eb5b6d 100644
--- a/hmp.c
+++ b/hmp.c
@@ -1340,7 +1340,6 @@ void hmp_migrate_set_parameter(Monitor *mon, const QDict *qdict)
     const char *valuestr = qdict_get_str(qdict, "value");
     int64_t valuebw = 0;
     long valueint = 0;
-    char *endp;
     Error *err = NULL;
     bool use_int_value = false;
     int i;
@@ -1379,9 +1378,8 @@ void hmp_migrate_set_parameter(Monitor *mon, const QDict *qdict)
                 break;
             case MIGRATION_PARAMETER_MAX_BANDWIDTH:
                 p.has_max_bandwidth = true;
-                valuebw = qemu_strtosz_mebi(valuestr, &endp);
-                if (valuebw < 0 || (size_t)valuebw != valuebw
-                    || *endp != '\0') {
+                valuebw = qemu_strtosz_mebi(valuestr, NULL);
+                if (valuebw < 0 || (size_t)valuebw != valuebw) {
                     error_setg(&err, "Invalid size %s", valuestr);
                     goto cleanup;
                 }
diff --git a/hw/misc/ivshmem.c b/hw/misc/ivshmem.c
index 382dd8b..f00cd75 100644
--- a/hw/misc/ivshmem.c
+++ b/hw/misc/ivshmem.c
@@ -1267,10 +1267,8 @@ static void ivshmem_realize(PCIDevice *dev, Error **errp)
     if (s->sizearg == NULL) {
         s->legacy_size = 4 << 20; /* 4 MB default */
     } else {
-        char *end;
-        int64_t size = qemu_strtosz_mebi(s->sizearg, &end);
-        if (size < 0 || (size_t)size != size || *end != '\0'
-            || !is_power_of_2(size)) {
+        int64_t size = qemu_strtosz_mebi(s->sizearg, NULL);
+        if (size < 0 || (size_t)size != size || !is_power_of_2(size)) {
             error_setg(errp, "Invalid size %s", s->sizearg);
             return;
         }
diff --git a/qapi/opts-visitor.c b/qapi/opts-visitor.c
index 360d337..911a0ee 100644
--- a/qapi/opts-visitor.c
+++ b/qapi/opts-visitor.c
@@ -482,15 +482,14 @@ opts_type_size(Visitor *v, const char *name, uint64_t *obj, Error **errp)
     OptsVisitor *ov = to_ov(v);
     const QemuOpt *opt;
     int64_t val;
-    char *endptr;
 
     opt = lookup_scalar(ov, name, errp);
     if (!opt) {
         return;
     }
 
-    val = qemu_strtosz(opt->str ? opt->str : "", &endptr);
-    if (val < 0 || *endptr) {
+    val = qemu_strtosz(opt->str ? opt->str : "", NULL);
+    if (val < 0) {
         error_setg(errp, QERR_INVALID_PARAMETER_VALUE, opt->name,
                    "a size value representible as a non-negative int64");
         return;
diff --git a/qemu-img.c b/qemu-img.c
index 2a47966..adcb511 100644
--- a/qemu-img.c
+++ b/qemu-img.c
@@ -370,14 +370,9 @@ static int add_old_style_options(const char *fmt, QemuOpts *opts,
 
 static int64_t cvtnum(const char *s)
 {
-    char *end;
     int64_t ret;
 
-    ret = qemu_strtosz(s, &end);
-    if (*end != '\0') {
-        /* Detritus at the end of the string */
-        return -EINVAL;
-    }
+    ret = qemu_strtosz(s, NULL);
     return ret;
 }
 
diff --git a/qemu-io-cmds.c b/qemu-io-cmds.c
index 6b7a89c..417a4e0 100644
--- a/qemu-io-cmds.c
+++ b/qemu-io-cmds.c
@@ -137,14 +137,9 @@ static char **breakline(char *input, int *count)
 
 static int64_t cvtnum(const char *s)
 {
-    char *end;
     int64_t ret;
 
-    ret = qemu_strtosz(s, &end);
-    if (*end != '\0') {
-        /* Detritus at the end of the string */
-        return -EINVAL;
-    }
+    ret = qemu_strtosz(s, NULL);
     return ret;
 }
 
diff --git a/target/i386/cpu.c b/target/i386/cpu.c
index 3a8d72d..5cb0b4b 100644
--- a/target/i386/cpu.c
+++ b/target/i386/cpu.c
@@ -2034,10 +2034,9 @@ static void x86_cpu_parse_featurestr(const char *typename, char *features,
         /* Special case: */
         if (!strcmp(name, "tsc-freq")) {
             int64_t tsc_freq;
-            char *err;
 
-            tsc_freq = qemu_strtosz_metric(val, &err);
-            if (tsc_freq < 0 || *err) {
+            tsc_freq = qemu_strtosz_metric(val, NULL);
+            if (tsc_freq < 0) {
                 error_setg(errp, "bad numerical value %s", val);
                 return;
             }
diff --git a/tests/test-cutils.c b/tests/test-cutils.c
index 585912b..07095e3 100644
--- a/tests/test-cutils.c
+++ b/tests/test-cutils.c
@@ -1510,10 +1510,16 @@ static void test_qemu_strtosz_trailing(void)
     g_assert_cmpint(res, ==, 123 * M_BYTE);
     g_assert(endptr == str + 3);
 
+    res = qemu_strtosz(str, NULL);
+    g_assert_cmpint(res, ==, -EINVAL);
+
     str = "1kiB";
     res = qemu_strtosz(str, &endptr);
     g_assert_cmpint(res, ==, 1024);
     g_assert(endptr == str + 2);
+
+    res = qemu_strtosz(str, NULL);
+    g_assert_cmpint(res, ==, -EINVAL);
 }
 
 static void test_qemu_strtosz_erange(void)
diff --git a/util/cutils.c b/util/cutils.c
index 4a290ea..5c1bfe5 100644
--- a/util/cutils.c
+++ b/util/cutils.c
@@ -208,7 +208,7 @@ static int64_t suffix_mul(char suffix, int64_t unit)
 static int64_t do_strtosz(const char *nptr, char **end,
                           const char default_suffix, int64_t unit)
 {
-    int64_t retval = -EINVAL;
+    int64_t retval;
     char *endptr;
     unsigned char c;
     int mul_required = 0;
@@ -217,7 +217,8 @@ static int64_t do_strtosz(const char *nptr, char **end,
     errno = 0;
     val = strtod(nptr, &endptr);
     if (isnan(val) || endptr == nptr || errno != 0) {
-        goto fail;
+        retval = -EINVAL;
+        goto out;
     }
     fraction = modf(val, &integral);
     if (fraction != 0) {
@@ -232,17 +233,20 @@ static int64_t do_strtosz(const char *nptr, char **end,
         assert(mul >= 0);
     }
     if (mul == 1 && mul_required) {
-        goto fail;
+        retval = -EINVAL;
+        goto out;
     }
     if ((val * mul >= INT64_MAX) || val < 0) {
         retval = -ERANGE;
-        goto fail;
+        goto out;
     }
     retval = val * mul;
 
-fail:
+out:
     if (end) {
         *end = endptr;
+    } else if (*endptr) {
+        retval = -EINVAL;
     }
 
     return retval;
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 79+ messages in thread

* [Qemu-devel] [PATCH 22/24] util/cutils: Return qemu_strtosz*() error and value separately
  2017-02-14 10:25 [Qemu-devel] [PATCH 00/24] QemuOpts util/cutils: Fix and clean up number conversions Markus Armbruster
                   ` (20 preceding siblings ...)
  2017-02-14 10:26 ` [Qemu-devel] [PATCH 21/24] util/cutils: Let qemu_strtosz*() optionally reject trailing crap Markus Armbruster
@ 2017-02-14 10:26 ` Markus Armbruster
  2017-02-17 22:03   ` Eric Blake
  2017-02-20 19:52   ` Dr. David Alan Gilbert
  2017-02-14 10:26 ` [Qemu-devel] [PATCH 23/24] util/cutils: Change qemu_strtosz*() from int64_t to uint64_t Markus Armbruster
                   ` (3 subsequent siblings)
  25 siblings, 2 replies; 79+ messages in thread
From: Markus Armbruster @ 2017-02-14 10:26 UTC (permalink / raw)
  To: qemu-devel
  Cc: Dr . David Alan Gilbert, Eduardo Habkost, Kevin Wolf, Max Reitz,
	open list:Block layer core

This makes qemu_strtosz(), qemu_strtosz_mebi() and
qemu_strtosz_metric() similar to qemu_strtoi64(), except negative
values are rejected.

Cc: Dr. David Alan Gilbert <dgilbert@redhat.com>
Cc: Eduardo Habkost <ehabkost@redhat.com> (maintainer:X86)
Cc: Kevin Wolf <kwolf@redhat.com> (supporter:Block layer core)
Cc: Max Reitz <mreitz@redhat.com> (supporter:Block layer core)
Cc: qemu-block@nongnu.org (open list:Block layer core)
Signed-off-by: Markus Armbruster <armbru@redhat.com>
---
 hmp.c                 |   6 +--
 hw/misc/ivshmem.c     |   7 ++-
 include/qemu/cutils.h |   6 +--
 monitor.c             |   5 ++-
 qapi/opts-visitor.c   |   5 ++-
 qemu-img.c            |  10 +++--
 qemu-io-cmds.c        |  10 +++--
 target/i386/cpu.c     |   5 ++-
 tests/test-cutils.c   | 120 ++++++++++++++++++++++++++++++--------------------
 util/cutils.c         |  22 ++++-----
 10 files changed, 119 insertions(+), 77 deletions(-)

diff --git a/hmp.c b/hmp.c
index 0eb5b6d..9846fa4 100644
--- a/hmp.c
+++ b/hmp.c
@@ -1342,7 +1342,7 @@ void hmp_migrate_set_parameter(Monitor *mon, const QDict *qdict)
     long valueint = 0;
     Error *err = NULL;
     bool use_int_value = false;
-    int i;
+    int i, ret;
 
     for (i = 0; i < MIGRATION_PARAMETER__MAX; i++) {
         if (strcmp(param, MigrationParameter_lookup[i]) == 0) {
@@ -1378,8 +1378,8 @@ void hmp_migrate_set_parameter(Monitor *mon, const QDict *qdict)
                 break;
             case MIGRATION_PARAMETER_MAX_BANDWIDTH:
                 p.has_max_bandwidth = true;
-                valuebw = qemu_strtosz_mebi(valuestr, NULL);
-                if (valuebw < 0 || (size_t)valuebw != valuebw) {
+                ret = qemu_strtosz_mebi(valuestr, NULL, &valuebw);
+                if (ret < 0 || (size_t)valuebw != valuebw) {
                     error_setg(&err, "Invalid size %s", valuestr);
                     goto cleanup;
                 }
diff --git a/hw/misc/ivshmem.c b/hw/misc/ivshmem.c
index f00cd75..3dc04f4 100644
--- a/hw/misc/ivshmem.c
+++ b/hw/misc/ivshmem.c
@@ -1267,8 +1267,11 @@ static void ivshmem_realize(PCIDevice *dev, Error **errp)
     if (s->sizearg == NULL) {
         s->legacy_size = 4 << 20; /* 4 MB default */
     } else {
-        int64_t size = qemu_strtosz_mebi(s->sizearg, NULL);
-        if (size < 0 || (size_t)size != size || !is_power_of_2(size)) {
+        int ret;
+        int64_t size;
+
+        ret = qemu_strtosz_mebi(s->sizearg, NULL, &size);
+        if (ret < 0 || (size_t)size != size || !is_power_of_2(size)) {
             error_setg(errp, "Invalid size %s", s->sizearg);
             return;
         }
diff --git a/include/qemu/cutils.h b/include/qemu/cutils.h
index 4184851..c91649b 100644
--- a/include/qemu/cutils.h
+++ b/include/qemu/cutils.h
@@ -139,9 +139,9 @@ int parse_uint(const char *s, unsigned long long *value, char **endptr,
                int base);
 int parse_uint_full(const char *s, unsigned long long *value, int base);
 
-int64_t qemu_strtosz(const char *nptr, char **end);
-int64_t qemu_strtosz_mebi(const char *nptr, char **end);
-int64_t qemu_strtosz_metric(const char *nptr, char **end);
+int qemu_strtosz(const char *nptr, char **end, int64_t *result);
+int qemu_strtosz_mebi(const char *nptr, char **end, int64_t *result);
+int qemu_strtosz_metric(const char *nptr, char **end, int64_t *result);
 
 #define K_BYTE     (1ULL << 10)
 #define M_BYTE     (1ULL << 20)
diff --git a/monitor.c b/monitor.c
index 1f8c031..85b1b61 100644
--- a/monitor.c
+++ b/monitor.c
@@ -2773,6 +2773,7 @@ static QDict *monitor_parse_arguments(Monitor *mon,
             break;
         case 'o':
             {
+                int ret;
                 int64_t val;
                 char *end;
 
@@ -2785,8 +2786,8 @@ static QDict *monitor_parse_arguments(Monitor *mon,
                         break;
                     }
                 }
-                val = qemu_strtosz_mebi(p, &end);
-                if (val < 0) {
+                ret = qemu_strtosz_mebi(p, &end, &val);
+                if (ret < 0) {
                     monitor_printf(mon, "invalid size\n");
                     goto fail;
                 }
diff --git a/qapi/opts-visitor.c b/qapi/opts-visitor.c
index 911a0ee..aac2e09 100644
--- a/qapi/opts-visitor.c
+++ b/qapi/opts-visitor.c
@@ -482,14 +482,15 @@ opts_type_size(Visitor *v, const char *name, uint64_t *obj, Error **errp)
     OptsVisitor *ov = to_ov(v);
     const QemuOpt *opt;
     int64_t val;
+    int err;
 
     opt = lookup_scalar(ov, name, errp);
     if (!opt) {
         return;
     }
 
-    val = qemu_strtosz(opt->str ? opt->str : "", NULL);
-    if (val < 0) {
+    err = qemu_strtosz(opt->str ? opt->str : "", NULL, &val);
+    if (err < 0) {
         error_setg(errp, QERR_INVALID_PARAMETER_VALUE, opt->name,
                    "a size value representible as a non-negative int64");
         return;
diff --git a/qemu-img.c b/qemu-img.c
index adcb511..89ced5a 100644
--- a/qemu-img.c
+++ b/qemu-img.c
@@ -370,10 +370,14 @@ static int add_old_style_options(const char *fmt, QemuOpts *opts,
 
 static int64_t cvtnum(const char *s)
 {
-    int64_t ret;
+    int err;
+    int64_t value;
 
-    ret = qemu_strtosz(s, NULL);
-    return ret;
+    err = qemu_strtosz(s, NULL, &value);
+    if (err < 0) {
+        return err;
+    }
+    return value;
 }
 
 static int img_create(int argc, char **argv)
diff --git a/qemu-io-cmds.c b/qemu-io-cmds.c
index 417a4e0..d9f3e93 100644
--- a/qemu-io-cmds.c
+++ b/qemu-io-cmds.c
@@ -137,10 +137,14 @@ static char **breakline(char *input, int *count)
 
 static int64_t cvtnum(const char *s)
 {
-    int64_t ret;
+    int err;
+    int64_t value;
 
-    ret = qemu_strtosz(s, NULL);
-    return ret;
+    err = qemu_strtosz(s, NULL, &value);
+    if (err < 0) {
+        return err;
+    }
+    return value;
 }
 
 static void print_cvtnum_err(int64_t rc, const char *arg)
diff --git a/target/i386/cpu.c b/target/i386/cpu.c
index 5cb0b4b..5f85410 100644
--- a/target/i386/cpu.c
+++ b/target/i386/cpu.c
@@ -2033,10 +2033,11 @@ static void x86_cpu_parse_featurestr(const char *typename, char *features,
 
         /* Special case: */
         if (!strcmp(name, "tsc-freq")) {
+            int ret;
             int64_t tsc_freq;
 
-            tsc_freq = qemu_strtosz_metric(val, NULL);
-            if (tsc_freq < 0) {
+            ret = qemu_strtosz_metric(val, NULL, &tsc_freq);
+            if (ret < 0) {
                 error_setg(errp, "bad numerical value %s", val);
                 return;
             }
diff --git a/tests/test-cutils.c b/tests/test-cutils.c
index 07095e3..9c2eed3 100644
--- a/tests/test-cutils.c
+++ b/tests/test-cutils.c
@@ -1373,45 +1373,54 @@ static void test_qemu_strtosz_simple(void)
 {
     const char *str;
     char *endptr = NULL;
-    int64_t res;
+    int err;
+    int64_t res = 0xbaadf00d;
 
     str = "0";
-    res = qemu_strtosz(str, &endptr);
+    err = qemu_strtosz(str, &endptr, &res);
+    g_assert_cmpint(err, ==, 0);
     g_assert_cmpint(res, ==, 0);
     g_assert(endptr == str + 1);
 
     str = "12345";
-    res = qemu_strtosz(str, &endptr);
+    err = qemu_strtosz(str, &endptr, &res);
+    g_assert_cmpint(err, ==, 0);
     g_assert_cmpint(res, ==, 12345);
     g_assert(endptr == str + 5);
 
-    res = qemu_strtosz(str, NULL);
+    err = qemu_strtosz(str, NULL, &res);
+    g_assert_cmpint(err, ==, 0);
     g_assert_cmpint(res, ==, 12345);
 
     /* Note: precision is 53 bits since we're parsing with strtod() */
 
     str = "9007199254740991"; /* 2^53-1 */
-    res = qemu_strtosz(str, &endptr);
+    err = qemu_strtosz(str, &endptr, &res);
+    g_assert_cmpint(err, ==, 0);
     g_assert_cmpint(res, ==, 0x1fffffffffffff);
     g_assert(endptr == str + 16);
 
     str = "9007199254740992"; /* 2^53 */
-    res = qemu_strtosz(str, &endptr);
+    err = qemu_strtosz(str, &endptr, &res);
+    g_assert_cmpint(err, ==, 0);
     g_assert_cmpint(res, ==, 0x20000000000000);
     g_assert(endptr == str + 16);
 
     str = "9007199254740993"; /* 2^53+1 */
-    res = qemu_strtosz(str, &endptr);
+    err = qemu_strtosz(str, &endptr, &res);
+    g_assert_cmpint(err, ==, 0);
     g_assert_cmpint(res, ==, 0x20000000000000); /* rounded to 53 bits */
     g_assert(endptr == str + 16);
 
     str = "9223372036854774784"; /* 0x7ffffffffffffc00 (53 msbs set) */
-    res = qemu_strtosz(str, &endptr);
+    err = qemu_strtosz(str, &endptr, &res);
+    g_assert_cmpint(err, ==, 0);
     g_assert_cmpint(res, ==, 0x7ffffffffffffc00);
     g_assert(endptr == str + 19);
 
     str = "9223372036854775295"; /* 0x7ffffffffffffdff */
-    res = qemu_strtosz(str, &endptr);
+    err = qemu_strtosz(str, &endptr, &res);
+    g_assert_cmpint(err, ==, 0);
     g_assert_cmpint(res, ==, 0x7ffffffffffffc00); /* rounded to 53 bits */
     g_assert(endptr == str + 19);
 
@@ -1429,39 +1438,48 @@ static void test_qemu_strtosz_units(void)
     const char *t = "1T";
     const char *p = "1P";
     const char *e = "1E";
+    int err;
     char *endptr = NULL;
-    int64_t res;
+    int64_t res = 0xbaadf00d;
 
     /* default is M */
-    res = qemu_strtosz_mebi(none, &endptr);
+    err = qemu_strtosz_mebi(none, &endptr, &res);
+    g_assert_cmpint(err, ==, 0);
     g_assert_cmpint(res, ==, M_BYTE);
     g_assert(endptr == none + 1);
 
-    res = qemu_strtosz(b, &endptr);
+    err = qemu_strtosz(b, &endptr, &res);
+    g_assert_cmpint(err, ==, 0);
     g_assert_cmpint(res, ==, 1);
     g_assert(endptr == b + 2);
 
-    res = qemu_strtosz(k, &endptr);
+    err = qemu_strtosz(k, &endptr, &res);
+    g_assert_cmpint(err, ==, 0);
     g_assert_cmpint(res, ==, K_BYTE);
     g_assert(endptr == k + 2);
 
-    res = qemu_strtosz(m, &endptr);
+    err = qemu_strtosz(m, &endptr, &res);
+    g_assert_cmpint(err, ==, 0);
     g_assert_cmpint(res, ==, M_BYTE);
     g_assert(endptr == m + 2);
 
-    res = qemu_strtosz(g, &endptr);
+    err = qemu_strtosz(g, &endptr, &res);
+    g_assert_cmpint(err, ==, 0);
     g_assert_cmpint(res, ==, G_BYTE);
     g_assert(endptr == g + 2);
 
-    res = qemu_strtosz(t, &endptr);
+    err = qemu_strtosz(t, &endptr, &res);
+    g_assert_cmpint(err, ==, 0);
     g_assert_cmpint(res, ==, T_BYTE);
     g_assert(endptr == t + 2);
 
-    res = qemu_strtosz(p, &endptr);
+    err = qemu_strtosz(p, &endptr, &res);
+    g_assert_cmpint(err, ==, 0);
     g_assert_cmpint(res, ==, P_BYTE);
     g_assert(endptr == p + 2);
 
-    res = qemu_strtosz(e, &endptr);
+    err = qemu_strtosz(e, &endptr, &res);
+    g_assert_cmpint(err, ==, 0);
     g_assert_cmpint(res, ==, E_BYTE);
     g_assert(endptr == e + 2);
 }
@@ -1469,10 +1487,12 @@ static void test_qemu_strtosz_units(void)
 static void test_qemu_strtosz_float(void)
 {
     const char *str = "12.345M";
+    int err;
     char *endptr = NULL;
-    int64_t res;
+    int64_t res = 0xbaadf00d;
 
-    res = qemu_strtosz(str, &endptr);
+    err = qemu_strtosz(str, &endptr, &res);
+    g_assert_cmpint(err, ==, 0);
     g_assert_cmpint(res, ==, 12.345 * M_BYTE);
     g_assert(endptr == str + 7);
 }
@@ -1481,21 +1501,22 @@ static void test_qemu_strtosz_invalid(void)
 {
     const char *str;
     char *endptr = NULL;
-    int64_t res;
+    int err;
+    int64_t res = 0xbaadf00d;
 
     str = "";
-    res = qemu_strtosz(str, &endptr);
-    g_assert_cmpint(res, ==, -EINVAL);
+    err = qemu_strtosz(str, &endptr, &res);
+    g_assert_cmpint(err, ==, -EINVAL);
     g_assert(endptr == str);
 
     str = " \t ";
-    res = qemu_strtosz(str, &endptr);
-    g_assert_cmpint(res, ==, -EINVAL);
+    err = qemu_strtosz(str, &endptr, &res);
+    g_assert_cmpint(err, ==, -EINVAL);
     g_assert(endptr == str);
 
     str = "crap";
-    res = qemu_strtosz(str, &endptr);
-    g_assert_cmpint(res, ==, -EINVAL);
+    err = qemu_strtosz(str, &endptr, &res);
+    g_assert_cmpint(err, ==, -EINVAL);
     g_assert(endptr == str);
 }
 
@@ -1503,64 +1524,69 @@ static void test_qemu_strtosz_trailing(void)
 {
     const char *str;
     char *endptr = NULL;
-    int64_t res;
+    int err;
+    int64_t res = 0xbaadf00d;
 
     str = "123xxx";
-    res = qemu_strtosz_mebi(str, &endptr);
+    err = qemu_strtosz_mebi(str, &endptr, &res);
     g_assert_cmpint(res, ==, 123 * M_BYTE);
     g_assert(endptr == str + 3);
 
-    res = qemu_strtosz(str, NULL);
-    g_assert_cmpint(res, ==, -EINVAL);
+    err = qemu_strtosz(str, NULL, &res);
+    g_assert_cmpint(err, ==, -EINVAL);
 
     str = "1kiB";
-    res = qemu_strtosz(str, &endptr);
+    err = qemu_strtosz(str, &endptr, &res);
+    g_assert_cmpint(err, ==, 0);
     g_assert_cmpint(res, ==, 1024);
     g_assert(endptr == str + 2);
 
-    res = qemu_strtosz(str, NULL);
-    g_assert_cmpint(res, ==, -EINVAL);
+    err = qemu_strtosz(str, NULL, &res);
+    g_assert_cmpint(err, ==, -EINVAL);
 }
 
 static void test_qemu_strtosz_erange(void)
 {
     const char *str;
     char *endptr = NULL;
-    int64_t res;
+    int err;
+    int64_t res = 0xbaadf00d;
 
     str = "-1";
-    res = qemu_strtosz(str, &endptr);
-    g_assert_cmpint(res, ==, -ERANGE);
+    err = qemu_strtosz(str, &endptr, &res);
+    g_assert_cmpint(err, ==, -ERANGE);
     g_assert(endptr == str + 2);
 
     str = "9223372036854775296"; /* 0x7ffffffffffffe00 */
-    res = qemu_strtosz(str, &endptr);
-    g_assert_cmpint(res, ==, -ERANGE);
+    err = qemu_strtosz(str, &endptr, &res);
+    g_assert_cmpint(err, ==, -ERANGE);
     g_assert(endptr == str + 19);
 
     str = "9223372036854775807"; /* 2^63-1 */
-    res = qemu_strtosz(str, &endptr);
-    g_assert_cmpint(res, ==, -ERANGE);
+    err = qemu_strtosz(str, &endptr, &res);
+    g_assert_cmpint(err, ==, -ERANGE);
     g_assert(endptr == str + 19);
 
     str = "9223372036854775808"; /* 2^63 */
-    res = qemu_strtosz(str, &endptr);
-    g_assert_cmpint(res, ==, -ERANGE);
+    err = qemu_strtosz(str, &endptr, &res);
+    g_assert_cmpint(err, ==, -ERANGE);
     g_assert(endptr == str + 19);
 
     str = "10E";
-    res = qemu_strtosz(str, &endptr);
-    g_assert_cmpint(res, ==, -ERANGE);
+    err = qemu_strtosz(str, &endptr, &res);
+    g_assert_cmpint(err, ==, -ERANGE);
     g_assert(endptr == str + 3);
 }
 
 static void test_qemu_strtosz_metric(void)
 {
     const char *str = "12345k";
+    int err;
     char *endptr = NULL;
-    int64_t res;
+    int64_t res = 0xbaadf00d;
 
-    res = qemu_strtosz_metric(str, &endptr);
+    err = qemu_strtosz_metric(str, &endptr, &res);
+    g_assert_cmpint(err, ==, 0);
     g_assert_cmpint(res, ==, 12345000);
     g_assert(endptr == str + 6);
 }
diff --git a/util/cutils.c b/util/cutils.c
index 5c1bfe5..08effe6 100644
--- a/util/cutils.c
+++ b/util/cutils.c
@@ -205,10 +205,11 @@ static int64_t suffix_mul(char suffix, int64_t unit)
  * in *end, if not NULL. Return -ERANGE on overflow, Return -EINVAL on
  * other error.
  */
-static int64_t do_strtosz(const char *nptr, char **end,
-                          const char default_suffix, int64_t unit)
+static int do_strtosz(const char *nptr, char **end,
+                      const char default_suffix, int64_t unit,
+                      int64_t *result)
 {
-    int64_t retval;
+    int retval;
     char *endptr;
     unsigned char c;
     int mul_required = 0;
@@ -240,7 +241,8 @@ static int64_t do_strtosz(const char *nptr, char **end,
         retval = -ERANGE;
         goto out;
     }
-    retval = val * mul;
+    *result = val * mul;
+    retval = 0;
 
 out:
     if (end) {
@@ -252,19 +254,19 @@ out:
     return retval;
 }
 
-int64_t qemu_strtosz(const char *nptr, char **end)
+int qemu_strtosz(const char *nptr, char **end, int64_t *result)
 {
-    return do_strtosz(nptr, end, 'B', 1024);
+    return do_strtosz(nptr, end, 'B', 1024, result);
 }
 
-int64_t qemu_strtosz_mebi(const char *nptr, char **end)
+int qemu_strtosz_mebi(const char *nptr, char **end, int64_t *result)
 {
-    return do_strtosz(nptr, end, 'M', 1024);
+    return do_strtosz(nptr, end, 'M', 1024, result);
 }
 
-int64_t qemu_strtosz_metric(const char *nptr, char **end)
+int qemu_strtosz_metric(const char *nptr, char **end, int64_t *result)
 {
-    return do_strtosz(nptr, end, 'B', 1000);
+    return do_strtosz(nptr, end, 'B', 1000, result);
 }
 
 /**
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 79+ messages in thread

* [Qemu-devel] [PATCH 23/24] util/cutils: Change qemu_strtosz*() from int64_t to uint64_t
  2017-02-14 10:25 [Qemu-devel] [PATCH 00/24] QemuOpts util/cutils: Fix and clean up number conversions Markus Armbruster
                   ` (21 preceding siblings ...)
  2017-02-14 10:26 ` [Qemu-devel] [PATCH 22/24] util/cutils: Return qemu_strtosz*() error and value separately Markus Armbruster
@ 2017-02-14 10:26 ` Markus Armbruster
  2017-02-17 22:19   ` Eric Blake
  2017-02-20 20:16   ` Dr. David Alan Gilbert
  2017-02-14 10:26 ` [Qemu-devel] [PATCH 24/24] QemuOpts: Fix checking of sizes for overflow and trailing crap Markus Armbruster
                   ` (2 subsequent siblings)
  25 siblings, 2 replies; 79+ messages in thread
From: Markus Armbruster @ 2017-02-14 10:26 UTC (permalink / raw)
  To: qemu-devel
  Cc: Dr . David Alan Gilbert, Eduardo Habkost, Kevin Wolf, Max Reitz,
	open list:Block layer core

This will permit its use in parse_option_size().

Cc: Dr. David Alan Gilbert <dgilbert@redhat.com>
Cc: Eduardo Habkost <ehabkost@redhat.com> (maintainer:X86)
Cc: Kevin Wolf <kwolf@redhat.com> (supporter:Block layer core)
Cc: Max Reitz <mreitz@redhat.com> (supporter:Block layer core)
Cc: qemu-block@nongnu.org (open list:Block layer core)
Signed-off-by: Markus Armbruster <armbru@redhat.com>
---
 hmp.c                 |  5 +++--
 hw/misc/ivshmem.c     |  2 +-
 include/qemu/cutils.h |  6 +++---
 monitor.c             |  4 ++--
 qapi/opts-visitor.c   |  6 ++----
 qemu-img.c            |  5 ++++-
 qemu-io-cmds.c        |  5 ++++-
 target/i386/cpu.c     |  4 ++--
 tests/test-cutils.c   | 40 ++++++++++++++++++++--------------------
 util/cutils.c         | 14 +++++++++-----
 10 files changed, 50 insertions(+), 41 deletions(-)

diff --git a/hmp.c b/hmp.c
index 9846fa4..5b9e461 100644
--- a/hmp.c
+++ b/hmp.c
@@ -1338,7 +1338,7 @@ void hmp_migrate_set_parameter(Monitor *mon, const QDict *qdict)
 {
     const char *param = qdict_get_str(qdict, "parameter");
     const char *valuestr = qdict_get_str(qdict, "value");
-    int64_t valuebw = 0;
+    uint64_t valuebw = 0;
     long valueint = 0;
     Error *err = NULL;
     bool use_int_value = false;
@@ -1379,7 +1379,8 @@ void hmp_migrate_set_parameter(Monitor *mon, const QDict *qdict)
             case MIGRATION_PARAMETER_MAX_BANDWIDTH:
                 p.has_max_bandwidth = true;
                 ret = qemu_strtosz_mebi(valuestr, NULL, &valuebw);
-                if (ret < 0 || (size_t)valuebw != valuebw) {
+                if (ret < 0 || valuebw > INT64_MAX
+                    || (size_t)valuebw != valuebw) {
                     error_setg(&err, "Invalid size %s", valuestr);
                     goto cleanup;
                 }
diff --git a/hw/misc/ivshmem.c b/hw/misc/ivshmem.c
index 3dc04f4..ba0cc22 100644
--- a/hw/misc/ivshmem.c
+++ b/hw/misc/ivshmem.c
@@ -1268,7 +1268,7 @@ static void ivshmem_realize(PCIDevice *dev, Error **errp)
         s->legacy_size = 4 << 20; /* 4 MB default */
     } else {
         int ret;
-        int64_t size;
+        uint64_t size;
 
         ret = qemu_strtosz_mebi(s->sizearg, NULL, &size);
         if (ret < 0 || (size_t)size != size || !is_power_of_2(size)) {
diff --git a/include/qemu/cutils.h b/include/qemu/cutils.h
index c91649b..476d274 100644
--- a/include/qemu/cutils.h
+++ b/include/qemu/cutils.h
@@ -139,9 +139,9 @@ int parse_uint(const char *s, unsigned long long *value, char **endptr,
                int base);
 int parse_uint_full(const char *s, unsigned long long *value, int base);
 
-int qemu_strtosz(const char *nptr, char **end, int64_t *result);
-int qemu_strtosz_mebi(const char *nptr, char **end, int64_t *result);
-int qemu_strtosz_metric(const char *nptr, char **end, int64_t *result);
+int qemu_strtosz(const char *nptr, char **end, uint64_t *result);
+int qemu_strtosz_mebi(const char *nptr, char **end, uint64_t *result);
+int qemu_strtosz_metric(const char *nptr, char **end, uint64_t *result);
 
 #define K_BYTE     (1ULL << 10)
 #define M_BYTE     (1ULL << 20)
diff --git a/monitor.c b/monitor.c
index 85b1b61..1008ced 100644
--- a/monitor.c
+++ b/monitor.c
@@ -2774,7 +2774,7 @@ static QDict *monitor_parse_arguments(Monitor *mon,
         case 'o':
             {
                 int ret;
-                int64_t val;
+                uint64_t val;
                 char *end;
 
                 while (qemu_isspace(*p)) {
@@ -2787,7 +2787,7 @@ static QDict *monitor_parse_arguments(Monitor *mon,
                     }
                 }
                 ret = qemu_strtosz_mebi(p, &end, &val);
-                if (ret < 0) {
+                if (ret < 0 || val > INT64_MAX) {
                     monitor_printf(mon, "invalid size\n");
                     goto fail;
                 }
diff --git a/qapi/opts-visitor.c b/qapi/opts-visitor.c
index aac2e09..a0a7c0e 100644
--- a/qapi/opts-visitor.c
+++ b/qapi/opts-visitor.c
@@ -481,7 +481,6 @@ opts_type_size(Visitor *v, const char *name, uint64_t *obj, Error **errp)
 {
     OptsVisitor *ov = to_ov(v);
     const QemuOpt *opt;
-    int64_t val;
     int err;
 
     opt = lookup_scalar(ov, name, errp);
@@ -489,14 +488,13 @@ opts_type_size(Visitor *v, const char *name, uint64_t *obj, Error **errp)
         return;
     }
 
-    err = qemu_strtosz(opt->str ? opt->str : "", NULL, &val);
+    err = qemu_strtosz(opt->str ? opt->str : "", NULL, obj);
     if (err < 0) {
         error_setg(errp, QERR_INVALID_PARAMETER_VALUE, opt->name,
-                   "a size value representible as a non-negative int64");
+                   "a size value");
         return;
     }
 
-    *obj = val;
     processed(ov, name);
 }
 
diff --git a/qemu-img.c b/qemu-img.c
index 89ced5a..b10ea66 100644
--- a/qemu-img.c
+++ b/qemu-img.c
@@ -371,12 +371,15 @@ static int add_old_style_options(const char *fmt, QemuOpts *opts,
 static int64_t cvtnum(const char *s)
 {
     int err;
-    int64_t value;
+    uint64_t value;
 
     err = qemu_strtosz(s, NULL, &value);
     if (err < 0) {
         return err;
     }
+    if (value > INT64_MAX) {
+        return -ERANGE;
+    }
     return value;
 }
 
diff --git a/qemu-io-cmds.c b/qemu-io-cmds.c
index d9f3e93..1b01160 100644
--- a/qemu-io-cmds.c
+++ b/qemu-io-cmds.c
@@ -138,12 +138,15 @@ static char **breakline(char *input, int *count)
 static int64_t cvtnum(const char *s)
 {
     int err;
-    int64_t value;
+    uint64_t value;
 
     err = qemu_strtosz(s, NULL, &value);
     if (err < 0) {
         return err;
     }
+    if (value > INT64_MAX) {
+        return -ERANGE;
+    }
     return value;
 }
 
diff --git a/target/i386/cpu.c b/target/i386/cpu.c
index 5f85410..e15f6bf 100644
--- a/target/i386/cpu.c
+++ b/target/i386/cpu.c
@@ -2034,10 +2034,10 @@ static void x86_cpu_parse_featurestr(const char *typename, char *features,
         /* Special case: */
         if (!strcmp(name, "tsc-freq")) {
             int ret;
-            int64_t tsc_freq;
+            uint64_t tsc_freq;
 
             ret = qemu_strtosz_metric(val, NULL, &tsc_freq);
-            if (ret < 0) {
+            if (ret < 0 || tsc_freq > INT64_MAX) {
                 error_setg(errp, "bad numerical value %s", val);
                 return;
             }
diff --git a/tests/test-cutils.c b/tests/test-cutils.c
index 9c2eed3..ebc1da2 100644
--- a/tests/test-cutils.c
+++ b/tests/test-cutils.c
@@ -1374,7 +1374,7 @@ static void test_qemu_strtosz_simple(void)
     const char *str;
     char *endptr = NULL;
     int err;
-    int64_t res = 0xbaadf00d;
+    uint64_t res = 0xbaadf00d;
 
     str = "0";
     err = qemu_strtosz(str, &endptr, &res);
@@ -1412,17 +1412,17 @@ static void test_qemu_strtosz_simple(void)
     g_assert_cmpint(res, ==, 0x20000000000000); /* rounded to 53 bits */
     g_assert(endptr == str + 16);
 
-    str = "9223372036854774784"; /* 0x7ffffffffffffc00 (53 msbs set) */
+    str = "18446744073709549568"; /* 0xfffffffffffff800 (53 msbs set) */
     err = qemu_strtosz(str, &endptr, &res);
     g_assert_cmpint(err, ==, 0);
-    g_assert_cmpint(res, ==, 0x7ffffffffffffc00);
-    g_assert(endptr == str + 19);
+    g_assert_cmpint(res, ==, 0xfffffffffffff800);
+    g_assert(endptr == str + 20);
 
-    str = "9223372036854775295"; /* 0x7ffffffffffffdff */
+    str = "18446744073709550591"; /* 0xfffffffffffffbff */
     err = qemu_strtosz(str, &endptr, &res);
     g_assert_cmpint(err, ==, 0);
-    g_assert_cmpint(res, ==, 0x7ffffffffffffc00); /* rounded to 53 bits */
-    g_assert(endptr == str + 19);
+    g_assert_cmpint(res, ==, 0xfffffffffffff800); /* rounded to 53 bits */
+    g_assert(endptr == str + 20);
 
     /* 0x7ffffffffffffe00..0x7fffffffffffffff get rounded to
      * 0x8000000000000000, thus -ERANGE; see test_qemu_strtosz_erange() */
@@ -1440,7 +1440,7 @@ static void test_qemu_strtosz_units(void)
     const char *e = "1E";
     int err;
     char *endptr = NULL;
-    int64_t res = 0xbaadf00d;
+    uint64_t res = 0xbaadf00d;
 
     /* default is M */
     err = qemu_strtosz_mebi(none, &endptr, &res);
@@ -1489,7 +1489,7 @@ static void test_qemu_strtosz_float(void)
     const char *str = "12.345M";
     int err;
     char *endptr = NULL;
-    int64_t res = 0xbaadf00d;
+    uint64_t res = 0xbaadf00d;
 
     err = qemu_strtosz(str, &endptr, &res);
     g_assert_cmpint(err, ==, 0);
@@ -1502,7 +1502,7 @@ static void test_qemu_strtosz_invalid(void)
     const char *str;
     char *endptr = NULL;
     int err;
-    int64_t res = 0xbaadf00d;
+    uint64_t res = 0xbaadf00d;
 
     str = "";
     err = qemu_strtosz(str, &endptr, &res);
@@ -1525,7 +1525,7 @@ static void test_qemu_strtosz_trailing(void)
     const char *str;
     char *endptr = NULL;
     int err;
-    int64_t res = 0xbaadf00d;
+    uint64_t res = 0xbaadf00d;
 
     str = "123xxx";
     err = qemu_strtosz_mebi(str, &endptr, &res);
@@ -1550,29 +1550,29 @@ static void test_qemu_strtosz_erange(void)
     const char *str;
     char *endptr = NULL;
     int err;
-    int64_t res = 0xbaadf00d;
+    uint64_t res = 0xbaadf00d;
 
     str = "-1";
     err = qemu_strtosz(str, &endptr, &res);
     g_assert_cmpint(err, ==, -ERANGE);
     g_assert(endptr == str + 2);
 
-    str = "9223372036854775296"; /* 0x7ffffffffffffe00 */
+    str = "18446744073709550592"; /* 0xfffffffffffffc00 */
     err = qemu_strtosz(str, &endptr, &res);
     g_assert_cmpint(err, ==, -ERANGE);
-    g_assert(endptr == str + 19);
+    g_assert(endptr == str + 20);
 
-    str = "9223372036854775807"; /* 2^63-1 */
+    str = "18446744073709551615"; /* 2^64-1 */
     err = qemu_strtosz(str, &endptr, &res);
     g_assert_cmpint(err, ==, -ERANGE);
-    g_assert(endptr == str + 19);
+    g_assert(endptr == str + 20);
 
-    str = "9223372036854775808"; /* 2^63 */
+    str = "18446744073709551616"; /* 2^64 */
     err = qemu_strtosz(str, &endptr, &res);
     g_assert_cmpint(err, ==, -ERANGE);
-    g_assert(endptr == str + 19);
+    g_assert(endptr == str + 20);
 
-    str = "10E";
+    str = "20E";
     err = qemu_strtosz(str, &endptr, &res);
     g_assert_cmpint(err, ==, -ERANGE);
     g_assert(endptr == str + 3);
@@ -1583,7 +1583,7 @@ static void test_qemu_strtosz_metric(void)
     const char *str = "12345k";
     int err;
     char *endptr = NULL;
-    int64_t res = 0xbaadf00d;
+    uint64_t res = 0xbaadf00d;
 
     err = qemu_strtosz_metric(str, &endptr, &res);
     g_assert_cmpint(err, ==, 0);
diff --git a/util/cutils.c b/util/cutils.c
index 08effe6..888c0fd 100644
--- a/util/cutils.c
+++ b/util/cutils.c
@@ -207,7 +207,7 @@ static int64_t suffix_mul(char suffix, int64_t unit)
  */
 static int do_strtosz(const char *nptr, char **end,
                       const char default_suffix, int64_t unit,
-                      int64_t *result)
+                      uint64_t *result)
 {
     int retval;
     char *endptr;
@@ -237,7 +237,11 @@ static int do_strtosz(const char *nptr, char **end,
         retval = -EINVAL;
         goto out;
     }
-    if ((val * mul >= INT64_MAX) || val < 0) {
+    /*
+     * Values >= 0xfffffffffffffc00 overflow uint64_t after their trip
+     * through double (53 bits of precision).
+     */
+    if ((val * mul >= 0xfffffffffffffc00) || val < 0) {
         retval = -ERANGE;
         goto out;
     }
@@ -254,17 +258,17 @@ out:
     return retval;
 }
 
-int qemu_strtosz(const char *nptr, char **end, int64_t *result)
+int qemu_strtosz(const char *nptr, char **end, uint64_t *result)
 {
     return do_strtosz(nptr, end, 'B', 1024, result);
 }
 
-int qemu_strtosz_mebi(const char *nptr, char **end, int64_t *result)
+int qemu_strtosz_mebi(const char *nptr, char **end, uint64_t *result)
 {
     return do_strtosz(nptr, end, 'M', 1024, result);
 }
 
-int qemu_strtosz_metric(const char *nptr, char **end, int64_t *result)
+int qemu_strtosz_metric(const char *nptr, char **end, uint64_t *result)
 {
     return do_strtosz(nptr, end, 'B', 1000, result);
 }
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 79+ messages in thread

* [Qemu-devel] [PATCH 24/24] QemuOpts: Fix checking of sizes for overflow and trailing crap
  2017-02-14 10:25 [Qemu-devel] [PATCH 00/24] QemuOpts util/cutils: Fix and clean up number conversions Markus Armbruster
                   ` (22 preceding siblings ...)
  2017-02-14 10:26 ` [Qemu-devel] [PATCH 23/24] util/cutils: Change qemu_strtosz*() from int64_t to uint64_t Markus Armbruster
@ 2017-02-14 10:26 ` Markus Armbruster
  2017-02-17 22:27   ` Eric Blake
  2017-02-14 10:57 ` [Qemu-devel] [PATCH 00/24] QemuOpts util/cutils: Fix and clean up number conversions no-reply
  2017-02-14 12:37 ` Paolo Bonzini
  25 siblings, 1 reply; 79+ messages in thread
From: Markus Armbruster @ 2017-02-14 10:26 UTC (permalink / raw)
  To: qemu-devel

parse_option_size()'s checking for overflow and trailing crap is
wrong.  Has always been that way.  qemu_strtosz() gets it right, so
use that.

This adds support for size suffixes 'P', 'E', and ignores case for all
suffixes, not just 'k'.

Signed-off-by: Markus Armbruster <armbru@redhat.com>
---
 tests/test-qemu-opts.c | 21 +++++++++------------
 util/qemu-option.c     | 41 +++++++++++++----------------------------
 2 files changed, 22 insertions(+), 40 deletions(-)

diff --git a/tests/test-qemu-opts.c b/tests/test-qemu-opts.c
index 6a9d3c5..b9d5b7e 100644
--- a/tests/test-qemu-opts.c
+++ b/tests/test-qemu-opts.c
@@ -667,10 +667,9 @@ static void test_opts_parse_size(void)
     g_assert(!opts);
     opts = qemu_opts_parse(&opts_list_02,
                            "size1=18446744073709550592", /* fffffffffffffc00 */
-                           false, &error_abort);
-    /* BUG: should reject */
-    g_assert_cmpuint(opts_count(opts), ==, 1);
-    g_assert_cmpuint(qemu_opt_get_size(opts, "size1", 1), ==, 0);
+                           false, &err);
+    error_free_or_abort(&err);
+    g_assert(!opts);
 
     /* Suffixes */
     opts = qemu_opts_parse(&opts_list_02, "size1=8b,size2=1.5k,size3=2M",
@@ -688,19 +687,17 @@ static void test_opts_parse_size(void)
 
     /* Beyond limit with suffix */
     opts = qemu_opts_parse(&opts_list_02, "size1=16777216T",
-                           false, &error_abort);
-    /* BUG: should reject */
-    g_assert_cmpuint(opts_count(opts), ==, 1);
-    g_assert_cmpuint(qemu_opt_get_size(opts, "size1", 1), ==, 0);
+                           false, &err);
+    error_free_or_abort(&err);
+    g_assert(!opts);
 
     /* Trailing crap */
     opts = qemu_opts_parse(&opts_list_02, "size1=16E", false, &err);
     error_free_or_abort(&err);
     g_assert(!opts);
-    opts = qemu_opts_parse(&opts_list_02, "size1=16Gi", false, &error_abort);
-    /* BUG: should reject */
-    g_assert_cmpuint(opts_count(opts), ==, 1);
-    g_assert_cmpuint(qemu_opt_get_size(opts, "size1", 1), ==, 16 * G_BYTE);
+    opts = qemu_opts_parse(&opts_list_02, "size1=16Gi", false, &err);
+    error_free_or_abort(&err);
+    g_assert(!opts);
 
     qemu_opts_reset(&opts_list_02);
 }
diff --git a/util/qemu-option.c b/util/qemu-option.c
index 5d82327..c11ce93 100644
--- a/util/qemu-option.c
+++ b/util/qemu-option.c
@@ -174,39 +174,24 @@ static const QemuOptDesc *find_desc_by_name(const QemuOptDesc *desc,
 void parse_option_size(const char *name, const char *value,
                        uint64_t *ret, Error **errp)
 {
-    char *postfix;
-    double sizef;
+    uint64_t size;
+    int err;
 
-    sizef = strtod(value, &postfix);
-    if (sizef < 0 || sizef > UINT64_MAX) {
+    err = qemu_strtosz(value, NULL, &size);
+    if (err == -ERANGE) {
+        error_setg(errp, "Value '%s' is too large for parameter '%s'",
+                   value, name);
+        return;
+    }
+    if (err) {
         error_setg(errp, QERR_INVALID_PARAMETER_VALUE, name,
                    "a non-negative number below 2^64");
+        error_append_hint(errp, "Optional suffix k, M, G, T, P or E means"
+                          " kilo-, mega-, giga-, tera-, peta-\n"
+                          "and exabytes, respectively.\n");
         return;
     }
-    switch (*postfix) {
-    case 'T':
-        sizef *= 1024;
-        /* fall through */
-    case 'G':
-        sizef *= 1024;
-        /* fall through */
-    case 'M':
-        sizef *= 1024;
-        /* fall through */
-    case 'K':
-    case 'k':
-        sizef *= 1024;
-        /* fall through */
-    case 'b':
-    case '\0':
-        *ret = (uint64_t) sizef;
-        break;
-    default:
-        error_setg(errp, QERR_INVALID_PARAMETER_VALUE, name, "a size");
-        error_append_hint(errp, "You may use k, M, G or T suffixes for "
-                          "kilobytes, megabytes, gigabytes and terabytes.\n");
-        return;
-    }
+    *ret = size;
 }
 
 bool has_help_option(const char *param)
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 79+ messages in thread

* Re: [Qemu-devel] [PATCH 08/24] util/cutils: Clean up control flow around qemu_strtol() a bit
  2017-02-14 10:25 ` [Qemu-devel] [PATCH 08/24] util/cutils: Clean up control flow around qemu_strtol() a bit Markus Armbruster
@ 2017-02-14 10:53   ` Peter Maydell
  2017-02-14 12:58     ` Markus Armbruster
  2017-02-14 21:40   ` Eric Blake
  1 sibling, 1 reply; 79+ messages in thread
From: Peter Maydell @ 2017-02-14 10:53 UTC (permalink / raw)
  To: Markus Armbruster; +Cc: QEMU Developers

On 14 February 2017 at 10:25, Markus Armbruster <armbru@redhat.com> wrote:
> Reorder check_strtox_error() to make it obvious that we always store
> through a non-null @endptr.
>
> Transform
>
>     if (some error) {
>         error case ...
>         err = value for error case;
>     } else {
>         normal case ...
>         err = value for normal case;
>     }
>     return err;
>
> to
>
>     if (some error) {
>         error case ...
>         return value for error case;
>     }
>     normal case ...
>     return value for normal case;
>
> Signed-off-by: Markus Armbruster <armbru@redhat.com>
> ---
>  util/cutils.c | 89 ++++++++++++++++++++++++++++++-----------------------------
>  1 file changed, 45 insertions(+), 44 deletions(-)
>
> diff --git a/util/cutils.c b/util/cutils.c
> index 7d165bc..7442d46 100644
> --- a/util/cutils.c
> +++ b/util/cutils.c
> @@ -265,15 +265,20 @@ int64_t qemu_strtosz(const char *nptr, char **end)
>  static int check_strtox_error(const char *nptr, char *ep,
>                                const char **endptr, int eno)
>  {
> -    if (eno == 0 && ep == nptr) {
> -        eno = EINVAL;
> -    }
> -    if (!endptr && *ep) {
> -        return -EINVAL;
> -    }
>      if (endptr) {
>          *endptr = ep;
>      }
> +
> +    /* Turn "no conversion" into an error */
> +    if (eno == 0 && ep == nptr) {
> +        return -EINVAL;
> +    }
> +
> +    /* Fail when we're expected to consume the string, but didn't */
> +    if (!endptr && *ep) {
> +        return -EINVAL;
> +    }
> +
>      return -eno;
>  }

Doesn't this change the semantics? Previously, for the
case of (eno == 0 && ep == nptr) we would both set
*endptr to ep and return -EINVAL. Now we only return -EINVAL
and leave *endptr alone. The comment describing the
qemu_strtol() API is a bit vague about what exactly we keep
from the strtol() semantics for "no convertable characters"
but I would assume that retaining "*endptr is written with
the original value of nptr" is intentional.

thanks
-- PMM

^ permalink raw reply	[flat|nested] 79+ messages in thread

* Re: [Qemu-devel] [PATCH 00/24] QemuOpts util/cutils: Fix and clean up number conversions
  2017-02-14 10:25 [Qemu-devel] [PATCH 00/24] QemuOpts util/cutils: Fix and clean up number conversions Markus Armbruster
                   ` (23 preceding siblings ...)
  2017-02-14 10:26 ` [Qemu-devel] [PATCH 24/24] QemuOpts: Fix checking of sizes for overflow and trailing crap Markus Armbruster
@ 2017-02-14 10:57 ` no-reply
  2017-02-14 12:37 ` Paolo Bonzini
  25 siblings, 0 replies; 79+ messages in thread
From: no-reply @ 2017-02-14 10:57 UTC (permalink / raw)
  To: armbru; +Cc: famz, qemu-devel

Hi,

Your series seems to have some coding style problems. See output below for
more information:

Subject: [Qemu-devel] [PATCH 00/24] QemuOpts util/cutils: Fix and clean up number conversions
Message-id: 1487067971-10443-1-git-send-email-armbru@redhat.com
Type: series

=== TEST SCRIPT BEGIN ===
#!/bin/bash

BASE=base
n=1
total=$(git log --oneline $BASE.. | wc -l)
failed=0

# Useful git options
git config --local diff.renamelimit 0
git config --local diff.renames True

commits="$(git log --format=%H --reverse $BASE..)"
for c in $commits; do
    echo "Checking PATCH $n/$total: $(git log -n 1 --format=%s $c)..."
    if ! git show $c --format=email | ./scripts/checkpatch.pl --mailback -; then
        failed=1
        echo
    fi
    n=$((n+1))
done

exit $failed
=== TEST SCRIPT END ===

Updating 3c8cf5a9c21ff8782164d1def7f44bd888713384
From https://github.com/patchew-project/qemu
 * [new tag]         patchew/1487067971-10443-1-git-send-email-armbru@redhat.com -> patchew/1487067971-10443-1-git-send-email-armbru@redhat.com
Switched to a new branch 'test'
855de21 QemuOpts: Fix checking of sizes for overflow and trailing crap
704c59b util/cutils: Change qemu_strtosz*() from int64_t to uint64_t
926a170 util/cutils: Return qemu_strtosz*() error and value separately
3efa6d4 util/cutils: Let qemu_strtosz*() optionally reject trailing crap
bd4e31d qemu-img: Wrap cvtnum() around qemu_strtosz()
18a3da0 tests/test-cutils: Drop suffix from test_qemu_strtosz_simple()
f2880dd tests/test-cutils: Use qemu_strtosz() more often
8e04b3b util/cutils: Drop QEMU_STRTOSZ_DEFSUFFIX_* macros
25f2bf6 util/cutils: New qemu_strtosz()
d133023 util/cutils: Rename qemu_strtosz() to qemu_strtosz_mebi()
5c33f1b util/cutils: New qemu_strtosz_metric()
567a856 tests/test-cutils: Cover qemu_strtosz() around range limits
5eea8e0 tests/test-cutils: Cover qemu_strtosz() with trailing crap
db765f5 tests/test-cutils: Cover qemu_strtosz() invalid input
958d0f3 tests/test-cutils: Add missing qemu_strtosz()... endptr checks
7c61791 QemuOpts: Fix to reject numbers that overflow uint64_t
29872d3 util/cutils: Clean up control flow around qemu_strtol() a bit
3a696e2 util/cutils: Clean up variable names around qemu_strtol()
b2e8b59 util/cutils: Rename qemu_strtoll(), qemu_strtoull()
5153908 util/cutils: Rewrite documentation of qemu_strtol() & friends
32a7846 tests/test-cutils: Clean up qemu_strtoul() result checks
2a602fb tests/test-cutils: Add missing qemu_strtol()... endptr checks
ebda9f0 QemuOpts: Assert value string isn't null
aced107 tests/test-qemu-opts: Cover qemu_opts_parse()

=== OUTPUT BEGIN ===
Checking PATCH 1/24: tests/test-qemu-opts: Cover qemu_opts_parse()...
Checking PATCH 2/24: QemuOpts: Assert value string isn't null...
ERROR: consider using qemu_strtoull in preference to strtoull
#75: FILE: util/qemu-option.c:147:
+    number = strtoull(value, &postfix, 0);

total: 1 errors, 0 warnings, 117 lines checked

Your patch has style problems, please review.  If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.

Checking PATCH 3/24: tests/test-cutils: Add missing qemu_strtol()... endptr checks...
Checking PATCH 4/24: tests/test-cutils: Clean up qemu_strtoul() result checks...
Checking PATCH 5/24: util/cutils: Rewrite documentation of qemu_strtol() & friends...
Checking PATCH 6/24: util/cutils: Rename qemu_strtoll(), qemu_strtoull()...
Checking PATCH 7/24: util/cutils: Clean up variable names around qemu_strtol()...
ERROR: consider using qemu_strtol in preference to strtol
#76: FILE: util/cutils.c:316:
+        *result = strtol(nptr, &ep, base);

ERROR: consider using qemu_strtoul in preference to strtoul
#95: FILE: util/cutils.c:359:
+        *result = strtoul(nptr, &ep, base);

ERROR: consider using qemu_strtoll in preference to strtoll
#120: FILE: util/cutils.c:388:
+        *result = strtoll(nptr, &ep, base);

ERROR: consider using qemu_strtoull in preference to strtoull
#139: FILE: util/cutils.c:412:
+        *result = strtoull(nptr, &ep, base);

total: 4 errors, 0 warnings, 110 lines checked

Your patch has style problems, please review.  If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.

Checking PATCH 8/24: util/cutils: Clean up control flow around qemu_strtol() a bit...
ERROR: consider using qemu_strtol in preference to strtol
#81: FILE: util/cutils.c:322:
+    *result = strtol(nptr, &ep, base);

ERROR: consider using qemu_strtoul in preference to strtoul
#109: FILE: util/cutils.c:364:
+    *result = strtoul(nptr, &ep, base);

ERROR: consider using qemu_strtoll in preference to strtoll
#141: FILE: util/cutils.c:392:
+    *result = strtoll(nptr, &ep, base);

ERROR: consider using qemu_strtoull in preference to strtoull
#171: FILE: util/cutils.c:415:
+    *result = strtoull(nptr, &ep, base);

total: 4 errors, 0 warnings, 140 lines checked

Your patch has style problems, please review.  If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.

Checking PATCH 9/24: QemuOpts: Fix to reject numbers that overflow uint64_t...
Checking PATCH 10/24: tests/test-cutils: Add missing qemu_strtosz()... endptr checks...
Checking PATCH 11/24: tests/test-cutils: Cover qemu_strtosz() invalid input...
Checking PATCH 12/24: tests/test-cutils: Cover qemu_strtosz() with trailing crap...
Checking PATCH 13/24: tests/test-cutils: Cover qemu_strtosz() around range limits...
Checking PATCH 14/24: util/cutils: New qemu_strtosz_metric()...
Checking PATCH 15/24: util/cutils: Rename qemu_strtosz() to qemu_strtosz_mebi()...
Checking PATCH 16/24: util/cutils: New qemu_strtosz()...
Checking PATCH 17/24: util/cutils: Drop QEMU_STRTOSZ_DEFSUFFIX_* macros...
Checking PATCH 18/24: tests/test-cutils: Use qemu_strtosz() more often...
Checking PATCH 19/24: tests/test-cutils: Drop suffix from test_qemu_strtosz_simple()...
Checking PATCH 20/24: qemu-img: Wrap cvtnum() around qemu_strtosz()...
Checking PATCH 21/24: util/cutils: Let qemu_strtosz*() optionally reject trailing crap...
Checking PATCH 22/24: util/cutils: Return qemu_strtosz*() error and value separately...
Checking PATCH 23/24: util/cutils: Change qemu_strtosz*() from int64_t to uint64_t...
Checking PATCH 24/24: QemuOpts: Fix checking of sizes for overflow and trailing crap...
=== OUTPUT END ===

Test command exited with code: 1


---
Email generated automatically by Patchew [http://patchew.org/].
Please send your feedback to patchew-devel@freelists.org

^ permalink raw reply	[flat|nested] 79+ messages in thread

* Re: [Qemu-devel] [PATCH 07/24] util/cutils: Clean up variable names around qemu_strtol()
  2017-02-14 10:25 ` [Qemu-devel] [PATCH 07/24] util/cutils: Clean up variable names around qemu_strtol() Markus Armbruster
@ 2017-02-14 12:33   ` Paolo Bonzini
  2017-02-14 13:11     ` Markus Armbruster
  2017-02-14 21:37   ` Eric Blake
  1 sibling, 1 reply; 79+ messages in thread
From: Paolo Bonzini @ 2017-02-14 12:33 UTC (permalink / raw)
  To: Markus Armbruster, qemu-devel



On 14/02/2017 11:25, Markus Armbruster wrote:
> * qemu_strtol()'s variable @err is *negative* errno,
>   check_strtox_error()'s parameter @err is *positive*.  Rename the
>   latter to @eno.

What about in_errno or libc_errno?  No need to repost of course.

Paolo

^ permalink raw reply	[flat|nested] 79+ messages in thread

* Re: [Qemu-devel] [PATCH 15/24] util/cutils: Rename qemu_strtosz() to qemu_strtosz_mebi()
  2017-02-14 10:26 ` [Qemu-devel] [PATCH 15/24] util/cutils: Rename qemu_strtosz() to qemu_strtosz_mebi() Markus Armbruster
@ 2017-02-14 12:35   ` Paolo Bonzini
  2017-02-14 13:12     ` Markus Armbruster
  2017-02-17 20:45   ` Eric Blake
  1 sibling, 1 reply; 79+ messages in thread
From: Paolo Bonzini @ 2017-02-14 12:35 UTC (permalink / raw)
  To: Markus Armbruster, qemu-devel



On 14/02/2017 11:26, Markus Armbruster wrote:
> With qemu_strtosz(), no suffix means mebibytes.  It's used rarely.
> I'm going to add a similar function where no suffix means bytes.
> Rename qemu_strtosz() to qemu_strtosz_mebi() to make the name
> qemu_strtosz() available for the new function.

What about qemu_strtosz_MiB (yes, camelcase intended).

Paolo

> 
> Signed-off-by: Markus Armbruster <armbru@redhat.com>
> ---
>  hmp.c                 |  2 +-
>  hw/misc/ivshmem.c     |  2 +-
>  include/qemu/cutils.h |  2 +-
>  monitor.c             |  2 +-
>  tests/test-cutils.c   | 38 +++++++++++++++++++-------------------
>  util/cutils.c         |  2 +-
>  6 files changed, 24 insertions(+), 24 deletions(-)
> 
> diff --git a/hmp.c b/hmp.c
> index 2bc4f06..6d0d05b 100644
> --- a/hmp.c
> +++ b/hmp.c
> @@ -1379,7 +1379,7 @@ void hmp_migrate_set_parameter(Monitor *mon, const QDict *qdict)
>                  break;
>              case MIGRATION_PARAMETER_MAX_BANDWIDTH:
>                  p.has_max_bandwidth = true;
> -                valuebw = qemu_strtosz(valuestr, &endp);
> +                valuebw = qemu_strtosz_mebi(valuestr, &endp);
>                  if (valuebw < 0 || (size_t)valuebw != valuebw
>                      || *endp != '\0') {
>                      error_setg(&err, "Invalid size %s", valuestr);
> diff --git a/hw/misc/ivshmem.c b/hw/misc/ivshmem.c
> index bf57e63..382dd8b 100644
> --- a/hw/misc/ivshmem.c
> +++ b/hw/misc/ivshmem.c
> @@ -1268,7 +1268,7 @@ static void ivshmem_realize(PCIDevice *dev, Error **errp)
>          s->legacy_size = 4 << 20; /* 4 MB default */
>      } else {
>          char *end;
> -        int64_t size = qemu_strtosz(s->sizearg, &end);
> +        int64_t size = qemu_strtosz_mebi(s->sizearg, &end);
>          if (size < 0 || (size_t)size != size || *end != '\0'
>              || !is_power_of_2(size)) {
>              error_setg(errp, "Invalid size %s", s->sizearg);
> diff --git a/include/qemu/cutils.h b/include/qemu/cutils.h
> index 81613d0..5f4e138 100644
> --- a/include/qemu/cutils.h
> +++ b/include/qemu/cutils.h
> @@ -153,9 +153,9 @@ int parse_uint_full(const char *s, unsigned long long *value, int base);
>  #define QEMU_STRTOSZ_DEFSUFFIX_MB 'M'
>  #define QEMU_STRTOSZ_DEFSUFFIX_KB 'K'
>  #define QEMU_STRTOSZ_DEFSUFFIX_B 'B'
> -int64_t qemu_strtosz(const char *nptr, char **end);
>  int64_t qemu_strtosz_suffix(const char *nptr, char **end,
>                              const char default_suffix);
> +int64_t qemu_strtosz_mebi(const char *nptr, char **end);
>  int64_t qemu_strtosz_metric(const char *nptr, char **end);
>  
>  #define K_BYTE     (1ULL << 10)
> diff --git a/monitor.c b/monitor.c
> index 3cd72a9..1f8c031 100644
> --- a/monitor.c
> +++ b/monitor.c
> @@ -2785,7 +2785,7 @@ static QDict *monitor_parse_arguments(Monitor *mon,
>                          break;
>                      }
>                  }
> -                val = qemu_strtosz(p, &end);
> +                val = qemu_strtosz_mebi(p, &end);
>                  if (val < 0) {
>                      monitor_printf(mon, "invalid size\n");
>                      goto fail;
> diff --git a/tests/test-cutils.c b/tests/test-cutils.c
> index 383f812..86d36b7 100644
> --- a/tests/test-cutils.c
> +++ b/tests/test-cutils.c
> @@ -1376,16 +1376,16 @@ static void test_qemu_strtosz_simple(void)
>      int64_t res;
>  
>      str = "0";
> -    res = qemu_strtosz(str, &endptr);
> +    res = qemu_strtosz_mebi(str, &endptr);
>      g_assert_cmpint(res, ==, 0);
>      g_assert(endptr == str + 1);
>  
>      str = "12345M";
> -    res = qemu_strtosz(str, &endptr);
> +    res = qemu_strtosz_mebi(str, &endptr);
>      g_assert_cmpint(res, ==, 12345 * M_BYTE);
>      g_assert(endptr == str + 6);
>  
> -    res = qemu_strtosz(str, NULL);
> +    res = qemu_strtosz_mebi(str, NULL);
>      g_assert_cmpint(res, ==, 12345 * M_BYTE);
>  
>      /* Note: precision is 53 bits since we're parsing with strtod() */
> @@ -1433,35 +1433,35 @@ static void test_qemu_strtosz_units(void)
>      int64_t res;
>  
>      /* default is M */
> -    res = qemu_strtosz(none, &endptr);
> +    res = qemu_strtosz_mebi(none, &endptr);
>      g_assert_cmpint(res, ==, M_BYTE);
>      g_assert(endptr == none + 1);
>  
> -    res = qemu_strtosz(b, &endptr);
> +    res = qemu_strtosz_mebi(b, &endptr);
>      g_assert_cmpint(res, ==, 1);
>      g_assert(endptr == b + 2);
>  
> -    res = qemu_strtosz(k, &endptr);
> +    res = qemu_strtosz_mebi(k, &endptr);
>      g_assert_cmpint(res, ==, K_BYTE);
>      g_assert(endptr == k + 2);
>  
> -    res = qemu_strtosz(m, &endptr);
> +    res = qemu_strtosz_mebi(m, &endptr);
>      g_assert_cmpint(res, ==, M_BYTE);
>      g_assert(endptr == m + 2);
>  
> -    res = qemu_strtosz(g, &endptr);
> +    res = qemu_strtosz_mebi(g, &endptr);
>      g_assert_cmpint(res, ==, G_BYTE);
>      g_assert(endptr == g + 2);
>  
> -    res = qemu_strtosz(t, &endptr);
> +    res = qemu_strtosz_mebi(t, &endptr);
>      g_assert_cmpint(res, ==, T_BYTE);
>      g_assert(endptr == t + 2);
>  
> -    res = qemu_strtosz(p, &endptr);
> +    res = qemu_strtosz_mebi(p, &endptr);
>      g_assert_cmpint(res, ==, P_BYTE);
>      g_assert(endptr == p + 2);
>  
> -    res = qemu_strtosz(e, &endptr);
> +    res = qemu_strtosz_mebi(e, &endptr);
>      g_assert_cmpint(res, ==, E_BYTE);
>      g_assert(endptr == e + 2);
>  }
> @@ -1472,7 +1472,7 @@ static void test_qemu_strtosz_float(void)
>      char *endptr = NULL;
>      int64_t res;
>  
> -    res = qemu_strtosz(str, &endptr);
> +    res = qemu_strtosz_mebi(str, &endptr);
>      g_assert_cmpint(res, ==, 12.345 * M_BYTE);
>      g_assert(endptr == str + 7);
>  }
> @@ -1484,17 +1484,17 @@ static void test_qemu_strtosz_invalid(void)
>      int64_t res;
>  
>      str = "";
> -    res = qemu_strtosz(str, &endptr);
> +    res = qemu_strtosz_mebi(str, &endptr);
>      g_assert_cmpint(res, ==, -EINVAL);
>      g_assert(endptr == str);
>  
>      str = " \t ";
> -    res = qemu_strtosz(str, &endptr);
> +    res = qemu_strtosz_mebi(str, &endptr);
>      g_assert_cmpint(res, ==, -EINVAL);
>      g_assert(endptr == str);
>  
>      str = "crap";
> -    res = qemu_strtosz(str, &endptr);
> +    res = qemu_strtosz_mebi(str, &endptr);
>      g_assert_cmpint(res, ==, -EINVAL);
>      g_assert(endptr == str);
>  }
> @@ -1506,12 +1506,12 @@ static void test_qemu_strtosz_trailing(void)
>      int64_t res;
>  
>      str = "123xxx";
> -    res = qemu_strtosz(str, &endptr);
> +    res = qemu_strtosz_mebi(str, &endptr);
>      g_assert_cmpint(res, ==, 123 * M_BYTE);
>      g_assert(endptr == str + 3);
>  
>      str = "1kiB";
> -    res = qemu_strtosz(str, &endptr);
> +    res = qemu_strtosz_mebi(str, &endptr);
>      g_assert_cmpint(res, ==, 1024);
>      g_assert(endptr == str + 2);
>  }
> @@ -1523,7 +1523,7 @@ static void test_qemu_strtosz_erange(void)
>      int64_t res;
>  
>      str = "-1";
> -    res = qemu_strtosz(str, &endptr);
> +    res = qemu_strtosz_mebi(str, &endptr);
>      g_assert_cmpint(res, ==, -ERANGE);
>      g_assert(endptr == str + 2);
>  
> @@ -1543,7 +1543,7 @@ static void test_qemu_strtosz_erange(void)
>      g_assert(endptr == str + 19);
>  
>      str = "10E";
> -    res = qemu_strtosz(str, &endptr);
> +    res = qemu_strtosz_mebi(str, &endptr);
>      g_assert_cmpint(res, ==, -ERANGE);
>      g_assert(endptr == str + 3);
>  }
> diff --git a/util/cutils.c b/util/cutils.c
> index 8a506e7..0315d5d 100644
> --- a/util/cutils.c
> +++ b/util/cutils.c
> @@ -254,7 +254,7 @@ int64_t qemu_strtosz_suffix(const char *nptr, char **end,
>      return do_strtosz(nptr, end, default_suffix, 1024);
>  }
>  
> -int64_t qemu_strtosz(const char *nptr, char **end)
> +int64_t qemu_strtosz_mebi(const char *nptr, char **end)
>  {
>      return qemu_strtosz_suffix(nptr, end, QEMU_STRTOSZ_DEFSUFFIX_MB);
>  }
> 

^ permalink raw reply	[flat|nested] 79+ messages in thread

* Re: [Qemu-devel] [PATCH 00/24] QemuOpts util/cutils: Fix and clean up number conversions
  2017-02-14 10:25 [Qemu-devel] [PATCH 00/24] QemuOpts util/cutils: Fix and clean up number conversions Markus Armbruster
                   ` (24 preceding siblings ...)
  2017-02-14 10:57 ` [Qemu-devel] [PATCH 00/24] QemuOpts util/cutils: Fix and clean up number conversions no-reply
@ 2017-02-14 12:37 ` Paolo Bonzini
  25 siblings, 0 replies; 79+ messages in thread
From: Paolo Bonzini @ 2017-02-14 12:37 UTC (permalink / raw)
  To: Markus Armbruster, qemu-devel



On 14/02/2017 11:25, Markus Armbruster wrote:
> QemuOpts has its own code to convert strings to numbers, and being
> QemuOpts, it gets it wrong.  util/cutils is less wrong.  Fix it up
> some, and reuse it for QemuOpts.

Nice.  I only had a couple minor remarks.

Paolo

> Markus Armbruster (24):
>   tests/test-qemu-opts: Cover qemu_opts_parse()
>   QemuOpts: Assert value string isn't null
>   tests/test-cutils: Add missing qemu_strtol()... endptr checks
>   tests/test-cutils: Clean up qemu_strtoul() result checks
>   util/cutils: Rewrite documentation of qemu_strtol() & friends
>   util/cutils: Rename qemu_strtoll(), qemu_strtoull()
>   util/cutils: Clean up variable names around qemu_strtol()
>   util/cutils: Clean up control flow around qemu_strtol() a bit
>   QemuOpts: Fix to reject numbers that overflow uint64_t
>   tests/test-cutils: Add missing qemu_strtosz()... endptr checks
>   tests/test-cutils: Cover qemu_strtosz() invalid input
>   tests/test-cutils: Cover qemu_strtosz() with trailing crap
>   tests/test-cutils: Cover qemu_strtosz() around range limits
>   util/cutils: New qemu_strtosz_metric()
>   util/cutils: Rename qemu_strtosz() to qemu_strtosz_mebi()
>   util/cutils: New qemu_strtosz()
>   util/cutils: Drop QEMU_STRTOSZ_DEFSUFFIX_* macros
>   tests/test-cutils: Use qemu_strtosz() more often
>   tests/test-cutils: Drop suffix from test_qemu_strtosz_simple()
>   qemu-img: Wrap cvtnum() around qemu_strtosz()
>   util/cutils: Let qemu_strtosz*() optionally reject trailing crap
>   util/cutils: Return qemu_strtosz*() error and value separately
>   util/cutils: Change qemu_strtosz*() from int64_t to uint64_t
>   QemuOpts: Fix checking of sizes for overflow and trailing crap

^ permalink raw reply	[flat|nested] 79+ messages in thread

* Re: [Qemu-devel] [PATCH 08/24] util/cutils: Clean up control flow around qemu_strtol() a bit
  2017-02-14 10:53   ` Peter Maydell
@ 2017-02-14 12:58     ` Markus Armbruster
  2017-02-14 13:01       ` Peter Maydell
  0 siblings, 1 reply; 79+ messages in thread
From: Markus Armbruster @ 2017-02-14 12:58 UTC (permalink / raw)
  To: Peter Maydell; +Cc: QEMU Developers

Peter Maydell <peter.maydell@linaro.org> writes:

> On 14 February 2017 at 10:25, Markus Armbruster <armbru@redhat.com> wrote:
>> Reorder check_strtox_error() to make it obvious that we always store
>> through a non-null @endptr.
>>
>> Transform
>>
>>     if (some error) {
>>         error case ...
>>         err = value for error case;
>>     } else {
>>         normal case ...
>>         err = value for normal case;
>>     }
>>     return err;
>>
>> to
>>
>>     if (some error) {
>>         error case ...
>>         return value for error case;
>>     }
>>     normal case ...
>>     return value for normal case;
>>
>> Signed-off-by: Markus Armbruster <armbru@redhat.com>
>> ---
>>  util/cutils.c | 89 ++++++++++++++++++++++++++++++-----------------------------
>>  1 file changed, 45 insertions(+), 44 deletions(-)
>>
>> diff --git a/util/cutils.c b/util/cutils.c
>> index 7d165bc..7442d46 100644
>> --- a/util/cutils.c
>> +++ b/util/cutils.c
>> @@ -265,15 +265,20 @@ int64_t qemu_strtosz(const char *nptr, char **end)
>>  static int check_strtox_error(const char *nptr, char *ep,
>>                                const char **endptr, int eno)
>>  {
>> -    if (eno == 0 && ep == nptr) {
>> -        eno = EINVAL;
>> -    }
>> -    if (!endptr && *ep) {
>> -        return -EINVAL;
>> -    }
>>      if (endptr) {
>>          *endptr = ep;
>>      }
>> +
>> +    /* Turn "no conversion" into an error */
>> +    if (eno == 0 && ep == nptr) {
>> +        return -EINVAL;
>> +    }
>> +
>> +    /* Fail when we're expected to consume the string, but didn't */
>> +    if (!endptr && *ep) {
>> +        return -EINVAL;
>> +    }
>> +
>>      return -eno;
>>  }
>
> Doesn't this change the semantics? Previously, for the
> case of (eno == 0 && ep == nptr) we would both set
> *endptr to ep and return -EINVAL. Now we only return -EINVAL
> and leave *endptr alone.

Behavior before the patch:

    if (eno == 0 && ep == nptr) {
        eno = EINVAL;           // set return value to EINVAL, but continue
    }
    if (!endptr && *ep) {
        return -EINVAL;         // return -EINVAL without setting *endptr
                                // correct because endptr is null
    }
    if (endptr) {
        *endptr = ep;           // set *endptr unless endptr is null
    }
    return -eno;                // *endptr got set unless endptr is null

As you say, we set *endptr unless it's null.

After the patch:

    if (endptr) {
        *endptr = ep;           // set *endptr unless endptr is null
    }

    // no matter what happens below, *endptr got set unless endptr is null

    /* Turn "no conversion" into an error */
    if (eno == 0 && ep == nptr) {
        return -EINVAL;
    }

    /* Fail when we're expected to consume the string, but didn't */
    if (!endptr && *ep) {
        return -EINVAL;
    }

    return -eno;

No change, as far as I can tell.

>                          The comment describing the
> qemu_strtol() API is a bit vague about what exactly we keep
> from the strtol() semantics for "no convertable characters"
> but I would assume that retaining "*endptr is written with
> the original value of nptr" is intentional.

I rewrite the comment PATCH 05.  Relevant part:

 * @nptr may be null, and no conversion is performed then.
 *
 * If no conversion is performed, store @nptr in *@endptr and return
 * -EINVAL.

I guess I should qualify "store @nptr in *@endptr" with "unless @endptr
is null" for completeness.  Anything else to improve?

^ permalink raw reply	[flat|nested] 79+ messages in thread

* Re: [Qemu-devel] [PATCH 08/24] util/cutils: Clean up control flow around qemu_strtol() a bit
  2017-02-14 12:58     ` Markus Armbruster
@ 2017-02-14 13:01       ` Peter Maydell
  0 siblings, 0 replies; 79+ messages in thread
From: Peter Maydell @ 2017-02-14 13:01 UTC (permalink / raw)
  To: Markus Armbruster; +Cc: QEMU Developers

On 14 February 2017 at 12:58, Markus Armbruster <armbru@redhat.com> wrote:
> Peter Maydell <peter.maydell@linaro.org> writes:
>> Doesn't this change the semantics? Previously, for the
>> case of (eno == 0 && ep == nptr) we would both set
>> *endptr to ep and return -EINVAL. Now we only return -EINVAL
>> and leave *endptr alone.

> No change, as far as I can tell.

Ah, you're right, and I misread the diff. Sorry.

thanks
-- PMM

^ permalink raw reply	[flat|nested] 79+ messages in thread

* Re: [Qemu-devel] [PATCH 07/24] util/cutils: Clean up variable names around qemu_strtol()
  2017-02-14 12:33   ` Paolo Bonzini
@ 2017-02-14 13:11     ` Markus Armbruster
  0 siblings, 0 replies; 79+ messages in thread
From: Markus Armbruster @ 2017-02-14 13:11 UTC (permalink / raw)
  To: Paolo Bonzini; +Cc: qemu-devel

Paolo Bonzini <pbonzini@redhat.com> writes:

> On 14/02/2017 11:25, Markus Armbruster wrote:
>> * qemu_strtol()'s variable @err is *negative* errno,
>>   check_strtox_error()'s parameter @err is *positive*.  Rename the
>>   latter to @eno.
>
> What about in_errno or libc_errno?  No need to repost of course.

I don't mind.

^ permalink raw reply	[flat|nested] 79+ messages in thread

* Re: [Qemu-devel] [PATCH 15/24] util/cutils: Rename qemu_strtosz() to qemu_strtosz_mebi()
  2017-02-14 12:35   ` Paolo Bonzini
@ 2017-02-14 13:12     ` Markus Armbruster
  0 siblings, 0 replies; 79+ messages in thread
From: Markus Armbruster @ 2017-02-14 13:12 UTC (permalink / raw)
  To: Paolo Bonzini; +Cc: qemu-devel

Paolo Bonzini <pbonzini@redhat.com> writes:

> On 14/02/2017 11:26, Markus Armbruster wrote:
>> With qemu_strtosz(), no suffix means mebibytes.  It's used rarely.
>> I'm going to add a similar function where no suffix means bytes.
>> Rename qemu_strtosz() to qemu_strtosz_mebi() to make the name
>> qemu_strtosz() available for the new function.
>
> What about qemu_strtosz_MiB (yes, camelcase intended).

Yes, that seems clearer.  Thanks!

^ permalink raw reply	[flat|nested] 79+ messages in thread

* Re: [Qemu-devel] [PATCH 01/24] tests/test-qemu-opts: Cover qemu_opts_parse()
  2017-02-14 10:25 ` [Qemu-devel] [PATCH 01/24] tests/test-qemu-opts: Cover qemu_opts_parse() Markus Armbruster
@ 2017-02-14 19:48   ` Eric Blake
  0 siblings, 0 replies; 79+ messages in thread
From: Eric Blake @ 2017-02-14 19:48 UTC (permalink / raw)
  To: Markus Armbruster, qemu-devel

[-- Attachment #1: Type: text/plain, Size: 778 bytes --]

On 02/14/2017 04:25 AM, Markus Armbruster wrote:
> The new tests demonstrate a few bugs, all clearly marked.
> 
> Signed-off-by: Markus Armbruster <armbru@redhat.com>
> ---
>  tests/test-qemu-opts.c | 294 ++++++++++++++++++++++++++++++++++++++++++++++++-
>  1 file changed, 292 insertions(+), 2 deletions(-)

> 
> +
> +    /* Anti-social ID */
> +    opts = qemu_opts_parse(&opts_list_01, "id=666", false, &err);

Love it. It's always fun to see cute references in a testsuite.

Obviously, the rest of this series cleans up the messes you've
uncovered.  Some of those new tests are pretty embarrassing.

Reviewed-by: Eric Blake <eblake@redhat.com>

-- 
Eric Blake   eblake redhat com    +1-919-301-3266
Libvirt virtualization library http://libvirt.org


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 604 bytes --]

^ permalink raw reply	[flat|nested] 79+ messages in thread

* Re: [Qemu-devel] [PATCH 02/24] QemuOpts: Assert value string isn't null
  2017-02-14 10:25 ` [Qemu-devel] [PATCH 02/24] QemuOpts: Assert value string isn't null Markus Armbruster
@ 2017-02-14 20:10   ` Eric Blake
  2017-02-16 12:58     ` Markus Armbruster
  0 siblings, 1 reply; 79+ messages in thread
From: Eric Blake @ 2017-02-14 20:10 UTC (permalink / raw)
  To: Markus Armbruster, qemu-devel

[-- Attachment #1: Type: text/plain, Size: 1835 bytes --]

On 02/14/2017 04:25 AM, Markus Armbruster wrote:
> Plenty of code relies on QemuOpt member @str not being null, including
> qemu_opts_print(), qemu_opts_to_qdict(), and callbacks passed to
> qemu_opt_foreach().
> 

> 
> Assert member @str isn't null, so that misuse is caught right away.
> 
> Simplify parse_option_bool(), parse_option_number() and
> parse_option_size() accordingly.  Best viewed with whitespace changes
> ignored.
> 
> Signed-off-by: Markus Armbruster <armbru@redhat.com>
> ---
>  util/qemu-option.c | 89 ++++++++++++++++++++++++------------------------------
>  1 file changed, 39 insertions(+), 50 deletions(-)
> 

> @@ -180,39 +172,35 @@ void parse_option_size(const char *name, const char *value,
>      char *postfix;
>      double sizef;
>  

> +    sizef = strtod(value, &postfix);
> +    if (sizef < 0 || sizef > UINT64_MAX) {
> +        error_setg(errp, QERR_INVALID_PARAMETER_VALUE, name,
> +                   "a non-negative number below 2^64");
> +        return;
> +    }
> +    switch (*postfix) {
> +    case 'T':
...
> +    default:
>          error_setg(errp, QERR_INVALID_PARAMETER_VALUE, name, "a size");
> +        error_append_hint(errp, "You may use k, M, G or T suffixes for "
> +                          "kilobytes, megabytes, gigabytes and terabytes.\n");
> +        return;
>      }

Unrelated to this patch, but noticing it now: it looks like we blindly
accept "qemu-system-x86_64 -nodefaults -m 1Mgarbage" as meaning the same
as "... -m 1M".  Looking back at 1/24, looks like you marked that as one
of the buggy cases.  Good - I guess I'll get to comment more on it in a
later patch.

Reviewed-by: Eric Blake <eblake@redhat.com>

-- 
Eric Blake   eblake redhat com    +1-919-301-3266
Libvirt virtualization library http://libvirt.org


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 604 bytes --]

^ permalink raw reply	[flat|nested] 79+ messages in thread

* Re: [Qemu-devel] [PATCH 03/24] tests/test-cutils: Add missing qemu_strtol()... endptr checks
  2017-02-14 10:25 ` [Qemu-devel] [PATCH 03/24] tests/test-cutils: Add missing qemu_strtol()... endptr checks Markus Armbruster
@ 2017-02-14 20:11   ` Eric Blake
  2017-02-19  4:12   ` Philippe Mathieu-Daudé
  1 sibling, 0 replies; 79+ messages in thread
From: Eric Blake @ 2017-02-14 20:11 UTC (permalink / raw)
  To: Markus Armbruster, qemu-devel

[-- Attachment #1: Type: text/plain, Size: 811 bytes --]

On 02/14/2017 04:25 AM, Markus Armbruster wrote:
> Signed-off-by: Markus Armbruster <armbru@redhat.com>
> ---
>  tests/test-cutils.c | 12 ++++++++++++
>  1 file changed, 12 insertions(+)
> 
> diff --git a/tests/test-cutils.c b/tests/test-cutils.c
> index 20b0f59..71681dc 100644
> --- a/tests/test-cutils.c
> +++ b/tests/test-cutils.c
> @@ -262,6 +262,7 @@ static void test_qemu_strtol_empty(void)
>      err = qemu_strtol(str, &endptr, 0, &res);
>  
>      g_assert_cmpint(err, ==, -EINVAL);
> +    g_assert(endptr == str);
>  }

In other words, enforce more of our contract that even on errors, endptr
is set to a documented value.

Reviewed-by: Eric Blake <eblake@redhat.com>

-- 
Eric Blake   eblake redhat com    +1-919-301-3266
Libvirt virtualization library http://libvirt.org


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 604 bytes --]

^ permalink raw reply	[flat|nested] 79+ messages in thread

* Re: [Qemu-devel] [PATCH 04/24] tests/test-cutils: Clean up qemu_strtoul() result checks
  2017-02-14 10:25 ` [Qemu-devel] [PATCH 04/24] tests/test-cutils: Clean up qemu_strtoul() result checks Markus Armbruster
@ 2017-02-14 21:28   ` Eric Blake
  2017-02-16 13:07     ` Markus Armbruster
  0 siblings, 1 reply; 79+ messages in thread
From: Eric Blake @ 2017-02-14 21:28 UTC (permalink / raw)
  To: Markus Armbruster, qemu-devel

[-- Attachment #1: Type: text/plain, Size: 682 bytes --]

On 02/14/2017 04:25 AM, Markus Armbruster wrote:
> Use unsigned comparisons to check the result of qemu_strtoul() and
> strtoull().
> 
> Signed-off-by: Markus Armbruster <armbru@redhat.com>
> ---
>  tests/test-cutils.c | 60 ++++++++++++++++++++++++++---------------------------
>  1 file changed, 30 insertions(+), 30 deletions(-)
> 

No real difference except when the test fails (better printed result if
the number being printed exceeds the max signed counterpart value), but
never hurts to be more precise.

Reviewed-by: Eric Blake <eblake@redhat.com>

-- 
Eric Blake   eblake redhat com    +1-919-301-3266
Libvirt virtualization library http://libvirt.org


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 604 bytes --]

^ permalink raw reply	[flat|nested] 79+ messages in thread

* Re: [Qemu-devel] [PATCH 05/24] util/cutils: Rewrite documentation of qemu_strtol() & friends
  2017-02-14 10:25 ` [Qemu-devel] [PATCH 05/24] util/cutils: Rewrite documentation of qemu_strtol() & friends Markus Armbruster
@ 2017-02-14 21:32   ` Eric Blake
  2017-02-19  4:12   ` Philippe Mathieu-Daudé
  1 sibling, 0 replies; 79+ messages in thread
From: Eric Blake @ 2017-02-14 21:32 UTC (permalink / raw)
  To: Markus Armbruster, qemu-devel

[-- Attachment #1: Type: text/plain, Size: 911 bytes --]

On 02/14/2017 04:25 AM, Markus Armbruster wrote:
> Fixes the following documentation bugs:
> 
> * Fails to document that null @nptr is safe.
> 
> * Fails to document that we return -EINVAL when no conversion could be
>   performed (commit 47d4be1).
> 
> * Confuses long long with int64_t, and unsigned long long with
>   uint64_t.
> 
> * Claims the unsigned conversions can underflow.  They can't.
> 
> While there, mark problematic assumptions that int64_t is long long,
> and uint64_t is unsigned long long with FIXME comments.
> 
> Signed-off-by: Markus Armbruster <armbru@redhat.com>
> ---
>  util/cutils.c | 80 +++++++++++++++++++++++++++++++++--------------------------
>  1 file changed, 45 insertions(+), 35 deletions(-)
> 

Reviewed-by: Eric Blake <eblake@redhat.com>

-- 
Eric Blake   eblake redhat com    +1-919-301-3266
Libvirt virtualization library http://libvirt.org


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 604 bytes --]

^ permalink raw reply	[flat|nested] 79+ messages in thread

* Re: [Qemu-devel] [PATCH 06/24] util/cutils: Rename qemu_strtoll(), qemu_strtoull()
  2017-02-14 10:25 ` [Qemu-devel] [PATCH 06/24] util/cutils: Rename qemu_strtoll(), qemu_strtoull() Markus Armbruster
@ 2017-02-14 21:34   ` Eric Blake
  2017-02-19  4:14   ` Philippe Mathieu-Daudé
  1 sibling, 0 replies; 79+ messages in thread
From: Eric Blake @ 2017-02-14 21:34 UTC (permalink / raw)
  To: Markus Armbruster, qemu-devel

[-- Attachment #1: Type: text/plain, Size: 1007 bytes --]

On 02/14/2017 04:25 AM, Markus Armbruster wrote:
> The name qemu_strtoll() suggests conversion to long long, but it
> actually converts to int64_t.  Rename to qemu_strtoi64().
> 
> The name qemu_strtoull() suggests conversion to unsigned long long,
> but it actually converts to uint64_t.  Rename to qemu_strtou64().
> 
> Signed-off-by: Markus Armbruster <armbru@redhat.com>
> ---
>  include/qemu/cutils.h |   6 +-
>  qobject/qdict.c       |   2 +-
>  qtest.c               |  34 ++---
>  tests/test-cutils.c   | 366 +++++++++++++++++++++++++++-----------------------
>  util/cutils.c         |   4 +-
>  util/log.c            |   4 +-
>  6 files changed, 224 insertions(+), 192 deletions(-)

Thankfully, not too many existing clients (except in the testsuite).
Mechanical search-and-replace, and I don't see anything missed, so:

Reviewed-by: Eric Blake <eblake@redhat.com>

-- 
Eric Blake   eblake redhat com    +1-919-301-3266
Libvirt virtualization library http://libvirt.org


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 604 bytes --]

^ permalink raw reply	[flat|nested] 79+ messages in thread

* Re: [Qemu-devel] [PATCH 07/24] util/cutils: Clean up variable names around qemu_strtol()
  2017-02-14 10:25 ` [Qemu-devel] [PATCH 07/24] util/cutils: Clean up variable names around qemu_strtol() Markus Armbruster
  2017-02-14 12:33   ` Paolo Bonzini
@ 2017-02-14 21:37   ` Eric Blake
  1 sibling, 0 replies; 79+ messages in thread
From: Eric Blake @ 2017-02-14 21:37 UTC (permalink / raw)
  To: Markus Armbruster, qemu-devel

[-- Attachment #1: Type: text/plain, Size: 1065 bytes --]

On 02/14/2017 04:25 AM, Markus Armbruster wrote:
> Name same things the same, different things differently.
> 
> * qemu_strtol()'s parameter @nptr is called @p in
>   check_strtox_error().  Rename the latter.
> 
> * qemu_strtol()'s parameter @endptr is called @next in
>   check_strtox_error().  Rename the latter.
> 
> * qemu_strtol()'s variable @p is called @endptr in
>   check_strtox_error().  Rename both to @ep.
> 
> * qemu_strtol()'s variable @err is *negative* errno,
>   check_strtox_error()'s parameter @err is *positive*.  Rename the
>   latter to @eno.

Whether or not you rename @eno based on Paolo's comments,

> 
> Same for qemu_strtoul(), qemu_strtoi64(), qemu_strtou64(), of course.
> 
> Signed-off-by: Markus Armbruster <armbru@redhat.com>
> ---
>  util/cutils.c | 42 +++++++++++++++++++++---------------------
>  1 file changed, 21 insertions(+), 21 deletions(-)

Reviewed-by: Eric Blake <eblake@redhat.com>

-- 
Eric Blake   eblake redhat com    +1-919-301-3266
Libvirt virtualization library http://libvirt.org


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 604 bytes --]

^ permalink raw reply	[flat|nested] 79+ messages in thread

* Re: [Qemu-devel] [PATCH 08/24] util/cutils: Clean up control flow around qemu_strtol() a bit
  2017-02-14 10:25 ` [Qemu-devel] [PATCH 08/24] util/cutils: Clean up control flow around qemu_strtol() a bit Markus Armbruster
  2017-02-14 10:53   ` Peter Maydell
@ 2017-02-14 21:40   ` Eric Blake
  1 sibling, 0 replies; 79+ messages in thread
From: Eric Blake @ 2017-02-14 21:40 UTC (permalink / raw)
  To: Markus Armbruster, qemu-devel

[-- Attachment #1: Type: text/plain, Size: 980 bytes --]

On 02/14/2017 04:25 AM, Markus Armbruster wrote:
> Reorder check_strtox_error() to make it obvious that we always store
> through a non-null @endptr.
> 
> Transform
> 
>     if (some error) {
>         error case ...
>         err = value for error case;
>     } else {
>         normal case ...
>         err = value for normal case;
>     }
>     return err;
> 
> to
> 
>     if (some error) {
>         error case ...
>         return value for error case;
>     }
>     normal case ...
>     return value for normal case;
> 
> Signed-off-by: Markus Armbruster <armbru@redhat.com>
> ---
>  util/cutils.c | 89 ++++++++++++++++++++++++++++++-----------------------------
>  1 file changed, 45 insertions(+), 44 deletions(-)

No real net change in lines, but I agree that it is more legible.

Reviewed-by: Eric Blake <eblake@redhat.com>

-- 
Eric Blake   eblake redhat com    +1-919-301-3266
Libvirt virtualization library http://libvirt.org


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 604 bytes --]

^ permalink raw reply	[flat|nested] 79+ messages in thread

* Re: [Qemu-devel] [PATCH 09/24] QemuOpts: Fix to reject numbers that overflow uint64_t
  2017-02-14 10:25 ` [Qemu-devel] [PATCH 09/24] QemuOpts: Fix to reject numbers that overflow uint64_t Markus Armbruster
@ 2017-02-14 21:48   ` Eric Blake
  0 siblings, 0 replies; 79+ messages in thread
From: Eric Blake @ 2017-02-14 21:48 UTC (permalink / raw)
  To: Markus Armbruster, qemu-devel

[-- Attachment #1: Type: text/plain, Size: 534 bytes --]

On 02/14/2017 04:25 AM, Markus Armbruster wrote:
> parse_option_number() fails to check for overflow after strtoull().
> Has always been broken.  Fix that.
> 
> Signed-off-by: Markus Armbruster <armbru@redhat.com>
> ---
>  tests/test-qemu-opts.c | 14 ++++++--------
>  util/qemu-option.c     | 11 ++++++++---
>  2 files changed, 14 insertions(+), 11 deletions(-)
> 

Reviewed-by: Eric Blake <eblake@redhat.com>

-- 
Eric Blake   eblake redhat com    +1-919-301-3266
Libvirt virtualization library http://libvirt.org


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 604 bytes --]

^ permalink raw reply	[flat|nested] 79+ messages in thread

* Re: [Qemu-devel] [PATCH 10/24] tests/test-cutils: Add missing qemu_strtosz()... endptr checks
  2017-02-14 10:25 ` [Qemu-devel] [PATCH 10/24] tests/test-cutils: Add missing qemu_strtosz()... endptr checks Markus Armbruster
@ 2017-02-14 22:26   ` Eric Blake
  2017-02-19  4:16   ` Philippe Mathieu-Daudé
  1 sibling, 0 replies; 79+ messages in thread
From: Eric Blake @ 2017-02-14 22:26 UTC (permalink / raw)
  To: Markus Armbruster, qemu-devel

[-- Attachment #1: Type: text/plain, Size: 396 bytes --]

On 02/14/2017 04:25 AM, Markus Armbruster wrote:
> Signed-off-by: Markus Armbruster <armbru@redhat.com>
> ---
>  tests/test-cutils.c | 37 ++++++++++++++++++++++++++-----------
>  1 file changed, 26 insertions(+), 11 deletions(-)
> 

Reviewed-by: Eric Blake <eblake@redhat.com>

-- 
Eric Blake   eblake redhat com    +1-919-301-3266
Libvirt virtualization library http://libvirt.org


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 604 bytes --]

^ permalink raw reply	[flat|nested] 79+ messages in thread

* Re: [Qemu-devel] [PATCH 11/24] tests/test-cutils: Cover qemu_strtosz() invalid input
  2017-02-14 10:25 ` [Qemu-devel] [PATCH 11/24] tests/test-cutils: Cover qemu_strtosz() invalid input Markus Armbruster
@ 2017-02-14 22:53   ` Eric Blake
  2017-02-16 14:19     ` Markus Armbruster
  0 siblings, 1 reply; 79+ messages in thread
From: Eric Blake @ 2017-02-14 22:53 UTC (permalink / raw)
  To: Markus Armbruster, qemu-devel

[-- Attachment #1: Type: text/plain, Size: 424 bytes --]

On 02/14/2017 04:25 AM, Markus Armbruster wrote:
> Signed-off-by: Markus Armbruster <armbru@redhat.com>
> ---
>  tests/test-cutils.c | 24 ++++++++++++++++++++++++
>  1 file changed, 24 insertions(+)
> 

Perhaps you could also add a test of "-".  Either way,

Reviewed-by: Eric Blake <eblake@redhat.com>

-- 
Eric Blake   eblake redhat com    +1-919-301-3266
Libvirt virtualization library http://libvirt.org


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 604 bytes --]

^ permalink raw reply	[flat|nested] 79+ messages in thread

* Re: [Qemu-devel] [PATCH 12/24] tests/test-cutils: Cover qemu_strtosz() with trailing crap
  2017-02-14 10:25 ` [Qemu-devel] [PATCH 12/24] tests/test-cutils: Cover qemu_strtosz() with trailing crap Markus Armbruster
@ 2017-02-14 22:58   ` Eric Blake
  0 siblings, 0 replies; 79+ messages in thread
From: Eric Blake @ 2017-02-14 22:58 UTC (permalink / raw)
  To: Markus Armbruster, qemu-devel

[-- Attachment #1: Type: text/plain, Size: 1201 bytes --]

On 02/14/2017 04:25 AM, Markus Armbruster wrote:
> Signed-off-by: Markus Armbruster <armbru@redhat.com>
> ---
>  tests/test-cutils.c | 19 +++++++++++++++++++
>  1 file changed, 19 insertions(+)
> 

Reviewed-by: Eric Blake <eblake@redhat.com>

> diff --git a/tests/test-cutils.c b/tests/test-cutils.c
> index 3dcd4c1..ec65d27 100644
> --- a/tests/test-cutils.c
> +++ b/tests/test-cutils.c
> @@ -1463,6 +1463,23 @@ static void test_qemu_strtosz_invalid(void)
>      g_assert(endptr == str);
>  }
>  
> +static void test_qemu_strtosz_trailing(void)
> +{
> +    const char *str;
> +    char *endptr = NULL;
> +    int64_t res;
> +
> +    str = "123xxx";
> +    res = qemu_strtosz(str, &endptr);
> +    g_assert_cmpint(res, ==, 123 * M_BYTE);
> +    g_assert(endptr == str + 3);
> +
> +    str = "1kiB";

Personally, I think this one would be useful to support, but agree that
right now it should be handled as trailing garbage.

> +    res = qemu_strtosz(str, &endptr);
> +    g_assert_cmpint(res, ==, 1024);
> +    g_assert(endptr == str + 2);
> +}
> +


-- 
Eric Blake   eblake redhat com    +1-919-301-3266
Libvirt virtualization library http://libvirt.org


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 604 bytes --]

^ permalink raw reply	[flat|nested] 79+ messages in thread

* Re: [Qemu-devel] [PATCH 13/24] tests/test-cutils: Cover qemu_strtosz() around range limits
  2017-02-14 10:26 ` [Qemu-devel] [PATCH 13/24] tests/test-cutils: Cover qemu_strtosz() around range limits Markus Armbruster
@ 2017-02-14 23:14   ` Eric Blake
  0 siblings, 0 replies; 79+ messages in thread
From: Eric Blake @ 2017-02-14 23:14 UTC (permalink / raw)
  To: Markus Armbruster, qemu-devel

[-- Attachment #1: Type: text/plain, Size: 411 bytes --]

On 02/14/2017 04:26 AM, Markus Armbruster wrote:
> Signed-off-by: Markus Armbruster <armbru@redhat.com>
> ---
>  tests/test-cutils.c | 61 +++++++++++++++++++++++++++++++++++++++++++++++++++--
>  1 file changed, 59 insertions(+), 2 deletions(-)
> 

Reviewed-by: Eric Blake <eblake@redhat.com>

-- 
Eric Blake   eblake redhat com    +1-919-301-3266
Libvirt virtualization library http://libvirt.org


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 604 bytes --]

^ permalink raw reply	[flat|nested] 79+ messages in thread

* Re: [Qemu-devel] [PATCH 02/24] QemuOpts: Assert value string isn't null
  2017-02-14 20:10   ` Eric Blake
@ 2017-02-16 12:58     ` Markus Armbruster
  0 siblings, 0 replies; 79+ messages in thread
From: Markus Armbruster @ 2017-02-16 12:58 UTC (permalink / raw)
  To: Eric Blake; +Cc: qemu-devel

Eric Blake <eblake@redhat.com> writes:

> On 02/14/2017 04:25 AM, Markus Armbruster wrote:
>> Plenty of code relies on QemuOpt member @str not being null, including
>> qemu_opts_print(), qemu_opts_to_qdict(), and callbacks passed to
>> qemu_opt_foreach().
>> 
>
>> 
>> Assert member @str isn't null, so that misuse is caught right away.
>> 
>> Simplify parse_option_bool(), parse_option_number() and
>> parse_option_size() accordingly.  Best viewed with whitespace changes
>> ignored.
>> 
>> Signed-off-by: Markus Armbruster <armbru@redhat.com>
>> ---
>>  util/qemu-option.c | 89 ++++++++++++++++++++++++------------------------------
>>  1 file changed, 39 insertions(+), 50 deletions(-)
>> 
>
>> @@ -180,39 +172,35 @@ void parse_option_size(const char *name, const char *value,
>>      char *postfix;
>>      double sizef;
>>  
>
>> +    sizef = strtod(value, &postfix);
>> +    if (sizef < 0 || sizef > UINT64_MAX) {
>> +        error_setg(errp, QERR_INVALID_PARAMETER_VALUE, name,
>> +                   "a non-negative number below 2^64");
>> +        return;
>> +    }
>> +    switch (*postfix) {
>> +    case 'T':
> ...
>> +    default:
>>          error_setg(errp, QERR_INVALID_PARAMETER_VALUE, name, "a size");
>> +        error_append_hint(errp, "You may use k, M, G or T suffixes for "
>> +                          "kilobytes, megabytes, gigabytes and terabytes.\n");
>> +        return;
>>      }
>
> Unrelated to this patch, but noticing it now: it looks like we blindly
> accept "qemu-system-x86_64 -nodefaults -m 1Mgarbage" as meaning the same
> as "... -m 1M".  Looking back at 1/24, looks like you marked that as one
> of the buggy cases.

Correct.

>                      Good - I guess I'll get to comment more on it in a
> later patch.
>
> Reviewed-by: Eric Blake <eblake@redhat.com>

Thanks!

^ permalink raw reply	[flat|nested] 79+ messages in thread

* Re: [Qemu-devel] [PATCH 04/24] tests/test-cutils: Clean up qemu_strtoul() result checks
  2017-02-14 21:28   ` Eric Blake
@ 2017-02-16 13:07     ` Markus Armbruster
  0 siblings, 0 replies; 79+ messages in thread
From: Markus Armbruster @ 2017-02-16 13:07 UTC (permalink / raw)
  To: Eric Blake; +Cc: qemu-devel

Eric Blake <eblake@redhat.com> writes:

> On 02/14/2017 04:25 AM, Markus Armbruster wrote:
>> Use unsigned comparisons to check the result of qemu_strtoul() and
>> strtoull().
>> 
>> Signed-off-by: Markus Armbruster <armbru@redhat.com>
>> ---
>>  tests/test-cutils.c | 60 ++++++++++++++++++++++++++---------------------------
>>  1 file changed, 30 insertions(+), 30 deletions(-)
>> 
>
> No real difference except when the test fails (better printed result if
> the number being printed exceeds the max signed counterpart value), but
> never hurts to be more precise.

Sadly, my version of glib prints signed all the same.

I'll use g_assert_cmphex() where useful in v2.

> Reviewed-by: Eric Blake <eblake@redhat.com>

Thanks!

^ permalink raw reply	[flat|nested] 79+ messages in thread

* Re: [Qemu-devel] [PATCH 11/24] tests/test-cutils: Cover qemu_strtosz() invalid input
  2017-02-14 22:53   ` Eric Blake
@ 2017-02-16 14:19     ` Markus Armbruster
  0 siblings, 0 replies; 79+ messages in thread
From: Markus Armbruster @ 2017-02-16 14:19 UTC (permalink / raw)
  To: Eric Blake; +Cc: qemu-devel

Eric Blake <eblake@redhat.com> writes:

> On 02/14/2017 04:25 AM, Markus Armbruster wrote:
>> Signed-off-by: Markus Armbruster <armbru@redhat.com>
>> ---
>>  tests/test-cutils.c | 24 ++++++++++++++++++++++++
>>  1 file changed, 24 insertions(+)
>> 
>
> Perhaps you could also add a test of "-".  Either way,

The test cases match the ones for qemu_strtol() & friends:
test_qemu_stro*_{empty,whitespace,invalid}().  If we add "-" here, we
should probably add it there as well.  I think we totally should if we
were testing a strtol() implementation.  But we're only testing a
wrapper, and other test cases cover the "strtol() fails without
converting anything" case, so I think we're okay.

> Reviewed-by: Eric Blake <eblake@redhat.com>

Thanks!

^ permalink raw reply	[flat|nested] 79+ messages in thread

* Re: [Qemu-devel] [PATCH 14/24] util/cutils: New qemu_strtosz_metric()
  2017-02-14 10:26 ` [Qemu-devel] [PATCH 14/24] util/cutils: New qemu_strtosz_metric() Markus Armbruster
@ 2017-02-17 20:44   ` Eric Blake
  2017-02-18 10:08     ` Markus Armbruster
  0 siblings, 1 reply; 79+ messages in thread
From: Eric Blake @ 2017-02-17 20:44 UTC (permalink / raw)
  To: Markus Armbruster, qemu-devel

[-- Attachment #1: Type: text/plain, Size: 1638 bytes --]

On 02/14/2017 04:26 AM, Markus Armbruster wrote:
> To parse numbers with metric suffixes, we use
> 
>     qemu_strtosz_suffix_unit(nptr, &eptr, QEMU_STRTOSZ_DEFSUFFIX_B, 1000)
> 
> Capture this in a new function for legibility:
> 
>     qemu_strtosz_metric(nptr, &eptr)
> 
> Replace test_qemu_strtosz_suffix_unit() by test_qemu_strtosz_metric().
> 
> Rename qemu_strtosz_suffix_unit() to do_strtosz() and give it internal
> linkage.

I don't know if you do this later, but coreutils (via gnulib) has a nice
convention that:

1k   => 1024
1kB  => 1000
1kiB => 1024

where the suffix can be used to express metric or power-of-two, letting
the user choose which scale they want rather than hard-coding the scale.
 But implementing that is beyond this scope of this particular patch.

> 
> Signed-off-by: Markus Armbruster <armbru@redhat.com>
> ---

> @@ -251,7 +251,7 @@ fail:
>  int64_t qemu_strtosz_suffix(const char *nptr, char **end,
>                              const char default_suffix)
>  {
> -    return qemu_strtosz_suffix_unit(nptr, end, default_suffix, 1024);
> +    return do_strtosz(nptr, end, default_suffix, 1024);
>  }
>  
>  int64_t qemu_strtosz(const char *nptr, char **end)
> @@ -259,6 +259,11 @@ int64_t qemu_strtosz(const char *nptr, char **end)
>      return qemu_strtosz_suffix(nptr, end, QEMU_STRTOSZ_DEFSUFFIX_MB);

Do you also want to convert this one to do_strtosz() to avoid
double-forwarding?

Either way,

Reviewed-by: Eric Blake <eblake@redhat.com>

-- 
Eric Blake   eblake redhat com    +1-919-301-3266
Libvirt virtualization library http://libvirt.org


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 604 bytes --]

^ permalink raw reply	[flat|nested] 79+ messages in thread

* Re: [Qemu-devel] [PATCH 15/24] util/cutils: Rename qemu_strtosz() to qemu_strtosz_mebi()
  2017-02-14 10:26 ` [Qemu-devel] [PATCH 15/24] util/cutils: Rename qemu_strtosz() to qemu_strtosz_mebi() Markus Armbruster
  2017-02-14 12:35   ` Paolo Bonzini
@ 2017-02-17 20:45   ` Eric Blake
  1 sibling, 0 replies; 79+ messages in thread
From: Eric Blake @ 2017-02-17 20:45 UTC (permalink / raw)
  To: Markus Armbruster, qemu-devel

[-- Attachment #1: Type: text/plain, Size: 594 bytes --]

On 02/14/2017 04:26 AM, Markus Armbruster wrote:
> With qemu_strtosz(), no suffix means mebibytes.  It's used rarely.
> I'm going to add a similar function where no suffix means bytes.
> Rename qemu_strtosz() to qemu_strtosz_mebi() to make the name
> qemu_strtosz() available for the new function.
> 
> Signed-off-by: Markus Armbruster <armbru@redhat.com>
> ---

With the conversion to Paolo's suggested naming (s/mebi/MiB/),

Reviewed-by: Eric Blake <eblake@redhat.com>

-- 
Eric Blake   eblake redhat com    +1-919-301-3266
Libvirt virtualization library http://libvirt.org


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 604 bytes --]

^ permalink raw reply	[flat|nested] 79+ messages in thread

* Re: [Qemu-devel] [PATCH 16/24] util/cutils: New qemu_strtosz()
  2017-02-14 10:26 ` [Qemu-devel] [PATCH 16/24] util/cutils: New qemu_strtosz() Markus Armbruster
@ 2017-02-17 20:48   ` Eric Blake
  0 siblings, 0 replies; 79+ messages in thread
From: Eric Blake @ 2017-02-17 20:48 UTC (permalink / raw)
  To: Markus Armbruster, qemu-devel

[-- Attachment #1: Type: text/plain, Size: 969 bytes --]

On 02/14/2017 04:26 AM, Markus Armbruster wrote:
> Most callers of qemu_strtosz_suffix() pass QEMU_STRTOSZ_DEFSUFFIX_B.
> Capture the pattern in new qemu_strtosz().
> 
> Inline qemu_strtosz_suffix() into its only remaining caller.
> 
> Signed-off-by: Markus Armbruster <armbru@redhat.com>
> ---

> +++ b/util/cutils.c
> @@ -178,6 +178,14 @@ int fcntl_setfl(int fd, int flag)
>  }
>  #endif
>  
> +#define QEMU_STRTOSZ_DEFSUFFIX_EB 'E'
> +#define QEMU_STRTOSZ_DEFSUFFIX_PB 'P'
> +#define QEMU_STRTOSZ_DEFSUFFIX_TB 'T'
> +#define QEMU_STRTOSZ_DEFSUFFIX_GB 'G'
> +#define QEMU_STRTOSZ_DEFSUFFIX_MB 'M'
> +#define QEMU_STRTOSZ_DEFSUFFIX_KB 'K'
> +#define QEMU_STRTOSZ_DEFSUFFIX_B 'B'

5/7 of these #defines are useless, now that all callers are limited to
file scope.

With that cleaned up,
Reviewed-by: Eric Blake <eblake@redhat.com>

-- 
Eric Blake   eblake redhat com    +1-919-301-3266
Libvirt virtualization library http://libvirt.org


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 604 bytes --]

^ permalink raw reply	[flat|nested] 79+ messages in thread

* Re: [Qemu-devel] [PATCH 17/24] util/cutils: Drop QEMU_STRTOSZ_DEFSUFFIX_* macros
  2017-02-14 10:26 ` [Qemu-devel] [PATCH 17/24] util/cutils: Drop QEMU_STRTOSZ_DEFSUFFIX_* macros Markus Armbruster
@ 2017-02-17 20:51   ` Eric Blake
  2017-02-19  4:21   ` Philippe Mathieu-Daudé
  1 sibling, 0 replies; 79+ messages in thread
From: Eric Blake @ 2017-02-17 20:51 UTC (permalink / raw)
  To: Markus Armbruster, qemu-devel

[-- Attachment #1: Type: text/plain, Size: 1328 bytes --]

On 02/14/2017 04:26 AM, Markus Armbruster wrote:
> Writing QEMU_STRTOSZ_DEFSUFFIX_* instead of '*' gains nothing.  Get
> rid of these eyesores.
> 
> Signed-off-by: Markus Armbruster <armbru@redhat.com>
> ---
>  util/cutils.c | 28 ++++++++++------------------
>  1 file changed, 10 insertions(+), 18 deletions(-)
> 
> diff --git a/util/cutils.c b/util/cutils.c
> index ef658bb..4a290ea 100644
> --- a/util/cutils.c
> +++ b/util/cutils.c
> @@ -178,30 +178,22 @@ int fcntl_setfl(int fd, int flag)
>  }
>  #endif
>  
> -#define QEMU_STRTOSZ_DEFSUFFIX_EB 'E'
> -#define QEMU_STRTOSZ_DEFSUFFIX_PB 'P'
> -#define QEMU_STRTOSZ_DEFSUFFIX_TB 'T'
> -#define QEMU_STRTOSZ_DEFSUFFIX_GB 'G'
> -#define QEMU_STRTOSZ_DEFSUFFIX_MB 'M'
> -#define QEMU_STRTOSZ_DEFSUFFIX_KB 'K'
> -#define QEMU_STRTOSZ_DEFSUFFIX_B 'B'
> -
>  static int64_t suffix_mul(char suffix, int64_t unit)
>  {
>      switch (qemu_toupper(suffix)) {
> -    case QEMU_STRTOSZ_DEFSUFFIX_B:
> +    case 'B':
>          return 1;
> -    case QEMU_STRTOSZ_DEFSUFFIX_KB:

Oh, my comments on 16/24 were a bit premature; those macros were used.
But I'm definitely in favor of this cleanup!

Reviewed-by: Eric Blake <eblake@redhat.com>

-- 
Eric Blake   eblake redhat com    +1-919-301-3266
Libvirt virtualization library http://libvirt.org


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 604 bytes --]

^ permalink raw reply	[flat|nested] 79+ messages in thread

* Re: [Qemu-devel] [PATCH 18/24] tests/test-cutils: Use qemu_strtosz() more often
  2017-02-14 10:26 ` [Qemu-devel] [PATCH 18/24] tests/test-cutils: Use qemu_strtosz() more often Markus Armbruster
@ 2017-02-17 20:55   ` Eric Blake
  0 siblings, 0 replies; 79+ messages in thread
From: Eric Blake @ 2017-02-17 20:55 UTC (permalink / raw)
  To: Markus Armbruster, qemu-devel

[-- Attachment #1: Type: text/plain, Size: 591 bytes --]

On 02/14/2017 04:26 AM, Markus Armbruster wrote:
> Use qemu_strtosz() instead of qemu_strtosz_mebi() where it doesn't
> really make a difference.

Rebase churn to Paolo's naming suggestion on 15/24, but that shouldn't
stop you from adding:

Reviewed-by: Eric Blake <eblake@redhat.com>

> 
> Signed-off-by: Markus Armbruster <armbru@redhat.com>
> ---
>  tests/test-cutils.c | 34 +++++++++++++++++-----------------
>  1 file changed, 17 insertions(+), 17 deletions(-)

-- 
Eric Blake   eblake redhat com    +1-919-301-3266
Libvirt virtualization library http://libvirt.org


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 604 bytes --]

^ permalink raw reply	[flat|nested] 79+ messages in thread

* Re: [Qemu-devel] [PATCH 19/24] tests/test-cutils: Drop suffix from test_qemu_strtosz_simple()
  2017-02-14 10:26 ` [Qemu-devel] [PATCH 19/24] tests/test-cutils: Drop suffix from test_qemu_strtosz_simple() Markus Armbruster
@ 2017-02-17 20:58   ` Eric Blake
  0 siblings, 0 replies; 79+ messages in thread
From: Eric Blake @ 2017-02-17 20:58 UTC (permalink / raw)
  To: Markus Armbruster, qemu-devel

[-- Attachment #1: Type: text/plain, Size: 429 bytes --]

On 02/14/2017 04:26 AM, Markus Armbruster wrote:
> Leave testing unit suffixes to test_qemu_strtosz_units().
> 
> Signed-off-by: Markus Armbruster <armbru@redhat.com>
> ---
>  tests/test-cutils.c | 8 ++++----
>  1 file changed, 4 insertions(+), 4 deletions(-)
> 

Reviewed-by: Eric Blake <eblake@redhat.com>

-- 
Eric Blake   eblake redhat com    +1-919-301-3266
Libvirt virtualization library http://libvirt.org


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 604 bytes --]

^ permalink raw reply	[flat|nested] 79+ messages in thread

* Re: [Qemu-devel] [PATCH 20/24] qemu-img: Wrap cvtnum() around qemu_strtosz()
  2017-02-14 10:26 ` [Qemu-devel] [PATCH 20/24] qemu-img: Wrap cvtnum() around qemu_strtosz() Markus Armbruster
@ 2017-02-17 21:10   ` Eric Blake
  2017-02-18 10:13     ` Markus Armbruster
  0 siblings, 1 reply; 79+ messages in thread
From: Eric Blake @ 2017-02-17 21:10 UTC (permalink / raw)
  To: Markus Armbruster, qemu-devel; +Cc: Kevin Wolf, qemu-block, Max Reitz

[-- Attachment #1: Type: text/plain, Size: 1312 bytes --]

On 02/14/2017 04:26 AM, Markus Armbruster wrote:
> Cc: Kevin Wolf <kwolf@redhat.com>
> Cc: Max Reitz <mreitz@redhat.com>
> Cc: qemu-block@nongnu.org
> Signed-off-by: Markus Armbruster <armbru@redhat.com>
> ---
>  qemu-img.c | 58 +++++++++++++++++++++++++++++++---------------------------
>  1 file changed, 31 insertions(+), 27 deletions(-)


> @@ -3858,11 +3866,9 @@ static int img_dd_count(const char *arg,
>                          struct DdIo *in, struct DdIo *out,
>                          struct DdInfo *dd)
>  {
> -    char *end;
> +    dd->count = cvtnum(arg);

Hmm. cvtnum() accepts "1.5G", GNU dd does not. POSIX requires dd to
accept '1kx10k' to mean 10 mebibytes, and GNU dd accepts '10xM' as a
synonym, but cvtnum() does not accept all those corner cases.  POSIX
requires dd to treat '1b' as '512', while cvdnum() treats it as '1'.  I
sometimes wonder if our 'qemu-img dd' subcommand should be reusing the
numeric parsing that we use everywhere else, in spite of it meaning that
we are different than the POSIX quirks on what numbers are required to
be supported by dd.  But that's not the concern of this patch.

Reviewed-by: Eric Blake <eblake@redhat.com>

-- 
Eric Blake   eblake redhat com    +1-919-301-3266
Libvirt virtualization library http://libvirt.org


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 604 bytes --]

^ permalink raw reply	[flat|nested] 79+ messages in thread

* Re: [Qemu-devel] [PATCH 21/24] util/cutils: Let qemu_strtosz*() optionally reject trailing crap
  2017-02-14 10:26 ` [Qemu-devel] [PATCH 21/24] util/cutils: Let qemu_strtosz*() optionally reject trailing crap Markus Armbruster
@ 2017-02-17 21:21   ` Eric Blake
  2017-02-18 10:22     ` Markus Armbruster
  2017-02-20 19:34   ` Dr. David Alan Gilbert
  1 sibling, 1 reply; 79+ messages in thread
From: Eric Blake @ 2017-02-17 21:21 UTC (permalink / raw)
  To: Markus Armbruster, qemu-devel
  Cc: Kevin Wolf, Max Reitz, Dr . David Alan Gilbert,
	open list:Block layer core, Eduardo Habkost

[-- Attachment #1: Type: text/plain, Size: 2913 bytes --]

On 02/14/2017 04:26 AM, Markus Armbruster wrote:
> Change the qemu_strtosz() & friends to return -EINVAL when @endptr is
> null and the conversion doesn't consume the string completely.
> Matches how qemu_strtol() & friends work.
> 
> Only test_qemu_strtosz_simple() passes a null @endptr.  No functional
> change there, because its conversion consumes the string.
> 
> Simplify callers that use @endptr only to fail when it doesn't point
> to '\0' to pass a null @endptr instead.
> 
> Cc: Dr. David Alan Gilbert <dgilbert@redhat.com>
> Cc: Eduardo Habkost <ehabkost@redhat.com> (maintainer:X86)
> Cc: Kevin Wolf <kwolf@redhat.com> (supporter:Block layer core)
> Cc: Max Reitz <mreitz@redhat.com> (supporter:Block layer core)
> Cc: qemu-block@nongnu.org (open list:Block layer core)
> Signed-off-by: Markus Armbruster <armbru@redhat.com>
> ---
>  hmp.c               |  6 ++----
>  hw/misc/ivshmem.c   |  6 ++----
>  qapi/opts-visitor.c |  5 ++---
>  qemu-img.c          |  7 +------
>  qemu-io-cmds.c      |  7 +------
>  target/i386/cpu.c   |  5 ++---
>  tests/test-cutils.c |  6 ++++++
>  util/cutils.c       | 14 +++++++++-----
>  8 files changed, 25 insertions(+), 31 deletions(-)

Nice cleanup.

Reviewed-by: Eric Blake <eblake@redhat.com>


> +++ b/qemu-img.c
> @@ -370,14 +370,9 @@ static int add_old_style_options(const char *fmt, QemuOpts *opts,
>  
>  static int64_t cvtnum(const char *s)
>  {

> +++ b/qemu-io-cmds.c
> @@ -137,14 +137,9 @@ static char **breakline(char *input, int *count)
>  
>  static int64_t cvtnum(const char *s)
>  {
> -    char *end;

Why do we reimplement cvtnum() as copied static functions instead of
exporting it?  But that would be a separate cleanup (perhaps squashed
into 20/24, where you use cvtnum in qemu-img).

> @@ -217,7 +217,8 @@ static int64_t do_strtosz(const char *nptr, char **end,
>      errno = 0;
>      val = strtod(nptr, &endptr);
>      if (isnan(val) || endptr == nptr || errno != 0) {

Hmm - we explicitly reject "NaN", but not "infinity".  But when strtod()
accepts infinity, ...

> -        goto fail;
> +        retval = -EINVAL;
> +        goto out;
>      }
>      fraction = modf(val, &integral);

then modf() returns 0 with integral left at infinity...

>      if (fraction != 0) {
> @@ -232,17 +233,20 @@ static int64_t do_strtosz(const char *nptr, char **end,
>          assert(mul >= 0);
>      }
>      if (mul == 1 && mul_required) {
> -        goto fail;
> +        retval = -EINVAL;
> +        goto out;
>      }
>      if ((val * mul >= INT64_MAX) || val < 0) {

...and the multiply exceeds INT64_MAX, so we still end up rejecting it
(with ERANGE instead of EINVAL).  Weird way but seems to work, and is
pre-existing, so not this patch's problem.

-- 
Eric Blake   eblake redhat com    +1-919-301-3266
Libvirt virtualization library http://libvirt.org


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 604 bytes --]

^ permalink raw reply	[flat|nested] 79+ messages in thread

* Re: [Qemu-devel] [PATCH 22/24] util/cutils: Return qemu_strtosz*() error and value separately
  2017-02-14 10:26 ` [Qemu-devel] [PATCH 22/24] util/cutils: Return qemu_strtosz*() error and value separately Markus Armbruster
@ 2017-02-17 22:03   ` Eric Blake
  2017-02-18 10:33     ` Markus Armbruster
  2017-02-20 19:52   ` Dr. David Alan Gilbert
  1 sibling, 1 reply; 79+ messages in thread
From: Eric Blake @ 2017-02-17 22:03 UTC (permalink / raw)
  To: Markus Armbruster, qemu-devel
  Cc: Kevin Wolf, Max Reitz, Dr . David Alan Gilbert,
	open list:Block layer core, Eduardo Habkost

[-- Attachment #1: Type: text/plain, Size: 2006 bytes --]

On 02/14/2017 04:26 AM, Markus Armbruster wrote:
> This makes qemu_strtosz(), qemu_strtosz_mebi() and
> qemu_strtosz_metric() similar to qemu_strtoi64(), except negative
> values are rejected.

Yay. It also opens the door to allowing them to return an unsigned 64
bit value ;)

> 
> Cc: Dr. David Alan Gilbert <dgilbert@redhat.com>
> Cc: Eduardo Habkost <ehabkost@redhat.com> (maintainer:X86)
> Cc: Kevin Wolf <kwolf@redhat.com> (supporter:Block layer core)
> Cc: Max Reitz <mreitz@redhat.com> (supporter:Block layer core)
> Cc: qemu-block@nongnu.org (open list:Block layer core)
> Signed-off-by: Markus Armbruster <armbru@redhat.com>
> ---
> @@ -1378,8 +1378,8 @@ void hmp_migrate_set_parameter(Monitor *mon, const QDict *qdict)
>                  break;
>              case MIGRATION_PARAMETER_MAX_BANDWIDTH:
>                  p.has_max_bandwidth = true;
> -                valuebw = qemu_strtosz_mebi(valuestr, NULL);
> -                if (valuebw < 0 || (size_t)valuebw != valuebw) {
> +                ret = qemu_strtosz_mebi(valuestr, NULL, &valuebw);
> +                if (ret < 0 || (size_t)valuebw != valuebw) {

Question: do we want a wrapper that takes a maximum, as in:

ret = qemu_strtosz_capped(valuestr, NULL, 'M', SIZE_MAX, &valuebw);

so that the caller doesn't have to check (size_t)valuebw != valuebw ?

But not essential, so I can live with what you did here.


> +++ b/qemu-img.c
> @@ -370,10 +370,14 @@ static int add_old_style_options(const char *fmt, QemuOpts *opts,
>  
>  static int64_t cvtnum(const char *s)

> +++ b/qemu-io-cmds.c
> @@ -137,10 +137,14 @@ static char **breakline(char *input, int *count)
>  
>  static int64_t cvtnum(const char *s)

May be some fallout based on rebase churn from earlier patch reviews,
but nothing too serious to prevent you from adding:

Reviewed-by: Eric Blake <eblake@redhat.com>

-- 
Eric Blake   eblake redhat com    +1-919-301-3266
Libvirt virtualization library http://libvirt.org


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 604 bytes --]

^ permalink raw reply	[flat|nested] 79+ messages in thread

* Re: [Qemu-devel] [PATCH 23/24] util/cutils: Change qemu_strtosz*() from int64_t to uint64_t
  2017-02-14 10:26 ` [Qemu-devel] [PATCH 23/24] util/cutils: Change qemu_strtosz*() from int64_t to uint64_t Markus Armbruster
@ 2017-02-17 22:19   ` Eric Blake
  2017-02-18 10:40     ` Markus Armbruster
  2017-02-20 20:16   ` Dr. David Alan Gilbert
  1 sibling, 1 reply; 79+ messages in thread
From: Eric Blake @ 2017-02-17 22:19 UTC (permalink / raw)
  To: Markus Armbruster, qemu-devel
  Cc: Kevin Wolf, Max Reitz, Dr . David Alan Gilbert,
	open list:Block layer core, Eduardo Habkost

[-- Attachment #1: Type: text/plain, Size: 3604 bytes --]

On 02/14/2017 04:26 AM, Markus Armbruster wrote:
> This will permit its use in parse_option_size().

Progress!  (not that it matters - off_t is a signed value, so you are
STILL limited to 2^63, not 2^64, as the maximum theoretical size storage
that you can target - and it's not like we have that much storage even
accessible)

> 
> Cc: Dr. David Alan Gilbert <dgilbert@redhat.com>
> Cc: Eduardo Habkost <ehabkost@redhat.com> (maintainer:X86)
> Cc: Kevin Wolf <kwolf@redhat.com> (supporter:Block layer core)
> Cc: Max Reitz <mreitz@redhat.com> (supporter:Block layer core)
> Cc: qemu-block@nongnu.org (open list:Block layer core)
> Signed-off-by: Markus Armbruster <armbru@redhat.com>
> ---

> +++ b/hmp.c
> @@ -1338,7 +1338,7 @@ void hmp_migrate_set_parameter(Monitor *mon, const QDict *qdict)
>  {
>      const char *param = qdict_get_str(qdict, "parameter");
>      const char *valuestr = qdict_get_str(qdict, "value");
> -    int64_t valuebw = 0;
> +    uint64_t valuebw = 0;
>      long valueint = 0;
>      Error *err = NULL;
>      bool use_int_value = false;
> @@ -1379,7 +1379,8 @@ void hmp_migrate_set_parameter(Monitor *mon, const QDict *qdict)
>              case MIGRATION_PARAMETER_MAX_BANDWIDTH:
>                  p.has_max_bandwidth = true;
>                  ret = qemu_strtosz_mebi(valuestr, NULL, &valuebw);
> -                if (ret < 0 || (size_t)valuebw != valuebw) {
> +                if (ret < 0 || valuebw > INT64_MAX
> +                    || (size_t)valuebw != valuebw) {

I don't know if this looks any better as:

if (ret < 0 || valuebw > MIN(INT64_MAX, SIZE_MAX))

so don't bother changing it if you think that's ugly.

> +++ b/qapi/opts-visitor.c
> @@ -481,7 +481,6 @@ opts_type_size(Visitor *v, const char *name, uint64_t *obj, Error **errp)
>  {
>      OptsVisitor *ov = to_ov(v);
>      const QemuOpt *opt;
> -    int64_t val;
>      int err;
>  
>      opt = lookup_scalar(ov, name, errp);
> @@ -489,14 +488,13 @@ opts_type_size(Visitor *v, const char *name, uint64_t *obj, Error **errp)
>          return;
>      }
>  
> -    err = qemu_strtosz(opt->str ? opt->str : "", NULL, &val);
> +    err = qemu_strtosz(opt->str ? opt->str : "", NULL, obj);
>      if (err < 0) {
>          error_setg(errp, QERR_INVALID_PARAMETER_VALUE, opt->name,
> -                   "a size value representible as a non-negative int64");

Nice - you're killing the unusual variant spelling of representable.

> +++ b/util/cutils.c
> @@ -207,7 +207,7 @@ static int64_t suffix_mul(char suffix, int64_t unit)
>   */
>  static int do_strtosz(const char *nptr, char **end,
>                        const char default_suffix, int64_t unit,
> -                      int64_t *result)
> +                      uint64_t *result)
>  {
>      int retval;
>      char *endptr;
> @@ -237,7 +237,11 @@ static int do_strtosz(const char *nptr, char **end,
>          retval = -EINVAL;
>          goto out;
>      }
> -    if ((val * mul >= INT64_MAX) || val < 0) {
> +    /*
> +     * Values >= 0xfffffffffffffc00 overflow uint64_t after their trip
> +     * through double (53 bits of precision).
> +     */
> +    if ((val * mul >= 0xfffffffffffffc00) || val < 0) {

I guess there's not any simpler expression using INT64_MAX and
operations (including casts to double and int64_t) that would reliably
produce the same constant that you just open-coded here.

Reviewed-by: Eric Blake <eblake@redhat.com>

-- 
Eric Blake   eblake redhat com    +1-919-301-3266
Libvirt virtualization library http://libvirt.org


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 604 bytes --]

^ permalink raw reply	[flat|nested] 79+ messages in thread

* Re: [Qemu-devel] [PATCH 24/24] QemuOpts: Fix checking of sizes for overflow and trailing crap
  2017-02-14 10:26 ` [Qemu-devel] [PATCH 24/24] QemuOpts: Fix checking of sizes for overflow and trailing crap Markus Armbruster
@ 2017-02-17 22:27   ` Eric Blake
  2017-02-18 10:46     ` Markus Armbruster
  0 siblings, 1 reply; 79+ messages in thread
From: Eric Blake @ 2017-02-17 22:27 UTC (permalink / raw)
  To: Markus Armbruster, qemu-devel

[-- Attachment #1: Type: text/plain, Size: 1281 bytes --]

On 02/14/2017 04:26 AM, Markus Armbruster wrote:
> parse_option_size()'s checking for overflow and trailing crap is
> wrong.  Has always been that way.  qemu_strtosz() gets it right, so
> use that.
> 
> This adds support for size suffixes 'P', 'E', and ignores case for all
> suffixes, not just 'k'.

Yay! Be liberal in what you accept!  (I've always been annoyed that '-m
1g' complains, forcing me to us '-m 1G').

Okay, we're at the end of the series, and I've pointed out other
possible improvements.  As mentioned elsewhere, it might be nice to add
a 25/24 to match coreutils, which allows 'm' and 'mib' to mean
1024*1024, vs. 'mb' to mean 1000*1000.  Right now, all clients of
qemu_strtosz() are stuck to one scale, vs. letting the user choose a
scale by their choice of suffix.  But it does not hold up this series if
you don't like the idea.

> 
> Signed-off-by: Markus Armbruster <armbru@redhat.com>
> ---
>  tests/test-qemu-opts.c | 21 +++++++++------------
>  util/qemu-option.c     | 41 +++++++++++++----------------------------
>  2 files changed, 22 insertions(+), 40 deletions(-)
> 

Reviewed-by: Eric Blake <eblake@redhat.com>

-- 
Eric Blake   eblake redhat com    +1-919-301-3266
Libvirt virtualization library http://libvirt.org


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 604 bytes --]

^ permalink raw reply	[flat|nested] 79+ messages in thread

* Re: [Qemu-devel] [PATCH 14/24] util/cutils: New qemu_strtosz_metric()
  2017-02-17 20:44   ` Eric Blake
@ 2017-02-18 10:08     ` Markus Armbruster
  0 siblings, 0 replies; 79+ messages in thread
From: Markus Armbruster @ 2017-02-18 10:08 UTC (permalink / raw)
  To: Eric Blake; +Cc: qemu-devel

Eric Blake <eblake@redhat.com> writes:

> On 02/14/2017 04:26 AM, Markus Armbruster wrote:
>> To parse numbers with metric suffixes, we use
>> 
>>     qemu_strtosz_suffix_unit(nptr, &eptr, QEMU_STRTOSZ_DEFSUFFIX_B, 1000)
>> 
>> Capture this in a new function for legibility:
>> 
>>     qemu_strtosz_metric(nptr, &eptr)
>> 
>> Replace test_qemu_strtosz_suffix_unit() by test_qemu_strtosz_metric().
>> 
>> Rename qemu_strtosz_suffix_unit() to do_strtosz() and give it internal
>> linkage.
>
> I don't know if you do this later, but coreutils (via gnulib) has a nice
> convention that:
>
> 1k   => 1024
> 1kB  => 1000
> 1kiB => 1024
>
> where the suffix can be used to express metric or power-of-two, letting
> the user choose which scale they want rather than hard-coding the scale.

Could be done for the calls that currently pass 1024, because the
existing one-character suffixes keep their meaning there.  Would be an
incompatible change for the calls that pass 1000.  There's just one
outside of tests, and it's a frequency value, i.e. 'k' makes sense, but
'kB' and 'kiB' do not.

>  But implementing that is beyond this scope of this particular patch.

Indeed.

>> Signed-off-by: Markus Armbruster <armbru@redhat.com>
>> ---
>
>> @@ -251,7 +251,7 @@ fail:
>>  int64_t qemu_strtosz_suffix(const char *nptr, char **end,
>>                              const char default_suffix)
>>  {
>> -    return qemu_strtosz_suffix_unit(nptr, end, default_suffix, 1024);
>> +    return do_strtosz(nptr, end, default_suffix, 1024);
>>  }
>>  
>>  int64_t qemu_strtosz(const char *nptr, char **end)
>> @@ -259,6 +259,11 @@ int64_t qemu_strtosz(const char *nptr, char **end)
>>      return qemu_strtosz_suffix(nptr, end, QEMU_STRTOSZ_DEFSUFFIX_MB);
>
> Do you also want to convert this one to do_strtosz() to avoid
> double-forwarding?

See next patch :)

> Either way,
>
> Reviewed-by: Eric Blake <eblake@redhat.com>

Thanks!

^ permalink raw reply	[flat|nested] 79+ messages in thread

* Re: [Qemu-devel] [PATCH 20/24] qemu-img: Wrap cvtnum() around qemu_strtosz()
  2017-02-17 21:10   ` Eric Blake
@ 2017-02-18 10:13     ` Markus Armbruster
  0 siblings, 0 replies; 79+ messages in thread
From: Markus Armbruster @ 2017-02-18 10:13 UTC (permalink / raw)
  To: Eric Blake; +Cc: qemu-devel, Kevin Wolf, qemu-block, Max Reitz

Eric Blake <eblake@redhat.com> writes:

> On 02/14/2017 04:26 AM, Markus Armbruster wrote:
>> Cc: Kevin Wolf <kwolf@redhat.com>
>> Cc: Max Reitz <mreitz@redhat.com>
>> Cc: qemu-block@nongnu.org
>> Signed-off-by: Markus Armbruster <armbru@redhat.com>
>> ---
>>  qemu-img.c | 58 +++++++++++++++++++++++++++++++---------------------------
>>  1 file changed, 31 insertions(+), 27 deletions(-)
>
>
>> @@ -3858,11 +3866,9 @@ static int img_dd_count(const char *arg,
>>                          struct DdIo *in, struct DdIo *out,
>>                          struct DdInfo *dd)
>>  {
>> -    char *end;
>> +    dd->count = cvtnum(arg);
>
> Hmm. cvtnum() accepts "1.5G", GNU dd does not. POSIX requires dd to
> accept '1kx10k' to mean 10 mebibytes, and GNU dd accepts '10xM' as a
> synonym, but cvtnum() does not accept all those corner cases.  POSIX
> requires dd to treat '1b' as '512', while cvdnum() treats it as '1'.  I
> sometimes wonder if our 'qemu-img dd' subcommand should be reusing the
> numeric parsing that we use everywhere else, in spite of it meaning that
> we are different than the POSIX quirks on what numbers are required to
> be supported by dd.

qemu-img dd falls short of its stated goal to be like /usr/bin/dd.
Whether that's good or bad I decline to judge ;)

>                      But that's not the concern of this patch.

Yes.

> Reviewed-by: Eric Blake <eblake@redhat.com>

Thanks!

^ permalink raw reply	[flat|nested] 79+ messages in thread

* Re: [Qemu-devel] [PATCH 21/24] util/cutils: Let qemu_strtosz*() optionally reject trailing crap
  2017-02-17 21:21   ` Eric Blake
@ 2017-02-18 10:22     ` Markus Armbruster
  0 siblings, 0 replies; 79+ messages in thread
From: Markus Armbruster @ 2017-02-18 10:22 UTC (permalink / raw)
  To: Eric Blake
  Cc: qemu-devel, Kevin Wolf, Eduardo Habkost, Dr . David Alan Gilbert,
	open list:Block layer core, Max Reitz

Eric Blake <eblake@redhat.com> writes:

> On 02/14/2017 04:26 AM, Markus Armbruster wrote:
>> Change the qemu_strtosz() & friends to return -EINVAL when @endptr is
>> null and the conversion doesn't consume the string completely.
>> Matches how qemu_strtol() & friends work.
>> 
>> Only test_qemu_strtosz_simple() passes a null @endptr.  No functional
>> change there, because its conversion consumes the string.
>> 
>> Simplify callers that use @endptr only to fail when it doesn't point
>> to '\0' to pass a null @endptr instead.
>> 
>> Cc: Dr. David Alan Gilbert <dgilbert@redhat.com>
>> Cc: Eduardo Habkost <ehabkost@redhat.com> (maintainer:X86)
>> Cc: Kevin Wolf <kwolf@redhat.com> (supporter:Block layer core)
>> Cc: Max Reitz <mreitz@redhat.com> (supporter:Block layer core)
>> Cc: qemu-block@nongnu.org (open list:Block layer core)
>> Signed-off-by: Markus Armbruster <armbru@redhat.com>
>> ---
>>  hmp.c               |  6 ++----
>>  hw/misc/ivshmem.c   |  6 ++----
>>  qapi/opts-visitor.c |  5 ++---
>>  qemu-img.c          |  7 +------
>>  qemu-io-cmds.c      |  7 +------
>>  target/i386/cpu.c   |  5 ++---
>>  tests/test-cutils.c |  6 ++++++
>>  util/cutils.c       | 14 +++++++++-----
>>  8 files changed, 25 insertions(+), 31 deletions(-)
>
> Nice cleanup.
>
> Reviewed-by: Eric Blake <eblake@redhat.com>
>
>
>> +++ b/qemu-img.c
>> @@ -370,14 +370,9 @@ static int add_old_style_options(const char *fmt, QemuOpts *opts,
>>  
>>  static int64_t cvtnum(const char *s)
>>  {
>
>> +++ b/qemu-io-cmds.c
>> @@ -137,14 +137,9 @@ static char **breakline(char *input, int *count)
>>  
>>  static int64_t cvtnum(const char *s)
>>  {
>> -    char *end;
>
> Why do we reimplement cvtnum() as copied static functions instead of
> exporting it?  But that would be a separate cleanup (perhaps squashed
> into 20/24, where you use cvtnum in qemu-img).

At the end of this series, the two cvtnum() look like this:

    static int64_t cvtnum(const char *s)
    {
        int err;
        uint64_t value;

        err = qemu_strtosz(s, NULL, &value);
        if (err < 0) {
            return err;
        }
        if (value > INT64_MAX) {
            return -ERANGE;
        }
        return value;
    }

Does two things: limit value range to 0..INT64_MAX, merge error into
value.

Perhaps their callers should simply use qemu_strtosz() directly.  I
chose not to go there to limit churn in this series.

>> @@ -217,7 +217,8 @@ static int64_t do_strtosz(const char *nptr, char **end,
>>      errno = 0;
>>      val = strtod(nptr, &endptr);
>>      if (isnan(val) || endptr == nptr || errno != 0) {
>
> Hmm - we explicitly reject "NaN", but not "infinity".  But when strtod()
> accepts infinity, ...
>
>> -        goto fail;
>> +        retval = -EINVAL;
>> +        goto out;
>>      }
>>      fraction = modf(val, &integral);
>
> then modf() returns 0 with integral left at infinity...
>
>>      if (fraction != 0) {
>> @@ -232,17 +233,20 @@ static int64_t do_strtosz(const char *nptr, char **end,
>>          assert(mul >= 0);
>>      }
>>      if (mul == 1 && mul_required) {
>> -        goto fail;
>> +        retval = -EINVAL;
>> +        goto out;
>>      }
>>      if ((val * mul >= INT64_MAX) || val < 0) {
>
> ...and the multiply exceeds INT64_MAX, so we still end up rejecting it
> (with ERANGE instead of EINVAL).  Weird way but seems to work, and is
> pre-existing, so not this patch's problem.

Yes.

We could easily check !isfinite() rather than isnan(), but then we'd get
-EINVAL rather than -ERANGE for infinities.  Matter of taste, I guess.

^ permalink raw reply	[flat|nested] 79+ messages in thread

* Re: [Qemu-devel] [PATCH 22/24] util/cutils: Return qemu_strtosz*() error and value separately
  2017-02-17 22:03   ` Eric Blake
@ 2017-02-18 10:33     ` Markus Armbruster
  0 siblings, 0 replies; 79+ messages in thread
From: Markus Armbruster @ 2017-02-18 10:33 UTC (permalink / raw)
  To: Eric Blake
  Cc: qemu-devel, Kevin Wolf, Eduardo Habkost, Dr . David Alan Gilbert,
	open list:Block layer core, Max Reitz

Eric Blake <eblake@redhat.com> writes:

> On 02/14/2017 04:26 AM, Markus Armbruster wrote:
>> This makes qemu_strtosz(), qemu_strtosz_mebi() and
>> qemu_strtosz_metric() similar to qemu_strtoi64(), except negative
>> values are rejected.
>
> Yay. It also opens the door to allowing them to return an unsigned 64
> bit value ;)
>
>> 
>> Cc: Dr. David Alan Gilbert <dgilbert@redhat.com>
>> Cc: Eduardo Habkost <ehabkost@redhat.com> (maintainer:X86)
>> Cc: Kevin Wolf <kwolf@redhat.com> (supporter:Block layer core)
>> Cc: Max Reitz <mreitz@redhat.com> (supporter:Block layer core)
>> Cc: qemu-block@nongnu.org (open list:Block layer core)
>> Signed-off-by: Markus Armbruster <armbru@redhat.com>
>> ---
>> @@ -1378,8 +1378,8 @@ void hmp_migrate_set_parameter(Monitor *mon, const QDict *qdict)
>>                  break;
>>              case MIGRATION_PARAMETER_MAX_BANDWIDTH:
>>                  p.has_max_bandwidth = true;
>> -                valuebw = qemu_strtosz_mebi(valuestr, NULL);
>> -                if (valuebw < 0 || (size_t)valuebw != valuebw) {
>> +                ret = qemu_strtosz_mebi(valuestr, NULL, &valuebw);
>> +                if (ret < 0 || (size_t)valuebw != valuebw) {
>
> Question: do we want a wrapper that takes a maximum, as in:
>
> ret = qemu_strtosz_capped(valuestr, NULL, 'M', SIZE_MAX, &valuebw);
>
> so that the caller doesn't have to check (size_t)valuebw != valuebw ?

Maybe.

It's a more interesting question for qemu_strtou64(), actually.  The
obvious

    err = qemu_strtou64(str, NULL, 0, &value);
    if (value > limit) {
        err = -ERANGE;
    }

is subtly weird.  With str = "-1", you get value = UINT64_MAX.  With str
= "-18446744073709551615", you get value = 1.  Rejecting the former but
accepting the latter is weird.

> But not essential, so I can live with what you did here.
>
>
>> +++ b/qemu-img.c
>> @@ -370,10 +370,14 @@ static int add_old_style_options(const char *fmt, QemuOpts *opts,
>>  
>>  static int64_t cvtnum(const char *s)
>
>> +++ b/qemu-io-cmds.c
>> @@ -137,10 +137,14 @@ static char **breakline(char *input, int *count)
>>  
>>  static int64_t cvtnum(const char *s)
>
> May be some fallout based on rebase churn from earlier patch reviews,
> but nothing too serious to prevent you from adding:
>
> Reviewed-by: Eric Blake <eblake@redhat.com>

Thanks!

^ permalink raw reply	[flat|nested] 79+ messages in thread

* Re: [Qemu-devel] [PATCH 23/24] util/cutils: Change qemu_strtosz*() from int64_t to uint64_t
  2017-02-17 22:19   ` Eric Blake
@ 2017-02-18 10:40     ` Markus Armbruster
  0 siblings, 0 replies; 79+ messages in thread
From: Markus Armbruster @ 2017-02-18 10:40 UTC (permalink / raw)
  To: Eric Blake
  Cc: qemu-devel, Kevin Wolf, Eduardo Habkost, Dr . David Alan Gilbert,
	open list:Block layer core, Max Reitz

Eric Blake <eblake@redhat.com> writes:

> On 02/14/2017 04:26 AM, Markus Armbruster wrote:
>> This will permit its use in parse_option_size().
>
> Progress!  (not that it matters - off_t is a signed value, so you are
> STILL limited to 2^63, not 2^64, as the maximum theoretical size storage
> that you can target - and it's not like we have that much storage even
> accessible)
>
>> 
>> Cc: Dr. David Alan Gilbert <dgilbert@redhat.com>
>> Cc: Eduardo Habkost <ehabkost@redhat.com> (maintainer:X86)
>> Cc: Kevin Wolf <kwolf@redhat.com> (supporter:Block layer core)
>> Cc: Max Reitz <mreitz@redhat.com> (supporter:Block layer core)
>> Cc: qemu-block@nongnu.org (open list:Block layer core)
>> Signed-off-by: Markus Armbruster <armbru@redhat.com>
>> ---
>
>> +++ b/hmp.c
>> @@ -1338,7 +1338,7 @@ void hmp_migrate_set_parameter(Monitor *mon, const QDict *qdict)
>>  {
>>      const char *param = qdict_get_str(qdict, "parameter");
>>      const char *valuestr = qdict_get_str(qdict, "value");
>> -    int64_t valuebw = 0;
>> +    uint64_t valuebw = 0;
>>      long valueint = 0;
>>      Error *err = NULL;
>>      bool use_int_value = false;
>> @@ -1379,7 +1379,8 @@ void hmp_migrate_set_parameter(Monitor *mon, const QDict *qdict)
>>              case MIGRATION_PARAMETER_MAX_BANDWIDTH:
>>                  p.has_max_bandwidth = true;
>>                  ret = qemu_strtosz_mebi(valuestr, NULL, &valuebw);
>> -                if (ret < 0 || (size_t)valuebw != valuebw) {
>> +                if (ret < 0 || valuebw > INT64_MAX
>> +                    || (size_t)valuebw != valuebw) {
>
> I don't know if this looks any better as:
>
> if (ret < 0 || valuebw > MIN(INT64_MAX, SIZE_MAX))
>
> so don't bother changing it if you think that's ugly.

I think (size_t)valuebw != valuebw neatly expresses "valuebw not
representable as size_t".  Requires unsigned, though.

>> +++ b/qapi/opts-visitor.c
>> @@ -481,7 +481,6 @@ opts_type_size(Visitor *v, const char *name, uint64_t *obj, Error **errp)
>>  {
>>      OptsVisitor *ov = to_ov(v);
>>      const QemuOpt *opt;
>> -    int64_t val;
>>      int err;
>>  
>>      opt = lookup_scalar(ov, name, errp);
>> @@ -489,14 +488,13 @@ opts_type_size(Visitor *v, const char *name, uint64_t *obj, Error **errp)
>>          return;
>>      }
>>  
>> -    err = qemu_strtosz(opt->str ? opt->str : "", NULL, &val);
>> +    err = qemu_strtosz(opt->str ? opt->str : "", NULL, obj);
>>      if (err < 0) {
>>          error_setg(errp, QERR_INVALID_PARAMETER_VALUE, opt->name,
>> -                   "a size value representible as a non-negative int64");
>
> Nice - you're killing the unusual variant spelling of representable.
>
>> +++ b/util/cutils.c
>> @@ -207,7 +207,7 @@ static int64_t suffix_mul(char suffix, int64_t unit)
>>   */
>>  static int do_strtosz(const char *nptr, char **end,
>>                        const char default_suffix, int64_t unit,
>> -                      int64_t *result)
>> +                      uint64_t *result)
>>  {
>>      int retval;
>>      char *endptr;
>> @@ -237,7 +237,11 @@ static int do_strtosz(const char *nptr, char **end,
>>          retval = -EINVAL;
>>          goto out;
>>      }
>> -    if ((val * mul >= INT64_MAX) || val < 0) {
>> +    /*
>> +     * Values >= 0xfffffffffffffc00 overflow uint64_t after their trip
>> +     * through double (53 bits of precision).
>> +     */
>> +    if ((val * mul >= 0xfffffffffffffc00) || val < 0) {
>
> I guess there's not any simpler expression using INT64_MAX and
> operations (including casts to double and int64_t) that would reliably
> produce the same constant that you just open-coded here.

I think the literal plus the comment explaining it is easier to read.

> Reviewed-by: Eric Blake <eblake@redhat.com>

Thanks!

^ permalink raw reply	[flat|nested] 79+ messages in thread

* Re: [Qemu-devel] [PATCH 24/24] QemuOpts: Fix checking of sizes for overflow and trailing crap
  2017-02-17 22:27   ` Eric Blake
@ 2017-02-18 10:46     ` Markus Armbruster
  0 siblings, 0 replies; 79+ messages in thread
From: Markus Armbruster @ 2017-02-18 10:46 UTC (permalink / raw)
  To: Eric Blake; +Cc: qemu-devel

Eric Blake <eblake@redhat.com> writes:

> On 02/14/2017 04:26 AM, Markus Armbruster wrote:
>> parse_option_size()'s checking for overflow and trailing crap is
>> wrong.  Has always been that way.  qemu_strtosz() gets it right, so
>> use that.
>> 
>> This adds support for size suffixes 'P', 'E', and ignores case for all
>> suffixes, not just 'k'.
>
> Yay! Be liberal in what you accept!  (I've always been annoyed that '-m
> 1g' complains, forcing me to us '-m 1G').

The liberality is okay when we measure bytes, because 'm' can only mean
"mega" there.  It's problematic when we measure things like seconds,
where 'm' definitely should mean "milli".

Perhaps I should make do_strtosz() case-insensitive only when unit ==
1024, but not when unit == 1000.

> Okay, we're at the end of the series, and I've pointed out other
> possible improvements.  As mentioned elsewhere, it might be nice to add
> a 25/24 to match coreutils, which allows 'm' and 'mib' to mean
> 1024*1024, vs. 'mb' to mean 1000*1000.  Right now, all clients of
> qemu_strtosz() are stuck to one scale, vs. letting the user choose a
> scale by their choice of suffix.  But it does not hold up this series if
> you don't like the idea.

I'd prefer not to do that now, because I'm busy on getting -blockdev
done before the soft freeze.

>> Signed-off-by: Markus Armbruster <armbru@redhat.com>
>> ---
>>  tests/test-qemu-opts.c | 21 +++++++++------------
>>  util/qemu-option.c     | 41 +++++++++++++----------------------------
>>  2 files changed, 22 insertions(+), 40 deletions(-)
>> 
>
> Reviewed-by: Eric Blake <eblake@redhat.com>

Thanks!

^ permalink raw reply	[flat|nested] 79+ messages in thread

* Re: [Qemu-devel] [PATCH 05/24] util/cutils: Rewrite documentation of qemu_strtol() & friends
  2017-02-14 10:25 ` [Qemu-devel] [PATCH 05/24] util/cutils: Rewrite documentation of qemu_strtol() & friends Markus Armbruster
  2017-02-14 21:32   ` Eric Blake
@ 2017-02-19  4:12   ` Philippe Mathieu-Daudé
  1 sibling, 0 replies; 79+ messages in thread
From: Philippe Mathieu-Daudé @ 2017-02-19  4:12 UTC (permalink / raw)
  To: Markus Armbruster, qemu-devel

On 02/14/2017 07:25 AM, Markus Armbruster wrote:
> Fixes the following documentation bugs:
>
> * Fails to document that null @nptr is safe.
>
> * Fails to document that we return -EINVAL when no conversion could be
>   performed (commit 47d4be1).
>
> * Confuses long long with int64_t, and unsigned long long with
>   uint64_t.
>
> * Claims the unsigned conversions can underflow.  They can't.
>
> While there, mark problematic assumptions that int64_t is long long,
> and uint64_t is unsigned long long with FIXME comments.
>
> Signed-off-by: Markus Armbruster <armbru@redhat.com>

Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>

> ---
>  util/cutils.c | 80 +++++++++++++++++++++++++++++++++--------------------------
>  1 file changed, 45 insertions(+), 35 deletions(-)
>
> diff --git a/util/cutils.c b/util/cutils.c
> index 4fefcf3..1ae2a08 100644
> --- a/util/cutils.c
> +++ b/util/cutils.c
> @@ -265,9 +265,6 @@ int64_t qemu_strtosz(const char *nptr, char **end)
>  static int check_strtox_error(const char *p, char *endptr, const char **next,
>                                int err)
>  {
> -    /* If no conversion was performed, prefer BSD behavior over glibc
> -     * behavior.
> -     */
>      if (err == 0 && endptr == p) {
>          err = EINVAL;
>      }
> @@ -281,30 +278,28 @@ static int check_strtox_error(const char *p, char *endptr, const char **next,
>  }
>
>  /**
> - * QEMU wrappers for strtol(), strtoll(), strtoul(), strotull() C functions.
> + * Convert string @nptr to a long integer, and store it in @result.
>   *
> - * Convert ASCII string @nptr to a long integer value
> - * from the given @base. Parameters @nptr, @endptr, @base
> - * follows same semantics as strtol() C function.
> + * This is a wrapper around strtol() that is harder to misuse.
> + * Semantics of @nptr, @endptr, @base match strtol() with differences
> + * noted below.
>   *
> - * Unlike from strtol() function, if @endptr is not NULL, this
> - * function will return -EINVAL whenever it cannot fully convert
> - * the string in @nptr with given @base to a long. This function returns
> - * the result of the conversion only through the @result parameter.
> + * @nptr may be null, and no conversion is performed then.
>   *
> - * If NULL is passed in @endptr, then the whole string in @ntpr
> - * is a number otherwise it returns -EINVAL.
> + * If no conversion is performed, store @nptr in *@endptr and return
> + * -EINVAL.
>   *
> - * RETURN VALUE
> - * Unlike from strtol() function, this wrapper returns either
> - * -EINVAL or the errno set by strtol() function (e.g -ERANGE).
> - * If the conversion overflows, -ERANGE is returned, and @result
> - * is set to the max value of the desired type
> - * (e.g. LONG_MAX, LLONG_MAX, ULONG_MAX, ULLONG_MAX). If the case
> - * of underflow, -ERANGE is returned, and @result is set to the min
> - * value of the desired type. For strtol(), strtoll(), @result is set to
> - * LONG_MIN, LLONG_MIN, respectively, and for strtoul(), strtoull() it
> - * is set to 0.
> + * If @endptr is null, and the string isn't fully converted, return
> + * -EINVAL.  This is the case when the pointer that would be stored in
> + * a non-null @endptr points to a character other than '\0'.
> + *
> + * If the conversion overflows @result, store LONG_MAX in @result,
> + * and return -ERANGE.
> + *
> + * If the conversion underflows @result, store LONG_MIN in @result,
> + * and return -ERANGE.
> + *
> + * Else store the converted value in @result, and return zero.
>   */
>  int qemu_strtol(const char *nptr, const char **endptr, int base,
>                  long *result)
> @@ -325,17 +320,29 @@ int qemu_strtol(const char *nptr, const char **endptr, int base,
>  }
>
>  /**
> - * Converts ASCII string to an unsigned long integer.
> + * Convert string @nptr to an unsigned long, and store it in @result.
>   *
> - * If string contains a negative number, value will be converted to
> - * the unsigned representation of the signed value, unless the original
> - * (nonnegated) value would overflow, in this case, it will set @result
> - * to ULONG_MAX, and return ERANGE.
> + * This is a wrapper around strtoul() that is harder to misuse.
> + * Semantics of @nptr, @endptr, @base match strtoul() with differences
> + * noted below.
>   *
> - * The same behavior holds, for qemu_strtoull() but sets @result to
> - * ULLONG_MAX instead of ULONG_MAX.
> + * @nptr may be null, and no conversion is performed then.
>   *
> - * See qemu_strtol() documentation for more info.
> + * If no conversion is performed, store @nptr in *@endptr and return
> + * -EINVAL.
> + *
> + * If @endptr is null, and the string isn't fully converted, return
> + * -EINVAL.  This is the case when the pointer that would be stored in
> + * a non-null @endptr points to a character other than '\0'.
> + *
> + * If the conversion overflows @result, store ULONG_MAX in @result,
> + * and return -ERANGE.
> + *
> + * Else store the converted value in @result, and return zero.
> + *
> + * Note that a number with a leading minus sign gets converted without
> + * the minus sign, checked for overflow (see above), then negated (in
> + * @result's type).  This is exactly how strtoul() works.
>   */
>  int qemu_strtoul(const char *nptr, const char **endptr, int base,
>                   unsigned long *result)
> @@ -360,9 +367,10 @@ int qemu_strtoul(const char *nptr, const char **endptr, int base,
>  }
>
>  /**
> - * Converts ASCII string to a long long integer.
> + * Convert string @nptr to an int64_t.
>   *
> - * See qemu_strtol() documentation for more info.
> + * Works like qemu_strtol(), except it stores INT64_MAX on overflow,
> + * and INT_MIN on underflow.
>   */
>  int qemu_strtoll(const char *nptr, const char **endptr, int base,
>                   int64_t *result)
> @@ -376,6 +384,7 @@ int qemu_strtoll(const char *nptr, const char **endptr, int base,
>          err = -EINVAL;
>      } else {
>          errno = 0;
> +        /* FIXME This assumes int64_t is long long */
>          *result = strtoll(nptr, &p, base);
>          err = check_strtox_error(nptr, p, endptr, errno);
>      }
> @@ -383,9 +392,9 @@ int qemu_strtoll(const char *nptr, const char **endptr, int base,
>  }
>
>  /**
> - * Converts ASCII string to an unsigned long long integer.
> + * Convert string @nptr to an uint64_t.
>   *
> - * See qemu_strtol() documentation for more info.
> + * Works like qemu_strtoul(), except it stores UINT64_MAX on overflow.
>   */
>  int qemu_strtoull(const char *nptr, const char **endptr, int base,
>                    uint64_t *result)
> @@ -399,6 +408,7 @@ int qemu_strtoull(const char *nptr, const char **endptr, int base,
>          err = -EINVAL;
>      } else {
>          errno = 0;
> +        /* FIXME This assumes uint64_t is unsigned long long */
>          *result = strtoull(nptr, &p, base);
>          /* Windows returns 1 for negative out-of-range values.  */
>          if (errno == ERANGE) {
>

^ permalink raw reply	[flat|nested] 79+ messages in thread

* Re: [Qemu-devel] [PATCH 03/24] tests/test-cutils: Add missing qemu_strtol()... endptr checks
  2017-02-14 10:25 ` [Qemu-devel] [PATCH 03/24] tests/test-cutils: Add missing qemu_strtol()... endptr checks Markus Armbruster
  2017-02-14 20:11   ` Eric Blake
@ 2017-02-19  4:12   ` Philippe Mathieu-Daudé
  1 sibling, 0 replies; 79+ messages in thread
From: Philippe Mathieu-Daudé @ 2017-02-19  4:12 UTC (permalink / raw)
  To: Markus Armbruster, qemu-devel

On 02/14/2017 07:25 AM, Markus Armbruster wrote:
> Signed-off-by: Markus Armbruster <armbru@redhat.com>

Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>

> ---
>  tests/test-cutils.c | 12 ++++++++++++
>  1 file changed, 12 insertions(+)
>
> diff --git a/tests/test-cutils.c b/tests/test-cutils.c
> index 20b0f59..71681dc 100644
> --- a/tests/test-cutils.c
> +++ b/tests/test-cutils.c
> @@ -262,6 +262,7 @@ static void test_qemu_strtol_empty(void)
>      err = qemu_strtol(str, &endptr, 0, &res);
>
>      g_assert_cmpint(err, ==, -EINVAL);
> +    g_assert(endptr == str);
>  }
>
>  static void test_qemu_strtol_whitespace(void)
> @@ -275,6 +276,7 @@ static void test_qemu_strtol_whitespace(void)
>      err = qemu_strtol(str, &endptr, 0, &res);
>
>      g_assert_cmpint(err, ==, -EINVAL);
> +    g_assert(endptr == str);
>  }
>
>  static void test_qemu_strtol_invalid(void)
> @@ -288,6 +290,7 @@ static void test_qemu_strtol_invalid(void)
>      err = qemu_strtol(str, &endptr, 0, &res);
>
>      g_assert_cmpint(err, ==, -EINVAL);
> +    g_assert(endptr == str);
>  }
>
>  static void test_qemu_strtol_trailing(void)
> @@ -548,6 +551,7 @@ static void test_qemu_strtoul_empty(void)
>      err = qemu_strtoul(str, &endptr, 0, &res);
>
>      g_assert_cmpint(err, ==, -EINVAL);
> +    g_assert(endptr == str);
>  }
>
>  static void test_qemu_strtoul_whitespace(void)
> @@ -561,6 +565,7 @@ static void test_qemu_strtoul_whitespace(void)
>      err = qemu_strtoul(str, &endptr, 0, &res);
>
>      g_assert_cmpint(err, ==, -EINVAL);
> +    g_assert(endptr == str);
>  }
>
>  static void test_qemu_strtoul_invalid(void)
> @@ -574,6 +579,7 @@ static void test_qemu_strtoul_invalid(void)
>      err = qemu_strtoul(str, &endptr, 0, &res);
>
>      g_assert_cmpint(err, ==, -EINVAL);
> +    g_assert(endptr == str);
>  }
>
>  static void test_qemu_strtoul_trailing(void)
> @@ -829,6 +835,7 @@ static void test_qemu_strtoll_empty(void)
>      err = qemu_strtoll(str, &endptr, 0, &res);
>
>      g_assert_cmpint(err, ==, -EINVAL);
> +    g_assert(endptr == str);
>  }
>
>  static void test_qemu_strtoll_whitespace(void)
> @@ -842,6 +849,7 @@ static void test_qemu_strtoll_whitespace(void)
>      err = qemu_strtoll(str, &endptr, 0, &res);
>
>      g_assert_cmpint(err, ==, -EINVAL);
> +    g_assert(endptr == str);
>  }
>
>  static void test_qemu_strtoll_invalid(void)
> @@ -855,6 +863,7 @@ static void test_qemu_strtoll_invalid(void)
>      err = qemu_strtoll(str, &endptr, 0, &res);
>
>      g_assert_cmpint(err, ==, -EINVAL);
> +    g_assert(endptr == str);
>  }
>
>  static void test_qemu_strtoll_trailing(void)
> @@ -1113,6 +1122,7 @@ static void test_qemu_strtoull_empty(void)
>      err = qemu_strtoull(str, &endptr, 0, &res);
>
>      g_assert_cmpint(err, ==, -EINVAL);
> +    g_assert(endptr == str);
>  }
>
>  static void test_qemu_strtoull_whitespace(void)
> @@ -1126,6 +1136,7 @@ static void test_qemu_strtoull_whitespace(void)
>      err = qemu_strtoull(str, &endptr, 0, &res);
>
>      g_assert_cmpint(err, ==, -EINVAL);
> +    g_assert(endptr == str);
>  }
>
>  static void test_qemu_strtoull_invalid(void)
> @@ -1139,6 +1150,7 @@ static void test_qemu_strtoull_invalid(void)
>      err = qemu_strtoull(str, &endptr, 0, &res);
>
>      g_assert_cmpint(err, ==, -EINVAL);
> +    g_assert(endptr == str);
>  }
>
>  static void test_qemu_strtoull_trailing(void)
>

^ permalink raw reply	[flat|nested] 79+ messages in thread

* Re: [Qemu-devel] [PATCH 06/24] util/cutils: Rename qemu_strtoll(), qemu_strtoull()
  2017-02-14 10:25 ` [Qemu-devel] [PATCH 06/24] util/cutils: Rename qemu_strtoll(), qemu_strtoull() Markus Armbruster
  2017-02-14 21:34   ` Eric Blake
@ 2017-02-19  4:14   ` Philippe Mathieu-Daudé
  1 sibling, 0 replies; 79+ messages in thread
From: Philippe Mathieu-Daudé @ 2017-02-19  4:14 UTC (permalink / raw)
  To: Markus Armbruster, qemu-devel

On 02/14/2017 07:25 AM, Markus Armbruster wrote:
> The name qemu_strtoll() suggests conversion to long long, but it
> actually converts to int64_t.  Rename to qemu_strtoi64().
>
> The name qemu_strtoull() suggests conversion to unsigned long long,
> but it actually converts to uint64_t.  Rename to qemu_strtou64().
>
> Signed-off-by: Markus Armbruster <armbru@redhat.com>

Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>

> ---
>  include/qemu/cutils.h |   6 +-
>  qobject/qdict.c       |   2 +-
>  qtest.c               |  34 ++---
>  tests/test-cutils.c   | 366 +++++++++++++++++++++++++++-----------------------
>  util/cutils.c         |   4 +-
>  util/log.c            |   4 +-
>  6 files changed, 224 insertions(+), 192 deletions(-)
>
> diff --git a/include/qemu/cutils.h b/include/qemu/cutils.h
> index 8033929..f922223 100644
> --- a/include/qemu/cutils.h
> +++ b/include/qemu/cutils.h
> @@ -130,9 +130,9 @@ int qemu_strtol(const char *nptr, const char **endptr, int base,
>                  long *result);
>  int qemu_strtoul(const char *nptr, const char **endptr, int base,
>                   unsigned long *result);
> -int qemu_strtoll(const char *nptr, const char **endptr, int base,
> -                 int64_t *result);
> -int qemu_strtoull(const char *nptr, const char **endptr, int base,
> +int qemu_strtoi64(const char *nptr, const char **endptr, int base,
> +                  int64_t *result);
> +int qemu_strtou64(const char *nptr, const char **endptr, int base,
>                    uint64_t *result);
>
>  int parse_uint(const char *s, unsigned long long *value, char **endptr,
> diff --git a/qobject/qdict.c b/qobject/qdict.c
> index 197b0fb..4be7d3e 100644
> --- a/qobject/qdict.c
> +++ b/qobject/qdict.c
> @@ -767,7 +767,7 @@ static int qdict_is_list(QDict *maybe_list, Error **errp)
>      for (ent = qdict_first(maybe_list); ent != NULL;
>           ent = qdict_next(maybe_list, ent)) {
>
> -        if (qemu_strtoll(ent->key, NULL, 10, &val) == 0) {
> +        if (qemu_strtoi64(ent->key, NULL, 10, &val) == 0) {
>              if (is_list == -1) {
>                  is_list = 1;
>              } else if (!is_list) {
> diff --git a/qtest.c b/qtest.c
> index 1446719..a685827 100644
> --- a/qtest.c
> +++ b/qtest.c
> @@ -373,8 +373,8 @@ static void qtest_process_command(CharBackend *chr, gchar **words)
>          uint64_t value;
>
>          g_assert(words[1] && words[2]);
> -        g_assert(qemu_strtoull(words[1], NULL, 0, &addr) == 0);
> -        g_assert(qemu_strtoull(words[2], NULL, 0, &value) == 0);
> +        g_assert(qemu_strtou64(words[1], NULL, 0, &addr) == 0);
> +        g_assert(qemu_strtou64(words[2], NULL, 0, &value) == 0);
>
>          if (words[0][5] == 'b') {
>              uint8_t data = value;
> @@ -402,7 +402,7 @@ static void qtest_process_command(CharBackend *chr, gchar **words)
>          uint64_t value = UINT64_C(-1);
>
>          g_assert(words[1]);
> -        g_assert(qemu_strtoull(words[1], NULL, 0, &addr) == 0);
> +        g_assert(qemu_strtou64(words[1], NULL, 0, &addr) == 0);
>
>          if (words[0][4] == 'b') {
>              uint8_t data;
> @@ -428,8 +428,8 @@ static void qtest_process_command(CharBackend *chr, gchar **words)
>          char *enc;
>
>          g_assert(words[1] && words[2]);
> -        g_assert(qemu_strtoull(words[1], NULL, 0, &addr) == 0);
> -        g_assert(qemu_strtoull(words[2], NULL, 0, &len) == 0);
> +        g_assert(qemu_strtou64(words[1], NULL, 0, &addr) == 0);
> +        g_assert(qemu_strtou64(words[2], NULL, 0, &len) == 0);
>          /* We'd send garbage to libqtest if len is 0 */
>          g_assert(len);
>
> @@ -452,8 +452,8 @@ static void qtest_process_command(CharBackend *chr, gchar **words)
>          gchar *b64_data;
>
>          g_assert(words[1] && words[2]);
> -        g_assert(qemu_strtoull(words[1], NULL, 0, &addr) == 0);
> -        g_assert(qemu_strtoull(words[2], NULL, 0, &len) == 0);
> +        g_assert(qemu_strtou64(words[1], NULL, 0, &addr) == 0);
> +        g_assert(qemu_strtou64(words[2], NULL, 0, &len) == 0);
>
>          data = g_malloc(len);
>          cpu_physical_memory_read(addr, data, len);
> @@ -469,8 +469,8 @@ static void qtest_process_command(CharBackend *chr, gchar **words)
>          size_t data_len;
>
>          g_assert(words[1] && words[2] && words[3]);
> -        g_assert(qemu_strtoull(words[1], NULL, 0, &addr) == 0);
> -        g_assert(qemu_strtoull(words[2], NULL, 0, &len) == 0);
> +        g_assert(qemu_strtou64(words[1], NULL, 0, &addr) == 0);
> +        g_assert(qemu_strtou64(words[2], NULL, 0, &len) == 0);
>
>          data_len = strlen(words[3]);
>          if (data_len < 3) {
> @@ -498,8 +498,8 @@ static void qtest_process_command(CharBackend *chr, gchar **words)
>          unsigned long pattern;
>
>          g_assert(words[1] && words[2] && words[3]);
> -        g_assert(qemu_strtoull(words[1], NULL, 0, &addr) == 0);
> -        g_assert(qemu_strtoull(words[2], NULL, 0, &len) == 0);
> +        g_assert(qemu_strtou64(words[1], NULL, 0, &addr) == 0);
> +        g_assert(qemu_strtou64(words[2], NULL, 0, &len) == 0);
>          g_assert(qemu_strtoul(words[3], NULL, 0, &pattern) == 0);
>
>          if (len) {
> @@ -518,8 +518,8 @@ static void qtest_process_command(CharBackend *chr, gchar **words)
>          gsize out_len;
>
>          g_assert(words[1] && words[2] && words[3]);
> -        g_assert(qemu_strtoull(words[1], NULL, 0, &addr) == 0);
> -        g_assert(qemu_strtoull(words[2], NULL, 0, &len) == 0);
> +        g_assert(qemu_strtou64(words[1], NULL, 0, &addr) == 0);
> +        g_assert(qemu_strtou64(words[2], NULL, 0, &len) == 0);
>
>          data_len = strlen(words[3]);
>          if (data_len < 3) {
> @@ -552,9 +552,9 @@ static void qtest_process_command(CharBackend *chr, gchar **words)
>          unsigned long nargs, nret;
>
>          g_assert(qemu_strtoul(words[2], NULL, 0, &nargs) == 0);
> -        g_assert(qemu_strtoull(words[3], NULL, 0, &args) == 0);
> +        g_assert(qemu_strtou64(words[3], NULL, 0, &args) == 0);
>          g_assert(qemu_strtoul(words[4], NULL, 0, &nret) == 0);
> -        g_assert(qemu_strtoull(words[5], NULL, 0, &ret) == 0);
> +        g_assert(qemu_strtou64(words[5], NULL, 0, &ret) == 0);
>          res = qtest_rtas_call(words[1], nargs, args, nret, ret);
>
>          qtest_send_prefix(chr);
> @@ -564,7 +564,7 @@ static void qtest_process_command(CharBackend *chr, gchar **words)
>          int64_t ns;
>
>          if (words[1]) {
> -            g_assert(qemu_strtoll(words[1], NULL, 0, &ns) == 0);
> +            g_assert(qemu_strtoi64(words[1], NULL, 0, &ns) == 0);
>          } else {
>              ns = qemu_clock_deadline_ns_all(QEMU_CLOCK_VIRTUAL);
>          }
> @@ -576,7 +576,7 @@ static void qtest_process_command(CharBackend *chr, gchar **words)
>          int64_t ns;
>
>          g_assert(words[1]);
> -        g_assert(qemu_strtoll(words[1], NULL, 0, &ns) == 0);
> +        g_assert(qemu_strtoi64(words[1], NULL, 0, &ns) == 0);
>          qtest_clock_warp(ns);
>          qtest_send_prefix(chr);
>          qtest_sendf(chr, "OK %"PRIi64"\n",
> diff --git a/tests/test-cutils.c b/tests/test-cutils.c
> index ef76792..47cc8a4 100644
> --- a/tests/test-cutils.c
> +++ b/tests/test-cutils.c
> @@ -796,7 +796,7 @@ static void test_qemu_strtoul_full_max(void)
>      g_free(str);
>  }
>
> -static void test_qemu_strtoll_correct(void)
> +static void test_qemu_strtoi64_correct(void)
>  {
>      const char *str = "12345 foo";
>      char f = 'X';
> @@ -804,27 +804,27 @@ static void test_qemu_strtoll_correct(void)
>      int64_t res = 999;
>      int err;
>
> -    err = qemu_strtoll(str, &endptr, 0, &res);
> +    err = qemu_strtoi64(str, &endptr, 0, &res);
>
>      g_assert_cmpint(err, ==, 0);
>      g_assert_cmpint(res, ==, 12345);
>      g_assert(endptr == str + 5);
>  }
>
> -static void test_qemu_strtoll_null(void)
> +static void test_qemu_strtoi64_null(void)
>  {
>      char f = 'X';
>      const char *endptr = &f;
>      int64_t res = 999;
>      int err;
>
> -    err = qemu_strtoll(NULL, &endptr, 0, &res);
> +    err = qemu_strtoi64(NULL, &endptr, 0, &res);
>
>      g_assert_cmpint(err, ==, -EINVAL);
>      g_assert(endptr == NULL);
>  }
>
> -static void test_qemu_strtoll_empty(void)
> +static void test_qemu_strtoi64_empty(void)
>  {
>      const char *str = "";
>      char f = 'X';
> @@ -832,13 +832,13 @@ static void test_qemu_strtoll_empty(void)
>      int64_t res = 999;
>      int err;
>
> -    err = qemu_strtoll(str, &endptr, 0, &res);
> +    err = qemu_strtoi64(str, &endptr, 0, &res);
>
>      g_assert_cmpint(err, ==, -EINVAL);
>      g_assert(endptr == str);
>  }
>
> -static void test_qemu_strtoll_whitespace(void)
> +static void test_qemu_strtoi64_whitespace(void)
>  {
>      const char *str = "  \t  ";
>      char f = 'X';
> @@ -846,13 +846,13 @@ static void test_qemu_strtoll_whitespace(void)
>      int64_t res = 999;
>      int err;
>
> -    err = qemu_strtoll(str, &endptr, 0, &res);
> +    err = qemu_strtoi64(str, &endptr, 0, &res);
>
>      g_assert_cmpint(err, ==, -EINVAL);
>      g_assert(endptr == str);
>  }
>
> -static void test_qemu_strtoll_invalid(void)
> +static void test_qemu_strtoi64_invalid(void)
>  {
>      const char *str = "   xxxx  \t abc";
>      char f = 'X';
> @@ -860,13 +860,13 @@ static void test_qemu_strtoll_invalid(void)
>      int64_t res = 999;
>      int err;
>
> -    err = qemu_strtoll(str, &endptr, 0, &res);
> +    err = qemu_strtoi64(str, &endptr, 0, &res);
>
>      g_assert_cmpint(err, ==, -EINVAL);
>      g_assert(endptr == str);
>  }
>
> -static void test_qemu_strtoll_trailing(void)
> +static void test_qemu_strtoi64_trailing(void)
>  {
>      const char *str = "123xxx";
>      char f = 'X';
> @@ -874,14 +874,14 @@ static void test_qemu_strtoll_trailing(void)
>      int64_t res = 999;
>      int err;
>
> -    err = qemu_strtoll(str, &endptr, 0, &res);
> +    err = qemu_strtoi64(str, &endptr, 0, &res);
>
>      g_assert_cmpint(err, ==, 0);
>      g_assert_cmpint(res, ==, 123);
>      g_assert(endptr == str + 3);
>  }
>
> -static void test_qemu_strtoll_octal(void)
> +static void test_qemu_strtoi64_octal(void)
>  {
>      const char *str = "0123";
>      char f = 'X';
> @@ -889,7 +889,7 @@ static void test_qemu_strtoll_octal(void)
>      int64_t res = 999;
>      int err;
>
> -    err = qemu_strtoll(str, &endptr, 8, &res);
> +    err = qemu_strtoi64(str, &endptr, 8, &res);
>
>      g_assert_cmpint(err, ==, 0);
>      g_assert_cmpint(res, ==, 0123);
> @@ -897,14 +897,14 @@ static void test_qemu_strtoll_octal(void)
>
>      endptr = &f;
>      res = 999;
> -    err = qemu_strtoll(str, &endptr, 0, &res);
> +    err = qemu_strtoi64(str, &endptr, 0, &res);
>
>      g_assert_cmpint(err, ==, 0);
>      g_assert_cmpint(res, ==, 0123);
>      g_assert(endptr == str + strlen(str));
>  }
>
> -static void test_qemu_strtoll_decimal(void)
> +static void test_qemu_strtoi64_decimal(void)
>  {
>      const char *str = "0123";
>      char f = 'X';
> @@ -912,7 +912,7 @@ static void test_qemu_strtoll_decimal(void)
>      int64_t res = 999;
>      int err;
>
> -    err = qemu_strtoll(str, &endptr, 10, &res);
> +    err = qemu_strtoi64(str, &endptr, 10, &res);
>
>      g_assert_cmpint(err, ==, 0);
>      g_assert_cmpint(res, ==, 123);
> @@ -921,14 +921,14 @@ static void test_qemu_strtoll_decimal(void)
>      str = "123";
>      endptr = &f;
>      res = 999;
> -    err = qemu_strtoll(str, &endptr, 0, &res);
> +    err = qemu_strtoi64(str, &endptr, 0, &res);
>
>      g_assert_cmpint(err, ==, 0);
>      g_assert_cmpint(res, ==, 123);
>      g_assert(endptr == str + strlen(str));
>  }
>
> -static void test_qemu_strtoll_hex(void)
> +static void test_qemu_strtoi64_hex(void)
>  {
>      const char *str = "0123";
>      char f = 'X';
> @@ -936,7 +936,7 @@ static void test_qemu_strtoll_hex(void)
>      int64_t res = 999;
>      int err;
>
> -    err = qemu_strtoll(str, &endptr, 16, &res);
> +    err = qemu_strtoi64(str, &endptr, 16, &res);
>
>      g_assert_cmpint(err, ==, 0);
>      g_assert_cmpint(res, ==, 0x123);
> @@ -945,14 +945,14 @@ static void test_qemu_strtoll_hex(void)
>      str = "0x123";
>      endptr = &f;
>      res = 999;
> -    err = qemu_strtoll(str, &endptr, 0, &res);
> +    err = qemu_strtoi64(str, &endptr, 0, &res);
>
>      g_assert_cmpint(err, ==, 0);
>      g_assert_cmpint(res, ==, 0x123);
>      g_assert(endptr == str + strlen(str));
>  }
>
> -static void test_qemu_strtoll_max(void)
> +static void test_qemu_strtoi64_max(void)
>  {
>      char *str = g_strdup_printf("%lld", LLONG_MAX);
>      char f = 'X';
> @@ -960,7 +960,7 @@ static void test_qemu_strtoll_max(void)
>      int64_t res = 999;
>      int err;
>
> -    err = qemu_strtoll(str, &endptr, 0, &res);
> +    err = qemu_strtoi64(str, &endptr, 0, &res);
>
>      g_assert_cmpint(err, ==, 0);
>      g_assert_cmpint(res, ==, LLONG_MAX);
> @@ -968,7 +968,7 @@ static void test_qemu_strtoll_max(void)
>      g_free(str);
>  }
>
> -static void test_qemu_strtoll_overflow(void)
> +static void test_qemu_strtoi64_overflow(void)
>  {
>      const char *str = "99999999999999999999999999999999999999999999";
>      char f = 'X';
> @@ -976,14 +976,14 @@ static void test_qemu_strtoll_overflow(void)
>      int64_t res = 999;
>      int err;
>
> -    err = qemu_strtoll(str, &endptr, 0, &res);
> +    err = qemu_strtoi64(str, &endptr, 0, &res);
>
>      g_assert_cmpint(err, ==, -ERANGE);
>      g_assert_cmpint(res, ==, LLONG_MAX);
>      g_assert(endptr == str + strlen(str));
>  }
>
> -static void test_qemu_strtoll_underflow(void)
> +static void test_qemu_strtoi64_underflow(void)
>  {
>      const char *str = "-99999999999999999999999999999999999999999999";
>      char f = 'X';
> @@ -991,14 +991,14 @@ static void test_qemu_strtoll_underflow(void)
>      int64_t res = 999;
>      int err;
>
> -    err  = qemu_strtoll(str, &endptr, 0, &res);
> +    err  = qemu_strtoi64(str, &endptr, 0, &res);
>
>      g_assert_cmpint(err, ==, -ERANGE);
>      g_assert_cmpint(res, ==, LLONG_MIN);
>      g_assert(endptr == str + strlen(str));
>  }
>
> -static void test_qemu_strtoll_negative(void)
> +static void test_qemu_strtoi64_negative(void)
>  {
>      const char *str = "  \t -321";
>      char f = 'X';
> @@ -1006,84 +1006,84 @@ static void test_qemu_strtoll_negative(void)
>      int64_t res = 999;
>      int err;
>
> -    err = qemu_strtoll(str, &endptr, 0, &res);
> +    err = qemu_strtoi64(str, &endptr, 0, &res);
>
>      g_assert_cmpint(err, ==, 0);
>      g_assert_cmpint(res, ==, -321);
>      g_assert(endptr == str + strlen(str));
>  }
>
> -static void test_qemu_strtoll_full_correct(void)
> +static void test_qemu_strtoi64_full_correct(void)
>  {
>      const char *str = "123";
>      int64_t res = 999;
>      int err;
>
> -    err = qemu_strtoll(str, NULL, 0, &res);
> +    err = qemu_strtoi64(str, NULL, 0, &res);
>
>      g_assert_cmpint(err, ==, 0);
>      g_assert_cmpint(res, ==, 123);
>  }
>
> -static void test_qemu_strtoll_full_null(void)
> +static void test_qemu_strtoi64_full_null(void)
>  {
>      int64_t res = 999;
>      int err;
>
> -    err = qemu_strtoll(NULL, NULL, 0, &res);
> +    err = qemu_strtoi64(NULL, NULL, 0, &res);
>
>      g_assert_cmpint(err, ==, -EINVAL);
>  }
>
> -static void test_qemu_strtoll_full_empty(void)
> +static void test_qemu_strtoi64_full_empty(void)
>  {
>      const char *str = "";
>      int64_t res = 999;
>      int err;
>
> -    err = qemu_strtoll(str, NULL, 0, &res);
> +    err = qemu_strtoi64(str, NULL, 0, &res);
>
>      g_assert_cmpint(err, ==, -EINVAL);
>  }
>
> -static void test_qemu_strtoll_full_negative(void)
> +static void test_qemu_strtoi64_full_negative(void)
>  {
>      const char *str = " \t -321";
>      int64_t res = 999;
>      int err;
>
> -    err = qemu_strtoll(str, NULL, 0, &res);
> +    err = qemu_strtoi64(str, NULL, 0, &res);
>
>      g_assert_cmpint(err, ==, 0);
>      g_assert_cmpint(res, ==, -321);
>  }
>
> -static void test_qemu_strtoll_full_trailing(void)
> +static void test_qemu_strtoi64_full_trailing(void)
>  {
>      const char *str = "123xxx";
>      int64_t res = 999;
>      int err;
>
> -    err = qemu_strtoll(str, NULL, 0, &res);
> +    err = qemu_strtoi64(str, NULL, 0, &res);
>
>      g_assert_cmpint(err, ==, -EINVAL);
>  }
>
> -static void test_qemu_strtoll_full_max(void)
> +static void test_qemu_strtoi64_full_max(void)
>  {
>
>      char *str = g_strdup_printf("%lld", LLONG_MAX);
>      int64_t res;
>      int err;
>
> -    err = qemu_strtoll(str, NULL, 0, &res);
> +    err = qemu_strtoi64(str, NULL, 0, &res);
>
>      g_assert_cmpint(err, ==, 0);
>      g_assert_cmpint(res, ==, LLONG_MAX);
>      g_free(str);
>  }
>
> -static void test_qemu_strtoull_correct(void)
> +static void test_qemu_strtou64_correct(void)
>  {
>      const char *str = "12345 foo";
>      char f = 'X';
> @@ -1091,27 +1091,27 @@ static void test_qemu_strtoull_correct(void)
>      uint64_t res = 999;
>      int err;
>
> -    err = qemu_strtoull(str, &endptr, 0, &res);
> +    err = qemu_strtou64(str, &endptr, 0, &res);
>
>      g_assert_cmpint(err, ==, 0);
>      g_assert_cmpuint(res, ==, 12345);
>      g_assert(endptr == str + 5);
>  }
>
> -static void test_qemu_strtoull_null(void)
> +static void test_qemu_strtou64_null(void)
>  {
>      char f = 'X';
>      const char *endptr = &f;
>      uint64_t res = 999;
>      int err;
>
> -    err = qemu_strtoull(NULL, &endptr, 0, &res);
> +    err = qemu_strtou64(NULL, &endptr, 0, &res);
>
>      g_assert_cmpint(err, ==, -EINVAL);
>      g_assert(endptr == NULL);
>  }
>
> -static void test_qemu_strtoull_empty(void)
> +static void test_qemu_strtou64_empty(void)
>  {
>      const char *str = "";
>      char f = 'X';
> @@ -1119,13 +1119,13 @@ static void test_qemu_strtoull_empty(void)
>      uint64_t res = 999;
>      int err;
>
> -    err = qemu_strtoull(str, &endptr, 0, &res);
> +    err = qemu_strtou64(str, &endptr, 0, &res);
>
>      g_assert_cmpint(err, ==, -EINVAL);
>      g_assert(endptr == str);
>  }
>
> -static void test_qemu_strtoull_whitespace(void)
> +static void test_qemu_strtou64_whitespace(void)
>  {
>      const char *str = "  \t  ";
>      char f = 'X';
> @@ -1133,13 +1133,13 @@ static void test_qemu_strtoull_whitespace(void)
>      uint64_t res = 999;
>      int err;
>
> -    err = qemu_strtoull(str, &endptr, 0, &res);
> +    err = qemu_strtou64(str, &endptr, 0, &res);
>
>      g_assert_cmpint(err, ==, -EINVAL);
>      g_assert(endptr == str);
>  }
>
> -static void test_qemu_strtoull_invalid(void)
> +static void test_qemu_strtou64_invalid(void)
>  {
>      const char *str = "   xxxx  \t abc";
>      char f = 'X';
> @@ -1147,13 +1147,13 @@ static void test_qemu_strtoull_invalid(void)
>      uint64_t res = 999;
>      int err;
>
> -    err = qemu_strtoull(str, &endptr, 0, &res);
> +    err = qemu_strtou64(str, &endptr, 0, &res);
>
>      g_assert_cmpint(err, ==, -EINVAL);
>      g_assert(endptr == str);
>  }
>
> -static void test_qemu_strtoull_trailing(void)
> +static void test_qemu_strtou64_trailing(void)
>  {
>      const char *str = "123xxx";
>      char f = 'X';
> @@ -1161,14 +1161,14 @@ static void test_qemu_strtoull_trailing(void)
>      uint64_t res = 999;
>      int err;
>
> -    err = qemu_strtoull(str, &endptr, 0, &res);
> +    err = qemu_strtou64(str, &endptr, 0, &res);
>
>      g_assert_cmpint(err, ==, 0);
>      g_assert_cmpuint(res, ==, 123);
>      g_assert(endptr == str + 3);
>  }
>
> -static void test_qemu_strtoull_octal(void)
> +static void test_qemu_strtou64_octal(void)
>  {
>      const char *str = "0123";
>      char f = 'X';
> @@ -1176,7 +1176,7 @@ static void test_qemu_strtoull_octal(void)
>      uint64_t res = 999;
>      int err;
>
> -    err = qemu_strtoull(str, &endptr, 8, &res);
> +    err = qemu_strtou64(str, &endptr, 8, &res);
>
>      g_assert_cmpint(err, ==, 0);
>      g_assert_cmpuint(res, ==, 0123);
> @@ -1184,14 +1184,14 @@ static void test_qemu_strtoull_octal(void)
>
>      endptr = &f;
>      res = 999;
> -    err = qemu_strtoull(str, &endptr, 0, &res);
> +    err = qemu_strtou64(str, &endptr, 0, &res);
>
>      g_assert_cmpint(err, ==, 0);
>      g_assert_cmpuint(res, ==, 0123);
>      g_assert(endptr == str + strlen(str));
>  }
>
> -static void test_qemu_strtoull_decimal(void)
> +static void test_qemu_strtou64_decimal(void)
>  {
>      const char *str = "0123";
>      char f = 'X';
> @@ -1199,7 +1199,7 @@ static void test_qemu_strtoull_decimal(void)
>      uint64_t res = 999;
>      int err;
>
> -    err = qemu_strtoull(str, &endptr, 10, &res);
> +    err = qemu_strtou64(str, &endptr, 10, &res);
>
>      g_assert_cmpint(err, ==, 0);
>      g_assert_cmpuint(res, ==, 123);
> @@ -1208,14 +1208,14 @@ static void test_qemu_strtoull_decimal(void)
>      str = "123";
>      endptr = &f;
>      res = 999;
> -    err = qemu_strtoull(str, &endptr, 0, &res);
> +    err = qemu_strtou64(str, &endptr, 0, &res);
>
>      g_assert_cmpint(err, ==, 0);
>      g_assert_cmpuint(res, ==, 123);
>      g_assert(endptr == str + strlen(str));
>  }
>
> -static void test_qemu_strtoull_hex(void)
> +static void test_qemu_strtou64_hex(void)
>  {
>      const char *str = "0123";
>      char f = 'X';
> @@ -1223,7 +1223,7 @@ static void test_qemu_strtoull_hex(void)
>      uint64_t res = 999;
>      int err;
>
> -    err = qemu_strtoull(str, &endptr, 16, &res);
> +    err = qemu_strtou64(str, &endptr, 16, &res);
>
>      g_assert_cmpint(err, ==, 0);
>      g_assert_cmpuint(res, ==, 0x123);
> @@ -1232,14 +1232,14 @@ static void test_qemu_strtoull_hex(void)
>      str = "0x123";
>      endptr = &f;
>      res = 999;
> -    err = qemu_strtoull(str, &endptr, 0, &res);
> +    err = qemu_strtou64(str, &endptr, 0, &res);
>
>      g_assert_cmpint(err, ==, 0);
>      g_assert_cmpuint(res, ==, 0x123);
>      g_assert(endptr == str + strlen(str));
>  }
>
> -static void test_qemu_strtoull_max(void)
> +static void test_qemu_strtou64_max(void)
>  {
>      char *str = g_strdup_printf("%llu", ULLONG_MAX);
>      char f = 'X';
> @@ -1247,7 +1247,7 @@ static void test_qemu_strtoull_max(void)
>      uint64_t res = 999;
>      int err;
>
> -    err = qemu_strtoull(str, &endptr, 0, &res);
> +    err = qemu_strtou64(str, &endptr, 0, &res);
>
>      g_assert_cmpint(err, ==, 0);
>      g_assert_cmpuint(res, ==, ULLONG_MAX);
> @@ -1255,7 +1255,7 @@ static void test_qemu_strtoull_max(void)
>      g_free(str);
>  }
>
> -static void test_qemu_strtoull_overflow(void)
> +static void test_qemu_strtou64_overflow(void)
>  {
>      const char *str = "99999999999999999999999999999999999999999999";
>      char f = 'X';
> @@ -1263,14 +1263,14 @@ static void test_qemu_strtoull_overflow(void)
>      uint64_t res = 999;
>      int err;
>
> -    err = qemu_strtoull(str, &endptr, 0, &res);
> +    err = qemu_strtou64(str, &endptr, 0, &res);
>
>      g_assert_cmpint(err, ==, -ERANGE);
>      g_assert_cmpuint(res, ==, ULLONG_MAX);
>      g_assert(endptr == str + strlen(str));
>  }
>
> -static void test_qemu_strtoull_underflow(void)
> +static void test_qemu_strtou64_underflow(void)
>  {
>      const char *str = "-99999999999999999999999999999999999999999999";
>      char f = 'X';
> @@ -1278,14 +1278,14 @@ static void test_qemu_strtoull_underflow(void)
>      uint64_t res = 999;
>      int err;
>
> -    err  = qemu_strtoull(str, &endptr, 0, &res);
> +    err  = qemu_strtou64(str, &endptr, 0, &res);
>
>      g_assert_cmpint(err, ==, -ERANGE);
>      g_assert_cmpuint(res, ==, (uint64_t)-1);
>      g_assert(endptr == str + strlen(str));
>  }
>
> -static void test_qemu_strtoull_negative(void)
> +static void test_qemu_strtou64_negative(void)
>  {
>      const char *str = "  \t -321";
>      char f = 'X';
> @@ -1293,76 +1293,76 @@ static void test_qemu_strtoull_negative(void)
>      uint64_t res = 999;
>      int err;
>
> -    err = qemu_strtoull(str, &endptr, 0, &res);
> +    err = qemu_strtou64(str, &endptr, 0, &res);
>
>      g_assert_cmpint(err, ==, 0);
>      g_assert_cmpuint(res, ==, (uint64_t)-321);
>      g_assert(endptr == str + strlen(str));
>  }
>
> -static void test_qemu_strtoull_full_correct(void)
> +static void test_qemu_strtou64_full_correct(void)
>  {
>      const char *str = "18446744073709551614";
>      uint64_t res = 999;
>      int err;
>
> -    err = qemu_strtoull(str, NULL, 0, &res);
> +    err = qemu_strtou64(str, NULL, 0, &res);
>
>      g_assert_cmpint(err, ==, 0);
>      g_assert_cmpuint(res, ==, 18446744073709551614LLU);
>  }
>
> -static void test_qemu_strtoull_full_null(void)
> +static void test_qemu_strtou64_full_null(void)
>  {
>      uint64_t res = 999;
>      int err;
>
> -    err = qemu_strtoull(NULL, NULL, 0, &res);
> +    err = qemu_strtou64(NULL, NULL, 0, &res);
>
>      g_assert_cmpint(err, ==, -EINVAL);
>  }
>
> -static void test_qemu_strtoull_full_empty(void)
> +static void test_qemu_strtou64_full_empty(void)
>  {
>      const char *str = "";
>      uint64_t res = 999;
>      int err;
>
> -    err = qemu_strtoull(str, NULL, 0, &res);
> +    err = qemu_strtou64(str, NULL, 0, &res);
>
>      g_assert_cmpint(err, ==, -EINVAL);
>  }
>
> -static void test_qemu_strtoull_full_negative(void)
> +static void test_qemu_strtou64_full_negative(void)
>  {
>      const char *str = " \t -321";
>      uint64_t res = 999;
>      int err;
>
> -    err = qemu_strtoull(str, NULL, 0, &res);
> +    err = qemu_strtou64(str, NULL, 0, &res);
>
>      g_assert_cmpint(err, ==, 0);
>      g_assert_cmpuint(res, ==, 18446744073709551295LLU);
>  }
>
> -static void test_qemu_strtoull_full_trailing(void)
> +static void test_qemu_strtou64_full_trailing(void)
>  {
>      const char *str = "18446744073709551614xxxxxx";
>      uint64_t res = 999;
>      int err;
>
> -    err = qemu_strtoull(str, NULL, 0, &res);
> +    err = qemu_strtou64(str, NULL, 0, &res);
>
>      g_assert_cmpint(err, ==, -EINVAL);
>  }
>
> -static void test_qemu_strtoull_full_max(void)
> +static void test_qemu_strtou64_full_max(void)
>  {
>      char *str = g_strdup_printf("%lld", ULLONG_MAX);
>      uint64_t res = 999;
>      int err;
>
> -    err = qemu_strtoull(str, NULL, 0, &res);
> +    err = qemu_strtou64(str, NULL, 0, &res);
>
>      g_assert_cmpint(err, ==, 0);
>      g_assert_cmpuint(res, ==, ULLONG_MAX);
> @@ -1471,21 +1471,32 @@ int main(int argc, char **argv)
>                      test_parse_uint_full_correct);
>
>      /* qemu_strtol() tests */
> -    g_test_add_func("/cutils/qemu_strtol/correct", test_qemu_strtol_correct);
> -    g_test_add_func("/cutils/qemu_strtol/null", test_qemu_strtol_null);
> -    g_test_add_func("/cutils/qemu_strtol/empty", test_qemu_strtol_empty);
> +    g_test_add_func("/cutils/qemu_strtol/correct",
> +                    test_qemu_strtol_correct);
> +    g_test_add_func("/cutils/qemu_strtol/null",
> +                    test_qemu_strtol_null);
> +    g_test_add_func("/cutils/qemu_strtol/empty",
> +                    test_qemu_strtol_empty);
>      g_test_add_func("/cutils/qemu_strtol/whitespace",
>                      test_qemu_strtol_whitespace);
> -    g_test_add_func("/cutils/qemu_strtol/invalid", test_qemu_strtol_invalid);
> -    g_test_add_func("/cutils/qemu_strtol/trailing", test_qemu_strtol_trailing);
> -    g_test_add_func("/cutils/qemu_strtol/octal", test_qemu_strtol_octal);
> -    g_test_add_func("/cutils/qemu_strtol/decimal", test_qemu_strtol_decimal);
> -    g_test_add_func("/cutils/qemu_strtol/hex", test_qemu_strtol_hex);
> -    g_test_add_func("/cutils/qemu_strtol/max", test_qemu_strtol_max);
> -    g_test_add_func("/cutils/qemu_strtol/overflow", test_qemu_strtol_overflow);
> +    g_test_add_func("/cutils/qemu_strtol/invalid",
> +                    test_qemu_strtol_invalid);
> +    g_test_add_func("/cutils/qemu_strtol/trailing",
> +                    test_qemu_strtol_trailing);
> +    g_test_add_func("/cutils/qemu_strtol/octal",
> +                    test_qemu_strtol_octal);
> +    g_test_add_func("/cutils/qemu_strtol/decimal",
> +                    test_qemu_strtol_decimal);
> +    g_test_add_func("/cutils/qemu_strtol/hex",
> +                    test_qemu_strtol_hex);
> +    g_test_add_func("/cutils/qemu_strtol/max",
> +                    test_qemu_strtol_max);
> +    g_test_add_func("/cutils/qemu_strtol/overflow",
> +                    test_qemu_strtol_overflow);
>      g_test_add_func("/cutils/qemu_strtol/underflow",
>                      test_qemu_strtol_underflow);
> -    g_test_add_func("/cutils/qemu_strtol/negative", test_qemu_strtol_negative);
> +    g_test_add_func("/cutils/qemu_strtol/negative",
> +                    test_qemu_strtol_negative);
>      g_test_add_func("/cutils/qemu_strtol_full/correct",
>                      test_qemu_strtol_full_correct);
>      g_test_add_func("/cutils/qemu_strtol_full/null",
> @@ -1500,18 +1511,26 @@ int main(int argc, char **argv)
>                      test_qemu_strtol_full_max);
>
>      /* qemu_strtoul() tests */
> -    g_test_add_func("/cutils/qemu_strtoul/correct", test_qemu_strtoul_correct);
> -    g_test_add_func("/cutils/qemu_strtoul/null", test_qemu_strtoul_null);
> -    g_test_add_func("/cutils/qemu_strtoul/empty", test_qemu_strtoul_empty);
> +    g_test_add_func("/cutils/qemu_strtoul/correct",
> +                    test_qemu_strtoul_correct);
> +    g_test_add_func("/cutils/qemu_strtoul/null",
> +                    test_qemu_strtoul_null);
> +    g_test_add_func("/cutils/qemu_strtoul/empty",
> +                    test_qemu_strtoul_empty);
>      g_test_add_func("/cutils/qemu_strtoul/whitespace",
>                      test_qemu_strtoul_whitespace);
> -    g_test_add_func("/cutils/qemu_strtoul/invalid", test_qemu_strtoul_invalid);
> +    g_test_add_func("/cutils/qemu_strtoul/invalid",
> +                    test_qemu_strtoul_invalid);
>      g_test_add_func("/cutils/qemu_strtoul/trailing",
>                      test_qemu_strtoul_trailing);
> -    g_test_add_func("/cutils/qemu_strtoul/octal", test_qemu_strtoul_octal);
> -    g_test_add_func("/cutils/qemu_strtoul/decimal", test_qemu_strtoul_decimal);
> -    g_test_add_func("/cutils/qemu_strtoul/hex", test_qemu_strtoul_hex);
> -    g_test_add_func("/cutils/qemu_strtoul/max", test_qemu_strtoul_max);
> +    g_test_add_func("/cutils/qemu_strtoul/octal",
> +                    test_qemu_strtoul_octal);
> +    g_test_add_func("/cutils/qemu_strtoul/decimal",
> +                    test_qemu_strtoul_decimal);
> +    g_test_add_func("/cutils/qemu_strtoul/hex",
> +                    test_qemu_strtoul_hex);
> +    g_test_add_func("/cutils/qemu_strtoul/max",
> +                    test_qemu_strtoul_max);
>      g_test_add_func("/cutils/qemu_strtoul/overflow",
>                      test_qemu_strtoul_overflow);
>      g_test_add_func("/cutils/qemu_strtoul/underflow",
> @@ -1531,73 +1550,86 @@ int main(int argc, char **argv)
>      g_test_add_func("/cutils/qemu_strtoul_full/max",
>                      test_qemu_strtoul_full_max);
>
> -    /* qemu_strtoll() tests */
> -    g_test_add_func("/cutils/qemu_strtoll/correct", test_qemu_strtoll_correct);
> -    g_test_add_func("/cutils/qemu_strtoll/null", test_qemu_strtoll_null);
> -    g_test_add_func("/cutils/qemu_strtoll/empty", test_qemu_strtoll_empty);
> -    g_test_add_func("/cutils/qemu_strtoll/whitespace",
> -                    test_qemu_strtoll_whitespace);
> -    g_test_add_func("/cutils/qemu_strtoll/invalid", test_qemu_strtoll_invalid);
> -    g_test_add_func("/cutils/qemu_strtoll/trailing",
> -                    test_qemu_strtoll_trailing);
> -    g_test_add_func("/cutils/qemu_strtoll/octal", test_qemu_strtoll_octal);
> -    g_test_add_func("/cutils/qemu_strtoll/decimal", test_qemu_strtoll_decimal);
> -    g_test_add_func("/cutils/qemu_strtoll/hex", test_qemu_strtoll_hex);
> -    g_test_add_func("/cutils/qemu_strtoll/max", test_qemu_strtoll_max);
> -    g_test_add_func("/cutils/qemu_strtoll/overflow",
> -                    test_qemu_strtoll_overflow);
> -    g_test_add_func("/cutils/qemu_strtoll/underflow",
> -                    test_qemu_strtoll_underflow);
> -    g_test_add_func("/cutils/qemu_strtoll/negative",
> -                    test_qemu_strtoll_negative);
> -    g_test_add_func("/cutils/qemu_strtoll_full/correct",
> -                    test_qemu_strtoll_full_correct);
> -    g_test_add_func("/cutils/qemu_strtoll_full/null",
> -                    test_qemu_strtoll_full_null);
> -    g_test_add_func("/cutils/qemu_strtoll_full/empty",
> -                    test_qemu_strtoll_full_empty);
> -    g_test_add_func("/cutils/qemu_strtoll_full/negative",
> -                    test_qemu_strtoll_full_negative);
> -    g_test_add_func("/cutils/qemu_strtoll_full/trailing",
> -                    test_qemu_strtoll_full_trailing);
> -    g_test_add_func("/cutils/qemu_strtoll_full/max",
> -                    test_qemu_strtoll_full_max);
> +    /* qemu_strtoi64() tests */
> +    g_test_add_func("/cutils/qemu_strtoi64/correct",
> +                    test_qemu_strtoi64_correct);
> +    g_test_add_func("/cutils/qemu_strtoi64/null",
> +                    test_qemu_strtoi64_null);
> +    g_test_add_func("/cutils/qemu_strtoi64/empty",
> +                    test_qemu_strtoi64_empty);
> +    g_test_add_func("/cutils/qemu_strtoi64/whitespace",
> +                    test_qemu_strtoi64_whitespace);
> +    g_test_add_func("/cutils/qemu_strtoi64/invalid"
> +                    ,
> +                    test_qemu_strtoi64_invalid);
> +    g_test_add_func("/cutils/qemu_strtoi64/trailing",
> +                    test_qemu_strtoi64_trailing);
> +    g_test_add_func("/cutils/qemu_strtoi64/octal",
> +                    test_qemu_strtoi64_octal);
> +    g_test_add_func("/cutils/qemu_strtoi64/decimal",
> +                    test_qemu_strtoi64_decimal);
> +    g_test_add_func("/cutils/qemu_strtoi64/hex",
> +                    test_qemu_strtoi64_hex);
> +    g_test_add_func("/cutils/qemu_strtoi64/max",
> +                    test_qemu_strtoi64_max);
> +    g_test_add_func("/cutils/qemu_strtoi64/overflow",
> +                    test_qemu_strtoi64_overflow);
> +    g_test_add_func("/cutils/qemu_strtoi64/underflow",
> +                    test_qemu_strtoi64_underflow);
> +    g_test_add_func("/cutils/qemu_strtoi64/negative",
> +                    test_qemu_strtoi64_negative);
> +    g_test_add_func("/cutils/qemu_strtoi64_full/correct",
> +                    test_qemu_strtoi64_full_correct);
> +    g_test_add_func("/cutils/qemu_strtoi64_full/null",
> +                    test_qemu_strtoi64_full_null);
> +    g_test_add_func("/cutils/qemu_strtoi64_full/empty",
> +                    test_qemu_strtoi64_full_empty);
> +    g_test_add_func("/cutils/qemu_strtoi64_full/negative",
> +                    test_qemu_strtoi64_full_negative);
> +    g_test_add_func("/cutils/qemu_strtoi64_full/trailing",
> +                    test_qemu_strtoi64_full_trailing);
> +    g_test_add_func("/cutils/qemu_strtoi64_full/max",
> +                    test_qemu_strtoi64_full_max);
>
> -    /* qemu_strtoull() tests */
> -    g_test_add_func("/cutils/qemu_strtoull/correct",
> -                    test_qemu_strtoull_correct);
> -    g_test_add_func("/cutils/qemu_strtoull/null",
> -                    test_qemu_strtoull_null);
> -    g_test_add_func("/cutils/qemu_strtoull/empty", test_qemu_strtoull_empty);
> -    g_test_add_func("/cutils/qemu_strtoull/whitespace",
> -                    test_qemu_strtoull_whitespace);
> -    g_test_add_func("/cutils/qemu_strtoull/invalid",
> -                    test_qemu_strtoull_invalid);
> -    g_test_add_func("/cutils/qemu_strtoull/trailing",
> -                    test_qemu_strtoull_trailing);
> -    g_test_add_func("/cutils/qemu_strtoull/octal", test_qemu_strtoull_octal);
> -    g_test_add_func("/cutils/qemu_strtoull/decimal",
> -                    test_qemu_strtoull_decimal);
> -    g_test_add_func("/cutils/qemu_strtoull/hex", test_qemu_strtoull_hex);
> -    g_test_add_func("/cutils/qemu_strtoull/max", test_qemu_strtoull_max);
> -    g_test_add_func("/cutils/qemu_strtoull/overflow",
> -                    test_qemu_strtoull_overflow);
> -    g_test_add_func("/cutils/qemu_strtoull/underflow",
> -                    test_qemu_strtoull_underflow);
> -    g_test_add_func("/cutils/qemu_strtoull/negative",
> -                    test_qemu_strtoull_negative);
> -    g_test_add_func("/cutils/qemu_strtoull_full/correct",
> -                    test_qemu_strtoull_full_correct);
> -    g_test_add_func("/cutils/qemu_strtoull_full/null",
> -                    test_qemu_strtoull_full_null);
> -    g_test_add_func("/cutils/qemu_strtoull_full/empty",
> -                    test_qemu_strtoull_full_empty);
> -    g_test_add_func("/cutils/qemu_strtoull_full/negative",
> -                    test_qemu_strtoull_full_negative);
> -    g_test_add_func("/cutils/qemu_strtoull_full/trailing",
> -                    test_qemu_strtoull_full_trailing);
> -    g_test_add_func("/cutils/qemu_strtoull_full/max",
> -                    test_qemu_strtoull_full_max);
> +    /* qemu_strtou64() tests */
> +    g_test_add_func("/cutils/qemu_strtou64/correct",
> +                    test_qemu_strtou64_correct);
> +    g_test_add_func("/cutils/qemu_strtou64/null",
> +                    test_qemu_strtou64_null);
> +    g_test_add_func("/cutils/qemu_strtou64/empty",
> +                    test_qemu_strtou64_empty);
> +    g_test_add_func("/cutils/qemu_strtou64/whitespace",
> +                    test_qemu_strtou64_whitespace);
> +    g_test_add_func("/cutils/qemu_strtou64/invalid",
> +                    test_qemu_strtou64_invalid);
> +    g_test_add_func("/cutils/qemu_strtou64/trailing",
> +                    test_qemu_strtou64_trailing);
> +    g_test_add_func("/cutils/qemu_strtou64/octal",
> +                    test_qemu_strtou64_octal);
> +    g_test_add_func("/cutils/qemu_strtou64/decimal",
> +                    test_qemu_strtou64_decimal);
> +    g_test_add_func("/cutils/qemu_strtou64/hex",
> +                    test_qemu_strtou64_hex);
> +    g_test_add_func("/cutils/qemu_strtou64/max",
> +                    test_qemu_strtou64_max);
> +    g_test_add_func("/cutils/qemu_strtou64/overflow",
> +                    test_qemu_strtou64_overflow);
> +    g_test_add_func("/cutils/qemu_strtou64/underflow",
> +                    test_qemu_strtou64_underflow);
> +    g_test_add_func("/cutils/qemu_strtou64/negative",
> +                    test_qemu_strtou64_negative);
> +    g_test_add_func("/cutils/qemu_strtou64_full/correct",
> +                    test_qemu_strtou64_full_correct);
> +    g_test_add_func("/cutils/qemu_strtou64_full/null",
> +                    test_qemu_strtou64_full_null);
> +    g_test_add_func("/cutils/qemu_strtou64_full/empty",
> +                    test_qemu_strtou64_full_empty);
> +    g_test_add_func("/cutils/qemu_strtou64_full/negative",
> +                    test_qemu_strtou64_full_negative);
> +    g_test_add_func("/cutils/qemu_strtou64_full/trailing",
> +                    test_qemu_strtou64_full_trailing);
> +    g_test_add_func("/cutils/qemu_strtou64_full/max",
> +                    test_qemu_strtou64_full_max);
>
>      g_test_add_func("/cutils/strtosz/simple",
>                      test_qemu_strtosz_simple);
> diff --git a/util/cutils.c b/util/cutils.c
> index 1ae2a08..0dc9b28 100644
> --- a/util/cutils.c
> +++ b/util/cutils.c
> @@ -372,7 +372,7 @@ int qemu_strtoul(const char *nptr, const char **endptr, int base,
>   * Works like qemu_strtol(), except it stores INT64_MAX on overflow,
>   * and INT_MIN on underflow.
>   */
> -int qemu_strtoll(const char *nptr, const char **endptr, int base,
> +int qemu_strtoi64(const char *nptr, const char **endptr, int base,
>                   int64_t *result)
>  {
>      char *p;
> @@ -396,7 +396,7 @@ int qemu_strtoll(const char *nptr, const char **endptr, int base,
>   *
>   * Works like qemu_strtoul(), except it stores UINT64_MAX on overflow.
>   */
> -int qemu_strtoull(const char *nptr, const char **endptr, int base,
> +int qemu_strtou64(const char *nptr, const char **endptr, int base,
>                    uint64_t *result)
>  {
>      char *p;
> diff --git a/util/log.c b/util/log.c
> index e077340..96f30dd 100644
> --- a/util/log.c
> +++ b/util/log.c
> @@ -183,13 +183,13 @@ void qemu_set_dfilter_ranges(const char *filter_spec, Error **errp)
>              goto out;
>          }
>
> -        if (qemu_strtoull(r, &e, 0, &r1val)
> +        if (qemu_strtou64(r, &e, 0, &r1val)
>              || e != range_op) {
>              error_setg(errp, "Invalid number to the left of %.*s",
>                         (int)(r2 - range_op), range_op);
>              goto out;
>          }
> -        if (qemu_strtoull(r2, NULL, 0, &r2val)) {
> +        if (qemu_strtou64(r2, NULL, 0, &r2val)) {
>              error_setg(errp, "Invalid number to the right of %.*s",
>                         (int)(r2 - range_op), range_op);
>              goto out;
>

^ permalink raw reply	[flat|nested] 79+ messages in thread

* Re: [Qemu-devel] [PATCH 10/24] tests/test-cutils: Add missing qemu_strtosz()... endptr checks
  2017-02-14 10:25 ` [Qemu-devel] [PATCH 10/24] tests/test-cutils: Add missing qemu_strtosz()... endptr checks Markus Armbruster
  2017-02-14 22:26   ` Eric Blake
@ 2017-02-19  4:16   ` Philippe Mathieu-Daudé
  1 sibling, 0 replies; 79+ messages in thread
From: Philippe Mathieu-Daudé @ 2017-02-19  4:16 UTC (permalink / raw)
  To: Markus Armbruster, qemu-devel

On 02/14/2017 07:25 AM, Markus Armbruster wrote:
> Signed-off-by: Markus Armbruster <armbru@redhat.com>

Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>

> ---
>  tests/test-cutils.c | 37 ++++++++++++++++++++++++++-----------
>  1 file changed, 26 insertions(+), 11 deletions(-)
>
> diff --git a/tests/test-cutils.c b/tests/test-cutils.c
> index 47cc8a4..2dc6832 100644
> --- a/tests/test-cutils.c
> +++ b/tests/test-cutils.c
> @@ -1393,60 +1393,75 @@ static void test_qemu_strtosz_units(void)
>      const char *t = "1T";
>      const char *p = "1P";
>      const char *e = "1E";
> +    char *endptr = NULL;
>      int64_t res;
>
>      /* default is M */
> -    res = qemu_strtosz(none, NULL);
> +    res = qemu_strtosz(none, &endptr);
>      g_assert_cmpint(res, ==, M_BYTE);
> +    g_assert(endptr == none + 1);
>
> -    res = qemu_strtosz(b, NULL);
> +    res = qemu_strtosz(b, &endptr);
>      g_assert_cmpint(res, ==, 1);
> +    g_assert(endptr == b + 2);
>
> -    res = qemu_strtosz(k, NULL);
> +    res = qemu_strtosz(k, &endptr);
>      g_assert_cmpint(res, ==, K_BYTE);
> +    g_assert(endptr == k + 2);
>
> -    res = qemu_strtosz(m, NULL);
> +    res = qemu_strtosz(m, &endptr);
>      g_assert_cmpint(res, ==, M_BYTE);
> +    g_assert(endptr == m + 2);
>
> -    res = qemu_strtosz(g, NULL);
> +    res = qemu_strtosz(g, &endptr);
>      g_assert_cmpint(res, ==, G_BYTE);
> +    g_assert(endptr == g + 2);
>
> -    res = qemu_strtosz(t, NULL);
> +    res = qemu_strtosz(t, &endptr);
>      g_assert_cmpint(res, ==, T_BYTE);
> +    g_assert(endptr == t + 2);
>
> -    res = qemu_strtosz(p, NULL);
> +    res = qemu_strtosz(p, &endptr);
>      g_assert_cmpint(res, ==, P_BYTE);
> +    g_assert(endptr == p + 2);
>
> -    res = qemu_strtosz(e, NULL);
> +    res = qemu_strtosz(e, &endptr);
>      g_assert_cmpint(res, ==, E_BYTE);
> +    g_assert(endptr == e + 2);
>  }
>
>  static void test_qemu_strtosz_float(void)
>  {
>      const char *str = "12.345M";
> +    char *endptr = NULL;
>      int64_t res;
>
> -    res = qemu_strtosz(str, NULL);
> +    res = qemu_strtosz(str, &endptr);
>      g_assert_cmpint(res, ==, 12.345 * M_BYTE);
> +    g_assert(endptr == str + 7);
>  }
>
>  static void test_qemu_strtosz_erange(void)
>  {
>      const char *str = "10E";
> +    char *endptr = NULL;
>      int64_t res;
>
> -    res = qemu_strtosz(str, NULL);
> +    res = qemu_strtosz(str, &endptr);
>      g_assert_cmpint(res, ==, -ERANGE);
> +    g_assert(endptr == str + 3);
>  }
>
>  static void test_qemu_strtosz_suffix_unit(void)
>  {
>      const char *str = "12345";
> +    char *endptr = NULL;
>      int64_t res;
>
> -    res = qemu_strtosz_suffix_unit(str, NULL,
> +    res = qemu_strtosz_suffix_unit(str, &endptr,
>                                     QEMU_STRTOSZ_DEFSUFFIX_KB, 1000);
>      g_assert_cmpint(res, ==, 12345000);
> +    g_assert(endptr == str + 5);
>  }
>
>  int main(int argc, char **argv)
>

^ permalink raw reply	[flat|nested] 79+ messages in thread

* Re: [Qemu-devel] [PATCH 17/24] util/cutils: Drop QEMU_STRTOSZ_DEFSUFFIX_* macros
  2017-02-14 10:26 ` [Qemu-devel] [PATCH 17/24] util/cutils: Drop QEMU_STRTOSZ_DEFSUFFIX_* macros Markus Armbruster
  2017-02-17 20:51   ` Eric Blake
@ 2017-02-19  4:21   ` Philippe Mathieu-Daudé
  1 sibling, 0 replies; 79+ messages in thread
From: Philippe Mathieu-Daudé @ 2017-02-19  4:21 UTC (permalink / raw)
  To: Markus Armbruster, qemu-devel


On 02/14/2017 07:26 AM, Markus Armbruster wrote:
> Writing QEMU_STRTOSZ_DEFSUFFIX_* instead of '*' gains nothing.  Get
> rid of these eyesores.
>
> Signed-off-by: Markus Armbruster <armbru@redhat.com>

Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>

> ---
>  util/cutils.c | 28 ++++++++++------------------
>  1 file changed, 10 insertions(+), 18 deletions(-)
>
> diff --git a/util/cutils.c b/util/cutils.c
> index ef658bb..4a290ea 100644
> --- a/util/cutils.c
> +++ b/util/cutils.c
> @@ -178,30 +178,22 @@ int fcntl_setfl(int fd, int flag)
>  }
>  #endif
>
> -#define QEMU_STRTOSZ_DEFSUFFIX_EB 'E'
> -#define QEMU_STRTOSZ_DEFSUFFIX_PB 'P'
> -#define QEMU_STRTOSZ_DEFSUFFIX_TB 'T'
> -#define QEMU_STRTOSZ_DEFSUFFIX_GB 'G'
> -#define QEMU_STRTOSZ_DEFSUFFIX_MB 'M'
> -#define QEMU_STRTOSZ_DEFSUFFIX_KB 'K'
> -#define QEMU_STRTOSZ_DEFSUFFIX_B 'B'
> -
>  static int64_t suffix_mul(char suffix, int64_t unit)
>  {
>      switch (qemu_toupper(suffix)) {
> -    case QEMU_STRTOSZ_DEFSUFFIX_B:
> +    case 'B':
>          return 1;
> -    case QEMU_STRTOSZ_DEFSUFFIX_KB:
> +    case 'K':
>          return unit;
> -    case QEMU_STRTOSZ_DEFSUFFIX_MB:
> +    case 'M':
>          return unit * unit;
> -    case QEMU_STRTOSZ_DEFSUFFIX_GB:
> +    case 'G':
>          return unit * unit * unit;
> -    case QEMU_STRTOSZ_DEFSUFFIX_TB:
> +    case 'T':
>          return unit * unit * unit * unit;
> -    case QEMU_STRTOSZ_DEFSUFFIX_PB:
> +    case 'P':
>          return unit * unit * unit * unit * unit;
> -    case QEMU_STRTOSZ_DEFSUFFIX_EB:
> +    case 'E':
>          return unit * unit * unit * unit * unit * unit;
>      }
>      return -1;
> @@ -258,17 +250,17 @@ fail:
>
>  int64_t qemu_strtosz(const char *nptr, char **end)
>  {
> -    return do_strtosz(nptr, end, QEMU_STRTOSZ_DEFSUFFIX_B, 1024);
> +    return do_strtosz(nptr, end, 'B', 1024);
>  }
>
>  int64_t qemu_strtosz_mebi(const char *nptr, char **end)
>  {
> -    return do_strtosz(nptr, end, QEMU_STRTOSZ_DEFSUFFIX_MB, 1024);
> +    return do_strtosz(nptr, end, 'M', 1024);
>  }
>
>  int64_t qemu_strtosz_metric(const char *nptr, char **end)
>  {
> -    return do_strtosz(nptr, end, QEMU_STRTOSZ_DEFSUFFIX_B, 1000);
> +    return do_strtosz(nptr, end, 'B', 1000);
>  }
>
>  /**
>

^ permalink raw reply	[flat|nested] 79+ messages in thread

* Re: [Qemu-devel] [PATCH 21/24] util/cutils: Let qemu_strtosz*() optionally reject trailing crap
  2017-02-14 10:26 ` [Qemu-devel] [PATCH 21/24] util/cutils: Let qemu_strtosz*() optionally reject trailing crap Markus Armbruster
  2017-02-17 21:21   ` Eric Blake
@ 2017-02-20 19:34   ` Dr. David Alan Gilbert
  2017-02-21  9:13     ` Markus Armbruster
  1 sibling, 1 reply; 79+ messages in thread
From: Dr. David Alan Gilbert @ 2017-02-20 19:34 UTC (permalink / raw)
  To: Markus Armbruster
  Cc: qemu-devel, Eduardo Habkost, Kevin Wolf, Max Reitz,
	open list:Block layer core

* Markus Armbruster (armbru@redhat.com) wrote:
> Change the qemu_strtosz() & friends to return -EINVAL when @endptr is
> null and the conversion doesn't consume the string completely.
> Matches how qemu_strtol() & friends work.
> 
> Only test_qemu_strtosz_simple() passes a null @endptr.  No functional
> change there, because its conversion consumes the string.
> 
> Simplify callers that use @endptr only to fail when it doesn't point
> to '\0' to pass a null @endptr instead.
> 
> Cc: Dr. David Alan Gilbert <dgilbert@redhat.com>
> Cc: Eduardo Habkost <ehabkost@redhat.com> (maintainer:X86)
> Cc: Kevin Wolf <kwolf@redhat.com> (supporter:Block layer core)
> Cc: Max Reitz <mreitz@redhat.com> (supporter:Block layer core)
> Cc: qemu-block@nongnu.org (open list:Block layer core)
> Signed-off-by: Markus Armbruster <armbru@redhat.com>

Reviewed-by: Dr. David Alan Gilbert <dgilbert@redhat.com>

(end and endptr are horribly confusing names in do_strtosz)

> ---
>  hmp.c               |  6 ++----
>  hw/misc/ivshmem.c   |  6 ++----
>  qapi/opts-visitor.c |  5 ++---
>  qemu-img.c          |  7 +------
>  qemu-io-cmds.c      |  7 +------
>  target/i386/cpu.c   |  5 ++---
>  tests/test-cutils.c |  6 ++++++
>  util/cutils.c       | 14 +++++++++-----
>  8 files changed, 25 insertions(+), 31 deletions(-)
> 
> diff --git a/hmp.c b/hmp.c
> index 6d0d05b..0eb5b6d 100644
> --- a/hmp.c
> +++ b/hmp.c
> @@ -1340,7 +1340,6 @@ void hmp_migrate_set_parameter(Monitor *mon, const QDict *qdict)
>      const char *valuestr = qdict_get_str(qdict, "value");
>      int64_t valuebw = 0;
>      long valueint = 0;
> -    char *endp;
>      Error *err = NULL;
>      bool use_int_value = false;
>      int i;
> @@ -1379,9 +1378,8 @@ void hmp_migrate_set_parameter(Monitor *mon, const QDict *qdict)
>                  break;
>              case MIGRATION_PARAMETER_MAX_BANDWIDTH:
>                  p.has_max_bandwidth = true;
> -                valuebw = qemu_strtosz_mebi(valuestr, &endp);
> -                if (valuebw < 0 || (size_t)valuebw != valuebw
> -                    || *endp != '\0') {
> +                valuebw = qemu_strtosz_mebi(valuestr, NULL);
> +                if (valuebw < 0 || (size_t)valuebw != valuebw) {
>                      error_setg(&err, "Invalid size %s", valuestr);
>                      goto cleanup;
>                  }
> diff --git a/hw/misc/ivshmem.c b/hw/misc/ivshmem.c
> index 382dd8b..f00cd75 100644
> --- a/hw/misc/ivshmem.c
> +++ b/hw/misc/ivshmem.c
> @@ -1267,10 +1267,8 @@ static void ivshmem_realize(PCIDevice *dev, Error **errp)
>      if (s->sizearg == NULL) {
>          s->legacy_size = 4 << 20; /* 4 MB default */
>      } else {
> -        char *end;
> -        int64_t size = qemu_strtosz_mebi(s->sizearg, &end);
> -        if (size < 0 || (size_t)size != size || *end != '\0'
> -            || !is_power_of_2(size)) {
> +        int64_t size = qemu_strtosz_mebi(s->sizearg, NULL);
> +        if (size < 0 || (size_t)size != size || !is_power_of_2(size)) {
>              error_setg(errp, "Invalid size %s", s->sizearg);
>              return;
>          }
> diff --git a/qapi/opts-visitor.c b/qapi/opts-visitor.c
> index 360d337..911a0ee 100644
> --- a/qapi/opts-visitor.c
> +++ b/qapi/opts-visitor.c
> @@ -482,15 +482,14 @@ opts_type_size(Visitor *v, const char *name, uint64_t *obj, Error **errp)
>      OptsVisitor *ov = to_ov(v);
>      const QemuOpt *opt;
>      int64_t val;
> -    char *endptr;
>  
>      opt = lookup_scalar(ov, name, errp);
>      if (!opt) {
>          return;
>      }
>  
> -    val = qemu_strtosz(opt->str ? opt->str : "", &endptr);
> -    if (val < 0 || *endptr) {
> +    val = qemu_strtosz(opt->str ? opt->str : "", NULL);
> +    if (val < 0) {
>          error_setg(errp, QERR_INVALID_PARAMETER_VALUE, opt->name,
>                     "a size value representible as a non-negative int64");
>          return;
> diff --git a/qemu-img.c b/qemu-img.c
> index 2a47966..adcb511 100644
> --- a/qemu-img.c
> +++ b/qemu-img.c
> @@ -370,14 +370,9 @@ static int add_old_style_options(const char *fmt, QemuOpts *opts,
>  
>  static int64_t cvtnum(const char *s)
>  {
> -    char *end;
>      int64_t ret;
>  
> -    ret = qemu_strtosz(s, &end);
> -    if (*end != '\0') {
> -        /* Detritus at the end of the string */
> -        return -EINVAL;
> -    }
> +    ret = qemu_strtosz(s, NULL);
>      return ret;
>  }
>  
> diff --git a/qemu-io-cmds.c b/qemu-io-cmds.c
> index 6b7a89c..417a4e0 100644
> --- a/qemu-io-cmds.c
> +++ b/qemu-io-cmds.c
> @@ -137,14 +137,9 @@ static char **breakline(char *input, int *count)
>  
>  static int64_t cvtnum(const char *s)
>  {
> -    char *end;
>      int64_t ret;
>  
> -    ret = qemu_strtosz(s, &end);
> -    if (*end != '\0') {
> -        /* Detritus at the end of the string */
> -        return -EINVAL;
> -    }
> +    ret = qemu_strtosz(s, NULL);
>      return ret;
>  }
>  
> diff --git a/target/i386/cpu.c b/target/i386/cpu.c
> index 3a8d72d..5cb0b4b 100644
> --- a/target/i386/cpu.c
> +++ b/target/i386/cpu.c
> @@ -2034,10 +2034,9 @@ static void x86_cpu_parse_featurestr(const char *typename, char *features,
>          /* Special case: */
>          if (!strcmp(name, "tsc-freq")) {
>              int64_t tsc_freq;
> -            char *err;
>  
> -            tsc_freq = qemu_strtosz_metric(val, &err);
> -            if (tsc_freq < 0 || *err) {
> +            tsc_freq = qemu_strtosz_metric(val, NULL);
> +            if (tsc_freq < 0) {
>                  error_setg(errp, "bad numerical value %s", val);
>                  return;
>              }
> diff --git a/tests/test-cutils.c b/tests/test-cutils.c
> index 585912b..07095e3 100644
> --- a/tests/test-cutils.c
> +++ b/tests/test-cutils.c
> @@ -1510,10 +1510,16 @@ static void test_qemu_strtosz_trailing(void)
>      g_assert_cmpint(res, ==, 123 * M_BYTE);
>      g_assert(endptr == str + 3);
>  
> +    res = qemu_strtosz(str, NULL);
> +    g_assert_cmpint(res, ==, -EINVAL);
> +
>      str = "1kiB";
>      res = qemu_strtosz(str, &endptr);
>      g_assert_cmpint(res, ==, 1024);
>      g_assert(endptr == str + 2);
> +
> +    res = qemu_strtosz(str, NULL);
> +    g_assert_cmpint(res, ==, -EINVAL);
>  }
>  
>  static void test_qemu_strtosz_erange(void)
> diff --git a/util/cutils.c b/util/cutils.c
> index 4a290ea..5c1bfe5 100644
> --- a/util/cutils.c
> +++ b/util/cutils.c
> @@ -208,7 +208,7 @@ static int64_t suffix_mul(char suffix, int64_t unit)
>  static int64_t do_strtosz(const char *nptr, char **end,
>                            const char default_suffix, int64_t unit)
>  {
> -    int64_t retval = -EINVAL;
> +    int64_t retval;
>      char *endptr;
>      unsigned char c;
>      int mul_required = 0;
> @@ -217,7 +217,8 @@ static int64_t do_strtosz(const char *nptr, char **end,
>      errno = 0;
>      val = strtod(nptr, &endptr);
>      if (isnan(val) || endptr == nptr || errno != 0) {
> -        goto fail;
> +        retval = -EINVAL;
> +        goto out;
>      }
>      fraction = modf(val, &integral);
>      if (fraction != 0) {
> @@ -232,17 +233,20 @@ static int64_t do_strtosz(const char *nptr, char **end,
>          assert(mul >= 0);
>      }
>      if (mul == 1 && mul_required) {
> -        goto fail;
> +        retval = -EINVAL;
> +        goto out;
>      }
>      if ((val * mul >= INT64_MAX) || val < 0) {
>          retval = -ERANGE;
> -        goto fail;
> +        goto out;
>      }
>      retval = val * mul;
>  
> -fail:
> +out:
>      if (end) {
>          *end = endptr;
> +    } else if (*endptr) {
> +        retval = -EINVAL;
>      }
>  
>      return retval;
> -- 
> 2.7.4
> 
--
Dr. David Alan Gilbert / dgilbert@redhat.com / Manchester, UK

^ permalink raw reply	[flat|nested] 79+ messages in thread

* Re: [Qemu-devel] [PATCH 22/24] util/cutils: Return qemu_strtosz*() error and value separately
  2017-02-14 10:26 ` [Qemu-devel] [PATCH 22/24] util/cutils: Return qemu_strtosz*() error and value separately Markus Armbruster
  2017-02-17 22:03   ` Eric Blake
@ 2017-02-20 19:52   ` Dr. David Alan Gilbert
  1 sibling, 0 replies; 79+ messages in thread
From: Dr. David Alan Gilbert @ 2017-02-20 19:52 UTC (permalink / raw)
  To: Markus Armbruster
  Cc: qemu-devel, Eduardo Habkost, Kevin Wolf, Max Reitz,
	open list:Block layer core

* Markus Armbruster (armbru@redhat.com) wrote:
> This makes qemu_strtosz(), qemu_strtosz_mebi() and
> qemu_strtosz_metric() similar to qemu_strtoi64(), except negative
> values are rejected.
> 
> Cc: Dr. David Alan Gilbert <dgilbert@redhat.com>
> Cc: Eduardo Habkost <ehabkost@redhat.com> (maintainer:X86)
> Cc: Kevin Wolf <kwolf@redhat.com> (supporter:Block layer core)
> Cc: Max Reitz <mreitz@redhat.com> (supporter:Block layer core)
> Cc: qemu-block@nongnu.org (open list:Block layer core)
> Signed-off-by: Markus Armbruster <armbru@redhat.com>

Reviewed-by: Dr. David Alan Gilbert <dgilbert@redhat.com>

> ---
>  hmp.c                 |   6 +--
>  hw/misc/ivshmem.c     |   7 ++-
>  include/qemu/cutils.h |   6 +--
>  monitor.c             |   5 ++-
>  qapi/opts-visitor.c   |   5 ++-
>  qemu-img.c            |  10 +++--
>  qemu-io-cmds.c        |  10 +++--
>  target/i386/cpu.c     |   5 ++-
>  tests/test-cutils.c   | 120 ++++++++++++++++++++++++++++++--------------------
>  util/cutils.c         |  22 ++++-----
>  10 files changed, 119 insertions(+), 77 deletions(-)
> 
> diff --git a/hmp.c b/hmp.c
> index 0eb5b6d..9846fa4 100644
> --- a/hmp.c
> +++ b/hmp.c
> @@ -1342,7 +1342,7 @@ void hmp_migrate_set_parameter(Monitor *mon, const QDict *qdict)
>      long valueint = 0;
>      Error *err = NULL;
>      bool use_int_value = false;
> -    int i;
> +    int i, ret;
>  
>      for (i = 0; i < MIGRATION_PARAMETER__MAX; i++) {
>          if (strcmp(param, MigrationParameter_lookup[i]) == 0) {
> @@ -1378,8 +1378,8 @@ void hmp_migrate_set_parameter(Monitor *mon, const QDict *qdict)
>                  break;
>              case MIGRATION_PARAMETER_MAX_BANDWIDTH:
>                  p.has_max_bandwidth = true;
> -                valuebw = qemu_strtosz_mebi(valuestr, NULL);
> -                if (valuebw < 0 || (size_t)valuebw != valuebw) {
> +                ret = qemu_strtosz_mebi(valuestr, NULL, &valuebw);
> +                if (ret < 0 || (size_t)valuebw != valuebw) {
>                      error_setg(&err, "Invalid size %s", valuestr);
>                      goto cleanup;
>                  }
> diff --git a/hw/misc/ivshmem.c b/hw/misc/ivshmem.c
> index f00cd75..3dc04f4 100644
> --- a/hw/misc/ivshmem.c
> +++ b/hw/misc/ivshmem.c
> @@ -1267,8 +1267,11 @@ static void ivshmem_realize(PCIDevice *dev, Error **errp)
>      if (s->sizearg == NULL) {
>          s->legacy_size = 4 << 20; /* 4 MB default */
>      } else {
> -        int64_t size = qemu_strtosz_mebi(s->sizearg, NULL);
> -        if (size < 0 || (size_t)size != size || !is_power_of_2(size)) {
> +        int ret;
> +        int64_t size;
> +
> +        ret = qemu_strtosz_mebi(s->sizearg, NULL, &size);
> +        if (ret < 0 || (size_t)size != size || !is_power_of_2(size)) {
>              error_setg(errp, "Invalid size %s", s->sizearg);
>              return;
>          }
> diff --git a/include/qemu/cutils.h b/include/qemu/cutils.h
> index 4184851..c91649b 100644
> --- a/include/qemu/cutils.h
> +++ b/include/qemu/cutils.h
> @@ -139,9 +139,9 @@ int parse_uint(const char *s, unsigned long long *value, char **endptr,
>                 int base);
>  int parse_uint_full(const char *s, unsigned long long *value, int base);
>  
> -int64_t qemu_strtosz(const char *nptr, char **end);
> -int64_t qemu_strtosz_mebi(const char *nptr, char **end);
> -int64_t qemu_strtosz_metric(const char *nptr, char **end);
> +int qemu_strtosz(const char *nptr, char **end, int64_t *result);
> +int qemu_strtosz_mebi(const char *nptr, char **end, int64_t *result);
> +int qemu_strtosz_metric(const char *nptr, char **end, int64_t *result);
>  
>  #define K_BYTE     (1ULL << 10)
>  #define M_BYTE     (1ULL << 20)
> diff --git a/monitor.c b/monitor.c
> index 1f8c031..85b1b61 100644
> --- a/monitor.c
> +++ b/monitor.c
> @@ -2773,6 +2773,7 @@ static QDict *monitor_parse_arguments(Monitor *mon,
>              break;
>          case 'o':
>              {
> +                int ret;
>                  int64_t val;
>                  char *end;
>  
> @@ -2785,8 +2786,8 @@ static QDict *monitor_parse_arguments(Monitor *mon,
>                          break;
>                      }
>                  }
> -                val = qemu_strtosz_mebi(p, &end);
> -                if (val < 0) {
> +                ret = qemu_strtosz_mebi(p, &end, &val);
> +                if (ret < 0) {
>                      monitor_printf(mon, "invalid size\n");
>                      goto fail;
>                  }
> diff --git a/qapi/opts-visitor.c b/qapi/opts-visitor.c
> index 911a0ee..aac2e09 100644
> --- a/qapi/opts-visitor.c
> +++ b/qapi/opts-visitor.c
> @@ -482,14 +482,15 @@ opts_type_size(Visitor *v, const char *name, uint64_t *obj, Error **errp)
>      OptsVisitor *ov = to_ov(v);
>      const QemuOpt *opt;
>      int64_t val;
> +    int err;
>  
>      opt = lookup_scalar(ov, name, errp);
>      if (!opt) {
>          return;
>      }
>  
> -    val = qemu_strtosz(opt->str ? opt->str : "", NULL);
> -    if (val < 0) {
> +    err = qemu_strtosz(opt->str ? opt->str : "", NULL, &val);
> +    if (err < 0) {
>          error_setg(errp, QERR_INVALID_PARAMETER_VALUE, opt->name,
>                     "a size value representible as a non-negative int64");
>          return;
> diff --git a/qemu-img.c b/qemu-img.c
> index adcb511..89ced5a 100644
> --- a/qemu-img.c
> +++ b/qemu-img.c
> @@ -370,10 +370,14 @@ static int add_old_style_options(const char *fmt, QemuOpts *opts,
>  
>  static int64_t cvtnum(const char *s)
>  {
> -    int64_t ret;
> +    int err;
> +    int64_t value;
>  
> -    ret = qemu_strtosz(s, NULL);
> -    return ret;
> +    err = qemu_strtosz(s, NULL, &value);
> +    if (err < 0) {
> +        return err;
> +    }
> +    return value;
>  }
>  
>  static int img_create(int argc, char **argv)
> diff --git a/qemu-io-cmds.c b/qemu-io-cmds.c
> index 417a4e0..d9f3e93 100644
> --- a/qemu-io-cmds.c
> +++ b/qemu-io-cmds.c
> @@ -137,10 +137,14 @@ static char **breakline(char *input, int *count)
>  
>  static int64_t cvtnum(const char *s)
>  {
> -    int64_t ret;
> +    int err;
> +    int64_t value;
>  
> -    ret = qemu_strtosz(s, NULL);
> -    return ret;
> +    err = qemu_strtosz(s, NULL, &value);
> +    if (err < 0) {
> +        return err;
> +    }
> +    return value;
>  }
>  
>  static void print_cvtnum_err(int64_t rc, const char *arg)
> diff --git a/target/i386/cpu.c b/target/i386/cpu.c
> index 5cb0b4b..5f85410 100644
> --- a/target/i386/cpu.c
> +++ b/target/i386/cpu.c
> @@ -2033,10 +2033,11 @@ static void x86_cpu_parse_featurestr(const char *typename, char *features,
>  
>          /* Special case: */
>          if (!strcmp(name, "tsc-freq")) {
> +            int ret;
>              int64_t tsc_freq;
>  
> -            tsc_freq = qemu_strtosz_metric(val, NULL);
> -            if (tsc_freq < 0) {
> +            ret = qemu_strtosz_metric(val, NULL, &tsc_freq);
> +            if (ret < 0) {
>                  error_setg(errp, "bad numerical value %s", val);
>                  return;
>              }
> diff --git a/tests/test-cutils.c b/tests/test-cutils.c
> index 07095e3..9c2eed3 100644
> --- a/tests/test-cutils.c
> +++ b/tests/test-cutils.c
> @@ -1373,45 +1373,54 @@ static void test_qemu_strtosz_simple(void)
>  {
>      const char *str;
>      char *endptr = NULL;
> -    int64_t res;
> +    int err;
> +    int64_t res = 0xbaadf00d;
>  
>      str = "0";
> -    res = qemu_strtosz(str, &endptr);
> +    err = qemu_strtosz(str, &endptr, &res);
> +    g_assert_cmpint(err, ==, 0);
>      g_assert_cmpint(res, ==, 0);
>      g_assert(endptr == str + 1);
>  
>      str = "12345";
> -    res = qemu_strtosz(str, &endptr);
> +    err = qemu_strtosz(str, &endptr, &res);
> +    g_assert_cmpint(err, ==, 0);
>      g_assert_cmpint(res, ==, 12345);
>      g_assert(endptr == str + 5);
>  
> -    res = qemu_strtosz(str, NULL);
> +    err = qemu_strtosz(str, NULL, &res);
> +    g_assert_cmpint(err, ==, 0);
>      g_assert_cmpint(res, ==, 12345);
>  
>      /* Note: precision is 53 bits since we're parsing with strtod() */
>  
>      str = "9007199254740991"; /* 2^53-1 */
> -    res = qemu_strtosz(str, &endptr);
> +    err = qemu_strtosz(str, &endptr, &res);
> +    g_assert_cmpint(err, ==, 0);
>      g_assert_cmpint(res, ==, 0x1fffffffffffff);
>      g_assert(endptr == str + 16);
>  
>      str = "9007199254740992"; /* 2^53 */
> -    res = qemu_strtosz(str, &endptr);
> +    err = qemu_strtosz(str, &endptr, &res);
> +    g_assert_cmpint(err, ==, 0);
>      g_assert_cmpint(res, ==, 0x20000000000000);
>      g_assert(endptr == str + 16);
>  
>      str = "9007199254740993"; /* 2^53+1 */
> -    res = qemu_strtosz(str, &endptr);
> +    err = qemu_strtosz(str, &endptr, &res);
> +    g_assert_cmpint(err, ==, 0);
>      g_assert_cmpint(res, ==, 0x20000000000000); /* rounded to 53 bits */
>      g_assert(endptr == str + 16);
>  
>      str = "9223372036854774784"; /* 0x7ffffffffffffc00 (53 msbs set) */
> -    res = qemu_strtosz(str, &endptr);
> +    err = qemu_strtosz(str, &endptr, &res);
> +    g_assert_cmpint(err, ==, 0);
>      g_assert_cmpint(res, ==, 0x7ffffffffffffc00);
>      g_assert(endptr == str + 19);
>  
>      str = "9223372036854775295"; /* 0x7ffffffffffffdff */
> -    res = qemu_strtosz(str, &endptr);
> +    err = qemu_strtosz(str, &endptr, &res);
> +    g_assert_cmpint(err, ==, 0);
>      g_assert_cmpint(res, ==, 0x7ffffffffffffc00); /* rounded to 53 bits */
>      g_assert(endptr == str + 19);
>  
> @@ -1429,39 +1438,48 @@ static void test_qemu_strtosz_units(void)
>      const char *t = "1T";
>      const char *p = "1P";
>      const char *e = "1E";
> +    int err;
>      char *endptr = NULL;
> -    int64_t res;
> +    int64_t res = 0xbaadf00d;
>  
>      /* default is M */
> -    res = qemu_strtosz_mebi(none, &endptr);
> +    err = qemu_strtosz_mebi(none, &endptr, &res);
> +    g_assert_cmpint(err, ==, 0);
>      g_assert_cmpint(res, ==, M_BYTE);
>      g_assert(endptr == none + 1);
>  
> -    res = qemu_strtosz(b, &endptr);
> +    err = qemu_strtosz(b, &endptr, &res);
> +    g_assert_cmpint(err, ==, 0);
>      g_assert_cmpint(res, ==, 1);
>      g_assert(endptr == b + 2);
>  
> -    res = qemu_strtosz(k, &endptr);
> +    err = qemu_strtosz(k, &endptr, &res);
> +    g_assert_cmpint(err, ==, 0);
>      g_assert_cmpint(res, ==, K_BYTE);
>      g_assert(endptr == k + 2);
>  
> -    res = qemu_strtosz(m, &endptr);
> +    err = qemu_strtosz(m, &endptr, &res);
> +    g_assert_cmpint(err, ==, 0);
>      g_assert_cmpint(res, ==, M_BYTE);
>      g_assert(endptr == m + 2);
>  
> -    res = qemu_strtosz(g, &endptr);
> +    err = qemu_strtosz(g, &endptr, &res);
> +    g_assert_cmpint(err, ==, 0);
>      g_assert_cmpint(res, ==, G_BYTE);
>      g_assert(endptr == g + 2);
>  
> -    res = qemu_strtosz(t, &endptr);
> +    err = qemu_strtosz(t, &endptr, &res);
> +    g_assert_cmpint(err, ==, 0);
>      g_assert_cmpint(res, ==, T_BYTE);
>      g_assert(endptr == t + 2);
>  
> -    res = qemu_strtosz(p, &endptr);
> +    err = qemu_strtosz(p, &endptr, &res);
> +    g_assert_cmpint(err, ==, 0);
>      g_assert_cmpint(res, ==, P_BYTE);
>      g_assert(endptr == p + 2);
>  
> -    res = qemu_strtosz(e, &endptr);
> +    err = qemu_strtosz(e, &endptr, &res);
> +    g_assert_cmpint(err, ==, 0);
>      g_assert_cmpint(res, ==, E_BYTE);
>      g_assert(endptr == e + 2);
>  }
> @@ -1469,10 +1487,12 @@ static void test_qemu_strtosz_units(void)
>  static void test_qemu_strtosz_float(void)
>  {
>      const char *str = "12.345M";
> +    int err;
>      char *endptr = NULL;
> -    int64_t res;
> +    int64_t res = 0xbaadf00d;
>  
> -    res = qemu_strtosz(str, &endptr);
> +    err = qemu_strtosz(str, &endptr, &res);
> +    g_assert_cmpint(err, ==, 0);
>      g_assert_cmpint(res, ==, 12.345 * M_BYTE);
>      g_assert(endptr == str + 7);
>  }
> @@ -1481,21 +1501,22 @@ static void test_qemu_strtosz_invalid(void)
>  {
>      const char *str;
>      char *endptr = NULL;
> -    int64_t res;
> +    int err;
> +    int64_t res = 0xbaadf00d;
>  
>      str = "";
> -    res = qemu_strtosz(str, &endptr);
> -    g_assert_cmpint(res, ==, -EINVAL);
> +    err = qemu_strtosz(str, &endptr, &res);
> +    g_assert_cmpint(err, ==, -EINVAL);
>      g_assert(endptr == str);
>  
>      str = " \t ";
> -    res = qemu_strtosz(str, &endptr);
> -    g_assert_cmpint(res, ==, -EINVAL);
> +    err = qemu_strtosz(str, &endptr, &res);
> +    g_assert_cmpint(err, ==, -EINVAL);
>      g_assert(endptr == str);
>  
>      str = "crap";
> -    res = qemu_strtosz(str, &endptr);
> -    g_assert_cmpint(res, ==, -EINVAL);
> +    err = qemu_strtosz(str, &endptr, &res);
> +    g_assert_cmpint(err, ==, -EINVAL);
>      g_assert(endptr == str);
>  }
>  
> @@ -1503,64 +1524,69 @@ static void test_qemu_strtosz_trailing(void)
>  {
>      const char *str;
>      char *endptr = NULL;
> -    int64_t res;
> +    int err;
> +    int64_t res = 0xbaadf00d;
>  
>      str = "123xxx";
> -    res = qemu_strtosz_mebi(str, &endptr);
> +    err = qemu_strtosz_mebi(str, &endptr, &res);
>      g_assert_cmpint(res, ==, 123 * M_BYTE);
>      g_assert(endptr == str + 3);
>  
> -    res = qemu_strtosz(str, NULL);
> -    g_assert_cmpint(res, ==, -EINVAL);
> +    err = qemu_strtosz(str, NULL, &res);
> +    g_assert_cmpint(err, ==, -EINVAL);
>  
>      str = "1kiB";
> -    res = qemu_strtosz(str, &endptr);
> +    err = qemu_strtosz(str, &endptr, &res);
> +    g_assert_cmpint(err, ==, 0);
>      g_assert_cmpint(res, ==, 1024);
>      g_assert(endptr == str + 2);
>  
> -    res = qemu_strtosz(str, NULL);
> -    g_assert_cmpint(res, ==, -EINVAL);
> +    err = qemu_strtosz(str, NULL, &res);
> +    g_assert_cmpint(err, ==, -EINVAL);
>  }
>  
>  static void test_qemu_strtosz_erange(void)
>  {
>      const char *str;
>      char *endptr = NULL;
> -    int64_t res;
> +    int err;
> +    int64_t res = 0xbaadf00d;
>  
>      str = "-1";
> -    res = qemu_strtosz(str, &endptr);
> -    g_assert_cmpint(res, ==, -ERANGE);
> +    err = qemu_strtosz(str, &endptr, &res);
> +    g_assert_cmpint(err, ==, -ERANGE);
>      g_assert(endptr == str + 2);
>  
>      str = "9223372036854775296"; /* 0x7ffffffffffffe00 */
> -    res = qemu_strtosz(str, &endptr);
> -    g_assert_cmpint(res, ==, -ERANGE);
> +    err = qemu_strtosz(str, &endptr, &res);
> +    g_assert_cmpint(err, ==, -ERANGE);
>      g_assert(endptr == str + 19);
>  
>      str = "9223372036854775807"; /* 2^63-1 */
> -    res = qemu_strtosz(str, &endptr);
> -    g_assert_cmpint(res, ==, -ERANGE);
> +    err = qemu_strtosz(str, &endptr, &res);
> +    g_assert_cmpint(err, ==, -ERANGE);
>      g_assert(endptr == str + 19);
>  
>      str = "9223372036854775808"; /* 2^63 */
> -    res = qemu_strtosz(str, &endptr);
> -    g_assert_cmpint(res, ==, -ERANGE);
> +    err = qemu_strtosz(str, &endptr, &res);
> +    g_assert_cmpint(err, ==, -ERANGE);
>      g_assert(endptr == str + 19);
>  
>      str = "10E";
> -    res = qemu_strtosz(str, &endptr);
> -    g_assert_cmpint(res, ==, -ERANGE);
> +    err = qemu_strtosz(str, &endptr, &res);
> +    g_assert_cmpint(err, ==, -ERANGE);
>      g_assert(endptr == str + 3);
>  }
>  
>  static void test_qemu_strtosz_metric(void)
>  {
>      const char *str = "12345k";
> +    int err;
>      char *endptr = NULL;
> -    int64_t res;
> +    int64_t res = 0xbaadf00d;
>  
> -    res = qemu_strtosz_metric(str, &endptr);
> +    err = qemu_strtosz_metric(str, &endptr, &res);
> +    g_assert_cmpint(err, ==, 0);
>      g_assert_cmpint(res, ==, 12345000);
>      g_assert(endptr == str + 6);
>  }
> diff --git a/util/cutils.c b/util/cutils.c
> index 5c1bfe5..08effe6 100644
> --- a/util/cutils.c
> +++ b/util/cutils.c
> @@ -205,10 +205,11 @@ static int64_t suffix_mul(char suffix, int64_t unit)
>   * in *end, if not NULL. Return -ERANGE on overflow, Return -EINVAL on
>   * other error.
>   */
> -static int64_t do_strtosz(const char *nptr, char **end,
> -                          const char default_suffix, int64_t unit)
> +static int do_strtosz(const char *nptr, char **end,
> +                      const char default_suffix, int64_t unit,
> +                      int64_t *result)
>  {
> -    int64_t retval;
> +    int retval;
>      char *endptr;
>      unsigned char c;
>      int mul_required = 0;
> @@ -240,7 +241,8 @@ static int64_t do_strtosz(const char *nptr, char **end,
>          retval = -ERANGE;
>          goto out;
>      }
> -    retval = val * mul;
> +    *result = val * mul;
> +    retval = 0;
>  
>  out:
>      if (end) {
> @@ -252,19 +254,19 @@ out:
>      return retval;
>  }
>  
> -int64_t qemu_strtosz(const char *nptr, char **end)
> +int qemu_strtosz(const char *nptr, char **end, int64_t *result)
>  {
> -    return do_strtosz(nptr, end, 'B', 1024);
> +    return do_strtosz(nptr, end, 'B', 1024, result);
>  }
>  
> -int64_t qemu_strtosz_mebi(const char *nptr, char **end)
> +int qemu_strtosz_mebi(const char *nptr, char **end, int64_t *result)
>  {
> -    return do_strtosz(nptr, end, 'M', 1024);
> +    return do_strtosz(nptr, end, 'M', 1024, result);
>  }
>  
> -int64_t qemu_strtosz_metric(const char *nptr, char **end)
> +int qemu_strtosz_metric(const char *nptr, char **end, int64_t *result)
>  {
> -    return do_strtosz(nptr, end, 'B', 1000);
> +    return do_strtosz(nptr, end, 'B', 1000, result);
>  }
>  
>  /**
> -- 
> 2.7.4
> 
--
Dr. David Alan Gilbert / dgilbert@redhat.com / Manchester, UK

^ permalink raw reply	[flat|nested] 79+ messages in thread

* Re: [Qemu-devel] [PATCH 23/24] util/cutils: Change qemu_strtosz*() from int64_t to uint64_t
  2017-02-14 10:26 ` [Qemu-devel] [PATCH 23/24] util/cutils: Change qemu_strtosz*() from int64_t to uint64_t Markus Armbruster
  2017-02-17 22:19   ` Eric Blake
@ 2017-02-20 20:16   ` Dr. David Alan Gilbert
  2017-02-21  8:40     ` Paolo Bonzini
  2017-02-21  9:25     ` Markus Armbruster
  1 sibling, 2 replies; 79+ messages in thread
From: Dr. David Alan Gilbert @ 2017-02-20 20:16 UTC (permalink / raw)
  To: Markus Armbruster
  Cc: qemu-devel, Eduardo Habkost, Kevin Wolf, Max Reitz,
	open list:Block layer core

* Markus Armbruster (armbru@redhat.com) wrote:
> This will permit its use in parse_option_size().
> 
> Cc: Dr. David Alan Gilbert <dgilbert@redhat.com>
> Cc: Eduardo Habkost <ehabkost@redhat.com> (maintainer:X86)
> Cc: Kevin Wolf <kwolf@redhat.com> (supporter:Block layer core)
> Cc: Max Reitz <mreitz@redhat.com> (supporter:Block layer core)
> Cc: qemu-block@nongnu.org (open list:Block layer core)
> Signed-off-by: Markus Armbruster <armbru@redhat.com>
> ---
>  hmp.c                 |  5 +++--
>  hw/misc/ivshmem.c     |  2 +-
>  include/qemu/cutils.h |  6 +++---
>  monitor.c             |  4 ++--
>  qapi/opts-visitor.c   |  6 ++----
>  qemu-img.c            |  5 ++++-
>  qemu-io-cmds.c        |  5 ++++-
>  target/i386/cpu.c     |  4 ++--
>  tests/test-cutils.c   | 40 ++++++++++++++++++++--------------------
>  util/cutils.c         | 14 +++++++++-----
>  10 files changed, 50 insertions(+), 41 deletions(-)
> 
> diff --git a/hmp.c b/hmp.c
> index 9846fa4..5b9e461 100644
> --- a/hmp.c
> +++ b/hmp.c
> @@ -1338,7 +1338,7 @@ void hmp_migrate_set_parameter(Monitor *mon, const QDict *qdict)
>  {
>      const char *param = qdict_get_str(qdict, "parameter");
>      const char *valuestr = qdict_get_str(qdict, "value");
> -    int64_t valuebw = 0;
> +    uint64_t valuebw = 0;
>      long valueint = 0;
>      Error *err = NULL;
>      bool use_int_value = false;
> @@ -1379,7 +1379,8 @@ void hmp_migrate_set_parameter(Monitor *mon, const QDict *qdict)
>              case MIGRATION_PARAMETER_MAX_BANDWIDTH:
>                  p.has_max_bandwidth = true;
>                  ret = qemu_strtosz_mebi(valuestr, NULL, &valuebw);
> -                if (ret < 0 || (size_t)valuebw != valuebw) {
> +                if (ret < 0 || valuebw > INT64_MAX
> +                    || (size_t)valuebw != valuebw) {

We should probably just turn all of the parameters into size_t's - although that's
more work and there's some int64_t's in qemu_file for no good reason.

>                      error_setg(&err, "Invalid size %s", valuestr);
>                      goto cleanup;
>                  }
> diff --git a/hw/misc/ivshmem.c b/hw/misc/ivshmem.c
> index 3dc04f4..ba0cc22 100644
> --- a/hw/misc/ivshmem.c
> +++ b/hw/misc/ivshmem.c
> @@ -1268,7 +1268,7 @@ static void ivshmem_realize(PCIDevice *dev, Error **errp)
>          s->legacy_size = 4 << 20; /* 4 MB default */
>      } else {
>          int ret;
> -        int64_t size;
> +        uint64_t size;
>  
>          ret = qemu_strtosz_mebi(s->sizearg, NULL, &size);
>          if (ret < 0 || (size_t)size != size || !is_power_of_2(size)) {
> diff --git a/include/qemu/cutils.h b/include/qemu/cutils.h
> index c91649b..476d274 100644
> --- a/include/qemu/cutils.h
> +++ b/include/qemu/cutils.h
> @@ -139,9 +139,9 @@ int parse_uint(const char *s, unsigned long long *value, char **endptr,
>                 int base);
>  int parse_uint_full(const char *s, unsigned long long *value, int base);
>  
> -int qemu_strtosz(const char *nptr, char **end, int64_t *result);
> -int qemu_strtosz_mebi(const char *nptr, char **end, int64_t *result);
> -int qemu_strtosz_metric(const char *nptr, char **end, int64_t *result);
> +int qemu_strtosz(const char *nptr, char **end, uint64_t *result);
> +int qemu_strtosz_mebi(const char *nptr, char **end, uint64_t *result);
> +int qemu_strtosz_metric(const char *nptr, char **end, uint64_t *result);
>  
>  #define K_BYTE     (1ULL << 10)
>  #define M_BYTE     (1ULL << 20)
> diff --git a/monitor.c b/monitor.c
> index 85b1b61..1008ced 100644
> --- a/monitor.c
> +++ b/monitor.c
> @@ -2774,7 +2774,7 @@ static QDict *monitor_parse_arguments(Monitor *mon,
>          case 'o':
>              {
>                  int ret;
> -                int64_t val;
> +                uint64_t val;
>                  char *end;
>  
>                  while (qemu_isspace(*p)) {
> @@ -2787,7 +2787,7 @@ static QDict *monitor_parse_arguments(Monitor *mon,
>                      }
>                  }
>                  ret = qemu_strtosz_mebi(p, &end, &val);
> -                if (ret < 0) {
> +                if (ret < 0 || val > INT64_MAX) {
>                      monitor_printf(mon, "invalid size\n");
>                      goto fail;
>                  }
> diff --git a/qapi/opts-visitor.c b/qapi/opts-visitor.c
> index aac2e09..a0a7c0e 100644
> --- a/qapi/opts-visitor.c
> +++ b/qapi/opts-visitor.c
> @@ -481,7 +481,6 @@ opts_type_size(Visitor *v, const char *name, uint64_t *obj, Error **errp)
>  {
>      OptsVisitor *ov = to_ov(v);
>      const QemuOpt *opt;
> -    int64_t val;
>      int err;
>  
>      opt = lookup_scalar(ov, name, errp);
> @@ -489,14 +488,13 @@ opts_type_size(Visitor *v, const char *name, uint64_t *obj, Error **errp)
>          return;
>      }
>  
> -    err = qemu_strtosz(opt->str ? opt->str : "", NULL, &val);
> +    err = qemu_strtosz(opt->str ? opt->str : "", NULL, obj);
>      if (err < 0) {
>          error_setg(errp, QERR_INVALID_PARAMETER_VALUE, opt->name,
> -                   "a size value representible as a non-negative int64");
> +                   "a size value");
>          return;
>      }
>  
> -    *obj = val;
>      processed(ov, name);
>  }
>  
> diff --git a/qemu-img.c b/qemu-img.c
> index 89ced5a..b10ea66 100644
> --- a/qemu-img.c
> +++ b/qemu-img.c
> @@ -371,12 +371,15 @@ static int add_old_style_options(const char *fmt, QemuOpts *opts,
>  static int64_t cvtnum(const char *s)
>  {
>      int err;
> -    int64_t value;
> +    uint64_t value;
>  
>      err = qemu_strtosz(s, NULL, &value);
>      if (err < 0) {
>          return err;
>      }
> +    if (value > INT64_MAX) {
> +        return -ERANGE;
> +    }
>      return value;
>  }
>  
> diff --git a/qemu-io-cmds.c b/qemu-io-cmds.c
> index d9f3e93..1b01160 100644
> --- a/qemu-io-cmds.c
> +++ b/qemu-io-cmds.c
> @@ -138,12 +138,15 @@ static char **breakline(char *input, int *count)
>  static int64_t cvtnum(const char *s)
>  {
>      int err;
> -    int64_t value;
> +    uint64_t value;
>  
>      err = qemu_strtosz(s, NULL, &value);
>      if (err < 0) {
>          return err;
>      }
> +    if (value > INT64_MAX) {
> +        return -ERANGE;
> +    }
>      return value;
>  }
>  
> diff --git a/target/i386/cpu.c b/target/i386/cpu.c
> index 5f85410..e15f6bf 100644
> --- a/target/i386/cpu.c
> +++ b/target/i386/cpu.c
> @@ -2034,10 +2034,10 @@ static void x86_cpu_parse_featurestr(const char *typename, char *features,
>          /* Special case: */
>          if (!strcmp(name, "tsc-freq")) {
>              int ret;
> -            int64_t tsc_freq;
> +            uint64_t tsc_freq;
>  
>              ret = qemu_strtosz_metric(val, NULL, &tsc_freq);
> -            if (ret < 0) {
> +            if (ret < 0 || tsc_freq > INT64_MAX) {
>                  error_setg(errp, "bad numerical value %s", val);
>                  return;
>              }
> diff --git a/tests/test-cutils.c b/tests/test-cutils.c
> index 9c2eed3..ebc1da2 100644
> --- a/tests/test-cutils.c
> +++ b/tests/test-cutils.c
> @@ -1374,7 +1374,7 @@ static void test_qemu_strtosz_simple(void)
>      const char *str;
>      char *endptr = NULL;
>      int err;
> -    int64_t res = 0xbaadf00d;
> +    uint64_t res = 0xbaadf00d;
>  
>      str = "0";
>      err = qemu_strtosz(str, &endptr, &res);
> @@ -1412,17 +1412,17 @@ static void test_qemu_strtosz_simple(void)
>      g_assert_cmpint(res, ==, 0x20000000000000); /* rounded to 53 bits */
>      g_assert(endptr == str + 16);
>  
> -    str = "9223372036854774784"; /* 0x7ffffffffffffc00 (53 msbs set) */
> +    str = "18446744073709549568"; /* 0xfffffffffffff800 (53 msbs set) */
>      err = qemu_strtosz(str, &endptr, &res);
>      g_assert_cmpint(err, ==, 0);
> -    g_assert_cmpint(res, ==, 0x7ffffffffffffc00);
> -    g_assert(endptr == str + 19);
> +    g_assert_cmpint(res, ==, 0xfffffffffffff800);
> +    g_assert(endptr == str + 20);
>  
> -    str = "9223372036854775295"; /* 0x7ffffffffffffdff */
> +    str = "18446744073709550591"; /* 0xfffffffffffffbff */
>      err = qemu_strtosz(str, &endptr, &res);
>      g_assert_cmpint(err, ==, 0);
> -    g_assert_cmpint(res, ==, 0x7ffffffffffffc00); /* rounded to 53 bits */
> -    g_assert(endptr == str + 19);
> +    g_assert_cmpint(res, ==, 0xfffffffffffff800); /* rounded to 53 bits */
> +    g_assert(endptr == str + 20);
>  
>      /* 0x7ffffffffffffe00..0x7fffffffffffffff get rounded to
>       * 0x8000000000000000, thus -ERANGE; see test_qemu_strtosz_erange() */
> @@ -1440,7 +1440,7 @@ static void test_qemu_strtosz_units(void)
>      const char *e = "1E";
>      int err;
>      char *endptr = NULL;
> -    int64_t res = 0xbaadf00d;
> +    uint64_t res = 0xbaadf00d;
>  
>      /* default is M */
>      err = qemu_strtosz_mebi(none, &endptr, &res);
> @@ -1489,7 +1489,7 @@ static void test_qemu_strtosz_float(void)
>      const char *str = "12.345M";
>      int err;
>      char *endptr = NULL;
> -    int64_t res = 0xbaadf00d;
> +    uint64_t res = 0xbaadf00d;
>  
>      err = qemu_strtosz(str, &endptr, &res);
>      g_assert_cmpint(err, ==, 0);
> @@ -1502,7 +1502,7 @@ static void test_qemu_strtosz_invalid(void)
>      const char *str;
>      char *endptr = NULL;
>      int err;
> -    int64_t res = 0xbaadf00d;
> +    uint64_t res = 0xbaadf00d;
>  
>      str = "";
>      err = qemu_strtosz(str, &endptr, &res);
> @@ -1525,7 +1525,7 @@ static void test_qemu_strtosz_trailing(void)
>      const char *str;
>      char *endptr = NULL;
>      int err;
> -    int64_t res = 0xbaadf00d;
> +    uint64_t res = 0xbaadf00d;
>  
>      str = "123xxx";
>      err = qemu_strtosz_mebi(str, &endptr, &res);
> @@ -1550,29 +1550,29 @@ static void test_qemu_strtosz_erange(void)
>      const char *str;
>      char *endptr = NULL;
>      int err;
> -    int64_t res = 0xbaadf00d;
> +    uint64_t res = 0xbaadf00d;
>  
>      str = "-1";
>      err = qemu_strtosz(str, &endptr, &res);
>      g_assert_cmpint(err, ==, -ERANGE);
>      g_assert(endptr == str + 2);
>  
> -    str = "9223372036854775296"; /* 0x7ffffffffffffe00 */
> +    str = "18446744073709550592"; /* 0xfffffffffffffc00 */
>      err = qemu_strtosz(str, &endptr, &res);
>      g_assert_cmpint(err, ==, -ERANGE);
> -    g_assert(endptr == str + 19);
> +    g_assert(endptr == str + 20);
>  
> -    str = "9223372036854775807"; /* 2^63-1 */
> +    str = "18446744073709551615"; /* 2^64-1 */
>      err = qemu_strtosz(str, &endptr, &res);
>      g_assert_cmpint(err, ==, -ERANGE);
> -    g_assert(endptr == str + 19);
> +    g_assert(endptr == str + 20);
>  
> -    str = "9223372036854775808"; /* 2^63 */
> +    str = "18446744073709551616"; /* 2^64 */
>      err = qemu_strtosz(str, &endptr, &res);
>      g_assert_cmpint(err, ==, -ERANGE);
> -    g_assert(endptr == str + 19);
> +    g_assert(endptr == str + 20);
>  
> -    str = "10E";
> +    str = "20E";
>      err = qemu_strtosz(str, &endptr, &res);
>      g_assert_cmpint(err, ==, -ERANGE);
>      g_assert(endptr == str + 3);
> @@ -1583,7 +1583,7 @@ static void test_qemu_strtosz_metric(void)
>      const char *str = "12345k";
>      int err;
>      char *endptr = NULL;
> -    int64_t res = 0xbaadf00d;
> +    uint64_t res = 0xbaadf00d;
>  
>      err = qemu_strtosz_metric(str, &endptr, &res);
>      g_assert_cmpint(err, ==, 0);
> diff --git a/util/cutils.c b/util/cutils.c
> index 08effe6..888c0fd 100644
> --- a/util/cutils.c
> +++ b/util/cutils.c
> @@ -207,7 +207,7 @@ static int64_t suffix_mul(char suffix, int64_t unit)
>   */
>  static int do_strtosz(const char *nptr, char **end,
>                        const char default_suffix, int64_t unit,
> -                      int64_t *result)
> +                      uint64_t *result)
>  {
>      int retval;
>      char *endptr;
> @@ -237,7 +237,11 @@ static int do_strtosz(const char *nptr, char **end,
>          retval = -EINVAL;
>          goto out;
>      }
> -    if ((val * mul >= INT64_MAX) || val < 0) {
> +    /*
> +     * Values >= 0xfffffffffffffc00 overflow uint64_t after their trip
> +     * through double (53 bits of precision).
> +     */
> +    if ((val * mul >= 0xfffffffffffffc00) || val < 0) {

It would be great to get rid of the double's at some point.

Reviewed-by: Dr. David Alan Gilbert <dgilbert@redhat.com>

>          retval = -ERANGE;
>          goto out;
>      }
> @@ -254,17 +258,17 @@ out:
>      return retval;
>  }
>  
> -int qemu_strtosz(const char *nptr, char **end, int64_t *result)
> +int qemu_strtosz(const char *nptr, char **end, uint64_t *result)
>  {
>      return do_strtosz(nptr, end, 'B', 1024, result);
>  }
>  
> -int qemu_strtosz_mebi(const char *nptr, char **end, int64_t *result)
> +int qemu_strtosz_mebi(const char *nptr, char **end, uint64_t *result)
>  {
>      return do_strtosz(nptr, end, 'M', 1024, result);
>  }
>  
> -int qemu_strtosz_metric(const char *nptr, char **end, int64_t *result)
> +int qemu_strtosz_metric(const char *nptr, char **end, uint64_t *result)
>  {
>      return do_strtosz(nptr, end, 'B', 1000, result);
>  }
> -- 
> 2.7.4
> 
--
Dr. David Alan Gilbert / dgilbert@redhat.com / Manchester, UK

^ permalink raw reply	[flat|nested] 79+ messages in thread

* Re: [Qemu-devel] [PATCH 23/24] util/cutils: Change qemu_strtosz*() from int64_t to uint64_t
  2017-02-20 20:16   ` Dr. David Alan Gilbert
@ 2017-02-21  8:40     ` Paolo Bonzini
  2017-02-21  9:25     ` Markus Armbruster
  1 sibling, 0 replies; 79+ messages in thread
From: Paolo Bonzini @ 2017-02-21  8:40 UTC (permalink / raw)
  To: Dr. David Alan Gilbert, Markus Armbruster
  Cc: Kevin Wolf, Max Reitz, qemu-devel, open list:Block layer core,
	Eduardo Habkost



On 20/02/2017 21:16, Dr. David Alan Gilbert wrote:
>>                  p.has_max_bandwidth = true;
>>                  ret = qemu_strtosz_mebi(valuestr, NULL, &valuebw);
>> -                if (ret < 0 || (size_t)valuebw != valuebw) {
>> +                if (ret < 0 || valuebw > INT64_MAX
>> +                    || (size_t)valuebw != valuebw) {
> 
> We should probably just turn all of the parameters into size_t's - although that's
> more work and there's some int64_t's in qemu_file for no good reason.

I disagree, there's no reason why 32-bit should not support a bandwidth
specification of 10 Gbps.

size_t is related to pointers, and it should only be used for those.

Paolo

^ permalink raw reply	[flat|nested] 79+ messages in thread

* Re: [Qemu-devel] [PATCH 21/24] util/cutils: Let qemu_strtosz*() optionally reject trailing crap
  2017-02-20 19:34   ` Dr. David Alan Gilbert
@ 2017-02-21  9:13     ` Markus Armbruster
  2017-02-21  9:21       ` Dr. David Alan Gilbert
  0 siblings, 1 reply; 79+ messages in thread
From: Markus Armbruster @ 2017-02-21  9:13 UTC (permalink / raw)
  To: Dr. David Alan Gilbert
  Cc: Kevin Wolf, Max Reitz, qemu-devel, open list:Block layer core,
	Eduardo Habkost

"Dr. David Alan Gilbert" <dgilbert@redhat.com> writes:

> * Markus Armbruster (armbru@redhat.com) wrote:
>> Change the qemu_strtosz() & friends to return -EINVAL when @endptr is
>> null and the conversion doesn't consume the string completely.
>> Matches how qemu_strtol() & friends work.
>> 
>> Only test_qemu_strtosz_simple() passes a null @endptr.  No functional
>> change there, because its conversion consumes the string.
>> 
>> Simplify callers that use @endptr only to fail when it doesn't point
>> to '\0' to pass a null @endptr instead.
>> 
>> Cc: Dr. David Alan Gilbert <dgilbert@redhat.com>
>> Cc: Eduardo Habkost <ehabkost@redhat.com> (maintainer:X86)
>> Cc: Kevin Wolf <kwolf@redhat.com> (supporter:Block layer core)
>> Cc: Max Reitz <mreitz@redhat.com> (supporter:Block layer core)
>> Cc: qemu-block@nongnu.org (open list:Block layer core)
>> Signed-off-by: Markus Armbruster <armbru@redhat.com>
>
> Reviewed-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
>
> (end and endptr are horribly confusing names in do_strtosz)

Could rename for consistency with qemu_strtol() & friends:

* Parameter @end to @endptr

* Local variable @endptr to @ep

Would that be useful?

^ permalink raw reply	[flat|nested] 79+ messages in thread

* Re: [Qemu-devel] [PATCH 21/24] util/cutils: Let qemu_strtosz*() optionally reject trailing crap
  2017-02-21  9:13     ` Markus Armbruster
@ 2017-02-21  9:21       ` Dr. David Alan Gilbert
  0 siblings, 0 replies; 79+ messages in thread
From: Dr. David Alan Gilbert @ 2017-02-21  9:21 UTC (permalink / raw)
  To: Markus Armbruster
  Cc: Kevin Wolf, Max Reitz, qemu-devel, open list:Block layer core,
	Eduardo Habkost

* Markus Armbruster (armbru@redhat.com) wrote:
> "Dr. David Alan Gilbert" <dgilbert@redhat.com> writes:
> 
> > * Markus Armbruster (armbru@redhat.com) wrote:
> >> Change the qemu_strtosz() & friends to return -EINVAL when @endptr is
> >> null and the conversion doesn't consume the string completely.
> >> Matches how qemu_strtol() & friends work.
> >> 
> >> Only test_qemu_strtosz_simple() passes a null @endptr.  No functional
> >> change there, because its conversion consumes the string.
> >> 
> >> Simplify callers that use @endptr only to fail when it doesn't point
> >> to '\0' to pass a null @endptr instead.
> >> 
> >> Cc: Dr. David Alan Gilbert <dgilbert@redhat.com>
> >> Cc: Eduardo Habkost <ehabkost@redhat.com> (maintainer:X86)
> >> Cc: Kevin Wolf <kwolf@redhat.com> (supporter:Block layer core)
> >> Cc: Max Reitz <mreitz@redhat.com> (supporter:Block layer core)
> >> Cc: qemu-block@nongnu.org (open list:Block layer core)
> >> Signed-off-by: Markus Armbruster <armbru@redhat.com>
> >
> > Reviewed-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
> >
> > (end and endptr are horribly confusing names in do_strtosz)
> 
> Could rename for consistency with qemu_strtol() & friends:
> 
> * Parameter @end to @endptr
> 
> * Local variable @endptr to @ep
> 
> Would that be useful?

Oh I wouldn't worry too much about it; and those perhaps aren't
that much clearer.

Dave

--
Dr. David Alan Gilbert / dgilbert@redhat.com / Manchester, UK

^ permalink raw reply	[flat|nested] 79+ messages in thread

* Re: [Qemu-devel] [PATCH 23/24] util/cutils: Change qemu_strtosz*() from int64_t to uint64_t
  2017-02-20 20:16   ` Dr. David Alan Gilbert
  2017-02-21  8:40     ` Paolo Bonzini
@ 2017-02-21  9:25     ` Markus Armbruster
  1 sibling, 0 replies; 79+ messages in thread
From: Markus Armbruster @ 2017-02-21  9:25 UTC (permalink / raw)
  To: Dr. David Alan Gilbert
  Cc: Kevin Wolf, Max Reitz, qemu-devel, open list:Block layer core,
	Eduardo Habkost

"Dr. David Alan Gilbert" <dgilbert@redhat.com> writes:

> * Markus Armbruster (armbru@redhat.com) wrote:
>> This will permit its use in parse_option_size().
>> 
>> Cc: Dr. David Alan Gilbert <dgilbert@redhat.com>
>> Cc: Eduardo Habkost <ehabkost@redhat.com> (maintainer:X86)
>> Cc: Kevin Wolf <kwolf@redhat.com> (supporter:Block layer core)
>> Cc: Max Reitz <mreitz@redhat.com> (supporter:Block layer core)
>> Cc: qemu-block@nongnu.org (open list:Block layer core)
>> Signed-off-by: Markus Armbruster <armbru@redhat.com>
>> ---
>>  hmp.c                 |  5 +++--
>>  hw/misc/ivshmem.c     |  2 +-
>>  include/qemu/cutils.h |  6 +++---
>>  monitor.c             |  4 ++--
>>  qapi/opts-visitor.c   |  6 ++----
>>  qemu-img.c            |  5 ++++-
>>  qemu-io-cmds.c        |  5 ++++-
>>  target/i386/cpu.c     |  4 ++--
>>  tests/test-cutils.c   | 40 ++++++++++++++++++++--------------------
>>  util/cutils.c         | 14 +++++++++-----
>>  10 files changed, 50 insertions(+), 41 deletions(-)
>> 
>> diff --git a/hmp.c b/hmp.c
>> index 9846fa4..5b9e461 100644
>> --- a/hmp.c
>> +++ b/hmp.c
>> @@ -1338,7 +1338,7 @@ void hmp_migrate_set_parameter(Monitor *mon, const QDict *qdict)
>>  {
>>      const char *param = qdict_get_str(qdict, "parameter");
>>      const char *valuestr = qdict_get_str(qdict, "value");
>> -    int64_t valuebw = 0;
>> +    uint64_t valuebw = 0;
>>      long valueint = 0;
>>      Error *err = NULL;
>>      bool use_int_value = false;
>> @@ -1379,7 +1379,8 @@ void hmp_migrate_set_parameter(Monitor *mon, const QDict *qdict)
>>              case MIGRATION_PARAMETER_MAX_BANDWIDTH:
>>                  p.has_max_bandwidth = true;
>>                  ret = qemu_strtosz_mebi(valuestr, NULL, &valuebw);
>> -                if (ret < 0 || (size_t)valuebw != valuebw) {
>> +                if (ret < 0 || valuebw > INT64_MAX
>> +                    || (size_t)valuebw != valuebw) {
>
> We should probably just turn all of the parameters into size_t's - although that's
> more work and there's some int64_t's in qemu_file for no good reason.

I guess that's a comment on migration parameters, not on the strosz
family of functions.

>>                      error_setg(&err, "Invalid size %s", valuestr);
>>                      goto cleanup;
>>                  }
[...]
>> diff --git a/util/cutils.c b/util/cutils.c
>> index 08effe6..888c0fd 100644
>> --- a/util/cutils.c
>> +++ b/util/cutils.c
>> @@ -207,7 +207,7 @@ static int64_t suffix_mul(char suffix, int64_t unit)
>>   */
>>  static int do_strtosz(const char *nptr, char **end,
>>                        const char default_suffix, int64_t unit,
>> -                      int64_t *result)
>> +                      uint64_t *result)
>>  {
>>      int retval;
>>      char *endptr;
>> @@ -237,7 +237,11 @@ static int do_strtosz(const char *nptr, char **end,
>>          retval = -EINVAL;
>>          goto out;
>>      }
>> -    if ((val * mul >= INT64_MAX) || val < 0) {
>> +    /*
>> +     * Values >= 0xfffffffffffffc00 overflow uint64_t after their trip
>> +     * through double (53 bits of precision).
>> +     */
>> +    if ((val * mul >= 0xfffffffffffffc00) || val < 0) {
>
> It would be great to get rid of the double's at some point.

Maybe.

53 bits of precision are fine in practice, if a bit awkward to document
and test once you bother to document and test (read: only now, 6 years
four months after its creation).  long double would give us 64 bits at
least on common hosts, but would be even more bothersome to document and
test.

Could try to parse both as integer and as floating-point and see which
one accepts more characters.

> Reviewed-by: Dr. David Alan Gilbert <dgilbert@redhat.com>

Thanks!

[...]

^ permalink raw reply	[flat|nested] 79+ messages in thread

end of thread, other threads:[~2017-02-21  9:25 UTC | newest]

Thread overview: 79+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-02-14 10:25 [Qemu-devel] [PATCH 00/24] QemuOpts util/cutils: Fix and clean up number conversions Markus Armbruster
2017-02-14 10:25 ` [Qemu-devel] [PATCH 01/24] tests/test-qemu-opts: Cover qemu_opts_parse() Markus Armbruster
2017-02-14 19:48   ` Eric Blake
2017-02-14 10:25 ` [Qemu-devel] [PATCH 02/24] QemuOpts: Assert value string isn't null Markus Armbruster
2017-02-14 20:10   ` Eric Blake
2017-02-16 12:58     ` Markus Armbruster
2017-02-14 10:25 ` [Qemu-devel] [PATCH 03/24] tests/test-cutils: Add missing qemu_strtol()... endptr checks Markus Armbruster
2017-02-14 20:11   ` Eric Blake
2017-02-19  4:12   ` Philippe Mathieu-Daudé
2017-02-14 10:25 ` [Qemu-devel] [PATCH 04/24] tests/test-cutils: Clean up qemu_strtoul() result checks Markus Armbruster
2017-02-14 21:28   ` Eric Blake
2017-02-16 13:07     ` Markus Armbruster
2017-02-14 10:25 ` [Qemu-devel] [PATCH 05/24] util/cutils: Rewrite documentation of qemu_strtol() & friends Markus Armbruster
2017-02-14 21:32   ` Eric Blake
2017-02-19  4:12   ` Philippe Mathieu-Daudé
2017-02-14 10:25 ` [Qemu-devel] [PATCH 06/24] util/cutils: Rename qemu_strtoll(), qemu_strtoull() Markus Armbruster
2017-02-14 21:34   ` Eric Blake
2017-02-19  4:14   ` Philippe Mathieu-Daudé
2017-02-14 10:25 ` [Qemu-devel] [PATCH 07/24] util/cutils: Clean up variable names around qemu_strtol() Markus Armbruster
2017-02-14 12:33   ` Paolo Bonzini
2017-02-14 13:11     ` Markus Armbruster
2017-02-14 21:37   ` Eric Blake
2017-02-14 10:25 ` [Qemu-devel] [PATCH 08/24] util/cutils: Clean up control flow around qemu_strtol() a bit Markus Armbruster
2017-02-14 10:53   ` Peter Maydell
2017-02-14 12:58     ` Markus Armbruster
2017-02-14 13:01       ` Peter Maydell
2017-02-14 21:40   ` Eric Blake
2017-02-14 10:25 ` [Qemu-devel] [PATCH 09/24] QemuOpts: Fix to reject numbers that overflow uint64_t Markus Armbruster
2017-02-14 21:48   ` Eric Blake
2017-02-14 10:25 ` [Qemu-devel] [PATCH 10/24] tests/test-cutils: Add missing qemu_strtosz()... endptr checks Markus Armbruster
2017-02-14 22:26   ` Eric Blake
2017-02-19  4:16   ` Philippe Mathieu-Daudé
2017-02-14 10:25 ` [Qemu-devel] [PATCH 11/24] tests/test-cutils: Cover qemu_strtosz() invalid input Markus Armbruster
2017-02-14 22:53   ` Eric Blake
2017-02-16 14:19     ` Markus Armbruster
2017-02-14 10:25 ` [Qemu-devel] [PATCH 12/24] tests/test-cutils: Cover qemu_strtosz() with trailing crap Markus Armbruster
2017-02-14 22:58   ` Eric Blake
2017-02-14 10:26 ` [Qemu-devel] [PATCH 13/24] tests/test-cutils: Cover qemu_strtosz() around range limits Markus Armbruster
2017-02-14 23:14   ` Eric Blake
2017-02-14 10:26 ` [Qemu-devel] [PATCH 14/24] util/cutils: New qemu_strtosz_metric() Markus Armbruster
2017-02-17 20:44   ` Eric Blake
2017-02-18 10:08     ` Markus Armbruster
2017-02-14 10:26 ` [Qemu-devel] [PATCH 15/24] util/cutils: Rename qemu_strtosz() to qemu_strtosz_mebi() Markus Armbruster
2017-02-14 12:35   ` Paolo Bonzini
2017-02-14 13:12     ` Markus Armbruster
2017-02-17 20:45   ` Eric Blake
2017-02-14 10:26 ` [Qemu-devel] [PATCH 16/24] util/cutils: New qemu_strtosz() Markus Armbruster
2017-02-17 20:48   ` Eric Blake
2017-02-14 10:26 ` [Qemu-devel] [PATCH 17/24] util/cutils: Drop QEMU_STRTOSZ_DEFSUFFIX_* macros Markus Armbruster
2017-02-17 20:51   ` Eric Blake
2017-02-19  4:21   ` Philippe Mathieu-Daudé
2017-02-14 10:26 ` [Qemu-devel] [PATCH 18/24] tests/test-cutils: Use qemu_strtosz() more often Markus Armbruster
2017-02-17 20:55   ` Eric Blake
2017-02-14 10:26 ` [Qemu-devel] [PATCH 19/24] tests/test-cutils: Drop suffix from test_qemu_strtosz_simple() Markus Armbruster
2017-02-17 20:58   ` Eric Blake
2017-02-14 10:26 ` [Qemu-devel] [PATCH 20/24] qemu-img: Wrap cvtnum() around qemu_strtosz() Markus Armbruster
2017-02-17 21:10   ` Eric Blake
2017-02-18 10:13     ` Markus Armbruster
2017-02-14 10:26 ` [Qemu-devel] [PATCH 21/24] util/cutils: Let qemu_strtosz*() optionally reject trailing crap Markus Armbruster
2017-02-17 21:21   ` Eric Blake
2017-02-18 10:22     ` Markus Armbruster
2017-02-20 19:34   ` Dr. David Alan Gilbert
2017-02-21  9:13     ` Markus Armbruster
2017-02-21  9:21       ` Dr. David Alan Gilbert
2017-02-14 10:26 ` [Qemu-devel] [PATCH 22/24] util/cutils: Return qemu_strtosz*() error and value separately Markus Armbruster
2017-02-17 22:03   ` Eric Blake
2017-02-18 10:33     ` Markus Armbruster
2017-02-20 19:52   ` Dr. David Alan Gilbert
2017-02-14 10:26 ` [Qemu-devel] [PATCH 23/24] util/cutils: Change qemu_strtosz*() from int64_t to uint64_t Markus Armbruster
2017-02-17 22:19   ` Eric Blake
2017-02-18 10:40     ` Markus Armbruster
2017-02-20 20:16   ` Dr. David Alan Gilbert
2017-02-21  8:40     ` Paolo Bonzini
2017-02-21  9:25     ` Markus Armbruster
2017-02-14 10:26 ` [Qemu-devel] [PATCH 24/24] QemuOpts: Fix checking of sizes for overflow and trailing crap Markus Armbruster
2017-02-17 22:27   ` Eric Blake
2017-02-18 10:46     ` Markus Armbruster
2017-02-14 10:57 ` [Qemu-devel] [PATCH 00/24] QemuOpts util/cutils: Fix and clean up number conversions no-reply
2017-02-14 12:37 ` Paolo Bonzini

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.