Commit a885271c authored by Nick Mathewson's avatar Nick Mathewson 🦞
Browse files

Add new tor_assert_nonfatal*() macros.

Unlike tor_assert(), these macros don't abort the process.  They're
good for checking conditions we want to warn about, but which don't
warrant a full crash.

This commit also changes the default implementation for
tor_fragile_assert() to tor_assert_nonfatal_unreached_once().

Closes ticket 18613.
parent 78654021
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
  o Minor features (safety, debugging):

    * Add a set of macros to check nonfatal assertions, for internal
      use. Migrating more of our checks to these should help us avoid
      needless crash bugs. Closes ticket 18613.
+24 −0
Original line number Diff line number Diff line
@@ -26,3 +26,27 @@ tor_assertion_failed_(const char *fname, unsigned int line,
  log_backtrace(LOG_ERR, LD_BUG, buf);
}


void
tor_bug_occurred_(const char *fname, unsigned int line,
                  const char *func, const char *expr,
                  int once)
{
  char buf[256];
  const char *once_str = once ?
    " (Future instances of this warning will be silenced.)": "";
  if (! expr) {
    log_warn(LD_BUG, "%s:%u: %s: This line should not have been reached.%s",
             fname, line, func, once_str);
    tor_snprintf(buf, sizeof(buf),
                 "Line unexpectedly reached at %s at %s:%u",
                 func, fname, line);
  } else {
    log_warn(LD_BUG, "%s:%u: %s: Non-fatal assertion %s failed.%s",
             fname, line, func, expr, once_str);
    tor_snprintf(buf, sizeof(buf),
                 "Non-fatal assertion %s failed in %s at %s:%u",
                 expr, func, fname, line);
  }
  log_backtrace(LOG_WARN, LD_BUG, buf);
}
+47 −2
Original line number Diff line number Diff line
@@ -46,13 +46,58 @@
  } STMT_END
#endif

#define tor_assert_unreached() tor_assert(0)

/* Non-fatal bug assertions. The "unreached" variants mean "this line should
 * never be reached." The "once" variants mean "Don't log a warning more than
 * once".
 */

#ifdef ALL_BUGS_ARE_FATAL
#define tor_assert_nonfatal_unreached() tor_assert(0)
#define tor_assert_nonfatal(cond) tor_assert((cond))
#define tor_assert_nonfatal_unreached_once() tor_assert(0)
#define tor_assert_nonfatal_once(cond) tor_assert((cond))
#elif defined(TOR_UNIT_TESTS) && defined(DISABLE_ASSERTS_IN_UNIT_TESTS)
#define tor_assert_nonfatal_unreached() STMT_NIL
#define tor_assert_nonfatal(cond) ((void)(cond))
#define tor_assert_nonfatal_unreached_once() STMT_NIL
#define tor_assert_nonfatal_once(cond) ((void)(cond))
#else /* Normal case, !ALL_BUGS_ARE_FATAL, !DISABLE_ASSERTS_IN_UNIT_TESTS */
#define tor_assert_nonfatal_unreached() STMT_BEGIN                      \
  tor_bug_occurred_(SHORT_FILE__, __LINE__, __func__, NULL, 0);         \
  STMT_END
#define tor_assert_nonfatal(cond) STMT_BEGIN                            \
  if (PREDICT_UNLIKELY(!(cond))) {                                      \
    tor_bug_occurred_(SHORT_FILE__, __LINE__, __func__, #cond, 0);  \
  }                                                                     \
  STMT_END
#define tor_assert_nonfatal_unreached_once() STMT_BEGIN                 \
  static int warning_logged__ = 0;                                      \
  if (!warning_logged__) {                                              \
    warning_logged__ = 1;                                               \
    tor_bug_occurred_(SHORT_FILE__, __LINE__, __func__, NULL, 1);       \
  }                                                                     \
  STMT_END
#define tor_assert_nonfatal_once(cond) STMT_BEGIN                       \
  static int warning_logged__ = 0;                                      \
  if (!warning_logged__ && PREDICT_UNLIKELY(!(cond))) {                 \
    warning_logged__ = 1;                                               \
    tor_bug_occurred_(SHORT_FILE__, __LINE__, __func__, #cond, 1);      \
  }                                                                     \
  STMT_END
#endif

/** Define this if you want Tor to crash when any problem comes up,
 * so you can get a coredump and track things down. */
// #define tor_fragile_assert() tor_assert(0)
#define tor_fragile_assert()
// #define tor_fragile_assert() tor_assert_unreached(0)
#define tor_fragile_assert() tor_assert_nonfatal_unreached_once()

void tor_assertion_failed_(const char *fname, unsigned int line,
                           const char *func, const char *expr);
void tor_bug_occurred_(const char *fname, unsigned int line,
                       const char *func, const char *expr,
                       int once);

#endif
+3 −5
Original line number Diff line number Diff line
@@ -1643,8 +1643,8 @@ rotate_x509_certificate_callback(time_t now, const or_options_t *options)
   * TLS context. */
  log_info(LD_GENERAL,"Rotating tls context.");
  if (router_initialize_tls_context() < 0) {
    log_warn(LD_BUG, "Error reinitializing TLS context");
    tor_assert(0);
    log_err(LD_BUG, "Error reinitializing TLS context");
    tor_assert_unreached();
  }

  /* We also make sure to rotate the TLS connections themselves if they've
@@ -2563,9 +2563,7 @@ run_main_loop_once(void)
        return -1;
#endif
    } else {
      if (ERRNO_IS_EINPROGRESS(e))
        log_warn(LD_BUG,
                 "libevent call returned EINPROGRESS? Please report.");
      tor_assert_nonfatal_once(! ERRNO_IS_EINPROGRESS(e));
      log_debug(LD_NET,"libevent call interrupted.");
      /* You can't trust the results of this poll(). Go back to the
       * top of the big for loop. */
+1 −1
Original line number Diff line number Diff line
@@ -103,7 +103,7 @@ policy_expand_private(smartlist_t **policy)
       if (tor_addr_parse_mask_ports(private_nets[i], 0,
                               &newpolicy.addr,
                               &newpolicy.maskbits, &port_min, &port_max)<0) {
         tor_assert(0);
         tor_assert_unreached();
       }
       smartlist_add(tmp, addr_policy_get_canonical_entry(&newpolicy));
     }
Loading