2016-04-03 16:48:44 -04:00
|
|
|
/* Copyright (c) 2003, Roger Dingledine
|
|
|
|
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
|
2018-06-20 08:13:28 -04:00
|
|
|
* Copyright (c) 2007-2018, The Tor Project, Inc. */
|
2016-04-03 16:48:44 -04:00
|
|
|
/* See LICENSE for licensing information */
|
|
|
|
|
|
|
|
/**
|
|
|
|
* \file util_bug.c
|
|
|
|
**/
|
|
|
|
|
|
|
|
#include "orconfig.h"
|
2018-06-22 11:54:38 -04:00
|
|
|
#include "lib/log/util_bug.h"
|
2018-06-22 10:32:10 -04:00
|
|
|
#include "lib/log/torlog.h"
|
2018-06-21 09:54:04 -04:00
|
|
|
#include "lib/err/backtrace.h"
|
2018-06-21 17:00:48 -04:00
|
|
|
#ifdef TOR_UNIT_TESTS
|
2018-06-26 12:13:23 -04:00
|
|
|
#include "lib/smartlist_core/smartlist_core.h"
|
|
|
|
#include "lib/smartlist_core/smartlist_foreach.h"
|
2018-06-21 17:00:48 -04:00
|
|
|
#endif
|
2018-06-21 16:48:54 -04:00
|
|
|
#include "lib/malloc/util_malloc.h"
|
2018-06-22 11:51:58 -04:00
|
|
|
#include "lib/string/printf.h"
|
2016-09-06 21:01:17 -04:00
|
|
|
|
2018-06-22 13:10:52 -04:00
|
|
|
#include <string.h>
|
|
|
|
|
2017-07-28 10:02:38 -04:00
|
|
|
#ifdef __COVERITY__
|
|
|
|
int bug_macro_deadcode_dummy__ = 0;
|
|
|
|
#endif
|
|
|
|
|
2016-09-06 21:01:17 -04:00
|
|
|
#ifdef TOR_UNIT_TESTS
|
2016-09-08 13:27:30 -04:00
|
|
|
static void (*failed_assertion_cb)(void) = NULL;
|
2016-09-06 21:01:17 -04:00
|
|
|
static int n_bugs_to_capture = 0;
|
|
|
|
static smartlist_t *bug_messages = NULL;
|
|
|
|
#define capturing_bugs() (bug_messages != NULL && n_bugs_to_capture)
|
|
|
|
void
|
|
|
|
tor_capture_bugs_(int n)
|
|
|
|
{
|
|
|
|
tor_end_capture_bugs_();
|
|
|
|
bug_messages = smartlist_new();
|
|
|
|
n_bugs_to_capture = n;
|
|
|
|
}
|
|
|
|
void
|
|
|
|
tor_end_capture_bugs_(void)
|
|
|
|
{
|
|
|
|
n_bugs_to_capture = 0;
|
|
|
|
if (!bug_messages)
|
|
|
|
return;
|
|
|
|
SMARTLIST_FOREACH(bug_messages, char *, cp, tor_free(cp));
|
|
|
|
smartlist_free(bug_messages);
|
2018-06-22 11:54:38 -04:00
|
|
|
bug_messages = NULL;
|
2016-09-06 21:01:17 -04:00
|
|
|
}
|
|
|
|
const smartlist_t *
|
|
|
|
tor_get_captured_bug_log_(void)
|
|
|
|
{
|
|
|
|
return bug_messages;
|
|
|
|
}
|
|
|
|
static void
|
|
|
|
add_captured_bug(const char *s)
|
|
|
|
{
|
|
|
|
--n_bugs_to_capture;
|
2016-10-27 10:26:06 +01:00
|
|
|
smartlist_add_strdup(bug_messages, s);
|
2016-09-06 21:01:17 -04:00
|
|
|
}
|
2016-09-08 13:27:30 -04:00
|
|
|
/** Set a callback to be invoked when we get any tor_bug_occurred_
|
|
|
|
* invocation. We use this in the unit tests so that a nonfatal
|
|
|
|
* assertion failure can also count as a test failure.
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
tor_set_failed_assertion_callback(void (*fn)(void))
|
|
|
|
{
|
|
|
|
failed_assertion_cb = fn;
|
|
|
|
}
|
2017-09-15 16:24:44 -04:00
|
|
|
#else /* !(defined(TOR_UNIT_TESTS)) */
|
2016-09-06 21:01:17 -04:00
|
|
|
#define capturing_bugs() (0)
|
|
|
|
#define add_captured_bug(s) do { } while (0)
|
2017-09-15 16:24:44 -04:00
|
|
|
#endif /* defined(TOR_UNIT_TESTS) */
|
2016-04-03 16:48:44 -04:00
|
|
|
|
|
|
|
/** Helper for tor_assert: report the assertion failure. */
|
|
|
|
void
|
|
|
|
tor_assertion_failed_(const char *fname, unsigned int line,
|
|
|
|
const char *func, const char *expr)
|
|
|
|
{
|
|
|
|
char buf[256];
|
|
|
|
log_err(LD_BUG, "%s:%u: %s: Assertion %s failed; aborting.",
|
|
|
|
fname, line, func, expr);
|
|
|
|
tor_snprintf(buf, sizeof(buf),
|
|
|
|
"Assertion %s failed in %s at %s:%u",
|
|
|
|
expr, func, fname, line);
|
|
|
|
log_backtrace(LOG_ERR, LD_BUG, buf);
|
|
|
|
}
|
|
|
|
|
2016-04-12 10:10:44 -04:00
|
|
|
/** Helper for tor_assert_nonfatal: report the assertion failure. */
|
2016-04-05 09:40:51 -04:00
|
|
|
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) {
|
2016-09-06 21:01:17 -04:00
|
|
|
if (capturing_bugs()) {
|
|
|
|
add_captured_bug("This line should not have been reached.");
|
|
|
|
return;
|
|
|
|
}
|
2016-04-05 09:40:51 -04:00
|
|
|
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 {
|
2016-09-06 21:01:17 -04:00
|
|
|
if (capturing_bugs()) {
|
|
|
|
add_captured_bug(expr);
|
|
|
|
return;
|
|
|
|
}
|
2016-04-05 09:40:51 -04:00
|
|
|
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);
|
2016-09-08 13:27:30 -04:00
|
|
|
|
|
|
|
#ifdef TOR_UNIT_TESTS
|
|
|
|
if (failed_assertion_cb) {
|
|
|
|
failed_assertion_cb();
|
|
|
|
}
|
|
|
|
#endif
|
2016-04-05 09:40:51 -04:00
|
|
|
}
|
2018-06-22 11:51:58 -04:00
|
|
|
|
|
|
|
#ifdef _WIN32
|
|
|
|
/** Take a filename and return a pointer to its final element. This
|
|
|
|
* function is called on __FILE__ to fix a MSVC nit where __FILE__
|
|
|
|
* contains the full path to the file. This is bad, because it
|
|
|
|
* confuses users to find the home directory of the person who
|
|
|
|
* compiled the binary in their warning messages.
|
|
|
|
*/
|
|
|
|
const char *
|
|
|
|
tor_fix_source_file(const char *fname)
|
|
|
|
{
|
|
|
|
const char *cp1, *cp2, *r;
|
|
|
|
cp1 = strrchr(fname, '/');
|
|
|
|
cp2 = strrchr(fname, '\\');
|
|
|
|
if (cp1 && cp2) {
|
|
|
|
r = (cp1<cp2)?(cp2+1):(cp1+1);
|
|
|
|
} else if (cp1) {
|
|
|
|
r = cp1+1;
|
|
|
|
} else if (cp2) {
|
|
|
|
r = cp2+1;
|
|
|
|
} else {
|
|
|
|
r = fname;
|
|
|
|
}
|
|
|
|
return r;
|
|
|
|
}
|
|
|
|
#endif /* defined(_WIN32) */
|