dte test coverage


Directory: ./
File: src/util/xmalloc.h
Date: 2024-12-21 16:03:22
Exec Total Coverage
Lines: 20 20 100.0%
Functions: 7 7 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) xmalloc(xmul(sizeof(type), (n)))
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 17479 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 not taken.
✓ Branch 1 taken 17479 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 17479 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
17479 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 17479 return xmul_(a, b);
36 }
37
38 RETURNS_NONNULL WARN_UNUSED_RESULT ALLOC_SIZE(2, 3)
39 11018 static inline void *xreallocarray(void *ptr, size_t nmemb, size_t size)
40 {
41 11018 return xrealloc(ptr, xmul(nmemb, size));
42 }
43
44 NONNULL_ARGS_AND_RETURN ALLOC_SIZE(2)
45 3965 static inline void *xmemdup(const void *ptr, size_t size)
46 {
47 3965 return memcpy(xmalloc(size), ptr, size);
48 }
49
50 // Return a null-terminated copy of the first `size` bytes of `str`
51 XSTRDUP
52 325 static inline char *xstrcut(const char *str, size_t size)
53 {
54 325 char *s = xmalloc(size + 1);
55 325 s[size] = '\0';
56 325 return memcpy(s, str, size);
57 }
58
59 // Return a null-terminated copy of the substring between `pos` and `end`
60 XSTRDUP
61 87 static inline char *xstrslice(const char *str, size_t pos, size_t end)
62 {
63 87 return xstrcut(str + pos, end - pos);
64 }
65
66 NONNULL_ARGS_AND_RETURN
67 1425 static inline void *xmemjoin(const void *p1, size_t n1, const void *p2, size_t n2)
68 {
69 1425 char *joined = xmalloc(xadd(n1, n2));
70 1425 memcpy(joined, p1, n1);
71 1425 memcpy(joined + n1, p2, n2);
72 1425 return joined;
73 }
74
75 XSTRDUP
76 1391 static inline char *xstrjoin(const char *s1, const char *s2)
77 {
78 1391 return xmemjoin(s1, strlen(s1), s2, strlen(s2) + 1);
79 }
80
81 #endif
82