[tor-commits] [tor/master] Merge remote-tracking branch 'public/bug3122_memcmp_022' into bug3122_memcmp_023

nickm at torproject.org nickm at torproject.org
Thu May 12 23:28:07 UTC 2011


commit 9fba014e3f7f89520841b65b8b038e5fb931b1d6
Merge: 6d5478a 8fb3833
Author: Nick Mathewson <nickm at torproject.org>
Date:   Wed May 11 16:39:45 2011 -0400

    Merge remote-tracking branch 'public/bug3122_memcmp_022' into bug3122_memcmp_023
    
    Conflicts in various places, mainly node-related.  Resolved them in
    favor of HEAD, with copying of tor_mem* operations from bug3122_memcmp_022.
    
    	src/common/Makefile.am
    	src/or/circuitlist.c
    	src/or/connection_edge.c
    	src/or/directory.c
    	src/or/microdesc.c
    	src/or/networkstatus.c
    	src/or/router.c
    	src/or/routerlist.c
    	src/test/test_util.c

 changes/bug3122_memcmp   |    7 +++
 configure.in             |   18 ++++++
 src/common/Makefile.am   |    2 +
 src/common/address.c     |    2 +-
 src/common/compat.c      |    4 +-
 src/common/container.c   |   10 ++--
 src/common/container.h   |    4 +-
 src/common/crypto.c      |    2 +-
 src/common/di_ops.c      |  133 ++++++++++++++++++++++++++++++++++++++++++++++
 src/common/di_ops.h      |   30 ++++++++++
 src/common/torgzip.c     |    2 +-
 src/common/util.c        |   21 +++++---
 src/common/util.h        |    5 +-
 src/or/circuitbuild.c    |   12 ++--
 src/or/circuitlist.c     |   10 ++--
 src/or/circuituse.c      |    2 +-
 src/or/connection_edge.c |    4 +-
 src/or/connection_or.c   |   10 ++--
 src/or/control.c         |   14 +++---
 src/or/directory.c       |   10 ++--
 src/or/dirserv.c         |   12 ++--
 src/or/dirvote.c         |   40 +++++++-------
 src/or/eventdns.c        |    4 +-
 src/or/microdesc.c       |    4 +-
 src/or/networkstatus.c   |   40 +++++++-------
 src/or/onion.c           |    4 +-
 src/or/relay.c           |    2 +-
 src/or/rendclient.c      |    6 +-
 src/or/rendcommon.c      |    8 ++--
 src/or/rendmid.c         |    2 +-
 src/or/rendservice.c     |   16 +++---
 src/or/rephist.c         |    4 +-
 src/or/router.c          |    6 +-
 src/or/routerlist.c      |   66 +++++++++++-----------
 src/or/routerparse.c     |   33 ++++++------
 src/test/test_util.c     |   55 +++++++++++++++++++
 36 files changed, 429 insertions(+), 175 deletions(-)

diff --cc src/common/Makefile.am
index 20e3f5a,2d009bd..3a80eb8
--- a/src/common/Makefile.am
+++ b/src/common/Makefile.am
@@@ -11,44 -11,12 +11,46 @@@ els
  libor_extra_source=
  endif
  
 -libor_a_SOURCES = address.c log.c util.c compat.c container.c mempool.c \
 -	memarea.c di_ops.c util_codedigest.c $(libor_extra_source)
 -libor_crypto_a_SOURCES = crypto.c aes.c tortls.c torgzip.c
 +libor_a_SOURCES = \
 +  address.c					\
 +  compat.c					\
 +  container.c					\
++  di_ops.c					\
 +  log.c						\
 +  memarea.c					\
 +  mempool.c					\
 +  util.c					\
 +  util_codedigest.c				\
 +  $(libor_extra_source)
 +
 +libor_crypto_a_SOURCES = \
 +  aes.c		\
 +  crypto.c	\
 +  torgzip.c	\
 +  tortls.c
 +
  libor_event_a_SOURCES = compat_libevent.c
  
 -noinst_HEADERS = address.h torlog.h crypto.h util.h compat.h aes.h torint.h tortls.h strlcpy.c strlcat.c torgzip.h container.h ht.h mempool.h memarea.h ciphers.inc compat_libevent.h tortls_states.h di_ops.h
 +noinst_HEADERS = 				\
 +  address.h					\
 +  aes.h						\
 +  ciphers.inc					\
 +  compat.h					\
 +  compat_libevent.h				\
 +  container.h					\
 +  crypto.h					\
