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