[tor-commits] [tor/master] Switch ed-command parsing to use tor_parse_long.

nickm at torproject.org nickm at torproject.org
Thu Mar 16 19:01:08 UTC 2017


commit 643c9078c98cb81d51334cf03fdac76166e57f9a
Author: Nick Mathewson <nickm at torproject.org>
Date:   Thu Mar 16 11:21:52 2017 -0400

    Switch ed-command parsing to use tor_parse_long.
---
 src/or/consdiff.c | 68 +++++++++++++++++++++++++++++++++----------------------
 1 file changed, 41 insertions(+), 27 deletions(-)

diff --git a/src/or/consdiff.c b/src/or/consdiff.c
index 510ebd9..13b267f 100644
--- a/src/or/consdiff.c
+++ b/src/or/consdiff.c
@@ -748,6 +748,23 @@ gen_ed_diff(const smartlist_t *cons1, const smartlist_t *cons2,
   return NULL;
 }
 
+/* Helper: Read a base-10 number between 0 and INT32_MAX from <b>s</b> and
+ * store it in <b>num_out</b>.  Advance <b>s</b> to the characer immediately
+ * after the number.  Return 0 on success, -1 on failure. */
+static int
+get_linenum(const char **s, int *num_out)
+{
+  int ok;
+  char *next;
+  *num_out = (int) tor_parse_long(*s, 10, 0, INT32_MAX, &ok, &next);
+  if (ok && next) {
+    *s = next;
+    return 0;
+  } else {
+    return -1;
+  }
+}
+
 /** Apply the ed diff, starting at <b>diff_starting_line</b>, to the consensus
  * and return a new consensus, also as a line-based smartlist. Will return
  * NULL if the ed diff is not properly formatted.
@@ -766,42 +783,39 @@ apply_ed_diff(const smartlist_t *cons1, const smartlist_t *diff,
   for (int i=diff_starting_line; i<diff_len; ++i) {
     const cdline_t *diff_cdline = smartlist_get(diff, i);
     char diff_line[128];
-    char *endptr1, *endptr2;
 
     if (diff_cdline->len > sizeof(diff_line) - 1) {
       log_warn(LD_CONSDIFF, "Could not apply consensus diff because "
                "an ed command was far too long");
       goto error_cleanup;
     }
+    /* Copy the line to make it nul-terminated. */
     memcpy(diff_line, diff_cdline->s, diff_cdline->len);
     diff_line[diff_cdline->len] = 0;
-    int start = (int)strtol(diff_line, &endptr1, 10);
-    int end;
-    if (endptr1 == diff_line) {
+    const char *ptr = diff_line;
+    int start = 0, end = 0;
+    if (get_linenum(&ptr, &start) < 0) {
       log_warn(LD_CONSDIFF, "Could not apply consensus diff because "
-          "an ed command was missing a line number.");
+               "an ed command was missing a line number.");
       goto error_cleanup;
     }
-
-    /* Two-item range */
-    if (*endptr1 == ',') {
-        end = (int)strtol(endptr1+1, &endptr2, 10);
-        if (endptr2 == endptr1+1) {
-          log_warn(LD_CONSDIFF, "Could not apply consensus diff because "
-              "an ed command was missing a range end line number.");
-          goto error_cleanup;
-        }
-        /* Incoherent range. */
-        if (end <= start) {
-          log_warn(LD_CONSDIFF, "Could not apply consensus diff because "
-              "an invalid range was found in an ed command.");
-          goto error_cleanup;
-        }
-
-    /* We'll take <n1> as <n1>,<n1> for simplicity. */
+    if (*ptr == ',') {
+      /* Two-item range */
+      ++ptr;
+      if (get_linenum(&ptr, &end) < 0) {
+        log_warn(LD_CONSDIFF, "Could not apply consensus diff because "
+                 "an ed command was missing a range end line number.");
+        goto error_cleanup;
+      }
+      /* Incoherent range. */
+      if (end <= start) {
+        log_warn(LD_CONSDIFF, "Could not apply consensus diff because "
+                 "an invalid range was found in an ed command.");
+        goto error_cleanup;
+      }
     } else {
-        endptr2 = endptr1;
-        end = start;
+      /* We'll take <n1> as <n1>,<n1> for simplicity. */
+      end = start;
     }
 
     if (end > j) {
@@ -810,19 +824,19 @@ apply_ed_diff(const smartlist_t *cons1, const smartlist_t *diff,
       goto error_cleanup;
     }
 
-    if (*endptr2 == '\0') {
+    if (*ptr == '\0') {
       log_warn(LD_CONSDIFF, "Could not apply consensus diff because "
                "a line with no ed command was found");
       goto error_cleanup;
     }
 
-    if (*(endptr2+1) != '\0') {
+    if (*(ptr+1) != '\0') {
       log_warn(LD_CONSDIFF, "Could not apply consensus diff because "
           "an ed command longer than one char was found.");
       goto error_cleanup;
     }
 
-    char action = *endptr2;
+    char action = *ptr;
 
     switch (action) {
       case 'a':





More information about the tor-commits mailing list