++  di_ops.h					\
 +  ht.h						\
 +  memarea.h					\
 +  mempool.h					\
 +  strlcat.c					\
 +  strlcpy.c					\
 +  torgzip.h					\
 +  torint.h					\
 +  torlog.h					\
 +  tortls.h					\
 +  tortls_states.h				\
 +  util.h
  
  common_sha1.i: $(libor_SOURCES) $(libor_crypto_a_SOURCES) $(noinst_HEADERS)
  	if test "@SHA1SUM@" != none; then \
diff --cc src/or/circuitlist.c
index 0aadcbf,8ec4618..7c5fd25
--- a/src/or/circuitlist.c
+++ b/src/or/circuitlist.c
@@@ -1003,10 -1005,10 +1003,10 @@@ circuit_find_to_cannibalize(uint8_t pur
          if (info) {
            /* need to make sure we don't duplicate hops */
            crypt_path_t *hop = circ->cpath;
 -          routerinfo_t *ri1 = router_get_by_digest(info->identity_digest);
 +          const node_t *ri1 = node_get_by_id(info->identity_digest);
            do {
 -            routerinfo_t *ri2;
 +            const node_t *ri2;
-             if (!memcmp(hop->extend_info->identity_digest,
+             if (tor_memeq(hop->extend_info->identity_digest,
                          info->identity_digest, DIGEST_LEN))
                goto next;
              if (ri1 &&
diff --cc src/or/connection_edge.c
index 4e45cbe,037920b..186137b
--- a/src/or/connection_edge.c
+++ b/src/or/connection_edge.c
@@@ -3070,10 -3059,10 +3070,10 @@@ connection_ap_can_use_exit(edge_connect
     * make sure the exit node of the existing circuit matches exactly.
     */
    if (conn->chosen_exit_name) {
 -    routerinfo_t *chosen_exit =
 -      router_get_by_nickname(conn->chosen_exit_name, 1);
 -    if (!chosen_exit || tor_memneq(chosen_exit->cache_info.identity_digest,
 -                               exit->cache_info.identity_digest, DIGEST_LEN)) {
 +    const node_t *chosen_exit =
 +      node_get_by_nickname(conn->chosen_exit_name, 1);
-     if (!chosen_exit || memcmp(chosen_exit->identity,
++    if (!chosen_exit || tor_memneq(chosen_exit->identity,
 +                               exit->identity, DIGEST_LEN)) {
        /* doesn't match */
  //      log_debug(LD_APP,"Requested node '%s', considering node '%s'. No.",
  //                conn->chosen_exit_name, exit->nickname);
diff --cc src/or/directory.c
index 313c6c5,309d997..56c4457
--- a/src/or/directory.c
+++ b/src/or/directory.c
@@@ -3714,38 -3609,8 +3714,38 @@@ dir_routerdesc_download_failed(smartlis
     * every 10 or 60 seconds (FOO_DESCRIPTOR_RETRY_INTERVAL) in main.c. */
  }
  
 +/* DOCDOC NM */
 +static void
 +dir_microdesc_download_failed(smartlist_t *failed,
 +                              int status_code)
 +{
 +  networkstatus_t *consensus
 +    = networkstatus_get_latest_consensus_by_flavor(FLAV_MICRODESC);
 +  routerstatus_t *rs;
 +  download_status_t *dls;
 +  time_t now = time(NULL);
 +  int server = directory_fetches_from_authorities(get_options());
 +
 +  if (! consensus)
 +    return;
 +  SMARTLIST_FOREACH_BEGIN(failed, const char *, d) {
 +    rs = router_get_mutable_consensus_status_by_descriptor_digest(consensus,d);
 +    if (!rs)
 +      continue;
 +    dls = &rs->dl_status;
 +    if (dls->n_download_failures >= MAX_MICRODESC_DOWNLOAD_FAILURES)
 +      continue;
 +    {
 +      char buf[BASE64_DIGEST256_LEN+1];
 +      digest256_to_base64(buf, d);
 +      download_status_increment_failure(dls, status_code, buf,
 +                                        server, now);
 +    }
 +  } SMARTLIST_FOREACH_END(d);
 +}
 +
- /** Helper.  Compare two fp_pair_t objects, and return -1, 0, or 1 as
-  * appropriate. */
+ /** Helper.  Compare two fp_pair_t objects, and return negative, 0, or
+  * positive as appropriate. */
  static int
  _compare_pairs(const void **a, const void **b)
  {
diff --cc src/or/microdesc.c
index 717488b,b87e0d9..f7f42a4
--- a/src/or/microdesc.c
+++ b/src/or/microdesc.c
@@@ -464,21 -414,7 +464,21 @@@ microdesc_cache_rebuild(microdesc_cache
    SMARTLIST_FOREACH_BEGIN(wrote, microdesc_t *, md) {
      tor_assert(md->saved_location == SAVED_IN_CACHE);
      md->body = (char*)cache->cache_content->data + md->off;
 -    tor_assert(fast_memeq(md->body, "onion-key", 9));
 +    if (PREDICT_UNLIKELY(
 +                 md->bodylen < 9 || memcmp(md->body, "onion-key", 9) != 0)) {
 +      /* XXXX023 once bug 2022 is solved, we can kill this block and turn it
 +       * into just the tor_assert(!memcmp) */
 +      off_t avail = cache->cache_content->size - md->off;
 +      char *bad_str;
 +      tor_assert(avail >= 0);
 +      bad_str = tor_strndup(md->body, MIN(128, (size_t)avail));
 +      log_err(LD_BUG, "After rebuilding microdesc cache, offsets seem wrong. "
 +              " At offset %d, I expected to find a microdescriptor starting "
 +              " with \"onion-key\".  Instead I got %s.",
 +              (int)md->off, escaped(bad_str));
 +      tor_free(bad_str);
-       tor_assert(!memcmp(md->body, "onion-key", 9));
++      tor_assert(fast_memeq(md->body, "onion-key", 9));
 +    }
    } SMARTLIST_FOREACH_END(md);
  
    smartlist_free(wrote);
diff --cc src/or/networkstatus.c
index 7fd3d36,1aa4e4a..837c8c2
--- a/src/or/networkstatus.c
+++ b/src/or/networkstatus.c
@@@ -939,12 -924,13 +939,12 @@@ compare_digest_to_routerstatus_entry(co
  {
    const char *key = _key;
    const routerstatus_t *rs = *_member;
-   return memcmp(key, rs->identity_digest, DIGEST_LEN);
+   return tor_memcmp(key, rs->identity_digest, DIGEST_LEN);
  }
  
 -/** Return the entry in <b>ns</b> for the identity digest <b>digest</b>, or
 - * NULL if none was found. */
 +/** As networkstatus_v2_find_entry, but do not return a const pointer */
  routerstatus_t *
 -networkstatus_v2_find_entry(networkstatus_v2_t *ns, const char *digest)
 +networkstatus_v2_find_mutable_entry(networkstatus_v2_t *ns, const char *digest)
  {
    return smartlist_bsearch(ns->entries, digest,
                             compare_digest_to_routerstatus_entry);
@@@ -1519,14 -1493,13 +1519,14 @@@ notify_control_networkstatus_changed(co
    }
    changed = smartlist_create();
  
 -  SMARTLIST_FOREACH_JOIN(old_c->routerstatus_list, routerstatus_t *, rs_old,
 -                         new_c->routerstatus_list, routerstatus_t *, rs_new,
 -                         tor_memcmp(rs_old->identity_digest,
 -                                rs_new->identity_digest, DIGEST_LEN),
 -                         smartlist_add(changed, rs_new)) {
 +  SMARTLIST_FOREACH_JOIN(
 +                     old_c->routerstatus_list, const routerstatus_t *, rs_old,
 +                     new_c->routerstatus_list, const routerstatus_t *, rs_new,
-                      memcmp(rs_old->identity_digest,
++                     tor_memcmp(rs_old->identity_digest,
 +                            rs_new->identity_digest, DIGEST_LEN),
 +                     smartlist_add(changed, (void*) rs_new)) {
      if (routerstatus_has_changed(rs_old, rs_new))
 -      smartlist_add(changed, rs_new);
 +      smartlist_add(changed, (void*)rs_new);
    } SMARTLIST_FOREACH_JOIN_END(rs_old, rs_new);
  
    control_event_networkstatus_changed(changed);
@@@ -1550,9 -1523,10 +1550,9 @@@ networkstatus_copy_old_consensus_info(n
                                  rs_new->identity_digest, DIGEST_LEN),
                           STMT_NIL) {
      /* Okay, so we're looking at the same identity. */
 -    rs_new->name_lookup_warned = rs_old->name_lookup_warned;
      rs_new->last_dir_503_at = rs_old->last_dir_503_at;
  
-     if (!memcmp(rs_old->descriptor_digest, rs_new->descriptor_digest,
+     if (tor_memeq(rs_old->descriptor_digest, rs_new->descriptor_digest,
                  DIGEST_LEN)) {
        /* And the same descriptor too! */
        memcpy(&rs_new->dl_status, &rs_old->dl_status,sizeof(download_status_t));
@@@ -2003,11 -1957,12 +2003,11 @@@ routers_update_status_from_consensus_ne
  
    SMARTLIST_FOREACH_JOIN(ns->routerstatus_list, routerstatus_t *, rs,
                           routers, routerinfo_t *, router,
-                          memcmp(rs->identity_digest,
+                          tor_memcmp(rs->identity_digest,
                                 router->cache_info.identity_digest, DIGEST_LEN),
    {
 +#if 0
      /* We have no routerstatus for this router. Clear flags and skip it. */
 -    if (!namingdir)
 -      router->is_named = 0;
      if (!authdir) {
        if (router->purpose == ROUTER_PURPOSE_GENERAL)
          router_clear_status_flags(router);
@@@ -2019,8 -1973,14 +2019,8 @@@
  
      ds = router_get_trusteddirserver_by_digest(digest);
  
 -    if (!namingdir) {
 -      if (rs->is_named && !strcasecmp(router->nickname, rs->nickname))
 -        router->is_named = 1;
 -      else
 -        router->is_named = 0;
 -    }
      /* Is it the same descriptor, or only the same identity? */
-     if (!memcmp(router->cache_info.signed_descriptor_digest,
+     if (tor_memeq(router->cache_info.signed_descriptor_digest,
                  rs->descriptor_digest, DIGEST_LEN)) {
        if (ns->valid_until > router->cache_info.last_listed_as_valid_until)
          router->cache_info.last_listed_as_valid_until = ns->valid_until;
@@@ -2045,14 -2016,15 +2045,14 @@@
    } SMARTLIST_FOREACH_JOIN_END(rs, router);
  
    /* Now update last_listed_as_valid_until from v2 networkstatuses. */
 -  /* XXXX If this is slow, we need to rethink the code. */
    SMARTLIST_FOREACH(networkstatus_v2_list, networkstatus_v2_t *, ns, {
      time_t live_until = ns->published_on + V2_NETWORKSTATUS_ROUTER_LIFETIME;
 -    SMARTLIST_FOREACH_JOIN(ns->entries, routerstatus_t *, rs,
 +    SMARTLIST_FOREACH_JOIN(ns->entries, const routerstatus_t *, rs,
                           routers, routerinfo_t *, ri,
-                          memcmp(rs->identity_digest,
+                          tor_memcmp(rs->identity_digest,
                                  ri->cache_info.identity_digest, DIGEST_LEN),
                           STMT_NIL) {
-       if (!memcmp(ri->cache_info.signed_descriptor_digest,
+       if (tor_memeq(ri->cache_info.signed_descriptor_digest,
                    rs->descriptor_digest, DIGEST_LEN)) {
          if (live_until > ri->cache_info.last_listed_as_valid_until)
            ri->cache_info.last_listed_as_valid_until = live_until;
diff --cc src/or/router.c
index 6de069f,a7148ea..42b07cb
--- a/src/or/router.c
+++ b/src/or/router.c
@@@ -724,8 -721,8 +724,8 @@@ init_keys(void
               type, ds->type);
      ds->type = type;
    }
 -  if (v3_digest_set && (ds->type & V3_AUTHORITY) &&
 +  if (v3_digest_set && (ds->type & V3_DIRINFO) &&
-       memcmp(v3_digest, ds->v3_identity_digest, DIGEST_LEN)) {
+       tor_memneq(v3_digest, ds->v3_identity_digest, DIGEST_LEN)) {
      log_warn(LD_DIR, "V3 identity key does not match identity declared in "
               "DirServer line.  Adjusting.");
      memcpy(ds->v3_identity_digest, v3_digest, DIGEST_LEN);
diff --cc src/or/routerlist.c
index 04f4214,6c649ab..8d25eaa
--- a/src/or/routerlist.c
+++ b/src/or/routerlist.c
@@@ -1027,8 -1021,8 +1027,8 @@@ trusteddirserver_get_by_v3_auth_digest(
  
    SMARTLIST_FOREACH(trusted_dir_servers, trusted_dir_server_t *, ds,
       {
-        if (!memcmp(ds->v3_identity_digest, digest, DIGEST_LEN) &&
+        if (tor_memeq(ds->v3_identity_digest, digest, DIGEST_LEN) &&
 -           (ds->type & V3_AUTHORITY))
 +           (ds->type & V3_DIRINFO))
           return ds;
       });
  
@@@ -2280,19 -2265,9 +2280,19 @@@ hex_digest_nickname_matches(const char 
        return 0;
    }
  
-   return !memcmp(digest, identity_digest, DIGEST_LEN);
 -  if (base16_decode(digest, DIGEST_LEN, hexdigest, HEX_DIGEST_LEN)<0)
 -    return 0;
 -  return (tor_memeq(digest, identity_digest, DIGEST_LEN));
++  return tor_memeq(digest, identity_digest, DIGEST_LEN);
 +}
 +
 +/* Return true iff <b>router</b> is listed as named in the current
 + * consensus. */
 +static int
 +router_is_named(const routerinfo_t *router)
 +{
 +  const char *digest =
 +    networkstatus_get_router_digest_by_nickname(router->nickname);
 +
 +  return (digest &&
-           !memcmp(digest, router->cache_info.identity_digest, DIGEST_LEN));
++          tor_memeq(digest, router->cache_info.identity_digest, DIGEST_LEN));
  }
  
  /** Return true iff the digest of <b>router</b>'s identity key,
@@@ -3224,23 -3205,23 +3224,23 @@@ router_set_status(const char *digest, i
    tor_assert(digest);
  
    SMARTLIST_FOREACH(trusted_dir_servers, trusted_dir_server_t *, d,
-                     if (!memcmp(d->digest, digest, DIGEST_LEN))
+                     if (tor_memeq(d->digest, digest, DIGEST_LEN))
                        d->is_running = up);
  
 -  router = router_get_by_digest(digest);
 -  if (router) {
 -    log_debug(LD_DIR,"Marking router '%s/%s' as %s.",
 -              router->nickname, router->address, up ? "up" : "down");
 -    if (!up && router_is_me(router) && !we_are_hibernating())
 +  node = node_get_mutable_by_id(digest);
 +  if (node) {
 +#if 0
 +    char buf[MAX_VERBOSE_NICKNAME_LEN+1];
 +    node_get_verbose_nickname(node,buf);
 +    log_debug(LD_DIR,"Marking router %s as %s.",
 +              buf, up ? "up" : "down");
 +#endif
 +    if (!up && node_is_me(node) && !we_are_hibernating())
        log_warn(LD_NET, "We just marked ourself as down. Are your external "
                 "addresses reachable?");
 -    router->is_running = up;
 -  }
 -  status = router_get_consensus_status_by_id(digest);
 -  if (status && status->is_running != up) {
 -    status->is_running = up;
 -    control_event_networkstatus_changed_single(status);
 +    node->is_running = up;
    }
 +
    router_dir_info_changed();
  }
  
@@@ -3347,16 -3328,15 +3347,16 @@@ router_add_to_routerlist(routerinfo_t *
    SMARTLIST_FOREACH(networkstatus_v2_list, networkstatus_v2_t *, ns,
    {
      routerstatus_t *rs =
 -      networkstatus_v2_find_entry(ns, id_digest);
 +      networkstatus_v2_find_mutable_entry(ns, id_digest);
-     if (rs && !memcmp(rs->descriptor_digest,
+     if (rs && tor_memeq(rs->descriptor_digest,
                        router->cache_info.signed_descriptor_digest,
                        DIGEST_LEN))
        rs->need_to_mirror = 0;
    });
    if (consensus) {
 -    routerstatus_t *rs = networkstatus_vote_find_entry(consensus, id_digest);
 +    routerstatus_t *rs = networkstatus_vote_find_mutable_entry(
 +                                                     consensus, id_digest);
-     if (rs && !memcmp(rs->descriptor_digest,
+     if (rs && tor_memeq(rs->descriptor_digest,
                        router->cache_info.signed_descriptor_digest,
                        DIGEST_LEN)) {
        in_consensus = 1;
@@@ -4627,10 -4545,10 +4627,10 @@@ update_consensus_router_descriptor_down
          is_vote ? &(((vote_routerstatus_t *)rsp)->status) : rsp;
        signed_descriptor_t *sd;
        if ((sd = router_get_by_descriptor_digest(rs->descriptor_digest))) {
 -        routerinfo_t *ri;
 +        const routerinfo_t *ri;
          ++n_have;
 -        if (!(ri = router_get_by_digest(rs->identity_digest)) ||
 +        if (!(ri = router_get_by_id_digest(rs->identity_digest)) ||
-             memcmp(ri->cache_info.signed_descriptor_digest,
+             tor_memneq(ri->cache_info.signed_descriptor_digest,
                     sd->signed_descriptor_digest, DIGEST_LEN)) {
            /* We have a descriptor with this digest, but either there is no
             * entry in routerlist with the same ID (!ri), or there is one,
diff --cc src/test/test_util.c
index efbc47b,0da45df..f4b17c9
--- a/src/test/test_util.c
+++ b/src/test/test_util.c
@@@ -1223,201 -1210,58 +1223,255 @@@ test_util_load_win_lib(void *ptr
  #endif
  
  static void
 +clear_hex_errno(char *hex_errno)
 +{
 +  memset(hex_errno, '\0', HEX_ERRNO_SIZE + 1);
 +}
 +
 +static void
 +test_util_exit_status(void *ptr)
 +{
 +  /* Leave an extra byte for a \0 so we can do string comparison */
 +  char hex_errno[HEX_ERRNO_SIZE + 1];
 +
 +  (void)ptr;
 +
 +  clear_hex_errno(hex_errno);
 +  format_helper_exit_status(0, 0, hex_errno);
 +  tt_str_op(hex_errno, ==, "         0/0\n");
 +
 +  clear_hex_errno(hex_errno);
 +  format_helper_exit_status(0, 0x7FFFFFFF, hex_errno);
 +  tt_str_op(hex_errno, ==, "  0/7FFFFFFF\n");
 +
 +  clear_hex_errno(hex_errno);
 +  format_helper_exit_status(0xFF, -0x80000000, hex_errno);
 +  tt_str_op(hex_errno, ==, "FF/-80000000\n");
 +
 +  clear_hex_errno(hex_errno);
 +  format_helper_exit_status(0x7F, 0, hex_errno);
 +  tt_str_op(hex_errno, ==, "        7F/0\n");
 +
 +  clear_hex_errno(hex_errno);
 +  format_helper_exit_status(0x08, -0x242, hex_errno);
 +  tt_str_op(hex_errno, ==, "      8/-242\n");
 +
 + done:
 +  ;
 +}
 +
 +#ifndef MS_WINDOWS
 +/** Check that fgets waits until a full line, and not return a partial line, on
 + * a EAGAIN with a non-blocking pipe */
 +static void
 +test_util_fgets_eagain(void *ptr)
 +{
 +  int test_pipe[2] = {-1, -1};
 +  int retval;
 +  ssize_t retlen;
 +  char *retptr;
 +  FILE *test_stream = NULL;
 +  char buf[10];
 +
 +  (void)ptr;
 +
 +  /* Set up a pipe to test on */
 +  retval = pipe(test_pipe);
 +  tt_int_op(retval, >=, 0);
 +
 +  /* Set up the read-end to be non-blocking */
 +  retval = fcntl(test_pipe[0], F_SETFL, O_NONBLOCK);
 +  tt_int_op(retval, >=, 0);
 +
 +  /* Open it as a stdio stream */
 +  test_stream = fdopen(test_pipe[0], "r");
 +  tt_ptr_op(test_stream, !=, NULL);
 +
 +  /* Send in a partial line */
 +  retlen = write(test_pipe[1], "A", 1);
 +  tt_int_op(retlen, ==, 1);
 +  retptr = fgets(buf, sizeof(buf), test_stream);
 +  tt_want(retptr == NULL);
 +  tt_int_op(errno, ==, EAGAIN);
 +
 +  /* Send in the rest */
 +  retlen = write(test_pipe[1], "B\n", 2);
 +  tt_int_op(retlen, ==, 2);
 +  retptr = fgets(buf, sizeof(buf), test_stream);
 +  tt_ptr_op(retptr, ==, buf);
 +  tt_str_op(buf, ==, "AB\n");
 +
 +  /* Send in a full line */
 +  retlen = write(test_pipe[1], "CD\n", 3);
 +  tt_int_op(retlen, ==, 3);
 +  retptr = fgets(buf, sizeof(buf), test_stream);
 +  tt_ptr_op(retptr, ==, buf);
 +  tt_str_op(buf, ==, "CD\n");
 +
 +  /* Send in a partial line */
 +  retlen = write(test_pipe[1], "E", 1);
 +  tt_int_op(retlen, ==, 1);
 +  retptr = fgets(buf, sizeof(buf), test_stream);
 +  tt_ptr_op(retptr, ==, NULL);
 +  tt_int_op(errno, ==, EAGAIN);
 +
 +  /* Send in the rest */
 +  retlen = write(test_pipe[1], "F\n", 2);
 +  tt_int_op(retlen, ==, 2);
 +  retptr = fgets(buf, sizeof(buf), test_stream);
 +  tt_ptr_op(retptr, ==, buf);
 +  tt_str_op(buf, ==, "EF\n");
 +
 +  /* Send in a full line and close */
 +  retlen = write(test_pipe[1], "GH", 2);
 +  tt_int_op(retlen, ==, 2);
 +  retval = close(test_pipe[1]);
 +  test_pipe[1] = -1;
 +  tt_int_op(retval, ==, 0);
 +  retptr = fgets(buf, sizeof(buf), test_stream);
 +  tt_ptr_op(retptr, ==, buf);
 +  tt_str_op(buf, ==, "GH");
 +
 +  /* Check for EOF */
 +  retptr = fgets(buf, sizeof(buf), test_stream);
 +  tt_ptr_op(retptr, ==, NULL);
 +  tt_int_op(feof(test_stream), >, 0);
 +
 + done:
 +  if (test_stream != NULL)
 +    fclose(test_stream);
 +  if (test_pipe[0] != -1)
 +    close(test_pipe[0]);
 +  if (test_pipe[1] != -1)
 +    close(test_pipe[1]);
 +}
 +#endif
 +
 +#ifndef MS_WINDOWS
 +/** Helper function for testing tor_spawn_background */
 +static void
 +run_util_spawn_background(const char *argv[], const char *expected_out,
 +                          const char *expected_err, int expected_exit)
 +{
 +  int stdout_pipe=-1, stderr_pipe=-1;
 +  int retval, stat_loc;
 +  pid_t pid;
 +  ssize_t pos;
 +  char stdout_buf[100], stderr_buf[100];
 +
 +  /* Start the program */
 +  retval = tor_spawn_background(argv[0], &stdout_pipe, &stderr_pipe, argv);
 +  tt_int_op(retval, >, 0);
 +  tt_int_op(stdout_pipe, >, 0);
 +  tt_int_op(stderr_pipe, >, 0);
 +  pid = retval;
 +
 +  /* Check stdout */
 +  pos = read_all(stdout_pipe, stdout_buf, sizeof(stdout_buf) - 1, 0);
 +  stdout_buf[pos] = '\0';
 +  tt_int_op(pos, ==, strlen(expected_out));
 +  tt_str_op(stdout_buf, ==, expected_out);
 +
 +  /* Check it terminated correctly */
 +  retval = waitpid(pid, &stat_loc, 0);
 +  tt_int_op(retval, ==, pid);
 +  tt_assert(WIFEXITED(stat_loc));
 +  tt_int_op(WEXITSTATUS(stat_loc), ==, expected_exit);
 +  tt_assert(!WIFSIGNALED(stat_loc));
 +  tt_assert(!WIFSTOPPED(stat_loc));
 +
 +  /* Check stderr */
 +  pos = read_all(stderr_pipe, stderr_buf, sizeof(stderr_buf) - 1, 0);
 +  stderr_buf[pos] = '\0';
 +  tt_int_op(pos, ==, strlen(expected_err));
 +  tt_str_op(stderr_buf, ==, expected_err);
 +
 + done:
 +  ;
 +}
 +
 +/** Check that we can launch a process and read the output */
 +static void
 +test_util_spawn_background_ok(void *ptr)
 +{
 +  const char *argv[] = {BUILDDIR "/src/test/test-child", "--test", NULL};
 +  const char *expected_out = "OUT\n--test\nDONE\n";
 +  const char *expected_err = "ERR\n";
 +
 +  (void)ptr;
 +
 +  run_util_spawn_background(argv, expected_out, expected_err, 0);
 +}
 +
 +/** Check that failing to find the executable works as expected */
 +static void
 +test_util_spawn_background_fail(void *ptr)
 +{
 +  const char *argv[] = {BUILDDIR "/src/test/no-such-file", "--test", NULL};
 +  const char *expected_out = "ERR: Failed to spawn background process "
 +                             "- code          9/2\n";
 +  const char *expected_err = "";
 +
 +  (void)ptr;
 +
 +  run_util_spawn_background(argv, expected_out, expected_err, 255);
 +}
 +#endif
 +
++
++static void
+ test_util_di_ops(void)
+ {
+ #define LT -1
+ #define GT 1
+ #define EQ 0
+   const struct {
+     const char *a; int want_sign; const char *b;
+   } examples[] = {
+     { "Foo", EQ, "Foo" },
+     { "foo", GT, "bar", },
+     { "foobar", EQ ,"foobar" },
+     { "foobar", LT, "foobaw" },
+     { "foobar", GT, "f00bar" },
+     { "foobar", GT, "boobar" },
+     { "", EQ, "" },
+     { NULL, 0, NULL },
+   };
+ 
+   int i;
+ 
+   for (i = 0; examples[i].a; ++i) {
+     size_t len = strlen(examples[i].a);
+     int eq1, eq2, neq1, neq2, cmp1, cmp2;
+     test_eq(len, strlen(examples[i].b));
+     /* We do all of the operations, with operands in both orders. */
+     eq1 = tor_memeq(examples[i].a, examples[i].b, len);
+     eq2 = tor_memeq(examples[i].b, examples[i].a, len);
+     neq1 = tor_memneq(examples[i].a, examples[i].b, len);
+     neq2 = tor_memneq(examples[i].b, examples[i].a, len);
+     cmp1 = tor_memcmp(examples[i].a, examples[i].b, len);
+     cmp2 = tor_memcmp(examples[i].b, examples[i].a, len);
+ 
+     /* Check for correctness of cmp1 */
+     if (cmp1 < 0 && examples[i].want_sign != LT)
+       test_fail();
+     else if (cmp1 > 0 && examples[i].want_sign != GT)
+       test_fail();
+     else if (cmp1 == 0 && examples[i].want_sign != EQ)
+       test_fail();
+ 
+     /* Check for consistency of everything else with cmp1 */
+     test_eq(eq1, eq2);
+     test_eq(neq1, neq2);
+     test_eq(cmp1, -cmp2);
+     test_eq(eq1, cmp1 == 0);
+     test_eq(neq1, !eq1);
+   }
+ 
+  done:
+   ;
+ }
+ 
  #define UTIL_LEGACY(name)                                               \
    { #name, legacy_test_helper, 0, &legacy_setup, test_util_ ## name }
  





More information about the tor-commits mailing list