summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNick Mathewson <nickm@torproject.org>2017-02-27 11:25:34 -0500
committerNick Mathewson <nickm@torproject.org>2017-02-27 11:25:34 -0500
commitc51919b0da2afe73780508e5593ebf9052e177cc (patch)
tree2dc3c47bf9beb1af0d77b9d195538a6fec9fc732
parent6747c62386964d961c3e98768e4dc9c51f8529de (diff)
parent074f24846321b8d08a8f67c37d72018842274c4e (diff)
downloadtor-c51919b0da2afe73780508e5593ebf9052e177cc.tar.gz
tor-c51919b0da2afe73780508e5593ebf9052e177cc.zip
Merge branch 'bug21369_check_029_squashed' into maint-0.3.0
-rw-r--r--changes/bug21369_check3
-rw-r--r--src/or/buffers.c21
-rw-r--r--src/or/dirserv.c10
3 files changed, 32 insertions, 2 deletions
diff --git a/changes/bug21369_check b/changes/bug21369_check
new file mode 100644
index 0000000000..2cd808c9b6
--- /dev/null
+++ b/changes/bug21369_check
@@ -0,0 +1,3 @@
+ o Minor features (reliability, crash):
+ - Try better to detect problems in buffers where they might grow (or
+ think they have grown) over 2 GB in size. Diagnostic for bug 21369.
diff --git a/src/or/buffers.c b/src/or/buffers.c
index 6111820701..603da1bb6e 100644
--- a/src/or/buffers.c
+++ b/src/or/buffers.c
@@ -610,6 +610,11 @@ read_to_buf(tor_socket_t s, size_t at_most, buf_t *buf, int *reached_eof,
tor_assert(reached_eof);
tor_assert(SOCKET_OK(s));
+ if (BUG(buf->datalen >= INT_MAX))
+ return -1;
+ if (BUG(buf->datalen >= INT_MAX - at_most))
+ return -1;
+
while (at_most > total_read) {
size_t readlen = at_most - total_read;
chunk_t *chunk;
@@ -667,6 +672,11 @@ read_to_buf_tls(tor_tls_t *tls, size_t at_most, buf_t *buf)
check();
+ if (BUG(buf->datalen >= INT_MAX))
+ return -1;
+ if (BUG(buf->datalen >= INT_MAX - at_most))
+ return -1;
+
while (at_most > total_read) {
size_t readlen = at_most - total_read;
chunk_t *chunk;
@@ -861,6 +871,11 @@ write_to_buf(const char *string, size_t string_len, buf_t *buf)
return (int)buf->datalen;
check();
+ if (BUG(buf->datalen >= INT_MAX))
+ return -1;
+ if (BUG(buf->datalen >= INT_MAX - string_len))
+ return -1;
+
while (string_len) {
size_t copy;
if (!buf->tail || !CHUNK_REMAINING_CAPACITY(buf->tail))
@@ -1010,6 +1025,12 @@ move_buf_to_buf(buf_t *buf_out, buf_t *buf_in, size_t *buf_flushlen)
/* We can do way better here, but this doesn't turn up in any profiles. */
char b[4096];
size_t cp, len;
+
+ if (BUG(buf_out->datalen >= INT_MAX))
+ return -1;
+ if (BUG(buf_out->datalen >= INT_MAX - *buf_flushlen))
+ return -1;
+
len = *buf_flushlen;
if (len > buf_in->datalen)
len = buf_in->datalen;
diff --git a/src/or/dirserv.c b/src/or/dirserv.c
index af01f8c283..f01668adcb 100644
--- a/src/or/dirserv.c
+++ b/src/or/dirserv.c
@@ -3658,8 +3658,14 @@ connection_dirserv_add_dir_bytes_to_outbuf(dir_connection_t *conn)
if (bytes < 8192)
bytes = 8192;
remaining = conn->cached_dir->dir_z_len - conn->cached_dir_offset;
- if (bytes > remaining)
+ if (BUG(remaining < 0)) {
+ remaining = 0;
+ }
+ if (bytes > remaining) {
bytes = (ssize_t) remaining;
+ if (BUG(bytes < 0))
+ return -1;
+ }
if (conn->zlib_state) {
connection_write_to_buf_zlib(
@@ -3670,7 +3676,7 @@ connection_dirserv_add_dir_bytes_to_outbuf(dir_connection_t *conn)
bytes, TO_CONN(conn));
}
conn->cached_dir_offset += bytes;
- if (conn->cached_dir_offset == (int)conn->cached_dir->dir_z_len) {
+ if (conn->cached_dir_offset >= (off_t)conn->cached_dir->dir_z_len) {
/* We just wrote the last one; finish up. */
connection_dirserv_finish_spooling(conn);
cached_dir_decref(conn->cached_dir);