tor  0.4.1.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-2019, The Tor Project, Inc. */
4 /* See LICENSE for licensing information */
5 
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
84 #define ASSERT_PREDICT_UNLIKELY_(e) PREDICT_UNLIKELY(e)
85 #define ASSERT_PREDICT_LIKELY_(e) PREDICT_LIKELY(e)
86 #endif
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
100 
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  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  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 #nodef BUG(x) (x)
135 #endif /* defined(__COVERITY__) */
136 
137 #if defined(__COVERITY__) || defined(__clang_analyzer__)
138 // We're running with a static analysis tool: let's treat even nonfatal
139 // assertion failures as something that we need to avoid.
140 #define ALL_BUGS_ARE_FATAL
141 #endif
142 
143 #ifdef ALL_BUGS_ARE_FATAL
144 #define tor_assert_nonfatal_unreached() tor_assert(0)
145 #define tor_assert_nonfatal(cond) tor_assert((cond))
146 #define tor_assertf_nonfatal(cond, fmt, ...) tor_assertf(cond, fmt, ...)
147 #define tor_assert_nonfatal_unreached_once() tor_assert(0)
148 #define tor_assert_nonfatal_once(cond) tor_assert((cond))
149 #define BUG(cond) \
150  (ASSERT_PREDICT_UNLIKELY_(cond) ? \
151  (tor_assertion_failed_(SHORT_FILE__,__LINE__,__func__,"!("#cond")"), \
152  abort(), 1) \
153  : 0)
154 #elif defined(TOR_UNIT_TESTS) && defined(DISABLE_ASSERTS_IN_UNIT_TESTS)
155 #define tor_assert_nonfatal_unreached() STMT_NIL
156 #define tor_assert_nonfatal(cond) ((void)(cond))
157 #define tor_assertf_nonfatal(cond, fmt, ...) STMT_BEGIN \
158  (void)cond; \
159  (void)fmt; \
160  STMT_END
161 #define tor_assert_nonfatal_unreached_once() STMT_NIL
162 #define tor_assert_nonfatal_once(cond) ((void)(cond))
163 #define BUG(cond) (ASSERT_PREDICT_UNLIKELY_(cond) ? 1 : 0)
164 #else /* Normal case, !ALL_BUGS_ARE_FATAL, !DISABLE_ASSERTS_IN_UNIT_TESTS */
165 #define tor_assert_nonfatal_unreached() STMT_BEGIN \
166  tor_bug_occurred_(SHORT_FILE__, __LINE__, __func__, NULL, 0, NULL); \
167  STMT_END
168 #define tor_assert_nonfatal(cond) STMT_BEGIN \
169  if (ASSERT_PREDICT_LIKELY_(cond)) { \
170  } else { \
171  tor_bug_occurred_(SHORT_FILE__, __LINE__, __func__, #cond, 0, NULL);\
172  } \
173  STMT_END
174 #define tor_assertf_nonfatal(cond, fmt, ...) STMT_BEGIN \
175  if (ASSERT_PREDICT_UNLIKELY_(cond)) { \
176  } else { \
177  tor_bug_occurred_(SHORT_FILE__, __LINE__, __func__, #cond, 0, \
178  fmt, ##__VA_ARGS__); \
179  } \
180  STMT_END
181 #define tor_assert_nonfatal_unreached_once() STMT_BEGIN \
182  static int warning_logged__ = 0; \
183  if (!warning_logged__) { \
184  warning_logged__ = 1; \
185  tor_bug_occurred_(SHORT_FILE__, __LINE__, __func__, NULL, 1, NULL); \
186  } \
187  STMT_END
188 #define tor_assert_nonfatal_once(cond) STMT_BEGIN \
189  static int warning_logged__ = 0; \
190  if (ASSERT_PREDICT_LIKELY_(cond)) { \
191  } else if (!warning_logged__) { \
192  warning_logged__ = 1; \
193  tor_bug_occurred_(SHORT_FILE__, __LINE__, __func__, #cond, 1, NULL);\
194  } \
195  STMT_END
196 #define BUG(cond) \
197  (ASSERT_PREDICT_UNLIKELY_(cond) ? \
198  (tor_bug_occurred_(SHORT_FILE__,__LINE__,__func__,"!("#cond")",1,NULL),1) \
199  : 0)
200 #endif /* defined(ALL_BUGS_ARE_FATAL) || ... */
201 
202 #ifdef __GNUC__
203 #define IF_BUG_ONCE__(cond,var) \
204  if (( { \
205  static int var = 0; \
206  int bool_result = !!(cond); \
207  if (bool_result && !var) { \
208  var = 1; \
209  tor_bug_occurred_(SHORT_FILE__, __LINE__, __func__, \
210  "!("#cond")", 1, NULL); \
211  } \
212  bool_result; } ))
213 #else /* !(defined(__GNUC__)) */
214 #define IF_BUG_ONCE__(cond,var) \
215  static int var = 0; \
216  if ((cond) ? \
217  (var ? 1 : \
218  (var=1, \
219  tor_bug_occurred_(SHORT_FILE__, __LINE__, __func__, \
220  "!("#cond")", 1, NULL), \
221  1)) \
222  : 0)
223 #endif /* defined(__GNUC__) */
224 #define IF_BUG_ONCE_VARNAME_(a) \
225  warning_logged_on_ ## a ## __
226 #define IF_BUG_ONCE_VARNAME__(a) \
227  IF_BUG_ONCE_VARNAME_(a)
228 
233 #define IF_BUG_ONCE(cond) \
234  IF_BUG_ONCE__(ASSERT_PREDICT_UNLIKELY_(cond), \
235  IF_BUG_ONCE_VARNAME__(__LINE__))
236 
239 // #define tor_fragile_assert() tor_assert_unreached(0)
240 #define tor_fragile_assert() tor_assert_nonfatal_unreached_once()
241 
242 void tor_assertion_failed_(const char *fname, unsigned int line,
243  const char *func, const char *expr,
244  const char *fmt, ...);
245 void tor_bug_occurred_(const char *fname, unsigned int line,
246  const char *func, const char *expr,
247  int once, const char *fmt, ...);
248 
249 #ifdef _WIN32
250 #define SHORT_FILE__ (tor_fix_source_file(__FILE__))
251 const char *tor_fix_source_file(const char *fname);
252 #else
253 #define SHORT_FILE__ (__FILE__)
254 #define tor_fix_source_file(s) (s)
255 #endif /* defined(_WIN32) */
256 
257 #ifdef TOR_UNIT_TESTS
258 void tor_capture_bugs_(int n);
259 void tor_end_capture_bugs_(void);
260 const struct smartlist_t *tor_get_captured_bug_log_(void);
261 void tor_set_failed_assertion_callback(void (*fn)(void));
262 #endif /* defined(TOR_UNIT_TESTS) */
263 
264 #endif /* !defined(TOR_UTIL_BUG_H) */
Utility macros to handle different features and behavior in different compilers.
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
Macros to implement mocking and selective exposure for the test code.
Headers for log.c.
void tor_assertion_failed_(const char *fname, unsigned int line, const char *func, const char *expr, const char *fmt,...)
Definition: util_bug.c:73