diff --git a/libc/fmt/strtol.c b/libc/fmt/strtol.c index 00b13f96d..f0892fbfa 100644 --- a/libc/fmt/strtol.c +++ b/libc/fmt/strtol.c @@ -17,6 +17,7 @@ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "libc/fmt/conv.h" +#include "libc/errno.h" #include "libc/limits.h" /** @@ -25,5 +26,15 @@ * @param optional_base is recommended as 0 for flexidecimal */ long strtol(const char *s, char **opt_out_end, int optional_base) { - return strtoimax(s, opt_out_end, optional_base); + intmax_t res; + res = strtoimax(s, opt_out_end, optional_base); + if (res < LONG_MIN) { + errno = ERANGE; + return LONG_MIN; + } + if (res > LONG_MAX) { + errno = ERANGE; + return LONG_MAX; + } + return res; } diff --git a/libc/fmt/strtoll.c b/libc/fmt/strtoll.c index bf65c7c4b..2ed524c15 100644 --- a/libc/fmt/strtoll.c +++ b/libc/fmt/strtoll.c @@ -17,12 +17,19 @@ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "libc/fmt/conv.h" +#include "libc/errno.h" #include "libc/limits.h" long long strtoll(const char *s, char **endptr, int optional_base) { - long long res; + intmax_t res; res = strtoimax(s, endptr, optional_base); - if (res < LONG_LONG_MIN) return LONG_LONG_MIN; - if (res > LONG_LONG_MAX) return LONG_LONG_MAX; + if (res < LONG_LONG_MIN) { + errno = ERANGE; + return LONG_LONG_MIN; + } + if (res > LONG_LONG_MAX) { + errno = ERANGE; + return LONG_LONG_MAX; + } return res; } diff --git a/libc/fmt/strtoul.c b/libc/fmt/strtoul.c index 430a4a2b1..1e9ef3a41 100644 --- a/libc/fmt/strtoul.c +++ b/libc/fmt/strtoul.c @@ -17,12 +17,19 @@ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "libc/fmt/conv.h" +#include "libc/errno.h" #include "libc/limits.h" unsigned long strtoul(const char *s, char **endptr, int optional_base) { - unsigned long long res; + intmax_t res; res = strtoimax(s, endptr, optional_base); - if (res < ULONG_MIN) return ULONG_MIN; - if (res > ULONG_MAX) return ULONG_MAX; + if (res < ULONG_MIN) { + errno = ERANGE; + return ULONG_MIN; + } + if (res > ULONG_MAX) { + errno = ERANGE; + return ULONG_MAX; + } return res; } diff --git a/libc/fmt/strtoull.c b/libc/fmt/strtoull.c index b3a3d7d17..94d4c3071 100644 --- a/libc/fmt/strtoull.c +++ b/libc/fmt/strtoull.c @@ -17,12 +17,19 @@ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "libc/fmt/conv.h" +#include "libc/errno.h" #include "libc/limits.h" unsigned long long strtoull(const char *s, char **endptr, int optional_base) { - unsigned long long res; + intmax_t res; res = strtoimax(s, endptr, optional_base); - if (res < ULONG_LONG_MIN) return ULONG_LONG_MIN; - if (res > ULONG_LONG_MAX) return ULONG_LONG_MAX; + if (res < ULONG_LONG_MIN) { + errno = ERANGE; + return ULONG_LONG_MIN; + } + if (res > ULONG_LONG_MAX) { + errno = ERANGE; + return ULONG_LONG_MAX; + } return res; } diff --git a/test/libc/fmt/strtoimax_test.c b/test/libc/fmt/strtoimax_test.c index 29186a816..df22d7f94 100644 --- a/test/libc/fmt/strtoimax_test.c +++ b/test/libc/fmt/strtoimax_test.c @@ -19,6 +19,7 @@ #include "libc/bits/bits.h" #include "libc/fmt/conv.h" #include "libc/testlib/testlib.h" +#include "libc/errno.h" TEST(strtoimax, testZero) { EXPECT_EQ(0, strtoimax("0", NULL, 0)); @@ -57,6 +58,17 @@ TEST(strtoimax, testTwosBane) { strtoimax("0x80000000000000000000000000000000", NULL, 0)); } -TEST(strtol, neghex) { - ASSERT_EQ(-16, strtol("0xfffffffffffffff0", NULL, 0)); +TEST(strtoul, neghex) { + errno = 0; + ASSERT_EQ(-16, (long) strtoul("0xfffffffffffffff0", NULL, 0)); + EXPECT_EQ(0, errno); +} + +TEST(strtol, testOutsideLimit) { + errno = 0; + EXPECT_EQ(0x7fffffffffffffff, strtol("0x8000000000000000", NULL, 0)); + EXPECT_EQ(ERANGE, errno); + errno = 0; + EXPECT_EQ(0x8000000000000000, strtol("-0x8000000000000001", NULL, 0)); + EXPECT_EQ(ERANGE, errno); } diff --git a/third_party/chibicc/as.c b/third_party/chibicc/as.c index ce33af3b4..8d59d04a6 100644 --- a/third_party/chibicc/as.c +++ b/third_party/chibicc/as.c @@ -782,7 +782,7 @@ static void Tokenize(struct As *a, int path) { a->things.p[a->things.n - 1].t = TT_FLOAT; } else { APPEND(a->ints); - a->ints.p[a->ints.n - 1] = strtol(p, NULL, 0); + a->ints.p[a->ints.n - 1] = strtoul(p, NULL, 0); a->things.p[a->things.n - 1].i = a->ints.n - 1; if (p[i] == 'f' || p[i] == 'F') { a->things.p[a->things.n - 1].t = TT_FORWARD;