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