Skip to content

Commit 1d4b7cc

Browse files
committed
Guard against heap memory corruption
1 parent 99a08dd commit 1d4b7cc

File tree

1 file changed

+35
-12
lines changed

1 file changed

+35
-12
lines changed

src/usr/lib/stdlib.c

Lines changed: 35 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -177,15 +177,17 @@ _heap_end: # dynamic marker based on current esp
177177
178178
*/
179179

180+
#define HEAP_ENTRY_SIGNATURE 0x89B26F78
180181
static union heap_entry {
181182
// header of each allocated or unallocated block
182183
struct {
183184
// including the header size
184185
uint32_t size; // size of current block
185186
uint32_t prev_size; // size of prev block for doubly linked list
186187
uint8_t state;
188+
uint32_t signature;
187189
} content;
188-
uint32_t __padding[3]; // force heap_entry size to be 12 bytes.
190+
uint32_t __padding[4]; // force heap_entry size to be 16 bytes.
189191
};
190192

191193
#define HEAP_HEADER_SIZE (sizeof(union heap_entry))
@@ -237,16 +239,30 @@ static inline void heap_may_init() {
237239
first->content.prev_size = 0;
238240
last->content.size = HEAP_HEADER_SIZE;
239241
first->content.size = last->content.prev_size = HEAP_HEADER_SIZE;
242+
first->content.signature = last->content.signature =
243+
HEAP_ENTRY_SIGNATURE;
240244
heap_initialized = 1;
241245
}
242246
}
243247

244-
static inline union heap_entry *heap_next_block(union heap_entry *current) {
245-
return (((void *)current) + current->content.size);
248+
static inline union heap_entry *heap_next_block(union heap_entry *current,
249+
int verify_signature) {
250+
union heap_entry *block = (((void *)current) + current->content.size);
251+
if (verify_signature) {
252+
heap_assert(block->content.signature == HEAP_ENTRY_SIGNATURE,
253+
"heap_next_block, invalid signature");
254+
}
255+
return block;
246256
}
247257

248-
static inline union heap_entry *heap_prev_block(union heap_entry *current) {
249-
return (((void *)current) - current->content.prev_size);
258+
static inline union heap_entry *heap_prev_block(union heap_entry *current,
259+
int verify_signature) {
260+
union heap_entry *block = (((void *)current) - current->content.prev_size);
261+
if (verify_signature) {
262+
heap_assert(block->content.signature == HEAP_ENTRY_SIGNATURE,
263+
"heap_prev_block, invalid signature");
264+
}
265+
return block;
250266
}
251267

252268
static inline union heap_entry *heap_push_back(union heap_entry *olast,
@@ -257,7 +273,8 @@ static inline union heap_entry *heap_push_back(union heap_entry *olast,
257273

258274
olast->content.state = HEAP_BLOCK_FREE;
259275
olast->content.size = new_size;
260-
union heap_entry *nlast = heap_next_block(olast);
276+
277+
union heap_entry *nlast = heap_next_block(olast, 0);
261278

262279
benchmark_heap_area =
263280
max(benchmark_heap_area, (int)nlast - (int)_heap_start);
@@ -271,6 +288,7 @@ static inline union heap_entry *heap_push_back(union heap_entry *olast,
271288
nlast->content.state = HEAP_BLOCK_LAST;
272289
nlast->content.size = HEAP_HEADER_SIZE;
273290
nlast->content.prev_size = new_size;
291+
nlast->content.signature = HEAP_ENTRY_SIGNATURE;
274292
return olast;
275293
}
276294

@@ -293,12 +311,14 @@ static inline union heap_entry *heap_freeblock_split(union heap_entry *node,
293311
return node;
294312
}
295313

296-
union heap_entry *out_block = heap_next_block(node);
314+
union heap_entry *out_block = heap_next_block(node, 1);
297315
node->content.size = first_size;
298-
union heap_entry *second = heap_next_block(node);
316+
317+
union heap_entry *second = heap_next_block(node, 0);
299318
second->content.state = second->content.state;
300319
second->content.size = second_block_size;
301320
second->content.prev_size = node->content.size;
321+
second->content.signature = HEAP_ENTRY_SIGNATURE;
302322

303323
out_block->content.prev_size = second->content.size;
304324
return node;
@@ -314,8 +334,9 @@ static inline union heap_entry *heap_freeblocks_merge(union heap_entry *node) {
314334
// after : [prev] [ node + next] OR
315335
// after : [prev + node + next]
316336

317-
union heap_entry *prev = heap_prev_block(node);
318-
union heap_entry *next = heap_next_block(node);
337+
union heap_entry *prev = heap_prev_block(node, 1);
338+
339+
union heap_entry *next = heap_next_block(node, 1);
319340
if (prev->content.state == HEAP_BLOCK_FREE) {
320341
// merge
321342
prev->content.size += node->content.size;
@@ -324,7 +345,8 @@ static inline union heap_entry *heap_freeblocks_merge(union heap_entry *node) {
324345
}
325346
if (next->content.state == HEAP_BLOCK_FREE) {
326347
// merge
327-
union heap_entry *next_2 = heap_next_block(next);
348+
349+
union heap_entry *next_2 = heap_next_block(next, 1);
328350
node->content.size += next->content.size;
329351
next_2->content.prev_size = node->content.size;
330352
}
@@ -351,7 +373,8 @@ static inline union heap_entry *heap_get_free_block(size_t new_size) {
351373
#endif
352374
}
353375
}
354-
block = heap_next_block(block);
376+
377+
block = heap_next_block(block, 1);
355378
}
356379
if (most_appropriate_block == NULL) {
357380
return heap_push_back(block, new_size);

0 commit comments

Comments
 (0)