Line data Source code
1 : /* Copyright (c) 2001-2004, Roger Dingledine.
2 : * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
3 : * Copyright (c) 2007-2021, The Tor Project, Inc. */
4 : /* See LICENSE for licensing information */
5 :
6 : #include "orconfig.h"
7 : #define COMPAT_TIME_PRIVATE
8 : #define UTIL_MALLOC_PRIVATE
9 : #define PROCESS_WIN32_PRIVATE
10 : #include "lib/testsupport/testsupport.h"
11 : #include "core/or/or.h"
12 : #include "lib/buf/buffers.h"
13 : #include "app/config/config.h"
14 : #include "feature/control/control.h"
15 : #include "feature/control/control_proto.h"
16 : #include "feature/client/transports.h"
17 : #include "lib/crypt_ops/crypto_format.h"
18 : #include "lib/crypt_ops/crypto_rand.h"
19 : #include "lib/defs/time.h"
20 : #include "test/test.h"
21 : #include "test/test_helpers.h"
22 : #include "lib/memarea/memarea.h"
23 : #include "lib/process/waitpid.h"
24 : #include "lib/process/process_win32.h"
25 : #include "test/log_test_helpers.h"
26 : #include "lib/compress/compress.h"
27 : #include "lib/compress/compress_zstd.h"
28 : #include "lib/encoding/keyval.h"
29 : #include "lib/fdio/fdio.h"
30 : #include "lib/fs/winlib.h"
31 : #include "lib/process/env.h"
32 : #include "lib/process/pidfile.h"
33 : #include "lib/intmath/weakrng.h"
34 : #include "lib/intmath/muldiv.h"
35 : #include "lib/thread/numcpus.h"
36 : #include "lib/math/fp.h"
37 : #include "lib/math/laplace.h"
38 : #include "lib/meminfo/meminfo.h"
39 : #include "lib/time/tvdiff.h"
40 : #include "lib/encoding/confline.h"
41 : #include "lib/net/socketpair.h"
42 : #include "lib/malloc/map_anon.h"
43 :
44 : #ifdef HAVE_PWD_H
45 : #include <pwd.h>
46 : #endif
47 : #ifdef HAVE_SYS_UTIME_H
48 : #include <sys/utime.h>
49 : #endif
50 : #ifdef HAVE_UTIME_H
51 : #include <utime.h>
52 : #endif
53 : #ifdef HAVE_SYS_STAT_H
54 : #include <sys/stat.h>
55 : #endif
56 : #ifdef HAVE_FCNTL_H
57 : #include <fcntl.h>
58 : #endif
59 : #ifdef HAVE_UNISTD_H
60 : #include <unistd.h>
61 : #endif
62 : #ifdef HAVE_SYS_MMAN_H
63 : #include <sys/mman.h>
64 : #endif
65 : #ifdef HAVE_SYS_WAIT_H
66 : #include <sys/wait.h>
67 : #endif
68 :
69 : #ifdef _WIN32
70 : #include <tchar.h>
71 : #endif
72 : #include <math.h>
73 : #include <ctype.h>
74 : #include <float.h>
75 :
76 : /* These platforms don't have meaningful pwdb or homedirs. */
77 : #if defined(_WIN32) || defined(__ANDROID__)
78 : #define DISABLE_PWDB_TESTS
79 : #endif
80 :
81 : static void set_file_mtime(const char *fname, time_t when);
82 :
83 : #define INFINITY_DBL ((double)INFINITY)
84 : #define NAN_DBL ((double)NAN)
85 :
86 : /** Test the tor_isinf() wrapper */
87 : static void
88 1 : test_tor_isinf(void *arg)
89 : {
90 1 : (void) arg;
91 :
92 1 : tt_assert(tor_isinf(INFINITY_DBL));
93 :
94 1 : tt_assert(!tor_isinf(NAN_DBL));
95 1 : tt_assert(!tor_isinf(DBL_EPSILON));
96 1 : tt_assert(!tor_isinf(DBL_MAX));
97 1 : tt_assert(!tor_isinf(DBL_MIN));
98 :
99 1 : tt_assert(!tor_isinf(0.0));
100 1 : tt_assert(!tor_isinf(0.1));
101 1 : tt_assert(!tor_isinf(3));
102 1 : tt_assert(!tor_isinf(3.14));
103 :
104 1 : done:
105 1 : ;
106 1 : }
107 :
108 : /* XXXX this is a minimal wrapper to make the unit tests compile with the
109 : * changed tor_timegm interface. */
110 : static time_t
111 52 : tor_timegm_wrapper(const struct tm *tm)
112 : {
113 52 : time_t t;
114 52 : if (tor_timegm(tm, &t) < 0)
115 : return -1;
116 32 : return t;
117 : }
118 :
119 : #define tor_timegm tor_timegm_wrapper
120 :
121 : static void
122 6 : test_util_read_until_eof_impl(const char *fname, size_t file_len,
123 : size_t read_limit)
124 : {
125 6 : char *fifo_name = NULL;
126 6 : char *test_str = NULL;
127 6 : char *str = NULL;
128 6 : size_t sz = 9999999;
129 6 : int fd = -1;
130 6 : int r;
131 :
132 6 : fifo_name = tor_strdup(get_fname(fname));
133 6 : test_str = tor_malloc(file_len);
134 6 : crypto_rand(test_str, file_len);
135 :
136 6 : r = write_bytes_to_file(fifo_name, test_str, file_len, 1);
137 6 : tt_int_op(r, OP_EQ, 0);
138 :
139 6 : fd = open(fifo_name, O_RDONLY|O_BINARY);
140 6 : tt_int_op(fd, OP_GE, 0);
141 6 : str = read_file_to_str_until_eof(fd, read_limit, &sz);
142 6 : tt_ptr_op(str, OP_NE, NULL);
143 :
144 6 : if (read_limit < file_len)
145 2 : tt_int_op(sz, OP_EQ, read_limit);
146 : else
147 4 : tt_int_op(sz, OP_EQ, file_len);
148 :
149 6 : tt_mem_op(test_str, OP_EQ, str, sz);
150 6 : tt_int_op(str[sz], OP_EQ, '\0');
151 :
152 6 : done:
153 6 : unlink(fifo_name);
154 6 : tor_free(fifo_name);
155 6 : tor_free(test_str);
156 6 : tor_free(str);
157 6 : if (fd >= 0)
158 6 : close(fd);
159 6 : }
160 :
161 : static void
162 1 : test_util_read_file_eof_tiny_limit(void *arg)
163 : {
164 1 : (void)arg;
165 : // purposely set limit shorter than what we wrote to the FIFO to
166 : // test the maximum, and that it puts the NUL in the right spot
167 :
168 1 : test_util_read_until_eof_impl("tor_test_fifo_tiny", 5, 4);
169 1 : }
170 :
171 : static void
172 1 : test_util_read_file_eof_one_loop_a(void *arg)
173 : {
174 1 : (void)arg;
175 1 : test_util_read_until_eof_impl("tor_test_fifo_1ka", 1024, 1023);
176 1 : }
177 :
178 : static void
179 1 : test_util_read_file_eof_one_loop_b(void *arg)
180 : {
181 1 : (void)arg;
182 1 : test_util_read_until_eof_impl("tor_test_fifo_1kb", 1024, 1024);
183 1 : }
184 :
185 : static void
186 1 : test_util_read_file_eof_two_loops(void *arg)
187 : {
188 1 : (void)arg;
189 : // write more than 1024 bytes to the FIFO to test two passes through
190 : // the loop in the method; if the re-alloc size is changed this
191 : // should be updated as well.
192 :
193 1 : test_util_read_until_eof_impl("tor_test_fifo_2k", 2048, 10000);
194 1 : }
195 :
196 : static void
197 1 : test_util_read_file_eof_two_loops_b(void *arg)
198 : {
199 1 : (void)arg;
200 :
201 1 : test_util_read_until_eof_impl("tor_test_fifo_2kb", 2048, 2048);
202 1 : }
203 :
204 : static void
205 1 : test_util_read_file_eof_zero_bytes(void *arg)
206 : {
207 1 : (void)arg;
208 : // zero-byte fifo
209 1 : test_util_read_until_eof_impl("tor_test_fifo_empty", 0, 10000);
210 1 : }
211 :
212 : static void
213 1 : test_util_read_file_endlines(void *arg)
214 : {
215 1 : (void)arg;
216 :
217 1 : char *fname = NULL;
218 1 : char *read_content = NULL;
219 1 : int r = -1;
220 :
221 : /* Write a file that contains both \n and \r\n as line ending. */
222 1 : const char *file_content = "foo bar\n"
223 : "foo bar baz\r\n"
224 : "foo bar\r\n";
225 :
226 1 : const char *expected_file_content = "foo bar\n"
227 : "foo bar baz\n"
228 : "foo bar\n";
229 :
230 1 : fname = tor_strdup(get_fname("file_with_crlf_ending"));
231 :
232 1 : r = write_bytes_to_file(fname, file_content, strlen(file_content), 1);
233 1 : tt_int_op(r, OP_EQ, 0);
234 :
235 : /* Read the file in text mode: we strip \r's from the files on both Windows
236 : * and UNIX. */
237 1 : read_content = read_file_to_str(fname, 0, NULL);
238 :
239 1 : tt_ptr_op(read_content, OP_NE, NULL);
240 1 : tt_int_op(strlen(read_content), OP_EQ, strlen(expected_file_content));
241 1 : tt_str_op(read_content, OP_EQ, expected_file_content);
242 :
243 1 : tor_free(read_content);
244 :
245 : /* Read the file in binary mode: we should preserve the \r here. */
246 1 : read_content = read_file_to_str(fname, RFTS_BIN, NULL);
247 :
248 1 : tt_ptr_op(read_content, OP_NE, NULL);
249 1 : tt_int_op(strlen(read_content), OP_EQ, strlen(file_content));
250 1 : tt_str_op(read_content, OP_EQ, file_content);
251 :
252 1 : tor_free(read_content);
253 :
254 1 : done:
255 1 : unlink(fname);
256 1 : tor_free(fname);
257 1 : tor_free(read_content);
258 1 : }
259 :
260 : /* Test the basic expected behaviour for write_chunks_to_file.
261 : * NOTE: This will need to be updated if we ever change the tempfile location
262 : * or extension */
263 : static void
264 1 : test_util_write_chunks_to_file(void *arg)
265 : {
266 1 : char *fname = NULL;
267 1 : char *tempname = NULL;
268 1 : char *str = NULL;
269 1 : int r;
270 1 : struct stat st;
271 :
272 : /* These should be two different sizes to ensure the data is different
273 : * between the data file and the temp file's 'known string' */
274 1 : int temp_str_len = 1024;
275 1 : int data_str_len = 512;
276 1 : char *data_str = tor_malloc(data_str_len);
277 1 : char *temp_str = tor_malloc(temp_str_len);
278 :
279 1 : smartlist_t *chunks = smartlist_new();
280 1 : sized_chunk_t c = {data_str, data_str_len/2};
281 1 : sized_chunk_t c2 = {data_str + data_str_len/2, data_str_len/2};
282 1 : (void)arg;
283 :
284 1 : crypto_rand(temp_str, temp_str_len);
285 1 : crypto_rand(data_str, data_str_len);
286 :
287 : // Ensure it can write multiple chunks
288 :
289 1 : smartlist_add(chunks, &c);
290 1 : smartlist_add(chunks, &c2);
291 :
292 : /*
293 : * Check if it writes using a tempfile
294 : */
295 1 : fname = tor_strdup(get_fname("write_chunks_with_tempfile"));
296 1 : tor_asprintf(&tempname, "%s.tmp", fname);
297 :
298 : // write a known string to a file where the tempfile will be
299 1 : r = write_bytes_to_file(tempname, temp_str, temp_str_len, 1);
300 1 : tt_int_op(r, OP_EQ, 0);
301 :
302 : // call write_chunks_to_file
303 1 : r = write_chunks_to_file(fname, chunks, 1, 0);
304 1 : tt_int_op(r, OP_EQ, 0);
305 :
306 : // assert the file has been written (expected size)
307 1 : str = read_file_to_str(fname, RFTS_BIN, &st);
308 1 : tt_assert(str != NULL);
309 1 : tt_u64_op((uint64_t)st.st_size, OP_EQ, data_str_len);
310 1 : tt_mem_op(data_str, OP_EQ, str, data_str_len);
311 1 : tor_free(str);
312 :
313 : // assert that the tempfile is removed (should not leave artifacts)
314 1 : str = read_file_to_str(tempname, RFTS_BIN|RFTS_IGNORE_MISSING, &st);
315 1 : tt_assert(str == NULL);
316 :
317 : // Remove old testfile for second test
318 1 : r = unlink(fname);
319 1 : tt_int_op(r, OP_EQ, 0);
320 1 : tor_free(fname);
321 1 : tor_free(tempname);
322 :
323 : /*
324 : * Check if it skips using a tempfile with flags
325 : */
326 1 : fname = tor_strdup(get_fname("write_chunks_with_no_tempfile"));
327 1 : tor_asprintf(&tempname, "%s.tmp", fname);
328 :
329 : // write a known string to a file where the tempfile will be
330 1 : r = write_bytes_to_file(tempname, temp_str, temp_str_len, 1);
331 1 : tt_int_op(r, OP_EQ, 0);
332 :
333 : // call write_chunks_to_file with no_tempfile = true
334 1 : r = write_chunks_to_file(fname, chunks, 1, 1);
335 1 : tt_int_op(r, OP_EQ, 0);
336 :
337 : // assert the file has been written (expected size)
338 1 : str = read_file_to_str(fname, RFTS_BIN, &st);
339 1 : tt_assert(str != NULL);
340 1 : tt_u64_op((uint64_t)st.st_size, OP_EQ, data_str_len);
341 1 : tt_mem_op(data_str, OP_EQ, str, data_str_len);
342 1 : tor_free(str);
343 :
344 : // assert the tempfile still contains the known string
345 1 : str = read_file_to_str(tempname, RFTS_BIN, &st);
346 1 : tt_assert(str != NULL);
347 1 : tt_u64_op((uint64_t)st.st_size, OP_EQ, temp_str_len);
348 1 : tt_mem_op(temp_str, OP_EQ, str, temp_str_len);
349 :
350 1 : done:
351 1 : unlink(fname);
352 1 : unlink(tempname);
353 1 : smartlist_free(chunks);
354 1 : tor_free(fname);
355 1 : tor_free(tempname);
356 1 : tor_free(str);
357 1 : tor_free(data_str);
358 1 : tor_free(temp_str);
359 1 : }
360 :
361 : /* Test write_str_to_file_if_not_equal(). */
362 : static void
363 1 : test_util_write_str_if_changed(void *arg)
364 : {
365 1 : (void)arg;
366 1 : char *fname = tor_strdup(get_fname("write_if_changed"));
367 1 : char *s = NULL;
368 1 : int rv;
369 1 : const char str1[] = "The wombat lives across the seas";
370 1 : const char str2[] = "Among the far Antipodes"; /* -- Ogden Nash */
371 :
372 : /* We can create files. */
373 1 : rv = write_str_to_file_if_not_equal(fname, str1);
374 1 : tt_int_op(rv, OP_EQ, 0);
375 1 : s = read_file_to_str(fname, 0, NULL);
376 1 : tt_str_op(s, OP_EQ, str1);
377 1 : tor_free(s);
378 :
379 : /* We can replace files. */
380 1 : rv = write_str_to_file_if_not_equal(fname, str2);
381 1 : tt_int_op(rv, OP_EQ, 0);
382 1 : s = read_file_to_str(fname, 0, NULL);
383 1 : tt_str_op(s, OP_EQ, str2);
384 1 : tor_free(s);
385 :
386 : /* Make sure we don't replace files when they're equal. (That's the whole
387 : * point of the function we're testing. */
388 : /* First, change the mtime of the file so that we can tell whether we
389 : * replaced it. */
390 1 : const time_t now = time(NULL);
391 1 : const time_t five_sec_ago = now - 5;
392 1 : set_file_mtime(fname, five_sec_ago);
393 1 : rv = write_str_to_file_if_not_equal(fname, str2);
394 1 : tt_int_op(rv, OP_EQ, 0);
395 : /* Make sure that the file's mtime is unchanged... */
396 1 : struct stat st;
397 1 : rv = stat(fname, &st);
398 1 : tt_int_op(rv, OP_EQ, 0);
399 1 : tt_i64_op(st.st_mtime, OP_EQ, five_sec_ago);
400 : /* And make sure its contents are unchanged. */
401 1 : s = read_file_to_str(fname, 0, NULL);
402 1 : tt_str_op(s, OP_EQ, str2);
403 1 : tor_free(s);
404 :
405 1 : done:
406 1 : tor_free(fname);
407 1 : tor_free(s);
408 1 : }
409 :
410 : #ifndef COCCI
411 : #define _TFE(a, b, f) tt_int_op((a).f, OP_EQ, (b).f)
412 : /** test the minimum set of struct tm fields needed for a unique epoch value
413 : * this is also the set we use to test tor_timegm */
414 : #define TM_EQUAL(a, b) \
415 : TT_STMT_BEGIN \
416 : _TFE(a, b, tm_year); \
417 : _TFE(a, b, tm_mon ); \
418 : _TFE(a, b, tm_mday); \
419 : _TFE(a, b, tm_hour); \
420 : _TFE(a, b, tm_min ); \
421 : _TFE(a, b, tm_sec ); \
422 : TT_STMT_END
423 : #endif /* !defined(COCCI) */
424 :
425 : static void
426 1 : test_util_time(void *arg)
427 : {
428 1 : struct timeval start, end;
429 1 : struct tm a_time, b_time;
430 1 : char timestr[128];
431 1 : time_t t_res;
432 1 : int i;
433 1 : struct timeval tv;
434 :
435 : /* Test tv_udiff and tv_mdiff */
436 :
437 1 : (void)arg;
438 1 : start.tv_sec = 5;
439 1 : start.tv_usec = 5000;
440 :
441 1 : end.tv_sec = 5;
442 1 : end.tv_usec = 5000;
443 :
444 1 : tt_int_op(0L,OP_EQ, tv_udiff(&start, &end));
445 1 : tt_int_op(0L,OP_EQ, tv_mdiff(&start, &end));
446 1 : tt_int_op(0L,OP_EQ, tv_udiff(&end, &start));
447 1 : tt_int_op(0L,OP_EQ, tv_mdiff(&end, &start));
448 :
449 1 : end.tv_usec = 7000;
450 :
451 1 : tt_int_op(2000L,OP_EQ, tv_udiff(&start, &end));
452 1 : tt_int_op(2L,OP_EQ, tv_mdiff(&start, &end));
453 1 : tt_int_op(-2000L,OP_EQ, tv_udiff(&end, &start));
454 1 : tt_int_op(-2L,OP_EQ, tv_mdiff(&end, &start));
455 :
456 1 : end.tv_sec = 6;
457 :
458 1 : tt_int_op(1002000L,OP_EQ, tv_udiff(&start, &end));
459 1 : tt_int_op(1002L,OP_EQ, tv_mdiff(&start, &end));
460 1 : tt_int_op(-1002000L,OP_EQ, tv_udiff(&end, &start));
461 1 : tt_int_op(-1002L,OP_EQ, tv_mdiff(&end, &start));
462 :
463 1 : end.tv_usec = 0;
464 :
465 1 : tt_int_op(995000L,OP_EQ, tv_udiff(&start, &end));
466 1 : tt_int_op(995L,OP_EQ, tv_mdiff(&start, &end));
467 1 : tt_int_op(-995000L,OP_EQ, tv_udiff(&end, &start));
468 1 : tt_int_op(-995L,OP_EQ, tv_mdiff(&end, &start));
469 :
470 1 : end.tv_sec = 4;
471 :
472 1 : tt_int_op(-1005000L,OP_EQ, tv_udiff(&start, &end));
473 1 : tt_int_op(-1005L,OP_EQ, tv_mdiff(&start, &end));
474 1 : tt_int_op(1005000L,OP_EQ, tv_udiff(&end, &start));
475 1 : tt_int_op(1005L,OP_EQ, tv_mdiff(&end, &start));
476 :
477 : /* Negative tv_sec values, these will break on platforms where tv_sec is
478 : * unsigned */
479 :
480 1 : end.tv_sec = -10;
481 :
482 1 : tt_int_op(-15005000L,OP_EQ, tv_udiff(&start, &end));
483 1 : tt_int_op(-15005L,OP_EQ, tv_mdiff(&start, &end));
484 1 : tt_int_op(15005000L,OP_EQ, tv_udiff(&end, &start));
485 1 : tt_int_op(15005L,OP_EQ, tv_mdiff(&end, &start));
486 :
487 1 : start.tv_sec = -100;
488 :
489 1 : tt_int_op(89995000L,OP_EQ, tv_udiff(&start, &end));
490 1 : tt_int_op(89995L,OP_EQ, tv_mdiff(&start, &end));
491 1 : tt_int_op(-89995000L,OP_EQ, tv_udiff(&end, &start));
492 1 : tt_int_op(-89995L,OP_EQ, tv_mdiff(&end, &start));
493 :
494 : /* Test that tv_usec values round away from zero when converted to msec */
495 1 : start.tv_sec = 0;
496 1 : start.tv_usec = 0;
497 1 : end.tv_sec = 10;
498 1 : end.tv_usec = 499;
499 :
500 1 : tt_int_op(10000499L, OP_EQ, tv_udiff(&start, &end));
501 1 : tt_int_op(10000L, OP_EQ, tv_mdiff(&start, &end));
502 1 : tt_int_op(-10000499L, OP_EQ, tv_udiff(&end, &start));
503 1 : tt_int_op(-10000L, OP_EQ, tv_mdiff(&end, &start));
504 :
505 1 : start.tv_sec = 0;
506 1 : start.tv_usec = 0;
507 1 : end.tv_sec = 10;
508 1 : end.tv_usec = 500;
509 :
510 1 : tt_int_op(10000500L, OP_EQ, tv_udiff(&start, &end));
511 1 : tt_int_op(10001L, OP_EQ, tv_mdiff(&start, &end));
512 1 : tt_int_op(-10000500L, OP_EQ, tv_udiff(&end, &start));
513 1 : tt_int_op(-10000L, OP_EQ, tv_mdiff(&end, &start));
514 :
515 1 : start.tv_sec = 0;
516 1 : start.tv_usec = 0;
517 1 : end.tv_sec = 10;
518 1 : end.tv_usec = 501;
519 :
520 1 : tt_int_op(10000501L, OP_EQ, tv_udiff(&start, &end));
521 1 : tt_int_op(10001L, OP_EQ, tv_mdiff(&start, &end));
522 1 : tt_int_op(-10000501L, OP_EQ, tv_udiff(&end, &start));
523 1 : tt_int_op(-10001L, OP_EQ, tv_mdiff(&end, &start));
524 :
525 : /* Overflow conditions */
526 :
527 : #ifdef _WIN32
528 : /* Would you believe that tv_sec is a long on windows? Of course you would.*/
529 : #define TV_SEC_MAX LONG_MAX
530 : #define TV_SEC_MIN LONG_MIN
531 : #else
532 : /* Some BSDs have struct timeval.tv_sec 64-bit, but time_t (and long) 32-bit
533 : * Which means TIME_MAX is not actually the maximum value of tv_sec.
534 : * But that's ok for the moment, because the code correctly performs 64-bit
535 : * calculations internally, then catches the overflow. */
536 : #define TV_SEC_MAX TIME_MAX
537 : #define TV_SEC_MIN TIME_MIN
538 : #endif /* defined(_WIN32) */
539 :
540 : /* Assume tv_usec is an unsigned integer until proven otherwise */
541 : #define TV_USEC_MAX UINT_MAX
542 :
543 : /* Overflows in the result type */
544 :
545 : /* All comparisons work */
546 1 : start.tv_sec = 0;
547 1 : start.tv_usec = 0;
548 1 : end.tv_sec = LONG_MAX/1000 - 2;
549 1 : end.tv_usec = 0;
550 :
551 1 : tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&start, &end));
552 1 : tt_int_op(end.tv_sec*1000L, OP_EQ, tv_mdiff(&start, &end));
553 1 : tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&end, &start));
554 1 : tt_int_op(-end.tv_sec*1000L, OP_EQ, tv_mdiff(&end, &start));
555 :
556 1 : start.tv_sec = 0;
557 1 : start.tv_usec = 0;
558 1 : end.tv_sec = LONG_MAX/1000000 - 1;
559 1 : end.tv_usec = 0;
560 :
561 1 : tt_int_op(end.tv_sec*1000000L, OP_EQ, tv_udiff(&start, &end));
562 1 : tt_int_op(end.tv_sec*1000L, OP_EQ, tv_mdiff(&start, &end));
563 1 : tt_int_op(-end.tv_sec*1000000L, OP_EQ, tv_udiff(&end, &start));
564 1 : tt_int_op(-end.tv_sec*1000L, OP_EQ, tv_mdiff(&end, &start));
565 :
566 : /* No comparisons work */
567 1 : start.tv_sec = 0;
568 1 : start.tv_usec = 0;
569 1 : end.tv_sec = LONG_MAX/1000 + 1;
570 1 : end.tv_usec = 0;
571 :
572 1 : tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&start, &end));
573 1 : tt_int_op(LONG_MAX, OP_EQ, tv_mdiff(&start, &end));
574 1 : tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&end, &start));
575 1 : tt_int_op(LONG_MAX, OP_EQ, tv_mdiff(&end, &start));
576 :
577 1 : start.tv_sec = 0;
578 1 : start.tv_usec = 0;
579 1 : end.tv_sec = LONG_MAX/1000000 + 1;
580 1 : end.tv_usec = 0;
581 :
582 1 : tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&start, &end));
583 1 : tt_int_op(end.tv_sec*1000L, OP_EQ, tv_mdiff(&start, &end));
584 1 : tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&end, &start));
585 1 : tt_int_op(-end.tv_sec*1000L, OP_EQ, tv_mdiff(&end, &start));
586 :
587 1 : start.tv_sec = 0;
588 1 : start.tv_usec = 0;
589 1 : end.tv_sec = LONG_MAX/1000;
590 1 : end.tv_usec = TOR_USEC_PER_SEC;
591 :
592 1 : tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&start, &end));
593 1 : tt_int_op(LONG_MAX, OP_EQ, tv_mdiff(&start, &end));
594 1 : tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&end, &start));
595 1 : tt_int_op(LONG_MAX, OP_EQ, tv_mdiff(&end, &start));
596 :
597 1 : start.tv_sec = 0;
598 1 : start.tv_usec = 0;
599 1 : end.tv_sec = LONG_MAX/1000000;
600 1 : end.tv_usec = TOR_USEC_PER_SEC;
601 :
602 1 : tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&start, &end));
603 1 : tt_int_op((end.tv_sec + 1)*1000L, OP_EQ, tv_mdiff(&start, &end));
604 1 : tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&end, &start));
605 1 : tt_int_op(-(end.tv_sec + 1)*1000L, OP_EQ, tv_mdiff(&end, &start));
606 :
607 : /* Overflows on comparison to zero */
608 :
609 1 : start.tv_sec = 0;
610 1 : start.tv_usec = 0;
611 :
612 1 : end.tv_sec = TV_SEC_MAX;
613 1 : end.tv_usec = 0;
614 :
615 1 : tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&start, &end));
616 1 : tt_int_op(LONG_MAX, OP_EQ, tv_mdiff(&start, &end));
617 1 : tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&end, &start));
618 1 : tt_int_op(LONG_MAX, OP_EQ, tv_mdiff(&end, &start));
619 :
620 1 : end.tv_sec = TV_SEC_MAX;
621 1 : end.tv_usec = TOR_USEC_PER_SEC;
622 :
623 1 : tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&start, &end));
624 1 : tt_int_op(LONG_MAX, OP_EQ, tv_mdiff(&start, &end));
625 1 : tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&end, &start));
626 1 : tt_int_op(LONG_MAX, OP_EQ, tv_mdiff(&end, &start));
627 :
628 1 : end.tv_sec = 0;
629 1 : end.tv_usec = TV_USEC_MAX;
630 :
631 1 : tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&start, &end));
632 1 : tt_int_op(LONG_MAX, OP_EQ, tv_mdiff(&start, &end));
633 1 : tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&end, &start));
634 1 : tt_int_op(LONG_MAX, OP_EQ, tv_mdiff(&end, &start));
635 :
636 1 : end.tv_sec = TV_SEC_MAX;
637 1 : end.tv_usec = TV_USEC_MAX;
638 :
639 1 : tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&start, &end));
640 1 : tt_int_op(LONG_MAX, OP_EQ, tv_mdiff(&start, &end));
641 1 : tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&end, &start));
642 1 : tt_int_op(LONG_MAX, OP_EQ, tv_mdiff(&end, &start));
643 :
644 1 : end.tv_sec = 0;
645 1 : end.tv_usec = 0;
646 :
647 1 : start.tv_sec = TV_SEC_MIN;
648 1 : start.tv_usec = 0;
649 :
650 1 : tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&start, &end));
651 1 : tt_int_op(LONG_MAX, OP_EQ, tv_mdiff(&start, &end));
652 1 : tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&end, &start));
653 1 : tt_int_op(LONG_MAX, OP_EQ, tv_mdiff(&end, &start));
654 :
655 1 : start.tv_sec = TV_SEC_MIN;
656 1 : start.tv_usec = TOR_USEC_PER_SEC;
657 :
658 1 : tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&start, &end));
659 1 : tt_int_op(LONG_MAX, OP_EQ, tv_mdiff(&start, &end));
660 1 : tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&end, &start));
661 1 : tt_int_op(LONG_MAX, OP_EQ, tv_mdiff(&end, &start));
662 :
663 1 : start.tv_sec = TV_SEC_MIN;
664 1 : start.tv_usec = TV_USEC_MAX;
665 :
666 1 : tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&start, &end));
667 1 : tt_int_op(LONG_MAX, OP_EQ, tv_mdiff(&start, &end));
668 1 : tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&end, &start));
669 1 : tt_int_op(LONG_MAX, OP_EQ, tv_mdiff(&end, &start));
670 :
671 : /* overflows on comparison to maxima / minima */
672 :
673 1 : start.tv_sec = TV_SEC_MIN;
674 1 : start.tv_usec = 0;
675 :
676 1 : end.tv_sec = TV_SEC_MAX;
677 1 : end.tv_usec = 0;
678 :
679 1 : tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&start, &end));
680 1 : tt_int_op(LONG_MAX, OP_EQ, tv_mdiff(&start, &end));
681 1 : tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&end, &start));
682 1 : tt_int_op(LONG_MAX, OP_EQ, tv_mdiff(&end, &start));
683 :
684 1 : end.tv_sec = TV_SEC_MAX;
685 1 : end.tv_usec = TOR_USEC_PER_SEC;
686 :
687 1 : tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&start, &end));
688 1 : tt_int_op(LONG_MAX, OP_EQ, tv_mdiff(&start, &end));
689 1 : tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&end, &start));
690 1 : tt_int_op(LONG_MAX, OP_EQ, tv_mdiff(&end, &start));
691 :
692 1 : end.tv_sec = TV_SEC_MAX;
693 1 : end.tv_usec = 0;
694 :
695 1 : start.tv_sec = TV_SEC_MIN;
696 1 : start.tv_usec = 0;
697 :
698 1 : tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&start, &end));
699 1 : tt_int_op(LONG_MAX, OP_EQ, tv_mdiff(&start, &end));
700 1 : tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&end, &start));
701 1 : tt_int_op(LONG_MAX, OP_EQ, tv_mdiff(&end, &start));
702 :
703 1 : start.tv_sec = TV_SEC_MIN;
704 1 : start.tv_usec = TOR_USEC_PER_SEC;
705 :
706 1 : tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&start, &end));
707 1 : tt_int_op(LONG_MAX, OP_EQ, tv_mdiff(&start, &end));
708 1 : tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&end, &start));
709 1 : tt_int_op(LONG_MAX, OP_EQ, tv_mdiff(&end, &start));
710 :
711 : /* overflows on comparison to maxima / minima with extra usec */
712 :
713 1 : start.tv_sec = TV_SEC_MIN;
714 1 : start.tv_usec = TOR_USEC_PER_SEC;
715 :
716 1 : end.tv_sec = TV_SEC_MAX;
717 1 : end.tv_usec = 0;
718 :
719 1 : tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&start, &end));
720 1 : tt_int_op(LONG_MAX, OP_EQ, tv_mdiff(&start, &end));
721 1 : tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&end, &start));
722 1 : tt_int_op(LONG_MAX, OP_EQ, tv_mdiff(&end, &start));
723 :
724 1 : end.tv_sec = TV_SEC_MAX;
725 1 : end.tv_usec = TOR_USEC_PER_SEC;
726 :
727 1 : tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&start, &end));
728 1 : tt_int_op(LONG_MAX, OP_EQ, tv_mdiff(&start, &end));
729 1 : tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&end, &start));
730 1 : tt_int_op(LONG_MAX, OP_EQ, tv_mdiff(&end, &start));
731 :
732 1 : end.tv_sec = TV_SEC_MAX;
733 1 : end.tv_usec = TOR_USEC_PER_SEC;
734 :
735 1 : start.tv_sec = TV_SEC_MIN;
736 1 : start.tv_usec = 0;
737 :
738 1 : tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&start, &end));
739 1 : tt_int_op(LONG_MAX, OP_EQ, tv_mdiff(&start, &end));
740 1 : tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&end, &start));
741 1 : tt_int_op(LONG_MAX, OP_EQ, tv_mdiff(&end, &start));
742 :
743 1 : start.tv_sec = TV_SEC_MIN;
744 1 : start.tv_usec = TOR_USEC_PER_SEC;
745 :
746 1 : tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&start, &end));
747 1 : tt_int_op(LONG_MAX, OP_EQ, tv_mdiff(&start, &end));
748 1 : tt_int_op(LONG_MAX, OP_EQ, tv_udiff(&end, &start));
749 1 : tt_int_op(LONG_MAX, OP_EQ, tv_mdiff(&end, &start));
750 :
751 : /* Test tor_timegm & tor_gmtime_r */
752 :
753 : /* The test values here are confirmed to be correct on a platform
754 : * with a working timegm & gmtime_r. */
755 :
756 : /* Start with known-zero a_time and b_time.
757 : * This avoids passing uninitialised values to TM_EQUAL in a_time.
758 : * Zeroing may not be needed for b_time, as long as tor_gmtime_r
759 : * never reads the existing values in the structure.
760 : * But we really don't want intermittently failing tests. */
761 1 : memset(&a_time, 0, sizeof(struct tm));
762 1 : memset(&b_time, 0, sizeof(struct tm));
763 :
764 1 : a_time.tm_year = 2003-1900;
765 1 : a_time.tm_mon = 7;
766 1 : a_time.tm_mday = 30;
767 1 : a_time.tm_hour = 6;
768 1 : a_time.tm_min = 14;
769 1 : a_time.tm_sec = 55;
770 1 : t_res = 1062224095UL;
771 1 : tt_int_op(t_res, OP_EQ, tor_timegm(&a_time));
772 1 : tor_gmtime_r(&t_res, &b_time);
773 1 : TM_EQUAL(a_time, b_time);
774 :
775 1 : a_time.tm_year = 2004-1900; /* Try a leap year, after feb. */
776 1 : t_res = 1093846495UL;
777 1 : tt_int_op(t_res, OP_EQ, tor_timegm(&a_time));
778 1 : tor_gmtime_r(&t_res, &b_time);
779 1 : TM_EQUAL(a_time, b_time);
780 :
781 1 : a_time.tm_mon = 1; /* Try a leap year, in feb. */
782 1 : a_time.tm_mday = 10;
783 1 : t_res = 1076393695UL;
784 1 : tt_int_op(t_res, OP_EQ, tor_timegm(&a_time));
785 1 : tor_gmtime_r(&t_res, &b_time);
786 1 : TM_EQUAL(a_time, b_time);
787 :
788 1 : a_time.tm_mon = 0;
789 1 : t_res = 1073715295UL;
790 1 : tt_int_op(t_res, OP_EQ, tor_timegm(&a_time));
791 1 : tor_gmtime_r(&t_res, &b_time);
792 1 : TM_EQUAL(a_time, b_time);
793 :
794 : /* This value is in range with 32 bit and 64 bit time_t */
795 1 : a_time.tm_year = 2037-1900;
796 1 : t_res = 2115180895UL;
797 1 : tt_int_op(t_res, OP_EQ, tor_timegm(&a_time));
798 1 : tor_gmtime_r(&t_res, &b_time);
799 1 : TM_EQUAL(a_time, b_time);
800 :
801 : /* This value is out of range with 32 bit time_t, but in range for 64 bit
802 : * time_t */
803 1 : a_time.tm_year = 2039-1900;
804 : #if SIZEOF_TIME_T == 4
805 : setup_full_capture_of_logs(LOG_WARN);
806 : tt_int_op((time_t) -1,OP_EQ, tor_timegm(&a_time));
807 : expect_single_log_msg_containing("Result does not fit in tor_timegm");
808 : teardown_capture_of_logs();
809 : #elif SIZEOF_TIME_T == 8
810 1 : t_res = 2178252895UL;
811 1 : tt_int_op(t_res, OP_EQ, tor_timegm(&a_time));
812 1 : tor_gmtime_r(&t_res, &b_time);
813 1 : TM_EQUAL(a_time, b_time);
814 : #endif /* SIZEOF_TIME_T == 4 || ... */
815 :
816 : /* Test tor_timegm out of range */
817 :
818 : /* The below tests will all cause a BUG message, so we capture, suppress,
819 : * and detect. */
820 : #define CAPTURE() do { \
821 : setup_full_capture_of_logs(LOG_WARN); \
822 : } while (0)
823 : #define CHECK_TIMEGM_WARNING(msg) do { \
824 : expect_single_log_msg_containing(msg); \
825 : teardown_capture_of_logs(); \
826 : } while (0)
827 : #define CHECK_POSSIBLE_EINVAL() do { \
828 : if (mock_saved_log_n_entries()) { \
829 : expect_single_log_msg_containing("Invalid argument"); \
830 : } \
831 : teardown_capture_of_logs(); \
832 : } while (0)
833 :
834 : #define CHECK_TIMEGM_ARG_OUT_OF_RANGE(msg) \
835 : CHECK_TIMEGM_WARNING("Out-of-range argument to tor_timegm")
836 :
837 : /* year */
838 :
839 : /* Wrong year < 1970 */
840 1 : a_time.tm_year = 1969-1900;
841 1 : CAPTURE();
842 1 : tt_int_op((time_t) -1,OP_EQ, tor_timegm(&a_time));
843 1 : CHECK_TIMEGM_ARG_OUT_OF_RANGE();
844 :
845 1 : a_time.tm_year = -1-1900;
846 1 : CAPTURE();
847 1 : tt_int_op((time_t) -1,OP_EQ, tor_timegm(&a_time));
848 1 : CHECK_TIMEGM_ARG_OUT_OF_RANGE();
849 :
850 : #if SIZEOF_INT == 4 || SIZEOF_INT == 8
851 1 : a_time.tm_year = -1*(1 << 16);
852 1 : CAPTURE();
853 1 : tt_int_op((time_t) -1,OP_EQ, tor_timegm(&a_time));
854 1 : CHECK_TIMEGM_ARG_OUT_OF_RANGE();
855 :
856 : /* one of the smallest tm_year values my 64 bit system supports:
857 : * t_res = -9223372036854775LL without clamping */
858 1 : a_time.tm_year = -292275055-1900;
859 1 : CAPTURE();
860 1 : tt_int_op((time_t) -1,OP_EQ, tor_timegm(&a_time));
861 1 : CHECK_TIMEGM_ARG_OUT_OF_RANGE();
862 :
863 1 : a_time.tm_year = INT32_MIN;
864 1 : CAPTURE();
865 1 : tt_int_op((time_t) -1,OP_EQ, tor_timegm(&a_time));
866 1 : CHECK_TIMEGM_ARG_OUT_OF_RANGE();
867 : #endif /* SIZEOF_INT == 4 || SIZEOF_INT == 8 */
868 :
869 : #if SIZEOF_INT == 8
870 : a_time.tm_year = -1*(1 << 48);
871 : CAPTURE();
872 : tt_int_op((time_t) -1,OP_EQ, tor_timegm(&a_time));
873 : CHECK_TIMEGM_ARG_OUT_OF_RANGE();
874 :
875 : /* while unlikely, the system's gmtime(_r) could return
876 : * a "correct" retrospective gregorian negative year value,
877 : * which I'm pretty sure is:
878 : * -1*(2^63)/60/60/24*2000/730485 + 1970 = -292277022657
879 : * 730485 is the number of days in two millennia, including leap days */
880 : a_time.tm_year = -292277022657-1900;
881 : CAPTURE();
882 : tt_int_op((time_t) -1,OP_EQ, tor_timegm(&a_time));
883 : CHECK_TIMEGM_ARG_OUT_OF_RANGE();
884 :
885 : a_time.tm_year = INT64_MIN;
886 : CAPTURE();
887 : tt_int_op((time_t) -1,OP_EQ, tor_timegm(&a_time));
888 : CHECK_TIMEGM_ARG_OUT_OF_RANGE();
889 : #endif /* SIZEOF_INT == 8 */
890 :
891 : /* Wrong year >= INT32_MAX - 1900 */
892 : #if SIZEOF_INT == 4 || SIZEOF_INT == 8
893 1 : a_time.tm_year = INT32_MAX-1900;
894 1 : CAPTURE();
895 1 : tt_int_op((time_t) -1,OP_EQ, tor_timegm(&a_time));
896 1 : CHECK_TIMEGM_ARG_OUT_OF_RANGE();
897 :
898 1 : a_time.tm_year = INT32_MAX;
899 1 : CAPTURE();
900 1 : tt_int_op((time_t) -1,OP_EQ, tor_timegm(&a_time));
901 1 : CHECK_TIMEGM_ARG_OUT_OF_RANGE();
902 : #endif /* SIZEOF_INT == 4 || SIZEOF_INT == 8 */
903 :
904 : #if SIZEOF_INT == 8
905 : /* one of the largest tm_year values my 64 bit system supports */
906 : a_time.tm_year = 292278994-1900;
907 : CAPTURE();
908 : tt_int_op((time_t) -1,OP_EQ, tor_timegm(&a_time));
909 : CHECK_TIMEGM_ARG_OUT_OF_RANGE();
910 :
911 : /* while unlikely, the system's gmtime(_r) could return
912 : * a "correct" proleptic gregorian year value,
913 : * which I'm pretty sure is:
914 : * (2^63-1)/60/60/24*2000/730485 + 1970 = 292277026596
915 : * 730485 is the number of days in two millennia, including leap days */
916 : a_time.tm_year = 292277026596-1900;
917 : CAPTURE();
918 : tt_int_op((time_t) -1,OP_EQ, tor_timegm(&a_time));
919 : CHECK_TIMEGM_ARG_OUT_OF_RANGE();
920 :
921 : a_time.tm_year = INT64_MAX-1900;
922 : CAPTURE();
923 : tt_int_op((time_t) -1,OP_EQ, tor_timegm(&a_time));
924 : CHECK_TIMEGM_ARG_OUT_OF_RANGE();
925 :
926 : a_time.tm_year = INT64_MAX;
927 : CAPTURE();
928 : tt_int_op((time_t) -1,OP_EQ, tor_timegm(&a_time));
929 : CHECK_TIMEGM_ARG_OUT_OF_RANGE();
930 : #endif /* SIZEOF_INT == 8 */
931 :
932 : /* month */
933 1 : a_time.tm_year = 2007-1900; /* restore valid year */
934 :
935 1 : a_time.tm_mon = 12; /* Wrong month, it's 0-based */
936 1 : CAPTURE();
937 1 : tt_int_op((time_t) -1,OP_EQ, tor_timegm(&a_time));
938 1 : CHECK_TIMEGM_ARG_OUT_OF_RANGE();
939 :
940 1 : a_time.tm_mon = -1; /* Wrong month */
941 1 : CAPTURE();
942 1 : tt_int_op((time_t) -1,OP_EQ, tor_timegm(&a_time));
943 1 : CHECK_TIMEGM_ARG_OUT_OF_RANGE();
944 :
945 : /* day */
946 1 : a_time.tm_mon = 6; /* Try July */
947 1 : a_time.tm_mday = 32; /* Wrong day */
948 1 : CAPTURE();
949 1 : tt_int_op((time_t) -1,OP_EQ, tor_timegm(&a_time));
950 1 : CHECK_TIMEGM_ARG_OUT_OF_RANGE();
951 :
952 1 : a_time.tm_mon = 5; /* Try June */
953 1 : a_time.tm_mday = 31; /* Wrong day */
954 1 : CAPTURE();
955 1 : tt_int_op((time_t) -1,OP_EQ, tor_timegm(&a_time));
956 1 : CHECK_TIMEGM_ARG_OUT_OF_RANGE();
957 :
958 1 : a_time.tm_year = 2008-1900; /* Try a leap year */
959 1 : a_time.tm_mon = 1; /* in feb. */
960 1 : a_time.tm_mday = 30; /* Wrong day */
961 1 : CAPTURE();
962 1 : tt_int_op((time_t) -1,OP_EQ, tor_timegm(&a_time));
963 1 : CHECK_TIMEGM_ARG_OUT_OF_RANGE();
964 :
965 1 : a_time.tm_year = 2011-1900; /* Try a non-leap year */
966 1 : a_time.tm_mon = 1; /* in feb. */
967 1 : a_time.tm_mday = 29; /* Wrong day */
968 1 : CAPTURE();
969 1 : tt_int_op((time_t) -1,OP_EQ, tor_timegm(&a_time));
970 1 : CHECK_TIMEGM_ARG_OUT_OF_RANGE();
971 :
972 1 : a_time.tm_mday = 0; /* Wrong day, it's 1-based (to be different) */
973 1 : CAPTURE();
974 1 : tt_int_op((time_t) -1,OP_EQ, tor_timegm(&a_time));
975 1 : CHECK_TIMEGM_ARG_OUT_OF_RANGE();
976 :
977 : /* hour */
978 1 : a_time.tm_mday = 3; /* restore valid month day */
979 :
980 1 : a_time.tm_hour = 24; /* Wrong hour, it's 0-based */
981 1 : CAPTURE();
982 1 : tt_int_op((time_t) -1,OP_EQ, tor_timegm(&a_time));
983 1 : CHECK_TIMEGM_ARG_OUT_OF_RANGE();
984 :
985 1 : a_time.tm_hour = -1; /* Wrong hour */
986 1 : CAPTURE();
987 1 : tt_int_op((time_t) -1,OP_EQ, tor_timegm(&a_time));
988 1 : CHECK_TIMEGM_ARG_OUT_OF_RANGE();
989 :
990 : /* minute */
991 1 : a_time.tm_hour = 22; /* restore valid hour */
992 :
993 1 : a_time.tm_min = 60; /* Wrong minute, it's 0-based */
994 1 : CAPTURE();
995 1 : tt_int_op((time_t) -1,OP_EQ, tor_timegm(&a_time));
996 1 : CHECK_TIMEGM_ARG_OUT_OF_RANGE();
997 :
998 1 : a_time.tm_min = -1; /* Wrong minute */
999 1 : CAPTURE();
1000 1 : tt_int_op((time_t) -1,OP_EQ, tor_timegm(&a_time));
1001 1 : CHECK_TIMEGM_ARG_OUT_OF_RANGE();
1002 :
1003 : /* second */
1004 1 : a_time.tm_min = 37; /* restore valid minute */
1005 :
1006 1 : a_time.tm_sec = 61; /* Wrong second: 0-based with leap seconds */
1007 1 : CAPTURE();
1008 1 : tt_int_op((time_t) -1,OP_EQ, tor_timegm(&a_time));
1009 1 : CHECK_TIMEGM_ARG_OUT_OF_RANGE();
1010 :
1011 1 : a_time.tm_sec = -1; /* Wrong second */
1012 1 : CAPTURE();
1013 1 : tt_int_op((time_t) -1,OP_EQ, tor_timegm(&a_time));
1014 1 : CHECK_TIMEGM_ARG_OUT_OF_RANGE();
1015 :
1016 : /* Test tor_gmtime_r out of range */
1017 :
1018 : /* time_t < 0 yields a year clamped to 1 or 1970,
1019 : * depending on whether the implementation of the system gmtime(_r)
1020 : * sets struct tm (1) or not (1970) */
1021 1 : t_res = -1;
1022 1 : CAPTURE();
1023 1 : tor_gmtime_r(&t_res, &b_time);
1024 1 : CHECK_POSSIBLE_EINVAL();
1025 1 : tt_assert(b_time.tm_year == (1970-1900) ||
1026 : b_time.tm_year == (1969-1900));
1027 :
1028 1 : if (sizeof(time_t) == 4 || sizeof(time_t) == 8) {
1029 1 : t_res = -1*(1 << 30);
1030 1 : CAPTURE();
1031 1 : tor_gmtime_r(&t_res, &b_time);
1032 1 : CHECK_POSSIBLE_EINVAL();
1033 1 : tt_assert(b_time.tm_year == (1970-1900) ||
1034 : b_time.tm_year == (1935-1900));
1035 :
1036 1 : t_res = INT32_MIN;
1037 1 : CAPTURE();
1038 1 : tor_gmtime_r(&t_res, &b_time);
1039 1 : CHECK_POSSIBLE_EINVAL();
1040 1 : tt_assert(b_time.tm_year == (1970-1900) ||
1041 : b_time.tm_year == (1901-1900));
1042 : }
1043 :
1044 : #if SIZEOF_TIME_T == 8
1045 : {
1046 : /* one of the smallest tm_year values my 64 bit system supports:
1047 : * b_time.tm_year == (-292275055LL-1900LL) without clamping */
1048 1 : t_res = -9223372036854775LL;
1049 1 : CAPTURE();
1050 1 : tor_gmtime_r(&t_res, &b_time);
1051 1 : CHECK_POSSIBLE_EINVAL();
1052 1 : tt_assert(b_time.tm_year == (1970-1900) ||
1053 : b_time.tm_year == (1-1900));
1054 :
1055 : /* while unlikely, the system's gmtime(_r) could return
1056 : * a "correct" retrospective gregorian negative year value,
1057 : * which I'm pretty sure is:
1058 : * -1*(2^63)/60/60/24*2000/730485 + 1970 = -292277022657
1059 : * 730485 is the number of days in two millennia, including leap days
1060 : * (int64_t)b_time.tm_year == (-292277022657LL-1900LL) without clamping */
1061 1 : t_res = INT64_MIN;
1062 1 : CAPTURE();
1063 1 : tor_gmtime_r(&t_res, &b_time);
1064 1 : if (! (b_time.tm_year == (1970-1900) ||
1065 : b_time.tm_year == (1-1900))) {
1066 0 : tt_int_op(b_time.tm_year, OP_EQ, 1970-1900);
1067 : }
1068 1 : if (b_time.tm_year != 1970-1900) {
1069 0 : CHECK_TIMEGM_WARNING("Rounding up to ");
1070 : } else {
1071 1 : teardown_capture_of_logs();
1072 : }
1073 : }
1074 : {
1075 : /* As above, but with localtime. */
1076 1 : t_res = -9223372036854775LL;
1077 1 : CAPTURE();
1078 1 : tor_localtime_r(&t_res, &b_time);
1079 1 : CHECK_POSSIBLE_EINVAL();
1080 1 : tt_assert(b_time.tm_year == (1970-1900) ||
1081 : b_time.tm_year == (1-1900));
1082 :
1083 : /* while unlikely, the system's gmtime(_r) could return
1084 : * a "correct" retrospective gregorian negative year value,
1085 : * which I'm pretty sure is:
1086 : * -1*(2^63)/60/60/24*2000/730485 + 1970 = -292277022657
1087 : * 730485 is the number of days in two millennia, including leap days
1088 : * (int64_t)b_time.tm_year == (-292277022657LL-1900LL) without clamping */
1089 1 : t_res = INT64_MIN;
1090 1 : CAPTURE();
1091 1 : tor_localtime_r(&t_res, &b_time);
1092 1 : if (! (b_time.tm_year == (1970-1900) ||
1093 : b_time.tm_year == (1-1900))) {
1094 0 : tt_int_op(b_time.tm_year, OP_EQ, 1970-1900);
1095 : }
1096 1 : if (b_time.tm_year != 1970-1900) {
1097 0 : CHECK_TIMEGM_WARNING("Rounding up to ");
1098 : } else {
1099 1 : teardown_capture_of_logs();
1100 : }
1101 : }
1102 : #endif /* SIZEOF_TIME_T == 8 */
1103 :
1104 : /* time_t >= INT_MAX yields a year clamped to 2037 or 9999,
1105 : * depending on whether the implementation of the system gmtime(_r)
1106 : * sets struct tm (9999) or not (2037) */
1107 : #if SIZEOF_TIME_T == 4 || SIZEOF_TIME_T == 8
1108 : {
1109 1 : t_res = 3*(1 << 29);
1110 1 : tor_gmtime_r(&t_res, &b_time);
1111 1 : tt_assert(b_time.tm_year == (2021-1900));
1112 :
1113 1 : t_res = INT32_MAX;
1114 1 : tor_gmtime_r(&t_res, &b_time);
1115 1 : tt_assert(b_time.tm_year == (2037-1900) ||
1116 : b_time.tm_year == (2038-1900));
1117 : }
1118 : {
1119 : /* as above but with localtime. */
1120 1 : t_res = 3*(1 << 29);
1121 1 : tor_localtime_r(&t_res, &b_time);
1122 1 : tt_assert(b_time.tm_year == (2021-1900));
1123 :
1124 1 : t_res = INT32_MAX;
1125 1 : tor_localtime_r(&t_res, &b_time);
1126 1 : tt_assert(b_time.tm_year == (2037-1900) ||
1127 : b_time.tm_year == (2038-1900));
1128 : }
1129 : #endif /* SIZEOF_TIME_T == 4 || SIZEOF_TIME_T == 8 */
1130 :
1131 : #if SIZEOF_TIME_T == 8
1132 : {
1133 : /* one of the largest tm_year values my 64 bit system supports:
1134 : * b_time.tm_year == (292278994L-1900L) without clamping */
1135 1 : t_res = 9223372036854775LL;
1136 1 : CAPTURE();
1137 1 : tor_gmtime_r(&t_res, &b_time);
1138 1 : CHECK_POSSIBLE_EINVAL();
1139 1 : tt_assert(b_time.tm_year == (2037-1900) ||
1140 : b_time.tm_year == (9999-1900));
1141 :
1142 : /* while unlikely, the system's gmtime(_r) could return
1143 : * a "correct" proleptic gregorian year value,
1144 : * which I'm pretty sure is:
1145 : * (2^63-1)/60/60/24*2000/730485 + 1970 = 292277026596
1146 : * 730485 is the number of days in two millennia, including leap days
1147 : * (int64_t)b_time.tm_year == (292277026596L-1900L) without clamping */
1148 1 : t_res = INT64_MAX;
1149 1 : CAPTURE();
1150 1 : tor_gmtime_r(&t_res, &b_time);
1151 1 : CHECK_TIMEGM_WARNING("Rounding down to ");
1152 :
1153 1 : tt_assert(b_time.tm_year == (2037-1900) ||
1154 : b_time.tm_year == (9999-1900));
1155 : }
1156 : {
1157 : /* As above but with localtime. */
1158 1 : t_res = 9223372036854775LL;
1159 1 : CAPTURE();
1160 1 : tor_localtime_r(&t_res, &b_time);
1161 1 : CHECK_POSSIBLE_EINVAL();
1162 1 : tt_assert(b_time.tm_year == (2037-1900) ||
1163 : b_time.tm_year == (9999-1900));
1164 :
1165 : /* while unlikely, the system's gmtime(_r) could return
1166 : * a "correct" proleptic gregorian year value,
1167 : * which I'm pretty sure is:
1168 : * (2^63-1)/60/60/24*2000/730485 + 1970 = 292277026596
1169 : * 730485 is the number of days in two millennia, including leap days
1170 : * (int64_t)b_time.tm_year == (292277026596L-1900L) without clamping */
1171 1 : t_res = INT64_MAX;
1172 1 : CAPTURE();
1173 1 : tor_localtime_r(&t_res, &b_time);
1174 1 : CHECK_TIMEGM_WARNING("Rounding down to ");
1175 :
1176 1 : tt_assert(b_time.tm_year == (2037-1900) ||
1177 : b_time.tm_year == (9999-1900));
1178 : }
1179 : #endif /* SIZEOF_TIME_T == 8 */
1180 :
1181 : /* Test {format,parse}_rfc1123_time */
1182 :
1183 1 : format_rfc1123_time(timestr, 0);
1184 1 : tt_str_op("Thu, 01 Jan 1970 00:00:00 GMT",OP_EQ, timestr);
1185 1 : format_rfc1123_time(timestr, (time_t)1091580502UL);
1186 1 : tt_str_op("Wed, 04 Aug 2004 00:48:22 GMT",OP_EQ, timestr);
1187 :
1188 1 : t_res = 0;
1189 1 : i = parse_rfc1123_time(timestr, &t_res);
1190 1 : tt_int_op(0,OP_EQ, i);
1191 1 : tt_int_op(t_res,OP_EQ, (time_t)1091580502UL);
1192 :
1193 : /* This value is in range with 32 bit and 64 bit time_t */
1194 1 : format_rfc1123_time(timestr, (time_t)2080000000UL);
1195 1 : tt_str_op("Fri, 30 Nov 2035 01:46:40 GMT",OP_EQ, timestr);
1196 :
1197 1 : t_res = 0;
1198 1 : i = parse_rfc1123_time(timestr, &t_res);
1199 1 : tt_int_op(0,OP_EQ, i);
1200 1 : tt_int_op(t_res,OP_EQ, (time_t)2080000000UL);
1201 :
1202 : /* This value is out of range with 32 bit time_t, but in range for 64 bit
1203 : * time_t */
1204 1 : CAPTURE();
1205 1 : format_rfc1123_time(timestr, (time_t)2150000000UL);
1206 1 : CHECK_POSSIBLE_EINVAL();
1207 :
1208 : #if SIZEOF_TIME_T == 4
1209 : #if 0
1210 : /* Wrapping around will have made it this. */
1211 : /* On windows, at least, this is clipped to 1 Jan 1970. ??? */
1212 : tt_str_op("Sat, 11 Jan 1902 23:45:04 GMT",OP_EQ, timestr);
1213 : #endif
1214 : /* Make sure that the right date doesn't parse. */
1215 : strlcpy(timestr, "Wed, 17 Feb 2038 06:13:20 GMT", sizeof(timestr));
1216 :
1217 : t_res = 0;
1218 : CAPTURE();
1219 : i = parse_rfc1123_time(timestr, &t_res);
1220 : CHECK_TIMEGM_WARNING("does not fit in tor_timegm");
1221 : tt_int_op(-1,OP_EQ, i);
1222 : #elif SIZEOF_TIME_T == 8
1223 1 : tt_str_op("Wed, 17 Feb 2038 06:13:20 GMT",OP_EQ, timestr);
1224 :
1225 1 : t_res = 0;
1226 1 : i = parse_rfc1123_time(timestr, &t_res);
1227 1 : tt_int_op(0,OP_EQ, i);
1228 1 : tt_int_op(t_res,OP_EQ, (time_t)2150000000UL);
1229 : #endif /* SIZEOF_TIME_T == 4 || ... */
1230 :
1231 : /* The timezone doesn't matter */
1232 1 : t_res = 0;
1233 1 : tt_int_op(0,OP_EQ,
1234 : parse_rfc1123_time("Wed, 04 Aug 2004 00:48:22 ZUL", &t_res));
1235 1 : tt_int_op(t_res,OP_EQ, (time_t)1091580502UL);
1236 1 : tt_int_op(-1,OP_EQ,
1237 : parse_rfc1123_time("Wed, zz Aug 2004 99-99x99 GMT", &t_res));
1238 1 : tt_int_op(-1,OP_EQ,
1239 : parse_rfc1123_time("Wed, 32 Mar 2011 00:00:00 GMT", &t_res));
1240 1 : tt_int_op(-1,OP_EQ,
1241 : parse_rfc1123_time("Wed, 30 Mar 2011 24:00:00 GMT", &t_res));
1242 1 : tt_int_op(-1,OP_EQ,
1243 : parse_rfc1123_time("Wed, 30 Mar 2011 23:60:00 GMT", &t_res));
1244 1 : tt_int_op(-1,OP_EQ,
1245 : parse_rfc1123_time("Wed, 30 Mar 2011 23:59:62 GMT", &t_res));
1246 1 : tt_int_op(-1,OP_EQ,
1247 : parse_rfc1123_time("Wed, 30 Mar 1969 23:59:59 GMT", &t_res));
1248 1 : tt_int_op(-1,OP_EQ,
1249 : parse_rfc1123_time("Wed, 30 Ene 2011 23:59:59 GMT", &t_res));
1250 1 : tt_int_op(-1,OP_EQ,
1251 : parse_rfc1123_time("Wed, 30 Mar 2011 23:59:59 GM", &t_res));
1252 1 : tt_int_op(-1,OP_EQ,
1253 : parse_rfc1123_time("Wed, 30 Mar 1900 23:59:59 GMT", &t_res));
1254 :
1255 : /* Leap year. */
1256 1 : tt_int_op(-1,OP_EQ,
1257 : parse_rfc1123_time("Wed, 29 Feb 2011 16:00:00 GMT", &t_res));
1258 1 : tt_int_op(0,OP_EQ,
1259 : parse_rfc1123_time("Wed, 29 Feb 2012 16:00:00 GMT", &t_res));
1260 :
1261 : /* Leap second plus one */
1262 1 : tt_int_op(-1,OP_EQ,
1263 : parse_rfc1123_time("Wed, 30 Mar 2011 23:59:61 GMT", &t_res));
1264 :
1265 : /* Test parse_iso_time */
1266 :
1267 1 : t_res = 0;
1268 1 : i = parse_iso_time("", &t_res);
1269 1 : tt_int_op(-1,OP_EQ, i);
1270 1 : t_res = 0;
1271 1 : i = parse_iso_time("2004-08-32 00:48:22", &t_res);
1272 1 : tt_int_op(-1,OP_EQ, i);
1273 1 : t_res = 0;
1274 1 : i = parse_iso_time("1969-08-03 00:48:22", &t_res);
1275 1 : tt_int_op(-1,OP_EQ, i);
1276 :
1277 1 : t_res = 0;
1278 1 : i = parse_iso_time("2004-08-04 00:48:22", &t_res);
1279 1 : tt_int_op(0,OP_EQ, i);
1280 1 : tt_int_op(t_res,OP_EQ, (time_t)1091580502UL);
1281 1 : t_res = 0;
1282 1 : i = parse_iso_time("2004-8-4 0:48:22", &t_res);
1283 1 : tt_int_op(0,OP_EQ, i);
1284 1 : tt_int_op(t_res,OP_EQ, (time_t)1091580502UL);
1285 :
1286 : /* This value is in range with 32 bit and 64 bit time_t */
1287 1 : t_res = 0;
1288 1 : i = parse_iso_time("2035-11-30 01:46:40", &t_res);
1289 1 : tt_int_op(0,OP_EQ, i);
1290 1 : tt_int_op(t_res,OP_EQ, (time_t)2080000000UL);
1291 :
1292 : /* This value is out of range with 32 bit time_t, but in range for 64 bit
1293 : * time_t */
1294 1 : t_res = 0;
1295 : #if SIZEOF_TIME_T == 4
1296 : CAPTURE();
1297 : i = parse_iso_time("2038-02-17 06:13:20", &t_res);
1298 : tt_int_op(-1,OP_EQ, i);
1299 : CHECK_TIMEGM_WARNING("does not fit in tor_timegm");
1300 : #elif SIZEOF_TIME_T == 8
1301 1 : i = parse_iso_time("2038-02-17 06:13:20", &t_res);
1302 1 : tt_int_op(0,OP_EQ, i);
1303 1 : tt_int_op(t_res,OP_EQ, (time_t)2150000000UL);
1304 : #endif /* SIZEOF_TIME_T == 4 || ... */
1305 :
1306 1 : tt_int_op(-1,OP_EQ, parse_iso_time("2004-08-zz 99-99x99", &t_res));
1307 1 : tt_int_op(-1,OP_EQ, parse_iso_time("2011-03-32 00:00:00", &t_res));
1308 1 : tt_int_op(-1,OP_EQ, parse_iso_time("2011-03-30 24:00:00", &t_res));
1309 1 : tt_int_op(-1,OP_EQ, parse_iso_time("2011-03-30 23:60:00", &t_res));
1310 1 : tt_int_op(-1,OP_EQ, parse_iso_time("2011-03-30 23:59:62", &t_res));
1311 1 : tt_int_op(-1,OP_EQ, parse_iso_time("1969-03-30 23:59:59", &t_res));
1312 1 : tt_int_op(-1,OP_EQ, parse_iso_time("2011-00-30 23:59:59", &t_res));
1313 1 : tt_int_op(-1,OP_EQ, parse_iso_time("2147483647-08-29 14:00:00", &t_res));
1314 1 : tt_int_op(-1,OP_EQ, parse_iso_time("2011-03-30 23:59", &t_res));
1315 1 : tt_int_op(-1,OP_EQ, parse_iso_time("2004-08-04 00:48:22.100", &t_res));
1316 1 : tt_int_op(-1,OP_EQ, parse_iso_time("2004-08-04 00:48:22XYZ", &t_res));
1317 :
1318 : /* but... that _is_ acceptable if we aren't being strict. */
1319 1 : t_res = 0;
1320 1 : i = parse_iso_time_("2004-08-04 00:48:22XYZ", &t_res, 0, 0);
1321 1 : tt_int_op(0,OP_EQ, i);
1322 1 : tt_int_op(t_res,OP_EQ, (time_t)1091580502UL);
1323 :
1324 : /* try nospace variant. */
1325 1 : t_res = 0;
1326 1 : i = parse_iso_time_nospace("2004-08-04T00:48:22", &t_res);
1327 1 : tt_int_op(0,OP_EQ, i);
1328 1 : tt_int_op(t_res,OP_EQ, (time_t)1091580502UL);
1329 :
1330 1 : tt_int_op(-1,OP_EQ, parse_iso_time("2004-08-04T00:48:22", &t_res));
1331 1 : tt_int_op(-1,OP_EQ, parse_iso_time_nospace("2004-08-04 00:48:22", &t_res));
1332 1 : tt_int_op(-1,OP_EQ, parse_iso_time("2004-08-04x00:48:22", &t_res));
1333 1 : tt_int_op(-1,OP_EQ, parse_iso_time_nospace("2004-08-04x00:48:22", &t_res));
1334 :
1335 : /* Test tor_gettimeofday */
1336 :
1337 1 : end.tv_sec = 4;
1338 1 : end.tv_usec = 999990;
1339 1 : start.tv_sec = 1;
1340 1 : start.tv_usec = 500;
1341 :
1342 1 : tor_gettimeofday(&start);
1343 : /* now make sure time works. */
1344 1 : tor_gettimeofday(&end);
1345 : /* We might've timewarped a little. */
1346 1 : tt_int_op(tv_udiff(&start, &end), OP_GE, -5000);
1347 :
1348 : /* Test format_iso_time */
1349 :
1350 1 : tv.tv_sec = (time_t)1326296338UL;
1351 1 : tv.tv_usec = 3060;
1352 1 : format_iso_time(timestr, (time_t)tv.tv_sec);
1353 1 : tt_str_op("2012-01-11 15:38:58",OP_EQ, timestr);
1354 : /* The output of format_local_iso_time will vary by timezone, and setting
1355 : our timezone for testing purposes would be a nontrivial flaky pain.
1356 : Skip this test for now.
1357 : format_local_iso_time(timestr, tv.tv_sec);
1358 : test_streq("2012-01-11 10:38:58", timestr);
1359 : */
1360 1 : format_iso_time_nospace(timestr, (time_t)tv.tv_sec);
1361 1 : tt_str_op("2012-01-11T15:38:58",OP_EQ, timestr);
1362 1 : tt_int_op(strlen(timestr),OP_EQ, ISO_TIME_LEN);
1363 1 : format_iso_time_nospace_usec(timestr, &tv);
1364 1 : tt_str_op("2012-01-11T15:38:58.003060",OP_EQ, timestr);
1365 1 : tt_int_op(strlen(timestr),OP_EQ, ISO_TIME_USEC_LEN);
1366 :
1367 1 : tv.tv_usec = 0;
1368 : /* This value is in range with 32 bit and 64 bit time_t */
1369 1 : tv.tv_sec = (time_t)2080000000UL;
1370 1 : format_iso_time(timestr, (time_t)tv.tv_sec);
1371 1 : tt_str_op("2035-11-30 01:46:40",OP_EQ, timestr);
1372 :
1373 : /* This value is out of range with 32 bit time_t, but in range for 64 bit
1374 : * time_t */
1375 1 : tv.tv_sec = (time_t)2150000000UL;
1376 1 : CAPTURE();
1377 1 : format_iso_time(timestr, (time_t)tv.tv_sec);
1378 1 : CHECK_POSSIBLE_EINVAL();
1379 : #if SIZEOF_TIME_T == 4
1380 : /* format_iso_time should indicate failure on overflow, but it doesn't yet.
1381 : * Hopefully #18480 will improve the failure semantics in this case.
1382 : tt_str_op("2038-02-17 06:13:20",OP_EQ, timestr);
1383 : */
1384 : #elif SIZEOF_TIME_T == 8
1385 : #ifndef _WIN32
1386 : /* This SHOULD work on windows too; see bug #18665 */
1387 1 : tt_str_op("2038-02-17 06:13:20",OP_EQ, timestr);
1388 : #endif
1389 : #endif /* SIZEOF_TIME_T == 4 || ... */
1390 :
1391 : #undef CAPTURE
1392 : #undef CHECK_TIMEGM_ARG_OUT_OF_RANGE
1393 : #undef CHECK_POSSIBLE_EINVAL
1394 :
1395 1 : done:
1396 1 : teardown_capture_of_logs();
1397 1 : }
1398 :
1399 : static void
1400 1 : test_util_parse_http_time(void *arg)
1401 : {
1402 1 : struct tm a_time;
1403 1 : char b[ISO_TIME_LEN+1];
1404 1 : (void)arg;
1405 :
1406 : #define T(s) do { \
1407 : format_iso_time(b, tor_timegm(&a_time)); \
1408 : tt_str_op(b, OP_EQ, (s)); \
1409 : b[0]='\0'; \
1410 : } while (0)
1411 :
1412 : /* Test parse_http_time */
1413 :
1414 1 : tt_int_op(-1,OP_EQ,
1415 : parse_http_time("", &a_time));
1416 1 : tt_int_op(-1,OP_EQ,
1417 : parse_http_time("Sunday, 32 Aug 2004 00:48:22 GMT", &a_time));
1418 1 : tt_int_op(-1,OP_EQ,
1419 : parse_http_time("Sunday, 3 Aug 1869 00:48:22 GMT", &a_time));
1420 1 : tt_int_op(-1,OP_EQ,
1421 : parse_http_time("Sunday, 32-Aug-94 00:48:22 GMT", &a_time));
1422 1 : tt_int_op(-1,OP_EQ,
1423 : parse_http_time("Sunday, 3-Ago-04 00:48:22", &a_time));
1424 1 : tt_int_op(-1,OP_EQ,
1425 : parse_http_time("Sunday, August the third", &a_time));
1426 1 : tt_int_op(-1,OP_EQ,
1427 : parse_http_time("Wednesday,,04 Aug 1994 00:48:22 GMT", &a_time));
1428 :
1429 1 : tt_int_op(0,OP_EQ,
1430 : parse_http_time("Wednesday, 04 Aug 1994 00:48:22 GMT", &a_time));
1431 1 : tt_int_op((time_t)775961302UL,OP_EQ, tor_timegm(&a_time));
1432 1 : T("1994-08-04 00:48:22");
1433 1 : tt_int_op(0,OP_EQ,
1434 : parse_http_time("Wednesday, 4 Aug 1994 0:48:22 GMT", &a_time));
1435 1 : tt_int_op((time_t)775961302UL,OP_EQ, tor_timegm(&a_time));
1436 1 : T("1994-08-04 00:48:22");
1437 1 : tt_int_op(0,OP_EQ,
1438 : parse_http_time("Miercoles, 4 Aug 1994 0:48:22 GMT", &a_time));
1439 1 : tt_int_op((time_t)775961302UL,OP_EQ, tor_timegm(&a_time));
1440 1 : T("1994-08-04 00:48:22");
1441 1 : tt_int_op(0,OP_EQ,
1442 : parse_http_time("Wednesday, 04-Aug-94 00:48:22 GMT", &a_time));
1443 1 : tt_int_op((time_t)775961302UL,OP_EQ, tor_timegm(&a_time));
1444 1 : T("1994-08-04 00:48:22");
1445 1 : tt_int_op(0,OP_EQ,
1446 : parse_http_time("Wednesday, 4-Aug-94 0:48:22 GMT", &a_time));
1447 1 : tt_int_op((time_t)775961302UL,OP_EQ, tor_timegm(&a_time));
1448 1 : T("1994-08-04 00:48:22");
1449 1 : tt_int_op(0,OP_EQ,
1450 : parse_http_time("Miercoles, 4-Aug-94 0:48:22 GMT", &a_time));
1451 1 : tt_int_op((time_t)775961302UL,OP_EQ, tor_timegm(&a_time));
1452 1 : T("1994-08-04 00:48:22");
1453 1 : tt_int_op(0,OP_EQ, parse_http_time("Wed Aug 04 00:48:22 1994", &a_time));
1454 1 : tt_int_op((time_t)775961302UL,OP_EQ, tor_timegm(&a_time));
1455 1 : T("1994-08-04 00:48:22");
1456 1 : tt_int_op(0,OP_EQ, parse_http_time("Wed Aug 4 0:48:22 1994", &a_time));
1457 1 : tt_int_op((time_t)775961302UL,OP_EQ, tor_timegm(&a_time));
1458 1 : T("1994-08-04 00:48:22");
1459 1 : tt_int_op(0,OP_EQ, parse_http_time("Mie Aug 4 0:48:22 1994", &a_time));
1460 1 : tt_int_op((time_t)775961302UL,OP_EQ, tor_timegm(&a_time));
1461 1 : T("1994-08-04 00:48:22");
1462 1 : tt_int_op(0,OP_EQ,parse_http_time("Sun, 1 Jan 2012 00:00:00 GMT", &a_time));
1463 1 : tt_int_op((time_t)1325376000UL,OP_EQ, tor_timegm(&a_time));
1464 1 : T("2012-01-01 00:00:00");
1465 1 : tt_int_op(0,OP_EQ,parse_http_time("Mon, 31 Dec 2012 00:00:00 GMT", &a_time));
1466 1 : tt_int_op((time_t)1356912000UL,OP_EQ, tor_timegm(&a_time));
1467 1 : T("2012-12-31 00:00:00");
1468 :
1469 : /* This value is in range with 32 bit and 64 bit time_t */
1470 1 : tt_int_op(0,OP_EQ,parse_http_time("Fri, 30 Nov 2035 01:46:40 GMT", &a_time));
1471 1 : tt_int_op((time_t)2080000000UL,OP_EQ, tor_timegm(&a_time));
1472 1 : T("2035-11-30 01:46:40");
1473 :
1474 : /* This value is out of range with 32 bit time_t, but in range for 64 bit
1475 : * time_t */
1476 : #if SIZEOF_TIME_T == 4
1477 : /* parse_http_time should indicate failure on overflow, but it doesn't yet.
1478 : * Hopefully #18480 will improve the failure semantics in this case. */
1479 : setup_full_capture_of_logs(LOG_WARN);
1480 : tt_int_op(0,OP_EQ,parse_http_time("Wed, 17 Feb 2038 06:13:20 GMT", &a_time));
1481 : tt_int_op((time_t)-1,OP_EQ, tor_timegm(&a_time));
1482 : expect_single_log_msg_containing("does not fit in tor_timegm");
1483 : teardown_capture_of_logs();
1484 : #elif SIZEOF_TIME_T == 8
1485 1 : tt_int_op(0,OP_EQ,parse_http_time("Wed, 17 Feb 2038 06:13:20 GMT", &a_time));
1486 1 : tt_int_op((time_t)2150000000UL,OP_EQ, tor_timegm(&a_time));
1487 1 : T("2038-02-17 06:13:20");
1488 : #endif /* SIZEOF_TIME_T == 4 || ... */
1489 :
1490 1 : tt_int_op(-1,OP_EQ, parse_http_time("2004-08-zz 99-99x99 GMT", &a_time));
1491 1 : tt_int_op(-1,OP_EQ, parse_http_time("2011-03-32 00:00:00 GMT", &a_time));
1492 1 : tt_int_op(-1,OP_EQ, parse_http_time("2011-03-30 24:00:00 GMT", &a_time));
1493 1 : tt_int_op(-1,OP_EQ, parse_http_time("2011-03-30 23:60:00 GMT", &a_time));
1494 1 : tt_int_op(-1,OP_EQ, parse_http_time("2011-03-30 23:59:62 GMT", &a_time));
1495 1 : tt_int_op(-1,OP_EQ, parse_http_time("1969-03-30 23:59:59 GMT", &a_time));
1496 1 : tt_int_op(-1,OP_EQ, parse_http_time("2011-00-30 23:59:59 GMT", &a_time));
1497 1 : tt_int_op(-1,OP_EQ, parse_http_time("2011-03-30 23:59", &a_time));
1498 :
1499 : #undef T
1500 1 : done:
1501 1 : teardown_capture_of_logs();
1502 1 : }
1503 :
1504 : static void
1505 1 : test_util_config_line(void *arg)
1506 : {
1507 1 : char buf[1024];
1508 1 : char *k=NULL, *v=NULL;
1509 1 : const char *str;
1510 :
1511 : /* Test parse_config_line_from_str */
1512 1 : (void)arg;
1513 1 : strlcpy(buf, "k v\n" " key value with spaces \n" "keykey val\n"
1514 : "k2\n"
1515 : "k3 \n" "\n" " \n" "#comment\n"
1516 : "k4#a\n" "k5#abc\n" "k6 val #with comment\n"
1517 : "kseven \"a quoted 'string\"\n"
1518 : "k8 \"a \\x71uoted\\n\\\"str\\\\ing\\t\\001\\01\\1\\\"\"\n"
1519 : "k9 a line that\\\n spans two lines.\n\n"
1520 : "k10 more than\\\n one contin\\\nuation\n"
1521 : "k11 \\\ncontinuation at the start\n"
1522 : "k12 line with a\\\n#comment\n embedded\n"
1523 : "k13\\\ncontinuation at the very start\n"
1524 : "k14 a line that has a comment and # ends with a slash \\\n"
1525 : "k15 this should be the next new line\n"
1526 : "k16 a line that has a comment and # ends without a slash \n"
1527 : "k17 this should be the next new line\n"
1528 : , sizeof(buf));
1529 1 : str = buf;
1530 :
1531 1 : str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1532 1 : tt_str_op(k,OP_EQ, "k");
1533 1 : tt_str_op(v,OP_EQ, "v");
1534 1 : tor_free(k); tor_free(v);
1535 1 : tt_assert(!strcmpstart(str, "key value with"));
1536 :
1537 1 : str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1538 1 : tt_str_op(k,OP_EQ, "key");
1539 1 : tt_str_op(v,OP_EQ, "value with spaces");
1540 1 : tor_free(k); tor_free(v);
1541 1 : tt_assert(!strcmpstart(str, "keykey"));
1542 :
1543 1 : str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1544 1 : tt_str_op(k,OP_EQ, "keykey");
1545 1 : tt_str_op(v,OP_EQ, "val");
1546 1 : tor_free(k); tor_free(v);
1547 1 : tt_assert(!strcmpstart(str, "k2\n"));
1548 :
1549 1 : str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1550 1 : tt_str_op(k,OP_EQ, "k2");
1551 1 : tt_str_op(v,OP_EQ, "");
1552 1 : tor_free(k); tor_free(v);
1553 1 : tt_assert(!strcmpstart(str, "k3 \n"));
1554 :
1555 1 : str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1556 1 : tt_str_op(k,OP_EQ, "k3");
1557 1 : tt_str_op(v,OP_EQ, "");
1558 1 : tor_free(k); tor_free(v);
1559 1 : tt_assert(!strcmpstart(str, "#comment"));
1560 :
1561 1 : str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1562 1 : tt_str_op(k,OP_EQ, "k4");
1563 1 : tt_str_op(v,OP_EQ, "");
1564 1 : tor_free(k); tor_free(v);
1565 1 : tt_assert(!strcmpstart(str, "k5#abc"));
1566 :
1567 1 : str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1568 1 : tt_str_op(k,OP_EQ, "k5");
1569 1 : tt_str_op(v,OP_EQ, "");
1570 1 : tor_free(k); tor_free(v);
1571 1 : tt_assert(!strcmpstart(str, "k6"));
1572 :
1573 1 : str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1574 1 : tt_str_op(k,OP_EQ, "k6");
1575 1 : tt_str_op(v,OP_EQ, "val");
1576 1 : tor_free(k); tor_free(v);
1577 1 : tt_assert(!strcmpstart(str, "kseven"));
1578 :
1579 1 : str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1580 1 : tt_str_op(k,OP_EQ, "kseven");
1581 1 : tt_str_op(v,OP_EQ, "a quoted \'string");
1582 1 : tor_free(k); tor_free(v);
1583 1 : tt_assert(!strcmpstart(str, "k8 "));
1584 :
1585 1 : str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1586 1 : tt_str_op(k,OP_EQ, "k8");
1587 1 : tt_str_op(v,OP_EQ, "a quoted\n\"str\\ing\t\x01\x01\x01\"");
1588 1 : tor_free(k); tor_free(v);
1589 :
1590 1 : str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1591 1 : tt_str_op(k,OP_EQ, "k9");
1592 1 : tt_str_op(v,OP_EQ, "a line that spans two lines.");
1593 1 : tor_free(k); tor_free(v);
1594 :
1595 1 : str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1596 1 : tt_str_op(k,OP_EQ, "k10");
1597 1 : tt_str_op(v,OP_EQ, "more than one continuation");
1598 1 : tor_free(k); tor_free(v);
1599 :
1600 1 : str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1601 1 : tt_str_op(k,OP_EQ, "k11");
1602 1 : tt_str_op(v,OP_EQ, "continuation at the start");
1603 1 : tor_free(k); tor_free(v);
1604 :
1605 1 : str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1606 1 : tt_str_op(k,OP_EQ, "k12");
1607 1 : tt_str_op(v,OP_EQ, "line with a embedded");
1608 1 : tor_free(k); tor_free(v);
1609 :
1610 1 : str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1611 1 : tt_str_op(k,OP_EQ, "k13");
1612 1 : tt_str_op(v,OP_EQ, "continuation at the very start");
1613 1 : tor_free(k); tor_free(v);
1614 :
1615 1 : str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1616 1 : tt_str_op(k,OP_EQ, "k14");
1617 1 : tt_str_op(v,OP_EQ, "a line that has a comment and" );
1618 1 : tor_free(k); tor_free(v);
1619 :
1620 1 : str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1621 1 : tt_str_op(k,OP_EQ, "k15");
1622 1 : tt_str_op(v,OP_EQ, "this should be the next new line");
1623 1 : tor_free(k); tor_free(v);
1624 :
1625 1 : str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1626 1 : tt_str_op(k,OP_EQ, "k16");
1627 1 : tt_str_op(v,OP_EQ, "a line that has a comment and" );
1628 1 : tor_free(k); tor_free(v);
1629 :
1630 1 : str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1631 1 : tt_str_op(k,OP_EQ, "k17");
1632 1 : tt_str_op(v,OP_EQ, "this should be the next new line");
1633 1 : tor_free(k); tor_free(v);
1634 :
1635 1 : tt_str_op(str,OP_EQ, "");
1636 :
1637 1 : done:
1638 1 : tor_free(k);
1639 1 : tor_free(v);
1640 1 : }
1641 :
1642 : static void
1643 1 : test_util_config_line_quotes(void *arg)
1644 : {
1645 1 : char buf1[1024];
1646 1 : char buf2[128];
1647 1 : char buf3[128];
1648 1 : char buf4[128];
1649 1 : char *k=NULL, *v=NULL;
1650 1 : const char *str;
1651 :
1652 : /* Test parse_config_line_from_str */
1653 1 : (void)arg;
1654 1 : strlcpy(buf1, "kTrailingSpace \"quoted value\" \n"
1655 : "kTrailingGarbage \"quoted value\"trailing garbage\n"
1656 : , sizeof(buf1));
1657 1 : strlcpy(buf2, "kTrailingSpaceAndGarbage \"quoted value\" trailing space+g\n"
1658 : , sizeof(buf2));
1659 1 : strlcpy(buf3, "kMultilineTrailingSpace \"mline\\ \nvalue w/ trailing sp\"\n"
1660 : , sizeof(buf3));
1661 1 : strlcpy(buf4, "kMultilineNoTrailingBackslash \"naked multiline\nvalue\"\n"
1662 : , sizeof(buf4));
1663 1 : str = buf1;
1664 :
1665 1 : str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1666 1 : tt_str_op(k,OP_EQ, "kTrailingSpace");
1667 1 : tt_str_op(v,OP_EQ, "quoted value");
1668 1 : tor_free(k); tor_free(v);
1669 :
1670 1 : str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1671 1 : tt_ptr_op(str,OP_EQ, NULL);
1672 1 : tor_free(k); tor_free(v);
1673 :
1674 1 : str = buf2;
1675 :
1676 1 : str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1677 1 : tt_ptr_op(str,OP_EQ, NULL);
1678 1 : tor_free(k); tor_free(v);
1679 :
1680 1 : str = buf3;
1681 :
1682 1 : const char *err = NULL;
1683 1 : str = parse_config_line_from_str_verbose(str, &k, &v, &err);
1684 1 : tt_ptr_op(str,OP_EQ, NULL);
1685 1 : tor_free(k); tor_free(v);
1686 1 : tt_str_op(err, OP_EQ, "Invalid escape sequence in quoted string");
1687 :
1688 1 : str = buf4;
1689 :
1690 1 : err = NULL;
1691 1 : str = parse_config_line_from_str_verbose(str, &k, &v, &err);
1692 1 : tt_ptr_op(str,OP_EQ, NULL);
1693 1 : tor_free(k); tor_free(v);
1694 1 : tt_str_op(err, OP_EQ, "Invalid escape sequence in quoted string");
1695 :
1696 1 : done:
1697 1 : tor_free(k);
1698 1 : tor_free(v);
1699 1 : }
1700 :
1701 : static void
1702 1 : test_util_config_line_comment_character(void *arg)
1703 : {
1704 1 : char buf[1024];
1705 1 : char *k=NULL, *v=NULL;
1706 1 : const char *str;
1707 :
1708 : /* Test parse_config_line_from_str */
1709 1 : (void)arg;
1710 1 : strlcpy(buf, "k1 \"# in quotes\"\n"
1711 : "k2 some value # some comment\n"
1712 : "k3 /home/user/myTorNetwork#2\n" /* Testcase for #1323 */
1713 : , sizeof(buf));
1714 1 : str = buf;
1715 :
1716 1 : str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1717 1 : tt_str_op(k,OP_EQ, "k1");
1718 1 : tt_str_op(v,OP_EQ, "# in quotes");
1719 1 : tor_free(k); tor_free(v);
1720 :
1721 1 : str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1722 1 : tt_str_op(k,OP_EQ, "k2");
1723 1 : tt_str_op(v,OP_EQ, "some value");
1724 1 : tor_free(k); tor_free(v);
1725 :
1726 1 : tt_str_op(str,OP_EQ, "k3 /home/user/myTorNetwork#2\n");
1727 :
1728 : #if 0
1729 : str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1730 : test_streq(k, "k3");
1731 : test_streq(v, "/home/user/myTorNetwork#2");
1732 : tor_free(k); tor_free(v);
1733 :
1734 : test_streq(str, "");
1735 : #endif /* 0 */
1736 :
1737 1 : done:
1738 1 : tor_free(k);
1739 1 : tor_free(v);
1740 1 : }
1741 :
1742 : static void
1743 1 : test_util_config_line_escaped_content(void *arg)
1744 : {
1745 1 : char buf1[1024];
1746 1 : char buf2[128];
1747 1 : char buf3[128];
1748 1 : char buf4[128];
1749 1 : char buf5[128];
1750 1 : char buf6[128];
1751 1 : char *k=NULL, *v=NULL;
1752 1 : const char *str;
1753 :
1754 : /* Test parse_config_line_from_str */
1755 1 : (void)arg;
1756 1 : strlcpy(buf1, "HexadecimalLower \"\\x2a\"\n"
1757 : "HexadecimalUpper \"\\x2A\"\n"
1758 : "HexadecimalUpperX \"\\X2A\"\n"
1759 : "Octal \"\\52\"\n"
1760 : "Newline \"\\n\"\n"
1761 : "Tab \"\\t\"\n"
1762 : "CarriageReturn \"\\r\"\n"
1763 : "DoubleQuote \"\\\"\"\n"
1764 : "SimpleQuote \"\\'\"\n"
1765 : "Backslash \"\\\\\"\n"
1766 : "Mix \"This is a \\\"star\\\":\\t\\'\\x2a\\'\\nAnd second line\"\n"
1767 : , sizeof(buf1));
1768 :
1769 1 : strlcpy(buf2, "BrokenEscapedContent \"\\a\"\n"
1770 : , sizeof(buf2));
1771 :
1772 1 : strlcpy(buf3, "BrokenEscapedContent \"\\x\"\n"
1773 : , sizeof(buf3));
1774 :
1775 1 : strlcpy(buf4, "BrokenOctal \"\\8\"\n"
1776 : , sizeof(buf4));
1777 :
1778 1 : strlcpy(buf5, "BrokenHex \"\\xg4\"\n"
1779 : , sizeof(buf5));
1780 :
1781 1 : strlcpy(buf6, "BrokenEscape \"\\"
1782 : , sizeof(buf6));
1783 :
1784 1 : str = buf1;
1785 :
1786 1 : str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1787 1 : tt_str_op(k,OP_EQ, "HexadecimalLower");
1788 1 : tt_str_op(v,OP_EQ, "*");
1789 1 : tor_free(k); tor_free(v);
1790 :
1791 1 : str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1792 1 : tt_str_op(k,OP_EQ, "HexadecimalUpper");
1793 1 : tt_str_op(v,OP_EQ, "*");
1794 1 : tor_free(k); tor_free(v);
1795 :
1796 1 : str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1797 1 : tt_str_op(k,OP_EQ, "HexadecimalUpperX");
1798 1 : tt_str_op(v,OP_EQ, "*");
1799 1 : tor_free(k); tor_free(v);
1800 :
1801 1 : str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1802 1 : tt_str_op(k,OP_EQ, "Octal");
1803 1 : tt_str_op(v,OP_EQ, "*");
1804 1 : tor_free(k); tor_free(v);
1805 :
1806 1 : str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1807 1 : tt_str_op(k,OP_EQ, "Newline");
1808 1 : tt_str_op(v,OP_EQ, "\n");
1809 1 : tor_free(k); tor_free(v);
1810 :
1811 1 : str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1812 1 : tt_str_op(k,OP_EQ, "Tab");
1813 1 : tt_str_op(v,OP_EQ, "\t");
1814 1 : tor_free(k); tor_free(v);
1815 :
1816 1 : str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1817 1 : tt_str_op(k,OP_EQ, "CarriageReturn");
1818 1 : tt_str_op(v,OP_EQ, "\r");
1819 1 : tor_free(k); tor_free(v);
1820 :
1821 1 : str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1822 1 : tt_str_op(k,OP_EQ, "DoubleQuote");
1823 1 : tt_str_op(v,OP_EQ, "\"");
1824 1 : tor_free(k); tor_free(v);
1825 :
1826 1 : str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1827 1 : tt_str_op(k,OP_EQ, "SimpleQuote");
1828 1 : tt_str_op(v,OP_EQ, "'");
1829 1 : tor_free(k); tor_free(v);
1830 :
1831 1 : str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1832 1 : tt_str_op(k,OP_EQ, "Backslash");
1833 1 : tt_str_op(v,OP_EQ, "\\");
1834 1 : tor_free(k); tor_free(v);
1835 :
1836 1 : str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1837 1 : tt_str_op(k,OP_EQ, "Mix");
1838 1 : tt_str_op(v,OP_EQ, "This is a \"star\":\t'*'\nAnd second line");
1839 1 : tor_free(k); tor_free(v);
1840 1 : tt_str_op(str,OP_EQ, "");
1841 :
1842 1 : str = buf2;
1843 :
1844 1 : str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1845 1 : tt_ptr_op(str,OP_EQ, NULL);
1846 1 : tor_free(k); tor_free(v);
1847 :
1848 1 : str = buf3;
1849 :
1850 1 : str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1851 1 : tt_ptr_op(str,OP_EQ, NULL);
1852 1 : tor_free(k); tor_free(v);
1853 :
1854 1 : str = buf4;
1855 :
1856 1 : str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1857 1 : tt_ptr_op(str,OP_EQ, NULL);
1858 1 : tor_free(k); tor_free(v);
1859 :
1860 : #if 0
1861 : str = buf5;
1862 :
1863 : str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1864 : tt_ptr_op(str, OP_EQ, NULL);
1865 : tor_free(k); tor_free(v);
1866 : #endif /* 0 */
1867 :
1868 1 : str = buf6;
1869 :
1870 1 : str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1871 1 : tt_ptr_op(str,OP_EQ, NULL);
1872 1 : tor_free(k); tor_free(v);
1873 :
1874 : /* more things to try. */
1875 : /* Bad hex: */
1876 1 : strlcpy(buf1, "Foo \"\\x9g\"\n", sizeof(buf1));
1877 1 : strlcpy(buf2, "Foo \"\\xg0\"\n", sizeof(buf2));
1878 1 : strlcpy(buf3, "Foo \"\\xf\"\n", sizeof(buf3));
1879 : /* bad escape */
1880 1 : strlcpy(buf4, "Foo \"\\q\"\n", sizeof(buf4));
1881 : /* missing endquote */
1882 1 : strlcpy(buf5, "Foo \"hello\n", sizeof(buf5));
1883 : /* extra stuff */
1884 1 : strlcpy(buf6, "Foo \"hello\" world\n", sizeof(buf6));
1885 :
1886 1 : str=buf1;
1887 1 : str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1888 1 : tt_ptr_op(str,OP_EQ, NULL);
1889 1 : tor_free(k); tor_free(v);
1890 :
1891 1 : str=buf2;
1892 1 : str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1893 1 : tt_ptr_op(str,OP_EQ, NULL);
1894 1 : tor_free(k); tor_free(v);
1895 :
1896 1 : str=buf3;
1897 1 : str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1898 1 : tt_ptr_op(str,OP_EQ, NULL);
1899 1 : tor_free(k); tor_free(v);
1900 :
1901 1 : str=buf4;
1902 1 : str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1903 1 : tt_ptr_op(str,OP_EQ, NULL);
1904 1 : tor_free(k); tor_free(v);
1905 :
1906 1 : str=buf5;
1907 :
1908 1 : str = parse_config_line_from_str_verbose(str, &k, &v, NULL);
1909 1 : tt_ptr_op(str,OP_EQ, NULL);
1910 1 : tor_free(k); tor_free(v);
1911 :
1912 1 : str=buf6;
1913 1 : const char *err = NULL;
1914 1 : str = parse_config_line_from_str_verbose(str, &k, &v, &err);
1915 1 : tt_ptr_op(str,OP_EQ, NULL);
1916 1 : tor_free(k); tor_free(v);
1917 1 : tt_str_op(err,OP_EQ, "Excess data after quoted string");
1918 :
1919 1 : done:
1920 1 : tor_free(k);
1921 1 : tor_free(v);
1922 1 : }
1923 :
1924 : static void
1925 1 : test_util_config_line_crlf(void *arg)
1926 : {
1927 1 : char *k=NULL, *v=NULL;
1928 1 : const char *err = NULL;
1929 1 : (void)arg;
1930 1 : const char *str =
1931 : "Hello world\r\n"
1932 : "Hello \"nice big world\"\r\n";
1933 :
1934 1 : str = parse_config_line_from_str_verbose(str, &k, &v, &err);
1935 1 : tt_assert(str);
1936 1 : tt_str_op(k,OP_EQ,"Hello");
1937 1 : tt_str_op(v,OP_EQ,"world");
1938 1 : tt_ptr_op(err, OP_EQ, NULL);
1939 1 : tor_free(k); tor_free(v);
1940 :
1941 1 : str = parse_config_line_from_str_verbose(str, &k, &v, &err);
1942 1 : tt_assert(str);
1943 1 : tt_str_op(k,OP_EQ,"Hello");
1944 1 : tt_str_op(v,OP_EQ,"nice big world");
1945 1 : tt_ptr_op(err, OP_EQ, NULL);
1946 1 : tor_free(k); tor_free(v);
1947 1 : tt_str_op(str,OP_EQ, "");
1948 :
1949 1 : done:
1950 1 : tor_free(k); tor_free(v);
1951 1 : }
1952 :
1953 : static void
1954 1 : test_util_config_line_partition(void *arg)
1955 : {
1956 1 : (void)arg;
1957 1 : config_line_t *lines = NULL, *orig, *rest = NULL;
1958 :
1959 1 : config_line_append(&lines, "Header", "X");
1960 1 : config_line_append(&lines, "Item", "Y");
1961 1 : config_line_append(&lines, "Thing", "Z");
1962 :
1963 1 : config_line_append(&lines, "HEADER", "X2");
1964 :
1965 1 : config_line_append(&lines, "header", "X3");
1966 1 : config_line_append(&lines, "Item3", "Foob");
1967 :
1968 : /* set up h2 and h3 to point to the places where we hope the headers will
1969 : be. */
1970 1 : config_line_t *h2 = lines->next->next->next;
1971 1 : config_line_t *h3 = h2->next;
1972 1 : tt_str_op(h2->key, OP_EQ, "HEADER");
1973 1 : tt_str_op(h3->key, OP_EQ, "header");
1974 :
1975 1 : orig = lines;
1976 1 : rest = config_lines_partition(lines, "Header");
1977 1 : tt_ptr_op(lines, OP_EQ, orig);
1978 1 : tt_ptr_op(rest, OP_EQ, h2);
1979 1 : tt_str_op(lines->next->key, OP_EQ, "Item");
1980 1 : tt_str_op(lines->next->next->key, OP_EQ, "Thing");
1981 1 : tt_ptr_op(lines->next->next->next, OP_EQ, NULL);
1982 1 : config_free_lines(lines);
1983 :
1984 1 : orig = lines = rest;
1985 1 : rest = config_lines_partition(lines, "Header");
1986 1 : tt_ptr_op(lines, OP_EQ, orig);
1987 1 : tt_ptr_op(rest, OP_EQ, h3);
1988 1 : tt_ptr_op(lines->next, OP_EQ, NULL);
1989 1 : config_free_lines(lines);
1990 :
1991 1 : orig = lines = rest;
1992 1 : rest = config_lines_partition(lines, "Header");
1993 1 : tt_ptr_op(lines, OP_EQ, orig);
1994 1 : tt_ptr_op(rest, OP_EQ, NULL);
1995 1 : tt_str_op(lines->next->key, OP_EQ, "Item3");
1996 1 : tt_ptr_op(lines->next->next, OP_EQ, NULL);
1997 :
1998 1 : done:
1999 1 : config_free_lines(lines);
2000 1 : config_free_lines(rest);
2001 1 : }
2002 :
2003 : #ifndef DISABLE_PWDB_TESTS
2004 : static void
2005 1 : test_util_expand_filename(void *arg)
2006 : {
2007 1 : char *str;
2008 :
2009 1 : (void)arg;
2010 1 : setenv("HOME", "/home/itv", 1); /* For "internal test value" */
2011 :
2012 1 : str = expand_filename("");
2013 1 : tt_str_op("",OP_EQ, str);
2014 1 : tor_free(str);
2015 :
2016 1 : str = expand_filename("/normal/path");
2017 1 : tt_str_op("/normal/path",OP_EQ, str);
2018 1 : tor_free(str);
2019 :
2020 1 : str = expand_filename("/normal/trailing/path/");
2021 1 : tt_str_op("/normal/trailing/path/",OP_EQ, str);
2022 1 : tor_free(str);
2023 :
2024 1 : str = expand_filename("~");
2025 1 : tt_str_op("/home/itv/",OP_EQ, str);
2026 1 : tor_free(str);
2027 :
2028 1 : str = expand_filename("$HOME/nodice");
2029 1 : tt_str_op("$HOME/nodice",OP_EQ, str);
2030 1 : tor_free(str);
2031 :
2032 1 : str = expand_filename("~/");
2033 1 : tt_str_op("/home/itv/",OP_EQ, str);
2034 1 : tor_free(str);
2035 :
2036 1 : str = expand_filename("~/foobarqux");
2037 1 : tt_str_op("/home/itv/foobarqux",OP_EQ, str);
2038 1 : tor_free(str);
2039 :
2040 1 : str = expand_filename("~/../../etc/passwd");
2041 1 : tt_str_op("/home/itv/../../etc/passwd",OP_EQ, str);
2042 1 : tor_free(str);
2043 :
2044 1 : str = expand_filename("~/trailing/");
2045 1 : tt_str_op("/home/itv/trailing/",OP_EQ, str);
2046 1 : tor_free(str);
2047 : /* Ideally we'd test ~anotheruser, but that's shady to test (we'd
2048 : have to somehow inject/fake the get_user_homedir call) */
2049 :
2050 : /* $HOME ending in a trailing slash */
2051 1 : setenv("HOME", "/home/itv/", 1);
2052 :
2053 1 : str = expand_filename("~");
2054 1 : tt_str_op("/home/itv/",OP_EQ, str);
2055 1 : tor_free(str);
2056 :
2057 1 : str = expand_filename("~/");
2058 1 : tt_str_op("/home/itv/",OP_EQ, str);
2059 1 : tor_free(str);
2060 :
2061 1 : str = expand_filename("~/foo");
2062 1 : tt_str_op("/home/itv/foo",OP_EQ, str);
2063 1 : tor_free(str);
2064 :
2065 : /* Try with empty $HOME */
2066 :
2067 1 : setenv("HOME", "", 1);
2068 :
2069 1 : str = expand_filename("~");
2070 1 : tt_str_op("/",OP_EQ, str);
2071 1 : tor_free(str);
2072 :
2073 1 : str = expand_filename("~/");
2074 1 : tt_str_op("/",OP_EQ, str);
2075 1 : tor_free(str);
2076 :
2077 1 : str = expand_filename("~/foobar");
2078 1 : tt_str_op("/foobar",OP_EQ, str);
2079 1 : tor_free(str);
2080 :
2081 : /* Try with $HOME unset */
2082 :
2083 1 : unsetenv("HOME");
2084 :
2085 1 : str = expand_filename("~");
2086 1 : tt_str_op("/",OP_EQ, str);
2087 1 : tor_free(str);
2088 :
2089 1 : str = expand_filename("~/");
2090 1 : tt_str_op("/",OP_EQ, str);
2091 1 : tor_free(str);
2092 :
2093 1 : str = expand_filename("~/foobar");
2094 1 : tt_str_op("/foobar",OP_EQ, str);
2095 1 : tor_free(str);
2096 :
2097 1 : done:
2098 1 : tor_free(str);
2099 1 : }
2100 : #endif /* !defined(DISABLE_PWDB_TESTS) */
2101 :
2102 : /** Test tor_escape_str_for_pt_args(). */
2103 : static void
2104 1 : test_util_escape_string_socks(void *arg)
2105 : {
2106 1 : char *escaped_string = NULL;
2107 :
2108 : /** Simple backslash escape. */
2109 1 : (void)arg;
2110 1 : escaped_string = tor_escape_str_for_pt_args("This is a backslash: \\",";\\");
2111 1 : tt_assert(escaped_string);
2112 1 : tt_str_op(escaped_string,OP_EQ, "This is a backslash: \\\\");
2113 1 : tor_free(escaped_string);
2114 :
2115 : /** Simple semicolon escape. */
2116 1 : escaped_string = tor_escape_str_for_pt_args("First rule:Do not use ;",";\\");
2117 1 : tt_assert(escaped_string);
2118 1 : tt_str_op(escaped_string,OP_EQ, "First rule:Do not use \\;");
2119 1 : tor_free(escaped_string);
2120 :
2121 : /** Empty string. */
2122 1 : escaped_string = tor_escape_str_for_pt_args("", ";\\");
2123 1 : tt_assert(escaped_string);
2124 1 : tt_str_op(escaped_string,OP_EQ, "");
2125 1 : tor_free(escaped_string);
2126 :
2127 : /** Escape all characters. */
2128 1 : escaped_string = tor_escape_str_for_pt_args(";\\;\\", ";\\");
2129 1 : tt_assert(escaped_string);
2130 1 : tt_str_op(escaped_string,OP_EQ, "\\;\\\\\\;\\\\");
2131 1 : tor_free(escaped_string);
2132 :
2133 1 : escaped_string = tor_escape_str_for_pt_args(";", ";\\");
2134 1 : tt_assert(escaped_string);
2135 1 : tt_str_op(escaped_string,OP_EQ, "\\;");
2136 1 : tor_free(escaped_string);
2137 :
2138 1 : done:
2139 1 : tor_free(escaped_string);
2140 1 : }
2141 :
2142 : static void
2143 1 : test_util_string_is_key_value(void *ptr)
2144 : {
2145 1 : (void)ptr;
2146 1 : tt_assert(string_is_key_value(LOG_WARN, "key=value"));
2147 1 : tt_assert(string_is_key_value(LOG_WARN, "k=v"));
2148 1 : tt_assert(string_is_key_value(LOG_WARN, "key="));
2149 1 : tt_assert(string_is_key_value(LOG_WARN, "x="));
2150 1 : tt_assert(string_is_key_value(LOG_WARN, "xx="));
2151 1 : tt_assert(!string_is_key_value(LOG_WARN, "=value"));
2152 1 : tt_assert(!string_is_key_value(LOG_WARN, "=x"));
2153 1 : tt_assert(!string_is_key_value(LOG_WARN, "="));
2154 :
2155 : /* ??? */
2156 : /* tt_assert(!string_is_key_value(LOG_WARN, "===")); */
2157 1 : done:
2158 1 : ;
2159 1 : }
2160 :
2161 : /** Test basic string functionality. */
2162 : static void
2163 1 : test_util_strmisc(void *arg)
2164 : {
2165 1 : char buf[1024];
2166 1 : char *cp_tmp = NULL;
2167 :
2168 : /* Test strl operations */
2169 1 : (void)arg;
2170 1 : tt_int_op(5,OP_EQ, strlcpy(buf, "Hello", 0));
2171 1 : tt_int_op(5,OP_EQ, strlcpy(buf, "Hello", 10));
2172 1 : tt_str_op(buf,OP_EQ, "Hello");
2173 1 : tt_int_op(5,OP_EQ, strlcpy(buf, "Hello", 6));
2174 1 : tt_str_op(buf,OP_EQ, "Hello");
2175 1 : tt_int_op(5,OP_EQ, strlcpy(buf, "Hello", 5));
2176 1 : tt_str_op(buf,OP_EQ, "Hell");
2177 1 : strlcpy(buf, "Hello", sizeof(buf));
2178 1 : tt_int_op(10,OP_EQ, strlcat(buf, "Hello", 5));
2179 :
2180 : /* Test strstrip() */
2181 1 : strlcpy(buf, "Testing 1 2 3", sizeof(buf));
2182 1 : tor_strstrip(buf, ",!");
2183 1 : tt_str_op(buf,OP_EQ, "Testing 1 2 3");
2184 1 : strlcpy(buf, "!Testing 1 2 3?", sizeof(buf));
2185 1 : tor_strstrip(buf, "!? ");
2186 1 : tt_str_op(buf,OP_EQ, "Testing123");
2187 1 : strlcpy(buf, "!!!Testing 1 2 3??", sizeof(buf));
2188 1 : tor_strstrip(buf, "!? ");
2189 1 : tt_str_op(buf,OP_EQ, "Testing123");
2190 :
2191 : /* Test snprintf */
2192 : /* Returning -1 when there's not enough room in the output buffer */
2193 1 : tt_int_op(-1,OP_EQ, tor_snprintf(buf, 0, "Foo"));
2194 1 : tt_int_op(-1,OP_EQ, tor_snprintf(buf, 2, "Foo"));
2195 1 : tt_int_op(-1,OP_EQ, tor_snprintf(buf, 3, "Foo"));
2196 1 : tt_int_op(-1,OP_NE, tor_snprintf(buf, 4, "Foo"));
2197 : /* Always NUL-terminate the output */
2198 1 : tor_snprintf(buf, 5, "abcdef");
2199 1 : tt_int_op(0,OP_EQ, buf[4]);
2200 1 : tor_snprintf(buf, 10, "abcdef");
2201 1 : tt_int_op(0,OP_EQ, buf[6]);
2202 : /* uint64 */
2203 1 : tor_snprintf(buf, sizeof(buf), "x!%"PRIu64"!x",
2204 : (UINT64_C(12345678901)));
2205 1 : tt_str_op("x!12345678901!x",OP_EQ, buf);
2206 :
2207 : /* Test str{,case}cmpstart */
2208 1 : tt_assert(strcmpstart("abcdef", "abcdef")==0);
2209 1 : tt_assert(strcmpstart("abcdef", "abc")==0);
2210 1 : tt_assert(strcmpstart("abcdef", "abd")<0);
2211 1 : tt_assert(strcmpstart("abcdef", "abb")>0);
2212 1 : tt_assert(strcmpstart("ab", "abb")<0);
2213 1 : tt_assert(strcmpstart("ab", "")==0);
2214 1 : tt_assert(strcmpstart("ab", "ab ")<0);
2215 1 : tt_assert(strcasecmpstart("abcdef", "abCdEF")==0);
2216 1 : tt_assert(strcasecmpstart("abcDeF", "abc")==0);
2217 1 : tt_assert(strcasecmpstart("abcdef", "Abd")<0);
2218 1 : tt_assert(strcasecmpstart("Abcdef", "abb")>0);
2219 1 : tt_assert(strcasecmpstart("ab", "Abb")<0);
2220 1 : tt_assert(strcasecmpstart("ab", "")==0);
2221 1 : tt_assert(strcasecmpstart("ab", "ab ")<0);
2222 :
2223 : /* Test str{,case}cmpend */
2224 1 : tt_assert(strcmpend("abcdef", "abcdef")==0);
2225 1 : tt_assert(strcmpend("abcdef", "def")==0);
2226 1 : tt_assert(strcmpend("abcdef", "deg")<0);
2227 1 : tt_assert(strcmpend("abcdef", "dee")>0);
2228 1 : tt_assert(strcmpend("ab", "aab")>0);
2229 1 : tt_assert(strcasecmpend("AbcDEF", "abcdef")==0);
2230 1 : tt_assert(strcasecmpend("abcdef", "dEF")==0);
2231 1 : tt_assert(strcasecmpend("abcdef", "Deg")<0);
2232 1 : tt_assert(strcasecmpend("abcDef", "dee")>0);
2233 1 : tt_assert(strcasecmpend("AB", "abb")<0);
2234 :
2235 : /* Test digest_is_zero */
2236 1 : memset(buf,0,20);
2237 1 : buf[20] = 'x';
2238 1 : tt_assert(tor_digest_is_zero(buf));
2239 1 : buf[19] = 'x';
2240 1 : tt_assert(!tor_digest_is_zero(buf));
2241 :
2242 : /* Test mem_is_zero */
2243 1 : memset(buf,0,128);
2244 1 : buf[128] = 'x';
2245 1 : tt_assert(fast_mem_is_zero(buf, 10));
2246 1 : tt_assert(fast_mem_is_zero(buf, 20));
2247 1 : tt_assert(fast_mem_is_zero(buf, 128));
2248 1 : tt_assert(!fast_mem_is_zero(buf, 129));
2249 1 : buf[60] = (char)255;
2250 1 : tt_assert(!fast_mem_is_zero(buf, 128));
2251 1 : buf[0] = (char)1;
2252 1 : tt_assert(!fast_mem_is_zero(buf, 10));
2253 :
2254 : /* Test 'escaped' */
2255 1 : tt_ptr_op(escaped(NULL), OP_EQ, NULL);
2256 1 : tt_str_op("\"\"",OP_EQ, escaped(""));
2257 1 : tt_str_op("\"abcd\"",OP_EQ, escaped("abcd"));
2258 1 : tt_str_op("\"\\\\ \\n\\r\\t\\\"\\'\"",OP_EQ, escaped("\\ \n\r\t\"'"));
2259 1 : tt_str_op("\"unnecessary \\'backslashes\\'\"",OP_EQ,
2260 : escaped("unnecessary \'backslashes\'"));
2261 : /* Non-printable characters appear as octal */
2262 1 : tt_str_op("\"z\\001abc\\277d\"",OP_EQ, escaped("z\001abc\277d"));
2263 1 : tt_str_op("\"z\\336\\255 ;foo\"",OP_EQ, escaped("z\xde\xad\x20;foo"));
2264 :
2265 : /* Other cases of esc_for_log{,_len} */
2266 1 : cp_tmp = esc_for_log(NULL);
2267 1 : tt_str_op(cp_tmp, OP_EQ, "(null)");
2268 1 : tor_free(cp_tmp);
2269 1 : cp_tmp = esc_for_log_len("abcdefg", 3);
2270 1 : tt_str_op(cp_tmp, OP_EQ, "\"abc\"");
2271 1 : tor_free(cp_tmp);
2272 1 : cp_tmp = esc_for_log_len("abcdefg", 100);
2273 1 : tt_str_op(cp_tmp, OP_EQ, "\"abcdefg\"");
2274 1 : tor_free(cp_tmp);
2275 :
2276 : /* Test strndup and memdup */
2277 : {
2278 1 : const char *s = "abcdefghijklmnopqrstuvwxyz";
2279 1 : cp_tmp = tor_strndup(s, 30);
2280 1 : tt_str_op(cp_tmp,OP_EQ, s); /* same string, */
2281 1 : tt_ptr_op(cp_tmp,OP_NE,s); /* but different pointers. */
2282 1 : tor_free(cp_tmp);
2283 :
2284 1 : cp_tmp = tor_strndup(s, 5);
2285 1 : tt_str_op(cp_tmp,OP_EQ, "abcde");
2286 1 : tor_free(cp_tmp);
2287 :
2288 1 : s = "a\0b\0c\0d\0e\0";
2289 1 : cp_tmp = tor_memdup(s,10);
2290 1 : tt_mem_op(cp_tmp,OP_EQ, s, 10); /* same ram, */
2291 1 : tt_ptr_op(cp_tmp,OP_NE,s); /* but different pointers. */
2292 1 : tor_free(cp_tmp);
2293 : }
2294 :
2295 : /* Test str-foo functions */
2296 1 : cp_tmp = tor_strdup("abcdef");
2297 1 : tt_assert(tor_strisnonupper(cp_tmp));
2298 1 : cp_tmp[3] = 'D';
2299 1 : tt_assert(!tor_strisnonupper(cp_tmp));
2300 1 : tor_strupper(cp_tmp);
2301 1 : tt_str_op(cp_tmp,OP_EQ, "ABCDEF");
2302 1 : tor_strlower(cp_tmp);
2303 1 : tt_str_op(cp_tmp,OP_EQ, "abcdef");
2304 1 : tt_assert(tor_strisnonupper(cp_tmp));
2305 1 : tt_assert(tor_strisprint(cp_tmp));
2306 1 : cp_tmp[3] = 3;
2307 1 : tt_assert(!tor_strisprint(cp_tmp));
2308 1 : tor_free(cp_tmp);
2309 :
2310 : /* Test memmem and memstr */
2311 : {
2312 1 : const char *haystack = "abcde";
2313 1 : tt_ptr_op(tor_memmem(haystack, 5, "ef", 2), OP_EQ, NULL);
2314 1 : tt_ptr_op(tor_memmem(haystack, 5, "cd", 2),OP_EQ, haystack + 2);
2315 1 : tt_ptr_op(tor_memmem(haystack, 5, "cde", 3),OP_EQ, haystack + 2);
2316 1 : tt_ptr_op(tor_memmem(haystack, 4, "cde", 3), OP_EQ, NULL);
2317 1 : haystack = "ababcad";
2318 1 : tt_ptr_op(tor_memmem(haystack, 7, "abc", 3),OP_EQ, haystack + 2);
2319 1 : tt_ptr_op(tor_memmem(haystack, 7, "ad", 2),OP_EQ, haystack + 5);
2320 1 : tt_ptr_op(tor_memmem(haystack, 7, "cad", 3),OP_EQ, haystack + 4);
2321 1 : tt_ptr_op(tor_memmem(haystack, 7, "dadad", 5), OP_EQ, NULL);
2322 1 : tt_ptr_op(tor_memmem(haystack, 7, "abcdefghij", 10), OP_EQ, NULL);
2323 : /* memstr */
2324 1 : tt_ptr_op(tor_memstr(haystack, 7, "abc"),OP_EQ, haystack + 2);
2325 1 : tt_ptr_op(tor_memstr(haystack, 7, "cad"),OP_EQ, haystack + 4);
2326 1 : tt_ptr_op(tor_memstr(haystack, 6, "cad"), OP_EQ, NULL);
2327 1 : tt_ptr_op(tor_memstr(haystack, 7, "cadd"), OP_EQ, NULL);
2328 1 : tt_ptr_op(tor_memstr(haystack, 7, "fe"), OP_EQ, NULL);
2329 1 : tt_ptr_op(tor_memstr(haystack, 7, "ababcade"), OP_EQ, NULL);
2330 : }
2331 :
2332 : /* Test hex_str */
2333 : {
2334 : char binary_data[68];
2335 : size_t idx;
2336 69 : for (idx = 0; idx < sizeof(binary_data); ++idx)
2337 68 : binary_data[idx] = idx;
2338 1 : tt_str_op(hex_str(binary_data, 0),OP_EQ, "");
2339 1 : tt_str_op(hex_str(binary_data, 1),OP_EQ, "00");
2340 1 : tt_str_op(hex_str(binary_data, 17),OP_EQ,
2341 : "000102030405060708090A0B0C0D0E0F10");
2342 1 : tt_str_op(hex_str(binary_data, 32),OP_EQ,
2343 : "000102030405060708090A0B0C0D0E0F"
2344 : "101112131415161718191A1B1C1D1E1F");
2345 1 : tt_str_op(hex_str(binary_data, 34),OP_EQ,
2346 : "000102030405060708090A0B0C0D0E0F"
2347 : "101112131415161718191A1B1C1D1E1F");
2348 : /* Repeat these tests for shorter strings after longer strings
2349 : have been tried, to make sure we're correctly terminating strings */
2350 1 : tt_str_op(hex_str(binary_data, 1),OP_EQ, "00");
2351 1 : tt_str_op(hex_str(binary_data, 0),OP_EQ, "");
2352 : }
2353 :
2354 : /* Test strcmp_opt */
2355 1 : tt_int_op(strcmp_opt("", "foo"), OP_LT, 0);
2356 1 : tt_int_op(strcmp_opt("", ""), OP_EQ, 0);
2357 1 : tt_int_op(strcmp_opt("foo", ""), OP_GT, 0);
2358 :
2359 1 : tt_int_op(strcmp_opt(NULL, ""), OP_LT, 0);
2360 1 : tt_int_op(strcmp_opt(NULL, NULL), OP_EQ, 0);
2361 1 : tt_int_op(strcmp_opt("", NULL), OP_GT, 0);
2362 :
2363 1 : tt_int_op(strcmp_opt(NULL, "foo"), OP_LT, 0);
2364 1 : tt_int_op(strcmp_opt("foo", NULL), OP_GT, 0);
2365 :
2366 1 : done:
2367 1 : tor_free(cp_tmp);
2368 1 : }
2369 :
2370 : static void
2371 1 : test_util_parse_integer(void *arg)
2372 : {
2373 1 : (void)arg;
2374 1 : int i;
2375 1 : char *cp;
2376 :
2377 : /* Test parse_long */
2378 : /* Empty/zero input */
2379 1 : tt_int_op(0L,OP_EQ, tor_parse_long("",10,0,100,&i,NULL));
2380 1 : tt_int_op(0,OP_EQ, i);
2381 1 : tt_int_op(0L,OP_EQ, tor_parse_long("0",10,0,100,&i,NULL));
2382 1 : tt_int_op(1,OP_EQ, i);
2383 : /* Normal cases */
2384 1 : tt_int_op(10L,OP_EQ, tor_parse_long("10",10,0,100,&i,NULL));
2385 1 : tt_int_op(1,OP_EQ, i);
2386 1 : tt_int_op(10L,OP_EQ, tor_parse_long("10",10,0,10,&i,NULL));
2387 1 : tt_int_op(1,OP_EQ, i);
2388 1 : tt_int_op(10L,OP_EQ, tor_parse_long("10",10,10,100,&i,NULL));
2389 1 : tt_int_op(1,OP_EQ, i);
2390 1 : tt_int_op(-50L,OP_EQ, tor_parse_long("-50",10,-100,100,&i,NULL));
2391 1 : tt_int_op(1,OP_EQ, i);
2392 1 : tt_int_op(-50L,OP_EQ, tor_parse_long("-50",10,-100,0,&i,NULL));
2393 1 : tt_int_op(1,OP_EQ, i);
2394 1 : tt_int_op(-50L,OP_EQ, tor_parse_long("-50",10,-50,0,&i,NULL));
2395 1 : tt_int_op(1,OP_EQ, i);
2396 : /* Extra garbage */
2397 1 : tt_int_op(0L,OP_EQ, tor_parse_long("10m",10,0,100,&i,NULL));
2398 1 : tt_int_op(0,OP_EQ, i);
2399 1 : tt_int_op(0L,OP_EQ, tor_parse_long("-50 plus garbage",10,-100,100,&i,NULL));
2400 1 : tt_int_op(0,OP_EQ, i);
2401 1 : tt_int_op(10L,OP_EQ, tor_parse_long("10m",10,0,100,&i,&cp));
2402 1 : tt_int_op(1,OP_EQ, i);
2403 1 : tt_str_op(cp,OP_EQ, "m");
2404 1 : tt_int_op(-50L,OP_EQ, tor_parse_long("-50 plus garbage",10,-100,100,&i,&cp));
2405 1 : tt_int_op(1,OP_EQ, i);
2406 1 : tt_str_op(cp,OP_EQ, " plus garbage");
2407 : /* Illogical min max */
2408 1 : tt_int_op(0L,OP_EQ, tor_parse_long("10",10,50,4,&i,NULL));
2409 1 : tt_int_op(0,OP_EQ, i);
2410 1 : tt_int_op(0L,OP_EQ, tor_parse_long("-50",10,100,-100,&i,NULL));
2411 1 : tt_int_op(0,OP_EQ, i);
2412 : /* Out of bounds */
2413 1 : tt_int_op(0L,OP_EQ, tor_parse_long("10",10,50,100,&i,NULL));
2414 1 : tt_int_op(0,OP_EQ, i);
2415 1 : tt_int_op(0L,OP_EQ, tor_parse_long("-50",10,0,100,&i,NULL));
2416 1 : tt_int_op(0,OP_EQ, i);
2417 : /* Base different than 10 */
2418 1 : tt_int_op(2L,OP_EQ, tor_parse_long("10",2,0,100,NULL,NULL));
2419 1 : tt_int_op(0L,OP_EQ, tor_parse_long("2",2,0,100,NULL,NULL));
2420 1 : tt_int_op(68284L,OP_EQ, tor_parse_long("10abc",16,0,70000,NULL,NULL));
2421 1 : tt_int_op(68284L,OP_EQ, tor_parse_long("10ABC",16,0,70000,NULL,NULL));
2422 1 : tt_int_op(0L,OP_EQ, tor_parse_long("10",-2,0,100,NULL,NULL));
2423 1 : tt_int_op(0,OP_EQ, tor_parse_long("10ABC",-1,0,70000,&i,NULL));
2424 1 : tt_int_op(i,OP_EQ, 0);
2425 :
2426 : /* Test parse_ulong */
2427 1 : tt_int_op(0UL,OP_EQ, tor_parse_ulong("",10,0,100,NULL,NULL));
2428 1 : tt_int_op(0UL,OP_EQ, tor_parse_ulong("0",10,0,100,NULL,NULL));
2429 1 : tt_int_op(10UL,OP_EQ, tor_parse_ulong("10",10,0,100,NULL,NULL));
2430 1 : tt_int_op(0UL,OP_EQ, tor_parse_ulong("10",10,50,100,NULL,NULL));
2431 1 : tt_int_op(10UL,OP_EQ, tor_parse_ulong("10",10,0,10,NULL,NULL));
2432 1 : tt_int_op(10UL,OP_EQ, tor_parse_ulong("10",10,10,100,NULL,NULL));
2433 1 : tt_int_op(0UL,OP_EQ, tor_parse_ulong("8",8,0,100,NULL,NULL));
2434 1 : tt_int_op(50UL,OP_EQ, tor_parse_ulong("50",10,50,100,NULL,NULL));
2435 1 : tt_int_op(0UL,OP_EQ, tor_parse_ulong("-50",10,0,100,NULL,NULL));
2436 1 : tt_int_op(0UL,OP_EQ, tor_parse_ulong("50",-1,50,100,&i,NULL));
2437 1 : tt_int_op(0,OP_EQ, i);
2438 1 : tt_int_op(0UL,OP_EQ, tor_parse_ulong("-50",10,0,100,&i,NULL));
2439 1 : tt_int_op(0,OP_EQ, i);
2440 :
2441 : /* Test parse_uint64 */
2442 1 : tt_assert(UINT64_C(10) == tor_parse_uint64("10 x",10,0,100, &i, &cp));
2443 1 : tt_int_op(1,OP_EQ, i);
2444 1 : tt_str_op(cp,OP_EQ, " x");
2445 1 : tt_assert(UINT64_C(12345678901) ==
2446 : tor_parse_uint64("12345678901",10,0,UINT64_MAX, &i, &cp));
2447 1 : tt_int_op(1,OP_EQ, i);
2448 1 : tt_str_op(cp,OP_EQ, "");
2449 1 : tt_assert(UINT64_C(0) ==
2450 : tor_parse_uint64("12345678901",10,500,INT32_MAX, &i, &cp));
2451 1 : tt_int_op(0,OP_EQ, i);
2452 1 : tt_assert(UINT64_C(0) ==
2453 : tor_parse_uint64("123",-1,0,INT32_MAX, &i, &cp));
2454 1 : tt_int_op(0,OP_EQ, i);
2455 :
2456 : {
2457 : /* Test parse_double */
2458 1 : double d = tor_parse_double("10", 0, (double)UINT64_MAX,&i,NULL);
2459 1 : tt_int_op(1,OP_EQ, i);
2460 1 : tt_assert(((uint64_t)d) == 10);
2461 1 : d = tor_parse_double("0", 0, (double)UINT64_MAX,&i,NULL);
2462 1 : tt_int_op(1,OP_EQ, i);
2463 1 : tt_assert(((uint64_t)d) == 0);
2464 1 : d = tor_parse_double(" ", 0, (double)UINT64_MAX,&i,NULL);
2465 1 : tt_double_op(fabs(d), OP_LT, 1e-10);
2466 1 : tt_int_op(0,OP_EQ, i);
2467 1 : d = tor_parse_double(".0a", 0, (double)UINT64_MAX,&i,NULL);
2468 1 : tt_double_op(fabs(d), OP_LT, 1e-10);
2469 1 : tt_int_op(0,OP_EQ, i);
2470 1 : d = tor_parse_double(".0a", 0, (double)UINT64_MAX,&i,&cp);
2471 1 : tt_double_op(fabs(d), OP_LT, 1e-10);
2472 1 : tt_int_op(1,OP_EQ, i);
2473 1 : d = tor_parse_double("-.0", 0, (double)UINT64_MAX,&i,NULL);
2474 1 : tt_int_op(1,OP_EQ, i);
2475 1 : tt_assert(((uint64_t)d) == 0);
2476 1 : d = tor_parse_double("-10", -100.0, 100.0,&i,NULL);
2477 1 : tt_int_op(1,OP_EQ, i);
2478 1 : tt_double_op(fabs(d - -10.0),OP_LT, 1E-12);
2479 : }
2480 :
2481 : {
2482 : /* Test tor_parse_* where we overflow/underflow the underlying type. */
2483 : /* This string should overflow 64-bit ints. */
2484 : #define TOOBIG "100000000000000000000000000"
2485 1 : tt_int_op(0L, OP_EQ,
2486 : tor_parse_long(TOOBIG, 10, LONG_MIN, LONG_MAX, &i, NULL));
2487 1 : tt_int_op(i,OP_EQ, 0);
2488 1 : tt_int_op(0L,OP_EQ,
2489 : tor_parse_long("-"TOOBIG, 10, LONG_MIN, LONG_MAX, &i, NULL));
2490 1 : tt_int_op(i,OP_EQ, 0);
2491 1 : tt_int_op(0UL,OP_EQ, tor_parse_ulong(TOOBIG, 10, 0, ULONG_MAX, &i, NULL));
2492 1 : tt_int_op(i,OP_EQ, 0);
2493 1 : tt_u64_op(UINT64_C(0), OP_EQ, tor_parse_uint64(TOOBIG, 10,
2494 : 0, UINT64_MAX, &i, NULL));
2495 1 : tt_int_op(i,OP_EQ, 0);
2496 : }
2497 1 : done:
2498 1 : ;
2499 1 : }
2500 :
2501 : static void
2502 1 : test_util_pow2(void *arg)
2503 : {
2504 : /* Test tor_log2(). */
2505 1 : (void)arg;
2506 1 : tt_int_op(tor_log2(64),OP_EQ, 6);
2507 1 : tt_int_op(tor_log2(65),OP_EQ, 6);
2508 1 : tt_int_op(tor_log2(63),OP_EQ, 5);
2509 : /* incorrect mathematically, but as specified: */
2510 1 : tt_int_op(tor_log2(0),OP_EQ, 0);
2511 1 : tt_int_op(tor_log2(1),OP_EQ, 0);
2512 1 : tt_int_op(tor_log2(2),OP_EQ, 1);
2513 1 : tt_int_op(tor_log2(3),OP_EQ, 1);
2514 1 : tt_int_op(tor_log2(4),OP_EQ, 2);
2515 1 : tt_int_op(tor_log2(5),OP_EQ, 2);
2516 1 : tt_int_op(tor_log2(UINT64_C(40000000000000000)),OP_EQ, 55);
2517 1 : tt_int_op(tor_log2(UINT64_MAX),OP_EQ, 63);
2518 :
2519 : /* Test round_to_power_of_2 */
2520 1 : tt_u64_op(round_to_power_of_2(120), OP_EQ, 128);
2521 1 : tt_u64_op(round_to_power_of_2(128), OP_EQ, 128);
2522 1 : tt_u64_op(round_to_power_of_2(130), OP_EQ, 128);
2523 1 : tt_u64_op(round_to_power_of_2(UINT64_C(40000000000000000)), OP_EQ,
2524 : UINT64_C(1)<<55);
2525 1 : tt_u64_op(round_to_power_of_2(UINT64_C(0xffffffffffffffff)), OP_EQ,
2526 : UINT64_C(1)<<63);
2527 1 : tt_u64_op(round_to_power_of_2(0), OP_EQ, 1);
2528 1 : tt_u64_op(round_to_power_of_2(1), OP_EQ, 1);
2529 1 : tt_u64_op(round_to_power_of_2(2), OP_EQ, 2);
2530 1 : tt_u64_op(round_to_power_of_2(3), OP_EQ, 2);
2531 1 : tt_u64_op(round_to_power_of_2(4), OP_EQ, 4);
2532 1 : tt_u64_op(round_to_power_of_2(5), OP_EQ, 4);
2533 1 : tt_u64_op(round_to_power_of_2(6), OP_EQ, 4);
2534 1 : tt_u64_op(round_to_power_of_2(7), OP_EQ, 8);
2535 :
2536 1 : done:
2537 1 : ;
2538 1 : }
2539 :
2540 : static void
2541 6 : test_util_compress_impl(compress_method_t method)
2542 : {
2543 6 : char *buf1=NULL, *buf2=NULL, *buf3=NULL;
2544 6 : size_t len1, len2;
2545 :
2546 6 : tt_assert(tor_compress_supports_method(method));
2547 :
2548 6 : if (method != NO_METHOD) {
2549 5 : tt_ptr_op(tor_compress_version_str(method), OP_NE, NULL);
2550 5 : tt_ptr_op(tor_compress_header_version_str(method), OP_NE, NULL);
2551 : }
2552 :
2553 6 : buf1 = tor_strdup("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAZAAAAAAAAAAAAAAAAAAAZ");
2554 6 : tt_assert(detect_compression_method(buf1, strlen(buf1)) == UNKNOWN_METHOD);
2555 :
2556 6 : tt_assert(!tor_compress(&buf2, &len1, buf1, strlen(buf1)+1, method));
2557 6 : tt_ptr_op(buf2, OP_NE, NULL);
2558 6 : if (method == NO_METHOD) {
2559 : // The identity transform doesn't actually compress, and it isn't
2560 : // detectable as "the identity transform."
2561 1 : tt_int_op(len1, OP_EQ, strlen(buf1)+1);
2562 1 : tt_int_op(detect_compression_method(buf2, len1), OP_EQ, UNKNOWN_METHOD);
2563 : } else {
2564 5 : tt_int_op(len1, OP_LT, strlen(buf1));
2565 5 : tt_int_op(detect_compression_method(buf2, len1), OP_EQ, method);
2566 : }
2567 :
2568 6 : tt_assert(!tor_uncompress(&buf3, &len2, buf2, len1, method, 1, LOG_INFO));
2569 6 : tt_ptr_op(buf3, OP_NE, NULL);
2570 6 : tt_int_op(strlen(buf1) + 1, OP_EQ, len2);
2571 6 : tt_str_op(buf1, OP_EQ, buf3);
2572 6 : tt_int_op(buf3[len2], OP_EQ, 0);
2573 :
2574 : /* Check whether we can uncompress concatenated, compressed strings. */
2575 6 : tor_free(buf3);
2576 6 : buf2 = tor_reallocarray(buf2, len1, 2);
2577 6 : memcpy(buf2+len1, buf2, len1);
2578 6 : tt_assert(!tor_uncompress(&buf3, &len2, buf2, len1*2, method, 1, LOG_INFO));
2579 6 : tt_int_op((strlen(buf1)+1)*2, OP_EQ, len2);
2580 6 : tt_mem_op(buf3, OP_EQ,
2581 : "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAZAAAAAAAAAAAAAAAAAAAZ\0"
2582 : "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAZAAAAAAAAAAAAAAAAAAAZ\0",
2583 6 : (strlen(buf1)+1)*2);
2584 6 : tt_int_op(buf3[len2], OP_EQ, 0);
2585 :
2586 : /* Check whether we can uncompress partial strings */
2587 :
2588 6 : tor_free(buf1);
2589 6 : tor_free(buf2);
2590 6 : tor_free(buf3);
2591 :
2592 6 : size_t b1len = 1<<10;
2593 6 : if (method == ZSTD_METHOD) {
2594 : // zstd needs a big input before it starts generating output that it
2595 : // can partially decompress.
2596 2 : b1len = 1<<18;
2597 : }
2598 6 : buf1 = tor_malloc(b1len);
2599 6 : crypto_rand(buf1, b1len);
2600 6 : tt_assert(!tor_compress(&buf2, &len1, buf1, b1len, method));
2601 6 : tt_int_op(len1, OP_GT, 16);
2602 : /* when we allow an incomplete output we should succeed.*/
2603 6 : tt_assert(!tor_uncompress(&buf3, &len2, buf2, len1-16,
2604 : method, 0, LOG_INFO));
2605 6 : tt_int_op(len2, OP_GT, 5);
2606 6 : tt_int_op(len2, OP_LE, len1);
2607 6 : tt_assert(fast_memeq(buf1, buf3, len2));
2608 6 : tt_int_op(buf3[len2], OP_EQ, 0);
2609 :
2610 : /* when we demand a complete output from a real compression method, this
2611 : * must fail. */
2612 6 : tor_free(buf3);
2613 6 : if (method != NO_METHOD) {
2614 5 : tt_assert(tor_uncompress(&buf3, &len2, buf2, len1-16,
2615 : method, 1, LOG_INFO));
2616 5 : tt_ptr_op(buf3, OP_EQ, NULL);
2617 : }
2618 :
2619 6 : done:
2620 6 : tor_free(buf1);
2621 6 : tor_free(buf2);
2622 6 : tor_free(buf3);
2623 6 : }
2624 :
2625 : static void
2626 24 : test_util_compress_stream_impl(compress_method_t method,
2627 : compression_level_t level)
2628 : {
2629 24 : char *buf1=NULL, *buf2=NULL, *buf3=NULL, *cp1, *cp2;
2630 24 : const char *ccp2;
2631 24 : size_t len1, len2;
2632 :
2633 24 : tor_compress_state_t *state = NULL;
2634 24 : state = tor_compress_new(1, method, level);
2635 24 : tt_assert(state);
2636 24 : cp1 = buf1 = tor_malloc(1024);
2637 24 : len1 = 1024;
2638 24 : ccp2 = "ABCDEFGHIJABCDEFGHIJ";
2639 24 : len2 = 21;
2640 24 : tt_int_op(tor_compress_process(state, &cp1, &len1, &ccp2, &len2, 0),
2641 : OP_EQ, TOR_COMPRESS_OK);
2642 24 : tt_int_op(0, OP_EQ, len2); /* Make sure we compressed it all. */
2643 24 : tt_assert(cp1 > buf1);
2644 :
2645 24 : len2 = 0;
2646 24 : cp2 = cp1;
2647 24 : tt_int_op(tor_compress_process(state, &cp1, &len1, &ccp2, &len2, 1),
2648 : OP_EQ, TOR_COMPRESS_DONE);
2649 24 : tt_int_op(0, OP_EQ, len2);
2650 24 : if (method == NO_METHOD) {
2651 4 : tt_ptr_op(cp1, OP_EQ, cp2);
2652 : } else {
2653 20 : tt_assert(cp1 > cp2); /* Make sure we really added something. */
2654 : }
2655 :
2656 24 : tt_int_op(tor_compress_state_size(state), OP_GT, 0);
2657 :
2658 24 : tt_assert(!tor_uncompress(&buf3, &len2, buf1, 1024-len1,
2659 : method, 1, LOG_WARN));
2660 : /* Make sure it compressed right. */
2661 24 : tt_str_op(buf3, OP_EQ, "ABCDEFGHIJABCDEFGHIJ");
2662 24 : tt_int_op(21, OP_EQ, len2);
2663 :
2664 24 : done:
2665 24 : if (state)
2666 24 : tor_compress_free(state);
2667 24 : tor_free(buf1);
2668 24 : tor_free(buf2);
2669 24 : tor_free(buf3);
2670 24 : }
2671 :
2672 : /** Setup function for compression tests: handles x-zstd:nostatic
2673 : */
2674 : static void *
2675 20 : compression_test_setup(const struct testcase_t *testcase)
2676 : {
2677 20 : tor_assert(testcase->setup_data);
2678 20 : tor_assert(testcase->setup_data != (void*)TT_SKIP);
2679 20 : const char *methodname = testcase->setup_data;
2680 :
2681 20 : if (!strcmp(methodname, "x-zstd:nostatic")) {
2682 3 : methodname = "x-zstd";
2683 3 : tor_zstd_set_static_apis_disabled_for_testing(1);
2684 : }
2685 :
2686 20 : return (void *)methodname;
2687 : }
2688 :
2689 : /** Cleanup for compression tests: disables nostatic */
2690 : static int
2691 20 : compression_test_cleanup(const struct testcase_t *testcase, void *ptr)
2692 : {
2693 20 : (void)testcase;
2694 20 : (void)ptr;
2695 20 : tor_zstd_set_static_apis_disabled_for_testing(0);
2696 20 : return 1;
2697 : }
2698 :
2699 : static const struct testcase_setup_t compress_setup = {
2700 : compression_test_setup, compression_test_cleanup
2701 : };
2702 :
2703 : /** Run unit tests for compression functions */
2704 : static void
2705 6 : test_util_compress(void *arg)
2706 : {
2707 6 : const char *methodname = arg;
2708 6 : tt_assert(methodname);
2709 :
2710 6 : compress_method_t method = compression_method_get_by_name(methodname);
2711 6 : tt_int_op(method, OP_NE, UNKNOWN_METHOD);
2712 :
2713 6 : if (! tor_compress_supports_method(method)) {
2714 0 : tt_skip();
2715 : }
2716 :
2717 6 : compression_level_t levels[] = {
2718 : BEST_COMPRESSION,
2719 : HIGH_COMPRESSION,
2720 : MEDIUM_COMPRESSION,
2721 : LOW_COMPRESSION
2722 : };
2723 :
2724 6 : test_util_compress_impl(method);
2725 :
2726 30 : for (unsigned l = 0; l < ARRAY_LENGTH(levels); ++l) {
2727 24 : compression_level_t level = levels[l];
2728 24 : test_util_compress_stream_impl(method, level);
2729 : }
2730 6 : done:
2731 6 : ;
2732 6 : }
2733 :
2734 : static void
2735 6 : test_util_decompress_concatenated_impl(compress_method_t method)
2736 : {
2737 6 : char input[4096];
2738 6 : char *c1 = NULL, *c2 = NULL, *c3 = NULL;
2739 6 : char *result = NULL;
2740 6 : size_t sz1, sz2, sz3, szr;
2741 6 : int r;
2742 :
2743 6 : crypto_rand(input, sizeof(input));
2744 :
2745 : /* Compress the input in two chunks. */
2746 6 : r = tor_compress(&c1, &sz1, input, 2048, method);
2747 6 : tt_int_op(r, OP_EQ, 0);
2748 6 : r = tor_compress(&c2, &sz2, input+2048, 2048, method);
2749 6 : tt_int_op(r, OP_EQ, 0);
2750 :
2751 : /* concatenate the chunks. */
2752 6 : sz3 = sz1 + sz2;
2753 6 : c3 = tor_malloc(sz3);
2754 6 : memcpy(c3, c1, sz1);
2755 6 : memcpy(c3+sz1, c2, sz2);
2756 :
2757 : /* decompress the concatenated result */
2758 6 : r = tor_uncompress(&result, &szr, c3, sz3, method, 0, LOG_WARN);
2759 6 : tt_int_op(r, OP_EQ, 0);
2760 6 : tt_int_op(szr, OP_EQ, sizeof(input));
2761 6 : tt_mem_op(result, OP_EQ, input, sizeof(input));
2762 :
2763 6 : done:
2764 6 : tor_free(c1);
2765 6 : tor_free(c2);
2766 6 : tor_free(c3);
2767 6 : tor_free(result);
2768 6 : }
2769 :
2770 : static void
2771 6 : test_util_decompress_concatenated(void *arg)
2772 : {
2773 6 : const char *methodname = arg;
2774 6 : tt_assert(methodname);
2775 :
2776 6 : compress_method_t method = compression_method_get_by_name(methodname);
2777 6 : tt_int_op(method, OP_NE, UNKNOWN_METHOD);
2778 6 : if (! tor_compress_supports_method(method)) {
2779 0 : tt_skip();
2780 : }
2781 :
2782 6 : test_util_decompress_concatenated_impl(method);
2783 6 : done:
2784 6 : ;
2785 6 : }
2786 :
2787 : static void
2788 3 : test_util_decompress_junk_impl(compress_method_t method)
2789 : {
2790 3 : char input[4096];
2791 3 : char *result = NULL, *result2 = NULL;
2792 3 : size_t szr, szr2, sz;
2793 3 : int r;
2794 :
2795 : /* This shouldn't be a compressed string according to any method. */
2796 3 : strlcpy(input, "This shouldn't be a compressed string by any means.",
2797 : sizeof(input));
2798 3 : sz = strlen(input);
2799 3 : setup_capture_of_logs(LOG_WARN);
2800 3 : r = tor_uncompress(&result, &szr, input, sz, method, 0, LOG_WARN);
2801 3 : tt_int_op(r, OP_EQ, -1);
2802 3 : tt_ptr_op(result, OP_EQ, NULL);
2803 3 : expect_log_msg_containing("Error while uncompressing data: bad input?");
2804 3 : mock_clean_saved_logs();
2805 :
2806 : /* Now try again, with a compressed object that starts out good and turns to
2807 : junk. */
2808 3 : crypto_rand(input, sizeof(input));
2809 3 : r = tor_compress(&result, &szr, input, sizeof(input), method);
2810 3 : tt_int_op(r, OP_EQ, 0);
2811 3 : crypto_rand(result+szr/2, szr-(szr/2)); // trash the 2nd half of the result
2812 3 : r = tor_uncompress(&result2, &szr2, result, szr, method, 0, LOG_WARN);
2813 3 : tt_int_op(r, OP_EQ, -1);
2814 3 : expect_log_msg_containing("Error while uncompressing data: bad input?");
2815 :
2816 3 : done:
2817 3 : teardown_capture_of_logs();
2818 3 : tor_free(result);
2819 3 : tor_free(result2);
2820 3 : }
2821 :
2822 : static void
2823 3 : test_util_decompress_junk(void *arg)
2824 : {
2825 3 : const char *methodname = arg;
2826 3 : tt_assert(methodname);
2827 :
2828 3 : compress_method_t method = compression_method_get_by_name(methodname);
2829 3 : tt_int_op(method, OP_NE, UNKNOWN_METHOD);
2830 3 : if (! tor_compress_supports_method(method)) {
2831 0 : tt_skip();
2832 : }
2833 :
2834 3 : test_util_decompress_junk_impl(method);
2835 3 : done:
2836 3 : ;
2837 3 : }
2838 :
2839 : /* mock replacement for tor_compress_is_compression_bomb that doesn't
2840 : * believe in compression bombs. */
2841 : static int
2842 5 : mock_is_never_compression_bomb(size_t in, size_t out)
2843 : {
2844 5 : (void)in;
2845 5 : (void) out;
2846 5 : return 0;
2847 : }
2848 :
2849 : static void
2850 5 : test_util_decompress_dos_impl(compress_method_t method)
2851 : {
2852 5 : char *input;
2853 5 : char *result = NULL, *result2 = NULL;
2854 5 : size_t szr, szr2;
2855 5 : int r;
2856 :
2857 5 : const size_t big = 1024*1024;
2858 : /* one megabyte of 0s. */
2859 5 : input = tor_malloc_zero(big);
2860 :
2861 : /* Compress it into "result": it should fail. */
2862 5 : setup_full_capture_of_logs(LOG_WARN);
2863 5 : r = tor_compress(&result, &szr, input, big, method);
2864 5 : tt_int_op(r, OP_EQ, -1);
2865 5 : expect_log_msg_containing(
2866 5 : "other Tors would think this was a compression bomb");
2867 5 : teardown_capture_of_logs();
2868 :
2869 : /* Try again, but this time suppress compression-bomb detection */
2870 5 : MOCK(tor_compress_is_compression_bomb, mock_is_never_compression_bomb);
2871 5 : r = tor_compress(&result, &szr, input, big, method);
2872 5 : UNMOCK(tor_compress_is_compression_bomb);
2873 5 : tt_int_op(r, OP_EQ, 0);
2874 5 : tt_ptr_op(result, OP_NE, NULL);
2875 :
2876 : /* We should refuse to uncomrpess it again, since it looks like a
2877 : * compression bomb. */
2878 5 : setup_capture_of_logs(LOG_WARN);
2879 5 : r = tor_uncompress(&result2, &szr2, result, szr, method, 0, LOG_WARN);
2880 5 : tt_int_op(r, OP_EQ, -1);
2881 5 : expect_log_msg_containing("bomb; abandoning stream");
2882 :
2883 5 : done:
2884 5 : teardown_capture_of_logs();
2885 5 : tor_free(input);
2886 5 : tor_free(result);
2887 5 : tor_free(result2);
2888 5 : }
2889 :
2890 : static void
2891 5 : test_util_decompress_dos(void *arg)
2892 : {
2893 5 : const char *methodname = arg;
2894 5 : tt_assert(methodname);
2895 :
2896 5 : compress_method_t method = compression_method_get_by_name(methodname);
2897 5 : tt_int_op(method, OP_NE, UNKNOWN_METHOD);
2898 5 : if (! tor_compress_supports_method(method)) {
2899 0 : tt_skip();
2900 : }
2901 :
2902 5 : test_util_decompress_dos_impl(method);
2903 5 : done:
2904 5 : ;
2905 5 : }
2906 :
2907 : static void
2908 1 : test_util_gzip_compression_bomb(void *arg)
2909 : {
2910 : /* A 'compression bomb' is a very small object that uncompresses to a huge
2911 : * one. Most compression formats support them, but they can be a DOS vector.
2912 : * In Tor we try not to generate them, and we don't accept them.
2913 : */
2914 1 : (void) arg;
2915 1 : size_t one_million = 1<<20;
2916 1 : char *one_mb = tor_malloc_zero(one_million);
2917 1 : char *result = NULL;
2918 1 : size_t result_len = 0;
2919 1 : tor_compress_state_t *state = NULL;
2920 :
2921 : /* Make sure we can't produce a compression bomb */
2922 1 : setup_full_capture_of_logs(LOG_WARN);
2923 1 : tt_int_op(-1, OP_EQ, tor_compress(&result, &result_len,
2924 : one_mb, one_million,
2925 : ZLIB_METHOD));
2926 1 : expect_single_log_msg_containing(
2927 : "We compressed something and got an insanely high "
2928 : "compression factor; other Tors would think this "
2929 : "was a compression bomb.");
2930 1 : teardown_capture_of_logs();
2931 :
2932 : /* Here's a compression bomb that we made manually. */
2933 1 : const char compression_bomb[1039] =
2934 : { 0x78, 0xDA, 0xED, 0xC1, 0x31, 0x01, 0x00, 0x00, 0x00, 0xC2,
2935 : 0xA0, 0xF5, 0x4F, 0x6D, 0x08, 0x5F, 0xA0 /* .... */ };
2936 1 : tt_int_op(-1, OP_EQ, tor_uncompress(&result, &result_len,
2937 : compression_bomb, 1039,
2938 : ZLIB_METHOD, 0, LOG_WARN));
2939 :
2940 : /* Now try streaming that. */
2941 1 : state = tor_compress_new(0, ZLIB_METHOD, HIGH_COMPRESSION);
2942 1 : tor_compress_output_t r;
2943 1 : const char *inp = compression_bomb;
2944 1 : size_t inlen = 1039;
2945 16 : do {
2946 16 : char *outp = one_mb;
2947 16 : size_t outleft = 4096; /* small on purpose */
2948 16 : r = tor_compress_process(state, &outp, &outleft, &inp, &inlen, 0);
2949 16 : tt_int_op(inlen, OP_NE, 0);
2950 16 : } while (r == TOR_COMPRESS_BUFFER_FULL);
2951 :
2952 1 : tt_int_op(r, OP_EQ, TOR_COMPRESS_ERROR);
2953 :
2954 1 : done:
2955 1 : tor_free(one_mb);
2956 1 : tor_compress_free(state);
2957 1 : }
2958 :
2959 : /** Run unit tests for mmap() wrapper functionality. */
2960 : static void
2961 1 : test_util_mmap(void *arg)
2962 : {
2963 1 : char *fname1 = tor_strdup(get_fname("mapped_1"));
2964 1 : char *fname2 = tor_strdup(get_fname("mapped_2"));
2965 1 : char *fname3 = tor_strdup(get_fname("mapped_3"));
2966 1 : const size_t buflen = 17000;
2967 1 : char *buf = tor_malloc(17000);
2968 1 : tor_mmap_t *mapping = NULL;
2969 :
2970 1 : (void)arg;
2971 1 : crypto_rand(buf, buflen);
2972 :
2973 1 : mapping = tor_mmap_file(fname1);
2974 1 : tt_ptr_op(mapping, OP_EQ, NULL);
2975 :
2976 1 : write_str_to_file(fname1, "Short file.", 1);
2977 :
2978 1 : mapping = tor_mmap_file(fname1);
2979 1 : tt_assert(mapping);
2980 1 : tt_int_op(mapping->size,OP_EQ, strlen("Short file."));
2981 1 : tt_str_op(mapping->data,OP_EQ, "Short file.");
2982 : #ifdef _WIN32
2983 : tt_int_op(0, OP_EQ, tor_munmap_file(mapping));
2984 : mapping = NULL;
2985 : tt_assert(unlink(fname1) == 0);
2986 : #else
2987 : /* make sure we can unlink. */
2988 1 : tt_assert(unlink(fname1) == 0);
2989 1 : tt_str_op(mapping->data,OP_EQ, "Short file.");
2990 1 : tt_int_op(0, OP_EQ, tor_munmap_file(mapping));
2991 1 : mapping = NULL;
2992 : #endif /* defined(_WIN32) */
2993 :
2994 : /* Now a zero-length file. */
2995 1 : write_str_to_file(fname1, "", 1);
2996 1 : mapping = tor_mmap_file(fname1);
2997 1 : tt_ptr_op(mapping,OP_EQ, NULL);
2998 1 : tt_int_op(ERANGE,OP_EQ, errno);
2999 1 : unlink(fname1);
3000 :
3001 : /* Make sure that we fail to map a no-longer-existent file. */
3002 1 : mapping = tor_mmap_file(fname1);
3003 1 : tt_ptr_op(mapping, OP_EQ, NULL);
3004 :
3005 : /* Now try a big file that stretches across a few pages and isn't aligned */
3006 1 : write_bytes_to_file(fname2, buf, buflen, 1);
3007 1 : mapping = tor_mmap_file(fname2);
3008 1 : tt_assert(mapping);
3009 1 : tt_int_op(mapping->size,OP_EQ, buflen);
3010 1 : tt_mem_op(mapping->data,OP_EQ, buf, buflen);
3011 1 : tt_int_op(0, OP_EQ, tor_munmap_file(mapping));
3012 1 : mapping = NULL;
3013 :
3014 : /* Now try a big aligned file. */
3015 1 : write_bytes_to_file(fname3, buf, 16384, 1);
3016 1 : mapping = tor_mmap_file(fname3);
3017 1 : tt_assert(mapping);
3018 1 : tt_int_op(mapping->size,OP_EQ, 16384);
3019 1 : tt_mem_op(mapping->data,OP_EQ, buf, 16384);
3020 1 : tt_int_op(0, OP_EQ, tor_munmap_file(mapping));
3021 : mapping = NULL;
3022 :
3023 1 : done:
3024 1 : unlink(fname1);
3025 1 : unlink(fname2);
3026 1 : unlink(fname3);
3027 :
3028 1 : tor_free(fname1);
3029 1 : tor_free(fname2);
3030 1 : tor_free(fname3);
3031 1 : tor_free(buf);
3032 :
3033 1 : tor_munmap_file(mapping);
3034 1 : }
3035 :
3036 : /** Run unit tests for escaping/unescaping data for use by controllers. */
3037 : static void
3038 1 : test_util_control_formats(void *arg)
3039 : {
3040 1 : char *out = NULL;
3041 1 : const char *inp =
3042 : "..This is a test\r\n.of the emergency \n..system.\r\n\rZ.\r\n";
3043 1 : size_t sz;
3044 :
3045 1 : (void)arg;
3046 1 : sz = read_escaped_data(inp, strlen(inp), &out);
3047 1 : tt_str_op(out,OP_EQ,
3048 : ".This is a test\nof the emergency \n.system.\n\rZ.\n");
3049 1 : tt_int_op(sz,OP_EQ, strlen(out));
3050 :
3051 1 : done:
3052 1 : tor_free(out);
3053 1 : }
3054 :
3055 : #define test_feq(value1,value2) do { \
3056 : double v1 = (value1), v2=(value2); \
3057 : double tf_diff = v1-v2; \
3058 : double tf_tolerance = ((v1+v2)/2.0)/1e8; \
3059 : if (tf_diff<0) tf_diff=-tf_diff; \
3060 : if (tf_tolerance<0) tf_tolerance=-tf_tolerance; \
3061 : if (tf_diff<tf_tolerance) { \
3062 : TT_BLATHER(("%s ~~ %s: %f ~~ %f",#value1,#value2,v1,v2)); \
3063 : } else { \
3064 : TT_FAIL(("%s ~~ %s: %f != %f",#value1,#value2,v1,v2)); \
3065 : } \
3066 : } while (0)
3067 :
3068 : static void
3069 1 : test_util_sscanf(void *arg)
3070 : {
3071 1 : unsigned u1, u2, u3;
3072 1 : unsigned long ulng;
3073 1 : char s1[20], s2[10], s3[10], ch, *huge = NULL;
3074 1 : int r;
3075 1 : long lng1,lng2;
3076 1 : int int1, int2;
3077 1 : double d1,d2,d3,d4;
3078 :
3079 : /* Simple tests (malformed patterns, literal matching, ...) */
3080 1 : (void)arg;
3081 1 : tt_int_op(-1,OP_EQ, tor_sscanf("123", "%i", &r)); /* %i is not supported */
3082 1 : tt_int_op(-1,OP_EQ,
3083 : tor_sscanf("wrong", "%5c", s1)); /* %c cannot have a number. */
3084 1 : tt_int_op(-1,OP_EQ, tor_sscanf("hello", "%s", s1)); /* %s needs a number. */
3085 : /* this will fail because we don't allow widths longer than 9999 */
3086 : {
3087 1 : huge = tor_malloc(1000000);
3088 1 : r = tor_sscanf("prettylongstring", "%99999s", huge);
3089 1 : tor_free(huge);
3090 1 : tt_int_op(-1,OP_EQ, r);
3091 : }
3092 : #if 0
3093 : /* GCC thinks these two are illegal. */
3094 : test_eq(-1, tor_sscanf("prettylongstring", "%0s", s1));
3095 : test_eq(0, tor_sscanf("prettylongstring", "%10s", NULL));
3096 : #endif
3097 : /* No '%'-strings: always "success" */
3098 1 : tt_int_op(0,OP_EQ, tor_sscanf("hello world", "hello world"));
3099 1 : tt_int_op(0,OP_EQ, tor_sscanf("hello world", "good bye"));
3100 : /* Excess data */
3101 1 : tt_int_op(0,OP_EQ,
3102 : tor_sscanf("hello 3", "%u", &u1)); /* have to match the start */
3103 1 : tt_int_op(0,OP_EQ, tor_sscanf(" 3 hello", "%u", &u1));
3104 1 : tt_int_op(0,OP_EQ,
3105 : tor_sscanf(" 3 hello", "%2u", &u1)); /* not even in this case */
3106 1 : tt_int_op(1,OP_EQ,
3107 : tor_sscanf("3 hello", "%u", &u1)); /* but trailing is alright */
3108 :
3109 : /* Numbers (ie. %u) */
3110 1 : tt_int_op(0,OP_EQ,
3111 : tor_sscanf("hello world 3", "hello worlb %u", &u1)); /* d vs b */
3112 1 : tt_int_op(1,OP_EQ, tor_sscanf("12345", "%u", &u1));
3113 1 : tt_int_op(12345u,OP_EQ, u1);
3114 1 : tt_int_op(1,OP_EQ, tor_sscanf("12346 ", "%u", &u1));
3115 1 : tt_int_op(12346u,OP_EQ, u1);
3116 1 : tt_int_op(0,OP_EQ, tor_sscanf(" 12347", "%u", &u1));
3117 1 : tt_int_op(1,OP_EQ, tor_sscanf(" 12348", " %u", &u1));
3118 1 : tt_int_op(12348u,OP_EQ, u1);
3119 1 : tt_int_op(1,OP_EQ, tor_sscanf("0", "%u", &u1));
3120 1 : tt_int_op(0u,OP_EQ, u1);
3121 1 : tt_int_op(1,OP_EQ, tor_sscanf("0000", "%u", &u2));
3122 1 : tt_int_op(0u,OP_EQ, u2);
3123 1 : tt_int_op(0,OP_EQ, tor_sscanf("", "%u", &u1)); /* absent number */
3124 1 : tt_int_op(0,OP_EQ, tor_sscanf("A", "%u", &u1)); /* bogus number */
3125 1 : tt_int_op(0,OP_EQ, tor_sscanf("-1", "%u", &u1)); /* negative number */
3126 :
3127 : /* Numbers with size (eg. %2u) */
3128 1 : tt_int_op(0,OP_EQ, tor_sscanf("-1", "%2u", &u1));
3129 1 : tt_int_op(2,OP_EQ, tor_sscanf("123456", "%2u%u", &u1, &u2));
3130 1 : tt_int_op(12u,OP_EQ, u1);
3131 1 : tt_int_op(3456u,OP_EQ, u2);
3132 1 : tt_int_op(1,OP_EQ, tor_sscanf("123456", "%8u", &u1));
3133 1 : tt_int_op(123456u,OP_EQ, u1);
3134 1 : tt_int_op(1,OP_EQ, tor_sscanf("123457 ", "%8u", &u1));
3135 1 : tt_int_op(123457u,OP_EQ, u1);
3136 1 : tt_int_op(0,OP_EQ, tor_sscanf(" 123456", "%8u", &u1));
3137 1 : tt_int_op(3,OP_EQ, tor_sscanf("!12:3:456", "!%2u:%2u:%3u", &u1, &u2, &u3));
3138 1 : tt_int_op(12u,OP_EQ, u1);
3139 1 : tt_int_op(3u,OP_EQ, u2);
3140 1 : tt_int_op(456u,OP_EQ, u3);
3141 1 : tt_int_op(3,OP_EQ,
3142 : tor_sscanf("67:8:099", "%2u:%2u:%3u", &u1, &u2, &u3)); /* 0s */
3143 1 : tt_int_op(67u,OP_EQ, u1);
3144 1 : tt_int_op(8u,OP_EQ, u2);
3145 1 : tt_int_op(99u,OP_EQ, u3);
3146 : /* %u does not match space.*/
3147 1 : tt_int_op(2,OP_EQ, tor_sscanf("12:3: 45", "%2u:%2u:%3u", &u1, &u2, &u3));
3148 1 : tt_int_op(12u,OP_EQ, u1);
3149 1 : tt_int_op(3u,OP_EQ, u2);
3150 : /* %u does not match negative numbers. */
3151 1 : tt_int_op(2,OP_EQ, tor_sscanf("67:8:-9", "%2u:%2u:%3u", &u1, &u2, &u3));
3152 1 : tt_int_op(67u,OP_EQ, u1);
3153 1 : tt_int_op(8u,OP_EQ, u2);
3154 : /* Arbitrary amounts of 0-padding are okay */
3155 1 : tt_int_op(3,OP_EQ, tor_sscanf("12:03:000000000000000099", "%2u:%2u:%u",
3156 : &u1, &u2, &u3));
3157 1 : tt_int_op(12u,OP_EQ, u1);
3158 1 : tt_int_op(3u,OP_EQ, u2);
3159 1 : tt_int_op(99u,OP_EQ, u3);
3160 :
3161 : /* Hex (ie. %x) */
3162 1 : tt_int_op(3,OP_EQ,
3163 : tor_sscanf("1234 02aBcdEf ff", "%x %x %x", &u1, &u2, &u3));
3164 1 : tt_int_op(0x1234,OP_EQ, u1);
3165 1 : tt_int_op(0x2ABCDEF,OP_EQ, u2);
3166 1 : tt_int_op(0xFF,OP_EQ, u3);
3167 : /* Width works on %x */
3168 1 : tt_int_op(3,OP_EQ, tor_sscanf("f00dcafe444", "%4x%4x%u", &u1, &u2, &u3));
3169 1 : tt_int_op(0xf00d,OP_EQ, u1);
3170 1 : tt_int_op(0xcafe,OP_EQ, u2);
3171 1 : tt_int_op(444,OP_EQ, u3);
3172 :
3173 : /* Literal '%' (ie. '%%') */
3174 1 : tt_int_op(1,OP_EQ, tor_sscanf("99% fresh", "%3u%% fresh", &u1));
3175 1 : tt_int_op(99,OP_EQ, u1);
3176 1 : tt_int_op(0,OP_EQ, tor_sscanf("99 fresh", "%% %3u %s", &u1, s1));
3177 1 : tt_int_op(1,OP_EQ, tor_sscanf("99 fresh", "%3u%% %s", &u1, s1));
3178 1 : tt_int_op(2,OP_EQ, tor_sscanf("99 fresh", "%3u %5s %%", &u1, s1));
3179 1 : tt_int_op(99,OP_EQ, u1);
3180 1 : tt_str_op(s1,OP_EQ, "fresh");
3181 1 : tt_int_op(1,OP_EQ, tor_sscanf("% boo", "%% %3s", s1));
3182 1 : tt_str_op("boo",OP_EQ, s1);
3183 :
3184 : /* Strings (ie. %s) */
3185 1 : tt_int_op(2,OP_EQ, tor_sscanf("hello", "%3s%7s", s1, s2));
3186 1 : tt_str_op(s1,OP_EQ, "hel");
3187 1 : tt_str_op(s2,OP_EQ, "lo");
3188 1 : tt_int_op(2,OP_EQ, tor_sscanf("WD40", "%2s%u", s3, &u1)); /* %s%u */
3189 1 : tt_str_op(s3,OP_EQ, "WD");
3190 1 : tt_int_op(40,OP_EQ, u1);
3191 1 : tt_int_op(2,OP_EQ, tor_sscanf("WD40", "%3s%u", s3, &u1)); /* %s%u */
3192 1 : tt_str_op(s3,OP_EQ, "WD4");
3193 1 : tt_int_op(0,OP_EQ, u1);
3194 1 : tt_int_op(2,OP_EQ, tor_sscanf("76trombones", "%6u%9s", &u1, s1)); /* %u%s */
3195 1 : tt_int_op(76,OP_EQ, u1);
3196 1 : tt_str_op(s1,OP_EQ, "trombones");
3197 : {
3198 1 : huge = tor_malloc(1000);
3199 1 : r = tor_sscanf("prettylongstring", "%999s", huge);
3200 1 : tt_int_op(1,OP_EQ, r);
3201 1 : tt_str_op(huge,OP_EQ, "prettylongstring");
3202 1 : tor_free(huge);
3203 : }
3204 : /* %s doesn't eat spaces */
3205 1 : tt_int_op(2,OP_EQ, tor_sscanf("hello world", "%9s %9s", s1, s2));
3206 1 : tt_str_op(s1,OP_EQ, "hello");
3207 1 : tt_str_op(s2,OP_EQ, "world");
3208 1 : tt_int_op(2,OP_EQ, tor_sscanf("bye world?", "%9s %9s", s1, s2));
3209 1 : tt_str_op(s1,OP_EQ, "bye");
3210 1 : tt_str_op(s2,OP_EQ, "");
3211 1 : tt_int_op(3,OP_EQ,
3212 : tor_sscanf("hi", "%9s%9s%3s", s1, s2, s3)); /* %s can be empty. */
3213 1 : tt_str_op(s1,OP_EQ, "hi");
3214 1 : tt_str_op(s2,OP_EQ, "");
3215 1 : tt_str_op(s3,OP_EQ, "");
3216 :
3217 1 : tt_int_op(3,OP_EQ, tor_sscanf("1.2.3", "%u.%u.%u%c", &u1, &u2, &u3, &ch));
3218 1 : tt_int_op(4,OP_EQ,
3219 : tor_sscanf("1.2.3 foobar", "%u.%u.%u%c", &u1, &u2, &u3, &ch));
3220 1 : tt_int_op(' ',OP_EQ, ch);
3221 :
3222 1 : r = tor_sscanf("12345 -67890 -1", "%d %ld %d", &int1, &lng1, &int2);
3223 1 : tt_int_op(r,OP_EQ, 3);
3224 1 : tt_int_op(int1,OP_EQ, 12345);
3225 1 : tt_int_op(lng1,OP_EQ, -67890);
3226 1 : tt_int_op(int2,OP_EQ, -1);
3227 :
3228 : #if SIZEOF_INT == 4
3229 : /* %u */
3230 : /* UINT32_MAX should work */
3231 1 : tt_int_op(1,OP_EQ, tor_sscanf("4294967295", "%u", &u1));
3232 1 : tt_int_op(4294967295U,OP_EQ, u1);
3233 :
3234 : /* But UINT32_MAX + 1 shouldn't work */
3235 1 : tt_int_op(0,OP_EQ, tor_sscanf("4294967296", "%u", &u1));
3236 : /* but parsing only 9... */
3237 1 : tt_int_op(1,OP_EQ, tor_sscanf("4294967296", "%9u", &u1));
3238 1 : tt_int_op(429496729U,OP_EQ, u1);
3239 :
3240 : /* %x */
3241 : /* UINT32_MAX should work */
3242 1 : tt_int_op(1,OP_EQ, tor_sscanf("FFFFFFFF", "%x", &u1));
3243 1 : tt_int_op(0xFFFFFFFF,OP_EQ, u1);
3244 :
3245 : /* But UINT32_MAX + 1 shouldn't work */
3246 1 : tt_int_op(0,OP_EQ, tor_sscanf("100000000", "%x", &u1));
3247 :
3248 : /* %d */
3249 : /* INT32_MIN and INT32_MAX should work */
3250 1 : r = tor_sscanf("-2147483648. 2147483647.", "%d. %d.", &int1, &int2);
3251 1 : tt_int_op(r,OP_EQ, 2);
3252 1 : tt_int_op(int1,OP_EQ, -2147483647 - 1);
3253 1 : tt_int_op(int2,OP_EQ, 2147483647);
3254 :
3255 : /* But INT32_MIN - 1 and INT32_MAX + 1 shouldn't work */
3256 1 : r = tor_sscanf("-2147483649.", "%d.", &int1);
3257 1 : tt_int_op(r,OP_EQ, 0);
3258 :
3259 1 : r = tor_sscanf("2147483648.", "%d.", &int1);
3260 1 : tt_int_op(r,OP_EQ, 0);
3261 :
3262 : /* and the first failure stops further processing */
3263 1 : r = tor_sscanf("-2147483648. 2147483648.",
3264 : "%d. %d.", &int1, &int2);
3265 1 : tt_int_op(r,OP_EQ, 1);
3266 :
3267 1 : r = tor_sscanf("-2147483649. 2147483647.",
3268 : "%d. %d.", &int1, &int2);
3269 1 : tt_int_op(r,OP_EQ, 0);
3270 :
3271 1 : r = tor_sscanf("2147483648. -2147483649.",
3272 : "%d. %d.", &int1, &int2);
3273 1 : tt_int_op(r,OP_EQ, 0);
3274 : #elif SIZEOF_INT == 8
3275 : /* %u */
3276 : /* UINT64_MAX should work */
3277 : tt_int_op(1,OP_EQ, tor_sscanf("18446744073709551615", "%u", &u1));
3278 : tt_int_op(18446744073709551615U,OP_EQ, u1);
3279 :
3280 : /* But UINT64_MAX + 1 shouldn't work */
3281 : tt_int_op(0,OP_EQ, tor_sscanf("18446744073709551616", "%u", &u1));
3282 : /* but parsing only 19... */
3283 : tt_int_op(1,OP_EQ, tor_sscanf("18446744073709551616", "%19u", &u1));
3284 : tt_int_op(1844674407370955161U,OP_EQ, u1);
3285 :
3286 : /* %x */
3287 : /* UINT64_MAX should work */
3288 : tt_int_op(1,OP_EQ, tor_sscanf("FFFFFFFFFFFFFFFF", "%x", &u1));
3289 : tt_int_op(0xFFFFFFFFFFFFFFFF,OP_EQ, u1);
3290 :
3291 : /* But UINT64_MAX + 1 shouldn't work */
3292 : tt_int_op(0,OP_EQ, tor_sscanf("10000000000000000", "%x", &u1));
3293 :
3294 : /* %d */
3295 : /* INT64_MIN and INT64_MAX should work */
3296 : r = tor_sscanf("-9223372036854775808. 9223372036854775807.",
3297 : "%d. %d.", &int1, &int2);
3298 : tt_int_op(r,OP_EQ, 2);
3299 : tt_int_op(int1,OP_EQ, -9223372036854775807 - 1);
3300 : tt_int_op(int2,OP_EQ, 9223372036854775807);
3301 :
3302 : /* But INT64_MIN - 1 and INT64_MAX + 1 shouldn't work */
3303 : r = tor_sscanf("-9223372036854775809.", "%d.", &int1);
3304 : tt_int_op(r,OP_EQ, 0);
3305 :
3306 : r = tor_sscanf("9223372036854775808.", "%d.", &int1);
3307 : tt_int_op(r,OP_EQ, 0);
3308 :
3309 : /* and the first failure stops further processing */
3310 : r = tor_sscanf("-9223372036854775808. 9223372036854775808.",
3311 : "%d. %d.", &int1, &int2);
3312 : tt_int_op(r,OP_EQ, 1);
3313 :
3314 : r = tor_sscanf("-9223372036854775809. 9223372036854775807.",
3315 : "%d. %d.", &int1, &int2);
3316 : tt_int_op(r,OP_EQ, 0);
3317 :
3318 : r = tor_sscanf("9223372036854775808. -9223372036854775809.",
3319 : "%d. %d.", &int1, &int2);
3320 : tt_int_op(r,OP_EQ, 0);
3321 : #endif /* SIZEOF_INT == 4 || ... */
3322 :
3323 : #if SIZEOF_LONG == 4
3324 : /* %lu */
3325 : /* UINT32_MAX should work */
3326 : tt_int_op(1,OP_EQ, tor_sscanf("4294967295", "%lu", &ulng));
3327 : tt_int_op(4294967295UL,OP_EQ, ulng);
3328 :
3329 : /* But UINT32_MAX + 1 shouldn't work */
3330 : tt_int_op(0,OP_EQ, tor_sscanf("4294967296", "%lu", &ulng));
3331 : /* but parsing only 9... */
3332 : tt_int_op(1,OP_EQ, tor_sscanf("4294967296", "%9lu", &ulng));
3333 : tt_int_op(429496729UL,OP_EQ, ulng);
3334 :
3335 : /* %lx */
3336 : /* UINT32_MAX should work */
3337 : tt_int_op(1,OP_EQ, tor_sscanf("FFFFFFFF", "%lx", &ulng));
3338 : tt_int_op(0xFFFFFFFFUL,OP_EQ, ulng);
3339 :
3340 : /* But UINT32_MAX + 1 shouldn't work */
3341 : tt_int_op(0,OP_EQ, tor_sscanf("100000000", "%lx", &ulng));
3342 :
3343 : /* %ld */
3344 : /* INT32_MIN and INT32_MAX should work */
3345 : r = tor_sscanf("-2147483648. 2147483647.", "%ld. %ld.", &lng1, &lng2);
3346 : tt_int_op(r,OP_EQ, 2);
3347 : tt_int_op(lng1,OP_EQ, -2147483647L - 1L);
3348 : tt_int_op(lng2,OP_EQ, 2147483647L);
3349 :
3350 : /* But INT32_MIN - 1 and INT32_MAX + 1 shouldn't work */
3351 : r = tor_sscanf("-2147483649.", "%ld.", &lng1);
3352 : tt_int_op(r,OP_EQ, 0);
3353 :
3354 : r = tor_sscanf("2147483648.", "%ld.", &lng1);
3355 : tt_int_op(r,OP_EQ, 0);
3356 :
3357 : /* and the first failure stops further processing */
3358 : r = tor_sscanf("-2147483648. 2147483648.",
3359 : "%ld. %ld.", &lng1, &lng2);
3360 : tt_int_op(r,OP_EQ, 1);
3361 :
3362 : r = tor_sscanf("-2147483649. 2147483647.",
3363 : "%ld. %ld.", &lng1, &lng2);
3364 : tt_int_op(r,OP_EQ, 0);
3365 :
3366 : r = tor_sscanf("2147483648. -2147483649.",
3367 : "%ld. %ld.", &lng1, &lng2);
3368 : tt_int_op(r,OP_EQ, 0);
3369 : #elif SIZEOF_LONG == 8
3370 : /* %lu */
3371 : /* UINT64_MAX should work */
3372 1 : tt_int_op(1,OP_EQ, tor_sscanf("18446744073709551615", "%lu", &ulng));
3373 1 : tt_int_op(18446744073709551615UL,OP_EQ, ulng);
3374 :
3375 : /* But UINT64_MAX + 1 shouldn't work */
3376 1 : tt_int_op(0,OP_EQ, tor_sscanf("18446744073709551616", "%lu", &ulng));
3377 : /* but parsing only 19... */
3378 1 : tt_int_op(1,OP_EQ, tor_sscanf("18446744073709551616", "%19lu", &ulng));
3379 1 : tt_int_op(1844674407370955161UL,OP_EQ, ulng);
3380 :
3381 : /* %lx */
3382 : /* UINT64_MAX should work */
3383 1 : tt_int_op(1,OP_EQ, tor_sscanf("FFFFFFFFFFFFFFFF", "%lx", &ulng));
3384 1 : tt_int_op(0xFFFFFFFFFFFFFFFFUL,OP_EQ, ulng);
3385 :
3386 : /* But UINT64_MAX + 1 shouldn't work */
3387 1 : tt_int_op(0,OP_EQ, tor_sscanf("10000000000000000", "%lx", &ulng));
3388 :
3389 : /* %ld */
3390 : /* INT64_MIN and INT64_MAX should work */
3391 1 : r = tor_sscanf("-9223372036854775808. 9223372036854775807.",
3392 : "%ld. %ld.", &lng1, &lng2);
3393 1 : tt_int_op(r,OP_EQ, 2);
3394 1 : tt_int_op(lng1,OP_EQ, -9223372036854775807L - 1L);
3395 1 : tt_int_op(lng2,OP_EQ, 9223372036854775807L);
3396 :
3397 : /* But INT64_MIN - 1 and INT64_MAX + 1 shouldn't work */
3398 1 : r = tor_sscanf("-9223372036854775809.", "%ld.", &lng1);
3399 1 : tt_int_op(r,OP_EQ, 0);
3400 :
3401 1 : r = tor_sscanf("9223372036854775808.", "%ld.", &lng1);
3402 1 : tt_int_op(r,OP_EQ, 0);
3403 :
3404 : /* and the first failure stops further processing */
3405 1 : r = tor_sscanf("-9223372036854775808. 9223372036854775808.",
3406 : "%ld. %ld.", &lng1, &lng2);
3407 1 : tt_int_op(r,OP_EQ, 1);
3408 :
3409 1 : r = tor_sscanf("-9223372036854775809. 9223372036854775807.",
3410 : "%ld. %ld.", &lng1, &lng2);
3411 1 : tt_int_op(r,OP_EQ, 0);
3412 :
3413 1 : r = tor_sscanf("9223372036854775808. -9223372036854775809.",
3414 : "%ld. %ld.", &lng1, &lng2);
3415 1 : tt_int_op(r,OP_EQ, 0);
3416 : #endif /* SIZEOF_LONG == 4 || ... */
3417 :
3418 1 : r = tor_sscanf("123.456 .000007 -900123123.2000787 00003.2",
3419 : "%lf %lf %lf %lf", &d1,&d2,&d3,&d4);
3420 1 : tt_int_op(r,OP_EQ, 4);
3421 1 : test_feq(d1, 123.456);
3422 1 : test_feq(d2, .000007);
3423 1 : test_feq(d3, -900123123.2000787);
3424 1 : test_feq(d4, 3.2);
3425 :
3426 : /* missing float */
3427 1 : r = tor_sscanf("3 ", "%d %lf", &int1, &d1);
3428 1 : tt_int_op(r, OP_EQ, 1);
3429 1 : tt_int_op(int1, OP_EQ, 3);
3430 :
3431 : /* not a float */
3432 1 : r = tor_sscanf("999 notafloat", "%d %lf", &int1, &d1);
3433 1 : tt_int_op(r, OP_EQ, 1);
3434 1 : tt_int_op(int1, OP_EQ, 999);
3435 :
3436 : /* %s but no buffer. */
3437 1 : char *nullbuf = NULL;
3438 1 : r = tor_sscanf("hello", "%3s", nullbuf);
3439 1 : tt_int_op(r, OP_EQ, 0);
3440 :
3441 1 : done:
3442 1 : tor_free(huge);
3443 1 : }
3444 :
3445 : #define tt_char_op(a,op,b) tt_assert_op_type(a,op,b,char,"%c")
3446 : #define tt_ci_char_op(a,op,b) \
3447 : tt_char_op(TOR_TOLOWER((int)a),op,TOR_TOLOWER((int)b))
3448 :
3449 : #ifndef HAVE_STRNLEN
3450 : static size_t
3451 : strnlen(const char *s, size_t len)
3452 : {
3453 : const char *p = memchr(s, 0, len);
3454 : if (!p)
3455 : return len;
3456 : return p - s;
3457 : }
3458 : #endif /* !defined(HAVE_STRNLEN) */
3459 :
3460 : static void
3461 1 : test_util_format_time_interval(void *arg)
3462 : {
3463 : /* use the same sized buffer and integers as tor uses */
3464 : #define DBUF_SIZE 64
3465 1 : char dbuf[DBUF_SIZE];
3466 : #define T_ "%ld"
3467 1 : long sec, min, hour, day;
3468 :
3469 : /* we don't care about the exact spelling of the
3470 : * second(s), minute(s), hour(s), day(s) labels */
3471 : #define LABEL_SIZE 21
3472 : #define L_ "%20s"
3473 1 : char label_s[LABEL_SIZE];
3474 1 : char label_m[LABEL_SIZE];
3475 1 : char label_h[LABEL_SIZE];
3476 1 : char label_d[LABEL_SIZE];
3477 :
3478 : #define TL_ T_ " " L_
3479 :
3480 1 : int r;
3481 :
3482 1 : (void)arg;
3483 :
3484 : /* In these tests, we're not picky about
3485 : * spelling or abbreviations */
3486 :
3487 : /* seconds: 0, 1, 9, 10, 59 */
3488 :
3489 : /* ignore exact spelling of "second(s)"*/
3490 1 : format_time_interval(dbuf, sizeof(dbuf), 0);
3491 1 : tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
3492 1 : r = tor_sscanf(dbuf, TL_, &sec, label_s);
3493 1 : tt_int_op(r,OP_EQ, 2);
3494 1 : tt_ci_char_op(label_s[0],OP_EQ, 's');
3495 1 : tt_int_op(sec,OP_EQ, 0);
3496 :
3497 1 : format_time_interval(dbuf, sizeof(dbuf), 1);
3498 1 : tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
3499 1 : r = tor_sscanf(dbuf, TL_, &sec, label_s);
3500 1 : tt_int_op(r,OP_EQ, 2);
3501 1 : tt_ci_char_op(label_s[0],OP_EQ, 's');
3502 1 : tt_int_op(sec,OP_EQ, 1);
3503 :
3504 1 : format_time_interval(dbuf, sizeof(dbuf), 10);
3505 1 : tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
3506 1 : r = tor_sscanf(dbuf, TL_, &sec, label_s);
3507 1 : tt_int_op(r,OP_EQ, 2);
3508 1 : tt_ci_char_op(label_s[0],OP_EQ, 's');
3509 1 : tt_int_op(sec,OP_EQ, 10);
3510 :
3511 1 : format_time_interval(dbuf, sizeof(dbuf), 59);
3512 1 : tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
3513 1 : r = tor_sscanf(dbuf, TL_, &sec, label_s);
3514 1 : tt_int_op(r,OP_EQ, 2);
3515 1 : tt_ci_char_op(label_s[0],OP_EQ, 's');
3516 1 : tt_int_op(sec,OP_EQ, 59);
3517 :
3518 : /* negative seconds are reported as their absolute value */
3519 :
3520 1 : format_time_interval(dbuf, sizeof(dbuf), -4);
3521 1 : tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
3522 1 : r = tor_sscanf(dbuf, TL_, &sec, label_s);
3523 1 : tt_int_op(r,OP_EQ, 2);
3524 1 : tt_ci_char_op(label_s[0],OP_EQ, 's');
3525 1 : tt_int_op(sec,OP_EQ, 4);
3526 1 : tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
3527 :
3528 1 : format_time_interval(dbuf, sizeof(dbuf), -32);
3529 1 : tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
3530 1 : r = tor_sscanf(dbuf, TL_, &sec, label_s);
3531 1 : tt_int_op(r,OP_EQ, 2);
3532 1 : tt_ci_char_op(label_s[0],OP_EQ, 's');
3533 1 : tt_int_op(sec,OP_EQ, 32);
3534 1 : tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
3535 :
3536 : /* minutes: 1:00, 1:01, 1:59, 2:00, 2:01, 59:59 */
3537 :
3538 : /* ignore trailing "0 second(s)", if present */
3539 1 : format_time_interval(dbuf, sizeof(dbuf), 60);
3540 1 : tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
3541 1 : r = tor_sscanf(dbuf, TL_, &min, label_m);
3542 1 : tt_int_op(r,OP_EQ, 2);
3543 1 : tt_ci_char_op(label_m[0],OP_EQ, 'm');
3544 1 : tt_int_op(min,OP_EQ, 1);
3545 1 : tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
3546 :
3547 : /* ignore exact spelling of "minute(s)," and "second(s)" */
3548 1 : format_time_interval(dbuf, sizeof(dbuf), 60 + 1);
3549 1 : tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
3550 1 : r = tor_sscanf(dbuf, TL_ " " TL_,
3551 : &min, label_m, &sec, label_s);
3552 1 : tt_int_op(r,OP_EQ, 4);
3553 1 : tt_int_op(min,OP_EQ, 1);
3554 1 : tt_ci_char_op(label_m[0],OP_EQ, 'm');
3555 1 : tt_int_op(sec,OP_EQ, 1);
3556 1 : tt_ci_char_op(label_s[0],OP_EQ, 's');
3557 1 : tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
3558 :
3559 1 : format_time_interval(dbuf, sizeof(dbuf), 60*2 - 1);
3560 1 : tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
3561 1 : r = tor_sscanf(dbuf, TL_ " " TL_,
3562 : &min, label_m, &sec, label_s);
3563 1 : tt_int_op(r,OP_EQ, 4);
3564 1 : tt_int_op(min,OP_EQ, 1);
3565 1 : tt_ci_char_op(label_m[0],OP_EQ, 'm');
3566 1 : tt_int_op(sec,OP_EQ, 59);
3567 1 : tt_ci_char_op(label_s[0],OP_EQ, 's');
3568 :
3569 : /* ignore trailing "0 second(s)", if present */
3570 1 : format_time_interval(dbuf, sizeof(dbuf), 60*2);
3571 1 : tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
3572 1 : r = tor_sscanf(dbuf, TL_, &min, label_m);
3573 1 : tt_int_op(r,OP_EQ, 2);
3574 1 : tt_int_op(min,OP_EQ, 2);
3575 1 : tt_ci_char_op(label_m[0],OP_EQ, 'm');
3576 :
3577 : /* ignore exact spelling of "minute(s)," and "second(s)" */
3578 1 : format_time_interval(dbuf, sizeof(dbuf), 60*2 + 1);
3579 1 : tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
3580 1 : r = tor_sscanf(dbuf, TL_ " " TL_,
3581 : &min, label_m, &sec, label_s);
3582 1 : tt_int_op(r,OP_EQ, 4);
3583 1 : tt_int_op(min,OP_EQ, 2);
3584 1 : tt_ci_char_op(label_m[0],OP_EQ, 'm');
3585 1 : tt_int_op(sec,OP_EQ, 1);
3586 1 : tt_ci_char_op(label_s[0],OP_EQ, 's');
3587 :
3588 1 : format_time_interval(dbuf, sizeof(dbuf), 60*60 - 1);
3589 1 : tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
3590 1 : r = tor_sscanf(dbuf, TL_ " " TL_,
3591 : &min, label_m, &sec, label_s);
3592 1 : tt_int_op(r,OP_EQ, 4);
3593 1 : tt_int_op(min,OP_EQ, 59);
3594 1 : tt_ci_char_op(label_m[0],OP_EQ, 'm');
3595 1 : tt_int_op(sec,OP_EQ, 59);
3596 1 : tt_ci_char_op(label_s[0],OP_EQ, 's');
3597 :
3598 : /* negative minutes are reported as their absolute value */
3599 :
3600 : /* ignore trailing "0 second(s)", if present */
3601 1 : format_time_interval(dbuf, sizeof(dbuf), -3*60);
3602 1 : tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
3603 1 : r = tor_sscanf(dbuf, TL_, &min, label_m);
3604 1 : tt_int_op(r,OP_EQ, 2);
3605 1 : tt_int_op(min,OP_EQ, 3);
3606 1 : tt_ci_char_op(label_m[0],OP_EQ, 'm');
3607 :
3608 : /* ignore exact spelling of "minute(s)," and "second(s)" */
3609 1 : format_time_interval(dbuf, sizeof(dbuf), -96);
3610 1 : tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
3611 1 : r = tor_sscanf(dbuf, TL_ " " TL_,
3612 : &min, label_m, &sec, label_s);
3613 1 : tt_int_op(r,OP_EQ, 4);
3614 1 : tt_int_op(min,OP_EQ, 1);
3615 1 : tt_ci_char_op(label_m[0],OP_EQ, 'm');
3616 1 : tt_int_op(sec,OP_EQ, 36);
3617 1 : tt_ci_char_op(label_s[0],OP_EQ, 's');
3618 :
3619 1 : format_time_interval(dbuf, sizeof(dbuf), -2815);
3620 1 : tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
3621 1 : r = tor_sscanf(dbuf, TL_ " " TL_,
3622 : &min, label_m, &sec, label_s);
3623 1 : tt_int_op(r,OP_EQ, 4);
3624 1 : tt_int_op(min,OP_EQ, 46);
3625 1 : tt_ci_char_op(label_m[0],OP_EQ, 'm');
3626 1 : tt_int_op(sec,OP_EQ, 55);
3627 1 : tt_ci_char_op(label_s[0],OP_EQ, 's');
3628 :
3629 : /* hours: 1:00, 1:00:01, 1:01, 23:59, 23:59:59 */
3630 : /* always ignore trailing seconds, if present */
3631 :
3632 : /* ignore trailing "0 minute(s)" etc., if present */
3633 1 : format_time_interval(dbuf, sizeof(dbuf), 60*60);
3634 1 : tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
3635 1 : r = tor_sscanf(dbuf, TL_, &hour, label_h);
3636 1 : tt_int_op(r,OP_EQ, 2);
3637 1 : tt_int_op(hour,OP_EQ, 1);
3638 1 : tt_ci_char_op(label_h[0],OP_EQ, 'h');
3639 :
3640 1 : format_time_interval(dbuf, sizeof(dbuf), 60*60 + 1);
3641 1 : tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
3642 1 : r = tor_sscanf(dbuf, TL_, &hour, label_h);
3643 1 : tt_int_op(r,OP_EQ, 2);
3644 1 : tt_int_op(hour,OP_EQ, 1);
3645 1 : tt_ci_char_op(label_h[0],OP_EQ, 'h');
3646 :
3647 : /* ignore exact spelling of "hour(s)," etc. */
3648 1 : format_time_interval(dbuf, sizeof(dbuf), 60*60 + 60);
3649 1 : tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
3650 1 : r = tor_sscanf(dbuf, TL_ " " TL_,
3651 : &hour, label_h, &min, label_m);
3652 1 : tt_int_op(r,OP_EQ, 4);
3653 1 : tt_int_op(hour,OP_EQ, 1);
3654 1 : tt_ci_char_op(label_h[0],OP_EQ, 'h');
3655 1 : tt_int_op(min,OP_EQ, 1);
3656 1 : tt_ci_char_op(label_m[0],OP_EQ, 'm');
3657 :
3658 1 : format_time_interval(dbuf, sizeof(dbuf), 24*60*60 - 60);
3659 1 : tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
3660 1 : r = tor_sscanf(dbuf, TL_ " " TL_,
3661 : &hour, label_h, &min, label_m);
3662 1 : tt_int_op(r,OP_EQ, 4);
3663 1 : tt_int_op(hour,OP_EQ, 23);
3664 1 : tt_ci_char_op(label_h[0],OP_EQ, 'h');
3665 1 : tt_int_op(min,OP_EQ, 59);
3666 1 : tt_ci_char_op(label_m[0],OP_EQ, 'm');
3667 :
3668 1 : format_time_interval(dbuf, sizeof(dbuf), 24*60*60 - 1);
3669 1 : tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
3670 1 : r = tor_sscanf(dbuf, TL_ " " TL_,
3671 : &hour, label_h, &min, label_m);
3672 1 : tt_int_op(r,OP_EQ, 4);
3673 1 : tt_int_op(hour,OP_EQ, 23);
3674 1 : tt_ci_char_op(label_h[0],OP_EQ, 'h');
3675 1 : tt_int_op(min,OP_EQ, 59);
3676 1 : tt_ci_char_op(label_m[0],OP_EQ, 'm');
3677 :
3678 : /* negative hours are reported as their absolute value */
3679 :
3680 : /* ignore exact spelling of "hour(s)," etc., if present */
3681 1 : format_time_interval(dbuf, sizeof(dbuf), -2*60*60);
3682 1 : tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
3683 1 : r = tor_sscanf(dbuf, TL_, &hour, label_h);
3684 1 : tt_int_op(r,OP_EQ, 2);
3685 1 : tt_int_op(hour,OP_EQ, 2);
3686 1 : tt_ci_char_op(label_h[0],OP_EQ, 'h');
3687 :
3688 1 : format_time_interval(dbuf, sizeof(dbuf), -75804);
3689 1 : tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
3690 1 : r = tor_sscanf(dbuf, TL_ " " TL_,
3691 : &hour, label_h, &min, label_m);
3692 1 : tt_int_op(r,OP_EQ, 4);
3693 1 : tt_int_op(hour,OP_EQ, 21);
3694 1 : tt_ci_char_op(label_h[0],OP_EQ, 'h');
3695 1 : tt_int_op(min,OP_EQ, 3);
3696 1 : tt_ci_char_op(label_m[0],OP_EQ, 'm');
3697 :
3698 : /* days: 1:00, 1:00:00:01, 1:00:01, 1:01 */
3699 : /* always ignore trailing seconds, if present */
3700 :
3701 : /* ignore trailing "0 hours(s)" etc., if present */
3702 1 : format_time_interval(dbuf, sizeof(dbuf), 24*60*60);
3703 1 : tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
3704 1 : r = tor_sscanf(dbuf, TL_, &day, label_d);
3705 1 : tt_int_op(r,OP_EQ, 2);
3706 1 : tt_int_op(day,OP_EQ, 1);
3707 1 : tt_ci_char_op(label_d[0],OP_EQ, 'd');
3708 :
3709 1 : format_time_interval(dbuf, sizeof(dbuf), 24*60*60 + 1);
3710 1 : tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
3711 1 : r = tor_sscanf(dbuf, TL_, &day, label_d);
3712 1 : tt_int_op(r,OP_EQ, 2);
3713 1 : tt_int_op(day,OP_EQ, 1);
3714 1 : tt_ci_char_op(label_d[0],OP_EQ, 'd');
3715 :
3716 : /* ignore exact spelling of "days(s)," etc. */
3717 1 : format_time_interval(dbuf, sizeof(dbuf), 24*60*60 + 60);
3718 1 : tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
3719 1 : r = tor_sscanf(dbuf, TL_ " " TL_ " " TL_,
3720 : &day, label_d, &hour, label_h, &min, label_m);
3721 1 : if (r == -1) {
3722 : /* ignore 0 hours(s), if present */
3723 0 : r = tor_sscanf(dbuf, TL_ " " TL_,
3724 : &day, label_d, &min, label_m);
3725 : }
3726 1 : tt_assert(r == 4 || r == 6);
3727 1 : tt_int_op(day,OP_EQ, 1);
3728 1 : tt_ci_char_op(label_d[0],OP_EQ, 'd');
3729 1 : if (r == 6) {
3730 1 : tt_int_op(hour,OP_EQ, 0);
3731 1 : tt_ci_char_op(label_h[0],OP_EQ, 'h');
3732 : }
3733 1 : tt_int_op(min,OP_EQ, 1);
3734 1 : tt_ci_char_op(label_m[0],OP_EQ, 'm');
3735 :
3736 : /* ignore trailing "0 minutes(s)" etc., if present */
3737 1 : format_time_interval(dbuf, sizeof(dbuf), 24*60*60 + 60*60);
3738 1 : tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
3739 1 : r = tor_sscanf(dbuf, TL_ " " TL_,
3740 : &day, label_d, &hour, label_h);
3741 1 : tt_int_op(r,OP_EQ, 4);
3742 1 : tt_int_op(day,OP_EQ, 1);
3743 1 : tt_ci_char_op(label_d[0],OP_EQ, 'd');
3744 1 : tt_int_op(hour,OP_EQ, 1);
3745 1 : tt_ci_char_op(label_h[0],OP_EQ, 'h');
3746 :
3747 : /* negative days are reported as their absolute value */
3748 :
3749 1 : format_time_interval(dbuf, sizeof(dbuf), -21936184);
3750 1 : tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
3751 1 : r = tor_sscanf(dbuf, TL_ " " TL_ " " TL_,
3752 : &day, label_d, &hour, label_h, &min, label_m);
3753 1 : tt_int_op(r,OP_EQ, 6);
3754 1 : tt_int_op(day,OP_EQ, 253);
3755 1 : tt_ci_char_op(label_d[0],OP_EQ, 'd');
3756 1 : tt_int_op(hour,OP_EQ, 21);
3757 1 : tt_ci_char_op(label_h[0],OP_EQ, 'h');
3758 1 : tt_int_op(min,OP_EQ, 23);
3759 1 : tt_ci_char_op(label_m[0],OP_EQ, 'm');
3760 :
3761 : /* periods > 1 year are reported in days (warn?) */
3762 :
3763 : /* ignore exact spelling of "days(s)," etc., if present */
3764 1 : format_time_interval(dbuf, sizeof(dbuf), 758635154);
3765 1 : tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
3766 1 : r = tor_sscanf(dbuf, TL_ " " TL_ " " TL_,
3767 : &day, label_d, &hour, label_h, &min, label_m);
3768 1 : tt_int_op(r,OP_EQ, 6);
3769 1 : tt_int_op(day,OP_EQ, 8780);
3770 1 : tt_ci_char_op(label_d[0],OP_EQ, 'd');
3771 1 : tt_int_op(hour,OP_EQ, 11);
3772 1 : tt_ci_char_op(label_h[0],OP_EQ, 'h');
3773 1 : tt_int_op(min,OP_EQ, 59);
3774 1 : tt_ci_char_op(label_m[0],OP_EQ, 'm');
3775 :
3776 : /* negative periods > 1 year are reported in days (warn?) */
3777 :
3778 1 : format_time_interval(dbuf, sizeof(dbuf), -1427014922);
3779 1 : tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
3780 1 : r = tor_sscanf(dbuf, TL_ " " TL_ " " TL_,
3781 : &day, label_d, &hour, label_h, &min, label_m);
3782 1 : tt_int_op(r,OP_EQ, 6);
3783 1 : tt_int_op(day,OP_EQ, 16516);
3784 1 : tt_ci_char_op(label_d[0],OP_EQ, 'd');
3785 1 : tt_int_op(hour,OP_EQ, 9);
3786 1 : tt_ci_char_op(label_h[0],OP_EQ, 'h');
3787 1 : tt_int_op(min,OP_EQ, 2);
3788 1 : tt_ci_char_op(label_m[0],OP_EQ, 'm');
3789 :
3790 : #if SIZEOF_LONG == 4 || SIZEOF_LONG == 8
3791 :
3792 : /* We can try INT32_MIN/MAX */
3793 : /* Always ignore second(s) */
3794 :
3795 : /* INT32_MAX */
3796 1 : format_time_interval(dbuf, sizeof(dbuf), 2147483647);
3797 1 : tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
3798 1 : r = tor_sscanf(dbuf, TL_ " " TL_ " " TL_,
3799 : &day, label_d, &hour, label_h, &min, label_m);
3800 1 : tt_int_op(r,OP_EQ, 6);
3801 1 : tt_int_op(day,OP_EQ, 24855);
3802 1 : tt_ci_char_op(label_d[0],OP_EQ, 'd');
3803 1 : tt_int_op(hour,OP_EQ, 3);
3804 1 : tt_ci_char_op(label_h[0],OP_EQ, 'h');
3805 1 : tt_int_op(min,OP_EQ, 14);
3806 1 : tt_ci_char_op(label_m[0],OP_EQ, 'm');
3807 : /* and 7 seconds - ignored */
3808 :
3809 : /* INT32_MIN: check that we get the absolute value of interval,
3810 : * which doesn't actually fit in int32_t.
3811 : * We expect INT32_MAX or INT32_MAX + 1 with 64 bit longs */
3812 1 : format_time_interval(dbuf, sizeof(dbuf), -2147483647L - 1L);
3813 1 : tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
3814 1 : r = tor_sscanf(dbuf, TL_ " " TL_ " " TL_,
3815 : &day, label_d, &hour, label_h, &min, label_m);
3816 1 : tt_int_op(r,OP_EQ, 6);
3817 1 : tt_int_op(day,OP_EQ, 24855);
3818 1 : tt_ci_char_op(label_d[0],OP_EQ, 'd');
3819 1 : tt_int_op(hour,OP_EQ, 3);
3820 1 : tt_ci_char_op(label_h[0],OP_EQ, 'h');
3821 1 : tt_int_op(min,OP_EQ, 14);
3822 1 : tt_ci_char_op(label_m[0],OP_EQ, 'm');
3823 : /* and 7 or 8 seconds - ignored */
3824 :
3825 : #endif /* SIZEOF_LONG == 4 || SIZEOF_LONG == 8 */
3826 :
3827 : #if SIZEOF_LONG == 8
3828 :
3829 : /* We can try INT64_MIN/MAX */
3830 : /* Always ignore second(s) */
3831 :
3832 : /* INT64_MAX */
3833 1 : format_time_interval(dbuf, sizeof(dbuf), 9223372036854775807L);
3834 1 : tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
3835 1 : r = tor_sscanf(dbuf, TL_ " " TL_ " " TL_,
3836 : &day, label_d, &hour, label_h, &min, label_m);
3837 1 : tt_int_op(r,OP_EQ, 6);
3838 1 : tt_int_op(day,OP_EQ, 106751991167300L);
3839 1 : tt_ci_char_op(label_d[0],OP_EQ, 'd');
3840 1 : tt_int_op(hour,OP_EQ, 15);
3841 1 : tt_ci_char_op(label_h[0],OP_EQ, 'h');
3842 1 : tt_int_op(min,OP_EQ, 30);
3843 1 : tt_ci_char_op(label_m[0],OP_EQ, 'm');
3844 : /* and 7 seconds - ignored */
3845 :
3846 : /* INT64_MIN: check that we get the absolute value of interval,
3847 : * which doesn't actually fit in int64_t.
3848 : * We expect INT64_MAX */
3849 1 : format_time_interval(dbuf, sizeof(dbuf),
3850 : -9223372036854775807L - 1L);
3851 1 : tt_int_op(strnlen(dbuf, DBUF_SIZE),OP_LE, DBUF_SIZE - 1);
3852 1 : r = tor_sscanf(dbuf, TL_ " " TL_ " " TL_,
3853 : &day, label_d, &hour, label_h, &min, label_m);
3854 1 : tt_int_op(r,OP_EQ, 6);
3855 1 : tt_int_op(day,OP_EQ, 106751991167300L);
3856 1 : tt_ci_char_op(label_d[0],OP_EQ, 'd');
3857 1 : tt_int_op(hour,OP_EQ, 15);
3858 1 : tt_ci_char_op(label_h[0],OP_EQ, 'h');
3859 1 : tt_int_op(min,OP_EQ, 30);
3860 1 : tt_ci_char_op(label_m[0],OP_EQ, 'm');
3861 : /* and 7 or 8 seconds - ignored */
3862 :
3863 : #endif /* SIZEOF_LONG == 8 */
3864 :
3865 1 : done:
3866 1 : ;
3867 1 : }
3868 :
3869 : #undef tt_char_op
3870 : #undef tt_ci_char_op
3871 : #undef DBUF_SIZE
3872 : #undef T_
3873 : #undef LABEL_SIZE
3874 : #undef L_
3875 : #undef TL_
3876 :
3877 : static void
3878 1 : test_util_path_is_relative(void *arg)
3879 : {
3880 : /* OS-independent tests */
3881 1 : (void)arg;
3882 1 : tt_int_op(1,OP_EQ, path_is_relative(""));
3883 1 : tt_int_op(1,OP_EQ, path_is_relative("dir"));
3884 1 : tt_int_op(1,OP_EQ, path_is_relative("dir/"));
3885 1 : tt_int_op(1,OP_EQ, path_is_relative("./dir"));
3886 1 : tt_int_op(1,OP_EQ, path_is_relative("../dir"));
3887 :
3888 1 : tt_int_op(0,OP_EQ, path_is_relative("/"));
3889 1 : tt_int_op(0,OP_EQ, path_is_relative("/dir"));
3890 1 : tt_int_op(0,OP_EQ, path_is_relative("/dir/"));
3891 :
3892 : /* Windows */
3893 : #ifdef _WIN32
3894 : /* I don't have Windows so I can't test this, hence the "#ifdef
3895 : 0". These are tests that look useful, so please try to get them
3896 : running and uncomment if it all works as it should */
3897 : tt_int_op(1,OP_EQ, path_is_relative("dir"));
3898 : tt_int_op(1,OP_EQ, path_is_relative("dir\\"));
3899 : tt_int_op(1,OP_EQ, path_is_relative("dir\\a:"));
3900 : tt_int_op(1,OP_EQ, path_is_relative("dir\\a:\\"));
3901 : tt_int_op(1,OP_EQ, path_is_relative("http:\\dir"));
3902 :
3903 : tt_int_op(0,OP_EQ, path_is_relative("\\dir"));
3904 : tt_int_op(0,OP_EQ, path_is_relative("a:\\dir"));
3905 : tt_int_op(0,OP_EQ, path_is_relative("z:\\dir"));
3906 : #endif /* defined(_WIN32) */
3907 :
3908 1 : done:
3909 1 : ;
3910 1 : }
3911 :
3912 : /** Run unittests for memory area allocator */
3913 : static void
3914 1 : test_util_memarea(void *arg)
3915 : {
3916 1 : memarea_t *area = memarea_new();
3917 1 : char *p1, *p2, *p3, *p1_orig;
3918 1 : void *malloced_ptr = NULL;
3919 1 : int i;
3920 :
3921 : #ifdef DISABLE_MEMORY_SENTINELS
3922 : /* If memory sentinels are disabled, this whole module is just an alias for
3923 : malloc(), which is free to lay out memory most any way it wants. */
3924 : if (1)
3925 : tt_skip();
3926 : #endif /* defined(DISABLE_MEMORY_SENTINELS) */
3927 :
3928 1 : (void)arg;
3929 1 : tt_assert(area);
3930 :
3931 1 : p1_orig = p1 = memarea_alloc(area,64);
3932 1 : p2 = memarea_alloc_zero(area,52);
3933 1 : p3 = memarea_alloc(area,11);
3934 :
3935 1 : tt_assert(memarea_owns_ptr(area, p1));
3936 1 : tt_assert(memarea_owns_ptr(area, p2));
3937 1 : tt_assert(memarea_owns_ptr(area, p3));
3938 : /* Make sure we left enough space. */
3939 1 : tt_assert(p1+64 <= p2);
3940 1 : tt_assert(p2+52 <= p3);
3941 : /* Make sure we aligned. */
3942 1 : tt_int_op(((uintptr_t)p1) % sizeof(void*),OP_EQ, 0);
3943 1 : tt_int_op(((uintptr_t)p2) % sizeof(void*),OP_EQ, 0);
3944 1 : tt_int_op(((uintptr_t)p3) % sizeof(void*),OP_EQ, 0);
3945 1 : tt_assert(!memarea_owns_ptr(area, p3+8192));
3946 1 : tt_assert(!memarea_owns_ptr(area, p3+30));
3947 1 : tt_assert(fast_mem_is_zero(p2, 52));
3948 : /* Make sure we don't overalign. */
3949 1 : p1 = memarea_alloc(area, 1);
3950 1 : p2 = memarea_alloc(area, 1);
3951 1 : tt_ptr_op(p1+sizeof(void*),OP_EQ, p2);
3952 : {
3953 1 : malloced_ptr = tor_malloc(64);
3954 1 : tt_assert(!memarea_owns_ptr(area, malloced_ptr));
3955 1 : tor_free(malloced_ptr);
3956 : }
3957 :
3958 : /* memarea_memdup */
3959 : {
3960 1 : malloced_ptr = tor_malloc(64);
3961 1 : crypto_rand((char*)malloced_ptr, 64);
3962 1 : p1 = memarea_memdup(area, malloced_ptr, 64);
3963 1 : tt_assert(p1 != malloced_ptr);
3964 1 : tt_mem_op(p1,OP_EQ, malloced_ptr, 64);
3965 1 : tor_free(malloced_ptr);
3966 : }
3967 :
3968 : /* memarea_strdup. */
3969 1 : p1 = memarea_strdup(area,"");
3970 1 : p2 = memarea_strdup(area, "abcd");
3971 1 : tt_assert(p1);
3972 1 : tt_assert(p2);
3973 1 : tt_str_op(p1,OP_EQ, "");
3974 1 : tt_str_op(p2,OP_EQ, "abcd");
3975 :
3976 : /* memarea_strndup. */
3977 : {
3978 1 : const char *s = "Ad ogni porta batte la morte e grida: il nome!";
3979 : /* (From Turandot, act 3.) */
3980 1 : size_t len = strlen(s);
3981 1 : p1 = memarea_strndup(area, s, 1000);
3982 1 : p2 = memarea_strndup(area, s, 10);
3983 1 : tt_str_op(p1,OP_EQ, s);
3984 1 : tt_assert(p2 >= p1 + len + 1);
3985 1 : tt_mem_op(s,OP_EQ, p2, 10);
3986 1 : tt_int_op(p2[10],OP_EQ, '\0');
3987 1 : p3 = memarea_strndup(area, s, len);
3988 1 : tt_str_op(p3,OP_EQ, s);
3989 1 : p3 = memarea_strndup(area, s, len-1);
3990 1 : tt_mem_op(s,OP_EQ, p3, len-1);
3991 1 : tt_int_op(p3[len-1],OP_EQ, '\0');
3992 : }
3993 :
3994 1 : memarea_clear(area);
3995 1 : p1 = memarea_alloc(area, 1);
3996 1 : tt_ptr_op(p1,OP_EQ, p1_orig);
3997 1 : memarea_clear(area);
3998 1 : size_t total = 0, initial_allocation, allocation2, dummy;
3999 1 : memarea_get_stats(area, &initial_allocation, &dummy);
4000 :
4001 : /* Check for running over an area's size. */
4002 4098 : for (i = 0; i < 4096; ++i) {
4003 4096 : size_t n = crypto_rand_int(6);
4004 4096 : p1 = memarea_alloc(area, n);
4005 4096 : total += n;
4006 4096 : tt_assert(memarea_owns_ptr(area, p1));
4007 : }
4008 1 : memarea_assert_ok(area);
4009 1 : memarea_get_stats(area, &allocation2, &dummy);
4010 : /* Make sure we can allocate a too-big object. */
4011 1 : p1 = memarea_alloc_zero(area, 9000);
4012 1 : p2 = memarea_alloc_zero(area, 16);
4013 1 : total += 9000;
4014 1 : total += 16;
4015 1 : tt_assert(memarea_owns_ptr(area, p1));
4016 1 : tt_assert(memarea_owns_ptr(area, p2));
4017 :
4018 : /* Now test stats... */
4019 1 : size_t allocated = 0, used = 0;
4020 1 : memarea_get_stats(area, &allocated, &used);
4021 1 : tt_int_op(used, OP_LE, allocated);
4022 1 : tt_int_op(used, OP_GE, total); /* not EQ, because of alignment and headers*/
4023 1 : tt_int_op(allocated, OP_GT, allocation2);
4024 :
4025 1 : tt_int_op(allocation2, OP_GT, initial_allocation);
4026 :
4027 1 : memarea_clear(area);
4028 1 : memarea_get_stats(area, &allocated, &used);
4029 1 : tt_int_op(used, OP_LT, 128); /* Not 0, because of header */
4030 1 : tt_int_op(allocated, OP_EQ, initial_allocation);
4031 :
4032 1 : done:
4033 1 : memarea_drop_all(area);
4034 1 : tor_free(malloced_ptr);
4035 1 : }
4036 :
4037 : /** Run unit tests for utility functions to get file names relative to
4038 : * the data directory. */
4039 : static void
4040 1 : test_util_datadir(void *arg)
4041 : {
4042 1 : char buf[1024];
4043 1 : char *f = NULL;
4044 1 : char *temp_dir = NULL;
4045 :
4046 1 : (void)arg;
4047 1 : temp_dir = get_datadir_fname(NULL);
4048 1 : f = get_datadir_fname("state");
4049 1 : tor_snprintf(buf, sizeof(buf), "%s"PATH_SEPARATOR"state", temp_dir);
4050 1 : tt_str_op(f,OP_EQ, buf);
4051 1 : tor_free(f);
4052 1 : f = get_datadir_fname2("cache", "thingy");
4053 1 : tor_snprintf(buf, sizeof(buf),
4054 : "%s"PATH_SEPARATOR"cache"PATH_SEPARATOR"thingy", temp_dir);
4055 1 : tt_str_op(f,OP_EQ, buf);
4056 1 : tor_free(f);
4057 1 : f = get_datadir_fname2_suffix("cache", "thingy", ".foo");
4058 1 : tor_snprintf(buf, sizeof(buf),
4059 : "%s"PATH_SEPARATOR"cache"PATH_SEPARATOR"thingy.foo", temp_dir);
4060 1 : tt_str_op(f,OP_EQ, buf);
4061 1 : tor_free(f);
4062 1 : f = get_datadir_fname_suffix("cache", ".foo");
4063 1 : tor_snprintf(buf, sizeof(buf), "%s"PATH_SEPARATOR"cache.foo",
4064 : temp_dir);
4065 1 : tt_str_op(f,OP_EQ, buf);
4066 :
4067 1 : done:
4068 1 : tor_free(f);
4069 1 : tor_free(temp_dir);
4070 1 : }
4071 :
4072 : static void
4073 1 : test_util_strtok(void *arg)
4074 : {
4075 1 : char buf[128];
4076 1 : char buf2[128];
4077 1 : int i;
4078 1 : char *cp1, *cp2;
4079 :
4080 1 : (void)arg;
4081 4 : for (i = 0; i < 3; i++) {
4082 3 : const char *pad1="", *pad2="";
4083 3 : switch (i) {
4084 : case 0:
4085 : break;
4086 1 : case 1:
4087 1 : pad1 = " ";
4088 1 : pad2 = "!";
4089 1 : break;
4090 1 : case 2:
4091 1 : pad1 = " ";
4092 1 : pad2 = ";!";
4093 1 : break;
4094 : }
4095 3 : tor_snprintf(buf, sizeof(buf), "%s", pad1);
4096 3 : tor_snprintf(buf2, sizeof(buf2), "%s", pad2);
4097 3 : tt_ptr_op(tor_strtok_r_impl(buf, " ", &cp1), OP_EQ, NULL);
4098 3 : tt_ptr_op(tor_strtok_r_impl(buf2, ".!..;!", &cp2), OP_EQ, NULL);
4099 :
4100 3 : tor_snprintf(buf, sizeof(buf),
4101 : "%sGraved on the dark in gestures of descent%s", pad1, pad1);
4102 3 : tor_snprintf(buf2, sizeof(buf2),
4103 : "%sthey.seemed;;their!.own;most.perfect;monument%s",pad2,pad2);
4104 : /* -- "Year's End", Richard Wilbur */
4105 :
4106 3 : tt_str_op("Graved",OP_EQ, tor_strtok_r_impl(buf, " ", &cp1));
4107 3 : tt_str_op("they",OP_EQ, tor_strtok_r_impl(buf2, ".!..;!", &cp2));
4108 : #define S1() tor_strtok_r_impl(NULL, " ", &cp1)
4109 : #define S2() tor_strtok_r_impl(NULL, ".!..;!", &cp2)
4110 3 : tt_str_op("on",OP_EQ, S1());
4111 3 : tt_str_op("the",OP_EQ, S1());
4112 3 : tt_str_op("dark",OP_EQ, S1());
4113 3 : tt_str_op("seemed",OP_EQ, S2());
4114 3 : tt_str_op("their",OP_EQ, S2());
4115 3 : tt_str_op("own",OP_EQ, S2());
4116 3 : tt_str_op("in",OP_EQ, S1());
4117 3 : tt_str_op("gestures",OP_EQ, S1());
4118 3 : tt_str_op("of",OP_EQ, S1());
4119 3 : tt_str_op("most",OP_EQ, S2());
4120 3 : tt_str_op("perfect",OP_EQ, S2());
4121 3 : tt_str_op("descent",OP_EQ, S1());
4122 3 : tt_str_op("monument",OP_EQ, S2());
4123 3 : tt_ptr_op(NULL,OP_EQ, S1());
4124 3 : tt_ptr_op(NULL,OP_EQ, S2());
4125 : }
4126 :
4127 1 : buf[0] = 0;
4128 1 : tt_ptr_op(NULL,OP_EQ, tor_strtok_r_impl(buf, " ", &cp1));
4129 1 : tt_ptr_op(NULL,OP_EQ, tor_strtok_r_impl(buf, "!", &cp1));
4130 :
4131 1 : strlcpy(buf, "Howdy!", sizeof(buf));
4132 1 : tt_str_op("Howdy",OP_EQ, tor_strtok_r_impl(buf, "!", &cp1));
4133 1 : tt_ptr_op(NULL,OP_EQ, tor_strtok_r_impl(NULL, "!", &cp1));
4134 :
4135 1 : strlcpy(buf, " ", sizeof(buf));
4136 1 : tt_ptr_op(NULL,OP_EQ, tor_strtok_r_impl(buf, " ", &cp1));
4137 1 : strlcpy(buf, " ", sizeof(buf));
4138 1 : tt_ptr_op(NULL,OP_EQ, tor_strtok_r_impl(buf, " ", &cp1));
4139 :
4140 1 : strlcpy(buf, "something ", sizeof(buf));
4141 1 : tt_str_op("something",OP_EQ, tor_strtok_r_impl(buf, " ", &cp1));
4142 1 : tt_ptr_op(NULL,OP_EQ, tor_strtok_r_impl(NULL, ";", &cp1));
4143 1 : done:
4144 1 : ;
4145 1 : }
4146 :
4147 : static void
4148 1 : test_util_find_str_at_start_of_line(void *ptr)
4149 : {
4150 1 : const char *long_string =
4151 : "howdy world. how are you? i hope it's fine.\n"
4152 : "hello kitty\n"
4153 : "third line";
4154 1 : char *line2 = strchr(long_string,'\n')+1;
4155 1 : char *line3 = strchr(line2,'\n')+1;
4156 1 : const char *short_string = "hello kitty\n"
4157 : "second line\n";
4158 1 : char *short_line2 = strchr(short_string,'\n')+1;
4159 :
4160 1 : (void)ptr;
4161 :
4162 1 : tt_ptr_op(long_string,OP_EQ, find_str_at_start_of_line(long_string, ""));
4163 1 : tt_ptr_op(NULL,OP_EQ, find_str_at_start_of_line(short_string, "nonsense"));
4164 1 : tt_ptr_op(NULL,OP_EQ, find_str_at_start_of_line(long_string, "nonsense"));
4165 1 : tt_ptr_op(NULL,OP_EQ, find_str_at_start_of_line(long_string, "\n"));
4166 1 : tt_ptr_op(NULL,OP_EQ, find_str_at_start_of_line(long_string, "how "));
4167 1 : tt_ptr_op(NULL,OP_EQ, find_str_at_start_of_line(long_string, "kitty"));
4168 1 : tt_ptr_op(long_string,OP_EQ, find_str_at_start_of_line(long_string, "h"));
4169 1 : tt_ptr_op(long_string,OP_EQ, find_str_at_start_of_line(long_string, "how"));
4170 1 : tt_ptr_op(line2,OP_EQ, find_str_at_start_of_line(long_string, "he"));
4171 1 : tt_ptr_op(line2,OP_EQ, find_str_at_start_of_line(long_string, "hell"));
4172 1 : tt_ptr_op(line2,OP_EQ, find_str_at_start_of_line(long_string, "hello k"));
4173 1 : tt_ptr_op(line2,OP_EQ,
4174 : find_str_at_start_of_line(long_string, "hello kitty\n"));
4175 1 : tt_ptr_op(line2,OP_EQ,
4176 : find_str_at_start_of_line(long_string, "hello kitty\nt"));
4177 1 : tt_ptr_op(line3,OP_EQ, find_str_at_start_of_line(long_string, "third"));
4178 1 : tt_ptr_op(line3,OP_EQ, find_str_at_start_of_line(long_string, "third line"));
4179 1 : tt_ptr_op(NULL, OP_EQ,
4180 : find_str_at_start_of_line(long_string, "third line\n"));
4181 1 : tt_ptr_op(short_line2,OP_EQ, find_str_at_start_of_line(short_string,
4182 : "second line\n"));
4183 1 : done:
4184 1 : ;
4185 1 : }
4186 :
4187 : static void
4188 1 : test_util_tor_strreplacechar(void *ptr)
4189 : {
4190 1 : (void)ptr;
4191 1 : char empty[] = "";
4192 1 : char not_contain[] = "bbb";
4193 1 : char contains[] = "bab";
4194 1 : char contains_all[] = "aaa";
4195 :
4196 1 : tor_strreplacechar(empty, 'a', 'b');
4197 1 : tt_str_op(empty, OP_EQ, "");
4198 :
4199 1 : tor_strreplacechar(not_contain, 'a', 'b');
4200 1 : tt_str_op(not_contain, OP_EQ, "bbb");
4201 :
4202 1 : tor_strreplacechar(contains, 'a', 'b');
4203 1 : tt_str_op(contains, OP_EQ, "bbb");
4204 :
4205 1 : tor_strreplacechar(contains_all, 'a', 'b');
4206 1 : tt_str_op(contains_all, OP_EQ, "bbb");
4207 :
4208 1 : done:
4209 1 : ;
4210 1 : }
4211 :
4212 : static void
4213 1 : test_util_string_is_C_identifier(void *ptr)
4214 : {
4215 1 : (void)ptr;
4216 :
4217 1 : tt_int_op(1,OP_EQ, string_is_C_identifier("string_is_C_identifier"));
4218 1 : tt_int_op(1,OP_EQ, string_is_C_identifier("_string_is_C_identifier"));
4219 1 : tt_int_op(1,OP_EQ, string_is_C_identifier("_"));
4220 1 : tt_int_op(1,OP_EQ, string_is_C_identifier("i"));
4221 1 : tt_int_op(1,OP_EQ, string_is_C_identifier("_____"));
4222 1 : tt_int_op(1,OP_EQ, string_is_C_identifier("__00__"));
4223 1 : tt_int_op(1,OP_EQ, string_is_C_identifier("__init__"));
4224 1 : tt_int_op(1,OP_EQ, string_is_C_identifier("_0"));
4225 1 : tt_int_op(1,OP_EQ, string_is_C_identifier("_0string_is_C_identifier"));
4226 1 : tt_int_op(1,OP_EQ, string_is_C_identifier("_0"));
4227 :
4228 1 : tt_int_op(0,OP_EQ, string_is_C_identifier("0_string_is_C_identifier"));
4229 1 : tt_int_op(0,OP_EQ, string_is_C_identifier("0"));
4230 1 : tt_int_op(0,OP_EQ, string_is_C_identifier(""));
4231 1 : tt_int_op(0,OP_EQ, string_is_C_identifier(";"));
4232 1 : tt_int_op(0,OP_EQ, string_is_C_identifier("i;"));
4233 1 : tt_int_op(0,OP_EQ, string_is_C_identifier("_;"));
4234 1 : tt_int_op(0,OP_EQ, string_is_C_identifier("Ã"));
4235 1 : tt_int_op(0,OP_EQ, string_is_C_identifier("ñ"));
4236 :
4237 1 : done:
4238 1 : ;
4239 1 : }
4240 :
4241 : static void
4242 1 : test_util_string_is_utf8(void *ptr)
4243 : {
4244 1 : (void)ptr;
4245 :
4246 1 : tt_int_op(1, OP_EQ, string_is_utf8(NULL, 0));
4247 1 : tt_int_op(1, OP_EQ, string_is_utf8("", 1));
4248 1 : tt_int_op(1, OP_EQ, string_is_utf8("\uFEFF", 3));
4249 1 : tt_int_op(1, OP_EQ, string_is_utf8("\uFFFE", 3));
4250 1 : tt_int_op(1, OP_EQ, string_is_utf8("ascii\x7f\n", 7));
4251 1 : tt_int_op(1, OP_EQ, string_is_utf8("Risqu\u00e9=1", 9));
4252 :
4253 : /* Test the utf8_no_bom function */
4254 1 : tt_int_op(0, OP_EQ, string_is_utf8_no_bom("\uFEFF", 3));
4255 1 : tt_int_op(0, OP_EQ, string_is_utf8_no_bom("\uFFFE", 3));
4256 1 : tt_int_op(0, OP_EQ, string_is_utf8_no_bom("\uFEFFlove", 7));
4257 1 : tt_int_op(1, OP_EQ, string_is_utf8_no_bom("loveandrespect",
4258 : strlen("loveandrespect")));
4259 :
4260 : // Validate exactly 'len' bytes.
4261 1 : tt_int_op(0, OP_EQ, string_is_utf8("\0\x80", 2));
4262 1 : tt_int_op(0, OP_EQ, string_is_utf8("Risqu\u00e9=1", 6));
4263 :
4264 : // Reject sequences with missing bytes.
4265 1 : tt_int_op(0, OP_EQ, string_is_utf8("\x80", 1));
4266 1 : tt_int_op(0, OP_EQ, string_is_utf8("\xc2", 1));
4267 1 : tt_int_op(0, OP_EQ, string_is_utf8("\xc2 ", 2));
4268 1 : tt_int_op(0, OP_EQ, string_is_utf8("\xe1\x80", 2));
4269 1 : tt_int_op(0, OP_EQ, string_is_utf8("\xe1\x80 ", 3));
4270 1 : tt_int_op(0, OP_EQ, string_is_utf8("\xf1\x80\x80", 3));
4271 1 : tt_int_op(0, OP_EQ, string_is_utf8("\xf1\x80\x80 ", 4));
4272 :
4273 : // Reject encodings that are overly long.
4274 1 : tt_int_op(0, OP_EQ, string_is_utf8("\xc1\xbf", 2));
4275 1 : tt_int_op(1, OP_EQ, string_is_utf8("\xc2\x80", 2));
4276 1 : tt_int_op(0, OP_EQ, string_is_utf8("\xe0\x9f\xbf", 3));
4277 1 : tt_int_op(1, OP_EQ, string_is_utf8("\xe0\xa0\x80", 3));
4278 1 : tt_int_op(0, OP_EQ, string_is_utf8("\xf0\x8f\xbf\xbf", 4));
4279 1 : tt_int_op(1, OP_EQ, string_is_utf8("\xf0\x90\x80\x80", 4));
4280 :
4281 : // Reject UTF-16 surrogate halves.
4282 1 : tt_int_op(1, OP_EQ, string_is_utf8("\xed\x9f\xbf", 3));
4283 1 : tt_int_op(0, OP_EQ, string_is_utf8("\xed\xa0\x80", 3));
4284 1 : tt_int_op(0, OP_EQ, string_is_utf8("\xed\xbf\xbf", 3));
4285 1 : tt_int_op(1, OP_EQ, string_is_utf8("\xee\x80\x80", 3));
4286 :
4287 : // The minimum legal codepoint, 0x00.
4288 1 : tt_int_op(1, OP_EQ, string_is_utf8("\0", 1));
4289 :
4290 : // The maximum legal codepoint, 0x10FFFF.
4291 1 : tt_int_op(1, OP_EQ, string_is_utf8("\xf4\x8f\xbf\xbf", 4));
4292 1 : tt_int_op(0, OP_EQ, string_is_utf8("\xf4\x90\x80\x80", 4));
4293 :
4294 : /* Test cases that vary between programming languages /
4295 : * UTF-8 implementations.
4296 : * Source: POC||GTFO 19, page 43
4297 : * https://www.alchemistowl.org/pocorgtfo/
4298 : */
4299 :
4300 : // Invalid (in most implementations)
4301 : // surrogate
4302 1 : tt_int_op(0, OP_EQ, string_is_utf8("\xed\xa0\x81", 3));
4303 : // nullsurrog
4304 1 : tt_int_op(0, OP_EQ, string_is_utf8("\x30\x00\xed\xa0\x81", 5));
4305 : // threehigh
4306 1 : tt_int_op(0, OP_EQ, string_is_utf8("\xed\xbf\xbf", 3));
4307 : // fourhigh
4308 1 : tt_int_op(0, OP_EQ, string_is_utf8("\xf4\x90\xbf\xbf", 4));
4309 : // fivebyte
4310 1 : tt_int_op(0, OP_EQ, string_is_utf8("\xfb\x80\x80\x80\x80", 5));
4311 : // sixbyte
4312 1 : tt_int_op(0, OP_EQ, string_is_utf8("\xfd\x80\x80\x80\x80", 5));
4313 : // sixhigh
4314 1 : tt_int_op(0, OP_EQ, string_is_utf8("\xfd\xbf\xbf\xbf\xbf", 5));
4315 :
4316 : // Valid (in most implementations)
4317 : // fourbyte
4318 1 : tt_int_op(1, OP_EQ, string_is_utf8("\xf0\x90\x8d\x88", 4));
4319 : // fourbyte2
4320 1 : tt_int_op(1, OP_EQ, string_is_utf8("\xf0\xbf\xbf\xbf", 4));
4321 : // nullbyte
4322 1 : tt_int_op(1, OP_EQ, string_is_utf8("\x30\x31\x32\x00\x33", 5));
4323 :
4324 1 : done:
4325 1 : ;
4326 1 : }
4327 :
4328 : static void
4329 1 : test_util_asprintf(void *ptr)
4330 : {
4331 : #define LOREMIPSUM \
4332 : "Lorem ipsum dolor sit amet, consectetur adipisicing elit"
4333 1 : char *cp=NULL, *cp2=NULL;
4334 1 : int r;
4335 1 : (void)ptr;
4336 :
4337 : /* simple string */
4338 1 : r = tor_asprintf(&cp, "simple string 100%% safe");
4339 1 : tt_assert(cp);
4340 1 : tt_str_op("simple string 100% safe",OP_EQ, cp);
4341 1 : tt_int_op(strlen(cp),OP_EQ, r);
4342 1 : tor_free(cp);
4343 :
4344 : /* empty string */
4345 1 : r = tor_asprintf(&cp, "%s", "");
4346 1 : tt_assert(cp);
4347 1 : tt_str_op("",OP_EQ, cp);
4348 1 : tt_int_op(strlen(cp),OP_EQ, r);
4349 1 : tor_free(cp);
4350 :
4351 : /* numbers (%i) */
4352 1 : r = tor_asprintf(&cp, "I like numbers-%2i, %i, etc.", -1, 2);
4353 1 : tt_assert(cp);
4354 1 : tt_str_op("I like numbers--1, 2, etc.",OP_EQ, cp);
4355 1 : tt_int_op(strlen(cp),OP_EQ, r);
4356 : /* don't free cp; next test uses it. */
4357 :
4358 : /* numbers (%d) */
4359 1 : r = tor_asprintf(&cp2, "First=%d, Second=%d", 101, 202);
4360 1 : tt_assert(cp2);
4361 1 : tt_int_op(strlen(cp2),OP_EQ, r);
4362 1 : tt_str_op("First=101, Second=202",OP_EQ, cp2);
4363 1 : tt_assert(cp != cp2);
4364 1 : tor_free(cp);
4365 1 : tor_free(cp2);
4366 :
4367 : /* Glass-box test: a string exactly 128 characters long. */
4368 1 : r = tor_asprintf(&cp, "Lorem1: %sLorem2: %s", LOREMIPSUM, LOREMIPSUM);
4369 1 : tt_assert(cp);
4370 1 : tt_int_op(128,OP_EQ, r);
4371 1 : tt_int_op(cp[128], OP_EQ, '\0');
4372 1 : tt_str_op("Lorem1: "LOREMIPSUM"Lorem2: "LOREMIPSUM,OP_EQ, cp);
4373 1 : tor_free(cp);
4374 :
4375 : /* String longer than 128 characters */
4376 1 : r = tor_asprintf(&cp, "1: %s 2: %s 3: %s",
4377 : LOREMIPSUM, LOREMIPSUM, LOREMIPSUM);
4378 1 : tt_assert(cp);
4379 1 : tt_int_op(strlen(cp),OP_EQ, r);
4380 1 : tt_str_op("1: "LOREMIPSUM" 2: "LOREMIPSUM" 3: "LOREMIPSUM,OP_EQ, cp);
4381 :
4382 1 : done:
4383 1 : tor_free(cp);
4384 1 : tor_free(cp2);
4385 1 : }
4386 :
4387 : static void
4388 1 : test_util_listdir(void *ptr)
4389 : {
4390 1 : smartlist_t *dir_contents = NULL;
4391 1 : char *fname1=NULL, *fname2=NULL, *fname3=NULL, *dir1=NULL, *dirname=NULL;
4392 1 : int r;
4393 1 : (void)ptr;
4394 :
4395 1 : fname1 = tor_strdup(get_fname("hopscotch"));
4396 1 : fname2 = tor_strdup(get_fname("mumblety-peg"));
4397 1 : fname3 = tor_strdup(get_fname(".hidden-file"));
4398 1 : dir1 = tor_strdup(get_fname("some-directory"));
4399 1 : dirname = tor_strdup(get_fname(NULL));
4400 :
4401 1 : tt_int_op(0,OP_EQ, write_str_to_file(fname1, "X\n", 0));
4402 1 : tt_int_op(0,OP_EQ, write_str_to_file(fname2, "Y\n", 0));
4403 1 : tt_int_op(0,OP_EQ, write_str_to_file(fname3, "Z\n", 0));
4404 : #ifdef _WIN32
4405 : r = mkdir(dir1);
4406 : #else
4407 1 : r = mkdir(dir1, 0700);
4408 : #endif
4409 1 : if (r) {
4410 0 : fprintf(stderr, "Can't create directory %s:", dir1);
4411 0 : perror("");
4412 0 : exit(1);
4413 : }
4414 :
4415 1 : dir_contents = tor_listdir(dirname);
4416 1 : tt_assert(dir_contents);
4417 : /* make sure that each filename is listed. */
4418 1 : tt_assert(smartlist_contains_string_case(dir_contents, "hopscotch"));
4419 1 : tt_assert(smartlist_contains_string_case(dir_contents, "mumblety-peg"));
4420 1 : tt_assert(smartlist_contains_string_case(dir_contents, ".hidden-file"));
4421 1 : tt_assert(smartlist_contains_string_case(dir_contents, "some-directory"));
4422 :
4423 1 : tt_assert(!smartlist_contains_string(dir_contents, "."));
4424 1 : tt_assert(!smartlist_contains_string(dir_contents, ".."));
4425 :
4426 1 : done:
4427 1 : tor_free(fname1);
4428 1 : tor_free(fname2);
4429 1 : tor_free(fname3);
4430 1 : tor_free(dir1);
4431 1 : tor_free(dirname);
4432 1 : if (dir_contents) {
4433 6 : SMARTLIST_FOREACH(dir_contents, char *, cp, tor_free(cp));
4434 1 : smartlist_free(dir_contents);
4435 : }
4436 1 : }
4437 :
4438 : static void
4439 1 : test_util_glob(void *ptr)
4440 : {
4441 1 : (void)ptr;
4442 :
4443 : #ifdef HAVE_GLOB
4444 1 : smartlist_t *results = NULL;
4445 1 : int r, i;
4446 1 : char *dir1 = NULL, *dir2 = NULL, *forbidden = NULL, *dirname = NULL;
4447 1 : char *expected = NULL, *pattern = NULL;
4448 : // used for cleanup
4449 1 : char *dir1_forbidden = NULL, *dir2_forbidden = NULL;
4450 1 : char *forbidden_forbidden = NULL;
4451 :
4452 1 : dirname = tor_strdup(get_fname("test_glob"));
4453 1 : tt_ptr_op(dirname, OP_NE, NULL);
4454 :
4455 : #ifdef _WIN32
4456 : r = mkdir(dirname);
4457 : #else
4458 1 : r = mkdir(dirname, 0700);
4459 : #endif
4460 1 : if (r) {
4461 0 : fprintf(stderr, "Can't create directory %s:", dirname);
4462 0 : perror("");
4463 0 : exit(1);
4464 : }
4465 :
4466 1 : tt_int_op(0, OP_EQ, create_test_directory_structure(dirname));
4467 1 : tor_asprintf(&dir1, "%s"PATH_SEPARATOR"dir1", dirname);
4468 1 : tor_asprintf(&dir1_forbidden,
4469 : "%s"PATH_SEPARATOR"dir1"PATH_SEPARATOR"forbidden", dirname);
4470 1 : tt_int_op(0, OP_EQ, create_test_directory_structure(dir1));
4471 1 : tor_asprintf(&dir2, "%s"PATH_SEPARATOR"dir2", dirname);
4472 1 : tor_asprintf(&dir2_forbidden,
4473 : "%s"PATH_SEPARATOR"dir2"PATH_SEPARATOR"forbidden", dirname);
4474 1 : tt_int_op(0, OP_EQ, create_test_directory_structure(dir2));
4475 1 : tor_asprintf(&forbidden, "%s"PATH_SEPARATOR"forbidden", dirname);
4476 1 : tor_asprintf(&forbidden_forbidden,
4477 : "%s"PATH_SEPARATOR"forbidden"PATH_SEPARATOR"forbidden",dirname);
4478 : #ifndef _WIN32
4479 1 : tt_int_op(0, OP_EQ, chmod(forbidden, 0700));
4480 : #endif
4481 1 : tt_int_op(0, OP_EQ, create_test_directory_structure(forbidden));
4482 : #ifndef _WIN32
4483 1 : tt_int_op(0, OP_EQ, chmod(forbidden, 0));
4484 : #endif
4485 :
4486 : #define TEST(input) \
4487 : do { \
4488 : tor_asprintf(&pattern, "%s"PATH_SEPARATOR"%s", dirname, input); \
4489 : results = tor_glob(pattern); \
4490 : tor_free(pattern); \
4491 : tt_assert(results); \
4492 : smartlist_sort_strings(results); \
4493 : } while (0);
4494 :
4495 : #define EXPECT(result) \
4496 : do { \
4497 : tt_int_op(smartlist_len(results), OP_EQ, \
4498 : sizeof(result)/sizeof(*result)); \
4499 : i = 0; \
4500 : SMARTLIST_FOREACH_BEGIN(results, const char *, f) { \
4501 : tor_asprintf(&expected, "%s"PATH_SEPARATOR"%s", dirname, result[i]); \
4502 : tt_str_op(f, OP_EQ, expected); \
4503 : i++; \
4504 : tor_free(expected); \
4505 : } SMARTLIST_FOREACH_END(f); \
4506 : SMARTLIST_FOREACH(results, char *, f, tor_free(f)); \
4507 : smartlist_free(results); \
4508 : } while (0);
4509 :
4510 : #define EXPECT_EMPTY() \
4511 : do { \
4512 : tt_int_op(smartlist_len(results), OP_EQ, 0); \
4513 : SMARTLIST_FOREACH(results, char *, f, tor_free(f)); \
4514 : smartlist_free(results); \
4515 : } while (0);
4516 :
4517 : // wildcards at beginning
4518 1 : const char *results_test1[] = {"dir2", "file2"};
4519 1 : TEST("*2");
4520 5 : EXPECT(results_test1);
4521 :
4522 : // wildcards at end
4523 1 : const char *results_test2[] = {"dir1", "dir2"};
4524 1 : TEST("d*");
4525 5 : EXPECT(results_test2);
4526 :
4527 : // wildcards at beginning and end
4528 : #ifdef _WIN32
4529 : // dot files are not ignored on Windows
4530 : const char *results_test3[] = {".test-hidden", "dir1", "dir2", "file1",
4531 : "file2", "forbidden"};
4532 : #else
4533 1 : const char *results_test3[] = {"dir1", "dir2", "file1", "file2",
4534 : "forbidden"};
4535 : #endif /* defined(_WIN32) */
4536 1 : TEST("*i*");
4537 11 : EXPECT(results_test3);
4538 :
4539 : // wildcards in middle
4540 1 : const char *results_test4[] = {"dir1", "dir2"};
4541 1 : TEST("d?r*");
4542 5 : EXPECT(results_test4);
4543 :
4544 : // test file that does not exist
4545 1 : TEST("not-exist");
4546 1 : EXPECT_EMPTY();
4547 :
4548 : // test wildcard that matches nothing
4549 1 : TEST("*not-exist*");
4550 1 : EXPECT_EMPTY();
4551 :
4552 : // test path separator at end - no wildcards
4553 1 : const char *results_test7[] = {"dir1"};
4554 1 : TEST("dir1");
4555 3 : EXPECT(results_test7);
4556 :
4557 1 : const char *results_test8[] = {"dir1"};
4558 1 : TEST("dir1"PATH_SEPARATOR);
4559 3 : EXPECT(results_test8);
4560 :
4561 1 : const char *results_test9[] = {"file1"};
4562 1 : TEST("file1");
4563 3 : EXPECT(results_test9);
4564 :
4565 1 : TEST("file1"PATH_SEPARATOR);
4566 1 : EXPECT_EMPTY();
4567 :
4568 : // test path separator at end - with wildcards and linux path separator
4569 1 : const char *results_test11[] = {"dir1", "dir2", "forbidden"};
4570 1 : TEST("*/");
4571 7 : EXPECT(results_test11);
4572 :
4573 : #ifdef _WIN32
4574 : // dot files are not ignored on Windows
4575 : const char *results_test12[] = {".test-hidden", "dir1", "dir2", "empty",
4576 : "file1", "file2", "forbidden"};
4577 : #else
4578 1 : const char *results_test12[] = {"dir1", "dir2", "empty", "file1", "file2",
4579 : "forbidden"};
4580 : #endif /* defined(_WIN32) */
4581 1 : TEST("*");
4582 13 : EXPECT(results_test12);
4583 :
4584 : // wildcards on folder and file and linux path separator
4585 1 : const char *results_test13[] = {"dir1"PATH_SEPARATOR"dir1",
4586 : "dir1"PATH_SEPARATOR"dir2",
4587 : "dir1"PATH_SEPARATOR"file1",
4588 : "dir1"PATH_SEPARATOR"file2",
4589 : "dir2"PATH_SEPARATOR"dir1",
4590 : "dir2"PATH_SEPARATOR"dir2",
4591 : "dir2"PATH_SEPARATOR"file1",
4592 : "dir2"PATH_SEPARATOR"file2"};
4593 1 : TEST("?i*/?i*");
4594 17 : EXPECT(results_test13);
4595 :
4596 : // wildcards on file only
4597 1 : const char *results_test14[] = {"dir1"PATH_SEPARATOR"dir1",
4598 : "dir1"PATH_SEPARATOR"dir2",
4599 : "dir1"PATH_SEPARATOR"file1",
4600 : "dir1"PATH_SEPARATOR"file2"};
4601 1 : TEST("dir1"PATH_SEPARATOR"?i*");
4602 9 : EXPECT(results_test14);
4603 :
4604 : // wildcards on folder only
4605 1 : const char *results_test15[] = {"dir1"PATH_SEPARATOR"file1",
4606 : "dir2"PATH_SEPARATOR"file1"};
4607 1 : TEST("?i*"PATH_SEPARATOR"file1");
4608 5 : EXPECT(results_test15);
4609 :
4610 : // wildcards after file name
4611 1 : TEST("file1"PATH_SEPARATOR"*");
4612 1 : EXPECT_EMPTY();
4613 :
4614 : #ifndef _WIN32
4615 : // test wildcard escaping
4616 1 : TEST("\\*");
4617 1 : EXPECT_EMPTY();
4618 :
4619 1 : if (getuid() != 0) {
4620 : // test forbidden directory, if we're not root.
4621 : // (Root will be able to see this directory anyway.)
4622 1 : tor_asprintf(&pattern, "%s"PATH_SEPARATOR"*"PATH_SEPARATOR"*", dirname);
4623 1 : results = tor_glob(pattern);
4624 1 : tor_free(pattern);
4625 1 : tt_assert(!results);
4626 : }
4627 : #endif /* !defined(_WIN32) */
4628 :
4629 : #undef TEST
4630 : #undef EXPECT
4631 : #undef EXPECT_EMPTY
4632 :
4633 1 : done:
4634 : #ifndef _WIN32
4635 1 : (void) chmod(forbidden, 0700);
4636 1 : (void) chmod(dir1_forbidden, 0700);
4637 1 : (void) chmod(dir2_forbidden, 0700);
4638 1 : (void) chmod(forbidden_forbidden, 0700);
4639 : #endif /* !defined(_WIN32) */
4640 1 : tor_free(dir1);
4641 1 : tor_free(dir2);
4642 1 : tor_free(forbidden);
4643 1 : tor_free(dirname);
4644 1 : tor_free(dir1_forbidden);
4645 1 : tor_free(dir2_forbidden);
4646 1 : tor_free(forbidden_forbidden);
4647 1 : tor_free(expected);
4648 1 : tor_free(pattern);
4649 1 : if (results) {
4650 0 : SMARTLIST_FOREACH(results, char *, f, tor_free(f));
4651 0 : smartlist_free(results);
4652 : }
4653 : #else /* !defined(HAVE_GLOB) */
4654 : tt_skip();
4655 : done:
4656 : return;
4657 : #endif /* defined(HAVE_GLOB) */
4658 1 : }
4659 :
4660 : static void
4661 1 : test_util_get_glob_opened_files(void *ptr)
4662 : {
4663 1 : (void)ptr;
4664 :
4665 : #ifdef HAVE_GLOB
4666 1 : smartlist_t *results = NULL;
4667 1 : int r, i;
4668 1 : char *dir1 = NULL, *dir2 = NULL, *forbidden = NULL, *dirname = NULL;
4669 1 : char *expected = NULL, *pattern = NULL;
4670 : // used for cleanup
4671 1 : char *dir1_forbidden = NULL, *dir2_forbidden = NULL;
4672 1 : char *forbidden_forbidden = NULL;
4673 :
4674 1 : dirname = tor_strdup(get_fname("test_get_glob_opened_files"));
4675 1 : tt_ptr_op(dirname, OP_NE, NULL);
4676 :
4677 : #ifdef _WIN32
4678 : r = mkdir(dirname);
4679 : #else
4680 1 : r = mkdir(dirname, 0700);
4681 : #endif
4682 1 : if (r) {
4683 0 : fprintf(stderr, "Can't create directory %s:", dirname);
4684 0 : perror("");
4685 0 : exit(1);
4686 : }
4687 :
4688 1 : tt_int_op(0, OP_EQ, create_test_directory_structure(dirname));
4689 1 : tor_asprintf(&dir1, "%s"PATH_SEPARATOR"dir1", dirname);
4690 1 : tor_asprintf(&dir1_forbidden,
4691 : "%s"PATH_SEPARATOR"dir1"PATH_SEPARATOR"forbidden", dirname);
4692 1 : tt_int_op(0, OP_EQ, create_test_directory_structure(dir1));
4693 1 : tor_asprintf(&dir2, "%s"PATH_SEPARATOR"dir2", dirname);
4694 1 : tor_asprintf(&dir2_forbidden,
4695 : "%s"PATH_SEPARATOR"dir2"PATH_SEPARATOR"forbidden", dirname);
4696 1 : tt_int_op(0, OP_EQ, create_test_directory_structure(dir2));
4697 1 : tor_asprintf(&forbidden, "%s"PATH_SEPARATOR"forbidden", dirname);
4698 1 : tor_asprintf(&forbidden_forbidden,
4699 : "%s"PATH_SEPARATOR"forbidden"PATH_SEPARATOR"forbidden",dirname);
4700 : #ifndef _WIN32
4701 1 : chmod(forbidden, 0700);
4702 : #endif
4703 1 : tt_int_op(0, OP_EQ, create_test_directory_structure(forbidden));
4704 : #ifndef _WIN32
4705 1 : chmod(forbidden, 0);
4706 : #endif
4707 :
4708 : #define TEST(input) \
4709 : do { \
4710 : if (*input) { \
4711 : tor_asprintf(&pattern, "%s"PATH_SEPARATOR"%s", dirname, input); \
4712 : } else { /* do not add path separator if empty string */ \
4713 : tor_asprintf(&pattern, "%s", dirname); \
4714 : } \
4715 : results = get_glob_opened_files(pattern); \
4716 : tor_free(pattern); \
4717 : tt_assert(results); \
4718 : smartlist_sort_strings(results); \
4719 : } while (0);
4720 :
4721 : #define EXPECT(result) \
4722 : do { \
4723 : tt_int_op(smartlist_len(results), OP_EQ, \
4724 : sizeof(result)/sizeof(*result)); \
4725 : i = 0; \
4726 : SMARTLIST_FOREACH_BEGIN(results, const char *, f) { \
4727 : if (*result[i]) { \
4728 : tor_asprintf(&expected, "%s"PATH_SEPARATOR"%s", dirname, result[i]); \
4729 : } else { /* do not add path separator if empty string */ \
4730 : tor_asprintf(&expected, "%s", dirname); \
4731 : } \
4732 : tt_str_op(f, OP_EQ, expected); \
4733 : i++; \
4734 : tor_free(expected); \
4735 : } SMARTLIST_FOREACH_END(f); \
4736 : SMARTLIST_FOREACH(results, char *, f, tor_free(f)); \
4737 : smartlist_free(results); \
4738 : } while (0);
4739 :
4740 : #define EXPECT_EMPTY() \
4741 : do { \
4742 : tt_int_op(smartlist_len(results), OP_EQ, 0); \
4743 : SMARTLIST_FOREACH(results, char *, f, tor_free(f)); \
4744 : smartlist_free(results); \
4745 : } while (0);
4746 :
4747 : // all files on folder
4748 1 : const char *results_test1[] = {""}; // only the folder is read
4749 1 : TEST("*");
4750 3 : EXPECT(results_test1);
4751 :
4752 : // same as before but ending in path separator
4753 1 : const char *results_test2[] = {""}; // only the folder is read
4754 1 : TEST("*"PATH_SEPARATOR);
4755 3 : EXPECT(results_test2);
4756 :
4757 : // wildcards in multiple path components
4758 : #ifndef _WIN32
4759 1 : const char *results_test3[] = {"", "dir1", "dir2", "empty", "file1", "file2",
4760 : "forbidden"};
4761 : #else
4762 : // dot files are not special on windows
4763 : const char *results_test3[] = {"", ".test-hidden", "dir1", "dir2", "empty",
4764 : "file1", "file2", "forbidden"};
4765 : #endif /* !defined(_WIN32) */
4766 1 : TEST("*"PATH_SEPARATOR"*");
4767 15 : EXPECT(results_test3);
4768 :
4769 : // same as before but ending in path separator
4770 : #ifndef _WIN32
4771 1 : const char *results_test4[] = {"", "dir1", "dir2", "empty", "file1", "file2",
4772 : "forbidden"};
4773 : #else
4774 : // dot files are not special on windows
4775 : const char *results_test4[] = {"", ".test-hidden", "dir1", "dir2", "empty",
4776 : "file1", "file2", "forbidden"};
4777 : #endif /* !defined(_WIN32) */
4778 1 : TEST("*"PATH_SEPARATOR"*"PATH_SEPARATOR);
4779 15 : EXPECT(results_test4);
4780 :
4781 : // no glob - folder
4782 1 : TEST("");
4783 1 : EXPECT_EMPTY();
4784 :
4785 : // same as before but ending in path separator
4786 1 : TEST(PATH_SEPARATOR);
4787 1 : EXPECT_EMPTY();
4788 :
4789 : // no glob - file
4790 1 : TEST("file1");
4791 1 : EXPECT_EMPTY();
4792 :
4793 : // same as before but ending in path separator and linux path separator
4794 1 : TEST("file1/");
4795 1 : EXPECT_EMPTY();
4796 :
4797 : // file but with wildcard after
4798 1 : const char *results_test9[] = {"file1"};
4799 1 : TEST("file1"PATH_SEPARATOR"*");
4800 3 : EXPECT(results_test9);
4801 :
4802 : // dir inside dir and linux path separator
4803 1 : TEST("dir1/dir1");
4804 1 : EXPECT_EMPTY();
4805 :
4806 : // same as before but ending in path separator
4807 1 : TEST("dir1"PATH_SEPARATOR"dir1"PATH_SEPARATOR);
4808 1 : EXPECT_EMPTY();
4809 :
4810 : // no glob - empty
4811 1 : TEST("empty");
4812 1 : EXPECT_EMPTY();
4813 :
4814 : // same as before but ending in path separator
4815 1 : TEST("empty"PATH_SEPARATOR);
4816 1 : EXPECT_EMPTY();
4817 :
4818 : // no glob - does not exist
4819 1 : TEST("not_exist");
4820 1 : EXPECT_EMPTY();
4821 :
4822 : #undef TEST
4823 : #undef EXPECT
4824 : #undef EXPECT_EMPTY
4825 :
4826 1 : done:
4827 : #ifndef _WIN32
4828 : {
4829 1 : int chmod_failed = 0;
4830 1 : if (forbidden)
4831 1 : chmod_failed |= chmod(forbidden, 0700);
4832 1 : if (dir1_forbidden)
4833 1 : chmod_failed |= chmod(dir1_forbidden, 0700);
4834 1 : if (dir2_forbidden)
4835 1 : chmod_failed |= chmod(dir2_forbidden, 0700);
4836 1 : if (forbidden_forbidden)
4837 1 : chmod_failed |= chmod(forbidden_forbidden, 0700);
4838 1 : if (chmod_failed) {
4839 0 : TT_FAIL(("unable to chmod a file on cleanup: %s", strerror(errno)));
4840 : }
4841 : }
4842 : #endif /* !defined(_WIN32) */
4843 1 : tor_free(dir1);
4844 1 : tor_free(dir2);
4845 1 : tor_free(forbidden);
4846 1 : tor_free(dirname);
4847 1 : tor_free(dir1_forbidden);
4848 1 : tor_free(dir2_forbidden);
4849 1 : tor_free(forbidden_forbidden);
4850 1 : tor_free(expected);
4851 1 : tor_free(pattern);
4852 1 : if (results) {
4853 0 : SMARTLIST_FOREACH(results, char *, f, tor_free(f));
4854 0 : smartlist_free(results);
4855 : }
4856 : #else /* !defined(HAVE_GLOB) */
4857 : tt_skip();
4858 : done:
4859 : return;
4860 : #endif /* defined(HAVE_GLOB) */
4861 1 : }
4862 :
4863 : static void
4864 1 : test_util_parent_dir(void *ptr)
4865 : {
4866 1 : char *cp;
4867 1 : (void)ptr;
4868 :
4869 : #define T(output,expect_ok,input) \
4870 : do { \
4871 : int ok; \
4872 : cp = tor_strdup(input); \
4873 : ok = get_parent_directory(cp); \
4874 : tt_int_op(expect_ok, OP_EQ, ok); \
4875 : if (ok==0) \
4876 : tt_str_op(output, OP_EQ, cp); \
4877 : tor_free(cp); \
4878 : } while (0);
4879 :
4880 1 : T("/home/wombat", 0, "/home/wombat/knish");
4881 1 : T("/home/wombat", 0, "/home/wombat/knish/");
4882 1 : T("/home/wombat", 0, "/home/wombat/knish///");
4883 1 : T("./home/wombat", 0, "./home/wombat/knish/");
4884 1 : T("/", 0, "/home");
4885 1 : T("/", 0, "/home//");
4886 1 : T(".", 0, "./wombat");
4887 1 : T(".", 0, "./wombat/");
4888 1 : T(".", 0, "./wombat//");
4889 1 : T("wombat", 0, "wombat/foo");
4890 1 : T("wombat/..", 0, "wombat/../foo");
4891 1 : T("wombat/../", 0, "wombat/..//foo"); /* Is this correct? */
4892 1 : T("wombat/.", 0, "wombat/./foo");
4893 1 : T("wombat/./", 0, "wombat/.//foo"); /* Is this correct? */
4894 1 : T("wombat", 0, "wombat/..//");
4895 1 : T("wombat", 0, "wombat/foo/");
4896 1 : T("wombat", 0, "wombat/.foo");
4897 1 : T("wombat", 0, "wombat/.foo/");
4898 :
4899 1 : T("wombat", -1, "");
4900 1 : T("w", -1, "");
4901 1 : T("wombat", 0, "wombat/knish");
4902 :
4903 1 : T("/", 0, "/");
4904 1 : T("/", 0, "////");
4905 :
4906 1 : done:
4907 1 : tor_free(cp);
4908 1 : }
4909 :
4910 : static void
4911 1 : test_util_ftruncate(void *ptr)
4912 : {
4913 1 : char *buf = NULL;
4914 1 : const char *fname;
4915 1 : int fd = -1;
4916 1 : const char *message = "Hello world";
4917 1 : const char *message2 = "Hola mundo";
4918 1 : struct stat st;
4919 :
4920 1 : (void) ptr;
4921 :
4922 1 : fname = get_fname("ftruncate");
4923 :
4924 1 : fd = tor_open_cloexec(fname, O_WRONLY|O_CREAT, 0600);
4925 1 : tt_int_op(fd, OP_GE, 0);
4926 :
4927 : /* Make the file be there. */
4928 1 : tt_int_op(strlen(message), OP_EQ,
4929 : write_all_to_fd(fd, message, strlen(message)));
4930 1 : tt_int_op((int)tor_fd_getpos(fd), OP_EQ, strlen(message));
4931 1 : tt_int_op(0, OP_EQ, fstat(fd, &st));
4932 1 : tt_int_op((int)st.st_size, OP_EQ, strlen(message));
4933 :
4934 : /* Truncate and see if it got truncated */
4935 1 : tt_int_op(0, OP_EQ, tor_ftruncate(fd));
4936 1 : tt_int_op((int)tor_fd_getpos(fd), OP_EQ, 0);
4937 1 : tt_int_op(0, OP_EQ, fstat(fd, &st));
4938 1 : tt_int_op((int)st.st_size, OP_EQ, 0);
4939 :
4940 : /* Replace, and see if it got replaced */
4941 1 : tt_int_op(strlen(message2), OP_EQ,
4942 : write_all_to_fd(fd, message2, strlen(message2)));
4943 1 : tt_int_op((int)tor_fd_getpos(fd), OP_EQ, strlen(message2));
4944 1 : tt_int_op(0, OP_EQ, fstat(fd, &st));
4945 1 : tt_int_op((int)st.st_size, OP_EQ, strlen(message2));
4946 :
4947 1 : close(fd);
4948 1 : fd = -1;
4949 :
4950 1 : buf = read_file_to_str(fname, 0, NULL);
4951 1 : tt_str_op(message2, OP_EQ, buf);
4952 :
4953 1 : done:
4954 0 : if (fd >= 0)
4955 0 : close(fd);
4956 1 : tor_free(buf);
4957 1 : }
4958 :
4959 : static void
4960 1 : test_util_num_cpus(void *arg)
4961 : {
4962 1 : (void)arg;
4963 1 : int num = compute_num_cpus();
4964 1 : if (num < 0)
4965 0 : tt_skip();
4966 :
4967 1 : tt_int_op(num, OP_GE, 1);
4968 1 : tt_int_op(num, OP_LE, 16);
4969 :
4970 1 : done:
4971 1 : ;
4972 1 : }
4973 :
4974 : #ifdef _WIN32
4975 : static void
4976 : test_util_load_win_lib(void *ptr)
4977 : {
4978 : HANDLE h = load_windows_system_library(_T("advapi32.dll"));
4979 : (void) ptr;
4980 :
4981 : tt_assert(h);
4982 : done:
4983 : if (h)
4984 : FreeLibrary(h);
4985 : }
4986 : #endif /* defined(_WIN32) */
4987 :
4988 : /**
4989 : * Test for format_hex_number_sigsafe()
4990 : */
4991 :
4992 : static void
4993 1 : test_util_format_hex_number(void *ptr)
4994 : {
4995 1 : int i, len;
4996 1 : char buf[33];
4997 1 : const struct {
4998 : const char *str;
4999 : unsigned int x;
5000 1 : } test_data[] = {
5001 : {"0", 0},
5002 : {"1", 1},
5003 : {"273A", 0x273a},
5004 : {"FFFF", 0xffff},
5005 : {"7FFFFFFF", 0x7fffffff},
5006 : {"FFFFFFFF", 0xffffffff},
5007 : #if UINT_MAX >= 0xffffffff
5008 : {"31BC421D", 0x31bc421d},
5009 : {"FFFFFFFF", 0xffffffff},
5010 : #endif
5011 : {NULL, 0}
5012 : };
5013 :
5014 1 : (void)ptr;
5015 :
5016 9 : for (i = 0; test_data[i].str != NULL; ++i) {
5017 8 : len = format_hex_number_sigsafe(test_data[i].x, buf, sizeof(buf));
5018 8 : tt_int_op(len,OP_NE, 0);
5019 8 : tt_int_op(len,OP_EQ, strlen(buf));
5020 8 : tt_str_op(buf,OP_EQ, test_data[i].str);
5021 : }
5022 :
5023 1 : tt_int_op(4,OP_EQ, format_hex_number_sigsafe(0xffff, buf, 5));
5024 1 : tt_str_op(buf,OP_EQ, "FFFF");
5025 1 : tt_int_op(0,OP_EQ, format_hex_number_sigsafe(0xffff, buf, 4));
5026 1 : tt_int_op(0,OP_EQ, format_hex_number_sigsafe(0, buf, 1));
5027 :
5028 1 : done:
5029 1 : return;
5030 : }
5031 :
5032 : /**
5033 : * Test for format_hex_number_sigsafe()
5034 : */
5035 :
5036 : static void
5037 1 : test_util_format_dec_number(void *ptr)
5038 : {
5039 1 : int i, len;
5040 1 : char buf[33];
5041 1 : const struct {
5042 : const char *str;
5043 : unsigned int x;
5044 1 : } test_data[] = {
5045 : {"0", 0},
5046 : {"1", 1},
5047 : {"1234", 1234},
5048 : {"12345678", 12345678},
5049 : {"99999999", 99999999},
5050 : {"100000000", 100000000},
5051 : {"4294967295", 4294967295u},
5052 : #if UINT_MAX > 0xffffffff
5053 : {"18446744073709551615", 18446744073709551615u },
5054 : #endif
5055 : {NULL, 0}
5056 : };
5057 :
5058 1 : (void)ptr;
5059 :
5060 8 : for (i = 0; test_data[i].str != NULL; ++i) {
5061 7 : len = format_dec_number_sigsafe(test_data[i].x, buf, sizeof(buf));
5062 7 : tt_int_op(len,OP_NE, 0);
5063 7 : tt_int_op(len,OP_EQ, strlen(buf));
5064 7 : tt_str_op(buf,OP_EQ, test_data[i].str);
5065 :
5066 14 : len = format_dec_number_sigsafe(test_data[i].x, buf,
5067 7 : (int)(strlen(test_data[i].str) + 1));
5068 7 : tt_int_op(len,OP_EQ, strlen(buf));
5069 7 : tt_str_op(buf,OP_EQ, test_data[i].str);
5070 : }
5071 :
5072 1 : tt_int_op(4,OP_EQ, format_dec_number_sigsafe(7331, buf, 5));
5073 1 : tt_str_op(buf,OP_EQ, "7331");
5074 1 : tt_int_op(0,OP_EQ, format_dec_number_sigsafe(7331, buf, 4));
5075 1 : tt_int_op(1,OP_EQ, format_dec_number_sigsafe(0, buf, 2));
5076 1 : tt_int_op(0,OP_EQ, format_dec_number_sigsafe(0, buf, 1));
5077 :
5078 1 : done:
5079 1 : return;
5080 : }
5081 :
5082 : #define MAX_SPLIT_LINE_COUNT 4
5083 : struct split_lines_test_t {
5084 : const char *orig_line; // Line to be split (may contain \0's)
5085 : int orig_length; // Length of orig_line
5086 : const char *split_line[MAX_SPLIT_LINE_COUNT]; // Split lines
5087 : };
5088 :
5089 : static void
5090 1 : test_util_di_ops(void *arg)
5091 : {
5092 : #define LT -1
5093 : #define GT 1
5094 : #define EQ 0
5095 1 : const struct {
5096 : const char *a; int want_sign; const char *b;
5097 1 : } examples[] = {
5098 : { "Foo", EQ, "Foo" },
5099 : { "foo", GT, "bar", },
5100 : { "foobar", EQ ,"foobar" },
5101 : { "foobar", LT, "foobaw" },
5102 : { "foobar", GT, "f00bar" },
5103 : { "foobar", GT, "boobar" },
5104 : { "", EQ, "" },
5105 : { NULL, 0, NULL },
5106 : };
5107 :
5108 1 : int i;
5109 :
5110 1 : (void)arg;
5111 8 : for (i = 0; examples[i].a; ++i) {
5112 7 : size_t len = strlen(examples[i].a);
5113 7 : int eq1, eq2, neq1, neq2, cmp1, cmp2;
5114 7 : tt_int_op(len,OP_EQ, strlen(examples[i].b));
5115 : /* We do all of the operations, with operands in both orders. */
5116 7 : eq1 = tor_memeq(examples[i].a, examples[i].b, len);
5117 7 : eq2 = tor_memeq(examples[i].b, examples[i].a, len);
5118 7 : neq1 = tor_memneq(examples[i].a, examples[i].b, len);
5119 7 : neq2 = tor_memneq(examples[i].b, examples[i].a, len);
5120 7 : cmp1 = tor_memcmp(examples[i].a, examples[i].b, len);
5121 7 : cmp2 = tor_memcmp(examples[i].b, examples[i].a, len);
5122 :
5123 : /* Check for correctness of cmp1 */
5124 7 : if (cmp1 < 0 && examples[i].want_sign != LT)
5125 0 : TT_DIE(("Assertion failed."));
5126 7 : else if (cmp1 > 0 && examples[i].want_sign != GT)
5127 0 : TT_DIE(("Assertion failed."));
5128 7 : else if (cmp1 == 0 && examples[i].want_sign != EQ)
5129 0 : TT_DIE(("Assertion failed."));
5130 :
5131 : /* Check for consistency of everything else with cmp1 */
5132 7 : tt_int_op(eq1,OP_EQ, eq2);
5133 7 : tt_int_op(neq1,OP_EQ, neq2);
5134 7 : tt_int_op(cmp1,OP_EQ, -cmp2);
5135 7 : tt_int_op(eq1,OP_EQ, cmp1 == 0);
5136 7 : tt_int_op(neq1,OP_EQ, !eq1);
5137 : }
5138 :
5139 : {
5140 1 : uint8_t zz = 0;
5141 1 : uint8_t ii = 0;
5142 1 : int z;
5143 :
5144 : /* exhaustively test tor_memeq and tor_memcmp
5145 : * against each possible single-byte numeric difference
5146 : * some arithmetic bugs only appear with certain bit patterns */
5147 257 : for (z = 0; z < 256; z++) {
5148 65792 : for (i = 0; i < 256; i++) {
5149 65536 : ii = (uint8_t)i;
5150 65536 : zz = (uint8_t)z;
5151 65536 : tt_int_op(tor_memeq(&zz, &ii, 1),OP_EQ, zz == ii);
5152 65536 : tt_int_op(tor_memcmp(&zz, &ii, 1) > 0 ? GT : EQ,OP_EQ,
5153 : zz > ii ? GT : EQ);
5154 131328 : tt_int_op(tor_memcmp(&ii, &zz, 1) < 0 ? LT : EQ,OP_EQ,
5155 : ii < zz ? LT : EQ);
5156 : }
5157 : }
5158 : }
5159 :
5160 1 : tt_int_op(1, OP_EQ, safe_mem_is_zero("", 0));
5161 1 : tt_int_op(1, OP_EQ, safe_mem_is_zero("", 1));
5162 1 : tt_int_op(0, OP_EQ, safe_mem_is_zero("a", 1));
5163 1 : tt_int_op(0, OP_EQ, safe_mem_is_zero("a", 2));
5164 1 : tt_int_op(0, OP_EQ, safe_mem_is_zero("\0a", 2));
5165 1 : tt_int_op(1, OP_EQ, safe_mem_is_zero("\0\0a", 2));
5166 1 : tt_int_op(1, OP_EQ, safe_mem_is_zero("\0\0\0\0\0\0\0\0", 8));
5167 1 : tt_int_op(1, OP_EQ, safe_mem_is_zero("\0\0\0\0\0\0\0\0a", 8));
5168 1 : tt_int_op(0, OP_EQ, safe_mem_is_zero("\0\0\0\0\0\0\0\0a", 9));
5169 :
5170 1 : done:
5171 1 : ;
5172 1 : }
5173 :
5174 : static void
5175 1 : test_util_memcpy_iftrue_timei(void *arg)
5176 : {
5177 1 : (void)arg;
5178 1 : char buf1[25];
5179 1 : char buf2[25];
5180 1 : char buf3[25];
5181 :
5182 101 : for (int i = 0; i < 100; ++i) {
5183 100 : crypto_rand(buf1, sizeof(buf1));
5184 100 : crypto_rand(buf2, sizeof(buf2));
5185 100 : memcpy(buf3, buf1, sizeof(buf1));
5186 :
5187 : /* We just copied buf1 into buf3. Now we're going to copy buf2 into buf2,
5188 : iff our coin flip comes up heads. */
5189 100 : bool coinflip = crypto_rand_int(2) == 0;
5190 :
5191 100 : memcpy_if_true_timei(coinflip, buf3, buf2, sizeof(buf3));
5192 :
5193 100 : if (coinflip) {
5194 49 : tt_mem_op(buf3, OP_EQ, buf2, sizeof(buf2));
5195 : } else {
5196 100 : tt_mem_op(buf3, OP_EQ, buf1, sizeof(buf1));
5197 : }
5198 : }
5199 1 : done:
5200 1 : ;
5201 1 : }
5202 :
5203 : static void
5204 1 : test_util_di_map(void *arg)
5205 : {
5206 1 : (void)arg;
5207 1 : di_digest256_map_t *dimap = NULL;
5208 1 : uint8_t key1[] = "Robert Anton Wilson ";
5209 1 : uint8_t key2[] = "Martin Gardner, _Fads&fallacies";
5210 1 : uint8_t key3[] = "Tom Lehrer, _Be Prepared_. ";
5211 1 : uint8_t key4[] = "Ursula Le Guin,_A Wizard of... ";
5212 :
5213 1 : char dflt_entry[] = "'You have made a good beginning', but no more";
5214 :
5215 1 : tt_int_op(32, OP_EQ, sizeof(key1));
5216 1 : tt_int_op(32, OP_EQ, sizeof(key2));
5217 1 : tt_int_op(32, OP_EQ, sizeof(key3));
5218 :
5219 1 : tt_ptr_op(dflt_entry, OP_EQ, dimap_search(dimap, key1, dflt_entry));
5220 :
5221 1 : char *str1 = tor_strdup("You are precisely as big as what you love"
5222 : " and precisely as small as what you allow"
5223 : " to annoy you.");
5224 1 : char *str2 = tor_strdup("Let us hope that Lysenko's success in Russia will"
5225 : " serve for many generations to come as another"
5226 : " reminder to the world of how quickly and easily"
5227 : " a science can be corrupted when ignorant"
5228 : " political leaders deem themselves competent"
5229 : " to arbitrate scientific disputes");
5230 1 : char *str3 = tor_strdup("Don't write naughty words on walls "
5231 : "if you can't spell.");
5232 :
5233 1 : dimap_add_entry(&dimap, key1, str1);
5234 1 : dimap_add_entry(&dimap, key2, str2);
5235 1 : dimap_add_entry(&dimap, key3, str3);
5236 :
5237 1 : tt_ptr_op(str1, OP_EQ, dimap_search(dimap, key1, dflt_entry));
5238 1 : tt_ptr_op(str3, OP_EQ, dimap_search(dimap, key3, dflt_entry));
5239 1 : tt_ptr_op(str2, OP_EQ, dimap_search(dimap, key2, dflt_entry));
5240 1 : tt_ptr_op(dflt_entry, OP_EQ, dimap_search(dimap, key4, dflt_entry));
5241 :
5242 1 : done:
5243 1 : dimap_free(dimap, tor_free_);
5244 1 : }
5245 :
5246 : /**
5247 : * Test counting high bits
5248 : */
5249 : static void
5250 1 : test_util_n_bits_set(void *ptr)
5251 : {
5252 1 : (void)ptr;
5253 1 : tt_int_op(0,OP_EQ, n_bits_set_u8(0));
5254 1 : tt_int_op(1,OP_EQ, n_bits_set_u8(1));
5255 1 : tt_int_op(3,OP_EQ, n_bits_set_u8(7));
5256 1 : tt_int_op(1,OP_EQ, n_bits_set_u8(8));
5257 1 : tt_int_op(2,OP_EQ, n_bits_set_u8(129));
5258 1 : tt_int_op(8,OP_EQ, n_bits_set_u8(255));
5259 1 : done:
5260 1 : ;
5261 1 : }
5262 :
5263 : /**
5264 : * Test LHS whitespace (and comment) eater
5265 : */
5266 : static void
5267 1 : test_util_eat_whitespace(void *ptr)
5268 : {
5269 1 : const char ws[] = { ' ', '\t', '\r' }; /* Except NL */
5270 1 : char str[80];
5271 1 : size_t i;
5272 :
5273 1 : (void)ptr;
5274 :
5275 : /* Try one leading ws */
5276 1 : strlcpy(str, "fuubaar", sizeof(str));
5277 5 : for (i = 0; i < sizeof(ws); ++i) {
5278 3 : str[0] = ws[i];
5279 3 : tt_ptr_op(str + 1,OP_EQ, eat_whitespace(str));
5280 3 : tt_ptr_op(str + 1,OP_EQ, eat_whitespace_eos(str, str + strlen(str)));
5281 3 : tt_ptr_op(str + 1,OP_EQ, eat_whitespace_no_nl(str));
5282 3 : tt_ptr_op(str + 1,OP_EQ, eat_whitespace_eos_no_nl(str, str + strlen(str)));
5283 : }
5284 1 : str[0] = '\n';
5285 1 : tt_ptr_op(str + 1,OP_EQ, eat_whitespace(str));
5286 1 : tt_ptr_op(str + 1,OP_EQ, eat_whitespace_eos(str, str + strlen(str)));
5287 1 : tt_ptr_op(str,OP_EQ, eat_whitespace_no_nl(str));
5288 1 : tt_ptr_op(str,OP_EQ, eat_whitespace_eos_no_nl(str, str + strlen(str)));
5289 :
5290 : /* Empty string */
5291 1 : strlcpy(str, "", sizeof(str));
5292 1 : tt_ptr_op(str,OP_EQ, eat_whitespace(str));
5293 1 : tt_ptr_op(str,OP_EQ, eat_whitespace_eos(str, str));
5294 1 : tt_ptr_op(str,OP_EQ, eat_whitespace_no_nl(str));
5295 1 : tt_ptr_op(str,OP_EQ, eat_whitespace_eos_no_nl(str, str));
5296 :
5297 : /* Only ws */
5298 1 : strlcpy(str, " \t\r\n", sizeof(str));
5299 1 : tt_ptr_op(str + strlen(str),OP_EQ, eat_whitespace(str));
5300 1 : tt_ptr_op(str + strlen(str),OP_EQ,
5301 : eat_whitespace_eos(str, str + strlen(str)));
5302 1 : tt_ptr_op(str + strlen(str) - 1,OP_EQ,
5303 : eat_whitespace_no_nl(str));
5304 1 : tt_ptr_op(str + strlen(str) - 1,OP_EQ,
5305 : eat_whitespace_eos_no_nl(str, str + strlen(str)));
5306 :
5307 1 : strlcpy(str, " \t\r ", sizeof(str));
5308 1 : tt_ptr_op(str + strlen(str),OP_EQ, eat_whitespace(str));
5309 1 : tt_ptr_op(str + strlen(str),OP_EQ,
5310 : eat_whitespace_eos(str, str + strlen(str)));
5311 1 : tt_ptr_op(str + strlen(str),OP_EQ, eat_whitespace_no_nl(str));
5312 1 : tt_ptr_op(str + strlen(str),OP_EQ,
5313 : eat_whitespace_eos_no_nl(str, str + strlen(str)));
5314 :
5315 : /* Multiple ws */
5316 1 : strlcpy(str, "fuubaar", sizeof(str));
5317 5 : for (i = 0; i < sizeof(ws); ++i)
5318 3 : str[i] = ws[i];
5319 1 : tt_ptr_op(str + sizeof(ws),OP_EQ, eat_whitespace(str));
5320 1 : tt_ptr_op(str + sizeof(ws),OP_EQ,
5321 : eat_whitespace_eos(str, str + strlen(str)));
5322 1 : tt_ptr_op(str + sizeof(ws),OP_EQ, eat_whitespace_no_nl(str));
5323 1 : tt_ptr_op(str + sizeof(ws),OP_EQ,
5324 : eat_whitespace_eos_no_nl(str, str + strlen(str)));
5325 :
5326 : /* Eat comment */
5327 1 : strlcpy(str, "# Comment \n No Comment", sizeof(str));
5328 1 : tt_str_op("No Comment",OP_EQ, eat_whitespace(str));
5329 1 : tt_str_op("No Comment",OP_EQ, eat_whitespace_eos(str, str + strlen(str)));
5330 1 : tt_ptr_op(str,OP_EQ, eat_whitespace_no_nl(str));
5331 1 : tt_ptr_op(str,OP_EQ, eat_whitespace_eos_no_nl(str, str + strlen(str)));
5332 :
5333 : /* Eat comment & ws mix */
5334 1 : strlcpy(str, " # \t Comment \n\t\nNo Comment", sizeof(str));
5335 1 : tt_str_op("No Comment",OP_EQ, eat_whitespace(str));
5336 1 : tt_str_op("No Comment",OP_EQ, eat_whitespace_eos(str, str + strlen(str)));
5337 1 : tt_ptr_op(str + 1,OP_EQ, eat_whitespace_no_nl(str));
5338 1 : tt_ptr_op(str + 1,OP_EQ, eat_whitespace_eos_no_nl(str, str + strlen(str)));
5339 :
5340 : /* Eat entire comment */
5341 1 : strlcpy(str, "#Comment", sizeof(str));
5342 1 : tt_ptr_op(str + strlen(str),OP_EQ, eat_whitespace(str));
5343 1 : tt_ptr_op(str + strlen(str),OP_EQ,
5344 : eat_whitespace_eos(str, str + strlen(str)));
5345 1 : tt_ptr_op(str,OP_EQ, eat_whitespace_no_nl(str));
5346 1 : tt_ptr_op(str,OP_EQ, eat_whitespace_eos_no_nl(str, str + strlen(str)));
5347 :
5348 : /* Blank line, then comment */
5349 1 : strlcpy(str, " \t\n # Comment", sizeof(str));
5350 1 : tt_ptr_op(str + strlen(str),OP_EQ, eat_whitespace(str));
5351 1 : tt_ptr_op(str + strlen(str),OP_EQ,
5352 : eat_whitespace_eos(str, str + strlen(str)));
5353 1 : tt_ptr_op(str + 2,OP_EQ, eat_whitespace_no_nl(str));
5354 1 : tt_ptr_op(str + 2,OP_EQ, eat_whitespace_eos_no_nl(str, str + strlen(str)));
5355 :
5356 1 : done:
5357 1 : ;
5358 1 : }
5359 :
5360 : /** Return a newly allocated smartlist containing the lines of text in
5361 : * <b>lines</b>. The returned strings are heap-allocated, and must be
5362 : * freed by the caller.
5363 : *
5364 : * XXXX? Move to container.[hc] ? */
5365 : static smartlist_t *
5366 8 : smartlist_new_from_text_lines(const char *lines)
5367 : {
5368 8 : smartlist_t *sl = smartlist_new();
5369 8 : char *last_line;
5370 :
5371 8 : smartlist_split_string(sl, lines, "\n", 0, 0);
5372 :
5373 8 : last_line = smartlist_pop_last(sl);
5374 8 : if (last_line != NULL && *last_line != '\0') {
5375 2 : smartlist_add(sl, last_line);
5376 : } else {
5377 6 : tor_free(last_line);
5378 : }
5379 :
5380 8 : return sl;
5381 : }
5382 :
5383 : /** Test smartlist_new_from_text_lines */
5384 : static void
5385 1 : test_util_sl_new_from_text_lines(void *ptr)
5386 : {
5387 1 : (void)ptr;
5388 :
5389 : { /* Normal usage */
5390 1 : smartlist_t *sl = smartlist_new_from_text_lines("foo\nbar\nbaz\n");
5391 1 : int sl_len = smartlist_len(sl);
5392 :
5393 1 : tt_want_int_op(sl_len, OP_EQ, 3);
5394 :
5395 1 : if (sl_len > 0) tt_want_str_op(smartlist_get(sl, 0), OP_EQ, "foo");
5396 1 : if (sl_len > 1) tt_want_str_op(smartlist_get(sl, 1), OP_EQ, "bar");
5397 1 : if (sl_len > 2) tt_want_str_op(smartlist_get(sl, 2), OP_EQ, "baz");
5398 :
5399 4 : SMARTLIST_FOREACH(sl, void *, x, tor_free(x));
5400 1 : smartlist_free(sl);
5401 : }
5402 :
5403 : { /* No final newline */
5404 1 : smartlist_t *sl = smartlist_new_from_text_lines("foo\nbar\nbaz");
5405 1 : int sl_len = smartlist_len(sl);
5406 :
5407 1 : tt_want_int_op(sl_len, OP_EQ, 3);
5408 :
5409 1 : if (sl_len > 0) tt_want_str_op(smartlist_get(sl, 0), OP_EQ, "foo");
5410 1 : if (sl_len > 1) tt_want_str_op(smartlist_get(sl, 1), OP_EQ, "bar");
5411 1 : if (sl_len > 2) tt_want_str_op(smartlist_get(sl, 2), OP_EQ, "baz");
5412 :
5413 4 : SMARTLIST_FOREACH(sl, void *, x, tor_free(x));
5414 1 : smartlist_free(sl);
5415 : }
5416 :
5417 : { /* No newlines */
5418 1 : smartlist_t *sl = smartlist_new_from_text_lines("foo");
5419 1 : int sl_len = smartlist_len(sl);
5420 :
5421 1 : tt_want_int_op(sl_len, OP_EQ, 1);
5422 :
5423 1 : if (sl_len > 0) tt_want_str_op(smartlist_get(sl, 0), OP_EQ, "foo");
5424 :
5425 2 : SMARTLIST_FOREACH(sl, void *, x, tor_free(x));
5426 1 : smartlist_free(sl);
5427 : }
5428 :
5429 : { /* No text at all */
5430 1 : smartlist_t *sl = smartlist_new_from_text_lines("");
5431 1 : int sl_len = smartlist_len(sl);
5432 :
5433 1 : tt_want_int_op(sl_len, OP_EQ, 0);
5434 :
5435 1 : SMARTLIST_FOREACH(sl, void *, x, tor_free(x));
5436 1 : smartlist_free(sl);
5437 : }
5438 1 : }
5439 :
5440 : static void
5441 1 : test_util_envnames(void *ptr)
5442 : {
5443 1 : (void) ptr;
5444 :
5445 1 : tt_assert(environment_variable_names_equal("abc", "abc"));
5446 1 : tt_assert(environment_variable_names_equal("abc", "abc="));
5447 1 : tt_assert(environment_variable_names_equal("abc", "abc=def"));
5448 1 : tt_assert(environment_variable_names_equal("abc=def", "abc"));
5449 1 : tt_assert(environment_variable_names_equal("abc=def", "abc=ghi"));
5450 :
5451 1 : tt_assert(environment_variable_names_equal("abc", "abc"));
5452 1 : tt_assert(environment_variable_names_equal("abc", "abc="));
5453 1 : tt_assert(environment_variable_names_equal("abc", "abc=def"));
5454 1 : tt_assert(environment_variable_names_equal("abc=def", "abc"));
5455 1 : tt_assert(environment_variable_names_equal("abc=def", "abc=ghi"));
5456 :
5457 1 : tt_assert(!environment_variable_names_equal("abc", "abcd"));
5458 1 : tt_assert(!environment_variable_names_equal("abc=", "abcd"));
5459 1 : tt_assert(!environment_variable_names_equal("abc=", "abcd"));
5460 1 : tt_assert(!environment_variable_names_equal("abc=", "def"));
5461 1 : tt_assert(!environment_variable_names_equal("abc=", "def="));
5462 1 : tt_assert(!environment_variable_names_equal("abc=x", "def=x"));
5463 :
5464 1 : tt_assert(!environment_variable_names_equal("", "a=def"));
5465 : /* A bit surprising. */
5466 1 : tt_assert(environment_variable_names_equal("", "=def"));
5467 1 : tt_assert(environment_variable_names_equal("=y", "=x"));
5468 :
5469 1 : done:
5470 1 : ;
5471 1 : }
5472 :
5473 : /** Test process_environment_make */
5474 : static void
5475 1 : test_util_make_environment(void *ptr)
5476 : {
5477 1 : const char *env_vars_string =
5478 : "PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/bin\n"
5479 : "HOME=/home/foozer\n";
5480 1 : const char expected_windows_env_block[] =
5481 : "HOME=/home/foozer\000"
5482 : "PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/bin\000"
5483 : "\000";
5484 1 : size_t expected_windows_env_block_len =
5485 : sizeof(expected_windows_env_block) - 1;
5486 :
5487 1 : smartlist_t *env_vars = smartlist_new_from_text_lines(env_vars_string);
5488 1 : smartlist_t *env_vars_sorted = smartlist_new();
5489 1 : smartlist_t *env_vars_in_unixoid_env_block_sorted = smartlist_new();
5490 :
5491 1 : process_environment_t *env;
5492 :
5493 1 : (void)ptr;
5494 :
5495 1 : env = process_environment_make(env_vars);
5496 :
5497 : /* Check that the Windows environment block is correct. */
5498 1 : tt_want(tor_memeq(expected_windows_env_block, env->windows_environment_block,
5499 : expected_windows_env_block_len));
5500 :
5501 : /* Now for the Unixoid environment block. We don't care which order
5502 : * these environment variables are in, so we sort both lists first. */
5503 :
5504 1 : smartlist_add_all(env_vars_sorted, env_vars);
5505 :
5506 : {
5507 1 : char **v;
5508 3 : for (v = env->unixoid_environment_block; *v; ++v) {
5509 2 : smartlist_add(env_vars_in_unixoid_env_block_sorted, *v);
5510 : }
5511 : }
5512 :
5513 1 : smartlist_sort_strings(env_vars_sorted);
5514 1 : smartlist_sort_strings(env_vars_in_unixoid_env_block_sorted);
5515 :
5516 1 : tt_want_int_op(smartlist_len(env_vars_sorted), OP_EQ,
5517 : smartlist_len(env_vars_in_unixoid_env_block_sorted));
5518 : {
5519 1 : int len = smartlist_len(env_vars_sorted);
5520 1 : int i;
5521 :
5522 1 : if (smartlist_len(env_vars_in_unixoid_env_block_sorted) < len) {
5523 : len = smartlist_len(env_vars_in_unixoid_env_block_sorted);
5524 : }
5525 :
5526 3 : for (i = 0; i < len; ++i) {
5527 2 : tt_want_str_op(smartlist_get(env_vars_sorted, i), OP_EQ,
5528 : smartlist_get(env_vars_in_unixoid_env_block_sorted, i));
5529 : }
5530 : }
5531 :
5532 : /* Clean up. */
5533 1 : smartlist_free(env_vars_in_unixoid_env_block_sorted);
5534 1 : smartlist_free(env_vars_sorted);
5535 :
5536 3 : SMARTLIST_FOREACH(env_vars, char *, x, tor_free(x));
5537 1 : smartlist_free(env_vars);
5538 :
5539 1 : process_environment_free(env);
5540 1 : }
5541 :
5542 : /** Test set_environment_variable_in_smartlist */
5543 : static void
5544 1 : test_util_set_env_var_in_sl(void *ptr)
5545 : {
5546 : /* The environment variables in these strings are in arbitrary
5547 : * order; we sort the resulting lists before comparing them.
5548 : *
5549 : * (They *will not* end up in the order shown in
5550 : * expected_resulting_env_vars_string.) */
5551 :
5552 1 : const char *base_env_vars_string =
5553 : "PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/bin\n"
5554 : "HOME=/home/foozer\n"
5555 : "TERM=xterm\n"
5556 : "SHELL=/bin/ksh\n"
5557 : "USER=foozer\n"
5558 : "LOGNAME=foozer\n"
5559 : "USERNAME=foozer\n"
5560 : "LANG=en_US.utf8\n"
5561 : ;
5562 :
5563 1 : const char *new_env_vars_string =
5564 : "TERM=putty\n"
5565 : "DISPLAY=:18.0\n"
5566 : ;
5567 :
5568 1 : const char *expected_resulting_env_vars_string =
5569 : "PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/bin\n"
5570 : "HOME=/home/foozer\n"
5571 : "TERM=putty\n"
5572 : "SHELL=/bin/ksh\n"
5573 : "USER=foozer\n"
5574 : "LOGNAME=foozer\n"
5575 : "USERNAME=foozer\n"
5576 : "LANG=en_US.utf8\n"
5577 : "DISPLAY=:18.0\n"
5578 : ;
5579 :
5580 2 : smartlist_t *merged_env_vars =
5581 1 : smartlist_new_from_text_lines(base_env_vars_string);
5582 2 : smartlist_t *new_env_vars =
5583 1 : smartlist_new_from_text_lines(new_env_vars_string);
5584 2 : smartlist_t *expected_resulting_env_vars =
5585 1 : smartlist_new_from_text_lines(expected_resulting_env_vars_string);
5586 :
5587 : /* Elements of merged_env_vars are heap-allocated, and must be
5588 : * freed. Some of them are (or should) be freed by
5589 : * set_environment_variable_in_smartlist.
5590 : *
5591 : * Elements of new_env_vars are heap-allocated, but are copied into
5592 : * merged_env_vars, so they are not freed separately at the end of
5593 : * the function.
5594 : *
5595 : * Elements of expected_resulting_env_vars are heap-allocated, and
5596 : * must be freed. */
5597 :
5598 1 : (void)ptr;
5599 :
5600 3 : SMARTLIST_FOREACH(new_env_vars, char *, env_var,
5601 : set_environment_variable_in_smartlist(merged_env_vars,
5602 : env_var,
5603 : tor_free_,
5604 : 1));
5605 :
5606 1 : smartlist_sort_strings(merged_env_vars);
5607 1 : smartlist_sort_strings(expected_resulting_env_vars);
5608 :
5609 1 : tt_want_int_op(smartlist_len(merged_env_vars), OP_EQ,
5610 : smartlist_len(expected_resulting_env_vars));
5611 : {
5612 1 : int len = smartlist_len(merged_env_vars);
5613 1 : int i;
5614 :
5615 1 : if (smartlist_len(expected_resulting_env_vars) < len) {
5616 : len = smartlist_len(expected_resulting_env_vars);
5617 : }
5618 :
5619 10 : for (i = 0; i < len; ++i) {
5620 9 : tt_want_str_op(smartlist_get(merged_env_vars, i), OP_EQ,
5621 : smartlist_get(expected_resulting_env_vars, i));
5622 : }
5623 : }
5624 :
5625 : /* Clean up. */
5626 10 : SMARTLIST_FOREACH(merged_env_vars, char *, x, tor_free(x));
5627 1 : smartlist_free(merged_env_vars);
5628 :
5629 1 : smartlist_free(new_env_vars);
5630 :
5631 10 : SMARTLIST_FOREACH(expected_resulting_env_vars, char *, x, tor_free(x));
5632 1 : smartlist_free(expected_resulting_env_vars);
5633 1 : }
5634 :
5635 : static void
5636 1 : test_util_weak_random(void *arg)
5637 : {
5638 1 : int i, j, n[16];
5639 1 : tor_weak_rng_t rng;
5640 1 : (void) arg;
5641 :
5642 1 : tor_init_weak_random(&rng, (unsigned)time(NULL));
5643 :
5644 258 : for (i = 1; i <= 256; ++i) {
5645 25856 : for (j=0;j<100;++j) {
5646 25600 : int r = tor_weak_random_range(&rng, i);
5647 25600 : tt_int_op(0, OP_LE, r);
5648 25600 : tt_int_op(r, OP_LT, i);
5649 : }
5650 : }
5651 :
5652 1 : memset(n,0,sizeof(n));
5653 8193 : for (j=0;j<8192;++j) {
5654 8192 : n[tor_weak_random_range(&rng, 16)]++;
5655 : }
5656 :
5657 17 : for (i=0;i<16;++i)
5658 16 : tt_int_op(n[i], OP_GT, 0);
5659 1 : done:
5660 1 : ;
5661 1 : }
5662 :
5663 : static void
5664 1 : test_util_mathlog(void *arg)
5665 : {
5666 1 : double d;
5667 1 : (void) arg;
5668 :
5669 1 : d = tor_mathlog(2.718281828);
5670 1 : tt_double_op(fabs(d - 1.0), OP_LT, .000001);
5671 1 : d = tor_mathlog(10);
5672 1 : tt_double_op(fabs(d - 2.30258509), OP_LT, .000001);
5673 1 : done:
5674 1 : ;
5675 1 : }
5676 :
5677 : static void
5678 1 : test_util_fraction(void *arg)
5679 : {
5680 1 : uint64_t a,b;
5681 1 : (void)arg;
5682 :
5683 1 : a = 99; b = 30;
5684 1 : simplify_fraction64(&a,&b);
5685 1 : tt_u64_op(a, OP_EQ, 33);
5686 1 : tt_u64_op(b, OP_EQ, 10);
5687 :
5688 1 : a = 3000000; b = 10000000;
5689 1 : simplify_fraction64(&a,&b);
5690 1 : tt_u64_op(a, OP_EQ, 3);
5691 1 : tt_u64_op(b, OP_EQ, 10);
5692 :
5693 1 : a = 0; b = 15;
5694 1 : simplify_fraction64(&a,&b);
5695 1 : tt_u64_op(a, OP_EQ, 0);
5696 1 : tt_u64_op(b, OP_EQ, 1);
5697 :
5698 1 : done:
5699 1 : ;
5700 1 : }
5701 :
5702 : static void
5703 1 : test_util_round_to_next_multiple_of(void *arg)
5704 : {
5705 1 : (void)arg;
5706 :
5707 1 : tt_u64_op(round_uint64_to_next_multiple_of(0,1), OP_EQ, 0);
5708 1 : tt_u64_op(round_uint64_to_next_multiple_of(0,7), OP_EQ, 0);
5709 :
5710 1 : tt_u64_op(round_uint64_to_next_multiple_of(99,1), OP_EQ, 99);
5711 1 : tt_u64_op(round_uint64_to_next_multiple_of(99,7), OP_EQ, 105);
5712 1 : tt_u64_op(round_uint64_to_next_multiple_of(99,9), OP_EQ, 99);
5713 :
5714 1 : tt_u64_op(round_uint64_to_next_multiple_of(UINT64_MAX,2), OP_EQ,
5715 : UINT64_MAX);
5716 :
5717 1 : tt_int_op(round_uint32_to_next_multiple_of(0,1), OP_EQ, 0);
5718 1 : tt_int_op(round_uint32_to_next_multiple_of(0,7), OP_EQ, 0);
5719 :
5720 1 : tt_int_op(round_uint32_to_next_multiple_of(99,1), OP_EQ, 99);
5721 1 : tt_int_op(round_uint32_to_next_multiple_of(99,7), OP_EQ, 105);
5722 1 : tt_int_op(round_uint32_to_next_multiple_of(99,9), OP_EQ, 99);
5723 :
5724 1 : tt_int_op(round_uint32_to_next_multiple_of(UINT32_MAX,2), OP_EQ,
5725 : UINT32_MAX);
5726 :
5727 1 : tt_uint_op(round_to_next_multiple_of(0,1), OP_EQ, 0);
5728 1 : tt_uint_op(round_to_next_multiple_of(0,7), OP_EQ, 0);
5729 :
5730 1 : tt_uint_op(round_to_next_multiple_of(99,1), OP_EQ, 99);
5731 1 : tt_uint_op(round_to_next_multiple_of(99,7), OP_EQ, 105);
5732 1 : tt_uint_op(round_to_next_multiple_of(99,9), OP_EQ, 99);
5733 :
5734 1 : tt_uint_op(round_to_next_multiple_of(UINT_MAX,2), OP_EQ,
5735 : UINT_MAX);
5736 1 : done:
5737 1 : ;
5738 1 : }
5739 :
5740 : static void
5741 1 : test_util_laplace(void *arg)
5742 : {
5743 : /* Sample values produced using Python's SciPy:
5744 : *
5745 : * >>> from scipy.stats import laplace
5746 : * >>> laplace.ppf([-0.01, 0.0, 0.01, 0.5, 0.51, 0.99, 1.0, 1.01],
5747 : ... loc = 24, scale = 24)
5748 : * array([ nan, -inf, -69.88855213, 24. ,
5749 : * 24.48486498, 117.88855213, inf, nan])
5750 : */
5751 1 : const double mu = 24.0, b = 24.0;
5752 1 : const double delta_f = 15.0, epsilon = 0.3; /* b = 15.0 / 0.3 = 50.0 */
5753 1 : (void)arg;
5754 :
5755 1 : tt_i64_op(INT64_MIN, OP_EQ, sample_laplace_distribution(mu, b, 0.0));
5756 1 : tt_i64_op(-69, OP_EQ, sample_laplace_distribution(mu, b, 0.01));
5757 1 : tt_i64_op(24, OP_EQ, sample_laplace_distribution(mu, b, 0.5));
5758 1 : tt_i64_op(24, OP_EQ, sample_laplace_distribution(mu, b, 0.51));
5759 1 : tt_i64_op(117, OP_EQ, sample_laplace_distribution(mu, b, 0.99));
5760 :
5761 : /* >>> laplace.ppf([0.0, 0.1, 0.25, 0.5, 0.75, 0.9, 0.99],
5762 : * ... loc = 0, scale = 50)
5763 : * array([ -inf, -80.47189562, -34.65735903, 0. ,
5764 : * 34.65735903, 80.47189562, 195.60115027])
5765 : */
5766 1 : tt_i64_op(INT64_MIN + 20, OP_EQ,
5767 : add_laplace_noise(20, 0.0, delta_f, epsilon));
5768 :
5769 1 : tt_i64_op(-60, OP_EQ, add_laplace_noise(20, 0.1, delta_f, epsilon));
5770 1 : tt_i64_op(-14, OP_EQ, add_laplace_noise(20, 0.25, delta_f, epsilon));
5771 1 : tt_i64_op(20, OP_EQ, add_laplace_noise(20, 0.5, delta_f, epsilon));
5772 1 : tt_i64_op(54, OP_EQ, add_laplace_noise(20, 0.75, delta_f, epsilon));
5773 1 : tt_i64_op(100, OP_EQ, add_laplace_noise(20, 0.9, delta_f, epsilon));
5774 1 : tt_i64_op(215, OP_EQ, add_laplace_noise(20, 0.99, delta_f, epsilon));
5775 :
5776 : /* Test extreme values of signal with maximally negative values of noise
5777 : * 1.0000000000000002 is the smallest number > 1
5778 : * 0.0000000000000002 is the double epsilon (error when calculating near 1)
5779 : * this is approximately 1/(2^52)
5780 : * per https://en.wikipedia.org/wiki/Double_precision
5781 : * (let's not descend into the world of subnormals)
5782 : * >>> laplace.ppf([0, 0.0000000000000002], loc = 0, scale = 1)
5783 : * array([ -inf, -35.45506713])
5784 : */
5785 1 : const double noscale_df = 1.0, noscale_eps = 1.0;
5786 :
5787 1 : tt_i64_op(INT64_MIN, OP_EQ,
5788 : add_laplace_noise(0, 0.0, noscale_df, noscale_eps));
5789 :
5790 : /* is it clipped to INT64_MIN? */
5791 1 : tt_i64_op(INT64_MIN, OP_EQ,
5792 : add_laplace_noise(-1, 0.0, noscale_df, noscale_eps));
5793 1 : tt_i64_op(INT64_MIN, OP_EQ,
5794 : add_laplace_noise(INT64_MIN, 0.0,
5795 : noscale_df, noscale_eps));
5796 : /* ... even when scaled? */
5797 1 : tt_i64_op(INT64_MIN, OP_EQ,
5798 : add_laplace_noise(0, 0.0, delta_f, epsilon));
5799 1 : tt_i64_op(INT64_MIN, OP_EQ,
5800 : add_laplace_noise(0, 0.0,
5801 : DBL_MAX, 1));
5802 1 : tt_i64_op(INT64_MIN, OP_EQ,
5803 : add_laplace_noise(INT64_MIN, 0.0,
5804 : DBL_MAX, 1));
5805 :
5806 : /* does it play nice with INT64_MAX? */
5807 1 : tt_i64_op((INT64_MIN + INT64_MAX), OP_EQ,
5808 : add_laplace_noise(INT64_MAX, 0.0,
5809 : noscale_df, noscale_eps));
5810 :
5811 : /* do near-zero fractional values work? */
5812 1 : const double min_dbl_error = 0.0000000000000002;
5813 :
5814 1 : tt_i64_op(-35, OP_EQ,
5815 : add_laplace_noise(0, min_dbl_error,
5816 : noscale_df, noscale_eps));
5817 1 : tt_i64_op(INT64_MIN, OP_EQ,
5818 : add_laplace_noise(INT64_MIN, min_dbl_error,
5819 : noscale_df, noscale_eps));
5820 1 : tt_i64_op((-35 + INT64_MAX), OP_EQ,
5821 : add_laplace_noise(INT64_MAX, min_dbl_error,
5822 : noscale_df, noscale_eps));
5823 1 : tt_i64_op(INT64_MIN, OP_EQ,
5824 : add_laplace_noise(0, min_dbl_error,
5825 : DBL_MAX, 1));
5826 1 : tt_i64_op((INT64_MAX + INT64_MIN), OP_EQ,
5827 : add_laplace_noise(INT64_MAX, min_dbl_error,
5828 : DBL_MAX, 1));
5829 1 : tt_i64_op(INT64_MIN, OP_EQ,
5830 : add_laplace_noise(INT64_MIN, min_dbl_error,
5831 : DBL_MAX, 1));
5832 :
5833 : /* does it play nice with INT64_MAX? */
5834 1 : tt_i64_op((INT64_MAX - 35), OP_EQ,
5835 : add_laplace_noise(INT64_MAX, min_dbl_error,
5836 : noscale_df, noscale_eps));
5837 :
5838 : /* Test extreme values of signal with maximally positive values of noise
5839 : * 1.0000000000000002 is the smallest number > 1
5840 : * 0.9999999999999998 is the greatest number < 1 by calculation
5841 : * per https://en.wikipedia.org/wiki/Double_precision
5842 : * >>> laplace.ppf([1.0, 0.9999999999999998], loc = 0, scale = 1)
5843 : * array([inf, 35.35050621])
5844 : * but the function rejects p == 1.0, so we just use max_dbl_lt_one
5845 : */
5846 1 : const double max_dbl_lt_one = 0.9999999999999998;
5847 :
5848 : /* do near-one fractional values work? */
5849 1 : tt_i64_op(35, OP_EQ,
5850 : add_laplace_noise(0, max_dbl_lt_one, noscale_df, noscale_eps));
5851 :
5852 : /* is it clipped to INT64_MAX? */
5853 1 : tt_i64_op(INT64_MAX, OP_EQ,
5854 : add_laplace_noise(INT64_MAX - 35, max_dbl_lt_one,
5855 : noscale_df, noscale_eps));
5856 1 : tt_i64_op(INT64_MAX, OP_EQ,
5857 : add_laplace_noise(INT64_MAX - 34, max_dbl_lt_one,
5858 : noscale_df, noscale_eps));
5859 1 : tt_i64_op(INT64_MAX, OP_EQ,
5860 : add_laplace_noise(INT64_MAX, max_dbl_lt_one,
5861 : noscale_df, noscale_eps));
5862 : /* ... even when scaled? */
5863 1 : tt_i64_op(INT64_MAX, OP_EQ,
5864 : add_laplace_noise(INT64_MAX, max_dbl_lt_one,
5865 : delta_f, epsilon));
5866 1 : tt_i64_op((INT64_MIN + INT64_MAX), OP_EQ,
5867 : add_laplace_noise(INT64_MIN, max_dbl_lt_one,
5868 : DBL_MAX, 1));
5869 1 : tt_i64_op(INT64_MAX, OP_EQ,
5870 : add_laplace_noise(INT64_MAX, max_dbl_lt_one,
5871 : DBL_MAX, 1));
5872 : /* does it play nice with INT64_MIN? */
5873 1 : tt_i64_op((INT64_MIN + 35), OP_EQ,
5874 : add_laplace_noise(INT64_MIN, max_dbl_lt_one,
5875 : noscale_df, noscale_eps));
5876 :
5877 1 : done:
5878 1 : ;
5879 1 : }
5880 :
5881 : static void
5882 1 : test_util_clamp_double_to_int64(void *arg)
5883 : {
5884 1 : (void)arg;
5885 :
5886 1 : tt_i64_op(INT64_MIN, OP_EQ, clamp_double_to_int64(-INFINITY_DBL));
5887 1 : tt_i64_op(INT64_MIN, OP_EQ,
5888 : clamp_double_to_int64(-1.0 * pow(2.0, 64.0) - 1.0));
5889 1 : tt_i64_op(INT64_MIN, OP_EQ,
5890 : clamp_double_to_int64(-1.0 * pow(2.0, 63.0) - 1.0));
5891 1 : tt_i64_op(((uint64_t) -1) << 53, OP_EQ,
5892 : clamp_double_to_int64(-1.0 * pow(2.0, 53.0)));
5893 1 : tt_i64_op((((uint64_t) -1) << 53) + 1, OP_EQ,
5894 : clamp_double_to_int64(-1.0 * pow(2.0, 53.0) + 1.0));
5895 1 : tt_i64_op(-1, OP_EQ, clamp_double_to_int64(-1.0));
5896 1 : tt_i64_op(0, OP_EQ, clamp_double_to_int64(-0.9));
5897 1 : tt_i64_op(0, OP_EQ, clamp_double_to_int64(-0.1));
5898 1 : tt_i64_op(0, OP_EQ, clamp_double_to_int64(0.0));
5899 1 : tt_i64_op(0, OP_EQ, clamp_double_to_int64(NAN_DBL));
5900 1 : tt_i64_op(0, OP_EQ, clamp_double_to_int64(0.1));
5901 1 : tt_i64_op(0, OP_EQ, clamp_double_to_int64(0.9));
5902 1 : tt_i64_op(1, OP_EQ, clamp_double_to_int64(1.0));
5903 1 : tt_i64_op((((int64_t) 1) << 53) - 1, OP_EQ,
5904 : clamp_double_to_int64(pow(2.0, 53.0) - 1.0));
5905 1 : tt_i64_op(((int64_t) 1) << 53, OP_EQ,
5906 : clamp_double_to_int64(pow(2.0, 53.0)));
5907 1 : tt_i64_op(INT64_MAX, OP_EQ,
5908 : clamp_double_to_int64(pow(2.0, 63.0)));
5909 1 : tt_i64_op(INT64_MAX, OP_EQ,
5910 : clamp_double_to_int64(pow(2.0, 64.0)));
5911 1 : tt_i64_op(INT64_MAX, OP_EQ, clamp_double_to_int64(INFINITY_DBL));
5912 :
5913 1 : done:
5914 1 : ;
5915 1 : }
5916 :
5917 : #ifdef FD_CLOEXEC
5918 : #define CAN_CHECK_CLOEXEC
5919 : static int
5920 12 : fd_is_cloexec(tor_socket_t fd)
5921 : {
5922 12 : int flags = fcntl(fd, F_GETFD, 0);
5923 12 : return (flags & FD_CLOEXEC) != 0;
5924 : }
5925 : #endif /* defined(FD_CLOEXEC) */
5926 :
5927 : #ifndef _WIN32
5928 : #define CAN_CHECK_NONBLOCK
5929 : static int
5930 12 : fd_is_nonblocking(tor_socket_t fd)
5931 : {
5932 12 : int flags = fcntl(fd, F_GETFL, 0);
5933 12 : return (flags & O_NONBLOCK) != 0;
5934 : }
5935 : #endif /* !defined(_WIN32) */
5936 :
5937 : #define ERRNO_IS_EPROTO(e) (e == SOCK_ERRNO(EPROTONOSUPPORT))
5938 : #define SOCK_ERR_IS_EPROTO(s) ERRNO_IS_EPROTO(tor_socket_errno(s))
5939 :
5940 : /* Test for tor_open_socket*, using IPv4 or IPv6 depending on arg. */
5941 : static void
5942 2 : test_util_socket(void *arg)
5943 : {
5944 2 : const int domain = !strcmp(arg, "4") ? AF_INET : AF_INET6;
5945 2 : tor_socket_t fd1 = TOR_INVALID_SOCKET;
5946 2 : tor_socket_t fd2 = TOR_INVALID_SOCKET;
5947 2 : tor_socket_t fd3 = TOR_INVALID_SOCKET;
5948 2 : tor_socket_t fd4 = TOR_INVALID_SOCKET;
5949 2 : int n = get_n_open_sockets();
5950 :
5951 2 : TT_BLATHER(("Starting with %d open sockets.", n));
5952 :
5953 2 : (void)arg;
5954 :
5955 2 : fd1 = tor_open_socket_with_extensions(domain, SOCK_STREAM, 0, 0, 0);
5956 2 : int err = tor_socket_errno(fd1);
5957 2 : if (fd1 < 0 && (err == SOCK_ERRNO(EPROTONOSUPPORT) ||
5958 0 : err == SOCK_ERRNO(EAFNOSUPPORT))) {
5959 : /* Assume we're on an IPv4-only or IPv6-only system, and give up now. */
5960 0 : goto done;
5961 : }
5962 2 : fd2 = tor_open_socket_with_extensions(domain, SOCK_STREAM, 0, 0, 1);
5963 2 : tt_assert(SOCKET_OK(fd1));
5964 2 : tt_assert(SOCKET_OK(fd2));
5965 2 : tt_int_op(get_n_open_sockets(), OP_EQ, n + 2);
5966 : //fd3 = tor_open_socket_with_extensions(domain, SOCK_STREAM, 0, 1, 0);
5967 : //fd4 = tor_open_socket_with_extensions(domain, SOCK_STREAM, 0, 1, 1);
5968 2 : fd3 = tor_open_socket(domain, SOCK_STREAM, 0);
5969 2 : fd4 = tor_open_socket_nonblocking(domain, SOCK_STREAM, 0);
5970 2 : tt_assert(SOCKET_OK(fd3));
5971 2 : tt_assert(SOCKET_OK(fd4));
5972 2 : tt_int_op(get_n_open_sockets(), OP_EQ, n + 4);
5973 :
5974 : #ifdef CAN_CHECK_CLOEXEC
5975 2 : tt_int_op(fd_is_cloexec(fd1), OP_EQ, 0);
5976 2 : tt_int_op(fd_is_cloexec(fd2), OP_EQ, 0);
5977 2 : tt_int_op(fd_is_cloexec(fd3), OP_EQ, 1);
5978 2 : tt_int_op(fd_is_cloexec(fd4), OP_EQ, 1);
5979 : #endif /* defined(CAN_CHECK_CLOEXEC) */
5980 : #ifdef CAN_CHECK_NONBLOCK
5981 2 : tt_int_op(fd_is_nonblocking(fd1), OP_EQ, 0);
5982 2 : tt_int_op(fd_is_nonblocking(fd2), OP_EQ, 1);
5983 2 : tt_int_op(fd_is_nonblocking(fd3), OP_EQ, 0);
5984 2 : tt_int_op(fd_is_nonblocking(fd4), OP_EQ, 1);
5985 : #endif /* defined(CAN_CHECK_NONBLOCK) */
5986 :
5987 2 : tor_assert(tor_close_socket == tor_close_socket__real);
5988 :
5989 : /* we use close_socket__real here so that coverity can tell that we are
5990 : * really closing these sockets. */
5991 2 : tor_close_socket__real(fd1);
5992 2 : tor_close_socket__real(fd2);
5993 2 : fd1 = fd2 = TOR_INVALID_SOCKET;
5994 2 : tt_int_op(get_n_open_sockets(), OP_EQ, n + 2);
5995 2 : tor_close_socket__real(fd3);
5996 2 : tor_close_socket__real(fd4);
5997 2 : fd3 = fd4 = TOR_INVALID_SOCKET;
5998 2 : tt_int_op(get_n_open_sockets(), OP_EQ, n);
5999 :
6000 2 : done:
6001 2 : if (SOCKET_OK(fd1))
6002 0 : tor_close_socket__real(fd1);
6003 2 : if (SOCKET_OK(fd2))
6004 0 : tor_close_socket__real(fd2);
6005 2 : if (SOCKET_OK(fd3))
6006 0 : tor_close_socket__real(fd3);
6007 2 : if (SOCKET_OK(fd4))
6008 0 : tor_close_socket__real(fd4);
6009 2 : }
6010 :
6011 : #if 0
6012 : static int
6013 : is_there_a_localhost(int family)
6014 : {
6015 : tor_socket_t s;
6016 : s = tor_open_socket(family, SOCK_STREAM, IPPROTO_TCP);
6017 : tor_assert(SOCKET_OK(s));
6018 :
6019 : int result = 0;
6020 : if (family == AF_INET) {
6021 : struct sockaddr_in s_in;
6022 : memset(&s_in, 0, sizeof(s_in));
6023 : s_in.sin_family = AF_INET;
6024 : s_in.sin_addr.s_addr = htonl(0x7f000001);
6025 : s_in.sin_port = 0;
6026 :
6027 : if (bind(s, (void*)&s_in, sizeof(s_in)) == 0) {
6028 : result = 1;
6029 : }
6030 : } else if (family == AF_INET6) {
6031 : struct sockaddr_in6 sin6;
6032 : memset(&sin6, 0, sizeof(sin6));
6033 : sin6.sin6_family = AF_INET6;
6034 : sin6.sin6_addr.s6_addr[15] = 1;
6035 : sin6.sin6_port = 0;
6036 : }
6037 : tor_close_socket(s);
6038 :
6039 : return result;
6040 : }
6041 : #endif /* 0 */
6042 :
6043 : /* Test for socketpair and ersatz_socketpair(). We test them both, since
6044 : * the latter is a tolerably good way to exercise tor_accept_socket(). */
6045 : static void
6046 2 : test_util_socketpair(void *arg)
6047 : {
6048 2 : const int ersatz = !strcmp(arg, "1");
6049 2 : int (*const tor_socketpair_fn)(int, int, int, tor_socket_t[2]) =
6050 : ersatz ? tor_ersatz_socketpair : tor_socketpair;
6051 2 : int n = get_n_open_sockets();
6052 2 : tor_socket_t fds[2] = {TOR_INVALID_SOCKET, TOR_INVALID_SOCKET};
6053 2 : const int family = AF_UNIX;
6054 2 : int socketpair_result = 0;
6055 :
6056 2 : socketpair_result = tor_socketpair_fn(family, SOCK_STREAM, 0, fds);
6057 :
6058 : #ifdef __FreeBSD__
6059 : /* If there is no 127.0.0.1, tor_ersatz_socketpair will and must fail.
6060 : * Otherwise, we risk exposing a socketpair on a routable IP address. (Some
6061 : * BSD jails use a routable address for localhost. Fortunately, they have
6062 : * the real AF_UNIX socketpair.) */
6063 : if (ersatz && socketpair_result < 0) {
6064 : /* In my testing, an IPv6-only FreeBSD jail without ::1 returned EINVAL.
6065 : * Assume we're on a machine without 127.0.0.1 or ::1 and give up now. */
6066 : tt_skip();
6067 : }
6068 : #endif /* defined(__FreeBSD__) */
6069 : #ifdef ENETUNREACH
6070 2 : if (ersatz && socketpair_result == -ENETUNREACH) {
6071 : /* We can also fail with -ENETUNREACH if we have no network stack at
6072 : * all. */
6073 0 : tt_skip();
6074 : }
6075 : #endif /* defined(ENETUNREACH) */
6076 2 : tt_int_op(0, OP_EQ, socketpair_result);
6077 :
6078 2 : tt_assert(SOCKET_OK(fds[0]));
6079 2 : tt_assert(SOCKET_OK(fds[1]));
6080 2 : if (ersatz)
6081 1 : tt_int_op(get_n_open_sockets(), OP_EQ, n);
6082 : else
6083 1 : tt_int_op(get_n_open_sockets(), OP_EQ, n + 2);
6084 : #ifdef CAN_CHECK_CLOEXEC
6085 2 : tt_int_op(fd_is_cloexec(fds[0]), OP_EQ, !ersatz);
6086 2 : tt_int_op(fd_is_cloexec(fds[1]), OP_EQ, !ersatz);
6087 : #endif
6088 : #ifdef CAN_CHECK_NONBLOCK
6089 2 : tt_int_op(fd_is_nonblocking(fds[0]), OP_EQ, 0);
6090 2 : tt_int_op(fd_is_nonblocking(fds[1]), OP_EQ, 0);
6091 : #endif
6092 :
6093 2 : done:
6094 2 : if (ersatz) {
6095 1 : if (SOCKET_OK(fds[0]))
6096 1 : tor_close_socket_simple(fds[0]);
6097 1 : if (SOCKET_OK(fds[1]))
6098 1 : tor_close_socket_simple(fds[1]);
6099 : } else {
6100 1 : if (SOCKET_OK(fds[0]))
6101 1 : tor_close_socket(fds[0]);
6102 1 : if (SOCKET_OK(fds[1]))
6103 1 : tor_close_socket(fds[1]);
6104 : }
6105 2 : }
6106 :
6107 : #undef SOCKET_EPROTO
6108 :
6109 : static void
6110 1 : test_util_max_mem(void *arg)
6111 : {
6112 1 : size_t memory1, memory2;
6113 1 : int r, r2;
6114 1 : (void) arg;
6115 :
6116 1 : r = get_total_system_memory(&memory1);
6117 1 : r2 = get_total_system_memory(&memory2);
6118 1 : tt_int_op(r, OP_EQ, r2);
6119 1 : tt_uint_op(memory2, OP_EQ, memory1);
6120 :
6121 1 : TT_BLATHER(("System memory: %"TOR_PRIuSZ, (memory1)));
6122 :
6123 1 : if (r==0) {
6124 : /* You have at least a megabyte. */
6125 1 : tt_uint_op(memory1, OP_GT, (1<<20));
6126 : } else {
6127 : /* You do not have a petabyte. */
6128 : #if SIZEOF_SIZE_T >= 8
6129 0 : tt_u64_op(memory1, OP_LT, (UINT64_C(1)<<50));
6130 : #endif
6131 : }
6132 :
6133 0 : done:
6134 1 : ;
6135 1 : }
6136 :
6137 : static void
6138 1 : test_util_dest_validation_edgecase(void *arg)
6139 : {
6140 1 : (void)arg;
6141 :
6142 1 : tt_assert(!string_is_valid_dest(NULL));
6143 1 : tt_assert(!string_is_valid_dest(""));
6144 :
6145 1 : done:
6146 1 : return;
6147 : }
6148 :
6149 : static void
6150 1 : test_util_hostname_validation(void *arg)
6151 : {
6152 1 : (void)arg;
6153 :
6154 : // Lets try valid hostnames first.
6155 1 : tt_assert(string_is_valid_nonrfc_hostname("torproject.org"));
6156 1 : tt_assert(string_is_valid_nonrfc_hostname("ocw.mit.edu"));
6157 1 : tt_assert(string_is_valid_nonrfc_hostname("i.4cdn.org"));
6158 1 : tt_assert(string_is_valid_nonrfc_hostname("stanford.edu"));
6159 1 : tt_assert(string_is_valid_nonrfc_hostname("multiple-words-with-hypens.jp"));
6160 :
6161 : // Subdomain name cannot start with '-' or '_'.
6162 1 : tt_assert(!string_is_valid_nonrfc_hostname("-torproject.org"));
6163 1 : tt_assert(!string_is_valid_nonrfc_hostname("subdomain.-domain.org"));
6164 1 : tt_assert(!string_is_valid_nonrfc_hostname("-subdomain.domain.org"));
6165 1 : tt_assert(!string_is_valid_nonrfc_hostname("___abc.org"));
6166 :
6167 : // Hostnames cannot contain non-alphanumeric characters.
6168 1 : tt_assert(!string_is_valid_nonrfc_hostname("%%domain.\\org."));
6169 1 : tt_assert(!string_is_valid_nonrfc_hostname("***x.net"));
6170 1 : tt_assert(!string_is_valid_nonrfc_hostname("\xff\xffxyz.org"));
6171 1 : tt_assert(!string_is_valid_nonrfc_hostname("word1 word2.net"));
6172 :
6173 : // Test workaround for nytimes.com stupidity, technically invalid,
6174 : // but we allow it since they are big, even though they are failing to
6175 : // comply with a ~30 year old standard.
6176 1 : tt_assert(string_is_valid_nonrfc_hostname("core3_euw1.fabrik.nytimes.com"));
6177 :
6178 : // Firefox passes FQDNs with trailing '.'s directly to the SOCKS proxy,
6179 : // which is redundant since the spec states DOMAINNAME addresses are fully
6180 : // qualified. While unusual, this should be tollerated.
6181 1 : tt_assert(string_is_valid_nonrfc_hostname("core9_euw1.fabrik.nytimes.com."));
6182 1 : tt_assert(!string_is_valid_nonrfc_hostname(
6183 : "..washingtonpost.is.better.com"));
6184 1 : tt_assert(!string_is_valid_nonrfc_hostname("so.is..ft.com"));
6185 1 : tt_assert(!string_is_valid_nonrfc_hostname("..."));
6186 :
6187 : // XXX: do we allow single-label DNS names?
6188 : // We shouldn't for SOCKS (spec says "contains a fully-qualified domain name"
6189 : // but only test pathologically malformed trailing '.' cases for now.
6190 1 : tt_assert(!string_is_valid_nonrfc_hostname("."));
6191 1 : tt_assert(!string_is_valid_nonrfc_hostname(".."));
6192 :
6193 : // IP address strings are not hostnames.
6194 1 : tt_assert(!string_is_valid_nonrfc_hostname("8.8.8.8"));
6195 1 : tt_assert(!string_is_valid_nonrfc_hostname("[2a00:1450:401b:800::200e]"));
6196 1 : tt_assert(!string_is_valid_nonrfc_hostname("2a00:1450:401b:800::200e"));
6197 :
6198 : // We allow alphanumeric TLDs. For discussion, see ticket #25055.
6199 1 : tt_assert(string_is_valid_nonrfc_hostname("lucky.13"));
6200 1 : tt_assert(string_is_valid_nonrfc_hostname("luck.y13"));
6201 1 : tt_assert(string_is_valid_nonrfc_hostname("luck.y13."));
6202 :
6203 : // We allow punycode TLDs. For examples, see
6204 : // https://data.iana.org/TLD/tlds-alpha-by-domain.txt
6205 1 : tt_assert(string_is_valid_nonrfc_hostname("example.xn--l1acc"));
6206 :
6207 1 : done:
6208 1 : return;
6209 : }
6210 :
6211 : static void
6212 1 : test_util_ipv4_validation(void *arg)
6213 : {
6214 1 : (void)arg;
6215 :
6216 1 : tt_assert(string_is_valid_ipv4_address("192.168.0.1"));
6217 1 : tt_assert(string_is_valid_ipv4_address("8.8.8.8"));
6218 :
6219 1 : tt_assert(!string_is_valid_ipv4_address("abcd"));
6220 1 : tt_assert(!string_is_valid_ipv4_address("300.300.300.300"));
6221 1 : tt_assert(!string_is_valid_ipv4_address("8.8."));
6222 :
6223 1 : done:
6224 1 : return;
6225 : }
6226 :
6227 : static void
6228 1 : test_util_ipv6_validation(void *arg)
6229 : {
6230 1 : (void)arg;
6231 :
6232 1 : tt_assert(string_is_valid_ipv6_address("2a00:1450:401b:800::200e"));
6233 1 : tt_assert(!string_is_valid_ipv6_address("11:22::33:44:"));
6234 :
6235 1 : done:
6236 1 : return;
6237 : }
6238 :
6239 : static void
6240 1 : test_util_writepid(void *arg)
6241 : {
6242 1 : (void) arg;
6243 :
6244 1 : char *contents = NULL;
6245 1 : const char *fname = get_fname("tmp_pid");
6246 1 : unsigned long pid;
6247 1 : char c;
6248 :
6249 1 : write_pidfile(fname);
6250 :
6251 1 : contents = read_file_to_str(fname, 0, NULL);
6252 1 : tt_assert(contents);
6253 :
6254 1 : int n = tor_sscanf(contents, "%lu\n%c", &pid, &c);
6255 1 : tt_int_op(n, OP_EQ, 1);
6256 :
6257 : #ifdef _WIN32
6258 : tt_uint_op(pid, OP_EQ, _getpid());
6259 : #else
6260 1 : tt_uint_op(pid, OP_EQ, getpid());
6261 : #endif
6262 :
6263 1 : done:
6264 1 : tor_free(contents);
6265 1 : }
6266 :
6267 : static void
6268 1 : test_util_get_avail_disk_space(void *arg)
6269 : {
6270 1 : (void) arg;
6271 1 : int64_t val;
6272 :
6273 : /* No answer for nonexistent directory */
6274 1 : val = tor_get_avail_disk_space("/akljasdfklsajdklasjkldjsa");
6275 1 : tt_i64_op(val, OP_EQ, -1);
6276 :
6277 : /* Try the current directory */
6278 1 : val = tor_get_avail_disk_space(".");
6279 :
6280 : #if !defined(HAVE_STATVFS) && !defined(_WIN32)
6281 : tt_i64_op(val, OP_EQ, -1); /* You don't have an implementation for this */
6282 : #else
6283 1 : tt_i64_op(val, OP_GT, 0); /* You have some space. */
6284 1 : tt_i64_op(val, OP_LT, ((int64_t)1)<<56); /* You don't have a zebibyte */
6285 : #endif /* !defined(HAVE_STATVFS) && !defined(_WIN32) */
6286 :
6287 1 : done:
6288 1 : ;
6289 1 : }
6290 :
6291 : /** Helper: Change the atime and mtime of a file. */
6292 : static void
6293 2 : set_file_mtime(const char *fname, time_t when)
6294 : {
6295 2 : struct utimbuf u = { when, when };
6296 2 : struct stat st;
6297 2 : tt_int_op(0, OP_EQ, utime(fname, &u));
6298 2 : tt_int_op(0, OP_EQ, stat(fname, &st));
6299 : /* Let's hope that utime/stat give the same second as a round-trip? */
6300 2 : tt_i64_op(st.st_mtime, OP_EQ, when);
6301 2 : done:
6302 2 : ;
6303 2 : }
6304 :
6305 : static void
6306 1 : test_util_touch_file(void *arg)
6307 : {
6308 1 : (void) arg;
6309 1 : const char *fname = get_fname("touch");
6310 :
6311 1 : const time_t now = time(NULL);
6312 1 : struct stat st;
6313 1 : write_bytes_to_file(fname, "abc", 3, 1);
6314 1 : tt_int_op(0, OP_EQ, stat(fname, &st));
6315 : /* A subtle point: the filesystem time is not necessarily equal to the
6316 : * system clock time, since one can be using a monotonic clock, or coarse
6317 : * monotonic clock, or whatever. So we might wind up with an mtime a few
6318 : * microseconds ago. Let's just give it a lot of wiggle room. */
6319 1 : tt_i64_op(st.st_mtime, OP_GE, now - 1);
6320 :
6321 1 : const time_t five_sec_ago = now - 5;
6322 1 : set_file_mtime(fname, five_sec_ago);
6323 :
6324 : /* Finally we can touch the file */
6325 1 : tt_int_op(0, OP_EQ, touch_file(fname));
6326 1 : tt_int_op(0, OP_EQ, stat(fname, &st));
6327 1 : tt_i64_op(st.st_mtime, OP_GE, now-1);
6328 :
6329 1 : done:
6330 1 : ;
6331 1 : }
6332 :
6333 : #ifndef DISABLE_PWDB_TESTS
6334 : static void
6335 1 : test_util_pwdb(void *arg)
6336 : {
6337 1 : (void) arg;
6338 1 : const struct passwd *me = NULL, *me2, *me3;
6339 1 : char *name = NULL;
6340 1 : char *dir = NULL;
6341 :
6342 : /* Uncached case. */
6343 : /* Let's assume that we exist. */
6344 1 : me = tor_getpwuid(getuid());
6345 1 : tt_ptr_op(me, OP_NE, NULL);
6346 1 : name = tor_strdup(me->pw_name);
6347 :
6348 : /* Uncached case */
6349 1 : me2 = tor_getpwnam(name);
6350 1 : tt_ptr_op(me2, OP_NE, NULL);
6351 1 : tt_int_op(me2->pw_uid, OP_EQ, getuid());
6352 :
6353 : /* Cached case */
6354 1 : me3 = tor_getpwuid(getuid());
6355 1 : tt_ptr_op(me3, OP_NE, NULL);
6356 1 : tt_str_op(me3->pw_name, OP_EQ, name);
6357 :
6358 1 : me3 = tor_getpwnam(name);
6359 1 : tt_ptr_op(me3, OP_NE, NULL);
6360 1 : tt_int_op(me3->pw_uid, OP_EQ, getuid());
6361 :
6362 1 : dir = get_user_homedir(name);
6363 1 : tt_ptr_op(dir, OP_NE, NULL);
6364 :
6365 : /* Try failing cases. First find a user that doesn't exist by name */
6366 : char randbytes[4];
6367 : char badname[9];
6368 1 : int i, found=0;
6369 1 : for (i = 0; i < 100; ++i) {
6370 1 : crypto_rand(randbytes, sizeof(randbytes));
6371 1 : base16_encode(badname, sizeof(badname), randbytes, sizeof(randbytes));
6372 1 : if (tor_getpwnam(badname) == NULL) {
6373 : found = 1;
6374 : break;
6375 : }
6376 : }
6377 1 : tt_assert(found);
6378 1 : tor_free(dir);
6379 :
6380 : /* We should do a LOG_ERR */
6381 1 : setup_full_capture_of_logs(LOG_ERR);
6382 1 : dir = get_user_homedir(badname);
6383 1 : tt_ptr_op(dir, OP_EQ, NULL);
6384 1 : expect_log_msg_containing("not found");
6385 1 : tt_int_op(smartlist_len(mock_saved_logs()), OP_EQ, 1);
6386 1 : teardown_capture_of_logs();
6387 :
6388 : /* Now try to find a user that doesn't exist by ID. */
6389 1 : found = 0;
6390 2 : for (i = 0; i < 1000; ++i) {
6391 1 : uid_t u;
6392 1 : crypto_rand((char*)&u, sizeof(u));
6393 1 : if (tor_getpwuid(u) == NULL) {
6394 1 : found = 1;
6395 1 : break;
6396 : }
6397 : }
6398 1 : tt_assert(found);
6399 :
6400 1 : done:
6401 1 : tor_free(name);
6402 1 : tor_free(dir);
6403 1 : teardown_capture_of_logs();
6404 1 : }
6405 : #endif /* !defined(DISABLE_PWDB_TESTS) */
6406 :
6407 : static void
6408 1 : test_util_calloc_check(void *arg)
6409 : {
6410 1 : (void) arg;
6411 : /* Easy cases that are good. */
6412 1 : tt_assert(size_mul_check(0,0));
6413 1 : tt_assert(size_mul_check(0,100));
6414 1 : tt_assert(size_mul_check(100,0));
6415 1 : tt_assert(size_mul_check(100,100));
6416 :
6417 : /* Harder cases that are still good. */
6418 1 : tt_assert(size_mul_check(SIZE_MAX, 1));
6419 1 : tt_assert(size_mul_check(1, SIZE_MAX));
6420 1 : tt_assert(size_mul_check(SIZE_MAX / 10, 9));
6421 1 : tt_assert(size_mul_check(11, SIZE_MAX / 12));
6422 1 : const size_t sqrt_size_max_p1 = ((size_t)1) << (sizeof(size_t) * 4);
6423 1 : tt_assert(size_mul_check(sqrt_size_max_p1, sqrt_size_max_p1 - 1));
6424 :
6425 : /* Cases that overflow */
6426 1 : tt_assert(! size_mul_check(SIZE_MAX, 2));
6427 1 : tt_assert(! size_mul_check(2, SIZE_MAX));
6428 1 : tt_assert(! size_mul_check(SIZE_MAX / 10, 11));
6429 1 : tt_assert(! size_mul_check(11, SIZE_MAX / 10));
6430 1 : tt_assert(! size_mul_check(SIZE_MAX / 8, 9));
6431 1 : tt_assert(! size_mul_check(sqrt_size_max_p1, sqrt_size_max_p1));
6432 :
6433 1 : done:
6434 1 : ;
6435 1 : }
6436 :
6437 : static void
6438 1 : test_util_monotonic_time(void *arg)
6439 : {
6440 1 : (void)arg;
6441 :
6442 1 : monotime_t mt1, mt2;
6443 1 : monotime_coarse_t mtc1, mtc2;
6444 1 : uint64_t nsec1, nsec2, usec1, msec1;
6445 1 : uint64_t nsecc1, nsecc2, usecc1, msecc1;
6446 1 : uint32_t stamp1, stamp2;
6447 :
6448 1 : monotime_init();
6449 :
6450 1 : monotime_get(&mt1);
6451 1 : monotime_coarse_get(&mtc1);
6452 1 : nsec1 = monotime_absolute_nsec();
6453 1 : usec1 = monotime_absolute_usec();
6454 1 : msec1 = monotime_absolute_msec();
6455 1 : nsecc1 = monotime_coarse_absolute_nsec();
6456 1 : usecc1 = monotime_coarse_absolute_usec();
6457 1 : msecc1 = monotime_coarse_absolute_msec();
6458 1 : stamp1 = monotime_coarse_to_stamp(&mtc1);
6459 :
6460 1 : tor_sleep_msec(200);
6461 :
6462 1 : monotime_get(&mt2);
6463 1 : monotime_coarse_get(&mtc2);
6464 1 : nsec2 = monotime_absolute_nsec();
6465 1 : nsecc2 = monotime_coarse_absolute_nsec();
6466 1 : stamp2 = monotime_coarse_to_stamp(&mtc2);
6467 :
6468 : /* We need to be a little careful here since we don't know the system load.
6469 : */
6470 1 : tt_i64_op(monotime_diff_msec(&mt1, &mt2), OP_GE, 175);
6471 1 : tt_i64_op(monotime_diff_msec(&mt1, &mt2), OP_LT, 1000);
6472 1 : tt_i64_op(monotime_coarse_diff_msec(&mtc1, &mtc2), OP_GE, 125);
6473 1 : tt_i64_op(monotime_coarse_diff_msec(&mtc1, &mtc2), OP_LT, 1000);
6474 1 : tt_u64_op(nsec2-nsec1, OP_GE, 175000000);
6475 1 : tt_u64_op(nsec2-nsec1, OP_LT, 1000000000);
6476 1 : tt_u64_op(nsecc2-nsecc1, OP_GE, 125000000);
6477 1 : tt_u64_op(nsecc2-nsecc1, OP_LT, 1000000000);
6478 :
6479 1 : tt_u64_op(msec1, OP_GE, nsec1 / 1000000);
6480 1 : tt_u64_op(usec1, OP_GE, nsec1 / 1000);
6481 1 : tt_u64_op(msecc1, OP_GE, nsecc1 / 1000000);
6482 1 : tt_u64_op(usecc1, OP_GE, nsecc1 / 1000);
6483 1 : tt_u64_op(msec1, OP_LE, nsec1 / 1000000 + 10);
6484 1 : tt_u64_op(usec1, OP_LE, nsec1 / 1000 + 10000);
6485 1 : tt_u64_op(msecc1, OP_LE, nsecc1 / 1000000 + 10);
6486 1 : tt_u64_op(usecc1, OP_LE, nsecc1 / 1000 + 10000);
6487 :
6488 1 : uint64_t coarse_stamp_diff =
6489 1 : monotime_coarse_stamp_units_to_approx_msec(stamp2-stamp1);
6490 1 : tt_u64_op(coarse_stamp_diff, OP_GE, 120);
6491 1 : tt_u64_op(coarse_stamp_diff, OP_LE, 1200);
6492 :
6493 : {
6494 1 : uint64_t units = monotime_msec_to_approx_coarse_stamp_units(5000);
6495 1 : uint64_t ms = monotime_coarse_stamp_units_to_approx_msec(units);
6496 1 : tt_u64_op(ms, OP_GE, 4950);
6497 1 : tt_u64_op(ms, OP_LT, 5050);
6498 : }
6499 :
6500 1 : done:
6501 1 : ;
6502 1 : }
6503 :
6504 : static void
6505 1 : test_util_monotonic_time_ratchet(void *arg)
6506 : {
6507 1 : (void)arg;
6508 1 : monotime_init();
6509 1 : monotime_reset_ratchets_for_testing();
6510 :
6511 : /* win32, performance counter ratchet. */
6512 1 : tt_i64_op(100, OP_EQ, ratchet_performance_counter(100));
6513 1 : tt_i64_op(101, OP_EQ, ratchet_performance_counter(101));
6514 1 : tt_i64_op(2000, OP_EQ, ratchet_performance_counter(2000));
6515 1 : tt_i64_op(2000, OP_EQ, ratchet_performance_counter(100));
6516 1 : tt_i64_op(2005, OP_EQ, ratchet_performance_counter(105));
6517 1 : tt_i64_op(3005, OP_EQ, ratchet_performance_counter(1105));
6518 1 : tt_i64_op(3005, OP_EQ, ratchet_performance_counter(1000));
6519 1 : tt_i64_op(3010, OP_EQ, ratchet_performance_counter(1005));
6520 :
6521 : /* win32, GetTickCounts32 ratchet-and-rollover-detector. */
6522 1 : const int64_t R = ((int64_t)1) << 32;
6523 1 : tt_i64_op(5, OP_EQ, ratchet_coarse_performance_counter(5));
6524 1 : tt_i64_op(1000, OP_EQ, ratchet_coarse_performance_counter(1000));
6525 1 : tt_i64_op(5+R, OP_EQ, ratchet_coarse_performance_counter(5));
6526 1 : tt_i64_op(10+R, OP_EQ, ratchet_coarse_performance_counter(10));
6527 1 : tt_i64_op(4+R*2, OP_EQ, ratchet_coarse_performance_counter(4));
6528 :
6529 : /* gettimeofday regular ratchet. */
6530 1 : struct timeval tv_in = {0,0}, tv_out;
6531 1 : tv_in.tv_usec = 9000;
6532 :
6533 1 : ratchet_timeval(&tv_in, &tv_out);
6534 1 : tt_int_op(tv_out.tv_usec, OP_EQ, 9000);
6535 1 : tt_i64_op(tv_out.tv_sec, OP_EQ, 0);
6536 :
6537 1 : tv_in.tv_sec = 1337;
6538 1 : tv_in.tv_usec = 0;
6539 1 : ratchet_timeval(&tv_in, &tv_out);
6540 1 : tt_int_op(tv_out.tv_usec, OP_EQ, 0);
6541 1 : tt_i64_op(tv_out.tv_sec, OP_EQ, 1337);
6542 :
6543 1 : tv_in.tv_sec = 1336;
6544 1 : tv_in.tv_usec = 500000;
6545 1 : ratchet_timeval(&tv_in, &tv_out);
6546 1 : tt_int_op(tv_out.tv_usec, OP_EQ, 0);
6547 1 : tt_i64_op(tv_out.tv_sec, OP_EQ, 1337);
6548 :
6549 1 : tv_in.tv_sec = 1337;
6550 1 : tv_in.tv_usec = 0;
6551 1 : ratchet_timeval(&tv_in, &tv_out);
6552 1 : tt_int_op(tv_out.tv_usec, OP_EQ, 500000);
6553 1 : tt_i64_op(tv_out.tv_sec, OP_EQ, 1337);
6554 :
6555 1 : tv_in.tv_sec = 1337;
6556 1 : tv_in.tv_usec = 600000;
6557 1 : ratchet_timeval(&tv_in, &tv_out);
6558 1 : tt_int_op(tv_out.tv_usec, OP_EQ, 100000);
6559 1 : tt_i64_op(tv_out.tv_sec, OP_EQ, 1338);
6560 :
6561 1 : tv_in.tv_sec = 1000;
6562 1 : tv_in.tv_usec = 1000;
6563 1 : ratchet_timeval(&tv_in, &tv_out);
6564 1 : tt_int_op(tv_out.tv_usec, OP_EQ, 100000);
6565 1 : tt_i64_op(tv_out.tv_sec, OP_EQ, 1338);
6566 :
6567 1 : tv_in.tv_sec = 2000;
6568 1 : tv_in.tv_usec = 2000;
6569 1 : ratchet_timeval(&tv_in, &tv_out);
6570 1 : tt_int_op(tv_out.tv_usec, OP_EQ, 101000);
6571 1 : tt_i64_op(tv_out.tv_sec, OP_EQ, 2338);
6572 :
6573 1 : done:
6574 1 : ;
6575 1 : }
6576 :
6577 : static void
6578 1 : test_util_monotonic_time_zero(void *arg)
6579 : {
6580 1 : (void) arg;
6581 1 : monotime_t t1;
6582 1 : monotime_coarse_t ct1;
6583 1 : monotime_init();
6584 : /* Check 1: The current time is not zero. */
6585 1 : monotime_get(&t1);
6586 1 : monotime_coarse_get(&ct1);
6587 1 : tt_assert(!monotime_is_zero(&t1));
6588 1 : tt_assert(!monotime_coarse_is_zero(&ct1));
6589 :
6590 : /* Check 2: The _zero() makes the time zero. */
6591 1 : monotime_zero(&t1);
6592 1 : monotime_coarse_zero(&ct1);
6593 1 : tt_assert(monotime_is_zero(&t1));
6594 1 : tt_assert(monotime_coarse_is_zero(&ct1));
6595 1 : done:
6596 1 : ;
6597 1 : }
6598 :
6599 : static void
6600 1 : test_util_monotonic_time_add_msec(void *arg)
6601 : {
6602 1 : (void) arg;
6603 1 : monotime_t t1, t2;
6604 1 : monotime_coarse_t ct1, ct2;
6605 1 : monotime_init();
6606 :
6607 1 : monotime_get(&t1);
6608 1 : monotime_coarse_get(&ct1);
6609 :
6610 : /* adding zero does nothing */
6611 1 : monotime_add_msec(&t2, &t1, 0);
6612 1 : monotime_coarse_add_msec(&ct2, &ct1, 0);
6613 1 : tt_i64_op(monotime_diff_msec(&t1, &t2), OP_EQ, 0);
6614 1 : tt_i64_op(monotime_coarse_diff_msec(&ct1, &ct2), OP_EQ, 0);
6615 :
6616 : /* Add 1337 msec; see if the diff function agree */
6617 1 : monotime_add_msec(&t2, &t1, 1337);
6618 1 : monotime_coarse_add_msec(&ct2, &ct1, 1337);
6619 1 : tt_i64_op(monotime_diff_msec(&t1, &t2), OP_EQ, 1337);
6620 1 : tt_i64_op(monotime_coarse_diff_msec(&ct1, &ct2), OP_EQ, 1337);
6621 : // The 32-bit variant must be within 1% of the regular one.
6622 1 : tt_int_op(monotime_coarse_diff_msec32_(&ct1, &ct2), OP_GT, 1323);
6623 1 : tt_int_op(monotime_coarse_diff_msec32_(&ct1, &ct2), OP_LT, 1350);
6624 :
6625 : /* Add 1337 msec twice more; make sure that any second rollover issues
6626 : * worked. */
6627 1 : monotime_add_msec(&t2, &t2, 1337);
6628 1 : monotime_coarse_add_msec(&ct2, &ct2, 1337);
6629 1 : monotime_add_msec(&t2, &t2, 1337);
6630 1 : monotime_coarse_add_msec(&ct2, &ct2, 1337);
6631 1 : tt_i64_op(monotime_diff_msec(&t1, &t2), OP_EQ, 1337*3);
6632 1 : tt_i64_op(monotime_coarse_diff_msec(&ct1, &ct2), OP_EQ, 1337*3);
6633 1 : tt_int_op(monotime_coarse_diff_msec32_(&ct1, &ct2), OP_GT, 3970);
6634 1 : tt_int_op(monotime_coarse_diff_msec32_(&ct1, &ct2), OP_LT, 4051);
6635 :
6636 1 : done:
6637 1 : ;
6638 1 : }
6639 :
6640 : static void
6641 1 : test_util_nowrap_math(void *arg)
6642 : {
6643 1 : (void)arg;
6644 :
6645 1 : tt_u64_op(0, OP_EQ, tor_add_u32_nowrap(0, 0));
6646 1 : tt_u64_op(1, OP_EQ, tor_add_u32_nowrap(0, 1));
6647 1 : tt_u64_op(1, OP_EQ, tor_add_u32_nowrap(1, 0));
6648 1 : tt_u64_op(4, OP_EQ, tor_add_u32_nowrap(2, 2));
6649 1 : tt_u64_op(UINT32_MAX, OP_EQ, tor_add_u32_nowrap(UINT32_MAX-1, 2));
6650 1 : tt_u64_op(UINT32_MAX, OP_EQ, tor_add_u32_nowrap(2, UINT32_MAX-1));
6651 1 : tt_u64_op(UINT32_MAX, OP_EQ, tor_add_u32_nowrap(UINT32_MAX, UINT32_MAX));
6652 :
6653 1 : tt_u64_op(0, OP_EQ, tor_mul_u64_nowrap(0, 0));
6654 1 : tt_u64_op(1, OP_EQ, tor_mul_u64_nowrap(1, 1));
6655 1 : tt_u64_op(2, OP_EQ, tor_mul_u64_nowrap(2, 1));
6656 1 : tt_u64_op(4, OP_EQ, tor_mul_u64_nowrap(2, 2));
6657 1 : tt_u64_op(UINT64_MAX, OP_EQ, tor_mul_u64_nowrap(UINT64_MAX, 1));
6658 1 : tt_u64_op(UINT64_MAX, OP_EQ, tor_mul_u64_nowrap(2, UINT64_MAX));
6659 1 : tt_u64_op(UINT64_MAX, OP_EQ, tor_mul_u64_nowrap(UINT64_MAX, UINT64_MAX));
6660 :
6661 1 : done:
6662 1 : ;
6663 1 : }
6664 :
6665 : static void
6666 1 : test_util_htonll(void *arg)
6667 : {
6668 1 : (void)arg;
6669 : #ifdef WORDS_BIGENDIAN
6670 : const uint64_t res_be = 0x8877665544332211;
6671 : #else
6672 1 : const uint64_t res_le = 0x1122334455667788;
6673 : #endif
6674 :
6675 1 : tt_u64_op(0, OP_EQ, tor_htonll(0));
6676 1 : tt_u64_op(0, OP_EQ, tor_ntohll(0));
6677 1 : tt_u64_op(UINT64_MAX, OP_EQ, tor_htonll(UINT64_MAX));
6678 1 : tt_u64_op(UINT64_MAX, OP_EQ, tor_ntohll(UINT64_MAX));
6679 :
6680 : #ifdef WORDS_BIGENDIAN
6681 : tt_u64_op(res_be, OP_EQ, tor_htonll(0x8877665544332211));
6682 : tt_u64_op(res_be, OP_EQ, tor_ntohll(0x8877665544332211));
6683 : #else
6684 1 : tt_u64_op(res_le, OP_EQ, tor_htonll(0x8877665544332211));
6685 1 : tt_u64_op(res_le, OP_EQ, tor_ntohll(0x8877665544332211));
6686 : #endif /* defined(WORDS_BIGENDIAN) */
6687 :
6688 1 : done:
6689 1 : ;
6690 1 : }
6691 :
6692 : static void
6693 1 : test_util_get_unquoted_path(void *arg)
6694 : {
6695 1 : (void)arg;
6696 :
6697 1 : char *r = NULL;
6698 :
6699 1 : r = get_unquoted_path("\""); // "
6700 1 : tt_ptr_op(r, OP_EQ, NULL);
6701 1 : tor_free(r);
6702 :
6703 1 : r = get_unquoted_path("\"\"\""); // """
6704 1 : tt_ptr_op(r, OP_EQ, NULL);
6705 1 : tor_free(r);
6706 :
6707 1 : r = get_unquoted_path("\\\""); // \"
6708 1 : tt_ptr_op(r, OP_EQ, NULL);
6709 1 : tor_free(r);
6710 :
6711 1 : r = get_unquoted_path("\\\"\\\""); // \"\"
6712 1 : tt_ptr_op(r, OP_EQ, NULL);
6713 1 : tor_free(r);
6714 :
6715 1 : r = get_unquoted_path("A\\B\\C\""); // A\B\C"
6716 1 : tt_ptr_op(r, OP_EQ, NULL);
6717 1 : tor_free(r);
6718 :
6719 1 : r = get_unquoted_path("\"A\\B\\C"); // "A\B\C
6720 1 : tt_ptr_op(r, OP_EQ, NULL);
6721 1 : tor_free(r);
6722 :
6723 1 : r = get_unquoted_path("\"A\\B\"C\""); // "A\B"C"
6724 1 : tt_ptr_op(r, OP_EQ, NULL);
6725 1 : tor_free(r);
6726 :
6727 1 : r = get_unquoted_path("A\\B\"C"); // A\B"C
6728 1 : tt_ptr_op(r, OP_EQ, NULL);
6729 1 : tor_free(r);
6730 :
6731 1 : r = get_unquoted_path("");
6732 1 : tt_str_op(r, OP_EQ, "");
6733 1 : tor_free(r);
6734 :
6735 1 : r = get_unquoted_path("\"\""); // ""
6736 1 : tt_str_op(r, OP_EQ, "");
6737 1 : tor_free(r);
6738 :
6739 1 : r = get_unquoted_path("A\\B\\C"); // A\B\C
6740 1 : tt_str_op(r, OP_EQ, "A\\B\\C"); // A\B\C
6741 1 : tor_free(r);
6742 :
6743 1 : r = get_unquoted_path("\"A\\B\\C\""); // "A\B\C"
6744 1 : tt_str_op(r, OP_EQ, "A\\B\\C"); // A\B\C
6745 1 : tor_free(r);
6746 :
6747 1 : r = get_unquoted_path("\"\\\""); // "\"
6748 1 : tt_str_op(r, OP_EQ, "\\"); // \ /* comment to prevent line continuation */
6749 1 : tor_free(r);
6750 :
6751 1 : r = get_unquoted_path("\"\\\"\""); // "\""
6752 1 : tt_str_op(r, OP_EQ, "\""); // "
6753 1 : tor_free(r);
6754 :
6755 1 : r = get_unquoted_path("\"A\\B\\C\\\"\""); // "A\B\C\""
6756 1 : tt_str_op(r, OP_EQ, "A\\B\\C\""); // A\B\C"
6757 1 : tor_free(r);
6758 :
6759 1 : r = get_unquoted_path("A\\B\\\"C"); // A\B\"C
6760 1 : tt_str_op(r, OP_EQ, "A\\B\"C"); // A\B"C
6761 1 : tor_free(r);
6762 :
6763 1 : r = get_unquoted_path("\"A\\B\\\"C\""); // "A\B\"C"
6764 1 : tt_str_op(r, OP_EQ, "A\\B\"C"); // A\B"C
6765 :
6766 1 : done:
6767 1 : tor_free(r);
6768 1 : }
6769 :
6770 : static void
6771 1 : test_util_map_anon(void *arg)
6772 : {
6773 1 : (void)arg;
6774 1 : char *ptr = NULL;
6775 1 : size_t sz = 16384;
6776 1 : unsigned inherit=0;
6777 :
6778 : /* Basic checks. */
6779 1 : ptr = tor_mmap_anonymous(sz, 0, &inherit);
6780 1 : tt_ptr_op(ptr, OP_NE, 0);
6781 1 : tt_int_op(inherit, OP_EQ, INHERIT_RES_KEEP);
6782 1 : ptr[sz-1] = 3;
6783 1 : tt_int_op(ptr[0], OP_EQ, 0);
6784 1 : tt_int_op(ptr[sz-2], OP_EQ, 0);
6785 1 : tt_int_op(ptr[sz-1], OP_EQ, 3);
6786 :
6787 : /* Try again, with a private (non-swappable) mapping. */
6788 1 : tor_munmap_anonymous(ptr, sz);
6789 1 : ptr = tor_mmap_anonymous(sz, ANONMAP_PRIVATE, &inherit);
6790 1 : tt_ptr_op(ptr, OP_NE, 0);
6791 1 : tt_int_op(inherit, OP_EQ, INHERIT_RES_KEEP);
6792 1 : ptr[sz-1] = 10;
6793 1 : tt_int_op(ptr[0], OP_EQ, 0);
6794 1 : tt_int_op(ptr[sz/2], OP_EQ, 0);
6795 1 : tt_int_op(ptr[sz-1], OP_EQ, 10);
6796 :
6797 : /* Now let's test a drop-on-fork mapping. */
6798 1 : tor_munmap_anonymous(ptr, sz);
6799 1 : ptr = tor_mmap_anonymous(sz, ANONMAP_NOINHERIT, &inherit);
6800 1 : tt_ptr_op(ptr, OP_NE, 0);
6801 1 : ptr[sz-1] = 10;
6802 1 : tt_int_op(ptr[0], OP_EQ, 0);
6803 1 : tt_int_op(ptr[sz/2], OP_EQ, 0);
6804 1 : tt_int_op(ptr[sz-1], OP_EQ, 10);
6805 :
6806 1 : done:
6807 1 : tor_munmap_anonymous(ptr, sz);
6808 1 : }
6809 :
6810 : static void
6811 1 : test_util_map_anon_nofork(void *arg)
6812 : {
6813 1 : (void)arg;
6814 : #ifdef _WIN32
6815 : /* The operating system doesn't support forking. */
6816 : tt_skip();
6817 : done:
6818 : ;
6819 : #else /* !defined(_WIN32) */
6820 : /* We have the right OS support. We're going to try marking the buffer as
6821 : * either zero-on-fork or as drop-on-fork, whichever is supported. Then we
6822 : * will fork and send a byte back to the parent process. This will either
6823 : * crash, or send zero. */
6824 :
6825 1 : char *ptr = NULL;
6826 1 : const char TEST_VALUE = 0xd0;
6827 1 : size_t sz = 16384;
6828 1 : int pipefd[2] = {-1, -1};
6829 1 : unsigned inherit=0;
6830 :
6831 1 : tor_munmap_anonymous(ptr, sz);
6832 1 : ptr = tor_mmap_anonymous(sz, ANONMAP_NOINHERIT, &inherit);
6833 1 : tt_ptr_op(ptr, OP_NE, 0);
6834 1 : memset(ptr, (uint8_t)TEST_VALUE, sz);
6835 :
6836 1 : tt_int_op(0, OP_EQ, pipe(pipefd));
6837 1 : pid_t child = fork();
6838 2 : if (child == 0) {
6839 : /* We're in the child. */
6840 1 : close(pipefd[0]);
6841 1 : ssize_t r = write(pipefd[1], &ptr[sz-1], 1); /* This may crash. */
6842 1 : close(pipefd[1]);
6843 1 : if (r < 0)
6844 0 : exit(1);
6845 1 : exit(0);
6846 : }
6847 1 : tt_int_op(child, OP_GT, 0);
6848 : /* In the parent. */
6849 1 : close(pipefd[1]);
6850 1 : pipefd[1] = -1;
6851 1 : char buf[1];
6852 1 : ssize_t r = read(pipefd[0], buf, 1);
6853 :
6854 1 : if (inherit == INHERIT_RES_ZERO) {
6855 : // We should be seeing clear-on-fork behavior.
6856 1 : tt_int_op((int)r, OP_EQ, 1); // child should send us a byte.
6857 1 : tt_int_op(buf[0], OP_EQ, 0); // that byte should be zero.
6858 0 : } else if (inherit == INHERIT_RES_DROP) {
6859 : // We should be seeing noinherit behavior.
6860 0 : tt_int_op(r, OP_LE, 0); // child said nothing; it should have crashed.
6861 : } else {
6862 : // noinherit isn't implemented.
6863 0 : tt_int_op(inherit, OP_EQ, INHERIT_RES_KEEP);
6864 0 : tt_int_op((int)r, OP_EQ, 1); // child should send us a byte.
6865 0 : tt_int_op(buf[0], OP_EQ, TEST_VALUE); // that byte should be TEST_VALUE.
6866 : }
6867 :
6868 1 : int ws;
6869 1 : waitpid(child, &ws, 0);
6870 :
6871 : #ifndef NOINHERIT_CAN_FAIL
6872 : /* Only if NOINHERIT_CAN_FAIL should it be possible for us to get
6873 : * INHERIT_KEEP behavior in this case. */
6874 : tt_int_op(inherit, OP_NE, INHERIT_RES_KEEP);
6875 : #else
6876 1 : if (inherit == INHERIT_RES_KEEP) {
6877 : /* Call this test "skipped", not "passed", since noinherit wasn't
6878 : * implemented. */
6879 0 : tt_skip();
6880 : }
6881 : #endif /* !defined(NOINHERIT_CAN_FAIL) */
6882 :
6883 1 : done:
6884 1 : tor_munmap_anonymous(ptr, sz);
6885 1 : if (pipefd[0] >= 0) {
6886 1 : close(pipefd[0]);
6887 : }
6888 1 : if (pipefd[1] >= 0) {
6889 0 : close(pipefd[1]);
6890 : }
6891 : #endif /* defined(_WIN32) */
6892 1 : }
6893 :
6894 : #ifndef COCCI
6895 : #define UTIL_LEGACY(name) \
6896 : { (#name), test_util_ ## name , 0, NULL, NULL }
6897 :
6898 : #define UTIL_TEST(name, flags) \
6899 : { (#name), test_util_ ## name, flags, NULL, NULL }
6900 :
6901 : #define COMPRESS(name, identifier) \
6902 : { ("compress/" #name), test_util_compress, 0, &compress_setup, \
6903 : (char*)(identifier) }
6904 :
6905 : #define COMPRESS_CONCAT(name, identifier) \
6906 : { ("compress_concat/" #name), test_util_decompress_concatenated, 0, \
6907 : &compress_setup, \
6908 : (char*)(identifier) }
6909 :
6910 : #define COMPRESS_JUNK(name, identifier) \
6911 : { ("compress_junk/" #name), test_util_decompress_junk, 0, \
6912 : &compress_setup, \
6913 : (char*)(identifier) }
6914 :
6915 : #define COMPRESS_DOS(name, identifier) \
6916 : { ("compress_dos/" #name), test_util_decompress_dos, 0, \
6917 : &compress_setup, \
6918 : (char*)(identifier) }
6919 :
6920 : #ifdef _WIN32
6921 : #define UTIL_TEST_WIN_ONLY(n, f) UTIL_TEST(n, (f))
6922 : #else
6923 : #define UTIL_TEST_WIN_ONLY(n, f) { (#n), NULL, TT_SKIP, NULL, NULL }
6924 : #endif
6925 :
6926 : #ifdef DISABLE_PWDB_TESTS
6927 : #define UTIL_TEST_PWDB(n, f) { (#n), NULL, TT_SKIP, NULL, NULL }
6928 : #else
6929 : #define UTIL_TEST_PWDB(n, f) UTIL_TEST(n, (f))
6930 : #endif
6931 : #endif /* !defined(COCCI) */
6932 :
6933 : struct testcase_t util_tests[] = {
6934 : UTIL_LEGACY(time),
6935 : UTIL_TEST(parse_http_time, 0),
6936 : UTIL_LEGACY(config_line),
6937 : UTIL_LEGACY(config_line_quotes),
6938 : UTIL_LEGACY(config_line_comment_character),
6939 : UTIL_LEGACY(config_line_escaped_content),
6940 : UTIL_LEGACY(config_line_crlf),
6941 : UTIL_TEST(config_line_partition, 0),
6942 : UTIL_TEST_PWDB(expand_filename, 0),
6943 : UTIL_LEGACY(escape_string_socks),
6944 : UTIL_LEGACY(string_is_key_value),
6945 : UTIL_LEGACY(strmisc),
6946 : UTIL_TEST(parse_integer, 0),
6947 : UTIL_LEGACY(pow2),
6948 : COMPRESS(zlib, "deflate"),
6949 : COMPRESS(gzip, "gzip"),
6950 : COMPRESS(lzma, "x-tor-lzma"),
6951 : COMPRESS(zstd, "x-zstd"),
6952 : COMPRESS(zstd_nostatic, "x-zstd:nostatic"),
6953 : COMPRESS(none, "identity"),
6954 : COMPRESS_CONCAT(zlib, "deflate"),
6955 : COMPRESS_CONCAT(gzip, "gzip"),
6956 : COMPRESS_CONCAT(lzma, "x-tor-lzma"),
6957 : COMPRESS_CONCAT(zstd, "x-zstd"),
6958 : COMPRESS_CONCAT(zstd_nostatic, "x-zstd:nostatic"),
6959 : COMPRESS_CONCAT(none, "identity"),
6960 : COMPRESS_JUNK(zlib, "deflate"),
6961 : COMPRESS_JUNK(gzip, "gzip"),
6962 : COMPRESS_JUNK(lzma, "x-tor-lzma"),
6963 : COMPRESS_DOS(zlib, "deflate"),
6964 : COMPRESS_DOS(gzip, "gzip"),
6965 : COMPRESS_DOS(lzma, "x-tor-lzma"),
6966 : COMPRESS_DOS(zstd, "x-zstd"),
6967 : COMPRESS_DOS(zstd_nostatic, "x-zstd:nostatic"),
6968 : UTIL_TEST(gzip_compression_bomb, TT_FORK),
6969 : UTIL_LEGACY(datadir),
6970 : UTIL_LEGACY(memarea),
6971 : UTIL_LEGACY(control_formats),
6972 : UTIL_LEGACY(mmap),
6973 : UTIL_TEST(sscanf, TT_FORK),
6974 : UTIL_LEGACY(format_time_interval),
6975 : UTIL_LEGACY(path_is_relative),
6976 : UTIL_LEGACY(strtok),
6977 : UTIL_LEGACY(di_ops),
6978 : UTIL_TEST(memcpy_iftrue_timei, 0),
6979 : UTIL_TEST(di_map, 0),
6980 : UTIL_TEST(round_to_next_multiple_of, 0),
6981 : UTIL_TEST(laplace, 0),
6982 : UTIL_TEST(clamp_double_to_int64, 0),
6983 : UTIL_TEST(find_str_at_start_of_line, 0),
6984 : UTIL_TEST(tor_strreplacechar, 0),
6985 : UTIL_TEST(string_is_C_identifier, 0),
6986 : UTIL_TEST(string_is_utf8, 0),
6987 : UTIL_TEST(asprintf, 0),
6988 : UTIL_TEST(listdir, 0),
6989 : UTIL_TEST(glob, 0),
6990 : UTIL_TEST(get_glob_opened_files, 0),
6991 : UTIL_TEST(parent_dir, 0),
6992 : UTIL_TEST(ftruncate, 0),
6993 : UTIL_TEST(nowrap_math, 0),
6994 : UTIL_TEST(num_cpus, 0),
6995 : UTIL_TEST_WIN_ONLY(load_win_lib, 0),
6996 : UTIL_TEST(format_hex_number, 0),
6997 : UTIL_TEST(format_dec_number, 0),
6998 : UTIL_TEST(n_bits_set, 0),
6999 : UTIL_TEST(eat_whitespace, 0),
7000 : UTIL_TEST(sl_new_from_text_lines, 0),
7001 : UTIL_TEST(envnames, 0),
7002 : UTIL_TEST(make_environment, 0),
7003 : UTIL_TEST(set_env_var_in_sl, 0),
7004 : UTIL_TEST(read_file_eof_tiny_limit, 0),
7005 : UTIL_TEST(read_file_eof_one_loop_a, 0),
7006 : UTIL_TEST(read_file_eof_one_loop_b, 0),
7007 : UTIL_TEST(read_file_eof_two_loops, 0),
7008 : UTIL_TEST(read_file_eof_two_loops_b, 0),
7009 : UTIL_TEST(read_file_eof_zero_bytes, 0),
7010 : UTIL_TEST(read_file_endlines, 0),
7011 : UTIL_TEST(write_chunks_to_file, 0),
7012 : UTIL_TEST(write_str_if_changed, 0),
7013 : UTIL_TEST(mathlog, 0),
7014 : UTIL_TEST(fraction, 0),
7015 : UTIL_TEST(weak_random, 0),
7016 : { "tor_isinf", test_tor_isinf, TT_FORK, NULL, NULL },
7017 : { "socket_ipv4", test_util_socket, TT_FORK, &passthrough_setup,
7018 : (void*)"4" },
7019 : { "socket_ipv6", test_util_socket, TT_FORK,
7020 : &passthrough_setup, (void*)"6" },
7021 : { "socketpair", test_util_socketpair, TT_FORK, &passthrough_setup,
7022 : (void*)"0" },
7023 : { "socketpair_ersatz", test_util_socketpair, TT_FORK,
7024 : &passthrough_setup, (void*)"1" },
7025 : UTIL_TEST(max_mem, 0),
7026 : UTIL_TEST(hostname_validation, 0),
7027 : UTIL_TEST(dest_validation_edgecase, 0),
7028 : UTIL_TEST(ipv4_validation, 0),
7029 : UTIL_TEST(ipv6_validation, 0),
7030 : UTIL_TEST(writepid, 0),
7031 : UTIL_TEST(get_avail_disk_space, 0),
7032 : UTIL_TEST(touch_file, 0),
7033 : UTIL_TEST_PWDB(pwdb, TT_FORK),
7034 : UTIL_TEST(calloc_check, 0),
7035 : UTIL_TEST(monotonic_time, 0),
7036 : UTIL_TEST(monotonic_time_ratchet, TT_FORK),
7037 : UTIL_TEST(monotonic_time_zero, 0),
7038 : UTIL_TEST(monotonic_time_add_msec, 0),
7039 : UTIL_TEST(htonll, 0),
7040 : UTIL_TEST(get_unquoted_path, 0),
7041 : UTIL_TEST(map_anon, 0),
7042 : UTIL_TEST(map_anon_nofork, 0),
7043 : END_OF_TESTCASES
7044 : };
|