/src/dropbear/src/dbmalloc.c
Line | Count | Source (jump to first uncovered line) |
1 | | #include "dbmalloc.h" |
2 | | #include "dbutil.h" |
3 | | |
4 | | |
5 | 0 | void * m_calloc(size_t nmemb, size_t size) { |
6 | 0 | if (SIZE_T_MAX / nmemb < size) { |
7 | 0 | dropbear_exit("m_calloc failed"); |
8 | 0 | } |
9 | 0 | return m_malloc(nmemb*size); |
10 | 0 | } |
11 | | |
12 | 6 | void * m_strdup(const char * str) { |
13 | 6 | char* ret; |
14 | 6 | unsigned int len; |
15 | 6 | len = strlen(str); |
16 | | |
17 | 6 | ret = m_malloc(len+1); |
18 | 6 | if (ret == NULL) { |
19 | 0 | dropbear_exit("m_strdup failed"); |
20 | 0 | } |
21 | 6 | memcpy(ret, str, len+1); |
22 | 6 | return ret; |
23 | 6 | } |
24 | | |
25 | | #if !DROPBEAR_TRACKING_MALLOC |
26 | | |
27 | | /* Simple wrappers around malloc etc */ |
28 | | void * m_malloc(size_t size) { |
29 | | |
30 | | void* ret; |
31 | | |
32 | | if (size == 0) { |
33 | | dropbear_exit("m_malloc failed"); |
34 | | } |
35 | | ret = calloc(1, size); |
36 | | if (ret == NULL) { |
37 | | dropbear_exit("m_malloc failed"); |
38 | | } |
39 | | return ret; |
40 | | |
41 | | } |
42 | | |
43 | | void * m_realloc(void* ptr, size_t size) { |
44 | | |
45 | | void *ret; |
46 | | |
47 | | if (size == 0) { |
48 | | dropbear_exit("m_realloc failed"); |
49 | | } |
50 | | ret = realloc(ptr, size); |
51 | | if (ret == NULL) { |
52 | | dropbear_exit("m_realloc failed"); |
53 | | } |
54 | | return ret; |
55 | | } |
56 | | |
57 | | |
58 | | #else |
59 | | |
60 | | /* For fuzzing */ |
61 | | |
62 | | struct dbmalloc_header { |
63 | | unsigned int epoch; |
64 | | struct dbmalloc_header *prev; |
65 | | struct dbmalloc_header *next; |
66 | | }; |
67 | | |
68 | | static void put_alloc(struct dbmalloc_header *header); |
69 | | static void remove_alloc(struct dbmalloc_header *header); |
70 | | |
71 | | /* end of the linked list */ |
72 | | static struct dbmalloc_header* staple; |
73 | | |
74 | | unsigned int current_epoch = 0; |
75 | | |
76 | 2.89k | void m_malloc_set_epoch(unsigned int epoch) { |
77 | 2.89k | current_epoch = epoch; |
78 | 2.89k | } |
79 | | |
80 | 2.89k | void m_malloc_free_epoch(unsigned int epoch, int dofree) { |
81 | 2.89k | struct dbmalloc_header* header; |
82 | 2.89k | struct dbmalloc_header* nextheader = NULL; |
83 | 2.89k | struct dbmalloc_header* oldstaple = staple; |
84 | 2.89k | staple = NULL; |
85 | | /* free allocations from this epoch, create a new staple-anchored list from |
86 | | the remainder */ |
87 | 2.93M | for (header = oldstaple; header; header = nextheader) |
88 | 2.93M | { |
89 | 2.93M | nextheader = header->next; |
90 | 2.93M | if (header->epoch == epoch) { |
91 | 7.83k | if (dofree) { |
92 | 7.83k | free(header); |
93 | 7.83k | } |
94 | 2.92M | } else { |
95 | 2.92M | header->prev = NULL; |
96 | 2.92M | header->next = NULL; |
97 | 2.92M | put_alloc(header); |
98 | 2.92M | } |
99 | 2.93M | } |
100 | 2.89k | } |
101 | | |
102 | 3.07M | static void put_alloc(struct dbmalloc_header *header) { |
103 | 3.07M | assert(header->next == NULL); |
104 | 3.07M | assert(header->prev == NULL); |
105 | 3.07M | if (staple) { |
106 | 3.07M | staple->prev = header; |
107 | 3.07M | } |
108 | 3.07M | header->next = staple; |
109 | 3.07M | staple = header; |
110 | 3.07M | } |
111 | | |
112 | 136k | static void remove_alloc(struct dbmalloc_header *header) { |
113 | 136k | if (header->prev) { |
114 | 56.7k | header->prev->next = header->next; |
115 | 56.7k | } |
116 | 136k | if (header->next) { |
117 | 136k | header->next->prev = header->prev; |
118 | 136k | } |
119 | 136k | if (staple == header) { |
120 | 79.7k | staple = header->next; |
121 | 79.7k | } |
122 | 136k | header->prev = NULL; |
123 | 136k | header->next = NULL; |
124 | 136k | } |
125 | | |
126 | 136k | static struct dbmalloc_header* get_header(void* ptr) { |
127 | 136k | char* bptr = ptr; |
128 | 136k | return (struct dbmalloc_header*)&bptr[-sizeof(struct dbmalloc_header)]; |
129 | 136k | } |
130 | | |
131 | 143k | void * m_malloc(size_t size) { |
132 | 143k | char* mem = NULL; |
133 | 143k | struct dbmalloc_header* header = NULL; |
134 | | |
135 | 143k | if (size == 0 || size > 1e9) { |
136 | 0 | dropbear_exit("m_malloc failed"); |
137 | 0 | } |
138 | | |
139 | 143k | size = size + sizeof(struct dbmalloc_header); |
140 | | |
141 | 143k | mem = calloc(1, size); |
142 | 143k | if (mem == NULL) { |
143 | 0 | dropbear_exit("m_malloc failed"); |
144 | 0 | } |
145 | 143k | header = (struct dbmalloc_header*)mem; |
146 | 143k | put_alloc(header); |
147 | 143k | header->epoch = current_epoch; |
148 | 143k | return &mem[sizeof(struct dbmalloc_header)]; |
149 | 143k | } |
150 | | |
151 | 3.07k | void * m_realloc(void* ptr, size_t size) { |
152 | 3.07k | char* mem = NULL; |
153 | 3.07k | struct dbmalloc_header* header = NULL; |
154 | 3.07k | if (size == 0 || size > 1e9) { |
155 | 0 | dropbear_exit("m_realloc failed"); |
156 | 0 | } |
157 | | |
158 | 3.07k | header = get_header(ptr); |
159 | 3.07k | remove_alloc(header); |
160 | | |
161 | 3.07k | size = size + sizeof(struct dbmalloc_header); |
162 | 3.07k | mem = realloc(header, size); |
163 | 3.07k | if (mem == NULL) { |
164 | 0 | dropbear_exit("m_realloc failed"); |
165 | 0 | } |
166 | | |
167 | 3.07k | header = (struct dbmalloc_header*)mem; |
168 | 3.07k | put_alloc(header); |
169 | 3.07k | return &mem[sizeof(struct dbmalloc_header)]; |
170 | 3.07k | } |
171 | | |
172 | 150k | void m_free_direct(void* ptr) { |
173 | 150k | struct dbmalloc_header* header = NULL; |
174 | 150k | if (!ptr) { |
175 | 17.5k | return; |
176 | 17.5k | } |
177 | 133k | header = get_header(ptr); |
178 | 133k | remove_alloc(header); |
179 | 133k | free(header); |
180 | 133k | } |
181 | | |
182 | | #endif /* DROPBEAR_TRACKING_MALLOC */ |
183 | | |
184 | 0 | void * m_realloc_ltm(void* ptr, size_t oldsize, size_t newsize) { |
185 | 0 | (void)oldsize; |
186 | 0 | return m_realloc(ptr, newsize); |
187 | 0 | } |
188 | | |
189 | 0 | void m_free_ltm(void *mem, size_t size) { |
190 | 0 | (void)size; |
191 | 0 | m_free_direct(mem); |
192 | 0 | } |