diff options
-rw-r--r-- | Makefile.am | 3 | ||||
-rw-r--r-- | changes/bug9254 | 4 | ||||
-rw-r--r-- | changes/bug9267 | 4 | ||||
-rwxr-xr-x | contrib/cov-blame | 48 | ||||
-rwxr-xr-x | contrib/coverage | 35 | ||||
-rw-r--r-- | src/common/sandbox.c | 16 | ||||
-rw-r--r-- | src/or/circuitlist.c | 6 | ||||
-rw-r--r-- | src/or/circuitmux.h | 3 | ||||
-rw-r--r-- | src/or/replaycache.c | 15 | ||||
-rw-r--r-- | src/test/test_circuitlist.c | 6 | ||||
-rw-r--r-- | src/test/test_pt.c | 25 | ||||
-rw-r--r-- | src/test/test_replay.c | 170 |
12 files changed, 305 insertions, 30 deletions
diff --git a/Makefile.am b/Makefile.am index 1bc1077ebb..0361d87cec 100644 --- a/Makefile.am +++ b/Makefile.am @@ -71,6 +71,9 @@ test: all test-network: all ./src/test/test-network.sh +reset-gcov: + rm -f src/*/*.gcda + # Avoid strlcpy.c, strlcat.c, aes.c, OpenBSD_malloc_Linux.c, sha256.c, # eventdns.[hc], tinytest*.[ch] check-spaces: diff --git a/changes/bug9254 b/changes/bug9254 new file mode 100644 index 0000000000..5179bdc523 --- /dev/null +++ b/changes/bug9254 @@ -0,0 +1,4 @@ + o Minor bugfixes: + - Fix a spurious compilation warning with some older versions of + GCC on FreeBSD. Fixes bug 9254; bugfix on 0.2.4.14-alpha. + diff --git a/changes/bug9267 b/changes/bug9267 new file mode 100644 index 0000000000..95a621148d --- /dev/null +++ b/changes/bug9267 @@ -0,0 +1,4 @@ + o Minor bugfixes: + - Added optional parameter to contrib/coverage script to specify directory + to put gcov files in, and added reset-gcov target to top-level makefile. + Fixes bug #9267. diff --git a/contrib/cov-blame b/contrib/cov-blame new file mode 100755 index 0000000000..601f211952 --- /dev/null +++ b/contrib/cov-blame @@ -0,0 +1,48 @@ +#!/usr/bin/python + +import os +import re +import subprocess +import sys + +def handle_file(source_fname, cov_fname): + + lines_blm = subprocess.Popen(["git", "blame", source_fname], stdout=subprocess.PIPE).stdout.readlines() + lines_cov = open(cov_fname).readlines() + + # XXXX expensive! + while re.match(r'\s*-:\s*0:', lines_cov[0]): + del lines_cov[0] + + if len(lines_blm) != len(lines_cov): + print >>sys.stderr, "MISMATCH IN NUMBER OF LINES in",source_fname + + for b,c in zip(lines_blm, lines_cov): + m = re.match(r'\s*([^\s:]+):', c) + if not m: + print >>sys.stderr, "CONFUSING LINE %r"% c + cov = 'X' + elif m.group(1) == '-': + cov = '-' + elif m.group(1)[0] == '#': + cov = '#' + elif m.group(1)[0].isdigit(): + cov = '1' + else: + print >>sys.stderr, "CONFUSING LINE %r"% c + cov = 'X' + + print cov, b, + +COV_DIR = sys.argv[1] +SOURCES = sys.argv[2:] + +for fn in SOURCES: + _, base = os.path.split(fn) + cfn = os.path.join(COV_DIR, base) + cfn += ".gcov" + if os.path.exists(cfn): + handle_file(fn, cfn) + else: + print >>sys.stderr, "NO FILE EXISTS CALLED ",cfn + diff --git a/contrib/coverage b/contrib/coverage index f51649a78e..f4ae475828 100755 --- a/contrib/coverage +++ b/contrib/coverage @@ -5,9 +5,42 @@ # coverage -- run gcov on the appropriate set of object files to extract # coverage information. +dst=$1 + for fn in src/or/*.c src/common/*.c; do BN=`basename $fn` DN=`dirname $fn` F=`echo $BN | sed -e 's/\.c$//;'` - gcov -o $DN/src_*$F.o $fn + GC="${BN}.gcov" + # Figure out the object file names + ONS=`echo ${DN}/src_*-${F}.o` + ONS_WILDCARD_LITERAL="${DN}/src_*-${F}.o" + # If the wildcard didn't expand, no files + if [ "$ONS" != "${ONS_WILDCARD_LITERAL}" ] + then + for on in $ONS; do + # We should have a gcno file + GCNO=`echo $on | sed -e 's/\.o$/\.gcno/;'` + if [ -e $GCNO ] + then + # No need to test for gcda, since gcov assumes no execution + # if it's absent + rm -f $GC + gcov -o $on $fn + if [ -e $GC ] + then + if [ -n $dst ] + then + mv $GC $dst/$GC + fi + else + echo "gcov -o $on $fn didn't make a .gcov file" + fi + else + echo "Couldn't find gcno file for $on" + fi + done + else + echo "No object file found matching source file $fn" + fi done diff --git a/src/common/sandbox.c b/src/common/sandbox.c index 68be89e881..dbb1657cdb 100644 --- a/src/common/sandbox.c +++ b/src/common/sandbox.c @@ -13,9 +13,10 @@ #include <string.h> #include <stdlib.h> +#include "orconfig.h" #include "sandbox.h" #include "torlog.h" -#include "orconfig.h" +#include "util.h" #if defined(HAVE_SECCOMP_H) && defined(__linux__) #define USE_LIBSECCOMP @@ -202,7 +203,7 @@ static void sigsys_debugging(int nr, siginfo_t *info, void *void_context) { ucontext_t *ctx = (ucontext_t *) (void_context); - char message[64]; + char message[256]; int rv = 0, syscall, length, err; (void) nr; @@ -214,11 +215,12 @@ sigsys_debugging(int nr, siginfo_t *info, void *void_context) syscall = ctx->uc_mcontext.gregs[REG_SYSCALL]; - /* XXXX Avoid use of snprintf; it isn't on the list of Stuff You're Allowed - * To Do In A Signal Handler. */ - length = snprintf(message, sizeof(message), - "\n\n(Sandbox) bad syscall (%d) was caught.\n", - syscall); + strlcpy(message, "\n\n(Sandbox) Caught a bad syscall attempt (syscall 0x", + sizeof(message)); + (void) format_hex_number_sigsafe(syscall, message+strlen(message), + sizeof(message)-strlen(message)); + strlcat(message, ")\n", sizeof(message)); + length = strlen(message); err = 0; if (sigsys_debugging_fd >= 0) { diff --git a/src/or/circuitlist.c b/src/or/circuitlist.c index 70c8980055..5e51301ceb 100644 --- a/src/or/circuitlist.c +++ b/src/or/circuitlist.c @@ -1642,8 +1642,10 @@ static size_t n_cells_in_circ_queues(const circuit_t *c) { size_t n = c->n_chan_cells.n; - if (! CIRCUIT_IS_ORIGIN(c)) - n += TO_OR_CIRCUIT((circuit_t*)c)->p_chan_cells.n; + if (! CIRCUIT_IS_ORIGIN(c)) { + circuit_t *cc = (circuit_t *) c; + n += TO_OR_CIRCUIT(cc)->p_chan_cells.n; + } return n; } diff --git a/src/or/circuitmux.h b/src/or/circuitmux.h index ffa28be06d..ee2f5d1535 100644 --- a/src/or/circuitmux.h +++ b/src/or/circuitmux.h @@ -128,7 +128,8 @@ void circuitmux_notify_xmit_cells(circuitmux_t *cmux, circuit_t *circ, void circuitmux_notify_xmit_destroy(circuitmux_t *cmux); /* Circuit interface */ -MOCK_DECL(void, circuitmux_attach_circuit, (circuitmux_t *cmux, circuit_t *circ, +MOCK_DECL(void, circuitmux_attach_circuit, (circuitmux_t *cmux, + circuit_t *circ, cell_direction_t direction)); MOCK_DECL(void, circuitmux_detach_circuit, (circuitmux_t *cmux, circuit_t *circ)); diff --git a/src/or/replaycache.c b/src/or/replaycache.c index f136072f61..122efb7030 100644 --- a/src/or/replaycache.c +++ b/src/or/replaycache.c @@ -134,7 +134,6 @@ replaycache_scrub_if_needed_internal(time_t present, replaycache_t *r) const char *digest; void *valp; time_t *access_time; - char scrub_this; /* sanity check */ if (!r || !(r->digests_seen)) { @@ -152,20 +151,10 @@ replaycache_scrub_if_needed_internal(time_t present, replaycache_t *r) /* okay, scrub time */ itr = digestmap_iter_init(r->digests_seen); while (!digestmap_iter_done(itr)) { - scrub_this = 0; digestmap_iter_get(itr, &digest, &valp); access_time = (time_t *)valp; - if (access_time) { - /* aged out yet? */ - if (*access_time < present - r->horizon) scrub_this = 1; - } else { - /* Buh? Get rid of it, anyway */ - log_info(LD_BUG, "replaycache_scrub_if_needed_internal() saw a NULL" - " entry in the digestmap."); - scrub_this = 1; - } - - if (scrub_this) { + /* aged out yet? */ + if (*access_time < present - r->horizon) { /* Advance the iterator and remove this one */ itr = digestmap_iter_next_rmv(r->digests_seen, itr); /* Free the value removed */ diff --git a/src/test/test_circuitlist.c b/src/test/test_circuitlist.c index a233653e16..720b407659 100644 --- a/src/test/test_circuitlist.c +++ b/src/test/test_circuitlist.c @@ -62,7 +62,6 @@ circuitmux_detach_mock(circuitmux_t *cmux, circuit_t *circ) memset(&cdm, 0, sizeof(cdm)); \ } while (0) - static void test_clist_maps(void *arg) { @@ -150,8 +149,7 @@ test_clist_maps(void *arg) tt_assert(! circuit_id_in_use_on_channel(200, ch2)); tt_assert(! circuit_id_in_use_on_channel(100, ch1)); - -done: + done: tor_free(ch1); tor_free(ch2); tor_free(ch3); @@ -163,8 +161,8 @@ done: UNMOCK(circuitmux_detach_circuit); } - struct testcase_t circuitlist_tests[] = { { "maps", test_clist_maps, TT_FORK, NULL, NULL }, END_OF_TESTCASES }; + diff --git a/src/test/test_pt.c b/src/test/test_pt.c index 6aa345d568..4970cfff44 100644 --- a/src/test/test_pt.c +++ b/src/test/test_pt.c @@ -24,6 +24,8 @@ static void test_pt_parsing(void) { char line[200]; + transport_t *transport = NULL; + tor_addr_t test_addr; managed_proxy_t *mp = tor_malloc(sizeof(managed_proxy_t)); mp->conf_state = PT_PROTO_INFANT; @@ -50,7 +52,17 @@ test_pt_parsing(void) /* correct line */ strlcpy(line,"CMETHOD trebuchet socks5 127.0.0.1:1999",sizeof(line)); test_assert(parse_cmethod_line(line, mp) == 0); - test_assert(smartlist_len(mp->transports)); + test_assert(smartlist_len(mp->transports) == 1); + transport = smartlist_get(mp->transports, 0); + /* test registered address of transport */ + tor_addr_parse(&test_addr, "127.0.0.1"); + test_assert(tor_addr_eq(&test_addr, &transport->addr)); + /* test registered port of transport */ + test_assert(transport->port == 1999); + /* test registered SOCKS version of transport */ + test_assert(transport->socks_version == PROXY_SOCKS5); + /* test registered name of transport */ + test_streq(transport->name, "trebuchet"); reset_mp(mp); @@ -67,8 +79,17 @@ test_pt_parsing(void) reset_mp(mp); /* cowwect */ - strlcpy(line,"SMETHOD trebuchy 127.0.0.1:1999",sizeof(line)); + strlcpy(line,"SMETHOD trebuchy 127.0.0.2:2999",sizeof(line)); test_assert(parse_smethod_line(line, mp) == 0); + test_assert(smartlist_len(mp->transports) == 1); + transport = smartlist_get(mp->transports, 0); + /* test registered address of transport */ + tor_addr_parse(&test_addr, "127.0.0.2"); + test_assert(tor_addr_eq(&test_addr, &transport->addr)); + /* test registered port of transport */ + test_assert(transport->port == 2999); + /* test registered name of transport */ + test_streq(transport->name, "trebuchy"); reset_mp(mp); diff --git a/src/test/test_replay.c b/src/test/test_replay.c index de841ad594..200bf4dd3e 100644 --- a/src/test/test_replay.c +++ b/src/test/test_replay.c @@ -32,6 +32,40 @@ test_replaycache_alloc(void) } static void +test_replaycache_badalloc(void) +{ + replaycache_t *r = NULL; + + /* Negative horizon should fail */ + r = replaycache_new(-600, 300); + test_assert(r == NULL); + /* Negative interval should get adjusted to zero */ + r = replaycache_new(600, -300); + test_assert(r != NULL); + test_eq(r->scrub_interval, 0); + replaycache_free(r); + /* Negative horizon and negative interval should still fail */ + r = replaycache_new(-600, -300); + test_assert(r == NULL); + + done: + if (r) replaycache_free(r); + + return; +} + +static void +test_replaycache_free_null(void) +{ + replaycache_free(NULL); + /* Assert that we're here without horrible death */ + test_assert(1); + + done: + return; +} + +static void test_replaycache_miss(void) { replaycache_t *r = NULL; @@ -45,6 +79,12 @@ test_replaycache_miss(void) (int)strlen(test_buffer), NULL); test_eq(result, 0); + /* poke the bad-parameter error case too */ + result = + replaycache_add_and_test_internal(1200, NULL, test_buffer, + (int)strlen(test_buffer), NULL); + test_eq(result, 0); + done: if (r) replaycache_free(r); @@ -163,16 +203,146 @@ test_replaycache_noexpire(void) return; } +static void +test_replaycache_scrub(void) +{ + replaycache_t *r = NULL; + int result; + + r = replaycache_new(600, 300); + test_assert(r != NULL); + + /* Set up like in test_replaycache_hit() */ + result = + replaycache_add_and_test_internal(100, r, test_buffer, + (int)strlen(test_buffer), NULL); + test_eq(result, 0); + + result = + replaycache_add_and_test_internal(200, r, test_buffer, + (int)strlen(test_buffer), NULL); + test_eq(result, 1); + + /* + * Poke a few replaycache_scrub_if_needed_internal() error cases that + * can't happen through replaycache_add_and_test_internal() + */ + + /* Null cache */ + replaycache_scrub_if_needed_internal(300, NULL); + /* Assert we're still here */ + test_assert(1); + + /* Make sure we hit the aging-out case too */ + replaycache_scrub_if_needed_internal(1500, r); + /* Assert that we aged it */ + test_eq(digestmap_size(r->digests_seen), 0); + + done: + if (r) replaycache_free(r); + + return; +} + +static void +test_replaycache_future(void) +{ + replaycache_t *r = NULL; + int result; + time_t elapsed = 0; + + r = replaycache_new(600, 300); + test_assert(r != NULL); + + /* Set up like in test_replaycache_hit() */ + result = + replaycache_add_and_test_internal(100, r, test_buffer, + (int)strlen(test_buffer), &elapsed); + test_eq(result, 0); + /* elapsed should still be 0, since it wasn't written */ + test_eq(elapsed, 0); + + result = + replaycache_add_and_test_internal(200, r, test_buffer, + (int)strlen(test_buffer), &elapsed); + test_eq(result, 1); + /* elapsed should be the time since the last hit */ + test_eq(elapsed, 100); + + /* + * Now let's turn the clock back to get coverage on the cache entry from the + * future not-supposed-to-happen case. + */ + result = + replaycache_add_and_test_internal(150, r, test_buffer, + (int)strlen(test_buffer), &elapsed); + /* We should still get a hit */ + test_eq(result, 1); + /* ...but it shouldn't let us see a negative elapsed time */ + test_eq(elapsed, 0); + + done: + if (r) replaycache_free(r); + + return; +} + +static void +test_replaycache_realtime(void) +{ + replaycache_t *r = NULL; + /* + * Negative so we fail if replaycache_add_test_and_elapsed() doesn't + * write to elapsed. + */ + time_t elapsed = -1; + int result; + + /* Test the realtime as well as *_internal() entry points */ + r = replaycache_new(600, 300); + test_assert(r != NULL); + + /* This should miss */ + result = + replaycache_add_and_test(r, test_buffer, (int)strlen(test_buffer)); + test_eq(result, 0); + + /* This should hit */ + result = + replaycache_add_and_test(r, test_buffer, (int)strlen(test_buffer)); + test_eq(result, 1); + + /* This should hit and return a small elapsed time */ + result = + replaycache_add_test_and_elapsed(r, test_buffer, + (int)strlen(test_buffer), &elapsed); + test_eq(result, 1); + test_assert(elapsed >= 0); + test_assert(elapsed <= 5); + + /* Scrub it to exercise that entry point too */ + replaycache_scrub_if_needed(r); + + done: + if (r) replaycache_free(r); + return; +} + #define REPLAYCACHE_LEGACY(name) \ { #name, legacy_test_helper, 0, &legacy_setup, test_replaycache_ ## name } struct testcase_t replaycache_tests[] = { REPLAYCACHE_LEGACY(alloc), + REPLAYCACHE_LEGACY(badalloc), + REPLAYCACHE_LEGACY(free_null), REPLAYCACHE_LEGACY(miss), REPLAYCACHE_LEGACY(hit), REPLAYCACHE_LEGACY(age), REPLAYCACHE_LEGACY(elapsed), REPLAYCACHE_LEGACY(noexpire), + REPLAYCACHE_LEGACY(scrub), + REPLAYCACHE_LEGACY(future), + REPLAYCACHE_LEGACY(realtime), END_OF_TESTCASES }; |