Line | Branch | Exec | Source |
---|---|---|---|
1 | #ifndef UTIL_XMALLOC_H | ||
2 | #define UTIL_XMALLOC_H | ||
3 | |||
4 | #include <stddef.h> | ||
5 | #include <string.h> | ||
6 | #include "arith.h" | ||
7 | #include "macros.h" | ||
8 | |||
9 | #define XMEMDUP(ptr) xmemdup(ptr, sizeof(*ptr)) | ||
10 | #define xrenew(mem, n) xreallocarray(mem, (n), sizeof(*mem)) | ||
11 | |||
12 | void *xmalloc(size_t size) XMALLOC ALLOC_SIZE(1); | ||
13 | void *xcalloc(size_t nmemb, size_t size) XMALLOC ALLOC_SIZE(1, 2); | ||
14 | void *xrealloc(void *ptr, size_t size) RETURNS_NONNULL WARN_UNUSED_RESULT ALLOC_SIZE(2); | ||
15 | char *xstrdup(const char *str) XSTRDUP; | ||
16 | char *xasprintf(const char *format, ...) PRINTF(1) XMALLOC; | ||
17 | size_t xmul_(size_t a, size_t b); | ||
18 | size_t xadd(size_t a, size_t b); | ||
19 | |||
20 | // Equivalent to `a * b`, but calling fatal_error() for arithmetic overflow. | ||
21 | // Note that if either operand is 2, adding 1 to the result can never | ||
22 | // overflow (often useful when doubling a buffer plus 1 extra byte). Similar | ||
23 | // observations can be made when multiplying by other powers of 2 (except 1) | ||
24 | // due to the equivalence with left shifting. | ||
25 | 14002 | static inline size_t xmul(size_t a, size_t b) | |
26 | { | ||
27 | // If either argument is known at compile-time to be 1, the multiplication | ||
28 | // can't overflow and is thus safe to be inlined without checks | ||
29 |
2/8✗ Branch 0 (2→3) not taken.
✓ Branch 1 (2→4) taken 14002 times.
✗ Branch 2 (3→4) not taken.
✗ Branch 3 (3→6) not taken.
✗ Branch 4 (4→5) not taken.
✓ Branch 5 (4→7) taken 14002 times.
✗ Branch 6 (5→6) not taken.
✗ Branch 7 (5→7) not taken.
|
14002 | if ((IS_CT_CONSTANT(a) && a <= 1) || (IS_CT_CONSTANT(b) && b <= 1)) { |
30 | − | return a * b; // GCOVR_EXCL_LINE | |
31 | } | ||
32 | // Otherwise, emit a call to the checked implementation | ||
33 | 14002 | return xmul_(a, b); | |
34 | } | ||
35 | |||
36 | 4 | static inline size_t xadd3(size_t a, size_t b, size_t c) | |
37 | { | ||
38 | 4 | return xadd(a, xadd(b, c)); | |
39 | } | ||
40 | |||
41 | XMALLOC ALLOC_SIZE(1, 2) | ||
42 | 1918 | static inline void *xmallocarray(size_t nmemb, size_t size) | |
43 | { | ||
44 | 1918 | return xmalloc(xmul(nmemb, size)); | |
45 | } | ||
46 | |||
47 | RETURNS_NONNULL WARN_UNUSED_RESULT ALLOC_SIZE(2, 3) | ||
48 | 12079 | static inline void *xreallocarray(void *ptr, size_t nmemb, size_t size) | |
49 | { | ||
50 | 12079 | return xrealloc(ptr, xmul(nmemb, size)); | |
51 | } | ||
52 | |||
53 | NONNULL_ARGS_AND_RETURN ALLOC_SIZE(2) | ||
54 | 4083 | static inline void *xmemdup(const void *ptr, size_t size) | |
55 | { | ||
56 | 4083 | return memcpy(xmalloc(size), ptr, size); | |
57 | } | ||
58 | |||
59 | // Portable version of glibc/FreeBSD mempcpy(3) | ||
60 | 1805 | static inline void *xmempcpy(void *restrict dest, const void *restrict src, size_t n) | |
61 | { | ||
62 | 1805 | memcpy(dest, src, n); | |
63 | 1805 | return (char*)dest + n; | |
64 | } | ||
65 | |||
66 | NONNULL_ARGS_AND_RETURN | ||
67 | 1803 | static inline void *xmemjoin(const void *p1, size_t n1, const void *p2, size_t n2) | |
68 | { | ||
69 | 1803 | char *joined = xmalloc(xadd(n1, n2)); | |
70 | 1803 | memcpy(xmempcpy(joined, p1, n1), p2, n2); | |
71 | 1803 | return joined; | |
72 | } | ||
73 | |||
74 | NONNULL_ARGS_AND_RETURN | ||
75 | 1 | static inline void *xmemjoin3 ( | |
76 | const void *p1, size_t n1, | ||
77 | const void *p2, size_t n2, | ||
78 | const void *p3, size_t n3 | ||
79 | ) { | ||
80 | 1 | char *joined = xmalloc(xadd3(n1, n2, n3)); | |
81 | 1 | memcpy(xmempcpy(xmempcpy(joined, p1, n1), p2, n2), p3, n3); | |
82 | 1 | return joined; | |
83 | } | ||
84 | |||
85 | XSTRDUP | ||
86 | 1412 | static inline char *xstrjoin(const char *s1, const char *s2) | |
87 | { | ||
88 | 1412 | return xmemjoin(s1, strlen(s1), s2, strlen(s2) + 1); | |
89 | } | ||
90 | |||
91 | // Return a null-terminated copy of the first `size` bytes of `str` | ||
92 | XSTRDUP | ||
93 | 333 | static inline char *xstrcut(const char *str, size_t size) | |
94 | { | ||
95 | 333 | return xmemjoin(str, size, "", 1); | |
96 | } | ||
97 | |||
98 | // Return a null-terminated copy of the substring between `pos` and `end` | ||
99 | XSTRDUP | ||
100 | 88 | static inline char *xstrslice(const char *str, size_t pos, size_t end) | |
101 | { | ||
102 | 88 | BUG_ON(pos > end); | |
103 | 88 | return xstrcut(str + pos, end - pos); | |
104 | } | ||
105 | |||
106 | #endif | ||
107 |