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.

Backports commit af02f4c5179675ad4e26b17ba26694a8fcde17fa from qemu
This commit is contained in:
David Hildenbrand 2018-12-18 04:48:10 -05:00 committed by Lioncash
parent bf15f4924b
commit 67f9141b13
No known key found for this signature in database
GPG key ID: 4E3C3CC1031BA9C7
2 changed files with 11 additions and 13 deletions

View file

@ -137,9 +137,9 @@ int qemu_strtou64(const char *nptr, const char **endptr, int base,
int qemu_strtod(const char *nptr, const char **endptr, double *result);
int qemu_strtod_finite(const char *nptr, const char **endptr, double *result);
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);
#define K_BYTE (1ULL << 10)
#define M_BYTE (1ULL << 20)

View file

@ -151,23 +151,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);
@ -207,17 +205,17 @@ out:
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);
}