/src/systemd/src/basic/macro.h
Line | Count | Source (jump to first uncovered line) |
1 | | /* SPDX-License-Identifier: LGPL-2.1-or-later */ |
2 | | #pragma once |
3 | | |
4 | | #include <assert.h> |
5 | | #include <errno.h> |
6 | | #include <inttypes.h> |
7 | | #include <stdbool.h> |
8 | | #include <sys/param.h> |
9 | | #include <sys/sysmacros.h> |
10 | | #include <sys/types.h> |
11 | | |
12 | | #include "macro-fundamental.h" |
13 | | |
14 | | #if !defined(HAS_FEATURE_MEMORY_SANITIZER) |
15 | | # if defined(__has_feature) |
16 | | # if __has_feature(memory_sanitizer) |
17 | | # define HAS_FEATURE_MEMORY_SANITIZER 1 |
18 | | # endif |
19 | | # endif |
20 | | # if !defined(HAS_FEATURE_MEMORY_SANITIZER) |
21 | | # define HAS_FEATURE_MEMORY_SANITIZER 0 |
22 | | # endif |
23 | | #endif |
24 | | |
25 | | #if !defined(HAS_FEATURE_ADDRESS_SANITIZER) |
26 | | # ifdef __SANITIZE_ADDRESS__ |
27 | | # define HAS_FEATURE_ADDRESS_SANITIZER 1 |
28 | | # elif defined(__has_feature) |
29 | | # if __has_feature(address_sanitizer) |
30 | | # define HAS_FEATURE_ADDRESS_SANITIZER 1 |
31 | | # endif |
32 | | # endif |
33 | | # if !defined(HAS_FEATURE_ADDRESS_SANITIZER) |
34 | | # define HAS_FEATURE_ADDRESS_SANITIZER 0 |
35 | | # endif |
36 | | #endif |
37 | | |
38 | | /* Note: on GCC "no_sanitize_address" is a function attribute only, on llvm it may also be applied to global |
39 | | * variables. We define a specific macro which knows this. Note that on GCC we don't need this decorator so much, since |
40 | | * our primary usecase for this attribute is registration structures placed in named ELF sections which shall not be |
41 | | * padded, but GCC doesn't pad those anyway if AddressSanitizer is enabled. */ |
42 | | #if HAS_FEATURE_ADDRESS_SANITIZER && defined(__clang__) |
43 | | #define _variable_no_sanitize_address_ __attribute__((__no_sanitize_address__)) |
44 | | #else |
45 | | #define _variable_no_sanitize_address_ |
46 | | #endif |
47 | | |
48 | | /* Apparently there's no has_feature() call defined to check for ubsan, hence let's define this |
49 | | * unconditionally on llvm */ |
50 | | #if defined(__clang__) |
51 | | #define _function_no_sanitize_float_cast_overflow_ __attribute__((no_sanitize("float-cast-overflow"))) |
52 | | #else |
53 | | #define _function_no_sanitize_float_cast_overflow_ |
54 | | #endif |
55 | | |
56 | | /* Temporarily disable some warnings */ |
57 | | #define DISABLE_WARNING_DEPRECATED_DECLARATIONS \ |
58 | | _Pragma("GCC diagnostic push"); \ |
59 | | _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"") |
60 | | |
61 | | #define DISABLE_WARNING_FORMAT_NONLITERAL \ |
62 | | _Pragma("GCC diagnostic push"); \ |
63 | | _Pragma("GCC diagnostic ignored \"-Wformat-nonliteral\"") |
64 | | |
65 | | #define DISABLE_WARNING_MISSING_PROTOTYPES \ |
66 | | _Pragma("GCC diagnostic push"); \ |
67 | | _Pragma("GCC diagnostic ignored \"-Wmissing-prototypes\"") |
68 | | |
69 | | #define DISABLE_WARNING_NONNULL \ |
70 | | _Pragma("GCC diagnostic push"); \ |
71 | | _Pragma("GCC diagnostic ignored \"-Wnonnull\"") |
72 | | |
73 | | #define DISABLE_WARNING_SHADOW \ |
74 | | _Pragma("GCC diagnostic push"); \ |
75 | | _Pragma("GCC diagnostic ignored \"-Wshadow\"") |
76 | | |
77 | | #define DISABLE_WARNING_INCOMPATIBLE_POINTER_TYPES \ |
78 | | _Pragma("GCC diagnostic push"); \ |
79 | | _Pragma("GCC diagnostic ignored \"-Wincompatible-pointer-types\"") |
80 | | |
81 | | #if HAVE_WSTRINGOP_TRUNCATION |
82 | | # define DISABLE_WARNING_STRINGOP_TRUNCATION \ |
83 | | _Pragma("GCC diagnostic push"); \ |
84 | | _Pragma("GCC diagnostic ignored \"-Wstringop-truncation\"") |
85 | | #else |
86 | | # define DISABLE_WARNING_STRINGOP_TRUNCATION \ |
87 | | _Pragma("GCC diagnostic push") |
88 | | #endif |
89 | | |
90 | | #define DISABLE_WARNING_TYPE_LIMITS \ |
91 | | _Pragma("GCC diagnostic push"); \ |
92 | | _Pragma("GCC diagnostic ignored \"-Wtype-limits\"") |
93 | | |
94 | | #define REENABLE_WARNING \ |
95 | | _Pragma("GCC diagnostic pop") |
96 | | |
97 | | /* automake test harness */ |
98 | | #define EXIT_TEST_SKIP 77 |
99 | | |
100 | | /* builtins */ |
101 | | #if __SIZEOF_INT__ == 4 |
102 | | #define BUILTIN_FFS_U32(x) __builtin_ffs(x); |
103 | | #elif __SIZEOF_LONG__ == 4 |
104 | | #define BUILTIN_FFS_U32(x) __builtin_ffsl(x); |
105 | | #else |
106 | | #error "neither int nor long are four bytes long?!?" |
107 | | #endif |
108 | | |
109 | | /* align to next higher power-of-2 (except for: 0 => 0, overflow => 0) */ |
110 | 0 | static inline unsigned long ALIGN_POWER2(unsigned long u) { |
111 | 0 |
|
112 | 0 | /* Avoid subtraction overflow */ |
113 | 0 | if (u == 0) |
114 | 0 | return 0; |
115 | 0 |
|
116 | 0 | /* clz(0) is undefined */ |
117 | 0 | if (u == 1) |
118 | 0 | return 1; |
119 | 0 |
|
120 | 0 | /* left-shift overflow is undefined */ |
121 | 0 | if (__builtin_clzl(u - 1UL) < 1) |
122 | 0 | return 0; |
123 | 0 |
|
124 | 0 | return 1UL << (sizeof(u) * 8 - __builtin_clzl(u - 1UL)); |
125 | 0 | } Unexecuted instantiation: fuzz-link-parser.c:ALIGN_POWER2 Unexecuted instantiation: link-config.c:ALIGN_POWER2 Unexecuted instantiation: link-config-gperf.c:ALIGN_POWER2 |
126 | | |
127 | 0 | static inline size_t GREEDY_ALLOC_ROUND_UP(size_t l) { |
128 | 0 | size_t m; |
129 | 0 |
|
130 | 0 | /* Round up allocation sizes a bit to some reasonable, likely larger value. This is supposed to be |
131 | 0 | * used for cases which are likely called in an allocation loop of some form, i.e. that repetitively |
132 | 0 | * grow stuff, for example strv_extend() and suchlike. |
133 | 0 | * |
134 | 0 | * Note the difference to GREEDY_REALLOC() here, as this helper operates on a single size value only, |
135 | 0 | * and rounds up to next multiple of 2, needing no further counter. |
136 | 0 | * |
137 | 0 | * Note the benefits of direct ALIGN_POWER2() usage: type-safety for size_t, sane handling for very |
138 | 0 | * small (i.e. <= 2) and safe handling for very large (i.e. > SSIZE_MAX) values. */ |
139 | 0 |
|
140 | 0 | if (l <= 2) |
141 | 0 | return 2; /* Never allocate less than 2 of something. */ |
142 | 0 |
|
143 | 0 | m = ALIGN_POWER2(l); |
144 | 0 | if (m == 0) /* overflow? */ |
145 | 0 | return l; |
146 | 0 |
|
147 | 0 | return m; |
148 | 0 | } Unexecuted instantiation: fuzz-link-parser.c:GREEDY_ALLOC_ROUND_UP Unexecuted instantiation: link-config.c:GREEDY_ALLOC_ROUND_UP Unexecuted instantiation: link-config-gperf.c:GREEDY_ALLOC_ROUND_UP |
149 | | |
150 | | /* |
151 | | * container_of - cast a member of a structure out to the containing structure |
152 | | * @ptr: the pointer to the member. |
153 | | * @type: the type of the container struct this is embedded in. |
154 | | * @member: the name of the member within the struct. |
155 | | */ |
156 | | #define container_of(ptr, type, member) __container_of(UNIQ, (ptr), type, member) |
157 | | #define __container_of(uniq, ptr, type, member) \ |
158 | | ({ \ |
159 | | const typeof( ((type*)0)->member ) *UNIQ_T(A, uniq) = (ptr); \ |
160 | | (type*)( (char *)UNIQ_T(A, uniq) - offsetof(type, member) ); \ |
161 | | }) |
162 | | |
163 | | #ifdef __COVERITY__ |
164 | | |
165 | | /* Use special definitions of assertion macros in order to prevent |
166 | | * false positives of ASSERT_SIDE_EFFECT on Coverity static analyzer |
167 | | * for uses of assert_se() and assert_return(). |
168 | | * |
169 | | * These definitions make expression go through a (trivial) function |
170 | | * call to ensure they are not discarded. Also use ! or !! to ensure |
171 | | * the boolean expressions are seen as such. |
172 | | * |
173 | | * This technique has been described and recommended in: |
174 | | * https://community.synopsys.com/s/question/0D534000046Yuzb/suppressing-assertsideeffect-for-functions-that-allow-for-sideeffects |
175 | | */ |
176 | | |
177 | | extern void __coverity_panic__(void); |
178 | | |
179 | | static inline void __coverity_check__(int condition) { |
180 | | if (!condition) |
181 | | __coverity_panic__(); |
182 | | } |
183 | | |
184 | | static inline int __coverity_check_and_return__(int condition) { |
185 | | return condition; |
186 | | } |
187 | | |
188 | | #define assert_message_se(expr, message) __coverity_check__(!!(expr)) |
189 | | |
190 | | #define assert_log(expr, message) __coverity_check_and_return__(!!(expr)) |
191 | | |
192 | | #else /* ! __COVERITY__ */ |
193 | | |
194 | | #define assert_message_se(expr, message) \ |
195 | 229k | do { \ |
196 | 229k | if (_unlikely_(!(expr))) \ |
197 | 229k | log_assert_failed(message, PROJECT_FILE, __LINE__, __PRETTY_FUNCTION__); \ |
198 | 229k | } while (false) |
199 | | |
200 | | #define assert_log(expr, message) ((_likely_(expr)) \ |
201 | | ? (true) \ |
202 | | : (log_assert_failed_return(message, PROJECT_FILE, __LINE__, __PRETTY_FUNCTION__), false)) |
203 | | |
204 | | #endif /* __COVERITY__ */ |
205 | | |
206 | 60.4k | #define assert_se(expr) assert_message_se(expr, #expr) |
207 | | |
208 | | /* We override the glibc assert() here. */ |
209 | | #undef assert |
210 | | #ifdef NDEBUG |
211 | | #define assert(expr) do {} while (false) |
212 | | #else |
213 | 169k | #define assert(expr) assert_message_se(expr, #expr) |
214 | | #endif |
215 | | |
216 | | #define assert_not_reached() \ |
217 | 0 | log_assert_failed_unreachable(PROJECT_FILE, __LINE__, __PRETTY_FUNCTION__) |
218 | | |
219 | | #define assert_return(expr, r) \ |
220 | | do { \ |
221 | | if (!assert_log(expr, #expr)) \ |
222 | | return (r); \ |
223 | | } while (false) |
224 | | |
225 | | #define assert_return_errno(expr, r, err) \ |
226 | | do { \ |
227 | | if (!assert_log(expr, #expr)) { \ |
228 | | errno = err; \ |
229 | | return (r); \ |
230 | | } \ |
231 | | } while (false) |
232 | | |
233 | | #define return_with_errno(r, err) \ |
234 | | do { \ |
235 | | errno = abs(err); \ |
236 | | return r; \ |
237 | | } while (false) |
238 | | |
239 | | #define PTR_TO_INT(p) ((int) ((intptr_t) (p))) |
240 | | #define INT_TO_PTR(u) ((void *) ((intptr_t) (u))) |
241 | | #define PTR_TO_UINT(p) ((unsigned) ((uintptr_t) (p))) |
242 | | #define UINT_TO_PTR(u) ((void *) ((uintptr_t) (u))) |
243 | | |
244 | | #define PTR_TO_LONG(p) ((long) ((intptr_t) (p))) |
245 | | #define LONG_TO_PTR(u) ((void *) ((intptr_t) (u))) |
246 | | #define PTR_TO_ULONG(p) ((unsigned long) ((uintptr_t) (p))) |
247 | | #define ULONG_TO_PTR(u) ((void *) ((uintptr_t) (u))) |
248 | | |
249 | | #define PTR_TO_UINT8(p) ((uint8_t) ((uintptr_t) (p))) |
250 | | #define UINT8_TO_PTR(u) ((void *) ((uintptr_t) (u))) |
251 | | |
252 | | #define PTR_TO_INT32(p) ((int32_t) ((intptr_t) (p))) |
253 | | #define INT32_TO_PTR(u) ((void *) ((intptr_t) (u))) |
254 | | #define PTR_TO_UINT32(p) ((uint32_t) ((uintptr_t) (p))) |
255 | | #define UINT32_TO_PTR(u) ((void *) ((uintptr_t) (u))) |
256 | | |
257 | | #define PTR_TO_INT64(p) ((int64_t) ((intptr_t) (p))) |
258 | | #define INT64_TO_PTR(u) ((void *) ((intptr_t) (u))) |
259 | | #define PTR_TO_UINT64(p) ((uint64_t) ((uintptr_t) (p))) |
260 | | #define UINT64_TO_PTR(u) ((void *) ((uintptr_t) (u))) |
261 | | |
262 | | #define PTR_TO_SIZE(p) ((size_t) ((uintptr_t) (p))) |
263 | | #define SIZE_TO_PTR(u) ((void *) ((uintptr_t) (u))) |
264 | | |
265 | | #define CHAR_TO_STR(x) ((char[2]) { x, 0 }) |
266 | | |
267 | | #define char_array_0(x) x[sizeof(x)-1] = 0; |
268 | | |
269 | | #define sizeof_field(struct_type, member) sizeof(((struct_type *) 0)->member) |
270 | | |
271 | | /* Returns the number of chars needed to format variables of the specified type as a decimal string. Adds in |
272 | | * extra space for a negative '-' prefix for signed types. Includes space for the trailing NUL. */ |
273 | | #define DECIMAL_STR_MAX(type) \ |
274 | | ((size_t) IS_SIGNED_INTEGER_TYPE(type) + 1U + \ |
275 | | (sizeof(type) <= 1 ? 3U : \ |
276 | | sizeof(type) <= 2 ? 5U : \ |
277 | | sizeof(type) <= 4 ? 10U : \ |
278 | | sizeof(type) <= 8 ? (IS_SIGNED_INTEGER_TYPE(type) ? 19U : 20U) : sizeof(int[-2*(sizeof(type) > 8)]))) |
279 | | |
280 | | /* Returns the number of chars needed to format the specified integer value. It's hence more specific than |
281 | | * DECIMAL_STR_MAX() which answers the same question for all possible values of the specified type. Does |
282 | | * *not* include space for a trailing NUL. (If you wonder why we special case _x_ == 0 here: it's to trick |
283 | | * out gcc's -Wtype-limits, which would complain on comparing an unsigned type with < 0, otherwise. By |
284 | | * special-casing == 0 here first, we can use <= 0 instead of < 0 to trick out gcc.) */ |
285 | | #define DECIMAL_STR_WIDTH(x) \ |
286 | | ({ \ |
287 | | typeof(x) _x_ = (x); \ |
288 | | size_t ans; \ |
289 | | if (_x_ == 0) \ |
290 | | ans = 1; \ |
291 | | else { \ |
292 | | ans = _x_ <= 0 ? 2 : 1; \ |
293 | | while ((_x_ /= 10) != 0) \ |
294 | | ans++; \ |
295 | | } \ |
296 | | ans; \ |
297 | | }) |
298 | | |
299 | | #define SWAP_TWO(x, y) do { \ |
300 | | typeof(x) _t = (x); \ |
301 | | (x) = (y); \ |
302 | | (y) = (_t); \ |
303 | | } while (false) |
304 | | |
305 | 20.1k | #define STRV_MAKE(...) ((char**) ((const char*[]) { __VA_ARGS__, NULL })) |
306 | | #define STRV_MAKE_EMPTY ((char*[1]) { NULL }) |
307 | 20.1k | #define STRV_MAKE_CONST(...) ((const char* const*) ((const char*[]) { __VA_ARGS__, NULL })) |
308 | | |
309 | | /* Pointers range from NULL to POINTER_MAX */ |
310 | | #define POINTER_MAX ((void*) UINTPTR_MAX) |
311 | | |
312 | | /* Iterates through a specified list of pointers. Accepts NULL pointers, but uses POINTER_MAX as internal marker for EOL. */ |
313 | | #define FOREACH_POINTER(p, x, ...) \ |
314 | | for (typeof(p) *_l = (typeof(p)[]) { ({ p = x; }), ##__VA_ARGS__, POINTER_MAX }; \ |
315 | | p != (typeof(p)) POINTER_MAX; \ |
316 | | p = *(++_l)) |
317 | | |
318 | | /* Define C11 thread_local attribute even on older gcc compiler |
319 | | * version */ |
320 | | #ifndef thread_local |
321 | | /* |
322 | | * Don't break on glibc < 2.16 that doesn't define __STDC_NO_THREADS__ |
323 | | * see https://gcc.gnu.org/bugzilla/show_bug.cgi?id=53769 |
324 | | */ |
325 | | #if __STDC_VERSION__ >= 201112L && !(defined(__STDC_NO_THREADS__) || (defined(__GNU_LIBRARY__) && __GLIBC__ == 2 && __GLIBC_MINOR__ < 16)) |
326 | | #define thread_local _Thread_local |
327 | | #else |
328 | | #define thread_local __thread |
329 | | #endif |
330 | | #endif |
331 | | |
332 | | #define DEFINE_TRIVIAL_DESTRUCTOR(name, type, func) \ |
333 | | static inline void name(type *p) { \ |
334 | | func(p); \ |
335 | | } |
336 | | |
337 | | /* When func() returns the void value (NULL, -1, …) of the appropriate type */ |
338 | | #define DEFINE_TRIVIAL_CLEANUP_FUNC(type, func) \ |
339 | 80.6k | static inline void func##p(type *p) { \ |
340 | 80.6k | if (*p) \ |
341 | 80.6k | *p = func(*p); \ |
342 | 80.6k | } fuzz-link-parser.c:link_config_ctx_freep Line | Count | Source | 339 | 20.1k | static inline void func##p(type *p) { \ | 340 | 20.1k | if (*p) \ | 341 | 20.1k | *p = func(*p); \ | 342 | 20.1k | } |
Unexecuted instantiation: fuzz-link-parser.c:rmdir_and_freep Unexecuted instantiation: fuzz-link-parser.c:unlink_and_freep Unexecuted instantiation: fuzz-link-parser.c:hashmap_freep Unexecuted instantiation: fuzz-link-parser.c:hashmap_free_freep Unexecuted instantiation: fuzz-link-parser.c:hashmap_free_free_keyp Unexecuted instantiation: fuzz-link-parser.c:hashmap_free_free_freep Unexecuted instantiation: fuzz-link-parser.c:ordered_hashmap_freep Unexecuted instantiation: fuzz-link-parser.c:ordered_hashmap_free_freep Unexecuted instantiation: fuzz-link-parser.c:ordered_hashmap_free_free_keyp Unexecuted instantiation: fuzz-link-parser.c:ordered_hashmap_free_free_freep Unexecuted instantiation: fuzz-link-parser.c:iterated_cache_freep Unexecuted instantiation: fuzz-link-parser.c:config_section_freep Unexecuted instantiation: fuzz-link-parser.c:set_freep Unexecuted instantiation: fuzz-link-parser.c:set_free_freep Unexecuted instantiation: fuzz-link-parser.c:link_freep link-config.c:link_config_ctx_freep Line | Count | Source | 339 | 20.1k | static inline void func##p(type *p) { \ | 340 | 20.1k | if (*p) \ | 341 | 20.1k | *p = func(*p); \ | 342 | 20.1k | } |
link-config.c:link_config_freep Line | Count | Source | 339 | 20.1k | static inline void func##p(type *p) { \ | 340 | 20.1k | if (*p) \ | 341 | 20.1k | *p = func(*p); \ | 342 | 20.1k | } |
link-config.c:hashmap_freep Line | Count | Source | 339 | 20.1k | static inline void func##p(type *p) { \ | 340 | 20.1k | if (*p) \ | 341 | 20.1k | *p = func(*p); \ | 342 | 20.1k | } |
Unexecuted instantiation: link-config.c:strv_freep Unexecuted instantiation: link-config.c:link_freep Unexecuted instantiation: link-config.c:hashmap_free_freep Unexecuted instantiation: link-config.c:hashmap_free_free_keyp Unexecuted instantiation: link-config.c:hashmap_free_free_freep Unexecuted instantiation: link-config.c:ordered_hashmap_freep Unexecuted instantiation: link-config.c:ordered_hashmap_free_freep Unexecuted instantiation: link-config.c:ordered_hashmap_free_free_keyp Unexecuted instantiation: link-config.c:ordered_hashmap_free_free_freep Unexecuted instantiation: link-config.c:iterated_cache_freep Unexecuted instantiation: link-config.c:config_section_freep Unexecuted instantiation: link-config.c:set_freep Unexecuted instantiation: link-config.c:set_free_freep Unexecuted instantiation: link-config.c:sr_iov_freep Unexecuted instantiation: link-config.c:sr_iov_free_or_set_invalidp Unexecuted instantiation: link-config.c:ordered_set_freep Unexecuted instantiation: link-config.c:ordered_set_free_freep Unexecuted instantiation: link-config.c:multipath_route_freep Unexecuted instantiation: link-config.c:strv_free_erasep Unexecuted instantiation: link-config-gperf.c:hashmap_freep Unexecuted instantiation: link-config-gperf.c:hashmap_free_freep Unexecuted instantiation: link-config-gperf.c:hashmap_free_free_keyp Unexecuted instantiation: link-config-gperf.c:hashmap_free_free_freep Unexecuted instantiation: link-config-gperf.c:ordered_hashmap_freep Unexecuted instantiation: link-config-gperf.c:ordered_hashmap_free_freep Unexecuted instantiation: link-config-gperf.c:ordered_hashmap_free_free_keyp Unexecuted instantiation: link-config-gperf.c:ordered_hashmap_free_free_freep Unexecuted instantiation: link-config-gperf.c:iterated_cache_freep Unexecuted instantiation: link-config-gperf.c:config_section_freep Unexecuted instantiation: link-config-gperf.c:set_freep Unexecuted instantiation: link-config-gperf.c:set_free_freep Unexecuted instantiation: link-config-gperf.c:link_config_ctx_freep Unexecuted instantiation: link-config-gperf.c:link_freep Unexecuted instantiation: link-config-gperf.c:sr_iov_freep Unexecuted instantiation: link-config-gperf.c:sr_iov_free_or_set_invalidp |
343 | | |
344 | | /* When func() doesn't return the appropriate type, set variable to empty afterwards */ |
345 | | #define DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(type, func, empty) \ |
346 | 0 | static inline void func##p(type *p) { \ |
347 | 0 | if (*p != (empty)) { \ |
348 | 0 | func(*p); \ |
349 | 0 | *p = (empty); \ |
350 | 0 | } \ |
351 | 0 | } Unexecuted instantiation: fuzz-link-parser.c:pclosep Unexecuted instantiation: fuzz-link-parser.c:closedirp Unexecuted instantiation: link-config.c:pclosep Unexecuted instantiation: link-config.c:closedirp |
352 | | |
353 | | #define _DEFINE_TRIVIAL_REF_FUNC(type, name, scope) \ |
354 | | scope type *name##_ref(type *p) { \ |
355 | | if (!p) \ |
356 | | return NULL; \ |
357 | | \ |
358 | | /* For type check. */ \ |
359 | | unsigned *q = &p->n_ref; \ |
360 | | assert(*q > 0); \ |
361 | | assert_se(*q < UINT_MAX); \ |
362 | | \ |
363 | | (*q)++; \ |
364 | | return p; \ |
365 | | } |
366 | | |
367 | | #define _DEFINE_TRIVIAL_UNREF_FUNC(type, name, free_func, scope) \ |
368 | | scope type *name##_unref(type *p) { \ |
369 | | if (!p) \ |
370 | | return NULL; \ |
371 | | \ |
372 | | assert(p->n_ref > 0); \ |
373 | | p->n_ref--; \ |
374 | | if (p->n_ref > 0) \ |
375 | | return NULL; \ |
376 | | \ |
377 | | return free_func(p); \ |
378 | | } |
379 | | |
380 | | #define DEFINE_TRIVIAL_REF_FUNC(type, name) \ |
381 | | _DEFINE_TRIVIAL_REF_FUNC(type, name,) |
382 | | #define DEFINE_PRIVATE_TRIVIAL_REF_FUNC(type, name) \ |
383 | | _DEFINE_TRIVIAL_REF_FUNC(type, name, static) |
384 | | #define DEFINE_PUBLIC_TRIVIAL_REF_FUNC(type, name) \ |
385 | | _DEFINE_TRIVIAL_REF_FUNC(type, name, _public_) |
386 | | |
387 | | #define DEFINE_TRIVIAL_UNREF_FUNC(type, name, free_func) \ |
388 | | _DEFINE_TRIVIAL_UNREF_FUNC(type, name, free_func,) |
389 | | #define DEFINE_PRIVATE_TRIVIAL_UNREF_FUNC(type, name, free_func) \ |
390 | | _DEFINE_TRIVIAL_UNREF_FUNC(type, name, free_func, static) |
391 | | #define DEFINE_PUBLIC_TRIVIAL_UNREF_FUNC(type, name, free_func) \ |
392 | | _DEFINE_TRIVIAL_UNREF_FUNC(type, name, free_func, _public_) |
393 | | |
394 | | #define DEFINE_TRIVIAL_REF_UNREF_FUNC(type, name, free_func) \ |
395 | | DEFINE_TRIVIAL_REF_FUNC(type, name); \ |
396 | | DEFINE_TRIVIAL_UNREF_FUNC(type, name, free_func); |
397 | | |
398 | | #define DEFINE_PRIVATE_TRIVIAL_REF_UNREF_FUNC(type, name, free_func) \ |
399 | | DEFINE_PRIVATE_TRIVIAL_REF_FUNC(type, name); \ |
400 | | DEFINE_PRIVATE_TRIVIAL_UNREF_FUNC(type, name, free_func); |
401 | | |
402 | | #define DEFINE_PUBLIC_TRIVIAL_REF_UNREF_FUNC(type, name, free_func) \ |
403 | | DEFINE_PUBLIC_TRIVIAL_REF_FUNC(type, name); \ |
404 | | DEFINE_PUBLIC_TRIVIAL_UNREF_FUNC(type, name, free_func); |
405 | | |
406 | | /* A macro to force copying of a variable from memory. This is useful whenever we want to read something from |
407 | | * memory and want to make sure the compiler won't optimize away the destination variable for us. It's not |
408 | | * supposed to be a full CPU memory barrier, i.e. CPU is still allowed to reorder the reads, but it is not |
409 | | * allowed to remove our local copies of the variables. We want this to work for unaligned memory, hence |
410 | | * memcpy() is great for our purposes. */ |
411 | | #define READ_NOW(x) \ |
412 | | ({ \ |
413 | | typeof(x) _copy; \ |
414 | | memcpy(&_copy, &(x), sizeof(_copy)); \ |
415 | | asm volatile ("" : : : "memory"); \ |
416 | | _copy; \ |
417 | | }) |
418 | | |
419 | | #define saturate_add(x, y, limit) \ |
420 | | ({ \ |
421 | | typeof(limit) _x = (x); \ |
422 | | typeof(limit) _y = (y); \ |
423 | | _x > (limit) || _y >= (limit) - _x ? (limit) : _x + _y; \ |
424 | | }) |
425 | | |
426 | 0 | static inline size_t size_add(size_t x, size_t y) { |
427 | 0 | return saturate_add(x, y, SIZE_MAX); |
428 | 0 | } Unexecuted instantiation: fuzz-link-parser.c:size_add Unexecuted instantiation: link-config.c:size_add Unexecuted instantiation: link-config-gperf.c:size_add |
429 | | |
430 | | typedef struct { |
431 | | int _empty[0]; |
432 | | } dummy_t; |
433 | | |
434 | | assert_cc(sizeof(dummy_t) == 0); |
435 | | |
436 | | /* A little helper for subtracting 1 off a pointer in a safe UB-free way. This is intended to be used for for |
437 | | * loops that count down from a high pointer until some base. A naive loop would implement this like this: |
438 | | * |
439 | | * for (p = end-1; p >= base; p--) … |
440 | | * |
441 | | * But this is not safe because p before the base is UB in C. With this macro the loop becomes this instead: |
442 | | * |
443 | | * for (p = PTR_SUB1(end, base); p; p = PTR_SUB1(p, base)) … |
444 | | * |
445 | | * And is free from UB! */ |
446 | | #define PTR_SUB1(p, base) \ |
447 | 0 | ({ \ |
448 | 0 | typeof(p) _q = (p); \ |
449 | 0 | _q && _q > (base) ? &_q[-1] : NULL; \ |
450 | 0 | }) |
451 | | |
452 | | #include "log.h" |