aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorNick Mathewson <nickm@torproject.org>2005-07-15 19:31:11 +0000
committerNick Mathewson <nickm@torproject.org>2005-07-15 19:31:11 +0000
commitf8b48176ede5012ff21c67fa4d9a8c13c0e12860 (patch)
tree46f264c15e45d3b00ac35b5590b0cbb37c8159e0 /src
parent61f2ea0df0f30ca37f6e60676f6f6d2a957b8022 (diff)
downloadtor-f8b48176ede5012ff21c67fa4d9a8c13c0e12860.tar
tor-f8b48176ede5012ff21c67fa4d9a8c13c0e12860.tar.gz
Fix several bugs in read_escaped_data; add a unit test and a few docs
svn:r4580
Diffstat (limited to 'src')
-rw-r--r--src/or/control.c61
-rw-r--r--src/or/test.c18
2 files changed, 61 insertions, 18 deletions
diff --git a/src/or/control.c b/src/or/control.c
index b01a0093c..a0748a2fe 100644
--- a/src/or/control.c
+++ b/src/or/control.c
@@ -255,7 +255,9 @@ control_adjust_event_log_severity(void)
control_event_logmsg);
}
-/* DOCDOC */
+/** Append a NUL-terminated string <b>s</b> to the end of
+ * <b>conn</b>-\>outbuf
+ */
static INLINE void
connection_write_str_to_buf(const char *s, connection_t *conn)
{
@@ -263,8 +265,15 @@ connection_write_str_to_buf(const char *s, connection_t *conn)
connection_write_to_buf(s, len, conn);
}
-/* DOCDOC ; test */
-static size_t
+/** Given a <b>len</b>-character string in <b>data</b>, made of lines
+ * terminated by CRLF, allocate a new string in *<b>out</b>, and copy
+ * the contents of <b>data</b> into *<b>out</b>, adding a period
+ * before any period that that appears at the start of a line, and
+ * adding a period-CRLF line at the end. If <b>translate_newlines</b>
+ * is true, replace all LF characters sequences with CRLF. Return the
+ * number of bytes in *<b>out</b>.
+ */
+/* static */ size_t
write_escaped_data(const char *data, size_t len, int translate_newlines,
char **out)
{
@@ -305,31 +314,39 @@ write_escaped_data(const char *data, size_t len, int translate_newlines,
return outp - *out;
}
-/* DOCDOC ; test */
-static size_t
+/** Given a <b>len</b>-character string in <b>data</b>, made of lines
+ * terminated by CRLF, allocate a new string in *<b>out</b>, and copy
+ * the contents of <b>data</b> into *<b>out</b>, removing any period
+ * that appears at the start of a line. If <b>translate_newlines</b>
+ * is true, replace all CRLF sequences with LF. Return the number of
+ * bytes in *<b>out</b>. */
+/*static*/ size_t
read_escaped_data(const char *data, size_t len, int translate_newlines,
char **out)
{
char *outp;
const char *next;
+ const char *end;
+
+ *out = outp = tor_malloc(len+1);
- *out = outp = tor_malloc(len);
+ end = data+len;
- while (len) { /* XXX: len never changes during the loop? */
+ while (data < end) {
if (*data == '.')
++data;
if (translate_newlines)
- next = tor_memmem(data, len, "\r\n", 2);
- /* XXX: as data increases, we're reading past our allowed buffer! */
+ next = tor_memmem(data, end-data, "\r\n", 2);
else
- next = tor_memmem(data, len, "\r\n.", 3);
+ next = tor_memmem(data, end-data, "\r\n.", 3);
if (next) {
memcpy(outp, data, next-data);
outp += (next-data);
data = next+2;
} else {
- memcpy(outp, data, len); /* len is constant. scribbling from past *out. */
- outp += len;
+ memcpy(outp, data, end-data);
+ outp += (end-data);
+ *outp = '\0';
return outp - *out;
}
if (translate_newlines) {
@@ -340,6 +357,7 @@ read_escaped_data(const char *data, size_t len, int translate_newlines,
}
}
+ *outp = '\0';
return outp - *out;
}
@@ -390,7 +408,10 @@ get_escaped_string(const char *start, size_t in_len_max,
return end+1;
}
-/* DOCDOC */
+/** Acts like sprintf, but writes its formatted string to the end of
+ * <b>conn</b>-\>outbuf. The message may be truncated if it is too long,
+ * but it will always end with a CRLF sequence.
+ */
static void
connection_printf_to_buf(connection_t *conn, const char *format, ...)
{
@@ -1834,18 +1855,20 @@ connection_control_process_inbuf_v1(connection_t *conn)
while (1) {
size_t last_idx;
int r;
+ /* First, fetch a line. */
do {
data_len = conn->incoming_cmd_len - conn->incoming_cmd_cur_len;
r = fetch_from_buf_line(conn->inbuf,
- conn->incoming_cmd+conn->incoming_cmd_cur_len,
- &data_len);
+ conn->incoming_cmd+conn->incoming_cmd_cur_len,
+ &data_len);
if (r == 0)
/* Line not all here yet. Wait. */
return 0;
else if (r == -1) {
while (conn->incoming_cmd_len < data_len+conn->incoming_cmd_cur_len)
conn->incoming_cmd_len *= 2;
- conn->incoming_cmd = tor_realloc(conn->incoming_cmd, conn->incoming_cmd_len);
+ conn->incoming_cmd = tor_realloc(conn->incoming_cmd,
+ conn->incoming_cmd_len);
}
} while (r != 1);
@@ -1859,9 +1882,11 @@ connection_control_process_inbuf_v1(connection_t *conn)
/* One line command, didn't start with '+'. */
break;
if (last_idx+3 == conn->incoming_cmd_cur_len &&
- !memcmp(conn->incoming_cmd + last_idx, ".\r\n", 3))
- /* Just appended ".\r\n"; we're done. */
+ !memcmp(conn->incoming_cmd + last_idx, ".\r\n", 3)) {
+ /* Just appended ".\r\n"; we're done. Remove it. */
+ conn->incoming_cmd_cur_len -= 3;
break;
+ }
/* Otherwise, read another line. */
}
data_len = conn->incoming_cmd_cur_len;
diff --git a/src/or/test.c b/src/or/test.c
index c365113df..2e3e764e5 100644
--- a/src/or/test.c
+++ b/src/or/test.c
@@ -33,6 +33,8 @@ void add_fingerprint_to_dir(const char *nickname, const char *fp,
smartlist_t *list);
void get_platform_str(char *platform, size_t len);
int is_obsolete_version(const char *myversion, const char *start);
+size_t read_escaped_data(const char *data, size_t len, int translate_newlines,
+ char **out);
static char temp_dir[256];
@@ -1018,6 +1020,21 @@ test_strmap(void)
}
static void
+test_control_formats(void)
+{
+ char *out;
+ const char *inp =
+ "..This is a test\r\nof the emergency \nbroadcast\r\n..system.\r\nZ.\r\n";
+ size_t sz;
+
+ sz = read_escaped_data(inp, strlen(inp), 1, &out);
+ test_streq(out,
+ ".This is a test\nof the emergency \nbroadcast\n.system.\nZ.\n");
+
+ tor_free(out);
+}
+
+static void
test_onion(void)
{
#if 0
@@ -1521,6 +1538,7 @@ main(int c, char**v)
test_gzip();
test_util();
test_strmap();
+ test_control_formats();
puts("\n========================= Onion Skins =====================");
test_onion();
test_onion_handshake();