dte test coverage


Directory: ./
File: src/util/xmalloc.h
Date: 2025-02-14 16:55:22
Exec Total Coverage
Lines: 31 31 100.0%
Functions: 11 11 100.0%
Branches: 2 8 25.0%

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