summaryrefslogtreecommitdiff
path: root/src/test
diff options
context:
space:
mode:
Diffstat (limited to 'src/test')
-rw-r--r--src/test/include.am17
-rw-r--r--src/test/test-memwipe.c204
-rwxr-xr-xsrc/test/test-network.sh2
-rw-r--r--src/test/test_address.c176
-rw-r--r--src/test/test_workqueue.c4
5 files changed, 395 insertions, 8 deletions
diff --git a/src/test/include.am b/src/test/include.am
index c56e887ca0..c857ec2f89 100644
--- a/src/test/include.am
+++ b/src/test/include.am
@@ -1,10 +1,11 @@
-TESTS += src/test/test src/test/test-slow
+TESTS += src/test/test src/test/test-slow src/test/test-memwipe
noinst_PROGRAMS+= src/test/bench
if UNITTESTS_ENABLED
noinst_PROGRAMS+= \
src/test/test \
src/test/test-slow \
+ src/test/test-memwipe \
src/test/test-child \
src/test/test_workqueue
endif
@@ -73,10 +74,13 @@ src_test_test_slow_SOURCES = \
src/test/testing_common.c \
src/ext/tinytest.c
+src_test_test_memwipe_SOURCES = \
+ src/test/test-memwipe.c
+
src_test_test_CFLAGS = $(AM_CFLAGS) $(TEST_CFLAGS)
-src_test_test_CPPFLAGS= $(src_test_AM_CPPFLAGS)
+src_test_test_CPPFLAGS= $(src_test_AM_CPPFLAGS) $(TEST_CPPFLAGS)
src_test_bench_SOURCES = \
src/test/bench.c
@@ -89,7 +93,7 @@ src_test_test_workqueue_CFLAGS = $(AM_CFLAGS) $(TEST_CFLAGS)
src_test_test_LDFLAGS = @TOR_LDFLAGS_zlib@ @TOR_LDFLAGS_openssl@ \
@TOR_LDFLAGS_libevent@
src_test_test_LDADD = src/or/libtor-testing.a src/common/libor-testing.a \
- src/common/libor-crypto-testing.a $(LIBDONNA) \
+ src/common/libor-crypto-testing.a $(LIBDONNA) src/common/libor.a \
src/common/libor-event-testing.a src/trunnel/libor-trunnel-testing.a \
@TOR_ZLIB_LIBS@ @TOR_LIB_MATH@ @TOR_LIBEVENT_LIBS@ \
@TOR_OPENSSL_LIBS@ @TOR_LIB_WS32@ @TOR_LIB_GDI@ @CURVE25519_LIBS@ \
@@ -100,6 +104,11 @@ src_test_test_slow_CFLAGS = $(src_test_test_CFLAGS)
src_test_test_slow_LDADD = $(src_test_test_LDADD)
src_test_test_slow_LDFLAGS = $(src_test_test_LDFLAGS)
+src_test_test_memwipe_CPPFLAGS = $(src_test_test_CPPFLAGS)
+src_test_test_memwipe_CFLAGS = $(src_test_test_CFLAGS)
+src_test_test_memwipe_LDADD = $(src_test_test_LDADD)
+src_test_test_memwipe_LDFLAGS = $(src_test_test_LDFLAGS)
+
src_test_bench_LDFLAGS = @TOR_LDFLAGS_zlib@ @TOR_LDFLAGS_openssl@ \
@TOR_LDFLAGS_libevent@
src_test_bench_LDADD = src/or/libtor.a src/common/libor.a \
@@ -151,7 +160,7 @@ src_test_test_bt_cl_LDADD = src/common/libor-testing.a \
@TOR_LIB_MATH@ \
@TOR_LIB_WS32@ @TOR_LIB_GDI@
src_test_test_bt_cl_CFLAGS = $(AM_CFLAGS) $(TEST_CFLAGS)
-src_test_test_bt_cl_CPPFLAGS= $(src_test_AM_CPPFLAGS)
+src_test_test_bt_cl_CPPFLAGS= $(src_test_AM_CPPFLAGS) $(TEST_CPPFLAGS)
check-local: $(NTOR_TEST_DEPS) $(CMDLINE_TEST_TOR)
diff --git a/src/test/test-memwipe.c b/src/test/test-memwipe.c
new file mode 100644
index 0000000000..a721a8e728
--- /dev/null
+++ b/src/test/test-memwipe.c
@@ -0,0 +1,204 @@
+#include <string.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <stdlib.h>
+
+#include "crypto.h"
+#include "compat.h"
+
+#undef MIN
+#define MIN(a,b) ( ((a)<(b)) ? (a) : (b) )
+
+static unsigned fill_a_buffer_memset(void) __attribute__((noinline));
+static unsigned fill_a_buffer_memwipe(void) __attribute__((noinline));
+static unsigned fill_a_buffer_nothing(void) __attribute__((noinline));
+static unsigned fill_heap_buffer_memset(void) __attribute__((noinline));
+static unsigned fill_heap_buffer_memwipe(void) __attribute__((noinline));
+static unsigned fill_heap_buffer_nothing(void) __attribute__((noinline));
+static unsigned check_a_buffer(void) __attribute__((noinline));
+
+const char *s = NULL;
+
+#define FILL_BUFFER_IMPL() \
+ unsigned int i; \
+ unsigned sum = 0; \
+ \
+ /* Fill up a 1k buffer with a recognizable pattern. */ \
+ for (i = 0; i < 2048; i += strlen(s)) { \
+ memcpy(buf+i, s, MIN(strlen(s), 2048-i)); \
+ } \
+ \
+ /* Use the buffer as input to a computation so the above can't get */ \
+ /* optimized away. */ \
+ for (i = 0; i < 2048; ++i) { \
+ sum += (unsigned char)buf[i]; \
+ }
+
+static unsigned
+fill_a_buffer_memset(void)
+{
+ char buf[2048];
+ FILL_BUFFER_IMPL()
+ memset(buf, 0, sizeof(buf));
+ return sum;
+}
+
+static unsigned
+fill_a_buffer_memwipe(void)
+{
+ char buf[2048];
+ FILL_BUFFER_IMPL()
+ memwipe(buf, 0, sizeof(buf));
+ return sum;
+}
+
+static unsigned
+fill_a_buffer_nothing(void)
+{
+ char buf[2048];
+ FILL_BUFFER_IMPL()
+ return sum;
+}
+
+static INLINE int
+vmemeq(volatile char *a, const char *b, size_t n)
+{
+ while (n--) {
+ if (*a++ != *b++)
+ return 0;
+ }
+ return 1;
+}
+
+static unsigned
+check_a_buffer(void)
+{
+ unsigned int i;
+ volatile char buf[1024];
+ unsigned sum = 0;
+
+ /* See if this buffer has the string in it.
+
+ YES, THIS DOES INVOKE UNDEFINED BEHAVIOR BY READING FROM AN UNINITIALIZED
+ BUFFER.
+
+ If you know a better way to figure out whether the compiler eliminated
+ the memset/memwipe calls or not, please let me know.
+ */
+ for (i = 0; i < sizeof(buf); ++i) {
+ if (vmemeq(buf+i, s, strlen(s)))
+ ++sum;
+ }
+
+ return sum;
+}
+
+static char *heap_buf = NULL;
+
+static unsigned
+fill_heap_buffer_memset(void)
+{
+ char *buf = heap_buf = malloc(2048);
+ FILL_BUFFER_IMPL()
+ memset(buf, 0, 2048);
+ free(buf);
+ return sum;
+}
+
+static unsigned
+fill_heap_buffer_memwipe(void)
+{
+ char *buf = heap_buf = malloc(2048);
+ FILL_BUFFER_IMPL()
+ memwipe(buf, 0, 2048);
+ free(buf);
+ return sum;
+}
+
+static unsigned
+fill_heap_buffer_nothing(void)
+{
+ char *buf = heap_buf = malloc(2048);
+ FILL_BUFFER_IMPL()
+ free(buf);
+ return sum;
+}
+
+static unsigned
+check_heap_buffer(void)
+{
+ unsigned int i;
+ unsigned sum = 0;
+ volatile char *buf = heap_buf;
+
+ /* See if this buffer has the string in it.
+
+ YES, THIS DOES INVOKE UNDEFINED BEHAVIOR BY READING FROM A FREED BUFFER.
+
+ If you know a better way to figure out whether the compiler eliminated
+ the memset/memwipe calls or not, please let me know.
+ */
+ for (i = 0; i < sizeof(buf); ++i) {
+ if (vmemeq(buf+i, s, strlen(s)))
+ ++sum;
+ }
+
+ return sum;
+}
+
+static struct testcase {
+ const char *name;
+ unsigned (*fill_fn)(void);
+ unsigned (*check_fn)(void);
+} testcases[] = {
+ { "nil", fill_a_buffer_nothing, check_a_buffer },
+ { "nil-heap", fill_heap_buffer_nothing, check_heap_buffer },
+ { "memset", fill_a_buffer_memset, check_a_buffer },
+ { "memset-heap", fill_heap_buffer_memset, check_heap_buffer },
+ { "memwipe", fill_a_buffer_memwipe, check_a_buffer },
+ { "memwipe-heap", fill_heap_buffer_memwipe, check_heap_buffer },
+ { NULL, NULL, NULL }
+};
+
+int
+main(int argc, char **argv)
+{
+ unsigned x, x2;
+ int i;
+ int working = 1;
+ unsigned found[6];
+ (void) argc; (void) argv;
+
+ s = "squamous haberdasher gallimaufry";
+
+ memset(found, 0, sizeof(found));
+
+ for (i = 0; testcases[i].name; ++i) {
+ x = testcases[i].fill_fn();
+ found[i] = testcases[i].check_fn();
+
+ x2 = fill_a_buffer_nothing();
+
+ if (x != x2) {
+ working = 0;
+ }
+ }
+
+ if (!working || !found[0] || !found[1]) {
+ printf("It appears that this test case may not give you reliable "
+ "information. Sorry.\n");
+ }
+
+ if (!found[2] && !found[3]) {
+ printf("It appears that memset is good enough on this platform. Good.\n");
+ }
+
+ if (found[4] || found[5]) {
+ printf("ERROR: memwipe does not wipe data!\n");
+ return 1;
+ } else {
+ printf("OKAY: memwipe seems to work.");
+ return 0;
+ }
+}
+
diff --git a/src/test/test-network.sh b/src/test/test-network.sh
index be57cafb7f..ccfb5df424 100755
--- a/src/test/test-network.sh
+++ b/src/test/test-network.sh
@@ -13,7 +13,7 @@ do
export TOR_DIR="$2"
shift
;;
- --flavo?r|--network-flavo?r)
+ --flavor|--flavour|--network-flavor|--network-flavour)
export NETWORK_FLAVOUR="$2"
shift
;;
diff --git a/src/test/test_address.c b/src/test/test_address.c
index 424a6352b0..4bd631d39c 100644
--- a/src/test/test_address.c
+++ b/src/test/test_address.c
@@ -130,8 +130,8 @@ test_address_ifaddrs_to_smartlist(void *arg)
ipv6_sockaddr = tor_malloc(sizeof(struct sockaddr_in6));
ipv6_sockaddr->sin6_family = AF_INET6;
ipv6_sockaddr->sin6_port = 0;
- inet_pton(AF_INET6, "2001:db8:8714:3a90::12",
- &(ipv6_sockaddr->sin6_addr));
+ tor_inet_pton(AF_INET6, "2001:db8:8714:3a90::12",
+ &(ipv6_sockaddr->sin6_addr));
ifa = tor_malloc(sizeof(struct ifaddrs));
ifa_ipv4 = tor_malloc(sizeof(struct ifaddrs));
@@ -452,10 +452,182 @@ test_address_get_if_addrs_ioctl(void *arg)
#endif
+#define FAKE_SOCKET_FD (42)
+
+static tor_socket_t
+fake_open_socket(int domain, int type, int protocol)
+{
+ (void)domain;
+ (void)type;
+ (void)protocol;
+
+ return FAKE_SOCKET_FD;
+}
+
+static int last_connected_socket_fd = 0;
+
+static int connect_retval = 0;
+
+static tor_socket_t
+pretend_to_connect(tor_socket_t socket, const struct sockaddr *address,
+ socklen_t address_len)
+{
+ (void)address;
+ (void)address_len;
+
+ last_connected_socket_fd = socket;
+
+ return connect_retval;
+}
+
+static struct sockaddr *mock_addr = NULL;
+
+static int
+fake_getsockname(tor_socket_t socket, struct sockaddr *address,
+ socklen_t *address_len)
+{
+ socklen_t bytes_to_copy = 0;
+ (void) socket;
+
+ if (!mock_addr)
+ return -1;
+
+ if (mock_addr->sa_family == AF_INET) {
+ bytes_to_copy = sizeof(struct sockaddr_in);
+ } else if (mock_addr->sa_family == AF_INET6) {
+ bytes_to_copy = sizeof(struct sockaddr_in6);
+ } else {
+ return -1;
+ }
+
+ if (*address_len < bytes_to_copy) {
+ return -1;
+ }
+
+ memcpy(address,mock_addr,bytes_to_copy);
+ *address_len = bytes_to_copy;
+
+ return 0;
+}
+
+static void
+test_address_udp_socket_trick_whitebox(void *arg)
+{
+ int hack_retval;
+ tor_addr_t *addr_from_hack = tor_malloc_zero(sizeof(tor_addr_t));
+ struct sockaddr_in6 *mock_addr6;
+ struct sockaddr_in6 *ipv6_to_check =
+ tor_malloc_zero(sizeof(struct sockaddr_in6));
+
+ (void)arg;
+
+ MOCK(tor_open_socket,fake_open_socket);
+ MOCK(tor_connect_socket,pretend_to_connect);
+ MOCK(tor_getsockname,fake_getsockname);
+
+ mock_addr = tor_malloc_zero(sizeof(struct sockaddr_storage));
+ sockaddr_in_from_string("23.32.246.118",(struct sockaddr_in *)mock_addr);
+
+ hack_retval =
+ get_interface_address6_via_udp_socket_hack(LOG_DEBUG,
+ AF_INET, addr_from_hack);
+
+ tt_int_op(hack_retval,==,0);
+ tt_assert(tor_addr_eq_ipv4h(addr_from_hack, 0x1720f676));
+
+ /* Now, lets do an IPv6 case. */
+ memset(mock_addr,0,sizeof(struct sockaddr_storage));
+
+ mock_addr6 = (struct sockaddr_in6 *)mock_addr;
+ mock_addr6->sin6_family = AF_INET6;
+ mock_addr6->sin6_port = 0;
+ tor_inet_pton(AF_INET6,"2001:cdba::3257:9652",&(mock_addr6->sin6_addr));
+
+ hack_retval =
+ get_interface_address6_via_udp_socket_hack(LOG_DEBUG,
+ AF_INET6, addr_from_hack);
+
+ tt_int_op(hack_retval,==,0);
+
+ tor_addr_to_sockaddr(addr_from_hack,0,(struct sockaddr *)ipv6_to_check,
+ sizeof(struct sockaddr_in6));
+
+ tt_assert(sockaddr_in6_are_equal(mock_addr6,ipv6_to_check));
+
+ UNMOCK(tor_open_socket);
+ UNMOCK(tor_connect_socket);
+ UNMOCK(tor_getsockname);
+
+ done:
+ tor_free(ipv6_to_check);
+ tor_free(mock_addr);
+ tor_free(addr_from_hack);
+ return;
+}
+
+static void
+test_address_udp_socket_trick_blackbox(void *arg)
+{
+ /* We want get_interface_address6_via_udp_socket_hack() to yield
+ * the same valid address that get_interface_address6() returns.
+ * If the latter is unable to find a valid address, we want
+ * _hack() to fail and return-1.
+ *
+ * Furthermore, we want _hack() never to crash, even if
+ * get_interface_addresses_raw() is returning NULL.
+ */
+
+ tor_addr_t addr4;
+ tor_addr_t addr4_to_check;
+ tor_addr_t addr6;
+ tor_addr_t addr6_to_check;
+ int retval, retval_reference;
+
+ (void)arg;
+
+ retval_reference = get_interface_address6(LOG_DEBUG,AF_INET,&addr4);
+ retval = get_interface_address6_via_udp_socket_hack(LOG_DEBUG,
+ AF_INET,
+ &addr4_to_check);
+
+ tt_int_op(retval,==,retval_reference);
+ tt_assert( (retval == -1 && retval_reference == -1) ||
+ (tor_addr_compare(&addr4,&addr4_to_check,CMP_EXACT) == 0) );
+
+ //[XXX: Skipping the AF_INET6 case because bug #12377 makes it fail.]
+ (void)addr6_to_check;
+ (void)addr6;
+#if 0
+ retval_reference = get_interface_address6(LOG_DEBUG,AF_INET6,&addr6);
+ retval = get_interface_address6_via_udp_socket_hack(LOG_DEBUG,
+ AF_INET6,
+ &addr6_to_check);
+
+ tt_int_op(retval,==,retval_reference);
+ tt_assert( (retval == -1 && retval_reference == -1) ||
+ (tor_addr_compare(&addr6,&addr6_to_check,CMP_EXACT) == 0) );
+
+#endif
+
+ /* When family is neither AF_INET nor AF_INET6, we want _hack to
+ * fail and return -1.
+ */
+
+ retval = get_interface_address6_via_udp_socket_hack(LOG_DEBUG,
+ AF_CCITT,&addr4);
+
+ tt_assert(retval == -1);
+
+ done:
+ return;
+}
+
#define ADDRESS_TEST(name, flags) \
{ #name, test_address_ ## name, flags, NULL, NULL }
struct testcase_t address_tests[] = {
+ ADDRESS_TEST(udp_socket_trick_whitebox, TT_FORK),
+ ADDRESS_TEST(udp_socket_trick_blackbox, TT_FORK),
#ifdef HAVE_IFADDRS_TO_SMARTLIST
ADDRESS_TEST(get_if_addrs_ifaddrs, TT_FORK),
ADDRESS_TEST(ifaddrs_to_smartlist, 0),
diff --git a/src/test/test_workqueue.c b/src/test/test_workqueue.c
index aaff5069be..83f6f3e215 100644
--- a/src/test/test_workqueue.c
+++ b/src/test/test_workqueue.c
@@ -18,6 +18,8 @@
#include <event.h>
#endif
+#define MAX_INFLIGHT (1<<16)
+
static int opt_verbose = 0;
static int opt_n_threads = 8;
static int opt_n_items = 10000;
@@ -348,7 +350,7 @@ main(int argc, char **argv)
}
if (opt_n_threads < 1 ||
opt_n_items < 1 || opt_n_inflight < 1 || opt_n_lowwater < 0 ||
- opt_n_cancel > opt_n_inflight ||
+ opt_n_cancel > opt_n_inflight || opt_n_inflight > MAX_INFLIGHT ||
opt_ratio_rsa < 0) {
help();
return 1;