From: Thomas Pornin Date: Sat, 12 Nov 2016 14:23:43 +0000 (+0100) Subject: Improved parsing of some integer arguments (sizes). X-Git-Tag: v0.4~60 X-Git-Url: https://bearssl.org/gitweb//home/git/?a=commitdiff_plain;h=0d974e1c9c284be028143fbbeaaac7faed8dca96;p=BearSSL Improved parsing of some integer arguments (sizes). --- diff --git a/tools/brssl.h b/tools/brssl.h index 99ce38d..a3ceb14 100644 --- a/tools/brssl.h +++ b/tools/brssl.h @@ -163,6 +163,12 @@ typedef VECTOR(unsigned char) bvector; */ int eqstr(const char *s1, const char *s2); +/* + * Convert a string to a positive integer (size_t). Returned value is + * (size_t)-1 on error. On error, an explicit error message is printed. + */ +size_t parse_size(const char *s); + /* * Structure for a known protocol version. */ diff --git a/tools/client.c b/tools/client.c index 3686441..692b60f 100644 --- a/tools/client.c +++ b/tools/client.c @@ -245,7 +245,11 @@ do_client(int argc, char *argv[]) usage_client(); goto client_exit_error; } - iobuf_len = strtoul(arg, 0, 10); + iobuf_len = parse_size(arg); + if (iobuf_len == (size_t)-1) { + usage_client(); + goto client_exit_error; + } } else if (eqstr(arg, "-CA")) { if (++ i >= argc) { fprintf(stderr, diff --git a/tools/names.c b/tools/names.c index b34354e..191dfeb 100644 --- a/tools/names.c +++ b/tools/names.c @@ -396,6 +396,60 @@ eqstr(const char *s1, const char *s2) return eqstr_chunk(s1, strlen(s1), s2, strlen(s2)); } +static int +hexval(int c) +{ + if (c >= '0' && c <= '9') { + return c - '0'; + } else if (c >= 'A' && c <= 'F') { + return c - 'A' + 10; + } else if (c >= 'a' && c <= 'f') { + return c - 'a' + 10; + } else { + return -1; + } +} + +/* see brssl.h */ +size_t +parse_size(const char *s) +{ + int radix; + size_t acc; + const char *t; + + t = s; + if (t[0] == '0' && (t[1] == 'x' || t[1] == 'X')) { + radix = 16; + t += 2; + } else { + radix = 10; + } + acc = 0; + for (;;) { + int c, d; + size_t z; + + c = *t ++; + if (c == 0) { + return acc; + } + d = hexval(c); + if (d < 0 || d >= radix) { + fprintf(stderr, "ERROR: not a valid digit: '%c'\n", c); + return (size_t)-1; + } + z = acc * (size_t)radix + (size_t)d; + if (z < (size_t)d || (z / (size_t)radix) != acc + || z == (size_t)-1) + { + fprintf(stderr, "ERROR: value too large: %s\n", s); + return (size_t)-1; + } + acc = z; + } +} + /* * Comma-separated list enumeration. This returns a pointer to the first * word in the string, skipping leading ignored characters. '*len' is diff --git a/tools/server.c b/tools/server.c index a631982..0af6b42 100644 --- a/tools/server.c +++ b/tools/server.c @@ -637,7 +637,11 @@ do_server(int argc, char *argv[]) usage_server(); goto server_exit_error; } - iobuf_len = strtoul(arg, 0, 10); + iobuf_len = parse_size(arg); + if (iobuf_len == (size_t)-1) { + usage_server(); + goto server_exit_error; + } } else if (eqstr(arg, "-cache")) { if (++ i >= argc) { fprintf(stderr, @@ -652,7 +656,11 @@ do_server(int argc, char *argv[]) usage_server(); goto server_exit_error; } - cache_len = strtoul(arg, 0, 10); + cache_len = parse_size(arg); + if (cache_len == (size_t)-1) { + usage_server(); + goto server_exit_error; + } } else if (eqstr(arg, "-cert")) { if (++ i >= argc) { fprintf(stderr,