diff --git a/src/libc/stdlib/stdlib_p.h b/src/libc/stdlib/stdlib_p.h index 1190863..f4a8288 100644 --- a/src/libc/stdlib/stdlib_p.h +++ b/src/libc/stdlib/stdlib_p.h @@ -15,7 +15,7 @@ (depending on use_unsigned). Signedness only affects the range of values that are considered to be ERANGE, and both results are stored in *outl. Similarly, if outll is non-NULL, strto_int produces a long long or unsigned - long long result. + long long result. Only one pointer should be non-NULL. On platforms where long is 32-bit, 64-bit operations are performed only if outll is non-NULL. This is because multiplications with overflow can be diff --git a/src/libc/stdlib/strto_int.c b/src/libc/stdlib/strto_int.c index 5c6abd8..ae4c9bd 100644 --- a/src/libc/stdlib/strto_int.c +++ b/src/libc/stdlib/strto_int.c @@ -96,6 +96,16 @@ int strto_int(char const * restrict ptr, char ** restrict endptr, int base, errno_value = ERANGE; } + /* Handle overflows */ + if(outl && errno_value == ERANGE) { + if(use_unsigned) xl = ULONG_MAX; + else xl = negative ? LONG_MIN : LONG_MAX; + } + if(outll && errno_value == ERANGE) { + if(use_unsigned) xll = ULLONG_MAX; + else xll = negative ? LLONG_MIN : LLONG_MAX; + } + if(outl) *outl = xl; if(outll) *outll = xll; if(endptr && valid) *endptr = (char *)ptr;