diff options
author | Nick Mathewson <nickm@torproject.org> | 2017-03-16 11:21:52 -0400 |
---|---|---|
committer | Nick Mathewson <nickm@torproject.org> | 2017-03-16 14:42:56 -0400 |
commit | 643c9078c98cb81d51334cf03fdac76166e57f9a (patch) | |
tree | 255c9c71d692c0526d59685e5e696b44bb642063 /src/or/consdiff.c | |
parent | 672e2a5461c1a1f9160cadce4d9f1574856bf2cd (diff) | |
download | tor-643c9078c98cb81d51334cf03fdac76166e57f9a.tar.gz tor-643c9078c98cb81d51334cf03fdac76166e57f9a.zip |
Switch ed-command parsing to use tor_parse_long.
Diffstat (limited to 'src/or/consdiff.c')
-rw-r--r-- | src/or/consdiff.c | 68 |
1 files changed, 41 insertions, 27 deletions
diff --git a/src/or/consdiff.c b/src/or/consdiff.c index 510ebd9f3f..13b267f4a0 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': |