diff options
author | Nick Mathewson <nickm@torproject.org> | 2017-08-09 08:58:38 -0400 |
---|---|---|
committer | Nick Mathewson <nickm@torproject.org> | 2017-08-09 09:02:12 -0400 |
commit | 6f7d548bc428a5aa923c04cdcdab59af88a3495b (patch) | |
tree | 593149ea4549eeddd9cd2a4cd5c4ba5033c63956 /src/or/control.c | |
parent | 1280de42a41ccf7ae398cc86529c880455e9c5d1 (diff) | |
download | tor-6f7d548bc428a5aa923c04cdcdab59af88a3495b.tar.gz tor-6f7d548bc428a5aa923c04cdcdab59af88a3495b.zip |
Make write_escaped_data more robust to large inputs.
The old implementation would fail with super-long inputs. We never
gave it any, but still, it's nicer to dtrt here.
Reported by Guido Vranken. Fixes bug 19281.
Diffstat (limited to 'src/or/control.c')
-rw-r--r-- | src/or/control.c | 20 |
1 files changed, 14 insertions, 6 deletions
diff --git a/src/or/control.c b/src/or/control.c index 2ff1cc8442..4df670cd27 100644 --- a/src/or/control.c +++ b/src/or/control.c @@ -313,16 +313,23 @@ connection_write_str_to_buf(const char *s, control_connection_t *conn) STATIC size_t write_escaped_data(const char *data, size_t len, char **out) { - size_t sz_out = len+8; + tor_assert(len < SIZE_MAX - 9); + size_t sz_out = len+8+1; char *outp; const char *start = data, *end; - int i; + size_t i; int start_of_line; - for (i=0; i<(int)len; ++i) { - if (data[i]== '\n') + for (i=0; i < len; ++i) { + if (data[i] == '\n') { sz_out += 2; /* Maybe add a CR; maybe add a dot. */ + if (sz_out >= SIZE_T_CEILING) { + log_warn(LD_BUG, "Input to write_escaped_data was too long"); + *out = tor_strdup(".\r\n"); + return 3; + } + } } - *out = outp = tor_malloc(sz_out+1); + *out = outp = tor_malloc(sz_out); end = data+len; start_of_line = 1; while (data < end) { @@ -348,7 +355,8 @@ write_escaped_data(const char *data, size_t len, char **out) *outp++ = '\r'; *outp++ = '\n'; *outp = '\0'; /* NUL-terminate just in case. */ - tor_assert((outp - *out) <= (int)sz_out); + tor_assert(outp >= *out); + tor_assert((size_t)(outp - *out) <= sz_out); return outp - *out; } |