summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/common/memarea.c91
-rw-r--r--src/or/buffers.c10
-rw-r--r--src/or/circuitbuild.c2
-rw-r--r--src/or/connection_edge.c6
-rw-r--r--src/or/control.c13
-rw-r--r--src/or/control.h5
-rw-r--r--src/or/directory.c72
-rw-r--r--src/or/or.h8
-rw-r--r--src/or/relay.c20
-rw-r--r--src/or/routerparse.c2
-rw-r--r--src/test/log_test_helpers.h4
-rw-r--r--src/test/test_controller.c40
-rw-r--r--src/test/test_dir.c135
-rw-r--r--src/test/test_util.c7
-rw-r--r--src/win32/orconfig.h2
15 files changed, 382 insertions, 35 deletions
diff --git a/src/common/memarea.c b/src/common/memarea.c
index 7d16b702e3..12781e76ea 100644
--- a/src/common/memarea.c
+++ b/src/common/memarea.c
@@ -12,6 +12,9 @@
#include "util.h"
#include "compat.h"
#include "torlog.h"
+#include "container.h"
+
+#ifndef DISABLE_MEMORY_SENTINELS
/** If true, we try to detect any attempts to write beyond the length of a
* memarea. */
@@ -304,3 +307,91 @@ memarea_assert_ok(memarea_t *area)
}
}
+#else
+
+struct memarea_t {
+ smartlist_t *pieces;
+};
+
+memarea_t *
+memarea_new(void)
+{
+ memarea_t *ma = tor_malloc_zero(sizeof(memarea_t));
+ ma->pieces = smartlist_new();
+ return ma;
+}
+void
+memarea_drop_all(memarea_t *area)
+{
+ memarea_clear(area);
+ smartlist_free(area->pieces);
+ tor_free(area);
+}
+void
+memarea_clear(memarea_t *area)
+{
+ SMARTLIST_FOREACH(area->pieces, void *, p, tor_free_(p));
+ smartlist_clear(area->pieces);
+}
+int
+memarea_owns_ptr(const memarea_t *area, const void *ptr)
+{
+ SMARTLIST_FOREACH(area->pieces, const void *, p, if (ptr == p) return 1;);
+ return 0;
+}
+
+void *
+memarea_alloc(memarea_t *area, size_t sz)
+{
+ void *result = tor_malloc(sz);
+ smartlist_add(area->pieces, result);
+ return result;
+}
+
+void *
+memarea_alloc_zero(memarea_t *area, size_t sz)
+{
+ void *result = tor_malloc_zero(sz);
+ smartlist_add(area->pieces, result);
+ return result;
+}
+void *
+memarea_memdup(memarea_t *area, const void *s, size_t n)
+{
+ void *r = memarea_alloc(area, n);
+ memcpy(r, s, n);
+ return r;
+}
+char *
+memarea_strdup(memarea_t *area, const char *s)
+{
+ size_t n = strlen(s);
+ char *r = memarea_alloc(area, n+1);
+ memcpy(r, s, n);
+ r[n] = 0;
+ return r;
+}
+char *
+memarea_strndup(memarea_t *area, const char *s, size_t n)
+{
+ size_t ln = strnlen(s, n);
+ char *r = memarea_alloc(area, ln+1);
+ memcpy(r, s, ln);
+ r[ln] = 0;
+ return r;
+}
+void
+memarea_get_stats(memarea_t *area,
+ size_t *allocated_out, size_t *used_out)
+{
+ (void)area;
+ *allocated_out = *used_out = 128;
+}
+void
+memarea_assert_ok(memarea_t *area)
+{
+ (void)area;
+}
+
+#endif
+
diff --git a/src/or/buffers.c b/src/or/buffers.c
index 603da1bb6e..155b1935ed 100644
--- a/src/or/buffers.c
+++ b/src/or/buffers.c
@@ -83,7 +83,11 @@ static int parse_socks_client(const uint8_t *data, size_t datalen,
#define CHUNK_HEADER_LEN STRUCT_OFFSET(chunk_t, mem[0])
/* We leave this many NUL bytes at the end of the buffer. */
+#ifdef DISABLE_MEMORY_SENTINELS
+#define SENTINEL_LEN 0
+#else
#define SENTINEL_LEN 4
+#endif
/* Header size plus NUL bytes at the end */
#define CHUNK_OVERHEAD (CHUNK_HEADER_LEN + SENTINEL_LEN)
@@ -97,18 +101,22 @@ static int parse_socks_client(const uint8_t *data, size_t datalen,
#define DEBUG_SENTINEL
-#ifdef DEBUG_SENTINEL
+#if defined(DEBUG_SENTINEL) && !defined(DISABLE_MEMORY_SENTINELS)
#define DBG_S(s) s
#else
#define DBG_S(s) (void)0
#endif
+#ifdef DISABLE_MEMORY_SENTINELS
+#define CHUNK_SET_SENTINEL(chunk, alloclen) STMT_NIL
+#else
#define CHUNK_SET_SENTINEL(chunk, alloclen) do { \
uint8_t *a = (uint8_t*) &(chunk)->mem[(chunk)->memlen]; \
DBG_S(uint8_t *b = &((uint8_t*)(chunk))[(alloclen)-SENTINEL_LEN]); \
DBG_S(tor_assert(a == b)); \
memset(a,0,SENTINEL_LEN); \
} while (0)
+#endif
/** Return the next character in <b>chunk</b> onto which data can be appended.
* If the chunk is full, this might be off the end of chunk->mem. */
diff --git a/src/or/circuitbuild.c b/src/or/circuitbuild.c
index 79962e8dbb..14e829b03e 100644
--- a/src/or/circuitbuild.c
+++ b/src/or/circuitbuild.c
@@ -819,7 +819,7 @@ should_use_create_fast_for_circuit(origin_circuit_t *circ)
}
if (options->FastFirstHopPK == -1) {
/* option is "auto", so look at the consensus. */
- return networkstatus_get_param(NULL, "usecreatefast", 1, 0, 1);
+ return networkstatus_get_param(NULL, "usecreatefast", 0, 0, 1);
}
return options->FastFirstHopPK;
diff --git a/src/or/connection_edge.c b/src/or/connection_edge.c
index ef551048b8..ca68099d5f 100644
--- a/src/or/connection_edge.c
+++ b/src/or/connection_edge.c
@@ -29,7 +29,7 @@
* <li>DNS lookup streams, created on the exit side in response to
* a RELAY_RESOLVE cell from a client.
* <li>Tunneled directory streams, created on the directory cache side
- * in response to a RELAY_BEGINDIR cell. These streams attach directly
+ * in response to a RELAY_BEGIN_DIR cell. These streams attach directly
* to a dir_connection_t object without ever using TCP.
* </ul>
*
@@ -1762,7 +1762,7 @@ connection_ap_handshake_rewrite_and_attach(entry_connection_t *conn,
conn->entry_cfg.ipv6_traffic = 0;
/* Still handling CONNECT. Now, check for exit enclaves. (Which we
- * don't do on BEGINDIR, or when there is a chosen exit.)
+ * don't do on BEGIN_DIR, or when there is a chosen exit.)
*
* TODO: Should we remove this? Exit enclaves are nutty and don't
* work very well
@@ -2995,7 +2995,7 @@ connection_ap_handshake_socks_reply(entry_connection_t *conn, char *reply,
return;
}
-/** Read a RELAY_BEGIN or RELAY_BEGINDIR cell from <b>cell</b>, decode it, and
+/** Read a RELAY_BEGIN or RELAY_BEGIN_DIR cell from <b>cell</b>, decode it, and
* place the result in <b>bcell</b>. On success return 0; on failure return
* <0 and set *<b>end_reason_out</b> to the end reason we should send back to
* the client.
diff --git a/src/or/control.c b/src/or/control.c
index b0a687679d..8ab31f18f7 100644
--- a/src/or/control.c
+++ b/src/or/control.c
@@ -2824,12 +2824,13 @@ getinfo_helper_events(control_connection_t *control_conn,
/** Implementation helper for GETINFO: knows how to enumerate hidden services
* created via the control port. */
-static int
+STATIC int
getinfo_helper_onions(control_connection_t *control_conn,
const char *question, char **answer,
const char **errmsg)
{
smartlist_t *onion_list = NULL;
+ (void) errmsg; /* no errors from this method */
if (control_conn && !strcmp(question, "onions/current")) {
onion_list = control_conn->ephemeral_onion_services;
@@ -2839,13 +2840,13 @@ getinfo_helper_onions(control_connection_t *control_conn,
return 0;
}
if (!onion_list || smartlist_len(onion_list) == 0) {
- if (errmsg) {
- *errmsg = "No onion services of the specified type.";
+ if (answer) {
+ *answer = tor_strdup("");
}
- return -1;
- }
- if (answer) {
+ } else {
+ if (answer) {
*answer = smartlist_join_strings(onion_list, "\r\n", 0, NULL);
+ }
}
return 0;
diff --git a/src/or/control.h b/src/or/control.h
index 6330c85571..16ba1ed8f0 100644
--- a/src/or/control.h
+++ b/src/or/control.h
@@ -262,6 +262,11 @@ STATIC crypto_pk_t *add_onion_helper_keyarg(const char *arg, int discard_pk,
STATIC rend_authorized_client_t *
add_onion_helper_clientauth(const char *arg, int *created, char **err_msg_out);
+STATIC int getinfo_helper_onions(
+ control_connection_t *control_conn,
+ const char *question,
+ char **answer,
+ const char **errmsg);
STATIC void getinfo_helper_downloads_networkstatus(
const char *flavor,
download_status_t **dl_to_emit,
diff --git a/src/or/directory.c b/src/or/directory.c
index 70437fe755..e60952fcf4 100644
--- a/src/or/directory.c
+++ b/src/or/directory.c
@@ -14,6 +14,7 @@
#include "connection.h"
#include "connection_edge.h"
#include "control.h"
+#include "compat.h"
#define DIRECTORY_PRIVATE
#include "directory.h"
#include "dirserv.h"
@@ -1079,12 +1080,10 @@ static int
directory_command_should_use_begindir(const or_options_t *options,
const tor_addr_t *or_addr, int or_port,
const tor_addr_t *dir_addr, int dir_port,
- uint8_t router_purpose,
dir_indirection_t indirection,
const char **reason)
{
- (void) router_purpose;
- (void) dir_addr;
+ (void)dir_addr;
tor_assert(reason);
*reason = NULL;
@@ -1198,8 +1197,9 @@ directory_initiate_command_rend(const tor_addr_port_t *or_addr_port,
const int use_begindir = directory_command_should_use_begindir(options,
&or_addr_port->addr, or_addr_port->port,
&dir_addr_port->addr, dir_addr_port->port,
- router_purpose, indirection,
+ indirection,
&begindir_reason);
+
/* Will the connection go via a three-hop Tor circuit? Note that this
* is separate from whether it will use_begindir. */
const int anonymized_connection = dirind_is_anon(indirection);
@@ -1477,7 +1477,9 @@ directory_send_command(dir_connection_t *conn,
char decorated_address[128];
smartlist_t *headers = smartlist_new();
char *url;
+ size_t url_len;
char request[8192];
+ size_t request_len, total_request_len = 0;
const char *httpcommand = NULL;
tor_assert(conn);
@@ -1623,8 +1625,14 @@ directory_send_command(dir_connection_t *conn,
}
tor_snprintf(request, sizeof(request), "%s %s", httpcommand, proxystring);
- connection_write_to_buf(request, strlen(request), TO_CONN(conn));
- connection_write_to_buf(url, strlen(url), TO_CONN(conn));
+
+ request_len = strlen(request);
+ total_request_len += request_len;
+ connection_write_to_buf(request, request_len, TO_CONN(conn));
+
+ url_len = strlen(url);
+ total_request_len += url_len;
+ connection_write_to_buf(url, url_len, TO_CONN(conn));
tor_free(url);
if (!strcmp(httpcommand, "POST") || payload) {
@@ -1639,15 +1647,27 @@ directory_send_command(dir_connection_t *conn,
tor_free(header);
}
- connection_write_to_buf(request, strlen(request), TO_CONN(conn));
+ request_len = strlen(request);
+ total_request_len += request_len;
+ connection_write_to_buf(request, request_len, TO_CONN(conn));
if (payload) {
/* then send the payload afterwards too */
connection_write_to_buf(payload, payload_len, TO_CONN(conn));
+ total_request_len += payload_len;
}
SMARTLIST_FOREACH(headers, char *, h, tor_free(h));
smartlist_free(headers);
+
+ log_debug(LD_DIR,
+ "Sent request to directory server '%s:%d': "
+ "(purpose: %d, request size: " U64_FORMAT ", "
+ "payload size: " U64_FORMAT ")",
+ conn->base_.address, conn->base_.port,
+ conn->base_.purpose,
+ U64_PRINTF_ARG(total_request_len),
+ U64_PRINTF_ARG(payload ? payload_len : 0));
}
/** Parse an HTTP request string <b>headers</b> of the form
@@ -1941,6 +1961,9 @@ connection_dir_client_reached_eof(dir_connection_t *conn)
conn->base_.purpose == DIR_PURPOSE_FETCH_MICRODESC);
time_t now = time(NULL);
int src_code;
+ size_t received_bytes;
+
+ received_bytes = connection_get_inbuf_len(TO_CONN(conn));
switch (connection_fetch_from_buf_http(TO_CONN(conn),
&headers, MAX_HEADERS_SIZE,
@@ -1967,12 +1990,20 @@ connection_dir_client_reached_eof(dir_connection_t *conn)
}
if (!reason) reason = tor_strdup("[no reason given]");
- log_debug(LD_DIR,
+ tor_log(LOG_DEBUG, LD_DIR,
"Received response from directory server '%s:%d': %d %s "
- "(purpose: %d)",
+ "(purpose: %d, response size: " U64_FORMAT
+#ifdef MEASUREMENTS_21206
+ ", data cells received: %d, data cells sent: %d"
+#endif
+ ", compression: %d)",
conn->base_.address, conn->base_.port, status_code,
- escaped(reason),
- conn->base_.purpose);
+ escaped(reason), conn->base_.purpose,
+ U64_PRINTF_ARG(received_bytes),
+#ifdef MEASUREMENTS_21206
+ conn->data_cells_received, conn->data_cells_sent,
+#endif
+ compression);
if (conn->guard_state) {
/* we count the connection as successful once we can read from it. We do
@@ -2104,7 +2135,7 @@ connection_dir_client_reached_eof(dir_connection_t *conn)
networkstatus_consensus_download_failed(status_code, flavname);
return -1;
}
- log_info(LD_DIR,"Received consensus directory (size %d) from server "
+ log_info(LD_DIR,"Received consensus directory (body size %d) from server "
"'%s:%d'", (int)body_len, conn->base_.address, conn->base_.port);
if ((r=networkstatus_set_current_consensus(body, flavname, 0,
conn->identity_digest))<0) {
@@ -2143,8 +2174,9 @@ connection_dir_client_reached_eof(dir_connection_t *conn)
tor_free(body); tor_free(headers); tor_free(reason);
return -1;
}
- log_info(LD_DIR,"Received authority certificates (size %d) from server "
- "'%s:%d'", (int)body_len, conn->base_.address, conn->base_.port);
+ log_info(LD_DIR,"Received authority certificates (body size %d) from "
+ "server '%s:%d'",
+ (int)body_len, conn->base_.address, conn->base_.port);
/*
* Tell trusted_dirs_load_certs_from_string() whether it was by fp
@@ -2179,7 +2211,7 @@ connection_dir_client_reached_eof(dir_connection_t *conn)
if (conn->base_.purpose == DIR_PURPOSE_FETCH_STATUS_VOTE) {
const char *msg;
int st;
- log_info(LD_DIR,"Got votes (size %d) from server %s:%d",
+ log_info(LD_DIR,"Got votes (body size %d) from server %s:%d",
(int)body_len, conn->base_.address, conn->base_.port);
if (status_code != 200) {
log_warn(LD_DIR,
@@ -2199,7 +2231,7 @@ connection_dir_client_reached_eof(dir_connection_t *conn)
}
if (conn->base_.purpose == DIR_PURPOSE_FETCH_DETACHED_SIGNATURES) {
const char *msg = NULL;
- log_info(LD_DIR,"Got detached signatures (size %d) from server %s:%d",
+ log_info(LD_DIR,"Got detached signatures (body size %d) from server %s:%d",
(int)body_len, conn->base_.address, conn->base_.port);
if (status_code != 200) {
log_warn(LD_DIR,
@@ -2223,7 +2255,7 @@ connection_dir_client_reached_eof(dir_connection_t *conn)
int n_asked_for = 0;
int descriptor_digests = conn->requested_resource &&
!strcmpstart(conn->requested_resource,"d/");
- log_info(LD_DIR,"Received %s (size %d) from server '%s:%d'",
+ log_info(LD_DIR,"Received %s (body size %d) from server '%s:%d'",
was_ei ? "extra server info" : "server info",
(int)body_len, conn->base_.address, conn->base_.port);
if (conn->requested_resource &&
@@ -2301,7 +2333,7 @@ connection_dir_client_reached_eof(dir_connection_t *conn)
if (conn->base_.purpose == DIR_PURPOSE_FETCH_MICRODESC) {
smartlist_t *which = NULL;
log_info(LD_DIR,"Received answer to microdescriptor request (status %d, "
- "size %d) from server '%s:%d'",
+ "body size %d) from server '%s:%d'",
status_code, (int)body_len, conn->base_.address,
conn->base_.port);
tor_assert(conn->requested_resource &&
@@ -2453,7 +2485,7 @@ connection_dir_client_reached_eof(dir_connection_t *conn)
conn->identity_digest, \
NULL) )
tor_assert(conn->rend_data);
- log_info(LD_REND,"Received rendezvous descriptor (size %d, status %d "
+ log_info(LD_REND,"Received rendezvous descriptor (body size %d, status %d "
"(%s))",
(int)body_len, status_code, escaped(reason));
switch (status_code) {
@@ -3727,7 +3759,7 @@ directory_handle_command_post,(dir_connection_t *conn, const char *headers,
if (connection_dir_is_encrypted(conn) &&
!strcmpstart(url,"/tor/rendezvous2/publish")) {
if (rend_cache_store_v2_desc_as_dir(body) < 0) {
- log_warn(LD_REND, "Rejected v2 rend descriptor (length %d) from %s.",
+ log_warn(LD_REND, "Rejected v2 rend descriptor (body size %d) from %s.",
(int)body_len, conn->base_.address);
write_http_status_line(conn, 400,
"Invalid v2 service descriptor rejected");
diff --git a/src/or/or.h b/src/or/or.h
index 0db9f23604..0e2dc2401b 100644
--- a/src/or/or.h
+++ b/src/or/or.h
@@ -1786,6 +1786,14 @@ typedef struct dir_connection_t {
* that's going away and being used on channels instead. The dirserver still
* needs this for the incoming side, so it's moved here. */
uint64_t dirreq_id;
+
+#ifdef MEASUREMENTS_21206
+ /** Number of RELAY_DATA cells received. */
+ uint32_t data_cells_received;
+
+ /** Number of RELAY_DATA cells sent. */
+ uint32_t data_cells_sent;
+#endif
} dir_connection_t;
/** Subtype of connection_t for an connection to a controller. */
diff --git a/src/or/relay.c b/src/or/relay.c
index 2e76a8ec36..6b3f34f3e5 100644
--- a/src/or/relay.c
+++ b/src/or/relay.c
@@ -732,6 +732,16 @@ connection_edge_send_command(edge_connection_t *fromconn,
return -1;
}
+#ifdef MEASUREMENTS_21206
+ /* Keep track of the number of RELAY_DATA cells sent for directory
+ * connections. */
+ connection_t *linked_conn = TO_CONN(fromconn)->linked_conn;
+
+ if (linked_conn && linked_conn->type == CONN_TYPE_DIR) {
+ ++(TO_DIR_CONN(linked_conn)->data_cells_sent);
+ }
+#endif
+
return relay_send_command_from_edge(fromconn->stream_id, circ,
relay_command, payload,
payload_len, cpath_layer);
@@ -1585,6 +1595,16 @@ connection_edge_process_relay_cell(cell_t *cell, circuit_t *circ,
connection_write_to_buf((char*)(cell->payload + RELAY_HEADER_SIZE),
rh.length, TO_CONN(conn));
+#ifdef MEASUREMENTS_21206
+ /* Count number of RELAY_DATA cells received on a linked directory
+ * connection. */
+ connection_t *linked_conn = TO_CONN(conn)->linked_conn;
+
+ if (linked_conn && linked_conn->type == CONN_TYPE_DIR) {
+ ++(TO_DIR_CONN(linked_conn)->data_cells_received);
+ }
+#endif
+
if (!optimistic_data) {
/* Only send a SENDME if we're not getting optimistic data; otherwise
* a SENDME could arrive before the CONNECTED.
diff --git a/src/or/routerparse.c b/src/or/routerparse.c
index 98167d44f8..0336c035b4 100644
--- a/src/or/routerparse.c
+++ b/src/or/routerparse.c
@@ -4894,6 +4894,8 @@ tor_version_parse(const char *s, tor_version_t *out)
#define NUMBER(m) \
do { \
+ if (!cp || *cp < '0' || *cp > '9') \
+ return -1; \
out->m = (int)tor_parse_uint64(cp, 10, 0, INT32_MAX, &ok, &eos); \
if (!ok) \
return -1; \
diff --git a/src/test/log_test_helpers.h b/src/test/log_test_helpers.h
index 922c68b42f..19c5a881a4 100644
--- a/src/test/log_test_helpers.h
+++ b/src/test/log_test_helpers.h
@@ -71,14 +71,14 @@ void mock_dump_saved_logs(void);
\
assert_log_predicate(mock_saved_log_has_message_containing(str) && \
mock_saved_log_n_entries() == 1, \
- "expected log to contain exactly 1 message: " # str); \
+ "expected log to contain exactly 1 message " # str); \
} while (0);
#define expect_single_log_msg_containing(str) \
do { \
assert_log_predicate(mock_saved_log_has_message_containing(str)&& \
mock_saved_log_n_entries() == 1 , \
- "expected log to contain 1 message, containing" # str); \
+ "expected log to contain 1 message, containing " # str); \
} while (0);
#define expect_no_log_msg(str) \
diff --git a/src/test/test_controller.c b/src/test/test_controller.c
index d9c0a1eaac..206315e289 100644
--- a/src/test/test_controller.c
+++ b/src/test/test_controller.c
@@ -109,6 +109,45 @@ test_add_onion_helper_keyarg(void *arg)
}
static void
+test_getinfo_helper_onion(void *arg)
+{
+ (void)arg;
+ control_connection_t dummy;
+ /* Get results out */
+ char *answer = NULL;
+ const char *errmsg = NULL;
+ char *service_id = NULL;
+ int rt = 0;
+
+ dummy.ephemeral_onion_services = NULL;
+
+ /* successfully get an empty answer */
+ rt = getinfo_helper_onions(&dummy, "onions/current", &answer, &errmsg);
+ tt_assert(rt == 0);
+ tt_str_op(answer, OP_EQ, "");
+ tor_free(answer);
+
+ /* successfully get an empty answer */
+ rt = getinfo_helper_onions(&dummy, "onions/detached", &answer, &errmsg);
+ tt_assert(rt == 0);
+ tt_str_op(answer, OP_EQ, "");
+ tor_free(answer);
+
+ /* get an answer for one onion service */
+ service_id = tor_strdup("dummy_onion_id");
+ dummy.ephemeral_onion_services = smartlist_new();
+ smartlist_add(dummy.ephemeral_onion_services, service_id);
+ rt = getinfo_helper_onions(&dummy, "onions/current", &answer, &errmsg);
+ tt_assert(rt == 0);
+ tt_str_op(answer, OP_EQ, "dummy_onion_id");
+
+ done:
+ tor_free(answer);
+ tor_free(service_id);
+ smartlist_free(dummy.ephemeral_onion_services);
+}
+
+static void
test_rend_service_parse_port_config(void *arg)
{
const char *sep = ",";
@@ -1332,6 +1371,7 @@ test_download_status_bridge(void *arg)
struct testcase_t controller_tests[] = {
{ "add_onion_helper_keyarg", test_add_onion_helper_keyarg, 0, NULL, NULL },
+ { "getinfo_helper_onion", test_getinfo_helper_onion, 0, NULL, NULL },
{ "rend_service_parse_port_config", test_rend_service_parse_port_config, 0,
NULL, NULL },
{ "add_onion_helper_clientauth", test_add_onion_helper_clientauth, 0, NULL,
diff --git a/src/test/test_dir.c b/src/test/test_dir.c
index 4e5876fa3c..3906206696 100644
--- a/src/test/test_dir.c
+++ b/src/test/test_dir.c
@@ -1065,6 +1065,7 @@ test_dir_versions(void *arg)
tt_int_op(0, OP_EQ, ver1.patchlevel);
tt_int_op(VER_RELEASE, OP_EQ, ver1.status);
tt_str_op("alpha", OP_EQ, ver1.status_tag);
+ /* Go through the full set of status tags */
tt_int_op(0, OP_EQ, tor_version_parse("2.1.700-alpha", &ver1));
tt_int_op(2, OP_EQ, ver1.major);
tt_int_op(1, OP_EQ, ver1.minor);
@@ -1079,6 +1080,60 @@ test_dir_versions(void *arg)
tt_int_op(0, OP_EQ, ver1.patchlevel);
tt_int_op(VER_RELEASE, OP_EQ, ver1.status);
tt_str_op("alpha-dev", OP_EQ, ver1.status_tag);
+ tt_int_op(0, OP_EQ, tor_version_parse("0.2.9.5-rc", &ver1));
+ tt_int_op(0, OP_EQ, ver1.major);
+ tt_int_op(2, OP_EQ, ver1.minor);
+ tt_int_op(9, OP_EQ, ver1.micro);
+ tt_int_op(5, OP_EQ, ver1.patchlevel);
+ tt_int_op(VER_RELEASE, OP_EQ, ver1.status);
+ tt_str_op("rc", OP_EQ, ver1.status_tag);
+ tt_int_op(0, OP_EQ, tor_version_parse("0.2.9.6-rc-dev", &ver1));
+ tt_int_op(0, OP_EQ, ver1.major);
+ tt_int_op(2, OP_EQ, ver1.minor);
+ tt_int_op(9, OP_EQ, ver1.micro);
+ tt_int_op(6, OP_EQ, ver1.patchlevel);
+ tt_int_op(VER_RELEASE, OP_EQ, ver1.status);
+ tt_str_op("rc-dev", OP_EQ, ver1.status_tag);
+ tt_int_op(0, OP_EQ, tor_version_parse("0.2.9.8", &ver1));
+ tt_int_op(0, OP_EQ, ver1.major);
+ tt_int_op(2, OP_EQ, ver1.minor);
+ tt_int_op(9, OP_EQ, ver1.micro);
+ tt_int_op(8, OP_EQ, ver1.patchlevel);
+ tt_int_op(VER_RELEASE, OP_EQ, ver1.status);
+ tt_str_op("", OP_EQ, ver1.status_tag);
+ tt_int_op(0, OP_EQ, tor_version_parse("0.2.9.9-dev", &ver1));
+ tt_int_op(0, OP_EQ, ver1.major);
+ tt_int_op(2, OP_EQ, ver1.minor);
+ tt_int_op(9, OP_EQ, ver1.micro);
+ tt_int_op(9, OP_EQ, ver1.patchlevel);
+ tt_int_op(VER_RELEASE, OP_EQ, ver1.status);
+ tt_str_op("dev", OP_EQ, ver1.status_tag);
+ /* In #21450, we fixed an inconsistency in parsing versions > INT32_MAX
+ * between i386 and x86_64, as we used tor_parse_long, and then cast to int
+ */
+ tt_int_op(0, OP_EQ, tor_version_parse("0.2147483647.0", &ver1));
+ tt_int_op(0, OP_EQ, ver1.major);
+ tt_int_op(2147483647, OP_EQ, ver1.minor);
+ tt_int_op(0, OP_EQ, ver1.micro);
+ tt_int_op(0, OP_EQ, ver1.patchlevel);
+ tt_int_op(VER_RELEASE, OP_EQ, ver1.status);
+ tt_str_op("", OP_EQ, ver1.status_tag);
+ tt_int_op(-1, OP_EQ, tor_version_parse("0.2147483648.0", &ver1));
+ tt_int_op(-1, OP_EQ, tor_version_parse("0.4294967295.0", &ver1));
+ /* In #21278, we reject negative version components */
+ tt_int_op(-1, OP_EQ, tor_version_parse("0.-1.0", &ver1));
+ tt_int_op(-1, OP_EQ, tor_version_parse("0.-2147483648.0", &ver1));
+ tt_int_op(-1, OP_EQ, tor_version_parse("0.-4294967295.0", &ver1));
+ /* In #21507, we reject version components with non-numeric prefixes */
+ tt_int_op(-1, OP_EQ, tor_version_parse("0.-0.0", &ver1));
+ tt_int_op(-1, OP_EQ, tor_version_parse("+1.0.0", &ver1));
+ /* use the list in isspace() */
+ tt_int_op(-1, OP_EQ, tor_version_parse("0.\t0.0", &ver1));
+ tt_int_op(-1, OP_EQ, tor_version_parse("0.\n0.0", &ver1));
+ tt_int_op(-1, OP_EQ, tor_version_parse("0.\v0.0", &ver1));
+ tt_int_op(-1, OP_EQ, tor_version_parse("0.\f0.0", &ver1));
+ tt_int_op(-1, OP_EQ, tor_version_parse("0.\r0.0", &ver1));
+ tt_int_op(-1, OP_EQ, tor_version_parse("0. 0.0", &ver1));
#define tt_versionstatus_op(vs1, op, vs2) \
tt_assert_test_type(vs1,vs2,#vs1" "#op" "#vs2,version_status_t, \
@@ -1098,6 +1153,7 @@ test_dir_versions(void *arg)
test_v_i_o(VS_RECOMMENDED, "0.0.7rc2", "0.0.7,Tor 0.0.7rc2,Tor 0.0.8");
test_v_i_o(VS_OLD, "0.0.5.0", "0.0.5.1-cvs");
test_v_i_o(VS_NEW_IN_SERIES, "0.0.5.1-cvs", "0.0.5, 0.0.6");
+ test_v_i_o(VS_NEW, "0.2.9.9-dev", "0.2.9.9");
/* Not on list, but newer than any in same series. */
test_v_i_o(VS_NEW_IN_SERIES, "0.1.0.3",
"Tor 0.1.0.2,Tor 0.0.9.5,Tor 0.1.1.0");
@@ -1136,6 +1192,70 @@ test_dir_versions(void *arg)
"Tor 0.2.1.0-dev (r99)"));
tt_int_op(1,OP_EQ, tor_version_as_new_as("Tor 0.2.1.1",
"Tor 0.2.1.0-dev (r99)"));
+ /* And git revisions */
+ tt_int_op(1,OP_EQ, tor_version_as_new_as(
+ "Tor 0.2.9.9 (git-56788a2489127072)",
+ "Tor 0.2.9.9 (git-56788a2489127072)"));
+ /* a git revision is newer than no git revision */
+ tt_int_op(1,OP_EQ, tor_version_as_new_as(
+ "Tor 0.2.9.9 (git-56788a2489127072)",
+ "Tor 0.2.9.9"));
+ /* a longer git revision is newer than a shorter git revision
+ * this should be true if they prefix-match, but if they don't, they are
+ * incomparable, because hashes aren't ordered (but we compare their bytes
+ * anyway) */
+ tt_int_op(1,OP_EQ, tor_version_as_new_as(
+ "Tor 0.2.9.9 (git-56788a2489127072d513cf4baf35a8ff475f3c7b)",
+ "Tor 0.2.9.9 (git-56788a2489127072)"));
+ tt_int_op(1,OP_EQ, tor_version_as_new_as(
+ "Tor 0.2.9.9 (git-0102)",
+ "Tor 0.2.9.9 (git-03)"));
+ tt_int_op(1,OP_EQ, tor_version_as_new_as(
+ "Tor 0.2.9.9 (git-0102)",
+ "Tor 0.2.9.9 (git-00)"));
+ tt_int_op(1,OP_EQ, tor_version_as_new_as(
+ "Tor 0.2.9.9 (git-01)",
+ "Tor 0.2.9.9 (git-00)"));
+ tt_int_op(0,OP_EQ, tor_version_as_new_as(
+ "Tor 0.2.9.9 (git-00)",
+ "Tor 0.2.9.9 (git-01)"));
+ /* In #21278, we comapre without integer overflows.
+ * But since #21450 limits version components to [0, INT32_MAX], it is no
+ * longer possible to cause an integer overflow in tor_version_compare() */
+ tt_int_op(0,OP_EQ, tor_version_as_new_as(
+ "Tor 0.0.0.0",
+ "Tor 2147483647.0.0.0"));
+ tt_int_op(1,OP_EQ, tor_version_as_new_as(
+ "Tor 2147483647.0.0.0",
+ "Tor 0.0.0.0"));
+ /* These versions used to cause an overflow, now they don't parse
+ * (and authorities reject their descriptors), and log a BUG message */
+ setup_full_capture_of_logs(LOG_WARN);
+ tt_int_op(0,OP_EQ, tor_version_as_new_as(
+ "Tor 0.0.0.0",
+ "Tor 0.-2147483648.0.0"));
+ expect_single_log_msg_containing("unparseable");
+ mock_clean_saved_logs();
+ tt_int_op(0,OP_EQ, tor_version_as_new_as(
+ "Tor 0.2147483647.0.0",
+ "Tor 0.-1.0.0"));
+ expect_single_log_msg_containing("unparseable");
+ mock_clean_saved_logs();
+ tt_int_op(0,OP_EQ, tor_version_as_new_as(
+ "Tor 0.2147483647.0.0",
+ "Tor 0.-2147483648.0.0"));
+ expect_single_log_msg_containing("unparseable");
+ mock_clean_saved_logs();
+ tt_int_op(1,OP_EQ, tor_version_as_new_as(
+ "Tor 4294967295.0.0.0",
+ "Tor 0.0.0.0"));
+ expect_no_log_entry();
+ tt_int_op(0,OP_EQ, tor_version_as_new_as(
+ "Tor 0.4294967295.0.0",
+ "Tor 0.-4294967295.0.0"));
+ expect_single_log_msg_containing("unparseable");
+ mock_clean_saved_logs();
+ teardown_capture_of_logs();
/* Now try git revisions */
tt_int_op(0,OP_EQ, tor_version_parse("0.5.6.7 (git-ff00ff)", &ver1));
@@ -1145,11 +1265,24 @@ test_dir_versions(void *arg)
tt_int_op(7,OP_EQ, ver1.patchlevel);
tt_int_op(3,OP_EQ, ver1.git_tag_len);
tt_mem_op(ver1.git_tag,OP_EQ, "\xff\x00\xff", 3);
+ /* reject bad hex digits */
tt_int_op(-1,OP_EQ, tor_version_parse("0.5.6.7 (git-ff00xx)", &ver1));
+ /* reject odd hex digit count */
tt_int_op(-1,OP_EQ, tor_version_parse("0.5.6.7 (git-ff00fff)", &ver1));
+ /* ignore "git " */
tt_int_op(0,OP_EQ, tor_version_parse("0.5.6.7 (git ff00fff)", &ver1));
+ /* standard length is 16 hex digits */
+ tt_int_op(0,OP_EQ, tor_version_parse("0.5.6.7 (git-0010203040506070)",
+ &ver1));
+ /* length limit is 40 hex digits */
+ tt_int_op(0,OP_EQ, tor_version_parse(
+ "0.5.6.7 (git-000102030405060708090a0b0c0d0e0f10111213)",
+ &ver1));
+ tt_int_op(-1,OP_EQ, tor_version_parse(
+ "0.5.6.7 (git-000102030405060708090a0b0c0d0e0f1011121314)",
+ &ver1));
done:
- ;
+ teardown_capture_of_logs();
}
/** Run unit tests for directory fp_pair functions. */
diff --git a/src/test/test_util.c b/src/test/test_util.c
index e80201737a..5b4d5b7703 100644
--- a/src/test/test_util.c
+++ b/src/test/test_util.c
@@ -3340,6 +3340,13 @@ test_util_memarea(void *arg)
void *malloced_ptr = NULL;
int i;
+#ifdef DISABLE_MEMORY_SENTINELS
+ /* If memory sentinels are disabled, this whole module is just an alias for
+ malloc(), which is free to lay out memory most any way it wants. */
+ if (1)
+ tt_skip();
+#endif
+
(void)arg;
tt_assert(area);
diff --git a/src/win32/orconfig.h b/src/win32/orconfig.h
index 5542452ba2..f7f4f19505 100644
--- a/src/win32/orconfig.h
+++ b/src/win32/orconfig.h
@@ -218,7 +218,7 @@
#define USING_TWOS_COMPLEMENT
/* Version number of package */
-#define VERSION "0.3.0.4-rc"
+#define VERSION "0.3.1.0-alpha-dev"