summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDustin Sallings <dustin@spy.net>2009-03-18 19:36:52 -0700
committerDustin Sallings <dustin@spy.net>2009-03-19 01:52:54 -0700
commit63ba0e14d0aed8d2d82c10d0b4706f204927da0c (patch)
treed33cff43be95863ffaeb15f3dc88326db3678033
parenta977b5563ab73b764c5b257d6ed1f182b5cd92ca (diff)
downloadmemcached-63ba0e14d0aed8d2d82c10d0b4706f204927da0c.tar.gz
Added safe_strtou?l functions.
Some of the tests for this were written but commented out because they fail on some platforms.
-rw-r--r--internal_tests.c52
-rw-r--r--util.c44
-rw-r--r--util.h2
3 files changed, 98 insertions, 0 deletions
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);