Tor  0.4.7.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"
40 #include "lib/cc/compat_compiler.h"
41 #include "lib/log/log.h"
43 
44 /* Replace assert() with a variant that sends failures to the log before
45  * calling assert() normally.
46  */
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.
52  *
53  * And I'm not just saying that because some of our asserts check
54  * security-critical properties.
55  */
56 #error "Sorry; we don't support building with NDEBUG."
57 #endif /* defined(NDEBUG) */
58 
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).
63  *
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.
68  *
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.
72  */
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__) */
87 
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)
103 
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) */
112 
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
119 
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".
123  *
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;
128  */
129 
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__) */
138 
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
144 
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);\
183  } \
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__); \
190  } \
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); \
197  } \
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);\
205  } \
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)
211 
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); \
222  } \
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) */
236 
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)
241 
242 /** This macro behaves as 'if (BUG(x))', except that it only logs its
243  * warning once, no matter how many times it triggers.
244  */
245 
246 #define IF_BUG_ONCE(cond) \
247  IF_BUG_ONCE__(ASSERT_PREDICT_UNLIKELY_(cond), \
248  IF_BUG_ONCE_VARNAME__(__LINE__))
249 
250 #endif /* defined(ALL_BUGS_ARE_FATAL) || ... */
251 
252 /**
253  * Use this macro after a nonfatal assertion, and before a case statement
254  * where you would want to fall through.
255  */
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) */
262 
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.)
266  *
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.
269  */
270 #define tor_fragile_assert() tor_assert_nonfatal_unreached_once()
271 
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);
280 
281 void tor_abort_(void) ATTR_NORETURN;
282 
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) */
290 
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) */
297 
298 #endif /* !defined(TOR_UTIL_BUG_H) */
Utility macros to handle different features and behavior in different compilers.
Headers for log.c.
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:106
void tor_abort_(void) ATTR_NORETURN
Definition: util_bug.c:171
void tor_assertion_failed_(const char *fname, unsigned int line, const char *func, const char *expr, const char *fmt,...)
Definition: util_bug.c:74