diff options
Diffstat (limited to 'src')
39 files changed, 386 insertions, 173 deletions
diff --git a/src/common/backtrace.c b/src/common/backtrace.c index afdc10d6a9..2841281927 100644 --- a/src/common/backtrace.c +++ b/src/common/backtrace.c @@ -109,8 +109,10 @@ log_backtrace(int severity, int domain, const char *msg) tor_log(severity, domain, "%s. Stack trace:", msg); if (!symbols) { + /* LCOV_EXCL_START -- we can't provoke this. */ tor_log(severity, domain, " Unable to generate backtrace."); goto done; + /* LCOV_EXCL_STOP */ } for (i=0; i < depth; ++i) { tor_log(severity, domain, " %s", symbols[i]); @@ -173,8 +175,10 @@ install_bt_handler(void) for (i = 0; trap_signals[i] >= 0; ++i) { if (sigaction(trap_signals[i], &sa, NULL) == -1) { + /* LCOV_EXCL_START */ log_warn(LD_BUG, "Sigaction failed: %s", strerror(errno)); rv = -1; + /* LCOV_EXCL_STOP */ } } diff --git a/src/common/compat.c b/src/common/compat.c index 72dffe2a6e..bae76f45db 100644 --- a/src/common/compat.c +++ b/src/common/compat.c @@ -1145,14 +1145,12 @@ tor_close_socket(tor_socket_t s) --n_sockets_open; #else if (r != EBADF) - --n_sockets_open; + --n_sockets_open; // LCOV_EXCL_LINE -- EIO and EINTR too hard to force. #endif r = -1; } - if (n_sockets_open < 0) - log_warn(LD_BUG, "Our socket count is below zero: %d. Please submit a " - "bug report.", n_sockets_open); + tor_assert_nonfatal(n_sockets_open >= 0); socket_accounting_unlock(); return r; } @@ -1932,7 +1930,7 @@ tor_getpwnam(const char *username) return NULL; if (! strcmp(username, passwd_cached->pw_name)) - return passwd_cached; + return passwd_cached; // LCOV_EXCL_LINE - would need to make getpwnam flaky return NULL; } @@ -1958,7 +1956,7 @@ tor_getpwuid(uid_t uid) return NULL; if (uid == passwd_cached->pw_uid) - return passwd_cached; + return passwd_cached; // LCOV_EXCL_LINE - would need to make getpwnam flaky return NULL; } @@ -2341,28 +2339,15 @@ get_parent_directory(char *fname) static char * alloc_getcwd(void) { - int saved_errno = errno; -/* We use this as a starting path length. Not too large seems sane. */ -#define START_PATH_LENGTH 128 -/* Nobody has a maxpath longer than this, as far as I know. And if they - * do, they shouldn't. */ -#define MAX_SANE_PATH_LENGTH 4096 - size_t path_length = START_PATH_LENGTH; - char *path = tor_malloc(path_length); - - errno = 0; - while (getcwd(path, path_length) == NULL) { - if (errno == ERANGE && path_length < MAX_SANE_PATH_LENGTH) { - path_length*=2; - path = tor_realloc(path, path_length); - } else { - tor_free(path); - path = NULL; - break; - } - } - errno = saved_errno; - return path; +#ifdef PATH_MAX +#define MAX_CWD PATH_MAX +#else +#define MAX_CWD 4096 +#endif + + char path_buf[MAX_CWD]; + char *path = getcwd(path_buf, sizeof(path_buf)); + return path ? tor_strdup(path) : NULL; } #endif @@ -2393,11 +2378,13 @@ make_path_absolute(char *fname) tor_asprintf(&absfname, "%s/%s", path, fname); tor_free(path); } else { + /* LCOV_EXCL_START Can't make getcwd fail. */ /* If getcwd failed, the best we can do here is keep using the * relative path. (Perhaps / isn't readable by this UID/GID.) */ log_warn(LD_GENERAL, "Unable to find current working directory: %s", strerror(errno)); absfname = tor_strdup(fname); + /* LCOV_EXCL_STOP */ } } return absfname; @@ -2761,7 +2748,9 @@ MOCK_IMPL(const char *, get_uname, (void)) } #endif #else + /* LCOV_EXCL_START -- can't provoke uname failure */ strlcpy(uname_result, "Unknown platform", sizeof(uname_result)); + /* LCOV_EXCL_STOP */ #endif } uname_result_is_set = 1; @@ -2835,11 +2824,14 @@ compute_num_cpus(void) if (num_cpus == -2) { num_cpus = compute_num_cpus_impl(); tor_assert(num_cpus != -2); - if (num_cpus > MAX_DETECTABLE_CPUS) + if (num_cpus > MAX_DETECTABLE_CPUS) { + /* LCOV_EXCL_START */ log_notice(LD_GENERAL, "Wow! I detected that you have %d CPUs. I " "will not autodetect any more than %d, though. If you " "want to configure more, set NumCPUs in your torrc", num_cpus, MAX_DETECTABLE_CPUS); + /* LCOV_EXCL_STOP */ + } } return num_cpus; } @@ -3369,9 +3361,11 @@ get_total_system_memory_impl(void) return result * 1024; err: + /* LCOV_EXCL_START Can't reach this unless proc is broken. */ tor_free(s); close(fd); return 0; + /* LCOV_EXCL_STOP */ #elif defined (_WIN32) /* Windows has MEMORYSTATUSEX; pretty straightforward. */ MEMORYSTATUSEX ms; @@ -3420,6 +3414,7 @@ get_total_system_memory(size_t *mem_out) static size_t mem_cached=0; uint64_t m = get_total_system_memory_impl(); if (0 == m) { + /* LCOV_EXCL_START -- can't make this happen without mocking. */ /* We couldn't find our memory total */ if (0 == mem_cached) { /* We have no cached value either */ @@ -3429,6 +3424,7 @@ get_total_system_memory(size_t *mem_out) *mem_out = mem_cached; return 0; + /* LCOV_EXCL_STOP */ } #if SIZE_MAX != UINT64_MAX diff --git a/src/common/compat_pthreads.c b/src/common/compat_pthreads.c index 1d6db34225..79f5cec43a 100644 --- a/src/common/compat_pthreads.c +++ b/src/common/compat_pthreads.c @@ -102,11 +102,13 @@ void tor_mutex_init(tor_mutex_t *mutex) { if (PREDICT_UNLIKELY(!threads_initialized)) - tor_threads_init(); + tor_threads_init(); // LCOV_EXCL_LINE const int err = pthread_mutex_init(&mutex->mutex, &attr_recursive); if (PREDICT_UNLIKELY(err)) { + // LCOV_EXCL_START log_err(LD_GENERAL, "Error %d creating a mutex.", err); - tor_fragile_assert(); + tor_assert_unreached(); + // LCOV_EXCL_STOP } } @@ -116,12 +118,14 @@ void tor_mutex_init_nonrecursive(tor_mutex_t *mutex) { int err; - if (PREDICT_UNLIKELY(!threads_initialized)) - tor_threads_init(); + if (!threads_initialized) + tor_threads_init(); // LCOV_EXCL_LINE err = pthread_mutex_init(&mutex->mutex, NULL); if (PREDICT_UNLIKELY(err)) { + // LCOV_EXCL_START log_err(LD_GENERAL, "Error %d creating a mutex.", err); - tor_fragile_assert(); + tor_assert_unreached(); + // LCOV_EXCL_STOP } } @@ -133,8 +137,10 @@ tor_mutex_acquire(tor_mutex_t *m) tor_assert(m); err = pthread_mutex_lock(&m->mutex); if (PREDICT_UNLIKELY(err)) { + // LCOV_EXCL_START log_err(LD_GENERAL, "Error %d locking a mutex.", err); - tor_fragile_assert(); + tor_assert_unreached(); + // LCOV_EXCL_STOP } } /** Release the lock <b>m</b> so another thread can have it. */ @@ -145,8 +151,10 @@ tor_mutex_release(tor_mutex_t *m) tor_assert(m); err = pthread_mutex_unlock(&m->mutex); if (PREDICT_UNLIKELY(err)) { + // LCOV_EXCL_START log_err(LD_GENERAL, "Error %d unlocking a mutex.", err); - tor_fragile_assert(); + tor_assert_unreached(); + // LCOV_EXCL_STOP } } /** Clean up the mutex <b>m</b> so that it no longer uses any system @@ -159,8 +167,10 @@ tor_mutex_uninit(tor_mutex_t *m) tor_assert(m); err = pthread_mutex_destroy(&m->mutex); if (PREDICT_UNLIKELY(err)) { + // LCOV_EXCL_START log_err(LD_GENERAL, "Error %d destroying a mutex.", err); - tor_fragile_assert(); + tor_assert_unreached(); + // LCOV_EXCL_STOP } } /** Return an integer representing this thread. */ @@ -210,8 +220,10 @@ void tor_cond_uninit(tor_cond_t *cond) { if (pthread_cond_destroy(&cond->cond)) { + // LCOV_EXCL_START log_warn(LD_GENERAL,"Error freeing condition: %s", strerror(errno)); return; + // LCOV_EXCL_STOP } } /** Wait until one of the tor_cond_signal functions is called on <b>cond</b>. @@ -232,7 +244,7 @@ tor_cond_wait(tor_cond_t *cond, tor_mutex_t *mutex, const struct timeval *tv) /* EINTR should be impossible according to POSIX, but POSIX, like the * Pirate's Code, is apparently treated "more like what you'd call * guidelines than actual rules." */ - continue; + continue; // LCOV_EXCL_LINE } return r ? -1 : 0; } diff --git a/src/common/compat_threads.c b/src/common/compat_threads.c index 9c6fa55b32..f4809060d6 100644 --- a/src/common/compat_threads.c +++ b/src/common/compat_threads.c @@ -61,8 +61,8 @@ tor_cond_t * tor_cond_new(void) { tor_cond_t *cond = tor_malloc(sizeof(tor_cond_t)); - if (tor_cond_init(cond)<0) - tor_free(cond); + if (BUG(tor_cond_init(cond)<0)) + tor_free(cond); // LCOV_EXCL_LINE return cond; } @@ -240,8 +240,11 @@ alert_sockets_create(alert_sockets_t *socks_out, uint32_t flags) if (socks[0] >= 0) { if (fcntl(socks[0], F_SETFD, FD_CLOEXEC) < 0 || set_socket_nonblocking(socks[0]) < 0) { + // LCOV_EXCL_START -- if eventfd succeeds, fcntl will. + tor_assert_nonfatal_unreached(); close(socks[0]); return -1; + // LCOV_EXCL_STOP } } } @@ -275,9 +278,12 @@ alert_sockets_create(alert_sockets_t *socks_out, uint32_t flags) fcntl(socks[1], F_SETFD, FD_CLOEXEC) < 0 || set_socket_nonblocking(socks[0]) < 0 || set_socket_nonblocking(socks[1]) < 0) { + // LCOV_EXCL_START -- if pipe succeeds, you can fcntl the output + tor_assert_nonfatal_unreached(); close(socks[0]); close(socks[1]); return -1; + // LCOV_EXCL_STOP } socks_out->read_fd = socks[0]; socks_out->write_fd = socks[1]; @@ -292,9 +298,12 @@ alert_sockets_create(alert_sockets_t *socks_out, uint32_t flags) tor_socketpair(AF_UNIX, SOCK_STREAM, 0, socks) == 0) { if (set_socket_nonblocking(socks[0]) < 0 || set_socket_nonblocking(socks[1])) { + // LCOV_EXCL_START -- if socketpair worked, you can make it nonblocking. + tor_assert_nonfatal_unreached(); tor_close_socket(socks[0]); tor_close_socket(socks[1]); return -1; + // LCOV_EXCL_STOP } socks_out->read_fd = socks[0]; socks_out->write_fd = socks[1]; diff --git a/src/common/torgzip.c b/src/common/torgzip.c index 71e55f8723..331bb5a017 100644 --- a/src/common/torgzip.c +++ b/src/common/torgzip.c @@ -46,34 +46,16 @@ #include <zlib.h> +#if defined ZLIB_VERNUM && ZLIB_VERNUM < 0x1200 +#error "We require zlib version 1.2 or later." +#endif + static size_t tor_zlib_state_size_precalc(int inflate, int windowbits, int memlevel); /** Total number of bytes allocated for zlib state */ static size_t total_zlib_allocation = 0; -/** Set to 1 if zlib is a version that supports gzip; set to 0 if it doesn't; - * set to -1 if we haven't checked yet. */ -static int gzip_is_supported = -1; - -/** Return true iff we support gzip-based compression. Otherwise, we need to - * use zlib. */ -int -is_gzip_supported(void) -{ - if (gzip_is_supported >= 0) - return gzip_is_supported; - - if (!strcmpstart(ZLIB_VERSION, "0.") || - !strcmpstart(ZLIB_VERSION, "1.0") || - !strcmpstart(ZLIB_VERSION, "1.1")) - gzip_is_supported = 0; - else - gzip_is_supported = 1; - - return gzip_is_supported; -} - /** Return a string representation of the version of the currently running * version of zlib. */ const char * @@ -165,12 +147,6 @@ tor_gzip_compress(char **out, size_t *out_len, *out = NULL; - if (method == GZIP_METHOD && !is_gzip_supported()) { - /* Old zlib version don't support gzip in deflateInit2 */ - log_warn(LD_BUG, "Gzip not supported with zlib %s", ZLIB_VERSION); - goto err; - } - stream = tor_malloc_zero(sizeof(struct z_stream_s)); stream->zalloc = Z_NULL; stream->zfree = Z_NULL; @@ -182,9 +158,11 @@ tor_gzip_compress(char **out, size_t *out_len, method_bits(method, HIGH_COMPRESSION), get_memlevel(HIGH_COMPRESSION), Z_DEFAULT_STRATEGY) != Z_OK) { + //LCOV_EXCL_START -- we can only provoke failure by giving junk arguments. log_warn(LD_GENERAL, "Error from deflateInit2: %s", stream->msg?stream->msg:"<no message>"); goto err; + //LCOV_EXCL_STOP } /* Guess 50% compression. */ @@ -237,13 +215,12 @@ tor_gzip_compress(char **out, size_t *out_len, * the newly unsigned field isn't negative." */ tor_assert(stream->total_out >= 0); #endif - if (((size_t)stream->total_out) > out_size + 4097) { - /* If we're wasting more than 4k, don't. */ - *out = tor_realloc(*out, stream->total_out + 1); - } if (deflateEnd(stream)!=Z_OK) { + // LCOV_EXCL_START -- unreachable if we handled the zlib structure right + tor_assert_nonfatal_unreached(); log_warn(LD_BUG, "Error freeing gzip structures"); goto err; + // LCOV_EXCL_STOP } tor_free(stream); @@ -291,12 +268,6 @@ tor_gzip_uncompress(char **out, size_t *out_len, tor_assert(in); tor_assert(in_len < UINT_MAX); - if (method == GZIP_METHOD && !is_gzip_supported()) { - /* Old zlib version don't support gzip in inflateInit2 */ - log_warn(LD_BUG, "Gzip not supported with zlib %s", ZLIB_VERSION); - return -1; - } - *out = NULL; stream = tor_malloc_zero(sizeof(struct z_stream_s)); @@ -308,9 +279,11 @@ tor_gzip_uncompress(char **out, size_t *out_len, if (inflateInit2(stream, method_bits(method, HIGH_COMPRESSION)) != Z_OK) { + // LCOV_EXCL_START -- can only hit this if we give bad inputs. log_warn(LD_GENERAL, "Error from inflateInit2: %s", stream->msg?stream->msg:"<no message>"); goto err; + // LCOV_EXCL_STOP } out_size = in_len * 2; /* guess 50% compression. */ @@ -451,12 +424,6 @@ tor_zlib_new(int compress, compress_method_t method, tor_zlib_state_t *out; int bits, memlevel; - if (method == GZIP_METHOD && !is_gzip_supported()) { - /* Old zlib version don't support gzip in inflateInit2 */ - log_warn(LD_BUG, "Gzip not supported with zlib %s", ZLIB_VERSION); - return NULL; - } - if (! compress) { /* use this setting for decompression, since we might have the * max number of window bits */ @@ -474,10 +441,10 @@ tor_zlib_new(int compress, compress_method_t method, if (deflateInit2(&out->stream, Z_BEST_COMPRESSION, Z_DEFLATED, bits, memlevel, Z_DEFAULT_STRATEGY) != Z_OK) - goto err; + goto err; // LCOV_EXCL_LINE } else { if (inflateInit2(&out->stream, bits) != Z_OK) - goto err; + goto err; // LCOV_EXCL_LINE } out->allocation = tor_zlib_state_size_precalc(!compress, bits, memlevel); diff --git a/src/common/util.c b/src/common/util.c index 7217cdc81e..4b6df81b7d 100644 --- a/src/common/util.c +++ b/src/common/util.c @@ -1111,6 +1111,9 @@ tor_digest256_is_zero(const char *digest) /* Were there unexpected unconverted characters? */ \ if (!next && *endptr) \ goto err; \ + /* Illogical (max, min) inputs? */ \ + if (BUG(max < min)) \ + goto err; \ /* Is r within limits? */ \ if (r < min || r > max) \ goto err; \ diff --git a/src/common/util_format.c b/src/common/util_format.c index e40fe30680..9009e1a814 100644 --- a/src/common/util_format.c +++ b/src/common/util_format.c @@ -46,6 +46,9 @@ base32_encode(char *dest, size_t destlen, const char *src, size_t srclen) tor_assert(base32_encoded_size(srclen) <= destlen); tor_assert(destlen < SIZE_T_CEILING); + /* Make sure we leave no uninitialized data in the destination buffer. */ + memset(dest, 0, destlen); + for (i=0,bit=0; bit < nbits; ++i, bit+=5) { /* set v to the 16-bit value starting at src[bits/8], 0-padded. */ v = ((uint8_t)src[bit/8]) << 8; @@ -75,6 +78,7 @@ base32_decode(char *dest, size_t destlen, const char *src, size_t srclen) tor_assert((nbits/8) <= destlen); /* We need enough space. */ tor_assert(destlen < SIZE_T_CEILING); + /* Make sure we leave no uninitialized data in the destination buffer. */ memset(dest, 0, destlen); /* Convert base32 encoded chars to the 5-bit values that they represent. */ @@ -197,7 +201,8 @@ base64_encode(char *dest, size_t destlen, const char *src, size_t srclen, if (enclen > INT_MAX) return -1; - memset(dest, 0, enclen); + /* Make sure we leave no uninitialized data in the destination buffer. */ + memset(dest, 0, destlen); /* XXX/Yawning: If this ends up being too slow, this can be sped up * by separating the multiline format case and the normal case, and @@ -398,6 +403,7 @@ base64_decode(char *dest, size_t destlen, const char *src, size_t srclen) if (destlen > SIZE_T_CEILING) return -1; + /* Make sure we leave no uninitialized data in the destination buffer. */ memset(dest, 0, destlen); /* Iterate over all the bytes in src. Each one will add 0 or 6 bits to the @@ -472,6 +478,9 @@ base16_encode(char *dest, size_t destlen, const char *src, size_t srclen) tor_assert(destlen >= srclen*2+1); tor_assert(destlen < SIZE_T_CEILING); + /* Make sure we leave no uninitialized data in the destination buffer. */ + memset(dest, 0, destlen); + cp = dest; end = src+srclen; while (src<end) { @@ -515,20 +524,24 @@ hex_decode_digit(char c) return hex_decode_digit_(c); } -/** Given a hexadecimal string of <b>srclen</b> bytes in <b>src</b>, decode it - * and store the result in the <b>destlen</b>-byte buffer at <b>dest</b>. - * Return 0 on success, -1 on failure. */ +/** Given a hexadecimal string of <b>srclen</b> bytes in <b>src</b>, decode + * it and store the result in the <b>destlen</b>-byte buffer at <b>dest</b>. + * Return the number of bytes decoded on success, -1 on failure. If + * <b>destlen</b> is greater than INT_MAX or less than half of + * <b>srclen</b>, -1 is returned. */ int base16_decode(char *dest, size_t destlen, const char *src, size_t srclen) { const char *end; - + char *dest_orig = dest; int v1,v2; + if ((srclen % 2) != 0) return -1; - if (destlen < srclen/2 || destlen > SIZE_T_CEILING) + if (destlen < srclen/2 || destlen > INT_MAX) return -1; + /* Make sure we leave no uninitialized data in the destination buffer. */ memset(dest, 0, destlen); end = src+srclen; @@ -541,6 +554,9 @@ base16_decode(char *dest, size_t destlen, const char *src, size_t srclen) ++dest; src+=2; } - return 0; + + tor_assert((dest-dest_orig) <= (ptrdiff_t) destlen); + + return (int) (dest-dest_orig); } diff --git a/src/common/workqueue.c b/src/common/workqueue.c index 0a38550de0..48c0cca01f 100644 --- a/src/common/workqueue.c +++ b/src/common/workqueue.c @@ -262,9 +262,12 @@ workerthread_new(void *state, threadpool_t *pool, replyqueue_t *replyqueue) thr->in_pool = pool; if (spawn_func(worker_thread_main, thr) < 0) { + //LCOV_EXCL_START + tor_assert_nonfatal_unreached(); log_err(LD_GENERAL, "Can't launch worker thread."); tor_free(thr); return NULL; + //LCOV_EXCL_STOP } return thr; @@ -375,8 +378,8 @@ threadpool_queue_update(threadpool_t *pool, static int threadpool_start_threads(threadpool_t *pool, int n) { - if (n < 0) - return -1; + if (BUG(n < 0)) + return -1; // LCOV_EXCL_LINE if (n > MAX_THREADS) n = MAX_THREADS; @@ -391,9 +394,12 @@ threadpool_start_threads(threadpool_t *pool, int n) workerthread_t *thr = workerthread_new(state, pool, pool->reply_queue); if (!thr) { + //LCOV_EXCL_START + tor_assert_nonfatal_unreached(); pool->free_thread_state_fn(state); tor_mutex_release(&pool->lock); return -1; + //LCOV_EXCL_STOP } thr->index = pool->n_threads; pool->threads[pool->n_threads++] = thr; @@ -429,10 +435,13 @@ threadpool_new(int n_threads, pool->reply_queue = replyqueue; if (threadpool_start_threads(pool, n_threads) < 0) { + //LCOV_EXCL_START + tor_assert_nonfatal_unreached(); tor_cond_uninit(&pool->condition); tor_mutex_uninit(&pool->lock); tor_free(pool); return NULL; + //LCOV_EXCL_STOP } return pool; @@ -456,8 +465,10 @@ replyqueue_new(uint32_t alertsocks_flags) rq = tor_malloc_zero(sizeof(replyqueue_t)); if (alert_sockets_create(&rq->alert, alertsocks_flags) < 0) { + //LCOV_EXCL_START tor_free(rq); return NULL; + //LCOV_EXCL_STOP } tor_mutex_init(&rq->lock); @@ -486,10 +497,12 @@ void replyqueue_process(replyqueue_t *queue) { if (queue->alert.drain_fn(queue->alert.read_fd) < 0) { + //LCOV_EXCL_START static ratelim_t warn_limit = RATELIM_INIT(7200); log_fn_ratelim(&warn_limit, LOG_WARN, LD_GENERAL, "Failure from drain_fd: %s", tor_socket_strerror(tor_socket_errno(queue->alert.read_fd))); + //LCOV_EXCL_STOP } tor_mutex_acquire(&queue->lock); diff --git a/src/or/circuituse.c b/src/or/circuituse.c index d2c05bd66e..f344703331 100644 --- a/src/or/circuituse.c +++ b/src/or/circuituse.c @@ -2028,7 +2028,8 @@ circuit_get_open_circ_or_launch(entry_connection_t *conn, char *hexdigest = conn->chosen_exit_name+1; tor_addr_t addr; if (strlen(hexdigest) < HEX_DIGEST_LEN || - base16_decode(digest,DIGEST_LEN,hexdigest,HEX_DIGEST_LEN)<0) { + base16_decode(digest,DIGEST_LEN, + hexdigest,HEX_DIGEST_LEN) != DIGEST_LEN) { log_info(LD_DIR, "Broken exit digest on tunnel conn. Closing."); return -1; } diff --git a/src/or/config.c b/src/or/config.c index 8a3fb47790..cdd4f10e92 100644 --- a/src/or/config.c +++ b/src/or/config.c @@ -5330,7 +5330,7 @@ parse_bridge_line(const char *line) goto err; } if (base16_decode(bridge_line->digest, DIGEST_LEN, - fingerprint, HEX_DIGEST_LEN)<0) { + fingerprint, HEX_DIGEST_LEN) != DIGEST_LEN) { log_warn(LD_CONFIG, "Unable to decode Bridge key digest."); goto err; } @@ -5781,7 +5781,8 @@ parse_dir_authority_line(const char *line, dirinfo_type_t required_type, } else if (!strcasecmpstart(flag, "v3ident=")) { char *idstr = flag + strlen("v3ident="); if (strlen(idstr) != HEX_DIGEST_LEN || - base16_decode(v3_digest, DIGEST_LEN, idstr, HEX_DIGEST_LEN)<0) { + base16_decode(v3_digest, DIGEST_LEN, + idstr, HEX_DIGEST_LEN) != DIGEST_LEN) { log_warn(LD_CONFIG, "Bad v3 identity digest '%s' on DirAuthority line", flag); } else { @@ -5830,7 +5831,8 @@ parse_dir_authority_line(const char *line, dirinfo_type_t required_type, fingerprint, (int)strlen(fingerprint)); goto err; } - if (base16_decode(digest, DIGEST_LEN, fingerprint, HEX_DIGEST_LEN)<0) { + if (base16_decode(digest, DIGEST_LEN, + fingerprint, HEX_DIGEST_LEN) != DIGEST_LEN) { log_warn(LD_CONFIG, "Unable to decode DirAuthority key digest."); goto err; } @@ -5898,8 +5900,8 @@ parse_dir_fallback_line(const char *line, orport = (int)tor_parse_long(cp+strlen("orport="), 10, 1, 65535, &ok, NULL); } else if (!strcmpstart(cp, "id=")) { - ok = !base16_decode(id, DIGEST_LEN, - cp+strlen("id="), strlen(cp)-strlen("id=")); + ok = base16_decode(id, DIGEST_LEN, cp+strlen("id="), + strlen(cp)-strlen("id=")) == DIGEST_LEN; } else if (!strcasecmpstart(cp, "ipv6=")) { if (ipv6_addrport_ptr) { log_warn(LD_CONFIG, "Redundant ipv6 addr/port on FallbackDir line"); diff --git a/src/or/control.c b/src/or/control.c index 1e90135e21..6e5dcf62e6 100644 --- a/src/or/control.c +++ b/src/or/control.c @@ -1211,7 +1211,8 @@ decode_hashed_passwords(config_line_t *passwords) const char *hashed = cl->value; if (!strcmpstart(hashed, "16:")) { - if (base16_decode(decoded, sizeof(decoded), hashed+3, strlen(hashed+3))<0 + if (base16_decode(decoded, sizeof(decoded), hashed+3, strlen(hashed+3)) + != S2K_RFC2440_SPECIFIER_LEN + DIGEST_LEN || strlen(hashed+3) != (S2K_RFC2440_SPECIFIER_LEN+DIGEST_LEN)*2) { goto err; } @@ -1262,7 +1263,8 @@ handle_control_authenticate(control_connection_t *conn, uint32_t len, tor_assert(i>0); password_len = i/2; password = tor_malloc(password_len + 1); - if (base16_decode(password, password_len+1, body, i)<0) { + if (base16_decode(password, password_len+1, body, i) + != (int) password_len) { connection_write_str_to_buf( "551 Invalid hexadecimal encoding. Maybe you tried a plain text " "password? If so, the standard requires that you put it in " @@ -2026,7 +2028,8 @@ getinfo_helper_dir(control_connection_t *control_conn, if (strlen(question) == HEX_DIGEST_LEN) { char d[DIGEST_LEN]; signed_descriptor_t *sd = NULL; - if (base16_decode(d, sizeof(d), question, strlen(question))==0) { + if (base16_decode(d, sizeof(d), question, strlen(question)) + != sizeof(d)) { /* XXXX this test should move into extrainfo_get_by_descriptor_digest, * but I don't want to risk affecting other parts of the code, * especially since the rules for using our own extrainfo (including @@ -3442,7 +3445,8 @@ handle_control_authchallenge(control_connection_t *conn, uint32_t len, client_nonce = tor_malloc_zero(client_nonce_len); if (base16_decode(client_nonce, client_nonce_len, - cp, client_nonce_encoded_len) < 0) { + cp, client_nonce_encoded_len) + != (int) client_nonce_len) { connection_write_str_to_buf("513 Invalid base16 client nonce\r\n", conn); connection_mark_for_close(TO_CONN(conn)); diff --git a/src/or/directory.c b/src/or/directory.c index c1b5ae7519..5886a73403 100644 --- a/src/or/directory.c +++ b/src/or/directory.c @@ -873,7 +873,7 @@ connection_dir_retry_bridges(smartlist_t *descs) char digest[DIGEST_LEN]; SMARTLIST_FOREACH(descs, const char *, cp, { - if (base16_decode(digest, DIGEST_LEN, cp, strlen(cp))<0) { + if (base16_decode(digest, DIGEST_LEN, cp, strlen(cp)) != DIGEST_LEN) { log_warn(LD_BUG, "Malformed fingerprint in list: %s", escaped(cp)); continue; @@ -2682,7 +2682,8 @@ client_likes_consensus(networkstatus_t *v, const char *want_url) if (want_len > DIGEST_LEN) want_len = DIGEST_LEN; - if (base16_decode(want_digest, DIGEST_LEN, d, want_len*2) < 0) { + if (base16_decode(want_digest, DIGEST_LEN, d, want_len*2) + != (int) want_len) { log_fn(LOG_PROTOCOL_WARN, LD_DIR, "Failed to decode requested authority digest %s.", escaped(d)); continue; @@ -4097,7 +4098,7 @@ dir_routerdesc_download_failed(smartlist_t *failed, int status_code, } SMARTLIST_FOREACH_BEGIN(failed, const char *, cp) { download_status_t *dls = NULL; - if (base16_decode(digest, DIGEST_LEN, cp, strlen(cp)) < 0) { + if (base16_decode(digest, DIGEST_LEN, cp, strlen(cp)) != DIGEST_LEN) { log_warn(LD_BUG, "Malformed fingerprint in list: %s", escaped(cp)); continue; } @@ -4194,9 +4195,10 @@ dir_split_resource_into_fingerprint_pairs(const char *res, "Skipping digest pair %s with missing dash.", escaped(cp)); } else { fp_pair_t pair; - if (base16_decode(pair.first, DIGEST_LEN, cp, HEX_DIGEST_LEN)<0 || - base16_decode(pair.second, - DIGEST_LEN, cp+HEX_DIGEST_LEN+1, HEX_DIGEST_LEN)<0) { + if (base16_decode(pair.first, DIGEST_LEN, + cp, HEX_DIGEST_LEN) != DIGEST_LEN || + base16_decode(pair.second,DIGEST_LEN, + cp+HEX_DIGEST_LEN+1, HEX_DIGEST_LEN) != DIGEST_LEN) { log_info(LD_DIR, "Skipping non-decodable digest pair %s", escaped(cp)); } else { smartlist_add(pairs_result, tor_memdup(&pair, sizeof(pair))); @@ -4274,8 +4276,9 @@ dir_split_resource_into_fingerprints(const char *resource, } d = tor_malloc_zero(digest_len); if (decode_hex ? - (base16_decode(d, digest_len, cp, hex_digest_len)<0) : - (base64_decode(d, digest_len, cp, base64_digest_len)<0)) { + (base16_decode(d, digest_len, cp, hex_digest_len) != digest_len) : + (base64_decode(d, digest_len, cp, base64_digest_len) + != digest_len)) { log_info(LD_DIR, "Skipping non-decodable digest %s", escaped(cp)); smartlist_del_keeporder(fp_tmp, i--); goto again; diff --git a/src/or/dirserv.c b/src/or/dirserv.c index fa698701c3..e616373b61 100644 --- a/src/or/dirserv.c +++ b/src/or/dirserv.c @@ -122,7 +122,8 @@ add_fingerprint_to_dir(const char *fp, authdir_config_t *list, fingerprint = tor_strdup(fp); tor_strstrip(fingerprint, " "); - if (base16_decode(d, DIGEST_LEN, fingerprint, strlen(fingerprint))) { + if (base16_decode(d, DIGEST_LEN, + fingerprint, strlen(fingerprint)) != DIGEST_LEN) { log_warn(LD_DIRSERV, "Couldn't decode fingerprint \"%s\"", escaped(fp)); tor_free(fingerprint); @@ -199,7 +200,7 @@ dirserv_load_fingerprint_file(void) tor_strstrip(fingerprint, " "); /* remove spaces */ if (strlen(fingerprint) != HEX_DIGEST_LEN || base16_decode(digest_tmp, sizeof(digest_tmp), - fingerprint, HEX_DIGEST_LEN) < 0) { + fingerprint, HEX_DIGEST_LEN) != sizeof(digest_tmp)) { log_notice(LD_CONFIG, "Invalid fingerprint (nickname '%s', " "fingerprint %s). Skipping.", @@ -2274,7 +2275,8 @@ guardfraction_file_parse_guard_line(const char *guard_line, inputs_tmp = smartlist_get(sl, 0); if (strlen(inputs_tmp) != HEX_DIGEST_LEN || - base16_decode(guard_id, DIGEST_LEN, inputs_tmp, HEX_DIGEST_LEN)) { + base16_decode(guard_id, DIGEST_LEN, + inputs_tmp, HEX_DIGEST_LEN) != DIGEST_LEN) { tor_asprintf(err_msg, "bad digest '%s'", inputs_tmp); goto done; } @@ -2578,7 +2580,8 @@ measured_bw_line_parse(measured_bw_line_t *out, const char *orig_line) cp+=strlen("node_id=$"); if (strlen(cp) != HEX_DIGEST_LEN || - base16_decode(out->node_id, DIGEST_LEN, cp, HEX_DIGEST_LEN)) { + base16_decode(out->node_id, DIGEST_LEN, + cp, HEX_DIGEST_LEN) != DIGEST_LEN) { log_warn(LD_DIRSERV, "Invalid node_id in bandwidth file line: %s", escaped(orig_line)); tor_free(line); diff --git a/src/or/entrynodes.c b/src/or/entrynodes.c index a210ca1125..68241af987 100644 --- a/src/or/entrynodes.c +++ b/src/or/entrynodes.c @@ -1253,7 +1253,7 @@ entry_guards_parse_state(or_state_t *state, int set, char **msg) } else { strlcpy(node->nickname, smartlist_get(args,0), MAX_NICKNAME_LEN+1); if (base16_decode(node->identity, DIGEST_LEN, smartlist_get(args,1), - strlen(smartlist_get(args,1)))<0) { + strlen(smartlist_get(args,1))) != DIGEST_LEN) { *msg = tor_strdup("Unable to parse entry nodes: " "Bad hex digest for EntryGuard"); } @@ -1309,8 +1309,9 @@ entry_guards_parse_state(or_state_t *state, int set, char **msg) log_warn(LD_BUG, "EntryGuardAddedBy line is not long enough."); continue; } - if (base16_decode(d, sizeof(d), line->value, HEX_DIGEST_LEN)<0 || - line->value[HEX_DIGEST_LEN] != ' ') { + if (base16_decode(d, sizeof(d), + line->value, HEX_DIGEST_LEN) != sizeof(d) || + line->value[HEX_DIGEST_LEN] != ' ') { log_warn(LD_BUG, "EntryGuardAddedBy line %s does not begin with " "hex digest", escaped(line->value)); continue; diff --git a/src/or/fallback_dirs.inc b/src/or/fallback_dirs.inc index 8e82a3fb2f..58c67c0bcb 100644 --- a/src/or/fallback_dirs.inc +++ b/src/or/fallback_dirs.inc @@ -40,8 +40,10 @@ URL: https:onionoo.torproject.orguptime?first_seen_days=7-&flag=V2Dir&type=relay " weight=10", "185.61.138.18:8080 orport=4443 id=2541759BEC04D37811C2209A88E863320271EC9C" " weight=10", +/* Fallback was on 0.2.8.2-alpha list, but went down before 0.2.8.5 "51.254.215.121:80 orport=443 id=262B66AD25C79588AD1FC8ED0E966395B47E5C1D" " weight=10", +*/ "194.150.168.79:11112 orport=11111 id=29F1020B94BE25E6BE1AD13E93CE19D2131B487C" " weight=10", "144.76.26.175:9012 orport=9011 id=2BA2C8E96B2590E1072AECE2BDB5C48921BF8510" @@ -90,8 +92,10 @@ URL: https:onionoo.torproject.orguptime?first_seen_days=7-&flag=V2Dir&type=relay " weight=10", "78.142.142.246:80 orport=443 id=5A5E03355C1908EBF424CAF1F3ED70782C0D2F74" " weight=10", +/* Fallback was on 0.2.8.2-alpha list, but went down before 0.2.8.5 "185.100.85.138:80 orport=46356 id=5C4DF16A0029CC4F67D3E127356E68F219269859" " weight=10", +*/ "178.16.208.62:80 orport=443 id=5CF8AFA5E4B0BB88942A44A3F3AAE08C3BDFD60B" " ipv6=[2a00:1c20:4089:1234:a6a4:2926:d0af:dfee]:443" " weight=10", @@ -120,12 +124,16 @@ URL: https:onionoo.torproject.orguptime?first_seen_days=7-&flag=V2Dir&type=relay " weight=10", "192.87.28.82:9030 orport=9001 id=844AE9CAD04325E955E2BE1521563B79FE7094B7" " weight=10", +/* Fallback was on 0.2.8.2-alpha list, but changed address before 0.2.8.5 "84.219.173.60:9030 orport=443 id=855BC2DABE24C861CD887DB9B2E950424B49FC34" " weight=10", +*/ "163.172.138.22:80 orport=443 id=8664DC892540F3C789DB37008236C096C871734D" " weight=10", +/* Fallback was on 0.2.8.2-alpha list, but downloads were slow before 0.2.8.5 "185.96.88.29:80 orport=443 id=86C281AD135058238D7A337D546C902BE8505DDE" " weight=10", +*/ "93.180.156.84:9030 orport=9001 id=8844D87E9B038BE3270938F05AF797E1D3C74C0F" " weight=10", "178.217.184.32:9030 orport=443 id=8B7F47AE1A5D954A3E58ACDE0865D09DBA5B738D" @@ -140,9 +148,11 @@ URL: https:onionoo.torproject.orguptime?first_seen_days=7-&flag=V2Dir&type=relay " weight=10", "91.219.237.244:80 orport=443 id=92ECC9E0E2AF81BB954719B189AC362E254AD4A5" " weight=10", +/* Fallback was on 0.2.8.2-alpha list, but changed fingerprint before 0.2.8.5 "46.101.102.71:80 orport=443 id=9504CB22EEB25D344DE63CB7A6F2C46F895C3686" " ipv6=[2a03:b0c0:3:d0::2ed:7001]:9050" " weight=10", +*/ "85.214.206.219:9030 orport=9001 id=98F8D5F359949E41DE8DF3DBB1975A86E96A84A0" " weight=10", "81.7.10.93:31336 orport=31337 id=99E246DB480B313A3012BC3363093CC26CD209C7" @@ -158,9 +168,11 @@ URL: https:onionoo.torproject.orguptime?first_seen_days=7-&flag=V2Dir&type=relay " weight=10", "192.34.63.137:9030 orport=443 id=ABCB4965F1FEE193602B50A365425105C889D3F8" " weight=10", +/* Fallback was on 0.2.8.2-alpha list, but had low uptime before 0.2.8.5 "195.154.164.243:80 orport=443 id=AC66FFA4AB35A59EBBF5BF4C70008BF24D8A7A5C" " ipv6=[2001:bc8:399f:f000::1]:993" " weight=10", +*/ "86.59.119.88:80 orport=443 id=ACD889D86E02EDDAB1AFD81F598C0936238DC6D0" " weight=10", "163.172.131.88:80 orport=443 id=AD253B49E303C6AB1E048B014392AC569E8A7DAE" @@ -177,8 +189,10 @@ URL: https:onionoo.torproject.orguptime?first_seen_days=7-&flag=V2Dir&type=relay " weight=10", "193.11.114.46:9032 orport=9003 id=B83DC1558F0D34353BB992EF93AFEAFDB226A73E" " weight=10", +/* Fallback was on 0.2.8.2-alpha list, but downloads were slow before 0.2.8.5 "178.62.36.64:9030 orport=9001 id=B87C84E38DAECFFFFDE98E5AEE5786AFDC748F2C" " weight=10", +*/ "197.231.221.211:9030 orport=9001 id=BC630CBBB518BE7E9F4E09712AB0269E9DC7D626" " weight=10", "198.96.155.3:8080 orport=5001 id=BCEDF6C193AA687AE471B8A22EBF6BC57C2D285E" @@ -197,17 +211,21 @@ URL: https:onionoo.torproject.orguptime?first_seen_days=7-&flag=V2Dir&type=relay "178.62.199.226:80 orport=443 id=CBEFF7BA4A4062045133C053F2D70524D8BBE5BE" " ipv6=[2a03:b0c0:2:d0::b7:5001]:443" " weight=10", +/* Fallback was on 0.2.8.2-alpha list, but went down before 0.2.8.5 "81.7.17.171:80 orport=443 id=CFECDDCA990E3EF7B7EC958B22441386B6B8D820" " ipv6=[2a02:180:1:1::517:11ab]:443" " weight=10", +*/ "134.119.3.164:9030 orport=9001 id=D1B8AAA98C65F3DF7D8BB3AF881CAEB84A33D8EE" " weight=10", "185.13.38.75:9030 orport=9001 id=D2A1703758A0FBBA026988B92C2F88BAB59F9361" " weight=10", "37.187.115.157:9030 orport=9001 id=D5039E1EBFD96D9A3F9846BF99EC9F75EDDE902A" " weight=10", +/* Fallback was on 0.2.8.2-alpha list, but lost Guard flag before 0.2.8.5 "185.14.185.240:9030 orport=443 id=D62FB817B0288085FAC38A6DC8B36DCD85B70260" " weight=10", +*/ "37.221.162.226:9030 orport=9001 id=D64366987CB39F61AD21DBCF8142FA0577B92811" " weight=10", "193.35.52.53:9030 orport=9001 id=DAA39FC00B196B353C2A271459C305C429AF09E4" diff --git a/src/or/main.c b/src/or/main.c index 9f3306dc4f..4de2e70a1d 100644 --- a/src/or/main.c +++ b/src/or/main.c @@ -2004,18 +2004,24 @@ check_fw_helper_app_callback(time_t now, const or_options_t *options) return PORT_FORWARDING_CHECK_INTERVAL; } +/** Callback to write heartbeat message in the logs. */ static int heartbeat_callback(time_t now, const or_options_t *options) { static int first = 1; - /* 12. write the heartbeat message */ + + /* Check if heartbeat is disabled */ + if (!options->HeartbeatPeriod) { + return PERIODIC_EVENT_NO_UPDATE; + } + + /* Write the heartbeat message */ if (first) { first = 0; /* Skip the first one. */ } else { log_heartbeat(now); } - /* XXXX This isn't such a good way to handle possible changes in the - * callback event */ + return options->HeartbeatPeriod; } diff --git a/src/or/networkstatus.c b/src/or/networkstatus.c index d5c8a262f0..3471288969 100644 --- a/src/or/networkstatus.c +++ b/src/or/networkstatus.c @@ -2216,7 +2216,7 @@ getinfo_helper_networkstatus(control_connection_t *conn, if (*q == '$') ++q; - if (base16_decode(d, DIGEST_LEN, q, strlen(q))) { + if (base16_decode(d, DIGEST_LEN, q, strlen(q)) != DIGEST_LEN) { *errmsg = "Data not decodeable as hex"; return -1; } diff --git a/src/or/rendservice.c b/src/or/rendservice.c index ff23050300..c50de83f7e 100644 --- a/src/or/rendservice.c +++ b/src/or/rendservice.c @@ -3460,8 +3460,6 @@ rend_service_desc_has_uploaded(const rend_data_t *rend_data) service = rend_service_get_by_service_id(rend_data->onion_address); if (service == NULL) { - log_warn(LD_REND, "Service %s not found after descriptor upload", - safe_str_client(rend_data->onion_address)); return; } diff --git a/src/or/rephist.c b/src/or/rephist.c index 72933550ed..8992571c52 100644 --- a/src/or/rephist.c +++ b/src/or/rephist.c @@ -1074,7 +1074,8 @@ rep_hist_load_mtbf_data(time_t now) if (mtbf_idx > i) i = mtbf_idx; } - if (base16_decode(digest, DIGEST_LEN, hexbuf, HEX_DIGEST_LEN) < 0) { + if (base16_decode(digest, DIGEST_LEN, + hexbuf, HEX_DIGEST_LEN) != DIGEST_LEN) { log_warn(LD_HIST, "Couldn't hex string %s", escaped(hexbuf)); continue; } diff --git a/src/or/routerlist.c b/src/or/routerlist.c index 9cd5ef171c..b6dab1b516 100644 --- a/src/or/routerlist.c +++ b/src/or/routerlist.c @@ -2688,7 +2688,8 @@ hex_digest_nickname_decode(const char *hexdigest, return -1; } - if (base16_decode(digest_out, DIGEST_LEN, hexdigest, HEX_DIGEST_LEN)<0) + if (base16_decode(digest_out, DIGEST_LEN, + hexdigest, HEX_DIGEST_LEN) != DIGEST_LEN) return -1; return 0; } @@ -2773,7 +2774,7 @@ hexdigest_to_digest(const char *hexdigest, char *digest) if (hexdigest[0]=='$') ++hexdigest; if (strlen(hexdigest) < HEX_DIGEST_LEN || - base16_decode(digest,DIGEST_LEN,hexdigest,HEX_DIGEST_LEN) < 0) + base16_decode(digest,DIGEST_LEN,hexdigest,HEX_DIGEST_LEN) != DIGEST_LEN) return -1; return 0; } diff --git a/src/or/routerparse.c b/src/or/routerparse.c index a612a94223..569c73f8e5 100644 --- a/src/or/routerparse.c +++ b/src/or/routerparse.c @@ -1513,7 +1513,8 @@ router_parse_entry_from_string(const char *s, const char *end, char d[DIGEST_LEN]; tor_assert(tok->n_args == 1); tor_strstrip(tok->args[0], " "); - if (base16_decode(d, DIGEST_LEN, tok->args[0], strlen(tok->args[0]))) { + if (base16_decode(d, DIGEST_LEN, + tok->args[0], strlen(tok->args[0])) != DIGEST_LEN) { log_warn(LD_DIR, "Couldn't decode router fingerprint %s", escaped(tok->args[0])); goto err; @@ -1594,8 +1595,10 @@ router_parse_entry_from_string(const char *s, const char *end, if ((tok = find_opt_by_keyword(tokens, K_EXTRA_INFO_DIGEST))) { tor_assert(tok->n_args >= 1); if (strlen(tok->args[0]) == HEX_DIGEST_LEN) { - base16_decode(router->cache_info.extra_info_digest, - DIGEST_LEN, tok->args[0], HEX_DIGEST_LEN); + if (base16_decode(router->cache_info.extra_info_digest, DIGEST_LEN, + tok->args[0], HEX_DIGEST_LEN) != DIGEST_LEN) { + log_warn(LD_DIR,"Invalid extra info digest"); + } } else { log_warn(LD_DIR, "Invalid extra info digest %s", escaped(tok->args[0])); } @@ -1738,7 +1741,7 @@ extrainfo_parse_entry_from_string(const char *s, const char *end, strlcpy(extrainfo->nickname, tok->args[0], sizeof(extrainfo->nickname)); if (strlen(tok->args[1]) != HEX_DIGEST_LEN || base16_decode(extrainfo->cache_info.identity_digest, DIGEST_LEN, - tok->args[1], HEX_DIGEST_LEN)) { + tok->args[1], HEX_DIGEST_LEN) != DIGEST_LEN) { log_warn(LD_DIR,"Invalid fingerprint %s on \"extra-info\"", escaped(tok->args[1])); goto err; @@ -1960,7 +1963,7 @@ authority_cert_parse_from_string(const char *s, const char **end_of_string) tok = find_by_keyword(tokens, K_FINGERPRINT); tor_assert(tok->n_args); if (base16_decode(fp_declared, DIGEST_LEN, tok->args[0], - strlen(tok->args[0]))) { + strlen(tok->args[0])) != DIGEST_LEN) { log_warn(LD_DIR, "Couldn't decode key certificate fingerprint %s", escaped(tok->args[0])); goto err; @@ -3097,7 +3100,8 @@ networkstatus_parse_vote_from_string(const char *s, const char **eos_out, voter->nickname = tor_strdup(tok->args[0]); if (strlen(tok->args[1]) != HEX_DIGEST_LEN || base16_decode(voter->identity_digest, sizeof(voter->identity_digest), - tok->args[1], HEX_DIGEST_LEN) < 0) { + tok->args[1], HEX_DIGEST_LEN) + != sizeof(voter->identity_digest)) { log_warn(LD_DIR, "Error decoding identity digest %s in " "network-status document.", escaped(tok->args[1])); goto err; @@ -3146,7 +3150,8 @@ networkstatus_parse_vote_from_string(const char *s, const char **eos_out, } if (strlen(tok->args[0]) != HEX_DIGEST_LEN || base16_decode(voter->vote_digest, sizeof(voter->vote_digest), - tok->args[0], HEX_DIGEST_LEN) < 0) { + tok->args[0], HEX_DIGEST_LEN) + != sizeof(voter->vote_digest)) { log_warn(LD_DIR, "Error decoding vote digest %s in " "network-status consensus.", escaped(tok->args[0])); goto err; @@ -3171,7 +3176,7 @@ networkstatus_parse_vote_from_string(const char *s, const char **eos_out, if (strlen(tok->args[0]) == HEX_DIGEST_LEN) { networkstatus_voter_info_t *voter = smartlist_get(ns->voters, 0); if (base16_decode(voter->legacy_id_digest, DIGEST_LEN, - tok->args[0], HEX_DIGEST_LEN)<0) + tok->args[0], HEX_DIGEST_LEN) != DIGEST_LEN) bad = 1; else bad = 0; @@ -3332,7 +3337,8 @@ networkstatus_parse_vote_from_string(const char *s, const char **eos_out, if (strlen(id_hexdigest) != HEX_DIGEST_LEN || base16_decode(declared_identity, sizeof(declared_identity), - id_hexdigest, HEX_DIGEST_LEN) < 0) { + id_hexdigest, HEX_DIGEST_LEN) + != sizeof(declared_identity)) { log_warn(LD_DIR, "Error decoding declared identity %s in " "network-status document.", escaped(id_hexdigest)); goto err; @@ -3347,7 +3353,8 @@ networkstatus_parse_vote_from_string(const char *s, const char **eos_out, sig->alg = alg; if (strlen(sk_hexdigest) != HEX_DIGEST_LEN || base16_decode(sig->signing_key_digest, sizeof(sig->signing_key_digest), - sk_hexdigest, HEX_DIGEST_LEN) < 0) { + sk_hexdigest, HEX_DIGEST_LEN) + != sizeof(sig->signing_key_digest)) { log_warn(LD_DIR, "Error decoding declared signing key digest %s in " "network-status document.", escaped(sk_hexdigest)); tor_free(sig); @@ -3549,7 +3556,7 @@ networkstatus_parse_detached_signatures(const char *s, const char *eos) continue; } if (base16_decode(digests->d[alg], digest_length, - hexdigest, strlen(hexdigest)) < 0) { + hexdigest, strlen(hexdigest)) != (int) digest_length) { log_warn(LD_DIR, "Bad encoding on consensus-digest in detached " "networkstatus signatures"); goto err; @@ -3622,14 +3629,14 @@ networkstatus_parse_detached_signatures(const char *s, const char *eos) if (strlen(id_hexdigest) != HEX_DIGEST_LEN || base16_decode(id_digest, sizeof(id_digest), - id_hexdigest, HEX_DIGEST_LEN) < 0) { + id_hexdigest, HEX_DIGEST_LEN) != sizeof(id_digest)) { log_warn(LD_DIR, "Error decoding declared identity %s in " "network-status vote.", escaped(id_hexdigest)); goto err; } if (strlen(sk_hexdigest) != HEX_DIGEST_LEN || base16_decode(sk_digest, sizeof(sk_digest), - sk_hexdigest, HEX_DIGEST_LEN) < 0) { + sk_hexdigest, HEX_DIGEST_LEN) != sizeof(sk_digest)) { log_warn(LD_DIR, "Error decoding declared signing key digest %s in " "network-status vote.", escaped(sk_hexdigest)); goto err; @@ -4831,7 +4838,7 @@ tor_version_parse(const char *s, tor_version_t *out) memwipe(digest, 0, sizeof(digest)); if ( hexlen == 0 || (hexlen % 2) == 1) return -1; - if (base16_decode(digest, hexlen/2, cp, hexlen)) + if (base16_decode(digest, hexlen/2, cp, hexlen) != hexlen/2) return -1; memcpy(out->git_tag, digest, hexlen/2); out->git_tag_len = hexlen/2; diff --git a/src/test/include.am b/src/test/include.am index fa660f5302..5a91c74cde 100644 --- a/src/test/include.am +++ b/src/test/include.am @@ -9,6 +9,12 @@ TESTS_ENVIRONMENT = \ export TESTING_TOR_BINARY="$(TESTING_TOR_BINARY)"; TESTSCRIPTS = src/test/test_zero_length_keys.sh \ + src/test/test_workqueue_cancel.sh \ + src/test/test_workqueue_efd.sh \ + src/test/test_workqueue_efd2.sh \ + src/test/test_workqueue_pipe.sh \ + src/test/test_workqueue_pipe2.sh \ + src/test/test_workqueue_socketpair.sh \ src/test/test_switch_id.sh if USEPYTHON @@ -16,7 +22,8 @@ TESTSCRIPTS += src/test/test_ntor.sh src/test/test_bt.sh endif TESTS += src/test/test src/test/test-slow src/test/test-memwipe \ - src/test/test_workqueue src/test/test_keygen.sh \ + src/test/test_workqueue \ + src/test/test_keygen.sh \ src/test/test-timers \ $(TESTSCRIPTS) @@ -257,4 +264,11 @@ EXTRA_DIST += \ src/test/test_zero_length_keys.sh \ src/test/test_ntor.sh src/test/test_bt.sh \ src/test/test-network.sh \ - src/test/test_switch_id.sh + src/test/test_switch_id.sh \ + src/test/test_workqueue_cancel.sh \ + src/test/test_workqueue_efd.sh \ + src/test/test_workqueue_efd2.sh \ + src/test/test_workqueue_pipe.sh \ + src/test/test_workqueue_pipe2.sh \ + src/test/test_workqueue_socketpair.sh + diff --git a/src/test/test_bt.sh b/src/test/test_bt.sh index fe1781659d..312905a4e2 100755 --- a/src/test/test_bt.sh +++ b/src/test/test_bt.sh @@ -8,4 +8,6 @@ export ASAN_OPTIONS="handle_segv=0:allow_user_segv_handler=1" "${builddir:-.}/src/test/test-bt-cl" assert 2>&1 | "${PYTHON:-python}" "${abs_top_srcdir:-.}/src/test/bt_test.py" || exitcode="$?" "${builddir:-.}/src/test/test-bt-cl" crash 2>&1 | "${PYTHON:-python}" "${abs_top_srcdir:-.}/src/test/bt_test.py" || exitcode="$?" +"${builddir:-.}/src/test/test-bt-cl" none || exitcode="$?" + exit ${exitcode} diff --git a/src/test/test_crypto.c b/src/test/test_crypto.c index bf4b68efe2..ba2fb86246 100644 --- a/src/test/test_crypto.c +++ b/src/test/test_crypto.c @@ -1521,7 +1521,7 @@ test_crypto_formats(void *arg) strlcpy(data1, "f0d678affc000100", 1024); i = base16_decode(data2, 8, data1, 16); - tt_int_op(i,OP_EQ, 0); + tt_int_op(i,OP_EQ, 8); tt_mem_op(data2,OP_EQ, "\xf0\xd6\x78\xaf\xfc\x00\x01\x00",8); /* now try some failing base16 decodes */ @@ -2537,8 +2537,9 @@ test_crypto_ed25519_testvectors(void *arg) #define DECODE(p,s) base16_decode((char*)(p),sizeof(p),(s),strlen(s)) #define EQ(a,h) test_memeq_hex((const char*)(a), (h)) - tt_int_op(0, OP_EQ, DECODE(sk, ED25519_SECRET_KEYS[i])); - tt_int_op(0, OP_EQ, DECODE(blinding_param, ED25519_BLINDING_PARAMS[i])); + tt_int_op(sizeof(sk), OP_EQ, DECODE(sk, ED25519_SECRET_KEYS[i])); + tt_int_op(sizeof(blinding_param), OP_EQ, DECODE(blinding_param, + ED25519_BLINDING_PARAMS[i])); tt_int_op(0, OP_EQ, ed25519_secret_key_from_seed(&esk, sk)); EQ(esk.seckey, ED25519_EXPANDED_SECRET_KEYS[i]); diff --git a/src/test/test_dir.c b/src/test/test_dir.c index 7acb4a3ba3..b8dcab39d5 100644 --- a/src/test/test_dir.c +++ b/src/test/test_dir.c @@ -580,7 +580,7 @@ test_dir_extrainfo_parsing(void *arg) crypto_pk_t *pk = ri->identity_pkey = crypto_pk_new(); \ tt_assert(! crypto_pk_read_public_key_from_string(pk, \ name##_KEY, strlen(name##_KEY))); \ - tt_int_op(0,OP_EQ,base16_decode(d, 20, name##_FP, strlen(name##_FP))); \ + tt_int_op(20,OP_EQ,base16_decode(d, 20, name##_FP, strlen(name##_FP))); \ digestmap_set((digestmap_t*)map, d, ri); \ ri = NULL; \ } while (0) diff --git a/src/test/test_guardfraction.c b/src/test/test_guardfraction.c index 300590a3d9..130aff11aa 100644 --- a/src/test/test_guardfraction.c +++ b/src/test/test_guardfraction.c @@ -40,7 +40,7 @@ gen_vote_routerstatus_for_tests(const char *digest_in_hex, int is_guard) tt_int_op(strlen(digest_in_hex), ==, HEX_DIGEST_LEN); retval = base16_decode(digest_tmp, sizeof(digest_tmp), digest_in_hex, HEX_DIGEST_LEN); - tt_int_op(retval, ==, 0); + tt_int_op(retval, ==, sizeof(digest_tmp)); memcpy(rs->identity_digest, digest_tmp, DIGEST_LEN); } diff --git a/src/test/test_microdesc.c b/src/test/test_microdesc.c index be90f53196..2afbdde88a 100644 --- a/src/test/test_microdesc.c +++ b/src/test/test_microdesc.c @@ -783,7 +783,8 @@ test_md_reject_cache(void *arg) mc = get_microdesc_cache(); #define ADD(hex) \ do { \ - tt_int_op(0,OP_EQ,base16_decode(buf,sizeof(buf),hex,strlen(hex))); \ + tt_int_op(sizeof(buf),OP_EQ,base16_decode(buf,sizeof(buf), \ + hex,strlen(hex)));\ smartlist_add(wanted, tor_memdup(buf, DIGEST256_LEN)); \ } while (0) diff --git a/src/test/test_ntor_cl.c b/src/test/test_ntor_cl.c index 49c9ad76d4..a560e5fc5e 100644 --- a/src/test/test_ntor_cl.c +++ b/src/test/test_ntor_cl.c @@ -21,7 +21,7 @@ } STMT_END #define BASE16(idx, var, n) STMT_BEGIN { \ const char *s = argv[(idx)]; \ - if (base16_decode((char*)var, n, s, strlen(s)) < 0 ) { \ + if (base16_decode((char*)var, n, s, strlen(s)) < (int)n ) { \ fprintf(stderr, "couldn't decode argument %d (%s)\n",idx,s); \ return 1; \ } \ diff --git a/src/test/test_rendcache.c b/src/test/test_rendcache.c index eac41ecdda..c8279fcced 100644 --- a/src/test/test_rendcache.c +++ b/src/test/test_rendcache.c @@ -17,8 +17,8 @@ static const int RECENT_TIME = -10; static const int TIME_IN_THE_PAST = -(REND_CACHE_MAX_AGE + \ - REND_CACHE_MAX_SKEW + 10); -static const int TIME_IN_THE_FUTURE = REND_CACHE_MAX_SKEW + 10; + REND_CACHE_MAX_SKEW + 60); +static const int TIME_IN_THE_FUTURE = REND_CACHE_MAX_SKEW + 60; static rend_data_t * mock_rend_data(const char *onion_address) diff --git a/src/test/test_switch_id.sh b/src/test/test_switch_id.sh index 1b4e0998b5..79c44f2eb1 100755 --- a/src/test/test_switch_id.sh +++ b/src/test/test_switch_id.sh @@ -10,6 +10,10 @@ if test "`id -u nobody`" = ""; then exit 1 fi +if test "$OVERRIDE_GCDA_PERMISSIONS_HACK" = "yes"; then + find src -type f -name '*gcda' -print0 | xargs -0 chmod 0666 +fi + "${builddir:-.}/src/test/test-switch-id" nobody setuid || exit 1 "${builddir:-.}/src/test/test-switch-id" nobody root-bind-low || exit 1 "${builddir:-.}/src/test/test-switch-id" nobody setuid-strict || exit 1 @@ -19,6 +23,9 @@ fi "${builddir:-.}/src/test/test-switch-id" nobody have-caps || exit 1 "${builddir:-.}/src/test/test-switch-id" nobody setuid-keepcaps || exit 1 +if test "$OVERRIDE_GCDA_PERMISSIONS_HACK" = "yes"; then + find src -type f -name '*gcda' -print0 | xargs -0 chmod 0644 +fi echo "All okay" diff --git a/src/test/test_util.c b/src/test/test_util.c index 0720822df3..56c71e871d 100644 --- a/src/test/test_util.c +++ b/src/test/test_util.c @@ -1501,6 +1501,11 @@ test_util_strmisc(void *arg) tt_int_op(-50L,OP_EQ, tor_parse_long("-50 plus garbage",10,-100,100,&i,&cp)); tt_int_op(1,OP_EQ, i); tt_str_op(cp,OP_EQ, " plus garbage"); + /* Illogical min max */ + tt_int_op(0L,OP_EQ, tor_parse_long("10",10,50,4,&i,NULL)); + tt_int_op(0,OP_EQ, i); + tt_int_op(0L,OP_EQ, tor_parse_long("-50",10,100,-100,&i,NULL)); + tt_int_op(0,OP_EQ, i); /* Out of bounds */ tt_int_op(0L,OP_EQ, tor_parse_long("10",10,50,100,&i,NULL)); tt_int_op(0,OP_EQ, i); @@ -1821,22 +1826,21 @@ test_util_gzip(void *arg) (void)arg; buf1 = tor_strdup("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAZAAAAAAAAAAAAAAAAAAAZ"); tt_assert(detect_compression_method(buf1, strlen(buf1)) == UNKNOWN_METHOD); - if (is_gzip_supported()) { - tt_assert(!tor_gzip_compress(&buf2, &len1, buf1, strlen(buf1)+1, - GZIP_METHOD)); - tt_assert(buf2); - tt_assert(len1 < strlen(buf1)); - tt_assert(detect_compression_method(buf2, len1) == GZIP_METHOD); - - tt_assert(!tor_gzip_uncompress(&buf3, &len2, buf2, len1, - GZIP_METHOD, 1, LOG_INFO)); - tt_assert(buf3); - tt_int_op(strlen(buf1) + 1,OP_EQ, len2); - tt_str_op(buf1,OP_EQ, buf3); - - tor_free(buf2); - tor_free(buf3); - } + + tt_assert(!tor_gzip_compress(&buf2, &len1, buf1, strlen(buf1)+1, + GZIP_METHOD)); + tt_assert(buf2); + tt_assert(len1 < strlen(buf1)); + tt_assert(detect_compression_method(buf2, len1) == GZIP_METHOD); + + tt_assert(!tor_gzip_uncompress(&buf3, &len2, buf2, len1, + GZIP_METHOD, 1, LOG_INFO)); + tt_assert(buf3); + tt_int_op(strlen(buf1) + 1,OP_EQ, len2); + tt_str_op(buf1,OP_EQ, buf3); + + tor_free(buf2); + tor_free(buf3); tt_assert(!tor_gzip_compress(&buf2, &len1, buf1, strlen(buf1)+1, ZLIB_METHOD)); @@ -1920,6 +1924,52 @@ test_util_gzip(void *arg) tor_free(buf1); } +static void +test_util_gzip_compression_bomb(void *arg) +{ + /* A 'compression bomb' is a very small object that uncompresses to a huge + * one. Most compression formats support them, but they can be a DOS vector. + * In Tor we try not to generate them, and we don't accept them. + */ + (void) arg; + size_t one_million = 1<<20; + char *one_mb = tor_malloc_zero(one_million); + char *result = NULL; + size_t result_len = 0; + tor_zlib_state_t *state = NULL; + + /* Make sure we can't produce a compression bomb */ + tt_int_op(-1, OP_EQ, tor_gzip_compress(&result, &result_len, + one_mb, one_million, + ZLIB_METHOD)); + + /* Here's a compression bomb that we made manually. */ + const char compression_bomb[1039] = + { 0x78, 0xDA, 0xED, 0xC1, 0x31, 0x01, 0x00, 0x00, 0x00, 0xC2, + 0xA0, 0xF5, 0x4F, 0x6D, 0x08, 0x5F, 0xA0 /* .... */ }; + tt_int_op(-1, OP_EQ, tor_gzip_uncompress(&result, &result_len, + compression_bomb, 1039, + ZLIB_METHOD, 0, LOG_WARN)); + + /* Now try streaming that. */ + state = tor_zlib_new(0, ZLIB_METHOD, HIGH_COMPRESSION); + tor_zlib_output_t r; + const char *inp = compression_bomb; + size_t inlen = 1039; + do { + char *outp = one_mb; + size_t outleft = 4096; /* small on purpose */ + r = tor_zlib_process(state, &outp, &outleft, &inp, &inlen, 0); + tt_int_op(inlen, OP_NE, 0); + } while (r == TOR_ZLIB_BUF_FULL); + + tt_int_op(r, OP_EQ, TOR_ZLIB_ERR); + + done: + tor_free(one_mb); + tor_zlib_free(state); +} + /** Run unit tests for mmap() wrapper functionality. */ static void test_util_mmap(void *arg) @@ -3349,6 +3399,21 @@ test_util_ftruncate(void *ptr) tor_free(buf); } +static void +test_util_num_cpus(void *arg) +{ + (void)arg; + int num = compute_num_cpus(); + if (num < 0) + tt_skip(); + + tt_int_op(num, OP_GE, 1); + tt_int_op(num, OP_LE, 16); + + done: + ; +} + #ifdef _WIN32 static void test_util_load_win_lib(void *ptr) @@ -4870,6 +4935,35 @@ test_util_pwdb(void *arg) dir = get_user_homedir(name); tt_assert(dir != NULL); + /* Try failing cases. First find a user that doesn't exist by name */ + char rand[4]; + char badname[9]; + int i, found=0; + for (i = 0; i < 100; ++i) { + crypto_rand(rand, sizeof(rand)); + base16_encode(badname, sizeof(badname), rand, sizeof(rand)); + if (tor_getpwnam(badname) == NULL) { + found = 1; + break; + } + } + tt_assert(found); + tor_free(dir); + dir = get_user_homedir(badname); + tt_assert(dir == NULL); + + /* Now try to find a user that doesn't exist by ID. */ + found = 0; + for (i = 0; i < 1000; ++i) { + uid_t u; + crypto_rand((char*)&u, sizeof(u)); + if (tor_getpwuid(u) == NULL) { + found = 1; + break; + } + } + tt_assert(found); + done: tor_free(name); tor_free(dir); @@ -4935,6 +5029,7 @@ struct testcase_t util_tests[] = { UTIL_LEGACY(strmisc), UTIL_LEGACY(pow2), UTIL_LEGACY(gzip), + UTIL_LEGACY(gzip_compression_bomb), UTIL_LEGACY(datadir), UTIL_LEGACY(memarea), UTIL_LEGACY(control_formats), @@ -4954,6 +5049,7 @@ struct testcase_t util_tests[] = { UTIL_TEST(listdir, 0), UTIL_TEST(parent_dir, 0), UTIL_TEST(ftruncate, 0), + UTIL_TEST(num_cpus, 0), UTIL_TEST_WIN_ONLY(load_win_lib, 0), UTIL_TEST_NO_WIN(exit_status, 0), UTIL_TEST_NO_WIN(fgets_eagain, 0), diff --git a/src/test/test_util_format.c b/src/test/test_util_format.c index c441037178..f3dcd1184c 100644 --- a/src/test/test_util_format.c +++ b/src/test/test_util_format.c @@ -263,14 +263,14 @@ test_util_format_base16_decode(void *ignored) res = base16_decode(dst, 1, src, 10); tt_int_op(res, OP_EQ, -1); - res = base16_decode(dst, SIZE_T_CEILING+2, src, 10); + res = base16_decode(dst, ((size_t)INT_MAX)+1, src, 10); tt_int_op(res, OP_EQ, -1); res = base16_decode(dst, 1000, "", 0); tt_int_op(res, OP_EQ, 0); res = base16_decode(dst, 1000, "aabc", 4); - tt_int_op(res, OP_EQ, 0); + tt_int_op(res, OP_EQ, 2); tt_mem_op(dst, OP_EQ, "\xaa\xbc", 2); res = base16_decode(dst, 1000, "aabcd", 6); @@ -280,7 +280,7 @@ test_util_format_base16_decode(void *ignored) tt_int_op(res, OP_EQ, -1); res = base16_decode(real_dst, 10, real_src, 14); - tt_int_op(res, OP_EQ, 0); + tt_int_op(res, OP_EQ, 7); tt_mem_op(real_dst, OP_EQ, expected, 7); done: diff --git a/src/test/test_workqueue.c b/src/test/test_workqueue.c index cbcf596b22..75d68a7ce0 100644 --- a/src/test/test_workqueue.c +++ b/src/test/test_workqueue.c @@ -400,6 +400,9 @@ main(int argc, char **argv) } rq = replyqueue_new(as_flags); + if (as_flags && rq == NULL) + return 77; // 77 means "skipped". + tor_assert(rq); tp = threadpool_new(opt_n_threads, rq, new_state, free_state, NULL); diff --git a/src/test/test_workqueue_cancel.sh b/src/test/test_workqueue_cancel.sh new file mode 100755 index 0000000000..f7c663171e --- /dev/null +++ b/src/test/test_workqueue_cancel.sh @@ -0,0 +1,4 @@ +#!/bin/sh + +${builddir:-.}/src/test/test_workqueue -C 1 + diff --git a/src/test/test_workqueue_efd.sh b/src/test/test_workqueue_efd.sh new file mode 100755 index 0000000000..4d89396819 --- /dev/null +++ b/src/test/test_workqueue_efd.sh @@ -0,0 +1,4 @@ +#!/bin/sh + +${builddir:-.}/src/test/test_workqueue \ + --no-eventfd2 --no-pipe2 --no-pipe --no-socketpair diff --git a/src/test/test_workqueue_efd2.sh b/src/test/test_workqueue_efd2.sh new file mode 100755 index 0000000000..7cfff45ff3 --- /dev/null +++ b/src/test/test_workqueue_efd2.sh @@ -0,0 +1,4 @@ +#!/bin/sh + +${builddir:-.}/src/test/test_workqueue \ + --no-eventfd --no-pipe2 --no-pipe --no-socketpair diff --git a/src/test/test_workqueue_pipe.sh b/src/test/test_workqueue_pipe.sh new file mode 100755 index 0000000000..afcef87853 --- /dev/null +++ b/src/test/test_workqueue_pipe.sh @@ -0,0 +1,4 @@ +#!/bin/sh + +${builddir:-.}/src/test/test_workqueue \ + --no-eventfd2 --no-eventfd --no-pipe2 --no-socketpair diff --git a/src/test/test_workqueue_pipe2.sh b/src/test/test_workqueue_pipe2.sh new file mode 100755 index 0000000000..a20a1427e0 --- /dev/null +++ b/src/test/test_workqueue_pipe2.sh @@ -0,0 +1,4 @@ +#!/bin/sh + +${builddir:-.}/src/test/test_workqueue \ + --no-eventfd2 --no-eventfd --no-pipe --no-socketpair diff --git a/src/test/test_workqueue_socketpair.sh b/src/test/test_workqueue_socketpair.sh new file mode 100755 index 0000000000..76af79746d --- /dev/null +++ b/src/test/test_workqueue_socketpair.sh @@ -0,0 +1,4 @@ +#!/bin/sh + +${builddir:-.}/src/test/test_workqueue \ + --no-eventfd2 --no-eventfd --no-pipe2 --no-pipe |