Merge branch 'tor-gitlab/mr/568'
[tor.git] / src / lib / log / util_bug.h
blobdd82981e089d619b2ba789bbed1b5f12c2af47cb
1 /* Copyright (c) 2003-2004, Roger Dingledine
2 * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
3 * Copyright (c) 2007-2021, 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 "lib/cc/compat_compiler.h"
41 #include "lib/log/log.h"
42 #include "lib/testsupport/testsupport.h"
44 /* Replace assert() with a variant that sends failures to the log before
45 * calling assert() normally.
47 #ifdef NDEBUG
48 /* Nobody should ever want to build with NDEBUG set. 99% of our asserts will
49 * be outside the critical path anyway, so it's silly to disable bug-checking
50 * throughout the entire program just because a few asserts are slowing you
51 * down. Profile, optimize the critical path, and keep debugging on.
53 * And I'm not just saying that because some of our asserts check
54 * security-critical properties.
56 #error "Sorry; we don't support building with NDEBUG."
57 #endif /* defined(NDEBUG) */
59 #if defined(TOR_UNIT_TESTS) && defined(__GNUC__)
60 /* We define this GCC macro as a replacement for PREDICT_UNLIKELY() in this
61 * header, so that in our unit test builds, we'll get compiler warnings about
62 * stuff like tor_assert(n = 5).
64 * The key here is that (e) is wrapped in exactly one layer of parentheses,
65 * and then passed right to a conditional. If you do anything else to the
66 * expression here, or introduce any more parentheses, the compiler won't
67 * help you.
69 * We only do this for the unit-test build case because it interferes with
70 * the likely-branch labeling. Note below that in the other case, we define
71 * these macros to just be synonyms for PREDICT_(UN)LIKELY.
73 #define ASSERT_PREDICT_UNLIKELY_(e) \
74 ( { \
75 int tor__assert_tmp_value__; \
76 if (e) \
77 tor__assert_tmp_value__ = 1; \
78 else \
79 tor__assert_tmp_value__ = 0; \
80 tor__assert_tmp_value__; \
81 } )
82 #define ASSERT_PREDICT_LIKELY_(e) ASSERT_PREDICT_UNLIKELY_(e)
83 #else /* !(defined(TOR_UNIT_TESTS) && defined(__GNUC__)) */
84 #define ASSERT_PREDICT_UNLIKELY_(e) PREDICT_UNLIKELY(e)
85 #define ASSERT_PREDICT_LIKELY_(e) PREDICT_LIKELY(e)
86 #endif /* defined(TOR_UNIT_TESTS) && defined(__GNUC__) */
88 /* Sometimes we don't want to use assertions during branch coverage tests; it
89 * leads to tons of unreached branches which in reality are only assertions we
90 * didn't hit. */
91 #if defined(TOR_UNIT_TESTS) && defined(DISABLE_ASSERTS_IN_UNIT_TESTS)
92 #define tor_assert(a) STMT_BEGIN \
93 (void)(a); \
94 STMT_END
95 #define tor_assertf(a, fmt, ...) STMT_BEGIN \
96 (void)(a); \
97 (void)(fmt); \
98 STMT_END
99 #else /* !(defined(TOR_UNIT_TESTS) && defined(DISABLE_ASSERTS_IN_UNIT_T...)) */
100 /** Like assert(3), but send assertion failures to the log as well as to
101 * stderr. */
102 #define tor_assert(expr) tor_assertf(expr, NULL)
104 #define tor_assertf(expr, fmt, ...) STMT_BEGIN \
105 if (ASSERT_PREDICT_LIKELY_(expr)) { \
106 } else { \
107 tor_assertion_failed_(SHORT_FILE__, __LINE__, __func__, #expr, \
108 fmt, ##__VA_ARGS__); \
109 tor_abort_(); \
110 } STMT_END
111 #endif /* defined(TOR_UNIT_TESTS) && defined(DISABLE_ASSERTS_IN_UNIT_TESTS) */
113 #define tor_assert_unreached() \
114 STMT_BEGIN { \
115 tor_assertion_failed_(SHORT_FILE__, __LINE__, __func__, \
116 "line should be unreached", NULL); \
117 tor_abort_(); \
118 } STMT_END
120 /* Non-fatal bug assertions. The "unreached" variants mean "this line should
121 * never be reached." The "once" variants mean "Don't log a warning more than
122 * once".
124 * The 'BUG' macro checks a boolean condition and logs an error message if it
125 * is true. Example usage:
126 * if (BUG(x == NULL))
127 * return -1;
130 #ifdef __COVERITY__
131 #undef BUG
132 // Coverity defines this in global headers; let's override it. This is a
133 // magic coverity-only preprocessor thing.
134 #ifndef COCCI
135 #nodef BUG(x) (x)
136 #endif
137 #endif /* defined(__COVERITY__) */
139 #if defined(__COVERITY__) || defined(__clang_analyzer__)
140 // We're running with a static analysis tool: let's treat even nonfatal
141 // assertion failures as something that we need to avoid.
142 #define ALL_BUGS_ARE_FATAL
143 #endif
145 /** Define ALL_BUGS_ARE_FATAL if you want Tor to crash when any problem comes
146 * up, so you can get a coredump and track things down. */
147 #ifdef ALL_BUGS_ARE_FATAL
148 #define tor_assert_nonfatal_unreached() tor_assert(0)
149 #define tor_assert_nonfatal(cond) tor_assert((cond))
150 #define tor_assertf_nonfatal(cond, fmt, ...) \
151 tor_assertf(cond, fmt, ##__VA_ARGS__)
152 #define tor_assert_nonfatal_unreached_once() tor_assert(0)
153 #define tor_assert_nonfatal_once(cond) tor_assert((cond))
154 #define BUG(cond) \
155 (ASSERT_PREDICT_UNLIKELY_(cond) ? \
156 (tor_assertion_failed_(SHORT_FILE__,__LINE__,__func__,"!("#cond")",NULL), \
157 tor_abort_(), 1) \
158 : 0)
159 #ifndef COCCI
160 #define IF_BUG_ONCE(cond) if (BUG(cond))
161 #endif
162 #elif defined(TOR_UNIT_TESTS) && defined(DISABLE_ASSERTS_IN_UNIT_TESTS)
163 #define tor_assert_nonfatal_unreached() STMT_NIL
164 #define tor_assert_nonfatal(cond) ((void)(cond))
165 #define tor_assertf_nonfatal(cond, fmt, ...) STMT_BEGIN \
166 (void)cond; \
167 (void)fmt; \
168 STMT_END
169 #define tor_assert_nonfatal_unreached_once() STMT_NIL
170 #define tor_assert_nonfatal_once(cond) ((void)(cond))
171 #define BUG(cond) (ASSERT_PREDICT_UNLIKELY_(cond) ? 1 : 0)
172 #ifndef COCCI
173 #define IF_BUG_ONCE(cond) if (BUG(cond))
174 #endif
175 #else /* Normal case, !ALL_BUGS_ARE_FATAL, !DISABLE_ASSERTS_IN_UNIT_TESTS */
176 #define tor_assert_nonfatal_unreached() STMT_BEGIN \
177 tor_bug_occurred_(SHORT_FILE__, __LINE__, __func__, NULL, 0, NULL); \
178 STMT_END
179 #define tor_assert_nonfatal(cond) STMT_BEGIN \
180 if (ASSERT_PREDICT_LIKELY_(cond)) { \
181 } else { \
182 tor_bug_occurred_(SHORT_FILE__, __LINE__, __func__, #cond, 0, NULL);\
184 STMT_END
185 #define tor_assertf_nonfatal(cond, fmt, ...) STMT_BEGIN \
186 if (ASSERT_PREDICT_UNLIKELY_(cond)) { \
187 } else { \
188 tor_bug_occurred_(SHORT_FILE__, __LINE__, __func__, #cond, 0, \
189 fmt, ##__VA_ARGS__); \
191 STMT_END
192 #define tor_assert_nonfatal_unreached_once() STMT_BEGIN \
193 static int warning_logged__ = 0; \
194 if (!warning_logged__) { \
195 warning_logged__ = 1; \
196 tor_bug_occurred_(SHORT_FILE__, __LINE__, __func__, NULL, 1, NULL); \
198 STMT_END
199 #define tor_assert_nonfatal_once(cond) STMT_BEGIN \
200 static int warning_logged__ = 0; \
201 if (ASSERT_PREDICT_LIKELY_(cond)) { \
202 } else if (!warning_logged__) { \
203 warning_logged__ = 1; \
204 tor_bug_occurred_(SHORT_FILE__, __LINE__, __func__, #cond, 1, NULL);\
206 STMT_END
207 #define BUG(cond) \
208 (ASSERT_PREDICT_UNLIKELY_(cond) ? \
209 (tor_bug_occurred_(SHORT_FILE__,__LINE__,__func__,"!("#cond")",0,NULL),1) \
210 : 0)
212 #ifndef COCCI
213 #ifdef __GNUC__
214 #define IF_BUG_ONCE__(cond,var) \
215 if (( { \
216 static int var = 0; \
217 int bool_result = !!(cond); \
218 if (bool_result && !var) { \
219 var = 1; \
220 tor_bug_occurred_(SHORT_FILE__, __LINE__, __func__, \
221 ("!("#cond")"), 1, NULL); \
223 bool_result; } ))
224 #else /* !defined(__GNUC__) */
225 #define IF_BUG_ONCE__(cond,var) \
226 static int var = 0; \
227 if ((cond) ? \
228 (var ? 1 : \
229 (var=1, \
230 tor_bug_occurred_(SHORT_FILE__, __LINE__, __func__, \
231 ("!("#cond")"), 1, NULL), \
232 1)) \
233 : 0)
234 #endif /* defined(__GNUC__) */
235 #endif /* !defined(COCCI) */
237 #define IF_BUG_ONCE_VARNAME_(a) \
238 warning_logged_on_ ## a ## __
239 #define IF_BUG_ONCE_VARNAME__(a) \
240 IF_BUG_ONCE_VARNAME_(a)
242 /** This macro behaves as 'if (BUG(x))', except that it only logs its
243 * warning once, no matter how many times it triggers.
246 #define IF_BUG_ONCE(cond) \
247 IF_BUG_ONCE__(ASSERT_PREDICT_UNLIKELY_(cond), \
248 IF_BUG_ONCE_VARNAME__(__LINE__))
250 #endif /* defined(ALL_BUGS_ARE_FATAL) || ... */
253 * Use this macro after a nonfatal assertion, and before a case statement
254 * where you would want to fall through.
256 #ifdef ALL_BUGS_ARE_FATAL
257 #define FALLTHROUGH_UNLESS_ALL_BUGS_ARE_FATAL \
258 abort()
259 #else
260 #define FALLTHROUGH_UNLESS_ALL_BUGS_ARE_FATAL FALLTHROUGH
261 #endif /* defined(ALL_BUGS_ARE_FATAL) */
263 /** In older code, we used tor_fragile_assert() to mark optional failure
264 * points. At these points, we could make some debug builds fail.
265 * (But release builds would continue.)
267 * To get the same behaviour in recent tor versions, define
268 * ALL_BUGS_ARE_FATAL, and use any non-fatal assertion or *BUG() macro.
270 #define tor_fragile_assert() tor_assert_nonfatal_unreached_once()
272 void tor_assertion_failed_(const char *fname, unsigned int line,
273 const char *func, const char *expr,
274 const char *fmt, ...)
275 CHECK_PRINTF(5,6);
276 void tor_bug_occurred_(const char *fname, unsigned int line,
277 const char *func, const char *expr,
278 int once, const char *fmt, ...)
279 CHECK_PRINTF(6,7);
281 void tor_abort_(void) ATTR_NORETURN;
283 #ifdef _WIN32
284 #define SHORT_FILE__ (tor_fix_source_file(__FILE__))
285 const char *tor_fix_source_file(const char *fname);
286 #else
287 #define SHORT_FILE__ (__FILE__)
288 #define tor_fix_source_file(s) (s)
289 #endif /* defined(_WIN32) */
291 #ifdef TOR_UNIT_TESTS
292 void tor_capture_bugs_(int n);
293 void tor_end_capture_bugs_(void);
294 const struct smartlist_t *tor_get_captured_bug_log_(void);
295 void tor_set_failed_assertion_callback(void (*fn)(void));
296 #endif /* defined(TOR_UNIT_TESTS) */
298 #endif /* !defined(TOR_UTIL_BUG_H) */