Wireshark 4.5.0
The Wireshark network protocol analyzer
Loading...
Searching...
No Matches
ws_assert.h
Go to the documentation of this file.
1
10#ifndef __WS_ASSERT_H__
11#define __WS_ASSERT_H__
12
13#include <ws_symbol_export.h>
14#include <ws_attributes.h>
15#include <stdbool.h>
16#include <string.h>
17#include <wsutil/wslog.h>
18#include <wsutil/wmem/wmem.h>
19
20#if defined(ENABLE_ASSERT)
21#define WS_ASSERT_ENABLED 1
22#elif defined(NDEBUG)
23#define WS_ASSERT_ENABLED 0
24#else
25#define WS_ASSERT_ENABLED 1
26#endif
27
28#ifdef __cplusplus
29extern "C" {
30#endif /* __cplusplus */
31
32/*
33 * We don't want to execute the expression without assertions because
34 * it might be time and space costly and the goal here is to optimize for
35 * that case. However removing it completely is not good enough
36 * because it might generate many unused variable warnings. So we use
37 * if (false) and let the compiler optimize away the dead execution branch.
38 */
39#define ws_assert_if_active(active, expr) \
40 do { \
41 if ((active) && !(expr)) \
42 ws_error("assertion failed: %s", #expr); \
43 } while (0)
44
45/*
46 * ws_abort_if_fail() is not conditional on having assertions enabled.
47 * Usually used to appease a static analyzer.
48 */
49#define ws_abort_if_fail(expr) \
50 ws_assert_if_active(true, expr)
51
52/*
53 * ws_assert() cannot produce side effects, otherwise code will
54 * behave differently because of having assertions enabled/disabled, and
55 * probably introduce some difficult to track bugs.
56 */
57#define ws_assert(expr) \
58 ws_assert_if_active(WS_ASSERT_ENABLED, expr)
59
60
61#define ws_assert_streq(s1, s2) \
62 ws_assert((s1) && (s2) && strcmp((s1), (s2)) == 0)
63
64#define ws_assert_utf8(str, len) \
65 do { \
66 const char *__assert_endptr; \
67 if (WS_ASSERT_ENABLED && \
68 !g_utf8_validate(str, len, &__assert_endptr)) { \
69 ws_log_utf8_full(LOG_DOMAIN_UTF_8, LOG_LEVEL_ERROR, \
70 __FILE__, __LINE__, __func__, \
71 str, len, __assert_endptr); \
72 } \
73 } while (0)
74
75/*
76 * We don't want to disable ws_assert_not_reached() with (optional) assertions
77 * disabled.
78 * That would blast compiler warnings everywhere for no benefit, not
79 * even a miniscule performance gain. Reaching this function is always
80 * a programming error and will unconditionally abort execution.
81 *
82 * Note: With g_assert_not_reached() if the compiler supports unreachable
83 * built-ins (which recent versions of GCC and MSVC do) there is no warning
84 * blast with g_assert_not_reached() and G_DISABLE_ASSERT. However if that
85 * is not the case then g_assert_not_reached() is simply (void)0 and that
86 * causes the spurious warnings, because the compiler can't tell anymore
87 * that a certain code path is not used. We avoid that with
88 * ws_assert_not_reached(). There is no reason to ever use a no-op here.
89 */
90#define ws_assert_not_reached() \
91 ws_error("assertion \"not reached\" failed")
92
93/*
94 * These macros can be used as an alternative to ws_assert() to
95 * assert some condition on function arguments. This must only be used
96 * to catch programming errors, in situations where an assertion is
97 * appropriate. And it should only be used if failing the condition
98 * doesn't necessarily lead to an inconsistent state for the program.
99 *
100 * It is possible to set the fatal log domain to "InvalidArg" to abort
101 * execution for debugging purposes, if one of these checks fail.
102 */
103
104#define ws_warn_badarg(str) \
105 ws_log_full(LOG_DOMAIN_EINVAL, LOG_LEVEL_WARNING, \
106 __FILE__, __LINE__, __func__, \
107 "invalid argument: %s", str)
108
109#define ws_return_str_if(expr, scope) \
110 do { \
111 if (WS_ASSERT_ENABLED && (expr)) { \
112 ws_warn_badarg(#expr); \
113 return wmem_strdup_printf(scope, "(invalid argument: %s)", #expr); \
114 } \
115 } while (0)
116
117#define ws_return_val_if(expr, val) \
118 do { \
119 if (WS_ASSERT_ENABLED && (expr)) { \
120 ws_warn_badarg(#expr); \
121 return (val); \
122 } \
123 } while (0)
124
125#ifdef __cplusplus
126}
127#endif /* __cplusplus */
128
129#endif /* __WS_ASSERT_H__ */