relay: Remove logging for a bug. It triggers a BUG() later
[tor.git] / src / test / test_proto_misc.c
blobd575b8b3da05e0c271c8052acc60fdd07aa9780f
1 /* Copyright (c) 2017-2021, The Tor Project, Inc. */
2 /* See LICENSE for licensing information */
4 /**
5 * \file test_proto_misc.c
6 * \brief Test our smaller buffer-based protocol functions
7 */
9 #include "core/or/or.h"
10 #include "test/test.h"
11 #include "lib/buf/buffers.h"
12 #include "core/or/connection_or.h"
13 #include "feature/relay/ext_orport.h"
14 #include "core/proto/proto_cell.h"
15 #include "core/proto/proto_control0.h"
16 #include "core/proto/proto_ext_or.h"
18 #include "core/or/var_cell_st.h"
20 static void
21 test_proto_var_cell(void *arg)
23 (void)arg;
24 char *mem_op_hex_tmp = NULL;
25 char tmp[1024];
26 buf_t *buf = NULL;
27 var_cell_t *cell = NULL;
29 buf = buf_new();
30 memset(tmp, 0xf0, sizeof(tmp));
32 /* Short little commands will make us say "no cell yet." */
33 tt_int_op(0, OP_EQ, fetch_var_cell_from_buf(buf, &cell, 4));
34 tt_ptr_op(cell, OP_EQ, NULL);
35 buf_add(buf, "\x01\x02\x02\0x2", 4);
36 tt_int_op(0, OP_EQ, fetch_var_cell_from_buf(buf, &cell, 4));
37 /* An incomplete fixed-length cell makes us say "no cell yet". */
38 buf_add(buf, "\x03", 1);
39 tt_int_op(0, OP_EQ, fetch_var_cell_from_buf(buf, &cell, 4));
40 /* A complete fixed length-cell makes us say "not a variable-length cell" */
41 buf_add(buf, tmp, 509);
42 tt_int_op(0, OP_EQ, fetch_var_cell_from_buf(buf, &cell, 4));
43 buf_clear(buf);
45 /* An incomplete versions cell is a variable-length cell that isn't ready
46 * yet. */
47 buf_add(buf,
48 "\x01\x02\x03\x04" /* circid */
49 "\x07" /* VERSIONS */
50 "\x00\x04" /* 4 bytes long */
51 "\x00" /* incomplete */, 8);
52 tt_int_op(1, OP_EQ, fetch_var_cell_from_buf(buf, &cell, 4));
53 tt_ptr_op(cell, OP_EQ, NULL);
54 /* Complete it, and it's a variable-length cell. Leave a byte on the end for
55 * fun. */
56 buf_add(buf, "\x09\x00\x25\ff", 4);
57 tt_int_op(1, OP_EQ, fetch_var_cell_from_buf(buf, &cell, 4));
58 tt_ptr_op(cell, OP_NE, NULL);
59 tt_int_op(cell->command, OP_EQ, CELL_VERSIONS);
60 tt_uint_op(cell->circ_id, OP_EQ, 0x01020304);
61 tt_int_op(cell->payload_len, OP_EQ, 4);
62 test_mem_op_hex(cell->payload, OP_EQ, "00090025");
63 var_cell_free(cell);
64 cell = NULL;
65 tt_int_op(buf_datalen(buf), OP_EQ, 1);
66 buf_clear(buf);
68 /* In link protocol 3 and earlier, circid fields were two bytes long. Let's
69 * ensure that gets handled correctly. */
70 buf_add(buf,
71 "\x23\x45\x81\x00\x06" /* command 81; 6 bytes long */
72 "coraje", 11);
73 tt_int_op(1, OP_EQ, fetch_var_cell_from_buf(buf, &cell, 3));
74 tt_ptr_op(cell, OP_NE, NULL);
75 tt_int_op(cell->command, OP_EQ, 129);
76 tt_uint_op(cell->circ_id, OP_EQ, 0x2345);
77 tt_int_op(cell->payload_len, OP_EQ, 6);
78 tt_mem_op(cell->payload, OP_EQ, "coraje", 6);
79 var_cell_free(cell);
80 cell = NULL;
81 tt_int_op(buf_datalen(buf), OP_EQ, 0);
83 /* In link protocol 2, only VERSIONS cells counted as variable-length */
84 buf_add(buf,
85 "\x23\x45\x81\x00\x06"
86 "coraje", 11); /* As above */
87 tt_int_op(0, OP_EQ, fetch_var_cell_from_buf(buf, &cell, 2));
88 buf_clear(buf);
89 buf_add(buf,
90 "\x23\x45\x07\x00\x06"
91 "futuro", 11);
92 tt_int_op(1, OP_EQ, fetch_var_cell_from_buf(buf, &cell, 2));
93 tt_ptr_op(cell, OP_NE, NULL);
94 tt_int_op(cell->command, OP_EQ, 7);
95 tt_uint_op(cell->circ_id, OP_EQ, 0x2345);
96 tt_int_op(cell->payload_len, OP_EQ, 6);
97 tt_mem_op(cell->payload, OP_EQ, "futuro", 6);
98 var_cell_free(cell);
99 cell = NULL;
101 done:
102 buf_free(buf);
103 var_cell_free(cell);
104 tor_free(mem_op_hex_tmp);
107 static void
108 test_proto_control0(void *arg)
110 (void)arg;
111 buf_t *buf = buf_new();
113 /* The only remaining function for the v0 control protocol is the function
114 that detects whether the user has stumbled across an old controller
115 that's using it. The format was:
116 u16 length;
117 u16 command;
118 u8 body[length];
121 /* Empty buffer -- nothing to do. */
122 tt_int_op(0, OP_EQ, peek_buf_has_control0_command(buf));
123 /* 3 chars in buf -- can't tell */
124 buf_add(buf, "AUT", 3);
125 tt_int_op(0, OP_EQ, peek_buf_has_control0_command(buf));
126 /* command in buf -- easy to tell */
127 buf_add(buf, "HENTICATE ", 10);
128 tt_int_op(0, OP_EQ, peek_buf_has_control0_command(buf));
130 /* Control0 command header in buf: make sure we detect it. */
131 buf_clear(buf);
132 buf_add(buf, "\x09\x05" "\x00\x05" "blah", 8);
133 tt_int_op(1, OP_EQ, peek_buf_has_control0_command(buf));
135 done:
136 buf_free(buf);
139 static void
140 test_proto_ext_or_cmd(void *arg)
142 ext_or_cmd_t *cmd = NULL;
143 buf_t *buf = buf_new();
144 char *tmp = NULL;
145 (void) arg;
147 /* Empty -- should give "not there. */
148 tt_int_op(0, OP_EQ, fetch_ext_or_command_from_buf(buf, &cmd));
149 tt_ptr_op(NULL, OP_EQ, cmd);
151 /* Three bytes: shouldn't work. */
152 buf_add(buf, "\x00\x20\x00", 3);
153 tt_int_op(0, OP_EQ, fetch_ext_or_command_from_buf(buf, &cmd));
154 tt_ptr_op(NULL, OP_EQ, cmd);
155 tt_int_op(3, OP_EQ, buf_datalen(buf));
157 /* 0020 0000: That's a nil command. It should work. */
158 buf_add(buf, "\x00", 1);
159 tt_int_op(1, OP_EQ, fetch_ext_or_command_from_buf(buf, &cmd));
160 tt_ptr_op(NULL, OP_NE, cmd);
161 tt_int_op(0x20, OP_EQ, cmd->cmd);
162 tt_int_op(0, OP_EQ, cmd->len);
163 tt_int_op(0, OP_EQ, buf_datalen(buf));
164 ext_or_cmd_free(cmd);
165 cmd = NULL;
167 /* Now try a length-6 command with one byte missing. */
168 buf_add(buf, "\x10\x21\x00\x06""abcde", 9);
169 tt_int_op(0, OP_EQ, fetch_ext_or_command_from_buf(buf, &cmd));
170 tt_ptr_op(NULL, OP_EQ, cmd);
171 buf_add(buf, "f", 1);
172 tt_int_op(1, OP_EQ, fetch_ext_or_command_from_buf(buf, &cmd));
173 tt_ptr_op(NULL, OP_NE, cmd);
174 tt_int_op(0x1021, OP_EQ, cmd->cmd);
175 tt_int_op(6, OP_EQ, cmd->len);
176 tt_mem_op("abcdef", OP_EQ, cmd->body, 6);
177 tt_int_op(0, OP_EQ, buf_datalen(buf));
178 ext_or_cmd_free(cmd);
179 cmd = NULL;
181 /* Now try a length-10 command with 4 extra bytes. */
182 buf_add(buf, "\xff\xff\x00\x0aloremipsum\x10\x00\xff\xff", 18);
183 tt_int_op(1, OP_EQ, fetch_ext_or_command_from_buf(buf, &cmd));
184 tt_ptr_op(NULL, OP_NE, cmd);
185 tt_int_op(0xffff, OP_EQ, cmd->cmd);
186 tt_int_op(10, OP_EQ, cmd->len);
187 tt_mem_op("loremipsum", OP_EQ, cmd->body, 10);
188 tt_int_op(4, OP_EQ, buf_datalen(buf));
189 ext_or_cmd_free(cmd);
190 cmd = NULL;
192 /* Finally, let's try a maximum-length command. We already have the header
193 * waiting. */
194 tt_int_op(0, OP_EQ, fetch_ext_or_command_from_buf(buf, &cmd));
195 tmp = tor_malloc_zero(65535);
196 buf_add(buf, tmp, 65535);
197 tt_int_op(1, OP_EQ, fetch_ext_or_command_from_buf(buf, &cmd));
198 tt_ptr_op(NULL, OP_NE, cmd);
199 tt_int_op(0x1000, OP_EQ, cmd->cmd);
200 tt_int_op(0xffff, OP_EQ, cmd->len);
201 tt_mem_op(tmp, OP_EQ, cmd->body, 65535);
202 tt_int_op(0, OP_EQ, buf_datalen(buf));
203 ext_or_cmd_free(cmd);
204 cmd = NULL;
206 done:
207 ext_or_cmd_free(cmd);
208 buf_free(buf);
209 tor_free(tmp);
212 static void
213 test_proto_line(void *arg)
215 (void)arg;
216 char tmp[60];
217 buf_t *buf = buf_new();
218 #define S(str) str, sizeof(str)-1
219 const struct {
220 const char *input;
221 size_t input_len;
222 size_t line_len;
223 const char *output;
224 int returnval;
225 } cases[] = {
226 { S("Hello world"), 0, NULL, 0 },
227 { S("Hello world\n"), 12, "Hello world\n", 1 },
228 { S("Hello world\nMore"), 12, "Hello world\n", 1 },
229 { S("\n oh hello world\nMore"), 1, "\n", 1 },
230 { S("Hello worpd\n\nMore"), 12, "Hello worpd\n", 1 },
231 { S("------------------------------------------------------------\n"), 0,
232 NULL, -1 },
234 unsigned i;
235 for (i = 0; i < ARRAY_LENGTH(cases); ++i) {
236 buf_add(buf, cases[i].input, cases[i].input_len);
237 memset(tmp, 0xfe, sizeof(tmp));
238 size_t sz = sizeof(tmp);
239 int rv = buf_get_line(buf, tmp, &sz);
240 tt_int_op(rv, OP_EQ, cases[i].returnval);
241 if (rv == 1) {
242 tt_int_op(sz, OP_LT, sizeof(tmp));
243 tt_mem_op(cases[i].output, OP_EQ, tmp, sz+1);
244 tt_int_op(buf_datalen(buf), OP_EQ, cases[i].input_len - strlen(tmp));
245 tt_int_op(sz, OP_EQ, cases[i].line_len);
246 } else {
247 tt_int_op(buf_datalen(buf), OP_EQ, cases[i].input_len);
248 // tt_int_op(sz, OP_EQ, sizeof(tmp));
250 buf_clear(buf);
253 done:
254 buf_free(buf);
257 struct testcase_t proto_misc_tests[] = {
258 { "var_cell", test_proto_var_cell, 0, NULL, NULL },
259 { "control0", test_proto_control0, 0, NULL, NULL },
260 { "ext_or_cmd", test_proto_ext_or_cmd, TT_FORK, NULL, NULL },
261 { "line", test_proto_line, 0, NULL, NULL },
263 END_OF_TESTCASES