diff options
-rw-r--r-- | payloads/libpayload/include/stdlib.h | 1 | ||||
-rw-r--r-- | payloads/libpayload/libc/string.c | 65 |
2 files changed, 26 insertions, 40 deletions
diff --git a/payloads/libpayload/include/stdlib.h b/payloads/libpayload/include/stdlib.h index 3f94d2119a..06fb735b75 100644 --- a/payloads/libpayload/include/stdlib.h +++ b/payloads/libpayload/include/stdlib.h @@ -186,6 +186,7 @@ static inline void *xmemalign_work(size_t align, size_t size, const char *file, * @{ */ long int strtol(const char *s, char **nptr, int base); +long long int strtoll(const char *s, char **nptr, int base); unsigned long int strtoul(const char *s, char **nptr, int base); unsigned long long int strtoull(const char *s, char **nptr, int base); long atol(const char *nptr); diff --git a/payloads/libpayload/libc/string.c b/payloads/libpayload/libc/string.c index f563f6338a..6c257cbdaa 100644 --- a/payloads/libpayload/libc/string.c +++ b/payloads/libpayload/libc/string.c @@ -33,6 +33,7 @@ #include <string.h> #include <ctype.h> #include <inttypes.h> +#include <limits.h> #include <errno.h> /** @@ -419,59 +420,43 @@ static int _offset(char ch, int base) * @return A signed integer representation of the string */ -long int strtol(const char *ptr, char **endptr, int base) +long long int strtoll(const char *orig_ptr, char **endptr, int base) { - int ret = 0; - int negative = 1; - - if (endptr != NULL) - *endptr = (char *) ptr; + const char *ptr = orig_ptr; + int is_negative = 0; /* Purge whitespace */ for( ; *ptr && isspace(*ptr); ptr++); if (ptr[0] == '-') { - negative = -1; + is_negative = 1; ptr++; } - if (!*ptr) - return 0; + unsigned long long uval = strtoull(ptr, endptr, base); - /* Determine the base */ + /* If the whole string is unparseable, endptr should point to start. */ + if (endptr && *endptr == ptr) + *endptr = (char *)orig_ptr; - if (base == 0) { - if (ptr[0] == '0' && (ptr[1] == 'x' || ptr[1] == 'X')) - base = 16; - else if (ptr[0] == '0') { - base = 8; - ptr++; - } - else - base = 10; - } - - /* Base 16 allows the 0x on front - so skip over it */ + if (uval > (unsigned long long)LLONG_MAX + !!is_negative) + uval = (unsigned long long)LLONG_MAX + !!is_negative; - if (base == 16) { - if (ptr[0] == '0' && (ptr[1] == 'x' || ptr[1] == 'X')) - ptr += 2; - } - - /* If the first character isn't valid, then don't - * bother */ - - if (!*ptr || !_valid(*ptr, base)) - return 0; - - for( ; *ptr && _valid(*ptr, base); ptr++) - ret = (ret * base) + _offset(*ptr, base); - - if (endptr != NULL) - *endptr = (char *) ptr; + if (is_negative) + return -uval; + else + return uval; +} - return ret * negative; +long int strtol(const char *ptr, char **endptr, int base) +{ + long long int val = strtoll(ptr, endptr, base); + if (val > LONG_MAX) + return LONG_MAX; + if (val < LONG_MIN) + return LONG_MIN; + return val; } long atol(const char *nptr) @@ -534,7 +519,7 @@ unsigned long long int strtoull(const char *ptr, char **endptr, int base) unsigned long int strtoul(const char *ptr, char **endptr, int base) { unsigned long long val = strtoull(ptr, endptr, base); - if (val > UINT32_MAX) return UINT32_MAX; + if (val > ULONG_MAX) return ULONG_MAX; return val; } |