util/cutils: Let qemu_strtosz*() optionally reject trailing crap
authorMarkus Armbruster <armbru@redhat.com>
Tue, 21 Feb 2017 20:14:05 +0000 (21:14 +0100)
committerMarkus Armbruster <armbru@redhat.com>
Thu, 23 Feb 2017 19:35:36 +0000 (20:35 +0100)
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: Eric Blake <eblake@redhat.com>
Reviewed-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
Message-Id: <1487708048-2131-22-git-send-email-armbru@redhat.com>

hmp.c
hw/misc/ivshmem.c
qapi/opts-visitor.c
qemu-img.c
qemu-io-cmds.c
target/i386/cpu.c
tests/test-cutils.c
util/cutils.c

diff --git a/hmp.c b/hmp.c
index 72a52566761ec08f6ee37da93e563386ccfea98c..2269e8b4572eed38e58c27ae7d6090b91772d71c 100644 (file)
--- a/hmp.c
+++ b/hmp.c
@@ -1346,7 +1346,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;
@@ -1385,9 +1384,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_MiB(valuestr, &endp);
-                if (valuebw < 0 || (size_t)valuebw != valuebw
-                    || *endp != '\0') {
+                valuebw = qemu_strtosz_MiB(valuestr, NULL);
+                if (valuebw < 0 || (size_t)valuebw != valuebw) {
                     error_setg(&err, "Invalid size %s", valuestr);
                     goto cleanup;
                 }
index b3d9ed99ddb8485161f18453d125ee8f18a66de4..848bebc794023e0b8284e83420db6e4b8423d96f 100644 (file)
@@ -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_MiB(s->sizearg, &end);
-        if (size < 0 || (size_t)size != size || *end != '\0'
-            || !is_power_of_2(size)) {
+        int64_t size = qemu_strtosz_MiB(s->sizearg, NULL);
+        if (size < 0 || (size_t)size != size || !is_power_of_2(size)) {
             error_setg(errp, "Invalid size %s", s->sizearg);
             return;
         }
index 360d33773fa4333111d82373be40ebbf2eaf0c0d..911a0ee300aa670337c5920353fb64be9b02ddc1 100644 (file)
@@ -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;
index 40629176033ef2f3b7a5c2f1bde85d633f32e2cb..39ef581cc1982523bc2c257d50888fd17f57afd8 100644 (file)
@@ -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;
 }
 
index 0166cfaa8d75e3d1de5ba8a68f60caedcf770729..973eb947744e2fdeb4cd59a210f443a9bc222f05 100644 (file)
@@ -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;
 }
 
index 685ca36640ce387953066b45f8dbc62d85c7eece..58a05ec870d19b1c689760ed02cc0ce09e2b61c0 100644 (file)
@@ -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;
             }
index c4437d9817e567842d99ed48ff2fdf3600e2f53c..f2ecb7aecbfab42a5877ba463389184679561b46 100644 (file)
@@ -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)
index 0ac8019ef63204cd4074b994780fdf7fa59d3d84..b9916237337f19f9752f595f6f0a85e24d3c94e1 100644 (file)
@@ -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;