From 473a2a331ee382703f7ca0067ba2545350cfa06c Mon Sep 17 00:00:00 2001 From: "Daniel P. Berrange" Date: Fri, 22 Dec 2017 12:46:23 +0000 Subject: cutils: add qemu_strtoi & qemu_strtoui parsers for int/unsigned int types MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There are qemu_strtoNN functions for various sized integers. This adds two more for plain int & unsigned int types, with suitable range checking. Reviewed-by: Eric Blake Reviewed-by: Marc-André Lureau Signed-off-by: Daniel P. Berrange --- util/cutils.c | 109 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 109 insertions(+) (limited to 'util') diff --git a/util/cutils.c b/util/cutils.c index b33ede83d1..0de69e6db4 100644 --- a/util/cutils.c +++ b/util/cutils.c @@ -297,6 +297,115 @@ static int check_strtox_error(const char *nptr, char *ep, return -libc_errno; } +/** + * Convert string @nptr to an 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 INT_MAX in @result, + * and return -ERANGE. + * + * If the conversion underflows @result, store INT_MIN in @result, + * and return -ERANGE. + * + * Else store the converted value in @result, and return zero. + */ +int qemu_strtoi(const char *nptr, const char **endptr, int base, + int *result) +{ + char *ep; + long long lresult; + + if (!nptr) { + if (endptr) { + *endptr = nptr; + } + return -EINVAL; + } + + errno = 0; + lresult = strtoll(nptr, &ep, base); + if (lresult < INT_MIN) { + *result = INT_MIN; + errno = ERANGE; + } else if (lresult > INT_MAX) { + *result = INT_MAX; + errno = ERANGE; + } else { + *result = lresult; + } + return check_strtox_error(nptr, ep, endptr, errno); +} + +/** + * Convert string @nptr to an unsigned integer, 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 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 UINT_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_strtoui(const char *nptr, const char **endptr, int base, + unsigned int *result) +{ + char *ep; + long long lresult; + + if (!nptr) { + if (endptr) { + *endptr = nptr; + } + return -EINVAL; + } + + errno = 0; + lresult = strtoull(nptr, &ep, base); + + /* Windows returns 1 for negative out-of-range values. */ + if (errno == ERANGE) { + *result = -1; + } else { + if (lresult > UINT_MAX) { + *result = UINT_MAX; + errno = ERANGE; + } else if (lresult < INT_MIN) { + *result = UINT_MAX; + errno = ERANGE; + } else { + *result = lresult; + } + } + return check_strtox_error(nptr, ep, endptr, errno); +} + /** * Convert string @nptr to a long integer, and store it in @result. * -- cgit v1.2.3