commit 80730c45e032544155074022c0df5b6909b68faa Author: Nick Mathewson nickm@torproject.org Date: Tue Jun 26 21:02:29 2018 -0400
Move tor_parse_long and friends into parse_int.h in libtor-string --- src/common/util.c | 116 ----------------------------------------- src/common/util.h | 10 +--- src/lib/string/include.am | 2 + src/lib/string/parse_int.c | 126 +++++++++++++++++++++++++++++++++++++++++++++ src/lib/string/parse_int.h | 20 +++++++ src/test/test_util.c | 21 +------- 6 files changed, 150 insertions(+), 145 deletions(-)
diff --git a/src/common/util.c b/src/common/util.c index dbde0aa5b..2ea990d79 100644 --- a/src/common/util.c +++ b/src/common/util.c @@ -443,122 +443,6 @@ tor_digest256_is_zero(const char *digest) return tor_mem_is_zero(digest, DIGEST256_LEN); }
-/* Helper: common code to check whether the result of a strtol or strtoul or - * strtoll is correct. */ -#define CHECK_STRTOX_RESULT() \ - /* Did an overflow occur? */ \ - if (errno == ERANGE) \ - goto err; \ - /* Was at least one character converted? */ \ - if (endptr == s) \ - goto err; \ - /* Were there unexpected unconverted characters? */ \ - if (!next && *endptr) \ - goto err; \ - /* Illogical (max, min) inputs? */ \ - if (BUG(max < min)) \ - goto err; \ - /* Is r within limits? */ \ - if (r < min || r > max) \ - goto err; \ - if (ok) *ok = 1; \ - if (next) *next = endptr; \ - return r; \ - err: \ - if (ok) *ok = 0; \ - if (next) *next = endptr; \ - return 0 - -/** Extract a long from the start of <b>s</b>, in the given numeric - * <b>base</b>. If <b>base</b> is 0, <b>s</b> is parsed as a decimal, - * octal, or hex number in the syntax of a C integer literal. If - * there is unconverted data and <b>next</b> is provided, set - * *<b>next</b> to the first unconverted character. An error has - * occurred if no characters are converted; or if there are - * unconverted characters and <b>next</b> is NULL; or if the parsed - * value is not between <b>min</b> and <b>max</b>. When no error - * occurs, return the parsed value and set *<b>ok</b> (if provided) to - * 1. When an error occurs, return 0 and set *<b>ok</b> (if provided) - * to 0. - */ -long -tor_parse_long(const char *s, int base, long min, long max, - int *ok, char **next) -{ - char *endptr; - long r; - - if (BUG(base < 0)) { - if (ok) - *ok = 0; - return 0; - } - - errno = 0; - r = strtol(s, &endptr, base); - CHECK_STRTOX_RESULT(); -} - -/** As tor_parse_long(), but return an unsigned long. */ -unsigned long -tor_parse_ulong(const char *s, int base, unsigned long min, - unsigned long max, int *ok, char **next) -{ - char *endptr; - unsigned long r; - - if (BUG(base < 0)) { - if (ok) - *ok = 0; - return 0; - } - - errno = 0; - r = strtoul(s, &endptr, base); - CHECK_STRTOX_RESULT(); -} - -/** As tor_parse_long(), but return a double. */ -double -tor_parse_double(const char *s, double min, double max, int *ok, char **next) -{ - char *endptr; - double r; - - errno = 0; - r = strtod(s, &endptr); - CHECK_STRTOX_RESULT(); -} - -/** As tor_parse_long, but return a uint64_t. Only base 10 is guaranteed to - * work for now. */ -uint64_t -tor_parse_uint64(const char *s, int base, uint64_t min, - uint64_t max, int *ok, char **next) -{ - char *endptr; - uint64_t r; - - if (BUG(base < 0)) { - if (ok) - *ok = 0; - return 0; - } - - errno = 0; -#ifdef HAVE_STRTOULL - r = (uint64_t)strtoull(s, &endptr, base); -#elif defined(_WIN32) - r = (uint64_t)_strtoui64(s, &endptr, base); -#elif SIZEOF_LONG == 8 - r = (uint64_t)strtoul(s, &endptr, base); -#else -#error "I don't know how to parse 64-bit numbers." -#endif /* defined(HAVE_STRTOULL) || ... */ - - CHECK_STRTOX_RESULT(); -} - /** Return a newly allocated string equal to <b>string</b>, except that every * character in <b>chars_to_escape</b> is preceded by a backslash. */ char * diff --git a/src/common/util.h b/src/common/util.h index d2c27064e..26ee2d75a 100644 --- a/src/common/util.h +++ b/src/common/util.h @@ -26,6 +26,7 @@ #include "lib/malloc/util_malloc.h" #include "lib/wallclock/approx_time.h" #include "lib/string/util_string.h" +#include "lib/string/parse_int.h" #include "lib/string/scanf.h" #include "lib/intmath/bits.h" #include "lib/intmath/addsub.h" @@ -79,15 +80,6 @@ int64_t clamp_double_to_int64(double number);
/* String manipulation */
-long tor_parse_long(const char *s, int base, long min, - long max, int *ok, char **next); -unsigned long tor_parse_ulong(const char *s, int base, unsigned long min, - unsigned long max, int *ok, char **next); -double tor_parse_double(const char *s, double min, double max, int *ok, - char **next); -uint64_t tor_parse_uint64(const char *s, int base, uint64_t min, - uint64_t max, int *ok, char **next); - const char *hex_str(const char *from, size_t fromlen) ATTR_NONNULL((1));
int string_is_key_value(int severity, const char *string); diff --git a/src/lib/string/include.am b/src/lib/string/include.am index e532d5030..edd74b8a3 100644 --- a/src/lib/string/include.am +++ b/src/lib/string/include.am @@ -9,6 +9,7 @@ src_lib_libtor_string_a_SOURCES = \ src/lib/string/compat_ctype.c \ src/lib/string/compat_string.c \ src/lib/string/util_string.c \ + src/lib/string/parse_int.c \ src/lib/string/printf.c \ src/lib/string/scanf.c
@@ -21,5 +22,6 @@ noinst_HEADERS += \ src/lib/string/compat_ctype.h \ src/lib/string/compat_string.h \ src/lib/string/util_string.h \ + src/lib/string/parse_int.h \ src/lib/string/printf.h \ src/lib/string/scanf.h diff --git a/src/lib/string/parse_int.c b/src/lib/string/parse_int.c new file mode 100644 index 000000000..e552730cc --- /dev/null +++ b/src/lib/string/parse_int.c @@ -0,0 +1,126 @@ +/* Copyright (c) 2003, Roger Dingledine + * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. + * Copyright (c) 2007-2018, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ + +#include "lib/string/parse_int.h" + +#include <errno.h> +#include <stdlib.h> +#include <string.h> + +/* Helper: common code to check whether the result of a strtol or strtoul or + * strtoll is correct. */ +#define CHECK_STRTOX_RESULT() \ + /* Did an overflow occur? */ \ + if (errno == ERANGE) \ + goto err; \ + /* Was at least one character converted? */ \ + if (endptr == s) \ + goto err; \ + /* Were there unexpected unconverted characters? */ \ + if (!next && *endptr) \ + goto err; \ + /* Illogical (max, min) inputs? */ \ + if (max < min) \ + goto err; \ + /* Is r within limits? */ \ + if (r < min || r > max) \ + goto err; \ + if (ok) *ok = 1; \ + if (next) *next = endptr; \ + return r; \ + err: \ + if (ok) *ok = 0; \ + if (next) *next = endptr; \ + return 0 + +/** Extract a long from the start of <b>s</b>, in the given numeric + * <b>base</b>. If <b>base</b> is 0, <b>s</b> is parsed as a decimal, + * octal, or hex number in the syntax of a C integer literal. If + * there is unconverted data and <b>next</b> is provided, set + * *<b>next</b> to the first unconverted character. An error has + * occurred if no characters are converted; or if there are + * unconverted characters and <b>next</b> is NULL; or if the parsed + * value is not between <b>min</b> and <b>max</b>. When no error + * occurs, return the parsed value and set *<b>ok</b> (if provided) to + * 1. When an error occurs, return 0 and set *<b>ok</b> (if provided) + * to 0. + */ +long +tor_parse_long(const char *s, int base, long min, long max, + int *ok, char **next) +{ + char *endptr; + long r; + + if (base < 0) { + if (ok) + *ok = 0; + return 0; + } + + errno = 0; + r = strtol(s, &endptr, base); + CHECK_STRTOX_RESULT(); +} + +/** As tor_parse_long(), but return an unsigned long. */ +unsigned long +tor_parse_ulong(const char *s, int base, unsigned long min, + unsigned long max, int *ok, char **next) +{ + char *endptr; + unsigned long r; + + if (base < 0) { + if (ok) + *ok = 0; + return 0; + } + + errno = 0; + r = strtoul(s, &endptr, base); + CHECK_STRTOX_RESULT(); +} + +/** As tor_parse_long(), but return a double. */ +double +tor_parse_double(const char *s, double min, double max, int *ok, char **next) +{ + char *endptr; + double r; + + errno = 0; + r = strtod(s, &endptr); + CHECK_STRTOX_RESULT(); +} + +/** As tor_parse_long, but return a uint64_t. Only base 10 is guaranteed to + * work for now. */ +uint64_t +tor_parse_uint64(const char *s, int base, uint64_t min, + uint64_t max, int *ok, char **next) +{ + char *endptr; + uint64_t r; + + if (base < 0) { + if (ok) + *ok = 0; + return 0; + } + + errno = 0; +#ifdef HAVE_STRTOULL + r = (uint64_t)strtoull(s, &endptr, base); +#elif defined(_WIN32) + r = (uint64_t)_strtoui64(s, &endptr, base); +#elif SIZEOF_LONG == 8 + r = (uint64_t)strtoul(s, &endptr, base); +#else +#error "I don't know how to parse 64-bit numbers." +#endif /* defined(HAVE_STRTOULL) || ... */ + + CHECK_STRTOX_RESULT(); +} diff --git a/src/lib/string/parse_int.h b/src/lib/string/parse_int.h new file mode 100644 index 000000000..6f56fc32a --- /dev/null +++ b/src/lib/string/parse_int.h @@ -0,0 +1,20 @@ +/* Copyright (c) 2003, Roger Dingledine + * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. + * Copyright (c) 2007-2018, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ + +#ifndef TOR_PARSE_INT_H +#define TOR_PARSE_INT_H + +#include "lib/cc/torint.h" + +long tor_parse_long(const char *s, int base, long min, + long max, int *ok, char **next); +unsigned long tor_parse_ulong(const char *s, int base, unsigned long min, + unsigned long max, int *ok, char **next); +double tor_parse_double(const char *s, double min, double max, int *ok, + char **next); +uint64_t tor_parse_uint64(const char *s, int base, uint64_t min, + uint64_t max, int *ok, char **next); + +#endif diff --git a/src/test/test_util.c b/src/test/test_util.c index 73f353a3f..41570e14d 100644 --- a/src/test/test_util.c +++ b/src/test/test_util.c @@ -2117,20 +2117,10 @@ test_util_parse_integer(void *arg) tt_int_op(1,OP_EQ, i); tt_str_op(cp,OP_EQ, " plus garbage"); /* Illogical min max */ - tor_capture_bugs_(1); tt_int_op(0L,OP_EQ, tor_parse_long("10",10,50,4,&i,NULL)); tt_int_op(0,OP_EQ, i); - tt_int_op(1, OP_EQ, smartlist_len(tor_get_captured_bug_log_())); - tt_str_op("!(max < min)", OP_EQ, - smartlist_get(tor_get_captured_bug_log_(), 0)); - tor_end_capture_bugs_(); - tor_capture_bugs_(1); tt_int_op(0L,OP_EQ, tor_parse_long("-50",10,100,-100,&i,NULL)); tt_int_op(0,OP_EQ, i); - tt_int_op(1, OP_EQ, smartlist_len(tor_get_captured_bug_log_())); - tt_str_op("!(max < min)", OP_EQ, - smartlist_get(tor_get_captured_bug_log_(), 0)); - tor_end_capture_bugs_(); /* Out of bounds */ tt_int_op(0L,OP_EQ, tor_parse_long("10",10,50,100,&i,NULL)); tt_int_op(0,OP_EQ, i); @@ -2141,11 +2131,8 @@ test_util_parse_integer(void *arg) tt_int_op(0L,OP_EQ, tor_parse_long("2",2,0,100,NULL,NULL)); tt_int_op(68284L,OP_EQ, tor_parse_long("10abc",16,0,70000,NULL,NULL)); tt_int_op(68284L,OP_EQ, tor_parse_long("10ABC",16,0,70000,NULL,NULL)); - tor_capture_bugs_(2); tt_int_op(0L,OP_EQ, tor_parse_long("10",-2,0,100,NULL,NULL)); tt_int_op(0,OP_EQ, tor_parse_long("10ABC",-1,0,70000,&i,NULL)); - tt_int_op(2, OP_EQ, smartlist_len(tor_get_captured_bug_log_())); - tor_end_capture_bugs_(); tt_int_op(i,OP_EQ, 0);
/* Test parse_ulong */ @@ -2158,10 +2145,7 @@ test_util_parse_integer(void *arg) tt_int_op(0UL,OP_EQ, tor_parse_ulong("8",8,0,100,NULL,NULL)); tt_int_op(50UL,OP_EQ, tor_parse_ulong("50",10,50,100,NULL,NULL)); tt_int_op(0UL,OP_EQ, tor_parse_ulong("-50",10,0,100,NULL,NULL)); - tor_capture_bugs_(1); tt_int_op(0UL,OP_EQ, tor_parse_ulong("50",-1,50,100,&i,NULL)); - tt_int_op(1, OP_EQ, smartlist_len(tor_get_captured_bug_log_())); - tor_end_capture_bugs_(); tt_int_op(0,OP_EQ, i); tt_int_op(0UL,OP_EQ, tor_parse_ulong("-50",10,0,100,&i,NULL)); tt_int_op(0,OP_EQ, i); @@ -2177,11 +2161,8 @@ test_util_parse_integer(void *arg) tt_assert(U64_LITERAL(0) == tor_parse_uint64("12345678901",10,500,INT32_MAX, &i, &cp)); tt_int_op(0,OP_EQ, i); - tor_capture_bugs_(1); tt_assert(U64_LITERAL(0) == tor_parse_uint64("123",-1,0,INT32_MAX, &i, &cp)); - tt_int_op(1, OP_EQ, smartlist_len(tor_get_captured_bug_log_())); - tor_end_capture_bugs_(); tt_int_op(0,OP_EQ, i);
{ @@ -2226,7 +2207,7 @@ test_util_parse_integer(void *arg) tt_int_op(i,OP_EQ, 0); } done: - tor_end_capture_bugs_(); + ; }
static void