diff --git a/changes/bug5786_range b/changes/bug5786_range new file mode 100644 index 0000000000..40ac4d2467 --- /dev/null +++ b/changes/bug5786_range @@ -0,0 +1,8 @@ + o Minor bugfixes: + - Make our number-parsing functions always treat too-large values + as an error, even when those values exceed the width of the + underlying type. Previously, if the caller provided these + functions with minima or maxima set to the extreme values of the + underlying integer type, these functions would return those + values on overflow rather than treating overflow as an error. + Fix for part of bug 5786; bugfix on Tor 0.0.9. \ No newline at end of file diff --git a/src/common/util.c b/src/common/util.c index 276c6dd13b..30bf6879ac 100644 --- a/src/common/util.c +++ b/src/common/util.c @@ -870,6 +870,9 @@ tor_digest256_is_zero(const char *digest) /* Helper: common code to check whether the result of a strtol or strtoul or * strtoll is correct. */ #define CHECK_STRTOX_RESULT() \ + /* Did an overflow occur? */ \ + if (errno == ERANGE) \ + goto err; \ /* Was at least one character converted? */ \ if (endptr == s) \ goto err; \ @@ -911,6 +914,8 @@ tor_parse_long(const char *s, int base, long min, long max, *ok = 0; return 0; } + + errno = 0; r = strtol(s, &endptr, base); CHECK_STRTOX_RESULT(); } @@ -928,6 +933,8 @@ tor_parse_ulong(const char *s, int base, unsigned long min, *ok = 0; return 0; } + + errno = 0; r = strtoul(s, &endptr, base); CHECK_STRTOX_RESULT(); } @@ -939,6 +946,7 @@ tor_parse_double(const char *s, double min, double max, int *ok, char **next) char *endptr; double r; + errno = 0; r = strtod(s, &endptr); CHECK_STRTOX_RESULT(); } @@ -958,6 +966,7 @@ tor_parse_uint64(const char *s, int base, uint64_t min, return 0; } + errno = 0; #ifdef HAVE_STRTOULL r = (uint64_t)strtoull(s, &endptr, base); #elif defined(_WIN32) diff --git a/src/test/test_util.c b/src/test/test_util.c index 7a455e06a9..e8f043a2c5 100644 --- a/src/test/test_util.c +++ b/src/test/test_util.c @@ -755,6 +755,21 @@ test_util_strmisc(void) test_eq(-10.0, d); } + { + /* Test tor_parse_* where we overflow/underflow the underlying type. */ + /* This string should overflow 64-bit ints. */ +#define TOOBIG "100000000000000000000000000" + test_eq(0L, tor_parse_long(TOOBIG, 10, LONG_MIN, LONG_MAX, &i, NULL)); + test_eq(i, 0); + test_eq(0L, tor_parse_long("-"TOOBIG, 10, LONG_MIN, LONG_MAX, &i, NULL)); + test_eq(i, 0); + test_eq(0UL, tor_parse_ulong(TOOBIG, 10, 0, ULONG_MAX, &i, NULL)); + test_eq(i, 0); + test_eq(U64_LITERAL(0), tor_parse_uint64(TOOBIG, 10, + 0, UINT64_MAX, &i, NULL)); + test_eq(i, 0); + } + /* Test snprintf */ /* Returning -1 when there's not enough room in the output buffer */ test_eq(-1, tor_snprintf(buf, 0, "Foo"));