Skip to content

Commit

Permalink
cutils: Fix qemu_strtosz() & friends to reject non-finite sizes
Browse files Browse the repository at this point in the history
qemu_strtosz() & friends reject NaNs, but happily accept infinities.
They shouldn't. Fix that.

The fix makes use of qemu_strtod_finite(). To avoid ugly casts,
change the @EnD parameter of qemu_strtosz() & friends from char **
to const char **.

Also, add two test cases, testing that "inf" and "NaN" are properly
rejected. While at it, also fixup the function documentation.

Reviewed-by: Eric Blake <[email protected]>
Reviewed-by: Markus Armbruster <[email protected]>
Signed-off-by: David Hildenbrand <[email protected]>
Message-Id: <[email protected]>
Signed-off-by: Markus Armbruster <[email protected]>
  • Loading branch information
davidhildenbrand authored and Markus Armbruster committed Dec 13, 2018
1 parent ca28f54 commit af02f4c
Show file tree
Hide file tree
Showing 4 changed files with 29 additions and 21 deletions.
6 changes: 3 additions & 3 deletions include/qemu/cutils.h
Original file line number Diff line number Diff line change
Expand Up @@ -153,9 +153,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, 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);
int qemu_strtosz(const char *nptr, const char **end, uint64_t *result);
int qemu_strtosz_MiB(const char *nptr, const char **end, uint64_t *result);
int qemu_strtosz_metric(const char *nptr, const char **end, uint64_t *result);

/* used to print char* safely */
#define STR_OR_NULL(str) ((str) ? (str) : "null")
Expand Down
2 changes: 1 addition & 1 deletion monitor.c
Original file line number Diff line number Diff line change
Expand Up @@ -3232,7 +3232,7 @@ static QDict *monitor_parse_arguments(Monitor *mon,
{
int ret;
uint64_t val;
char *end;
const char *end;

while (qemu_isspace(*p)) {
p++;
Expand Down
24 changes: 17 additions & 7 deletions tests/test-cutils.c
Original file line number Diff line number Diff line change
Expand Up @@ -1950,7 +1950,7 @@ static void test_qemu_strtou64_full_max(void)
static void test_qemu_strtosz_simple(void)
{
const char *str;
char *endptr = NULL;
const char *endptr;
int err;
uint64_t res = 0xbaadf00d;

Expand Down Expand Up @@ -2017,7 +2017,7 @@ static void test_qemu_strtosz_units(void)
const char *p = "1P";
const char *e = "1E";
int err;
char *endptr = NULL;
const char *endptr;
uint64_t res = 0xbaadf00d;

/* default is M */
Expand Down Expand Up @@ -2066,7 +2066,7 @@ static void test_qemu_strtosz_float(void)
{
const char *str = "12.345M";
int err;
char *endptr = NULL;
const char *endptr;
uint64_t res = 0xbaadf00d;

err = qemu_strtosz(str, &endptr, &res);
Expand All @@ -2078,7 +2078,7 @@ static void test_qemu_strtosz_float(void)
static void test_qemu_strtosz_invalid(void)
{
const char *str;
char *endptr = NULL;
const char *endptr;
int err;
uint64_t res = 0xbaadf00d;

Expand All @@ -2096,12 +2096,22 @@ static void test_qemu_strtosz_invalid(void)
err = qemu_strtosz(str, &endptr, &res);
g_assert_cmpint(err, ==, -EINVAL);
g_assert(endptr == str);

str = "inf";
err = qemu_strtosz(str, &endptr, &res);
g_assert_cmpint(err, ==, -EINVAL);
g_assert(endptr == str);

str = "NaN";
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;
const char *endptr;
int err;
uint64_t res = 0xbaadf00d;

Expand All @@ -2126,7 +2136,7 @@ static void test_qemu_strtosz_trailing(void)
static void test_qemu_strtosz_erange(void)
{
const char *str;
char *endptr = NULL;
const char *endptr;
int err;
uint64_t res = 0xbaadf00d;

Expand Down Expand Up @@ -2160,7 +2170,7 @@ static void test_qemu_strtosz_metric(void)
{
const char *str = "12345k";
int err;
char *endptr = NULL;
const char *endptr;
uint64_t res = 0xbaadf00d;

err = qemu_strtosz_metric(str, &endptr, &res);
Expand Down
18 changes: 8 additions & 10 deletions util/cutils.c
Original file line number Diff line number Diff line change
Expand Up @@ -203,23 +203,21 @@ static int64_t suffix_mul(char suffix, int64_t unit)
/*
* Convert string to bytes, allowing either B/b for bytes, K/k for KB,
* M/m for MB, G/g for GB or T/t for TB. End pointer will be returned
* in *end, if not NULL. Return -ERANGE on overflow, Return -EINVAL on
* in *end, if not NULL. Return -ERANGE on overflow, and -EINVAL on
* other error.
*/
static int do_strtosz(const char *nptr, char **end,
static int do_strtosz(const char *nptr, const char **end,
const char default_suffix, int64_t unit,
uint64_t *result)
{
int retval;
char *endptr;
const char *endptr;
unsigned char c;
int mul_required = 0;
double val, mul, integral, fraction;

errno = 0;
val = strtod(nptr, &endptr);
if (isnan(val) || endptr == nptr || errno != 0) {
retval = -EINVAL;
retval = qemu_strtod_finite(nptr, &endptr, &val);
if (retval) {
goto out;
}
fraction = modf(val, &integral);
Expand Down Expand Up @@ -259,17 +257,17 @@ static int do_strtosz(const char *nptr, char **end,
return retval;
}

int qemu_strtosz(const char *nptr, char **end, uint64_t *result)
int qemu_strtosz(const char *nptr, const 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)
int qemu_strtosz_MiB(const char *nptr, const char **end, uint64_t *result)
{
return do_strtosz(nptr, end, 'M', 1024, result);
}

int qemu_strtosz_metric(const char *nptr, char **end, uint64_t *result)
int qemu_strtosz_metric(const char *nptr, const char **end, uint64_t *result)
{
return do_strtosz(nptr, end, 'B', 1000, result);
}
Expand Down

0 comments on commit af02f4c

Please sign in to comment.