diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/common/memarea.c | 91 | ||||
-rw-r--r-- | src/or/buffers.c | 10 | ||||
-rw-r--r-- | src/or/circuitbuild.c | 2 | ||||
-rw-r--r-- | src/or/connection_edge.c | 6 | ||||
-rw-r--r-- | src/or/control.c | 13 | ||||
-rw-r--r-- | src/or/control.h | 5 | ||||
-rw-r--r-- | src/or/directory.c | 72 | ||||
-rw-r--r-- | src/or/or.h | 8 | ||||
-rw-r--r-- | src/or/relay.c | 20 | ||||
-rw-r--r-- | src/or/routerparse.c | 2 | ||||
-rw-r--r-- | src/test/log_test_helpers.h | 4 | ||||
-rw-r--r-- | src/test/test_controller.c | 40 | ||||
-rw-r--r-- | src/test/test_dir.c | 135 | ||||
-rw-r--r-- | src/test/test_util.c | 7 | ||||
-rw-r--r-- | src/win32/orconfig.h | 2 |
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" |