From 63ba0e14d0aed8d2d82c10d0b4706f204927da0c Mon Sep 17 00:00:00 2001 From: Dustin Sallings Date: Wed, 18 Mar 2009 19:36:52 -0700 Subject: Added safe_strtou?l functions. Some of the tests for this were written but commented out because they fail on some platforms. --- internal_tests.c | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++++ util.c | 44 ++++++++++++++++++++++++++++++++++++++++++++ util.h | 2 ++ 3 files changed, 98 insertions(+) diff --git a/internal_tests.c b/internal_tests.c index 0fcddef..b7661a0 100644 --- a/internal_tests.c +++ b/internal_tests.c @@ -7,7 +7,31 @@ #include "memcached.h" static void test_safe_strtoull(void); +static void test_safe_strtoul(void); static void test_safe_strtoll(void); +static void test_safe_strtol(void); + +static void test_safe_strtoul() { + uint32_t val; + assert(safe_strtoul("123", &val)); + assert(val == 123); + assert(safe_strtoul("+123", &val)); + assert(val == 123); + assert(!safe_strtoul("", &val)); // empty + assert(!safe_strtoul("123BOGUS", &val)); // non-numeric + /* Not sure what it does, but this works with ICC :/ + assert(!safe_strtoul("92837498237498237498029383", &val)); // out of range + */ + + // extremes: + assert(safe_strtoul("4294967295", &val)); // 2**32 - 1 + assert(val == 4294967295L); + /* This actually works on 64-bit ubuntu + assert(!safe_strtoul("4294967296", &val)); // 2**32 + */ + assert(!safe_strtoul("-1", &val)); // negative +} + static void test_safe_strtoull() { uint64_t val; @@ -51,12 +75,40 @@ static void test_safe_strtoll() { // We'll allow space to terminate the string. And leading space. assert(safe_strtoll(" 123 foo", &val)); assert(val == 123); +} + +static void test_safe_strtol() { + int32_t val; + assert(safe_strtol("123", &val)); + assert(val == 123); + assert(safe_strtol("+123", &val)); + assert(val == 123); + assert(safe_strtol("-123", &val)); + assert(val == -123); + assert(!safe_strtol("", &val)); // empty + assert(!safe_strtol("123BOGUS", &val)); // non-numeric + assert(!safe_strtol("92837498237498237498029383", &val)); // out of range + + // extremes: + /* This actually works on 64-bit ubuntu + assert(!safe_strtol("2147483648", &val)); // (expt 2.0 31.0) + */ + assert(safe_strtol("2147483647", &val)); // (- (expt 2.0 31) 1) + assert(val == 2147483647L); + /* This actually works on 64-bit ubuntu + assert(!safe_strtol("-2147483649", &val)); // (- (expt -2.0 31) 1) + */ + // We'll allow space to terminate the string. And leading space. + assert(safe_strtol(" 123 foo", &val)); + assert(val == 123); } int main(int argc, char **argv) { test_safe_strtoull(); test_safe_strtoll(); + test_safe_strtoul(); + test_safe_strtol(); printf("OK.\n"); return 0; } diff --git a/util.c b/util.c index a2d0728..307f7f0 100644 --- a/util.c +++ b/util.c @@ -44,3 +44,47 @@ bool safe_strtoll(const char *str, int64_t *out) { } return false; } + +bool safe_strtoul(const char *str, uint32_t *out) { + char *endptr = NULL; + unsigned long l = 0; + assert(out); + assert(str); + *out = 0; + errno = 0; + + l = strtoul(str, &endptr, 10); + if (errno == ERANGE) { + return false; + } + + if (isspace(*endptr) || (*endptr == '\0' && endptr != str)) { + if ((long) l < 0) { + /* only check for negative signs in the uncommon case when + * the unsigned number is so big that it's negative as a + * signed number. */ + if (strchr(str, '-') != NULL) { + return false; + } + } + *out = l; + return true; + } + + return false; +} + +bool safe_strtol(const char *str, int32_t *out) { + assert(out != NULL); + errno = 0; + *out = 0; + char *endptr; + long l = strtol(str, &endptr, 10); + if (errno == ERANGE) + return false; + if (isspace(*endptr) || (*endptr == '\0' && endptr != str)) { + *out = l; + return true; + } + return false; +} diff --git a/util.h b/util.h index b5a043f..9af886d 100644 --- a/util.h +++ b/util.h @@ -9,3 +9,5 @@ */ bool safe_strtoull(const char *str, uint64_t *out); bool safe_strtoll(const char *str, int64_t *out); +bool safe_strtoul(const char *str, uint32_t *out); +bool safe_strtol(const char *str, int32_t *out); -- cgit v1.2.1