diff --git a/qemu/include/qemu/cutils.h b/qemu/include/qemu/cutils.h index 34822da0..c77b9e77 100644 --- a/qemu/include/qemu/cutils.h +++ b/qemu/include/qemu/cutils.h @@ -131,9 +131,9 @@ int qemu_strtoi64(const char *nptr, const char **endptr, int base, int qemu_strtou64(const char *nptr, const char **endptr, int base, uint64_t *result); -int qemu_strtosz(const char *nptr, char **end, int64_t *result); -int qemu_strtosz_MiB(const char *nptr, char **end, int64_t *result); -int qemu_strtosz_metric(const char *nptr, char **end, int64_t *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); #define K_BYTE (1ULL << 10) #define M_BYTE (1ULL << 20) diff --git a/qemu/target/i386/cpu.c b/qemu/target/i386/cpu.c index a6f3e87d..0ac838c2 100644 --- a/qemu/target/i386/cpu.c +++ b/qemu/target/i386/cpu.c @@ -2182,10 +2182,10 @@ static void x86_cpu_parse_featurestr(CPUState *cs, char *features, /* Special case: */ if (!strcmp(name, "tsc-freq")) { int ret; - int64_t tsc_freq; + uint64_t tsc_freq; ret = qemu_strtosz_metric(val, NULL, &tsc_freq); - if (ret < 0) { + if (ret < 0 || tsc_freq > INT64_MAX) { error_setg(errp, "bad numerical value %s", val); return; } diff --git a/qemu/util/cutils.c b/qemu/util/cutils.c index dfa128fc..36847630 100644 --- a/qemu/util/cutils.c +++ b/qemu/util/cutils.c @@ -156,7 +156,7 @@ static int64_t suffix_mul(char suffix, int64_t unit) */ static int do_strtosz(const char *nptr, char **end, const char default_suffix, int64_t unit, - int64_t *result) + uint64_t *result) { int retval; char *endptr; @@ -186,7 +186,11 @@ static int do_strtosz(const char *nptr, char **end, 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 out; } @@ -203,17 +207,17 @@ out: return retval; } -int qemu_strtosz(const char *nptr, char **end, int64_t *result) +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, int64_t *result) +int qemu_strtosz_MiB(const char *nptr, char **end, uint64_t *result) { return do_strtosz(nptr, end, 'M', 1024, result); } -int qemu_strtosz_metric(const char *nptr, char **end, int64_t *result) +int qemu_strtosz_metric(const char *nptr, char **end, uint64_t *result) { return do_strtosz(nptr, end, 'B', 1000, result); }