Merge branch 'maint-0.2.9' into maint-0.3.3
[tor.git] / src / common / util_bug.h
blobc274355f30a4f3c4bb824cd6582bc3c75ca84a93
1 /* Copyright (c) 2003-2004, Roger Dingledine
2 * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
3 * Copyright (c) 2007-2017, The Tor Project, Inc. */
4 /* See LICENSE for licensing information */
6 /**
7 * \file util_bug.h
9 * \brief Macros to manage assertions, fatal and non-fatal.
11 * Guidelines: All the different kinds of assertion in this file are for
12 * bug-checking only. Don't write code that can assert based on bad inputs.
14 * We provide two kinds of assertion here: "fatal" and "nonfatal". Use
15 * nonfatal assertions for any bug you can reasonably recover from -- and
16 * please, try to recover! Many severe bugs in Tor have been caused by using
17 * a regular assertion when a nonfatal assertion would have been better.
19 * If you need to check a condition with a nonfatal assertion, AND recover
20 * from that same condition, consider using the BUG() macro inside a
21 * conditional. For example:
23 * <code>
24 * // wrong -- use tor_assert_nonfatal() if you just want an assertion.
25 * BUG(ptr == NULL);
27 * // okay, but needlessly verbose
28 * tor_assert_nonfatal(ptr != NULL);
29 * if (ptr == NULL) { ... }
31 * // this is how we do it:
32 * if (BUG(ptr == NULL)) { ... }
33 * </code>
34 **/
36 #ifndef TOR_UTIL_BUG_H
37 #define TOR_UTIL_BUG_H
39 #include "orconfig.h"
40 #include "compat.h"
41 #include "testsupport.h"
43 /* Replace assert() with a variant that sends failures to the log before
44 * calling assert() normally.
46 #ifdef NDEBUG
47 /* Nobody should ever want to build with NDEBUG set. 99% of our asserts will
48 * be outside the critical path anyway, so it's silly to disable bug-checking
49 * throughout the entire program just because a few asserts are slowing you
50 * down. Profile, optimize the critical path, and keep debugging on.
52 * And I'm not just saying that because some of our asserts check
53 * security-critical properties.
55 #error "Sorry; we don't support building with NDEBUG."
56 #endif /* defined(NDEBUG) */
58 #if defined(TOR_UNIT_TESTS) && defined(__GNUC__)
59 /* We define this GCC macro as a replacement for PREDICT_UNLIKELY() in this
60 * header, so that in our unit test builds, we'll get compiler warnings about
61 * stuff like tor_assert(n = 5).
63 * The key here is that (e) is wrapped in exactly one layer of parentheses,
64 * and then passed right to a conditional. If you do anything else to the
65 * expression here, or introduce any more parentheses, the compiler won't
66 * help you.
68 * We only do this for the unit-test build case because it interferes with
69 * the likely-branch labeling. Note below that in the other case, we define
70 * these macros to just be synonyms for PREDICT_(UN)LIKELY.
72 #define ASSERT_PREDICT_UNLIKELY_(e) \
73 ({ \
74 int tor__assert_tmp_value__; \
75 if (e) \
76 tor__assert_tmp_value__ = 1; \
77 else \
78 tor__assert_tmp_value__ = 0; \
79 tor__assert_tmp_value__; \
81 #define ASSERT_PREDICT_LIKELY_(e) ASSERT_PREDICT_UNLIKELY_(e)
82 #else
83 #define ASSERT_PREDICT_UNLIKELY_(e) PREDICT_UNLIKELY(e)
84 #define ASSERT_PREDICT_LIKELY_(e) PREDICT_LIKELY(e)
85 #endif
87 /* Sometimes we don't want to use assertions during branch coverage tests; it
88 * leads to tons of unreached branches which in reality are only assertions we
89 * didn't hit. */
90 #if defined(TOR_UNIT_TESTS) && defined(DISABLE_ASSERTS_IN_UNIT_TESTS)
91 #define tor_assert(a) STMT_BEGIN \
92 (void)(a); \
93 STMT_END
94 #else
95 /** Like assert(3), but send assertion failures to the log as well as to
96 * stderr. */
97 #define tor_assert(expr) STMT_BEGIN \
98 if (ASSERT_PREDICT_LIKELY_(expr)) { \
99 } else { \
100 tor_assertion_failed_(SHORT_FILE__, __LINE__, __func__, #expr); \
101 abort(); \
102 } STMT_END
103 #endif /* defined(TOR_UNIT_TESTS) && defined(DISABLE_ASSERTS_IN_UNIT_TESTS) */
105 #define tor_assert_unreached() tor_assert(0)
107 /* Non-fatal bug assertions. The "unreached" variants mean "this line should
108 * never be reached." The "once" variants mean "Don't log a warning more than
109 * once".
111 * The 'BUG' macro checks a boolean condition and logs an error message if it
112 * is true. Example usage:
113 * if (BUG(x == NULL))
114 * return -1;
117 #ifdef __COVERITY__
118 extern int bug_macro_deadcode_dummy__;
119 #undef BUG
120 // Coverity defines this in global headers; let's override it. This is a
121 // magic coverity-only preprocessor thing.
122 // We use this "deadcode_dummy__" trick to prevent coverity from
123 // complaining about unreachable bug cases.
124 #nodef BUG(x) ((x)?(__coverity_panic__(),1):(0+bug_macro_deadcode_dummy__))
125 #endif /* defined(__COVERITY__) */
127 #if defined(__COVERITY__) || defined(__clang_analyzer__)
128 // We're running with a static analysis tool: let's treat even nonfatal
129 // assertion failures as something that we need to avoid.
130 #define ALL_BUGS_ARE_FATAL
131 #endif
133 #ifdef ALL_BUGS_ARE_FATAL
134 #define tor_assert_nonfatal_unreached() tor_assert(0)
135 #define tor_assert_nonfatal(cond) tor_assert((cond))
136 #define tor_assert_nonfatal_unreached_once() tor_assert(0)
137 #define tor_assert_nonfatal_once(cond) tor_assert((cond))
138 #define BUG(cond) \
139 (ASSERT_PREDICT_UNLIKELY_(cond) ? \
140 (tor_assertion_failed_(SHORT_FILE__,__LINE__,__func__,"!("#cond")"), \
141 abort(), 1) \
142 : 0)
143 #elif defined(TOR_UNIT_TESTS) && defined(DISABLE_ASSERTS_IN_UNIT_TESTS)
144 #define tor_assert_nonfatal_unreached() STMT_NIL
145 #define tor_assert_nonfatal(cond) ((void)(cond))
146 #define tor_assert_nonfatal_unreached_once() STMT_NIL
147 #define tor_assert_nonfatal_once(cond) ((void)(cond))
148 #define BUG(cond) (ASSERT_PREDICT_UNLIKELY_(cond) ? 1 : 0)
149 #else /* Normal case, !ALL_BUGS_ARE_FATAL, !DISABLE_ASSERTS_IN_UNIT_TESTS */
150 #define tor_assert_nonfatal_unreached() STMT_BEGIN \
151 tor_bug_occurred_(SHORT_FILE__, __LINE__, __func__, NULL, 0); \
152 STMT_END
153 #define tor_assert_nonfatal(cond) STMT_BEGIN \
154 if (ASSERT_PREDICT_LIKELY_(cond)) { \
155 } else { \
156 tor_bug_occurred_(SHORT_FILE__, __LINE__, __func__, #cond, 0); \
158 STMT_END
159 #define tor_assert_nonfatal_unreached_once() STMT_BEGIN \
160 static int warning_logged__ = 0; \
161 if (!warning_logged__) { \
162 warning_logged__ = 1; \
163 tor_bug_occurred_(SHORT_FILE__, __LINE__, __func__, NULL, 1); \
165 STMT_END
166 #define tor_assert_nonfatal_once(cond) STMT_BEGIN \
167 static int warning_logged__ = 0; \
168 if (ASSERT_PREDICT_LIKELY_(cond)) { \
169 } else if (!warning_logged__) { \
170 warning_logged__ = 1; \
171 tor_bug_occurred_(SHORT_FILE__, __LINE__, __func__, #cond, 1); \
173 STMT_END
174 #define BUG(cond) \
175 (ASSERT_PREDICT_UNLIKELY_(cond) ? \
176 (tor_bug_occurred_(SHORT_FILE__,__LINE__,__func__,"!("#cond")",0), 1) \
177 : 0)
178 #endif /* defined(ALL_BUGS_ARE_FATAL) || ... */
180 #ifdef __GNUC__
181 #define IF_BUG_ONCE__(cond,var) \
182 if (( { \
183 static int var = 0; \
184 int bool_result = !!(cond); \
185 if (bool_result && !var) { \
186 var = 1; \
187 tor_bug_occurred_(SHORT_FILE__, __LINE__, __func__, \
188 "!("#cond")", 1); \
190 bool_result; } ))
191 #else /* !(defined(__GNUC__)) */
192 #define IF_BUG_ONCE__(cond,var) \
193 static int var = 0; \
194 if ((cond) ? \
195 (var ? 1 : \
196 (var=1, \
197 tor_bug_occurred_(SHORT_FILE__, __LINE__, __func__, \
198 "!("#cond")", 1), \
199 1)) \
200 : 0)
201 #endif /* defined(__GNUC__) */
202 #define IF_BUG_ONCE_VARNAME_(a) \
203 warning_logged_on_ ## a ## __
204 #define IF_BUG_ONCE_VARNAME__(a) \
205 IF_BUG_ONCE_VARNAME_(a)
207 /** This macro behaves as 'if (bug(x))', except that it only logs its
208 * warning once, no matter how many times it triggers.
211 #define IF_BUG_ONCE(cond) \
212 IF_BUG_ONCE__(ASSERT_PREDICT_UNLIKELY_(cond), \
213 IF_BUG_ONCE_VARNAME__(__LINE__))
215 /** Define this if you want Tor to crash when any problem comes up,
216 * so you can get a coredump and track things down. */
217 // #define tor_fragile_assert() tor_assert_unreached(0)
218 #define tor_fragile_assert() tor_assert_nonfatal_unreached_once()
220 void tor_assertion_failed_(const char *fname, unsigned int line,
221 const char *func, const char *expr);
222 void tor_bug_occurred_(const char *fname, unsigned int line,
223 const char *func, const char *expr,
224 int once);
226 #ifdef TOR_UNIT_TESTS
227 void tor_capture_bugs_(int n);
228 void tor_end_capture_bugs_(void);
229 const struct smartlist_t *tor_get_captured_bug_log_(void);
230 void tor_set_failed_assertion_callback(void (*fn)(void));
231 #endif /* defined(TOR_UNIT_TESTS) */
233 #endif /* !defined(TOR_UTIL_BUG_H) */