f867599440e60de6e15ed83f5a7f95815b7b6a9d
[WebKit-https.git] / Source / WTF / wtf / Assertions.h
1 /*
2  * Copyright (C) 2003, 2006, 2007, 2013 Apple Inc.  All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
24  */
25
26 #ifndef WTF_Assertions_h
27 #define WTF_Assertions_h
28
29 #include <wtf/Platform.h>
30
31 /*
32    no namespaces because this file has to be includable from C and Objective-C
33
34    Note, this file uses many GCC extensions, but it should be compatible with
35    C, Objective C, C++, and Objective C++.
36
37    For non-debug builds, everything is disabled by default except for "always
38    on" logging. Defining any of the symbols explicitly prevents this from
39    having any effect.
40 */
41
42 #include <inttypes.h>
43 #include <stdarg.h>
44 #include <stdbool.h>
45 #include <stddef.h>
46 #include <wtf/ExportMacros.h>
47
48 #if USE(OS_LOG)
49 #include <os/log.h>
50 #endif
51
52 #ifdef NDEBUG
53 /* Disable ASSERT* macros in release mode. */
54 #define ASSERTIONS_DISABLED_DEFAULT 1
55 #else
56 #define ASSERTIONS_DISABLED_DEFAULT 0
57 #endif
58
59 #ifndef BACKTRACE_DISABLED
60 #define BACKTRACE_DISABLED ASSERTIONS_DISABLED_DEFAULT
61 #endif
62
63 #ifndef ASSERT_DISABLED
64 #define ASSERT_DISABLED ASSERTIONS_DISABLED_DEFAULT
65 #endif
66
67 #ifndef ASSERT_MSG_DISABLED
68 #define ASSERT_MSG_DISABLED ASSERTIONS_DISABLED_DEFAULT
69 #endif
70
71 #ifndef ASSERT_ARG_DISABLED
72 #define ASSERT_ARG_DISABLED ASSERTIONS_DISABLED_DEFAULT
73 #endif
74
75 #ifndef FATAL_DISABLED
76 #define FATAL_DISABLED ASSERTIONS_DISABLED_DEFAULT
77 #endif
78
79 #ifndef ERROR_DISABLED
80 #define ERROR_DISABLED ASSERTIONS_DISABLED_DEFAULT
81 #endif
82
83 #ifndef LOG_DISABLED
84 #define LOG_DISABLED ASSERTIONS_DISABLED_DEFAULT
85 #endif
86
87 #ifndef RELEASE_LOG_DISABLED
88 #define RELEASE_LOG_DISABLED !(USE(OS_LOG))
89 #endif
90
91 #if COMPILER(GCC_OR_CLANG)
92 #define WTF_PRETTY_FUNCTION __PRETTY_FUNCTION__
93 #else
94 #define WTF_PRETTY_FUNCTION __FUNCTION__
95 #endif
96
97 /* WTF logging functions can process %@ in the format string to log a NSObject* but the printf format attribute
98    emits a warning when %@ is used in the format string.  Until <rdar://problem/5195437> is resolved we can't include
99    the attribute when being used from Objective-C code in case it decides to use %@. */
100 #if COMPILER(GCC_OR_CLANG) && !defined(__OBJC__)
101 #define WTF_ATTRIBUTE_PRINTF(formatStringArgument, extraArguments) __attribute__((__format__(printf, formatStringArgument, extraArguments)))
102 #else
103 #define WTF_ATTRIBUTE_PRINTF(formatStringArgument, extraArguments)
104 #endif
105
106 #if PLATFORM(IOS)
107 /* For a project that uses WTF but has no config.h, we need to explicitly set the export defines here. */
108 #ifndef WTF_EXPORT_PRIVATE
109 #define WTF_EXPORT_PRIVATE
110 #endif
111 #endif // PLATFORM(IOS)
112
113 /* These helper functions are always declared, but not necessarily always defined if the corresponding function is disabled. */
114
115 #ifdef __cplusplus
116 extern "C" {
117 #endif
118
119 /* CRASH() - Raises a fatal error resulting in program termination and triggering either the debugger or the crash reporter.
120
121    Use CRASH() in response to known, unrecoverable errors like out-of-memory.
122    Macro is enabled in both debug and release mode.
123    To test for unknown errors and verify assumptions, use ASSERT instead, to avoid impacting performance in release builds.
124
125    Signals are ignored by the crash reporter on OS X so we must do better.
126 */
127 #if COMPILER(GCC_OR_CLANG) || COMPILER(MSVC)
128 #define NO_RETURN_DUE_TO_CRASH NO_RETURN
129 #else
130 #define NO_RETURN_DUE_TO_CRASH
131 #endif
132
133 typedef enum { WTFLogChannelOff, WTFLogChannelOn, WTFLogChannelOnWithAccumulation } WTFLogChannelState;
134
135 typedef struct {
136     WTFLogChannelState state;
137     const char* name;
138 #if !RELEASE_LOG_DISABLED
139     const char* subsystem;
140     __unsafe_unretained os_log_t osLogChannel;
141 #endif
142 } WTFLogChannel;
143
144 #define LOG_CHANNEL(name) JOIN_LOG_CHANNEL_WITH_PREFIX(LOG_CHANNEL_PREFIX, name)
145 #define LOG_CHANNEL_ADDRESS(name) &LOG_CHANNEL(name),
146 #define JOIN_LOG_CHANNEL_WITH_PREFIX(prefix, channel) JOIN_LOG_CHANNEL_WITH_PREFIX_LEVEL_2(prefix, channel)
147 #define JOIN_LOG_CHANNEL_WITH_PREFIX_LEVEL_2(prefix, channel) prefix ## channel
148
149 #define LOG_CHANNEL_WEBKIT_SUBSYSTEM "com.apple.WebKit"
150
151 #define DECLARE_LOG_CHANNEL(name) \
152     extern WTFLogChannel LOG_CHANNEL(name);
153
154 #if !defined(DEFINE_LOG_CHANNEL)
155 #if RELEASE_LOG_DISABLED
156 #define DEFINE_LOG_CHANNEL(name, subsystem) \
157     WTFLogChannel LOG_CHANNEL(name) = { WTFLogChannelOff, #name };
158 #else
159 #define DEFINE_LOG_CHANNEL(name, subsystem) \
160     WTFLogChannel LOG_CHANNEL(name) = { WTFLogChannelOff, #name, subsystem, OS_LOG_DEFAULT };
161 #endif
162 #endif
163
164 WTF_EXPORT_PRIVATE void WTFReportAssertionFailure(const char* file, int line, const char* function, const char* assertion);
165 WTF_EXPORT_PRIVATE void WTFReportAssertionFailureWithMessage(const char* file, int line, const char* function, const char* assertion, const char* format, ...) WTF_ATTRIBUTE_PRINTF(5, 6);
166 WTF_EXPORT_PRIVATE void WTFReportArgumentAssertionFailure(const char* file, int line, const char* function, const char* argName, const char* assertion);
167 WTF_EXPORT_PRIVATE void WTFReportFatalError(const char* file, int line, const char* function, const char* format, ...) WTF_ATTRIBUTE_PRINTF(4, 5);
168 WTF_EXPORT_PRIVATE void WTFReportError(const char* file, int line, const char* function, const char* format, ...) WTF_ATTRIBUTE_PRINTF(4, 5);
169 WTF_EXPORT_PRIVATE void WTFLog(WTFLogChannel*, const char* format, ...) WTF_ATTRIBUTE_PRINTF(2, 3);
170 WTF_EXPORT_PRIVATE void WTFLogVerbose(const char* file, int line, const char* function, WTFLogChannel*, const char* format, ...) WTF_ATTRIBUTE_PRINTF(5, 6);
171 WTF_EXPORT_PRIVATE void WTFLogAlwaysV(const char* format, va_list);
172 WTF_EXPORT_PRIVATE void WTFLogAlways(const char* format, ...) WTF_ATTRIBUTE_PRINTF(1, 2);
173 WTF_EXPORT_PRIVATE NO_RETURN_DUE_TO_CRASH void WTFLogAlwaysAndCrash(const char* format, ...) WTF_ATTRIBUTE_PRINTF(1, 2);
174 WTF_EXPORT_PRIVATE WTFLogChannel* WTFLogChannelByName(WTFLogChannel*[], size_t count, const char*);
175 WTF_EXPORT_PRIVATE void WTFInitializeLogChannelStatesFromString(WTFLogChannel*[], size_t count, const char*);
176
177 WTF_EXPORT_PRIVATE void WTFGetBacktrace(void** stack, int* size);
178 WTF_EXPORT_PRIVATE void WTFReportBacktrace();
179 WTF_EXPORT_PRIVATE void WTFPrintBacktrace(void** stack, int size);
180
181 typedef void (*WTFCrashHookFunction)();
182 WTF_EXPORT_PRIVATE void WTFSetCrashHook(WTFCrashHookFunction);
183 WTF_EXPORT_PRIVATE void WTFInstallReportBacktraceOnCrashHook();
184
185 WTF_EXPORT_PRIVATE bool WTFIsDebuggerAttached();
186
187 #ifndef CRASH
188
189 #if defined(NDEBUG) && OS(DARWIN)
190 #if CPU(X86_64) || CPU(X86)
191 #define WTFBreakpointTrap()  __asm__ volatile ("int3")
192 #elif CPU(ARM_THUMB2)
193 #define WTFBreakpointTrap()  __asm__ volatile ("bkpt #0")
194 #elif CPU(ARM64)
195 #define WTFBreakpointTrap()  __asm__ volatile ("brk #0")
196 #else
197 #error "Unsupported CPU".
198 #endif
199
200 // Crash with a SIGTRAP i.e EXC_BREAKPOINT.
201 // We are not using __builtin_trap because it is only guaranteed to abort, but not necessarily
202 // trigger a SIGTRAP. Instead, we use inline asm to ensure that we trigger the SIGTRAP.
203 #define CRASH() do { \
204     WTFBreakpointTrap(); \
205     __builtin_unreachable(); \
206 } while (0)
207 #else
208 #define CRASH() WTFCrash()
209 #endif
210
211 #endif // CRASH
212
213 WTF_EXPORT_PRIVATE NO_RETURN_DUE_TO_CRASH void WTFCrash();
214
215 #ifndef CRASH_WITH_SECURITY_IMPLICATION
216 #define CRASH_WITH_SECURITY_IMPLICATION() WTFCrashWithSecurityImplication()
217 #endif
218
219 WTF_EXPORT_PRIVATE NO_RETURN_DUE_TO_CRASH void WTFCrashWithSecurityImplication();
220
221 #ifdef __cplusplus
222 }
223 #endif
224
225 /* BACKTRACE
226
227   Print a backtrace to the same location as ASSERT messages.
228 */
229
230 #if BACKTRACE_DISABLED
231
232 #define BACKTRACE() ((void)0)
233
234 #else
235
236 #define BACKTRACE() do { \
237     WTFReportBacktrace(); \
238 } while(false)
239
240 #endif
241
242 /* ASSERT, ASSERT_NOT_REACHED, ASSERT_UNUSED
243
244   These macros are compiled out of release builds.
245   Expressions inside them are evaluated in debug builds only.
246 */
247
248 #if OS(WINDOWS)
249 /* FIXME: Change to use something other than ASSERT to avoid this conflict with the underlying platform */
250 #undef ASSERT
251 #endif
252
253 #if ASSERT_DISABLED
254
255 #define ASSERT(assertion) ((void)0)
256 #define ASSERT_AT(assertion, file, line, function) ((void)0)
257 #define ASSERT_NOT_REACHED() ((void)0)
258 #define NO_RETURN_DUE_TO_ASSERT
259
260 #define ASSERT_UNUSED(variable, assertion) ((void)variable)
261
262 #if ENABLE(SECURITY_ASSERTIONS)
263 #define ASSERT_WITH_SECURITY_IMPLICATION(assertion) \
264     (!(assertion) ? \
265         (WTFReportAssertionFailure(__FILE__, __LINE__, WTF_PRETTY_FUNCTION, #assertion), \
266          CRASH_WITH_SECURITY_IMPLICATION()) : \
267         (void)0)
268
269 #define ASSERT_WITH_SECURITY_IMPLICATION_DISABLED 0
270 #else
271 #define ASSERT_WITH_SECURITY_IMPLICATION(assertion) ((void)0)
272 #define ASSERT_WITH_SECURITY_IMPLICATION_DISABLED 1
273 #endif
274
275 #else
276
277 #define ASSERT(assertion) do { \
278     if (!(assertion)) { \
279         WTFReportAssertionFailure(__FILE__, __LINE__, WTF_PRETTY_FUNCTION, #assertion); \
280         CRASH(); \
281     } \
282 } while (0)
283
284 #define ASSERT_AT(assertion, file, line, function) do { \
285     if (!(assertion)) { \
286         WTFReportAssertionFailure(file, line, function, #assertion); \
287         CRASH(); \
288     } \
289 } while (0)
290
291 #define ASSERT_NOT_REACHED() do { \
292     WTFReportAssertionFailure(__FILE__, __LINE__, WTF_PRETTY_FUNCTION, 0); \
293     CRASH(); \
294 } while (0)
295
296 #define ASSERT_UNUSED(variable, assertion) ASSERT(assertion)
297
298 #define NO_RETURN_DUE_TO_ASSERT NO_RETURN_DUE_TO_CRASH
299
300 /* ASSERT_WITH_SECURITY_IMPLICATION
301  
302    Failure of this assertion indicates a possible security vulnerability.
303    Class of vulnerabilities that it tests include bad casts, out of bounds
304    accesses, use-after-frees, etc. Please file a bug using the security
305    template - https://bugs.webkit.org/enter_bug.cgi?product=Security.
306  
307 */
308 #define ASSERT_WITH_SECURITY_IMPLICATION(assertion) \
309     (!(assertion) ? \
310         (WTFReportAssertionFailure(__FILE__, __LINE__, WTF_PRETTY_FUNCTION, #assertion), \
311          CRASH_WITH_SECURITY_IMPLICATION()) : \
312         (void)0)
313 #define ASSERT_WITH_SECURITY_IMPLICATION_DISABLED 0
314 #endif
315
316 /* ASSERT_WITH_MESSAGE */
317
318 #if ASSERT_MSG_DISABLED
319 #define ASSERT_WITH_MESSAGE(assertion, ...) ((void)0)
320 #else
321 #define ASSERT_WITH_MESSAGE(assertion, ...) do { \
322     if (!(assertion)) { \
323         WTFReportAssertionFailureWithMessage(__FILE__, __LINE__, WTF_PRETTY_FUNCTION, #assertion, __VA_ARGS__); \
324         CRASH(); \
325     } \
326 } while (0)
327 #endif
328
329 /* ASSERT_WITH_MESSAGE_UNUSED */
330
331 #if ASSERT_MSG_DISABLED
332 #define ASSERT_WITH_MESSAGE_UNUSED(variable, assertion, ...) ((void)variable)
333 #else
334 #define ASSERT_WITH_MESSAGE_UNUSED(variable, assertion, ...) do { \
335     if (!(assertion)) { \
336         WTFReportAssertionFailureWithMessage(__FILE__, __LINE__, WTF_PRETTY_FUNCTION, #assertion, __VA_ARGS__); \
337         CRASH(); \
338     } \
339 } while (0)
340 #endif
341                         
342                         
343 /* ASSERT_ARG */
344
345 #if ASSERT_ARG_DISABLED
346
347 #define ASSERT_ARG(argName, assertion) ((void)0)
348
349 #else
350
351 #define ASSERT_ARG(argName, assertion) do { \
352     if (!(assertion)) { \
353         WTFReportArgumentAssertionFailure(__FILE__, __LINE__, WTF_PRETTY_FUNCTION, #argName, #assertion); \
354         CRASH(); \
355     } \
356 } while (0)
357
358 #endif
359
360 /* COMPILE_ASSERT */
361 #ifndef COMPILE_ASSERT
362 #if COMPILER_SUPPORTS(C_STATIC_ASSERT)
363 /* Unlike static_assert below, this also works in plain C code. */
364 #define COMPILE_ASSERT(exp, name) _Static_assert((exp), #name)
365 #else
366 #define COMPILE_ASSERT(exp, name) static_assert((exp), #name)
367 #endif
368 #endif
369
370 /* FATAL */
371
372 #if FATAL_DISABLED
373 #define FATAL(...) ((void)0)
374 #else
375 #define FATAL(...) do { \
376     WTFReportFatalError(__FILE__, __LINE__, WTF_PRETTY_FUNCTION, __VA_ARGS__); \
377     CRASH(); \
378 } while (0)
379 #endif
380
381 /* LOG_ERROR */
382
383 #if ERROR_DISABLED
384 #define LOG_ERROR(...) ((void)0)
385 #else
386 #define LOG_ERROR(...) WTFReportError(__FILE__, __LINE__, WTF_PRETTY_FUNCTION, __VA_ARGS__)
387 #endif
388
389 /* LOG */
390
391 #if LOG_DISABLED
392 #define LOG(channel, ...) ((void)0)
393 #else
394 #define LOG(channel, ...) WTFLog(&LOG_CHANNEL(channel), __VA_ARGS__)
395 #endif
396
397 /* LOG_VERBOSE */
398
399 #if LOG_DISABLED
400 #define LOG_VERBOSE(channel, ...) ((void)0)
401 #else
402 #define LOG_VERBOSE(channel, ...) WTFLogVerbose(__FILE__, __LINE__, WTF_PRETTY_FUNCTION, &LOG_CHANNEL(channel), __VA_ARGS__)
403 #endif
404
405 /* RELEASE_LOG */
406
407 #if RELEASE_LOG_DISABLED
408 #define RELEASE_LOG(      channel, format, ...) ((void)0)
409 #define RELEASE_LOG_ERROR(channel, format, ...) LOG_ERROR(format, ##__VA_ARGS__)
410
411 #define RELEASE_LOG_IF(      isAllowed, channel, format, ...) ((void)0)
412 #define RELEASE_LOG_ERROR_IF(isAllowed, channel, format, ...) do { if (isAllowed) RELEASE_LOG_ERROR(channel, format, ##__VA_ARGS__); } while (0)
413 #else
414 #define RELEASE_LOG(      channel, format, ...) os_log(      LOG_CHANNEL(channel).osLogChannel, format, ##__VA_ARGS__)
415 #define RELEASE_LOG_ERROR(channel, format, ...) os_log_error(LOG_CHANNEL(channel).osLogChannel, format, ##__VA_ARGS__)
416
417 #define RELEASE_LOG_IF(      isAllowed, channel, format, ...) do { if (isAllowed) RELEASE_LOG(      channel, format, ##__VA_ARGS__); } while (0)
418 #define RELEASE_LOG_ERROR_IF(isAllowed, channel, format, ...) do { if (isAllowed) RELEASE_LOG_ERROR(channel, format, ##__VA_ARGS__); } while (0)
419 #endif
420
421
422 /* RELEASE_ASSERT */
423
424 #if ASSERT_DISABLED
425 #define RELEASE_ASSERT(assertion) do { \
426     if (UNLIKELY(!(assertion))) \
427         CRASH(); \
428 } while (0)
429 #define RELEASE_ASSERT_WITH_MESSAGE(assertion, ...) RELEASE_ASSERT(assertion)
430 #define RELEASE_ASSERT_NOT_REACHED() CRASH()
431 #else
432 #define RELEASE_ASSERT(assertion) ASSERT(assertion)
433 #define RELEASE_ASSERT_WITH_MESSAGE(assertion, ...) ASSERT_WITH_MESSAGE(assertion, __VA_ARGS__)
434 #define RELEASE_ASSERT_NOT_REACHED() ASSERT_NOT_REACHED()
435 #endif
436
437 /* UNREACHABLE_FOR_PLATFORM */
438
439 #if COMPILER(CLANG)
440 // This would be a macro except that its use of #pragma works best around
441 // a function. Hence it uses macro naming convention.
442 #pragma clang diagnostic push
443 #pragma clang diagnostic ignored "-Wmissing-noreturn"
444 static inline void UNREACHABLE_FOR_PLATFORM()
445 {
446     RELEASE_ASSERT_NOT_REACHED();
447 }
448 #pragma clang diagnostic pop
449 #else
450 #define UNREACHABLE_FOR_PLATFORM() RELEASE_ASSERT_NOT_REACHED()
451 #endif
452
453
454 #endif /* WTF_Assertions_h */