Browse Source

Make a bounds-checking replacement for strtol with slightly easier error-checking in the common case

svn:r2452
Nick Mathewson 21 years ago
parent
commit
19da1f36c2
2 changed files with 68 additions and 3 deletions
  1. 64 3
      src/common/util.c
  2. 4 0
      src/common/util.h

+ 64 - 3
src/common/util.c

@@ -2051,10 +2051,9 @@ parse_addr_port(const char *addrport, char **address, uint32_t *addr,
   colon = strchr(addrport, ':');
   colon = strchr(addrport, ':');
   if (colon) {
   if (colon) {
     _address = tor_strndup(addrport, colon-addrport);
     _address = tor_strndup(addrport, colon-addrport);
-    _port = atoi(colon+1);
-    if (_port<1 || _port>65535) {
+    _port = (int) tor_parse_long(colon+1,10,1,65535,NULL,NULL);
+    if (!_port) {
       log_fn(LOG_WARN, "Port '%s' out of range", colon+1);
       log_fn(LOG_WARN, "Port '%s' out of range", colon+1);
-      _port = 0;
       ok = 0;
       ok = 0;
     }
     }
   } else {
   } else {
@@ -2084,6 +2083,68 @@ parse_addr_port(const char *addrport, char **address, uint32_t *addr,
   return ok ? 0 : -1;
   return ok ? 0 : -1;
 }
 }
 
 
+/** Extract a long from the start of s, in the given numeric base.  If
+ * there is unconverted data and next is provided, set *next to the
+ * first unconverted character.  An error has occurred if no characters
+ * are converted; or if there are unconverted characters and next is NULL; or
+ * if the parsed value is not between min and max.  When no error occurs,
+ * return the parsed value and set *ok (if provided) to 1.  When an error
+ * ocurs, return 0 and set *ok (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;
+
+  r = strtol(s, &endptr, base);
+  /* Was at least one character converted? */
+  if (endptr == s)
+    goto err;
+  /* Were there unexpected unconverted characters? */
+  if (!next && *endptr)
+    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;
+}
+
+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;
+
+  r = strtol(s, &endptr, base);
+  /* Was at least one character converted? */
+  if (endptr == s)
+    goto err;
+  /* Were there unexpected unconverted characters? */
+  if (!next && *endptr)
+    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;
+}
+
 #ifndef MS_WINDOWS
 #ifndef MS_WINDOWS
 struct tor_mutex_t {
 struct tor_mutex_t {
 };
 };

+ 4 - 0
src/common/util.h

@@ -94,6 +94,10 @@ typedef enum {
 int tor_strpartition(char *dest, size_t dest_len,
 int tor_strpartition(char *dest, size_t dest_len,
                      const char *s, const char *insert, size_t n,
                      const char *s, const char *insert, size_t n,
                      part_finish_rule_t rule);
                      part_finish_rule_t rule);
+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);
 
 
 
 
 /* Some platforms segfault when you try to access a multi-byte type
 /* Some platforms segfault when you try to access a multi-byte type