Wireshark  4.3.0
The Wireshark network protocol analyzer
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
29 extern "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__ */