Browse Source

Merge branch 'scanbuild_fixes'

Nick Mathewson 10 years ago
parent
commit
d3c05a79f0

+ 9 - 0
changes/bug8793

@@ -0,0 +1,9 @@
+  o Minor bugfixes:
+    - Fix numerous warnings from the clang "scan-build" static analyzer.
+      Some of these are programming style issues; some of them are false
+      positives that indicated awkward code; some are undefined behavior
+      cases related to constructing (but not using) invalid pointers;
+      some are assumptions about API behavior; some are using
+      sizeof(ptr) when sizeof(*ptr) would be correct; and one or two are
+      genuine bugs that weren't reachable from the rest of the
+      program. Fixes bug 8793; bugfixes on many, many tor versions.

+ 3 - 1
src/common/address.c

@@ -236,7 +236,9 @@ tor_addr_lookup(const char *name, uint16_t family, tor_addr_t *addr)
     hints.ai_family = family;
     hints.ai_socktype = SOCK_STREAM;
     err = sandbox_getaddrinfo(name, NULL, &hints, &res);
-    if (!err) {
+    /* The check for 'res' here shouldn't be necessary, but it makes static
+     * analysis tools happy. */
+    if (!err && res) {
       best = NULL;
       for (res_p = res; res_p; res_p = res_p->ai_next) {
         if (family == AF_UNSPEC) {

+ 3 - 1
src/common/compat.c

@@ -2198,8 +2198,10 @@ tor_inet_pton(int af, const char *src, void *dst)
     else {
       unsigned byte1,byte2,byte3,byte4;
       char more;
-      for (eow = dot-1; eow >= src && TOR_ISDIGIT(*eow); --eow)
+      for (eow = dot-1; eow > src && TOR_ISDIGIT(*eow); --eow)
         ;
+      if (*eow != ':')
+        return 0;
       ++eow;
 
       /* We use "scanf" because some platform inet_aton()s are too lax

+ 2 - 5
src/common/memarea.c

@@ -291,14 +291,11 @@ memarea_strdup(memarea_t *area, const char *s)
 char *
 memarea_strndup(memarea_t *area, const char *s, size_t n)
 {
-  size_t ln;
+  size_t ln = 0;
   char *result;
-  const char *cp, *end = s+n;
   tor_assert(n < SIZE_T_CEILING);
-  for (cp = s; cp < end && *cp; ++cp)
+  for (ln = 0; ln < n && s[ln]; ++ln)
     ;
-  /* cp now points to s+n, or to the 0 in the string. */
-  ln = cp-s;
   result = memarea_alloc(area, ln+1);
   memcpy(result, s, ln);
   result[ln]='\0';

+ 4 - 2
src/ext/ht.h

@@ -303,14 +303,16 @@ ht_string_hash(const char *s)
 
 #define HT_GENERATE(name, type, field, hashfn, eqfn, load, mallocfn,    \
                     reallocfn, freefn)                                  \
+  /* Primes that aren't too far from powers of two. We stop at */       \
+  /* P=402653189 because P*sizeof(void*) is less than SSIZE_MAX */      \
+  /* even on a 32-bit platform. */                                      \
   static unsigned name##_PRIMES[] = {                                   \
     53, 97, 193, 389,                                                   \
     769, 1543, 3079, 6151,                                              \
     12289, 24593, 49157, 98317,                                         \
     196613, 393241, 786433, 1572869,                                    \
     3145739, 6291469, 12582917, 25165843,                               \
-    50331653, 100663319, 201326611, 402653189,                          \
-    805306457, 1610612741                                               \
+    50331653, 100663319, 201326611, 402653189                           \
   };                                                                    \
   static unsigned name##_N_PRIMES =                                     \
     (unsigned)(sizeof(name##_PRIMES)/sizeof(name##_PRIMES[0]));         \

+ 8 - 1
src/ext/tinytest.c

@@ -478,16 +478,23 @@ tinytest_format_hex_(const void *val_, unsigned long len)
 	const unsigned char *val = val_;
 	char *result, *cp;
 	size_t i;
+	int ellipses = 0;
 
 	if (!val)
 		return strdup("null");
-	if (!(result = malloc(len*2+1)))
+	if (len > 1024) {
+		ellipses = 3;
+		len = 1024;
+	}
+	if (!(result = malloc(len*2+4)))
 		return strdup("<allocation failure>");
 	cp = result;
 	for (i=0;i<len;++i) {
 		*cp++ = "0123456789ABCDEF"[val[i] >> 4];
 		*cp++ = "0123456789ABCDEF"[val[i] & 0x0f];
 	}
+	while (ellipses--)
+		*cp++ = '.';
 	*cp = 0;
 	return result;
 }

+ 1 - 1
src/or/buffers.c

@@ -322,7 +322,7 @@ buf_shrink_freelists(int free_all)
       chunk_t **chp = &freelists[i].head;
       chunk_t *chunk;
       while (n_to_skip) {
-        if (! (*chp)->next) {
+        if (!(*chp) || ! (*chp)->next) {
           log_warn(LD_BUG, "I wanted to skip %d chunks in the freelist for "
                    "%d-byte chunks, but only found %d. (Length %d)",
                    orig_n_to_skip, (int)freelists[i].alloc_size,

+ 2 - 2
src/or/circuitbuild.c

@@ -313,9 +313,9 @@ circuit_rep_hist_note_result(origin_circuit_t *circ)
 static int
 circuit_cpath_supports_ntor(const origin_circuit_t *circ)
 {
-  crypt_path_t *head = circ->cpath, *cpath = circ->cpath;
+  crypt_path_t *head, *cpath;
 
-  cpath = head;
+  cpath = head = circ->cpath;
   do {
     if (cpath->extend_info &&
         !tor_mem_is_zero(

+ 10 - 2
src/or/circuitlist.c

@@ -1269,8 +1269,16 @@ circuit_get_by_rend_token_and_purpose(uint8_t purpose, int is_rend_circ,
       circ->base_.marked_for_close)
     return NULL;
 
-  if (!circ->rendinfo ||
-      ! bool_eq(circ->rendinfo->is_rend_circ, is_rend_circ) ||
+  if (!circ->rendinfo) {
+    char *t = tor_strdup(hex_str(token, REND_TOKEN_LEN));
+    log_warn(LD_BUG, "Wanted a circuit with %s:%d, but lookup returned a "
+             "circuit with no rendinfo set.",
+             safe_str(t), is_rend_circ);
+    tor_free(t);
+    return NULL;
+  }
+
+  if (! bool_eq(circ->rendinfo->is_rend_circ, is_rend_circ) ||
       tor_memneq(circ->rendinfo->rend_token, token, REND_TOKEN_LEN)) {
     char *t = tor_strdup(hex_str(token, REND_TOKEN_LEN));
     log_warn(LD_BUG, "Wanted a circuit with %s:%d, but lookup returned %s:%d",

+ 5 - 1
src/or/circuitmux.c

@@ -412,7 +412,11 @@ circuitmux_detach_all_circuits(circuitmux_t *cmux, smartlist_t *detached_out)
   i = HT_START(chanid_circid_muxinfo_map, cmux->chanid_circid_map);
   while (i) {
     to_remove = *i;
-    if (to_remove) {
+
+    if (! to_remove) {
+      log_warn(LD_BUG, "Somehow, an HT iterator gave us a NULL pointer.");
+      break;
+    } else {
       /* Find a channel and circuit */
       chan = channel_find_by_global_id(to_remove->chan_id);
       if (chan) {

+ 14 - 5
src/or/circuituse.c

@@ -537,7 +537,9 @@ circuit_expire_building(void)
                  "%d guards are live.",
                  TO_ORIGIN_CIRCUIT(victim)->global_identifier,
                  circuit_purpose_to_string(victim->purpose),
-                 TO_ORIGIN_CIRCUIT(victim)->build_state->desired_path_len,
+                 TO_ORIGIN_CIRCUIT(victim)->build_state ?
+                   TO_ORIGIN_CIRCUIT(victim)->build_state->desired_path_len :
+                   -1,
                  circuit_state_to_string(victim->state),
                  channel_state_to_string(victim->n_chan->state),
                  num_live_entry_guards(0));
@@ -561,7 +563,9 @@ circuit_expire_building(void)
                  "anyway. %d guards are live.",
                  TO_ORIGIN_CIRCUIT(victim)->global_identifier,
                  circuit_purpose_to_string(victim->purpose),
-                 TO_ORIGIN_CIRCUIT(victim)->build_state->desired_path_len,
+                 TO_ORIGIN_CIRCUIT(victim)->build_state ?
+                   TO_ORIGIN_CIRCUIT(victim)->build_state->desired_path_len :
+                   -1,
                  circuit_state_to_string(victim->state),
                  channel_state_to_string(victim->n_chan->state),
                  (long)build_close_ms,
@@ -707,7 +711,8 @@ circuit_expire_building(void)
          * and we have tried to send an INTRODUCE1 cell specifying it.
          * Thus, if the pending_final_cpath field *is* NULL, then we
          * want to not spare it. */
-        if (TO_ORIGIN_CIRCUIT(victim)->build_state->pending_final_cpath ==
+        if (TO_ORIGIN_CIRCUIT(victim)->build_state &&
+            TO_ORIGIN_CIRCUIT(victim)->build_state->pending_final_cpath ==
             NULL)
           break;
         /* fallthrough! */
@@ -753,7 +758,9 @@ circuit_expire_building(void)
                TO_ORIGIN_CIRCUIT(victim)->has_opened,
                victim->state, circuit_state_to_string(victim->state),
                victim->purpose,
-               TO_ORIGIN_CIRCUIT(victim)->build_state->desired_path_len);
+               TO_ORIGIN_CIRCUIT(victim)->build_state ?
+                 TO_ORIGIN_CIRCUIT(victim)->build_state->desired_path_len :
+                 -1);
     else
       log_info(LD_CIRC,
                "Abandoning circ %u %u (state %d,%d:%s, purpose %d, len %d)",
@@ -762,7 +769,9 @@ circuit_expire_building(void)
                TO_ORIGIN_CIRCUIT(victim)->has_opened,
                victim->state,
                circuit_state_to_string(victim->state), victim->purpose,
-               TO_ORIGIN_CIRCUIT(victim)->build_state->desired_path_len);
+               TO_ORIGIN_CIRCUIT(victim)->build_state ?
+                 TO_ORIGIN_CIRCUIT(victim)->build_state->desired_path_len :
+                 -1);
 
     circuit_log_path(LOG_INFO,LD_CIRC,TO_ORIGIN_CIRCUIT(victim));
     if (victim->purpose == CIRCUIT_PURPOSE_C_MEASURE_TIMEOUT)

+ 2 - 0
src/or/connection.c

@@ -4812,6 +4812,8 @@ get_proxy_addrport(tor_addr_t *addr, uint16_t *port, int *proxy_type,
     }
   }
 
+  tor_addr_make_unspec(addr);
+  *port = 0;
   *proxy_type = PROXY_NONE;
   return 0;
 }

+ 1 - 1
src/or/cpuworker.c

@@ -436,7 +436,7 @@ cpuworker_main(void *data)
     if (req.task == CPUWORKER_TASK_ONION) {
       const create_cell_t *cc = &req.create_cell;
       created_cell_t *cell_out = &rpl.created_cell;
-      struct timeval tv_start, tv_end;
+      struct timeval tv_start = {0,0}, tv_end;
       int n;
       rpl.timed = req.timed;
       rpl.started_at = req.started_at;

+ 1 - 1
src/or/ext_orport.c

@@ -256,7 +256,7 @@ handle_client_auth_nonce(const char *client_nonce, size_t client_nonce_len,
     base16_encode(server_nonce_encoded, sizeof(server_nonce_encoded),
                   server_nonce, sizeof(server_nonce));
     base16_encode(client_nonce_encoded, sizeof(client_nonce_encoded),
-                  client_nonce, sizeof(client_nonce));
+                  client_nonce, EXT_OR_PORT_AUTH_NONCE_LEN);
 
     log_debug(LD_GENERAL,
               "server_hash: '%s'\nserver_nonce: '%s'\nclient_nonce: '%s'",

+ 4 - 2
src/or/onion.c

@@ -329,12 +329,14 @@ onion_queue_entry_remove(onion_queue_t *victim)
 void
 clear_pending_onions(void)
 {
-  onion_queue_t *victim;
+  onion_queue_t *victim, *next;
   int i;
   for (i=0; i<=MAX_ONION_HANDSHAKE_TYPE; i++) {
-    while ((victim = TOR_TAILQ_FIRST(&ol_list[i]))) {
+    for (victim = TOR_TAILQ_FIRST(&ol_list[i]); victim; victim = next) {
+      next = TOR_TAILQ_NEXT(victim,next);
       onion_queue_entry_remove(victim);
     }
+    tor_assert(TOR_TAILQ_EMPTY(&ol_list[i]));
   }
   memset(ol_entries, 0, sizeof(ol_entries));
 }

+ 2 - 2
src/or/rendservice.c

@@ -2041,7 +2041,7 @@ rend_service_decrypt_intro(
   if (err_msg_out && !err_msg) {
     tor_asprintf(&err_msg,
                  "unknown INTRODUCE%d error decrypting encrypted part",
-                 (int)(intro->type));
+                 intro ? (int)(intro->type) : -1);
   }
   if (status >= 0) status = -1;
 
@@ -2147,7 +2147,7 @@ rend_service_parse_intro_plaintext(
   if (err_msg_out && !err_msg) {
     tor_asprintf(&err_msg,
                  "unknown INTRODUCE%d error parsing encrypted part",
-                 (int)(intro->type));
+                 intro ? (int)(intro->type) : -1);
   }
   if (status >= 0) status = -1;
 

+ 3 - 0
src/test/test_addr.c

@@ -346,6 +346,9 @@ test_addr_ip6_helpers(void)
   test_pton6_bad("a:::b:c");
   test_pton6_bad(":::a:b:c");
   test_pton6_bad("a:b:c:::");
+  test_pton6_bad("1.2.3.4");
+  test_pton6_bad(":1.2.3.4");
+  test_pton6_bad(".2.3.4");
 
   /* test internal checking */
   test_external_ip("fbff:ffff::2:7", 0);

+ 2 - 2
src/test/test_oom.c

@@ -82,8 +82,8 @@ add_bytes_to_buf(generic_buffer_t *buf, size_t n_bytes)
   char b[3000];
 
   while (n_bytes) {
-    size_t this_add = n_bytes > sizeof(buf) ? sizeof(buf) : n_bytes;
-    crypto_rand(b, sizeof(b));
+    size_t this_add = n_bytes > sizeof(b) ? sizeof(b) : n_bytes;
+    crypto_rand(b, this_add);
     generic_buffer_add(buf, b, this_add);
     n_bytes -= this_add;
   }

+ 4 - 2
src/test/test_policy.c

@@ -417,8 +417,10 @@ test_dump_exit_policy_to_string(void *arg)
 
  done:
 
- SMARTLIST_FOREACH(ri->exit_policy, addr_policy_t *,
-                   entry, addr_policy_free(entry));
+ if (ri->exit_policy) {
+   SMARTLIST_FOREACH(ri->exit_policy, addr_policy_t *,
+                     entry, addr_policy_free(entry));
+ }
  tor_free(ri);
  tor_free(ep);
 }

+ 2 - 0
src/tools/tor-gencert.c

@@ -302,6 +302,7 @@ load_identity_key(void)
     if (!identity_key) {
       log_err(LD_GENERAL, "Couldn't read identity key from %s",
               identity_key_file);
+      fclose(f);
       return 1;
     }
     fclose(f);
@@ -322,6 +323,7 @@ load_signing_key(void)
   }
   if (!(signing_key = PEM_read_PrivateKey(f, NULL, NULL, NULL))) {
     log_err(LD_GENERAL, "Couldn't read siging key from %s", signing_key_file);
+    fclose(f);
     return 1;
   }
   fclose(f);