Line data Source code
1 : /* SPDX-License-Identifier: LGPL-2.1+ */
2 : #pragma once
3 :
4 : #include <inttypes.h>
5 : #include <malloc.h>
6 : #include <stdbool.h>
7 : #include <string.h>
8 : #include <sys/types.h>
9 :
10 : #include "macro.h"
11 :
12 : size_t page_size(void) _pure_;
13 : #define PAGE_ALIGN(l) ALIGN_TO((l), page_size())
14 :
15 : /* Normal memcpy requires src to be nonnull. We do nothing if n is 0. */
16 45675 : static inline void memcpy_safe(void *dst, const void *src, size_t n) {
17 45675 : if (n == 0)
18 46 : return;
19 45629 : assert(src);
20 45629 : memcpy(dst, src, n);
21 : }
22 :
23 : /* Normal memcmp requires s1 and s2 to be nonnull. We do nothing if n is 0. */
24 138 : static inline int memcmp_safe(const void *s1, const void *s2, size_t n) {
25 138 : if (n == 0)
26 4 : return 0;
27 134 : assert(s1);
28 134 : assert(s2);
29 134 : return memcmp(s1, s2, n);
30 : }
31 :
32 : /* Compare s1 (length n1) with s2 (length n2) in lexicographic order. */
33 18 : static inline int memcmp_nn(const void *s1, size_t n1, const void *s2, size_t n2) {
34 18 : return memcmp_safe(s1, s2, MIN(n1, n2))
35 18 : ?: CMP(n1, n2);
36 : }
37 :
38 : #define memzero(x,l) \
39 : ({ \
40 : size_t _l_ = (l); \
41 : if (_l_ > 0) \
42 : memset(x, 0, _l_); \
43 : })
44 :
45 : #define zero(x) (memzero(&(x), sizeof(x)))
46 :
47 : bool memeqzero(const void *data, size_t length);
48 :
49 : #define eqzero(x) memeqzero(x, sizeof(x))
50 :
51 67698 : static inline void *mempset(void *s, int c, size_t n) {
52 67698 : memset(s, c, n);
53 67698 : return (uint8_t*)s + n;
54 : }
55 :
56 : /* Normal memmem() requires haystack to be nonnull, which is annoying for zero-length buffers */
57 87 : static inline void *memmem_safe(const void *haystack, size_t haystacklen, const void *needle, size_t needlelen) {
58 :
59 87 : if (needlelen <= 0)
60 0 : return (void*) haystack;
61 :
62 87 : if (haystacklen < needlelen)
63 52 : return NULL;
64 :
65 35 : assert(haystack);
66 35 : assert(needle);
67 :
68 35 : return memmem(haystack, haystacklen, needle, needlelen);
69 : }
70 :
71 : #if HAVE_EXPLICIT_BZERO
72 29 : static inline void* explicit_bzero_safe(void *p, size_t l) {
73 29 : if (l > 0)
74 29 : explicit_bzero(p, l);
75 :
76 29 : return p;
77 : }
78 : #else
79 : void *explicit_bzero_safe(void *p, size_t l);
80 : #endif
81 :
82 29 : static inline void erase_and_freep(void *p) {
83 29 : void *ptr = *(void**) p;
84 :
85 29 : if (ptr) {
86 29 : size_t l = malloc_usable_size(ptr);
87 29 : explicit_bzero_safe(ptr, l);
88 29 : free(ptr);
89 : }
90 29 : }
91 :
92 : /* Use with _cleanup_ to erase a single 'char' when leaving scope */
93 0 : static inline void erase_char(char *p) {
94 0 : explicit_bzero_safe(p, sizeof(char));
95 0 : }
|