aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2017-02-24 18:34:27 +0000
committerPeter Maydell <peter.maydell@linaro.org>2017-02-24 18:34:27 +0000
commitd7941f4eed5fe6fe4aca6e4123bd70123c9e6080 (patch)
tree07ff785bd02d3f30597f7ce9a0a543f35bb65551
parent6959e4523e517b8af965af1030d3ac5bec9cd0fb (diff)
parent75cdcd1553e74b5edc58aed23e3b2da8dabb1876 (diff)
Merge remote-tracking branch 'remotes/armbru/tags/pull-util-2017-02-23' into staging
option cutils: Fix and clean up number conversions # gpg: Signature made Thu 23 Feb 2017 19:41:17 GMT # gpg: using RSA key 0x3870B400EB918653 # gpg: Good signature from "Markus Armbruster <armbru@redhat.com>" # gpg: aka "Markus Armbruster <armbru@pond.sub.org>" # Primary key fingerprint: 354B C8B3 D7EB 2A6B 6867 4E5F 3870 B400 EB91 8653 * remotes/armbru/tags/pull-util-2017-02-23: (24 commits) option: Fix checking of sizes for overflow and trailing crap util/cutils: Change qemu_strtosz*() from int64_t to uint64_t util/cutils: Return qemu_strtosz*() error and value separately util/cutils: Let qemu_strtosz*() optionally reject trailing crap qemu-img: Wrap cvtnum() around qemu_strtosz() test-cutils: Drop suffix from test_qemu_strtosz_simple() test-cutils: Use qemu_strtosz() more often util/cutils: Drop QEMU_STRTOSZ_DEFSUFFIX_* macros util/cutils: New qemu_strtosz() util/cutils: Rename qemu_strtosz() to qemu_strtosz_MiB() util/cutils: New qemu_strtosz_metric() test-cutils: Cover qemu_strtosz() around range limits test-cutils: Cover qemu_strtosz() with trailing crap test-cutils: Cover qemu_strtosz() invalid input test-cutils: Add missing qemu_strtosz()... endptr checks option: Fix to reject invalid and overflowing numbers util/cutils: Clean up control flow around qemu_strtol() a bit util/cutils: Clean up variable names around qemu_strtol() util/cutils: Rename qemu_strtoll(), qemu_strtoull() util/cutils: Rewrite documentation of qemu_strtol() & friends ... Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
-rw-r--r--hmp.c11
-rw-r--r--hw/misc/ivshmem.c9
-rw-r--r--include/qemu/cutils.h29
-rw-r--r--monitor.c7
-rw-r--r--qapi/opts-visitor.c11
-rw-r--r--qemu-img.c62
-rw-r--r--qemu-io-cmds.c16
-rw-r--r--qobject/qdict.c2
-rw-r--r--qtest.c34
-rw-r--r--target/i386/cpu.c9
-rw-r--r--tests/test-cutils.c644
-rw-r--r--tests/test-qemu-opts.c324
-rw-r--r--util/cutils.c247
-rw-r--r--util/log.c4
-rw-r--r--util/qemu-option.c89
15 files changed, 1000 insertions, 498 deletions
diff --git a/hmp.c b/hmp.c
index aba728f0de..83e287e0a4 100644
--- a/hmp.c
+++ b/hmp.c
@@ -1344,12 +1344,11 @@ 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;
- char *endp;
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) {
@@ -1385,9 +1384,9 @@ 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);
- if (valuebw < 0 || (size_t)valuebw != valuebw
- || *endp != '\0') {
+ ret = qemu_strtosz_MiB(valuestr, NULL, &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 bf57e635d6..82ce8378bf 100644
--- a/hw/misc/ivshmem.c
+++ b/hw/misc/ivshmem.c
@@ -1267,10 +1267,11 @@ 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(s->sizearg, &end);
- if (size < 0 || (size_t)size != size || *end != '\0'
- || !is_power_of_2(size)) {
+ int ret;
+ uint64_t size;
+
+ ret = qemu_strtosz_MiB(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 8033929139..f0878eaafa 100644
--- a/include/qemu/cutils.h
+++ b/include/qemu/cutils.h
@@ -130,34 +130,19 @@ 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,
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(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);
+int qemu_strtosz(const char *nptr, char **end, uint64_t *result);
+int qemu_strtosz_MiB(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)
#define G_BYTE (1ULL << 30)
diff --git a/monitor.c b/monitor.c
index 5aff7aebb0..f8f4a07cfb 100644
--- a/monitor.c
+++ b/monitor.c
@@ -2799,7 +2799,8 @@ static QDict *monitor_parse_arguments(Monitor *mon,
break;
case 'o':
{
- int64_t val;
+ int ret;
+ uint64_t val;
char *end;
while (qemu_isspace(*p)) {
@@ -2811,8 +2812,8 @@ static QDict *monitor_parse_arguments(Monitor *mon,
break;
}
}
- val = qemu_strtosz(p, &end);
- if (val < 0) {
+ ret = qemu_strtosz_MiB(p, &end, &val);
+ 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 1048bbc84e..a0a7c0e734 100644
--- a/qapi/opts-visitor.c
+++ b/qapi/opts-visitor.c
@@ -481,23 +481,20 @@ 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;
+ int err;
opt = lookup_scalar(ov, name, errp);
if (!opt) {
return;
}
- val = qemu_strtosz_suffix(opt->str ? opt->str : "", &endptr,
- QEMU_STRTOSZ_DEFSUFFIX_B);
- if (val < 0 || *endptr) {
+ 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 cff22e3005..df3aefd35a 100644
--- a/qemu-img.c
+++ b/qemu-img.c
@@ -368,6 +368,21 @@ static int add_old_style_options(const char *fmt, QemuOpts *opts,
return 0;
}
+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;
+}
+
static int img_create(int argc, char **argv)
{
int c;
@@ -461,10 +476,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_suffix(argv[optind++], &end,
- QEMU_STRTOSZ_DEFSUFFIX_B);
- 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 {
@@ -1864,9 +1878,9 @@ static int img_convert(int argc, char **argv)
case 'S':
{
int64_t sval;
- char *end;
- sval = qemu_strtosz_suffix(optarg, &end, QEMU_STRTOSZ_DEFSUFFIX_B);
- 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;
@@ -3651,11 +3665,8 @@ static int img_bench(int argc, char **argv)
break;
case 'o':
{
- char *end;
- errno = 0;
- offset = qemu_strtosz_suffix(optarg, &end,
- QEMU_STRTOSZ_DEFSUFFIX_B);
- if (offset < 0|| *end) {
+ offset = cvtnum(optarg);
+ if (offset < 0) {
error_report("Invalid offset specified");
return 1;
}
@@ -3668,10 +3679,9 @@ static int img_bench(int argc, char **argv)
case 's':
{
int64_t sval;
- char *end;
- sval = qemu_strtosz_suffix(optarg, &end, QEMU_STRTOSZ_DEFSUFFIX_B);
- if (sval < 0 || sval > INT_MAX || *end) {
+ sval = cvtnum(optarg);
+ if (sval < 0 || sval > INT_MAX) {
error_report("Invalid buffer size specified");
return 1;
}
@@ -3682,10 +3692,9 @@ static int img_bench(int argc, char **argv)
case 'S':
{
int64_t sval;
- char *end;
- sval = qemu_strtosz_suffix(optarg, &end, QEMU_STRTOSZ_DEFSUFFIX_B);
- if (sval < 0 || sval > INT_MAX || *end) {
+ sval = cvtnum(optarg);
+ if (sval < 0 || sval > INT_MAX) {
error_report("Invalid step size specified");
return 1;
}
@@ -3844,12 +3853,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_suffix(arg, &end, QEMU_STRTOSZ_DEFSUFFIX_B);
+ res = cvtnum(arg);
- if (res <= 0 || res > INT_MAX || *end) {
+ if (res <= 0 || res > INT_MAX) {
error_report("invalid number: '%s'", arg);
return 1;
}
@@ -3862,11 +3870,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_suffix(arg, &end, QEMU_STRTOSZ_DEFSUFFIX_B);
-
- if (dd->count < 0 || *end) {
+ if (dd->count < 0) {
error_report("invalid number: '%s'", arg);
return 1;
}
@@ -3896,11 +3902,9 @@ static int img_dd_skip(const char *arg,
struct DdIo *in, struct DdIo *out,
struct DdInfo *dd)
{
- char *end;
-
- in->offset = qemu_strtosz_suffix(arg, &end, QEMU_STRTOSZ_DEFSUFFIX_B);
+ in->offset = cvtnum(arg);
- if (in->offset < 0 || *end) {
+ if (in->offset < 0) {
error_report("invalid number: '%s'", arg);
return 1;
}
diff --git a/qemu-io-cmds.c b/qemu-io-cmds.c
index e415b03cd0..7ac1576d4c 100644
--- a/qemu-io-cmds.c
+++ b/qemu-io-cmds.c
@@ -137,15 +137,17 @@ static char **breakline(char *input, int *count)
static int64_t cvtnum(const char *s)
{
- char *end;
- int64_t ret;
+ int err;
+ uint64_t value;
- ret = qemu_strtosz_suffix(s, &end, QEMU_STRTOSZ_DEFSUFFIX_B);
- if (*end != '\0') {
- /* Detritus at the end of the string */
- return -EINVAL;
+ err = qemu_strtosz(s, NULL, &value);
+ if (err < 0) {
+ return err;
}
- return ret;
+ if (value > INT64_MAX) {
+ return -ERANGE;
+ }
+ return value;
}
static void print_cvtnum_err(int64_t rc, const char *arg)
diff --git a/qobject/qdict.c b/qobject/qdict.c
index b0c5364506..291eef1a19 100644
--- a/qobject/qdict.c
+++ b/qobject/qdict.c
@@ -743,7 +743,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 1446719e8d..a6858272eb 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/target/i386/cpu.c b/target/i386/cpu.c
index fd7add2521..b6f157dca3 100644
--- a/target/i386/cpu.c
+++ b/target/i386/cpu.c
@@ -2033,12 +2033,11 @@ static void x86_cpu_parse_featurestr(const char *typename, char *features,
/* Special case: */
if (!strcmp(name, "tsc-freq")) {
- int64_t tsc_freq;
- char *err;
+ int ret;
+ uint64_t tsc_freq;
- tsc_freq = qemu_strtosz_suffix_unit(val, &err,
- QEMU_STRTOSZ_DEFSUFFIX_B, 1000);
- if (tsc_freq < 0 || *err) {
+ ret = qemu_strtosz_metric(val, NULL, &tsc_freq);
+ 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 20b0f59ba2..f64a49b7fb 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)
@@ -520,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);
}
@@ -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)
@@ -587,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);
}
@@ -602,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;
@@ -610,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));
}
@@ -625,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";
@@ -634,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));
}
@@ -649,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_cmphex(res, ==, 0x123);
g_assert(endptr == str + strlen(str));
str = "0x123";
@@ -658,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_cmphex(res, ==, 0x123);
g_assert(endptr == str + strlen(str));
}
@@ -673,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_cmphex(res, ==, ULONG_MAX);
g_assert(endptr == str + strlen(str));
g_free(str);
}
@@ -689,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_cmphex(res, ==, ULONG_MAX);
g_assert(endptr == str + strlen(str));
}
@@ -704,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));
}
@@ -719,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));
}
@@ -732,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)
@@ -763,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)
@@ -786,11 +792,11 @@ 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_cmphex(res, ==, ULONG_MAX);
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';
@@ -798,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';
@@ -826,12 +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';
@@ -839,12 +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';
@@ -852,12 +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';
@@ -865,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';
@@ -880,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);
@@ -888,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';
@@ -903,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);
@@ -912,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';
@@ -927,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);
@@ -936,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';
@@ -951,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);
@@ -959,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';
@@ -967,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';
@@ -982,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';
@@ -997,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';
@@ -1082,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_cmpint(res, ==, 12345);
+ 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';
@@ -1110,12 +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';
@@ -1123,12 +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';
@@ -1136,12 +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';
@@ -1149,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_cmpint(res, ==, 123);
+ 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';
@@ -1164,22 +1176,22 @@ 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_cmpint(res, ==, 0123);
+ g_assert_cmpuint(res, ==, 0123);
g_assert(endptr == str + strlen(str));
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_cmpint(res, ==, 0123);
+ 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';
@@ -1187,23 +1199,23 @@ 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_cmpint(res, ==, 123);
+ g_assert_cmpuint(res, ==, 123);
g_assert(endptr == str + strlen(str));
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_cmpint(res, ==, 123);
+ 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';
@@ -1211,23 +1223,23 @@ 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_cmpint(res, ==, 0x123);
+ g_assert_cmphex(res, ==, 0x123);
g_assert(endptr == str + strlen(str));
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_cmpint(res, ==, 0x123);
+ g_assert_cmphex(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';
@@ -1235,15 +1247,15 @@ 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_cmpint(res, ==, ULLONG_MAX);
+ g_assert_cmphex(res, ==, ULLONG_MAX);
g_assert(endptr == str + strlen(str));
g_free(str);
}
-static void test_qemu_strtoull_overflow(void)
+static void test_qemu_strtou64_overflow(void)
{
const char *str = "99999999999999999999999999999999999999999999";
char f = 'X';
@@ -1251,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_cmpint(res, ==, ULLONG_MAX);
+ g_assert_cmphex(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';
@@ -1266,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_cmpint(res, ==, -1);
+ g_assert_cmphex(res, ==, -1ull);
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';
@@ -1281,94 +1293,139 @@ 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_cmpint(res, ==, -321);
+ g_assert_cmpuint(res, ==, -321ull);
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_cmpint(res, ==, 18446744073709551614LLU);
+ g_assert_cmpuint(res, ==, 18446744073709551614ull);
}
-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_cmpint(res, ==, 18446744073709551295LLU);
+ g_assert_cmpuint(res, ==, -321ull);
}
-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_cmpint(res, ==, ULLONG_MAX);
+ g_assert_cmphex(res, ==, ULLONG_MAX);
g_free(str);
}
static void test_qemu_strtosz_simple(void)
{
- const char *str = "12345M";
+ const char *str;
char *endptr = NULL;
- int64_t res;
+ int err;
+ uint64_t res = 0xbaadf00d;
- res = qemu_strtosz(str, &endptr);
- g_assert_cmpint(res, ==, 12345 * M_BYTE);
- g_assert(endptr == str + 6);
+ str = "0";
+ err = qemu_strtosz(str, &endptr, &res);
+ g_assert_cmpint(err, ==, 0);
+ g_assert_cmpint(res, ==, 0);
+ g_assert(endptr == str + 1);
+
+ str = "12345";
+ err = qemu_strtosz(str, &endptr, &res);
+ g_assert_cmpint(err, ==, 0);
+ g_assert_cmpint(res, ==, 12345);
+ g_assert(endptr == str + 5);
+
+ 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() */
- res = qemu_strtosz(str, NULL);
- g_assert_cmpint(res, ==, 12345 * M_BYTE);
+ str = "9007199254740991"; /* 2^53-1 */
+ 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 */
+ 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 */
+ 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 = "18446744073709549568"; /* 0xfffffffffffff800 (53 msbs set) */
+ err = qemu_strtosz(str, &endptr, &res);
+ g_assert_cmpint(err, ==, 0);
+ g_assert_cmpint(res, ==, 0xfffffffffffff800);
+ g_assert(endptr == str + 20);
+
+ str = "18446744073709550591"; /* 0xfffffffffffffbff */
+ err = qemu_strtosz(str, &endptr, &res);
+ g_assert_cmpint(err, ==, 0);
+ 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() */
}
static void test_qemu_strtosz_units(void)
@@ -1381,60 +1438,157 @@ static void test_qemu_strtosz_units(void)
const char *t = "1T";
const char *p = "1P";
const char *e = "1E";
- int64_t res;
+ int err;
+ char *endptr = NULL;
+ uint64_t res = 0xbaadf00d;
/* default is M */
- res = qemu_strtosz(none, NULL);
+ err = qemu_strtosz_MiB(none, &endptr, &res);
+ g_assert_cmpint(err, ==, 0);
g_assert_cmpint(res, ==, M_BYTE);
+ g_assert(endptr == none + 1);
- res = qemu_strtosz(b, NULL);
+ 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, NULL);
+ 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, NULL);
+ 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, NULL);
+ 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, NULL);
+ 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, NULL);
+ 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, NULL);
+ err = qemu_strtosz(e, &endptr, &res);
+ g_assert_cmpint(err, ==, 0);
g_assert_cmpint(res, ==, E_BYTE);
+ g_assert(endptr == e + 2);
}
static void test_qemu_strtosz_float(void)
{
const char *str = "12.345M";
- int64_t res;
+ int err;
+ char *endptr = NULL;
+ uint64_t res = 0xbaadf00d;
- res = qemu_strtosz(str, NULL);
+ err = qemu_strtosz(str, &endptr, &res);
+ g_assert_cmpint(err, ==, 0);
g_assert_cmpint(res, ==, 12.345 * M_BYTE);
+ g_assert(endptr == str + 7);
+}
+
+static void test_qemu_strtosz_invalid(void)
+{
+ const char *str;
+ char *endptr = NULL;
+ int err;
+ uint64_t res = 0xbaadf00d;
+
+ str = "";
+ err = qemu_strtosz(str, &endptr, &res);
+ g_assert_cmpint(err, ==, -EINVAL);
+ g_assert(endptr == str);
+
+ str = " \t ";
+ err = qemu_strtosz(str, &endptr, &res);
+ g_assert_cmpint(err, ==, -EINVAL);
+ g_assert(endptr == str);
+
+ str = "crap";
+ err = qemu_strtosz(str, &endptr, &res);
+ g_assert_cmpint(err, ==, -EINVAL);
+ g_assert(endptr == str);
+}
+
+static void test_qemu_strtosz_trailing(void)
+{
+ const char *str;
+ char *endptr = NULL;
+ int err;
+ uint64_t res = 0xbaadf00d;
+
+ str = "123xxx";
+ err = qemu_strtosz_MiB(str, &endptr, &res);
+ g_assert_cmpint(res, ==, 123 * M_BYTE);
+ g_assert(endptr == str + 3);
+
+ err = qemu_strtosz(str, NULL, &res);
+ g_assert_cmpint(err, ==, -EINVAL);
+
+ str = "1kiB";
+ err = qemu_strtosz(str, &endptr, &res);
+ g_assert_cmpint(err, ==, 0);
+ g_assert_cmpint(res, ==, 1024);
+ g_assert(endptr == str + 2);
+
+ err = qemu_strtosz(str, NULL, &res);
+ g_assert_cmpint(err, ==, -EINVAL);
}
static void test_qemu_strtosz_erange(void)
{
- const char *str = "10E";
- int64_t res;
+ const char *str;
+ char *endptr = NULL;
+ int err;
+ uint64_t res = 0xbaadf00d;
+
+ str = "-1";
+ err = qemu_strtosz(str, &endptr, &res);
+ g_assert_cmpint(err, ==, -ERANGE);
+ g_assert(endptr == str + 2);
+
+ str = "18446744073709550592"; /* 0xfffffffffffffc00 */
+ err = qemu_strtosz(str, &endptr, &res);
+ g_assert_cmpint(err, ==, -ERANGE);
+ g_assert(endptr == str + 20);
+
+ str = "18446744073709551615"; /* 2^64-1 */
+ err = qemu_strtosz(str, &endptr, &res);
+ g_assert_cmpint(err, ==, -ERANGE);
+ g_assert(endptr == str + 20);
+
+ str = "18446744073709551616"; /* 2^64 */
+ err = qemu_strtosz(str, &endptr, &res);
+ g_assert_cmpint(err, ==, -ERANGE);
+ g_assert(endptr == str + 20);
- res = qemu_strtosz(str, NULL);
- g_assert_cmpint(res, ==, -ERANGE);
+ str = "20E";
+ err = qemu_strtosz(str, &endptr, &res);
+ g_assert_cmpint(err, ==, -ERANGE);
+ g_assert(endptr == str + 3);
}
-static void test_qemu_strtosz_suffix_unit(void)
+static void test_qemu_strtosz_metric(void)
{
- const char *str = "12345";
- int64_t res;
+ const char *str = "12345k";
+ int err;
+ char *endptr = NULL;
+ uint64_t res = 0xbaadf00d;
- res = qemu_strtosz_suffix_unit(str, NULL,
- QEMU_STRTOSZ_DEFSUFFIX_KB, 1000);
+ err = qemu_strtosz_metric(str, &endptr, &res);
+ g_assert_cmpint(err, ==, 0);
g_assert_cmpint(res, ==, 12345000);
+ g_assert(endptr == str + 6);
}
int main(int argc, char **argv)
@@ -1459,21 +1613,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",
@@ -1488,18 +1653,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",
@@ -1519,73 +1692,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_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_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_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);
@@ -1593,10 +1779,14 @@ 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/trailing",
+ 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/tests/test-qemu-opts.c b/tests/test-qemu-opts.c
index a505a3e059..c46ef31658 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,308 @@ 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");
+
+ /* TODO Cover low-level access to repeated keys */
+
+ /* 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);
+
+ /* 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"), ==, "");
+
+ /* Implied key with empty value */
+ opts = qemu_opts_parse(&opts_list_03, ",", true, &error_abort);
+ g_assert_cmpuint(opts_count(opts), ==, 1);
+ g_assert_cmpstr(qemu_opt_get(opts, "implied"), ==, "");
+
+ /* Implied key with comma value */
+ opts = qemu_opts_parse(&opts_list_03, ",,,a=1", true, &error_abort);
+ g_assert_cmpuint(opts_count(opts), ==, 2);
+ g_assert_cmpstr(qemu_opt_get(opts, "implied"), ==, ",");
+ g_assert_cmpstr(qemu_opt_get(opts, "a"), ==, "1");
+
+ /* Empty key is not an implied key */
+ opts = qemu_opts_parse(&opts_list_03, "=val", true, &error_abort);
+ g_assert_cmpuint(opts_count(opts), ==, 1);
+ g_assert_cmpstr(qemu_opt_get(opts, ""), ==, "val");
+
+ /* 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_cmphex(qemu_opt_get_number(opts, "number1", 1), ==, UINT64_MAX);
+ g_assert_cmphex(qemu_opt_get_number(opts, "number2", 0), ==, UINT64_MAX);
+
+ /* Above upper limit */
+ opts = qemu_opts_parse(&opts_list_01, "number1=18446744073709551616",
+ false, &err);
+ error_free_or_abort(&err);
+ g_assert(!opts);
+
+ /* Below lower limit */
+ opts = qemu_opts_parse(&opts_list_01, "number1=-18446744073709551616",
+ false, &err);
+ error_free_or_abort(&err);
+ g_assert(!opts);
+
+ /* 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);
+
+ /* Invalid */
+ opts = qemu_opts_parse(&opts_list_01, "number1=", false, &err);
+ error_free_or_abort(&err);
+ g_assert(!opts);
+ opts = qemu_opts_parse(&opts_list_01, "number1=eins", false, &err);
+ error_free_or_abort(&err);
+ g_assert(!opts);
+
+ /* Leading whitespace */
+ opts = qemu_opts_parse(&opts_list_01, "number1= \t42",
+ false, &error_abort);
+ g_assert_cmpuint(opts_count(opts), ==, 1);
+ g_assert_cmpuint(qemu_opt_get_number(opts, "number1", 1), ==, 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);
+ opts = qemu_opts_parse(&opts_list_01, "number1=0 ", 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_cmphex(qemu_opt_get_size(opts, "size1", 1),
+ ==, 0x1fffffffffffff);
+ g_assert_cmphex(qemu_opt_get_size(opts, "size2", 1),
+ ==, 0x20000000000000);
+ g_assert_cmphex(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_cmphex(qemu_opt_get_size(opts, "size1", 1),
+ ==, 0x7ffffffffffffc00);
+ g_assert_cmphex(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_cmphex(qemu_opt_get_size(opts, "size1", 1),
+ ==, 0xfffffffffffff800);
+ g_assert_cmphex(qemu_opt_get_size(opts, "size2", 1),
+ ==, 0xfffffffffffff800);
+
+ /* Beyond limits */
+ 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, &err);
+ error_free_or_abort(&err);
+ g_assert(!opts);
+
+ /* 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_cmphex(qemu_opt_get_size(opts, "size1", 0), ==, 8);
+ g_assert_cmphex(qemu_opt_get_size(opts, "size2", 0), ==, 1536);
+ g_assert_cmphex(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_cmphex(qemu_opt_get_size(opts, "size1", 0), ==, G_BYTE / 10);
+ g_assert_cmphex(qemu_opt_get_size(opts, "size2", 0),
+ ==, 16777215 * T_BYTE);
+
+ /* Beyond limit with suffix */
+ opts = qemu_opts_parse(&opts_list_02, "size1=16777216T",
+ 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, &err);
+ error_free_or_abort(&err);
+ g_assert(!opts);
+
+ qemu_opts_reset(&opts_list_02);
+}
+
int main(int argc, char *argv[])
{
register_opts();
@@ -435,6 +751,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;
}
diff --git a/util/cutils.c b/util/cutils.c
index 4fefcf3be3..50ad179dc5 100644
--- a/util/cutils.c
+++ b/util/cutils.c
@@ -181,19 +181,19 @@ int fcntl_setfl(int fd, int flag)
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;
@@ -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.
*/
-int64_t qemu_strtosz_suffix_unit(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,
+ uint64_t *result)
{
- int64_t retval = -EINVAL;
+ int retval;
char *endptr;
unsigned char c;
int mul_required = 0;
@@ -217,7 +218,8 @@ int64_t qemu_strtosz_suffix_unit(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,181 +234,204 @@ int64_t qemu_strtosz_suffix_unit(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) {
+ /*
+ * Values >= 0xfffffffffffffc00 overflow uint64_t after their trip
+ * through double (53 bits of precision).
+ */
+ if ((val * mul >= 0xfffffffffffffc00) || val < 0) {
retval = -ERANGE;
- goto fail;
+ goto out;
}
- retval = val * mul;
+ *result = val * mul;
+ retval = 0;
-fail:
+out:
if (end) {
*end = endptr;
+ } else if (*endptr) {
+ retval = -EINVAL;
}
return retval;
}
-int64_t qemu_strtosz_suffix(const char *nptr, char **end,
- const char default_suffix)
+int qemu_strtosz(const char *nptr, char **end, uint64_t *result)
+{
+ return do_strtosz(nptr, end, 'B', 1024, result);
+}
+
+int qemu_strtosz_MiB(const char *nptr, char **end, uint64_t *result)
{
- return qemu_strtosz_suffix_unit(nptr, end, default_suffix, 1024);
+ return do_strtosz(nptr, end, 'M', 1024, result);
}
-int64_t qemu_strtosz(const char *nptr, char **end)
+int qemu_strtosz_metric(const char *nptr, char **end, uint64_t *result)
{
- return qemu_strtosz_suffix(nptr, end, QEMU_STRTOSZ_DEFSUFFIX_MB);
+ return do_strtosz(nptr, end, 'B', 1000, result);
}
/**
- * 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 libc_errno)
{
- /* If no conversion was performed, prefer BSD behavior over glibc
- * behavior.
- */
- if (err == 0 && endptr == p) {
- err = EINVAL;
+ if (endptr) {
+ *endptr = ep;
}
- if (!next && *endptr) {
+
+ /* Turn "no conversion" into an error */
+ if (libc_errno == 0 && ep == nptr) {
return -EINVAL;
}
- if (next) {
- *next = endptr;
+
+ /* Fail when we're expected to consume the string, but didn't */
+ if (!endptr && *ep) {
+ return -EINVAL;
}
- return -err;
+
+ return -libc_errno;
}
/**
- * QEMU wrappers for strtol(), strtoll(), strtoul(), strotull() C functions.
- *
- * Convert ASCII string @nptr to a long integer value
- * from the given @base. Parameters @nptr, @endptr, @base
- * follows same semantics as strtol() C function.
- *
- * 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.
- *
- * If NULL is passed in @endptr, then the whole string in @ntpr
- * is a number otherwise it returns -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.
+ * Convert string @nptr to a long integer, and store it in @result.
+ *
+ * This is a wrapper around strtol() that is harder to misuse.
+ * Semantics of @nptr, @endptr, @base match strtol() with differences
+ * noted below.
+ *
+ * @nptr may be null, and no conversion is performed then.
+ *
+ * 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 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)
{
- char *p;
- int err = 0;
+ char *ep;
+
if (!nptr) {
if (endptr) {
*endptr = nptr;
}
- err = -EINVAL;
- } else {
- errno = 0;
- *result = strtol(nptr, &p, base);
- err = check_strtox_error(nptr, p, endptr, errno);
+ return -EINVAL;
}
- return err;
+
+ errno = 0;
+ *result = strtol(nptr, &ep, base);
+ return check_strtox_error(nptr, ep, endptr, errno);
}
/**
- * Converts ASCII string to an unsigned long integer.
+ * Convert string @nptr to an unsigned long, and store it in @result.
+ *
+ * This is a wrapper around strtoul() that is harder to misuse.
+ * Semantics of @nptr, @endptr, @base match strtoul() with differences
+ * noted below.
+ *
+ * @nptr may be null, and no conversion is performed then.
*
- * 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.
+ * If no conversion is performed, store @nptr in *@endptr and return
+ * -EINVAL.
*
- * The same behavior holds, for qemu_strtoull() but sets @result to
- * ULLONG_MAX instead of ULONG_MAX.
+ * 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'.
*
- * See qemu_strtol() documentation for more info.
+ * 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)
{
- char *p;
- int err = 0;
+ char *ep;
+
if (!nptr) {
if (endptr) {
*endptr = nptr;
}
- err = -EINVAL;
- } else {
- errno = 0;
- *result = strtoul(nptr, &p, base);
- /* Windows returns 1 for negative out-of-range values. */
- if (errno == ERANGE) {
- *result = -1;
- }
- err = check_strtox_error(nptr, p, endptr, errno);
+ return -EINVAL;
+ }
+
+ errno = 0;
+ *result = strtoul(nptr, &ep, base);
+ /* Windows returns 1 for negative out-of-range values. */
+ if (errno == ERANGE) {
+ *result = -1;
}
- return err;
+ return check_strtox_error(nptr, ep, endptr, errno);
}
/**
- * 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,
+int qemu_strtoi64(const char *nptr, const char **endptr, int base,
int64_t *result)
{
- char *p;
- int err = 0;
+ char *ep;
+
if (!nptr) {
if (endptr) {
*endptr = nptr;
}
- err = -EINVAL;
- } else {
- errno = 0;
- *result = strtoll(nptr, &p, base);
- err = check_strtox_error(nptr, p, 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);
}
/**
- * 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,
+int qemu_strtou64(const char *nptr, const char **endptr, int base,
uint64_t *result)
{
- char *p;
- int err = 0;
+ char *ep;
+
if (!nptr) {
if (endptr) {
*endptr = nptr;
}
- err = -EINVAL;
- } else {
- errno = 0;
- *result = strtoull(nptr, &p, base);
- /* Windows returns 1 for negative out-of-range values. */
- if (errno == ERANGE) {
- *result = -1;
- }
- err = check_strtox_error(nptr, p, endptr, errno);
+ return -EINVAL;
+ }
+
+ 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 err;
+ return check_strtox_error(nptr, ep, endptr, errno);
}
/**
diff --git a/util/log.c b/util/log.c
index e077340ae1..96f30dd21a 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;
diff --git a/util/qemu-option.c b/util/qemu-option.c
index d611946333..419f2528b8 100644
--- a/util/qemu-option.c
+++ b/util/qemu-option.c
@@ -128,36 +128,33 @@ 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'");
}
}
static void parse_option_number(const char *name, const char *value,
uint64_t *ret, Error **errp)
{
- char *postfix;
uint64_t number;
+ int err;
- 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 {
+ 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;
}
+ *ret = number;
}
static const QemuOptDesc *find_desc_by_name(const QemuOptDesc *desc,
@@ -177,43 +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;
-
- 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 {
- error_setg(errp, QERR_INVALID_PARAMETER_VALUE, name, "a size");
+ uint64_t size;
+ int err;
+
+ 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;
}
+ *ret = size;
}
bool has_help_option(const char *param)
@@ -566,6 +544,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);