Improved parsing of some integer arguments (sizes).
authorThomas Pornin <pornin@bolet.org>
Sat, 12 Nov 2016 14:23:43 +0000 (15:23 +0100)
committerThomas Pornin <pornin@bolet.org>
Sat, 12 Nov 2016 14:23:43 +0000 (15:23 +0100)
tools/brssl.h
tools/client.c
tools/names.c
tools/server.c

index 99ce38d..a3ceb14 100644 (file)
@@ -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.
  */
index 3686441..692b60f 100644 (file)
@@ -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,
index b34354e..191dfeb 100644 (file)
@@ -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
index a631982..0af6b42 100644 (file)
@@ -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,