The FreeRADIUS server $Id: 15bac2a4c627c01d1aa2047687b3418955ac7f00 $
Loading...
Searching...
No Matches
build.h
Go to the documentation of this file.
1#pragma once
2/*
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation; either version 2 of the License, or
6 * (at your option) any later version.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
16 */
17
18/**
19 * $Id: e6cc822765a42facc335c5dfb3a9a7e5ffb78ad5 $
20 *
21 * @file include/build.h
22 * @brief Source control functions
23 *
24 * @copyright 2013 The FreeRADIUS server project
25 */
26
27#ifdef __cplusplus
28extern "C" {
29#endif
30
31/** For systems with an old version libc, define static_assert.
32 *
33 */
34#ifndef static_assert
35# if __STDC_VERSION__ < 202000
36# define static_assert _Static_assert
37# endif
38# else
39# include <assert.h>
40#endif
41
42/*
43 * Static analyzers don't notice or can't infer some properties
44 * of the code, and hence may give false positives. To deal with
45 * them, there is some conditionally compiled code in various
46 * places. The following lets the code change minimally if and
47 * when new static analyzers are added.
48 */
49#ifdef __clang_analyzer__
50#define STATIC_ANALYZER 1
51#endif
52#ifdef __COVERITY__
53#define STATIC_ANALYZER 1
54#endif
55
56/*
57 * Reduce spurious errors from static analyzers by having
58 * all paths that find the da to be NULL, result
59 * in program exit.
60 */
61#ifdef STATIC_ANALYZER
62# define WITH_VERIFY_PTR 1
63#endif
64
65/*
66 * GCC uses __SANITIZE_ADDRESS__, clang uses __has_feature, which
67 * GCC complains about.
68 */
69#ifndef __SANITIZE_ADDRESS__
70#ifdef __has_feature
71#if __has_feature(address_sanitizer)
72#define __SANITIZE_ADDRESS__ (1)
73#endif
74#endif
75#endif
76
77/*
78 * Basic headers we want everywhere
79 */
80#include <stdint.h>
81#include <stddef.h>
82#include <string.h>
83
84/*
85 * These are compile time options to toggle whether
86 * we're building with thread support.
87 *
88 * With EMSCRIPTEN threading support isn't guaranteed
89 * as many browsers have explicitly disabled support
90 * due to spectre attacks.
91 */
92#if (defined(__EMSCRIPTEN__) && defined(__EMSCRIPTEN_PTHREADS__)) || !defined(__EMSCRIPTEN__) && defined(HAVE_PTHREAD_H)
93# define HAVE_PTHREADS 1
94#endif
95
96/*
97 * GCC will sometimes define "unix" as well as "__unix",
98 * which gets confusing and is unnecessary.
99 */
100#undef unix
101
102/** Evaluates to +1 for a > b, and -1 for a < b
103 */
104#define CMP_PREFER_SMALLER(_a,_b) (((_a) > (_b)) - ((_a) < (_b)))
105
106/** Evaluates to -1 for a > b, and +1 for a < b
107 */
108#define CMP_PREFER_LARGER(_a,_b) (((_a) < (_b)) - ((_a) > (_b)))
109
110/** Same as CMP_PREFER_SMALLER use when you don't really care about ordering, you just want _an_ ordering.
111 */
112#define CMP(_a, _b) CMP_PREFER_SMALLER(_a, _b)
113
114/** Return if the comparison is not 0 (is unequal)
115 *
116 * @param[in] _a pointer to first structure.
117 * @param[in] _b pointer to second structure.
118 * @param[in] _field within the structs to compare.
119 * @return The result of the comparison.
120 */
121#define CMP_RETURN(_a, _b, _field) \
122do { \
123 int8_t _ret = CMP((_a)->_field, (_b)->_field); \
124 if (_ret != 0) return _ret; \
125} while (0)
126
127/** memcmp function which has similar behaviour as strncmp
128 *
129 * @param[in] a First thing to compare.
130 * @param[in] b Second thing to compare.
131 * @param[in] a_len Length of first thing.
132 * @param[in] b_len Length of second thing.
133 * @return
134 * - +1 if a > b
135 * - 0 if a == b
136 * - -1 if a < b
137 */
138static inline int8_t memcmp_return(void const *a, void const *b, size_t a_len, size_t b_len)
139{
140 size_t cmp_len = (a_len < b_len) ? a_len : b_len;
141 int8_t l_ret = CMP(a_len, b_len);
142 int8_t ret;
143 ret = CMP(memcmp(a, b, cmp_len), 0);
144 if (ret != 0) return ret;
145 return l_ret;
146}
147
148/** Return if the contents of the specified field is not identical between the specified structures
149 *
150 * @param[in] _a pointer to first structure.
151 * @param[in] _b pointer to second structure.
152 * @param[in] _field within the structs to compare.
153 * @param[in] _len_field within the structs, specifying the length of the data.
154 * @return The result of the comparison.
155 */
156#define MEMCMP_RETURN(_a, _b, _field, _len_field) \
157do { \
158 int8_t _ret = memcmp_return((_a)->_field, (_b)->_field, (_a)->_len_field, (_b)->_len_field); \
159 if (_ret != 0) return _ret; \
160} while (0)
161
162/** Remove const qualification from a pointer
163 *
164 * @param[in] _type The non-const version of the type.
165 * @param[in] _ptr to de-const.
166 */
167#define UNCONST(_type, _ptr) ((_type)((uintptr_t)(_ptr)))
168
169/** Typeof field
170 *
171 * @param[in] _type struct type containing the field.
172 * @param[in] _field to return the type of.
173 */
174#define typeof_field(_type, _field) __typeof__(((_type *)NULL)->_field)
175
176/** HEX concatenation macros
177 *
178 */
179#ifndef HEXIFY
180# define XHEXIFY4(b1,b2,b3,b4) (0x ## b1 ## b2 ## b3 ## b4)
181# define HEXIFY4(b1,b2,b3,b4) XHEXIFY4(b1, b2, b3, b4)
182
183# define XHEXIFY3(b1,b2,b3) (0x ## b1 ## b2 ## b3)
184# define HEXIFY3(b1,b2,b3) XHEXIFY3(b1, b2, b3)
185
186# define XHEXIFY2(b1,b2) (0x ## b1 ## b2)
187# define HEXIFY2(b1,b2) XHEXIFY2(b1, b2)
188
189# define XHEXIFY(b1) (0x ## b1)
190# define HEXIFY(b1) XHEXIFY(b1)
191#endif
192
193/** The ubiquitous stringify macros
194 *
195 */
196#define XSTRINGIFY(x) #x
197#define STRINGIFY(x) XSTRINGIFY(x)
198#define JOINSTR(x,y) XSTRINGIFY(x ## y)
199
200/** Join two values without stringifying
201 *
202 * Useful for calling different macros based on the output of
203*/
204#define _JOIN(x,y) x ## y
205#define JOIN(x,y) _JOIN(x,y)
206
207/** Helper for initialising arrays of string literals
208 */
209#define L(_str) { _str, sizeof(_str) - 1 }
210
211/** Fill macros for array initialisation
212 */
213#define F1(_idx, _val) [_idx] = _val
214#define F2(_idx, _val) F1(_idx, _val), F1(_idx + 1, _val)
215#define F4(_idx, _val) F2(_idx, _val), F2(_idx + 2, _val)
216#define F8(_idx, _val) F4(_idx, _val), F4(_idx + 4, _val)
217#define F16(_idx, _val) F8(_idx, _val), F8(_idx + 8, _val)
218#define F32(_idx, _val) F16(_idx, _val), F16(_idx + 16, _val)
219#define F64(_idx, _val) F32(_idx, _val), F32(_idx + 32, _val)
220#define F128(_idx, _val) F64(_idx, _val), F64(_idx + 64, _val)
221#define F256(_idx, _val) F128(_idx, _val), F128(_idx + 128, _val)
222
223/** Variadic macro framework
224 */
225
226/**
227 * The VA_NARG macro evaluates to the number of arguments that have been
228 * passed to it.
229 *
230 * Laurent Deniau, "__VA_NARG__," 17 January 2006, <comp.std.c> (29 November 2007).
231 */
232#define VA_ARG_N( \
233 _1, _2, _3, _4, _5, _6, _7, _8, _9,_10, \
234 _11,_12,_13,_14,_15,_16,_17,_18,_19,_20, \
235 _21,_22,_23,_24,_25,_26,_27,_28,_29,_30, \
236 _31,_32,_33,_34,_35,_36,_37,_38,_39,_40, \
237 _41,_42,_43,_44,_45,_46,_47,_48,_49,_50, \
238 _51,_52,_53,_54,_55,_56,_57,_58,_59,_60, \
239 _61,_62,_63,N,...) N
240
241#define VA_RSEQ_N() \
242 63,62,61,60, \
243 59,58,57,56,55,54,53,52,51,50, \
244 49,48,47,46,45,44,43,42,41,40, \
245 39,38,37,36,35,34,33,32,31,30, \
246 29,28,27,26,25,24,23,22,21,20, \
247 19,18,17,16,15,14,13,12,11,10, \
248 9,8,7,6,5,4,3,2,1,0
249
250#define _VA_NARG(...) VA_ARG_N(__VA_ARGS__)
251
252/** Return the number of variadic arguments up to 64
253 *
254 * @param[in] ... Variadic arguments to count.
255 */
256#define VA_NARG(...) _VA_NARG(__VA_ARGS__, VA_RSEQ_N())
257
258
259/** Pass caller information to the function
260 *
261 */
262#ifndef NDEBUG
263# define NDEBUG_LOCATION_ARGS char const *file, int line,
264# define NDEBUG_LOCATION_VALS file, line,
265# define NDEBUG_LOCATION_EXP __FILE__, __LINE__,
266# define NDEBUG_LOCATION_NONNULL(_num) ((_num) + 2)
267#else
268# define NDEBUG_LOCATION_ARGS
269# define NDEBUG_LOCATION_VALS
270# define NDEBUG_LOCATION_EXP
271# define NDEBUG_LOCATION_NONNULL(_num) (_num)
272#endif
273
274/** Check if a given variable is the _const or not
275 *
276 * @param[in] _type The base type of the variable (should not be marked const)
277 * @param[in] _var to check.
278 */
279#define IS_CONST(_type, _var) \
280 _Generic((_var), \
281 _type: false, \
282 const _type: true \
283 )
284
285/** Check if a given variable is the const or unconst version of a type
286 *
287 * Expands to _var if _var matches type, otherwise throws a compiler error.
288 *
289 * Useful for creating typesafe wrapper macros around functions which take
290 * void *s.
291 *
292 * @param[in] _type The base type of the variable (should not be marked const)
293 * @param[in] _var to check.
294 */
295#define IS_TYPE(_type, _var) \
296 _Generic((_var), \
297 _type: _var, \
298 const _type: _var \
299 )
300/*
301 * Mark variables as unused
302 */
303#define UNUSED_VAR(_x) ((void)_x)
304
305/** Pad _x to the next multiple of _y
306 *
307 */
308#define PAD(_x, _y) (_y - ((_x) % _y))
309
310/** Should be placed before the function return type
311 *
312 */
313#define NEVER_RETURNS _Noreturn
314#define HIDDEN CC_HINT(visibility("hidden"))
315#define UNUSED CC_HINT(unused)
316
317/** clang 10 doesn't recognised the FALL-THROUGH comment anymore
318 */
319#if (defined(__clang__) && (__clang_major__ >= 10)) || (defined(__GNUC__) && __GNUC__ >= 7)
320# define FALL_THROUGH CC_HINT(fallthrough)
321#else
322# define FALL_THROUGH ((void)0)
323#endif
324
325#ifndef NDEBUG
326# define NDEBUG_UNUSED
327#else
328# define NDEBUG_UNUSED UNUSED
329#endif
330
331#define BLANK_FORMAT " " /* GCC_LINT whines about empty formats */
332
333/*
334 * struct field size
335 */
336#define SIZEOF_MEMBER(_t, _m) sizeof(((_t *)0)->_m)
337#define NUM_ELEMENTS(_t) (sizeof((_t)) / sizeof((_t)[0]))
338
339/*
340 * For use with multidimensional arrays where
341 * the deeper array element has a size smaller than
342 * a pointer i.e. char foo[n][m]
343 */
344#define NUM_PTR_ELEMENTS(_t) (sizeof((_t)) / sizeof(void *))
345
346/*
347 * Type checking
348 */
349
350/** Check if two types are compatible (the C11 way)
351 *
352 * Expands to 1 if types are compatible, else 0.
353 *
354 * @param[in] _x pointer to check.
355 * @param[in] _t type to check compatibility with.
356 */
357#define IS_COMPATIBLE(_x, _t) _Generic(_x, _t:1, default: 0)
358
359/** Check if a field in a struct is compatible (the C11 way)
360 *
361 * Expands to 1 if types are compatible, else 0.
362 *
363 * @param[in] _s struct to check.
364 * @param[in] _f field in struct.
365 * @param[in] _t type to check compatibility with.
366 */
367#define IS_FIELD_COMPATIBLE(_s, _f, _t) _Generic(((_s *)0)->_f, _t:1, default: 0)
368
369/*
370 * Only use GCC __attribute__ if were building with a GCClike
371 * compiler.
372 */
373#ifdef __GNUC__
374# define CC_HINT(...) __attribute__((__VA_ARGS__))
375# define likely(_x) __builtin_expect((_x), 1)
376# define unlikely(_x) __builtin_expect((_x), 0)
377# define unpredictable(_x) __builtin_unpredictable((_x))
378#else
379# define CC_HINT(...)
380# define likely(_x) _x
381# define unlikely(_x) _x
382# define unpredictable(_x) _x
383#endif
384
385/*
386 * GNU version check
387 */
388#ifdef __GNUC__
389#define __GNUC_PREREQ__(x, y) \
390 ((__GNUC__ == (x) && __GNUC_MINOR__ >= (y)) || \
391 (__GNUC__ > (x)))
392#else
393#define __GNUC_PREREQ__(x, y) 0
394#endif
395
396
397/*
398 * Macros to add pragmas
399 */
400#define PRAGMA(_x) _Pragma(#_x)
401
402/*
403 * Handle acquire/release macros
404 */
405#if defined(__clang__) && (__clang_major__ >= 13)
406# define CC_ACQUIRE_HANDLE(_tag) CC_HINT(acquire_handle(_tag))
407# define CC_USE_HANDLE(_tag) CC_HINT(use_handle(_tag))
408# define CC_RELEASE_HANDLE(_tag) CC_HINT(release_handle(_tag))
409#else
410# define CC_ACQUIRE_HANDLE(_tag)
411# define CC_USE_HANDLE(_tag)
412# define CC_RELEASE_HANDLE(_tag)
413#endif
414
415/*
416 * Disable various forms of ubsan
417 */
418#ifndef __has_feature
419# define __has_feature(_x) 0
420#endif
421#if defined(__clang__) && __has_feature(undefined_behavior_sanitizer)
422# define CC_NO_UBSAN(_sanitize) __attribute__((no_sanitize(STRINGIFY(_sanitize))))
423#elif __GNUC_PREREQ__(4, 9) && defined(__SANITIZE_UNDEFINED__)
424# define CC_NO_UBSAN(_sanitize) __attribute__((no_sanitize_undefined))
425#else
426# define CC_NO_UBSAN(_sanitize)
427#endif
428
429/*
430 * Disable sanitizers for undefined behaviour
431 */
432#if defined(__clang__)
433# define CC_NO_SANITIZE_UNDEFINED(_what) CC_HINT(no_sanitize(_what))
434#else
435# define CC_NO_SANITIZE_UNDEFINED(_what)
436#endif
437
438/*
439 * Macros for controlling warnings in GCC >= 4.2 and clang >= 2.8
440 */
441#if defined(__clang__) && ((__clang_major__ * 100) + __clang_minor__ >= 208)
442# define DIAG_UNKNOWN_PRAGMAS unknown-pragmas
443# define DIAG_PRAGMA(_x) PRAGMA(clang diagnostic _x)
444# define DIAG_OFF(_x) DIAG_PRAGMA(ignored JOINSTR(-W,_x))
445# define DIAG_ON(_x) DIAG_PRAGMA(warning JOINSTR(-W,_x))
446# define DIAG_PUSH() DIAG_PRAGMA(push)
447# define DIAG_POP() DIAG_PRAGMA(pop)
448#elif !defined(__clang__) && defined(__GNUC__) && ((__GNUC__ * 100) + __GNUC_MINOR__) >= 402
449# define DIAG_UNKNOWN_PRAGMAS pragmas
450# define DIAG_PRAGMA(_x) PRAGMA(GCC diagnostic _x)
451# define DIAG_OFF(_x) DIAG_PRAGMA(ignored JOINSTR(-W,_x))
452# define DIAG_ON(_x) DIAG_PRAGMA(warning JOINSTR(-W,_x))
453# define DIAG_PUSH() DIAG_PRAGMA(push)
454# define DIAG_POP() DIAG_PRAGMA(pop)
455#else
456# define DIAG_UNKNOWN_PRAGMAS
457# define DIAG_OFF(_x)
458# define DIAG_ON(_x)
459# define DIAG_PUSH()
460# define DIAG_POP()
461#endif
462
463/*
464 * For dealing with APIs which are only deprecated in OSX (like the OpenSSL API)
465 */
466#ifdef __APPLE__
467# define USES_APPLE_DEPRECATED_API DIAG_OFF(deprecated-declarations)
468# define USES_APPLE_RST DIAG_ON(deprecated-declarations)
469#else
470# define USES_APPLE_DEPRECATED_API
471# define USES_APPLE_RST
472#endif
473
474#if defined(__GNUC__)
475/* force inclusion of ident keywords in the face of optimization */
476# define RCSID(id) static char const rcsid[] __attribute__ ((used)) = id;
477# define RCSIDH(h, id) static char const rcsid_ ## h [] __attribute__ ((used)) = id;
478#elif defined(__SUNPRO_C)
479/* put ident keyword into comment section (nicer than gcc way) */
480# define RCSID(id) PRAGMA(sun ident id)
481# define RCSIDH(h, id) PRAGMA(sun ident id)
482#else
483# define RCSID(id)
484# define RCSIDH(h, id)
485#endif
486#ifdef __cplusplus
487}
488#endif
489
490/*
491 * For closing macros which open a code block e.g. fr_rb_inorder_foreach
492 */
493#define endforeach }
494
495/* Explicitly evaluate and ignore an expression
496 *
497 * Why this macro?
498 * 1. gcc will warn about unused return values, even with the traditional cast to void.
499 * 2. There are cases in which an error case wants to clean up, but the function to
500 * clean up itself returns a status. In this context you don't care, but then you
501 * have the Scylla of unused return value and the Charybdis of Coverity complaining
502 * about an if that doesn't affect control flow. The following evaluates _expr and
503 * stores it in a variable marked as unused
504 * @param _expr The expression to be evaluated and ignored
505 * @param _type The type of the expression
506 */
507#define IGNORE(_expr, _type) \
508 do { \
509 _type ignored UNUSED = (_expr); \
510 } while (0)
static int8_t memcmp_return(void const *a, void const *b, size_t a_len, size_t b_len)
memcmp function which has similar behaviour as strncmp
Definition build.h:138
#define CMP(_a, _b)
Same as CMP_PREFER_SMALLER use when you don't really care about ordering, you just want an ordering.
Definition build.h:112