cutils: Fix qemu_strtosz() & friends to reject non-finite sizes
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 <eblake@redhat.com> Reviewed-by: Markus Armbruster <armbru@redhat.com> Signed-off-by: David Hildenbrand <david@redhat.com> Message-Id: <20181121164421.20780-3-david@redhat.com> Signed-off-by: Markus Armbruster <armbru@redhat.com>
This commit is contained in:
parent
ca28f54816
commit
af02f4c517
@ -153,9 +153,9 @@ int parse_uint(const char *s, unsigned long long *value, char **endptr,
|
|||||||
int base);
|
int base);
|
||||||
int parse_uint_full(const char *s, unsigned long long *value, 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(const char *nptr, const char **end, uint64_t *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);
|
||||||
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);
|
||||||
|
|
||||||
/* used to print char* safely */
|
/* used to print char* safely */
|
||||||
#define STR_OR_NULL(str) ((str) ? (str) : "null")
|
#define STR_OR_NULL(str) ((str) ? (str) : "null")
|
||||||
|
@ -3232,7 +3232,7 @@ static QDict *monitor_parse_arguments(Monitor *mon,
|
|||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
uint64_t val;
|
uint64_t val;
|
||||||
char *end;
|
const char *end;
|
||||||
|
|
||||||
while (qemu_isspace(*p)) {
|
while (qemu_isspace(*p)) {
|
||||||
p++;
|
p++;
|
||||||
|
@ -1950,7 +1950,7 @@ static void test_qemu_strtou64_full_max(void)
|
|||||||
static void test_qemu_strtosz_simple(void)
|
static void test_qemu_strtosz_simple(void)
|
||||||
{
|
{
|
||||||
const char *str;
|
const char *str;
|
||||||
char *endptr = NULL;
|
const char *endptr;
|
||||||
int err;
|
int err;
|
||||||
uint64_t res = 0xbaadf00d;
|
uint64_t res = 0xbaadf00d;
|
||||||
|
|
||||||
@ -2017,7 +2017,7 @@ static void test_qemu_strtosz_units(void)
|
|||||||
const char *p = "1P";
|
const char *p = "1P";
|
||||||
const char *e = "1E";
|
const char *e = "1E";
|
||||||
int err;
|
int err;
|
||||||
char *endptr = NULL;
|
const char *endptr;
|
||||||
uint64_t res = 0xbaadf00d;
|
uint64_t res = 0xbaadf00d;
|
||||||
|
|
||||||
/* default is M */
|
/* default is M */
|
||||||
@ -2066,7 +2066,7 @@ static void test_qemu_strtosz_float(void)
|
|||||||
{
|
{
|
||||||
const char *str = "12.345M";
|
const char *str = "12.345M";
|
||||||
int err;
|
int err;
|
||||||
char *endptr = NULL;
|
const char *endptr;
|
||||||
uint64_t res = 0xbaadf00d;
|
uint64_t res = 0xbaadf00d;
|
||||||
|
|
||||||
err = qemu_strtosz(str, &endptr, &res);
|
err = qemu_strtosz(str, &endptr, &res);
|
||||||
@ -2078,7 +2078,7 @@ static void test_qemu_strtosz_float(void)
|
|||||||
static void test_qemu_strtosz_invalid(void)
|
static void test_qemu_strtosz_invalid(void)
|
||||||
{
|
{
|
||||||
const char *str;
|
const char *str;
|
||||||
char *endptr = NULL;
|
const char *endptr;
|
||||||
int err;
|
int err;
|
||||||
uint64_t res = 0xbaadf00d;
|
uint64_t res = 0xbaadf00d;
|
||||||
|
|
||||||
@ -2096,12 +2096,22 @@ static void test_qemu_strtosz_invalid(void)
|
|||||||
err = qemu_strtosz(str, &endptr, &res);
|
err = qemu_strtosz(str, &endptr, &res);
|
||||||
g_assert_cmpint(err, ==, -EINVAL);
|
g_assert_cmpint(err, ==, -EINVAL);
|
||||||
g_assert(endptr == str);
|
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)
|
static void test_qemu_strtosz_trailing(void)
|
||||||
{
|
{
|
||||||
const char *str;
|
const char *str;
|
||||||
char *endptr = NULL;
|
const char *endptr;
|
||||||
int err;
|
int err;
|
||||||
uint64_t res = 0xbaadf00d;
|
uint64_t res = 0xbaadf00d;
|
||||||
|
|
||||||
@ -2126,7 +2136,7 @@ static void test_qemu_strtosz_trailing(void)
|
|||||||
static void test_qemu_strtosz_erange(void)
|
static void test_qemu_strtosz_erange(void)
|
||||||
{
|
{
|
||||||
const char *str;
|
const char *str;
|
||||||
char *endptr = NULL;
|
const char *endptr;
|
||||||
int err;
|
int err;
|
||||||
uint64_t res = 0xbaadf00d;
|
uint64_t res = 0xbaadf00d;
|
||||||
|
|
||||||
@ -2160,7 +2170,7 @@ static void test_qemu_strtosz_metric(void)
|
|||||||
{
|
{
|
||||||
const char *str = "12345k";
|
const char *str = "12345k";
|
||||||
int err;
|
int err;
|
||||||
char *endptr = NULL;
|
const char *endptr;
|
||||||
uint64_t res = 0xbaadf00d;
|
uint64_t res = 0xbaadf00d;
|
||||||
|
|
||||||
err = qemu_strtosz_metric(str, &endptr, &res);
|
err = qemu_strtosz_metric(str, &endptr, &res);
|
||||||
|
@ -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,
|
* 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
|
* 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.
|
* 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,
|
const char default_suffix, int64_t unit,
|
||||||
uint64_t *result)
|
uint64_t *result)
|
||||||
{
|
{
|
||||||
int retval;
|
int retval;
|
||||||
char *endptr;
|
const char *endptr;
|
||||||
unsigned char c;
|
unsigned char c;
|
||||||
int mul_required = 0;
|
int mul_required = 0;
|
||||||
double val, mul, integral, fraction;
|
double val, mul, integral, fraction;
|
||||||
|
|
||||||
errno = 0;
|
retval = qemu_strtod_finite(nptr, &endptr, &val);
|
||||||
val = strtod(nptr, &endptr);
|
if (retval) {
|
||||||
if (isnan(val) || endptr == nptr || errno != 0) {
|
|
||||||
retval = -EINVAL;
|
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
fraction = modf(val, &integral);
|
fraction = modf(val, &integral);
|
||||||
@ -259,17 +257,17 @@ out:
|
|||||||
return retval;
|
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);
|
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);
|
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);
|
return do_strtosz(nptr, end, 'B', 1000, result);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user