From f190083fbc4ea2b9752950bf37a78f61abad12a0 Mon Sep 17 00:00:00 2001 From: Thomas Munro Date: Fri, 6 Dec 2024 09:31:16 +1300 Subject: [PATCH v2 4/5] pgbench: Modernize integer parsing routine. strtoint64() is from pre-C99 times and had comments about scanf() not being sure to handle long long. Even though C99 scanf() can do SCNi64, it seems like we'd lose a bit of error reporting. A more obvious modern drop-in is strtoi64(). Then strtoint64() can log the same errors as before. --- src/bin/pgbench/pgbench.c | 72 ++++++--------------------------------- 1 file changed, 11 insertions(+), 61 deletions(-) diff --git a/src/bin/pgbench/pgbench.c b/src/bin/pgbench/pgbench.c index acf55eccafb..0a9d3eefc8f 100644 --- a/src/bin/pgbench/pgbench.c +++ b/src/bin/pgbench/pgbench.c @@ -1003,9 +1003,6 @@ is_an_int(const char *str) /* * strtoint64 -- convert a string to 64-bit integer * - * This function is a slightly modified version of pg_strtoint64() from - * src/backend/utils/adt/numutils.c. - * * The function returns whether the conversion worked, and if so * "*result" is set to the result. * @@ -1014,71 +1011,24 @@ is_an_int(const char *str) bool strtoint64(const char *str, bool errorOK, int64 *result) { - const char *ptr = str; - int64 tmp = 0; - bool neg = false; - - /* - * Do our own scan, rather than relying on sscanf which might be broken - * for long long. - * - * As INT64_MIN can't be stored as a positive 64 bit integer, accumulate - * value as a negative number. - */ + char *end; - /* skip leading spaces */ - while (*ptr && isspace((unsigned char) *ptr)) - ptr++; + errno = 0; + *result = strtoi64(str, &end, 10); - /* handle sign */ - if (*ptr == '-') + if (errno == ERANGE) { - ptr++; - neg = true; - } - else if (*ptr == '+') - ptr++; - - /* require at least one digit */ - if (unlikely(!isdigit((unsigned char) *ptr))) - goto invalid_syntax; - - /* process digits */ - while (*ptr && isdigit((unsigned char) *ptr)) - { - int8 digit = (*ptr++ - '0'); - - if (unlikely(pg_mul_s64_overflow(tmp, 10, &tmp)) || - unlikely(pg_sub_s64_overflow(tmp, digit, &tmp))) - goto out_of_range; + if (!errorOK) + pg_log_error("value \"%s\" is out of range for type bigint", str); + return false; } - - /* allow trailing whitespace, but not other trailing chars */ - while (*ptr != '\0' && isspace((unsigned char) *ptr)) - ptr++; - - if (unlikely(*ptr != '\0')) - goto invalid_syntax; - - if (!neg) + if (str == end || *end != '\0') { - if (unlikely(tmp == PG_INT64_MIN)) - goto out_of_range; - tmp = -tmp; + if (!errorOK) + pg_log_error("invalid input syntax for type bigint: \"%s\"", str); + return false; } - - *result = tmp; return true; - -out_of_range: - if (!errorOK) - pg_log_error("value \"%s\" is out of range for type bigint", str); - return false; - -invalid_syntax: - if (!errorOK) - pg_log_error("invalid input syntax for type bigint: \"%s\"", str); - return false; } /* convert string to double, detecting overflows/underflows */ -- 2.48.1