forked from esp8266/Arduino
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathumm_integrity.c
137 lines (118 loc) · 4.23 KB
/
umm_integrity.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
#if defined(BUILD_UMM_MALLOC_C)
/* integrity check (UMM_INTEGRITY_CHECK) {{{ */
#if defined(UMM_INTEGRITY_CHECK)
#include <stdint.h>
#include <stdbool.h>
/*
* Perform integrity check of the whole heap data. Returns 1 in case of
* success, 0 otherwise.
*
* First of all, iterate through all free blocks, and check that all backlinks
* match (i.e. if block X has next free block Y, then the block Y should have
* previous free block set to X).
*
* Additionally, we check that each free block is correctly marked with
* `UMM_FREELIST_MASK` on the `next` pointer: during iteration through free
* list, we mark each free block by the same flag `UMM_FREELIST_MASK`, but
* on `prev` pointer. We'll check and unmark it later.
*
* Then, we iterate through all blocks in the heap, and similarly check that
* all backlinks match (i.e. if block X has next block Y, then the block Y
* should have previous block set to X).
*
* But before checking each backlink, we check that the `next` and `prev`
* pointers are both marked with `UMM_FREELIST_MASK`, or both unmarked.
* This way, we ensure that the free flag is in sync with the free pointers
* chain.
*/
bool umm_integrity_check(void) {
UMM_CRITICAL_DECL(id_integrity);
bool ok = true;
uint16_t prev;
uint16_t cur;
UMM_CHECK_INITIALIZED();
/* Iterate through all free blocks */
prev = 0;
UMM_CRITICAL_ENTRY(id_integrity);
umm_heap_context_t *_context = umm_get_current_heap();
while (1) {
cur = UMM_NFREE(prev);
/* Check that next free block number is valid */
if (cur >= UMM_NUMBLOCKS) {
DBGLOG_FUNCTION("heap integrity broken: too large next free num: %d "
"(in block %d, addr 0x%08x)\n", cur, prev,
DBGLOG_32_BIT_PTR(&UMM_NBLOCK(prev)));
ok = false;
goto clean;
}
if (cur == 0) {
/* No more free blocks */
break;
}
/* Check if prev free block number matches */
if (UMM_PFREE(cur) != prev) {
DBGLOG_FUNCTION("heap integrity broken: free links don't match: "
"%d -> %d, but %d -> %d\n",
prev, cur, cur, UMM_PFREE(cur));
ok = false;
goto clean;
}
UMM_PBLOCK(cur) |= UMM_FREELIST_MASK;
prev = cur;
}
/* Iterate through all blocks */
prev = 0;
while (1) {
cur = UMM_NBLOCK(prev) & UMM_BLOCKNO_MASK;
/* Check that next block number is valid */
if (cur >= UMM_NUMBLOCKS) {
DBGLOG_FUNCTION("heap integrity broken: too large next block num: %d "
"(in block %d, addr 0x%08x)\n", cur, prev,
DBGLOG_32_BIT_PTR(&UMM_NBLOCK(prev)));
ok = false;
goto clean;
}
if (cur == 0) {
/* No more blocks */
break;
}
/* make sure the free mark is appropriate, and unmark it */
if ((UMM_NBLOCK(cur) & UMM_FREELIST_MASK)
!= (UMM_PBLOCK(cur) & UMM_FREELIST_MASK)) {
DBGLOG_FUNCTION("heap integrity broken: mask wrong at addr 0x%08x: n=0x%x, p=0x%x\n",
DBGLOG_32_BIT_PTR(&UMM_NBLOCK(cur)),
(UMM_NBLOCK(cur) & UMM_FREELIST_MASK),
(UMM_PBLOCK(cur) & UMM_FREELIST_MASK));
ok = false;
goto clean;
}
/* make sure the block list is sequential */
if (cur <= prev) {
DBGLOG_FUNCTION("heap integrity broken: next block %d is before prev this one "
"(in block %d, addr 0x%08x)\n", cur, prev,
DBGLOG_32_BIT_PTR(&UMM_NBLOCK(prev)));
ok = false;
goto clean;
}
/* unmark */
UMM_PBLOCK(cur) &= UMM_BLOCKNO_MASK;
/* Check if prev block number matches */
if (UMM_PBLOCK(cur) != prev) {
DBGLOG_FUNCTION("heap integrity broken: block links don't match: "
"%d -> %d, but %d -> %d\n",
prev, cur, cur, UMM_PBLOCK(cur));
ok = false;
goto clean;
}
prev = cur;
}
clean:
UMM_CRITICAL_EXIT(id_integrity);
if (!ok) {
UMM_HEAP_CORRUPTION_CB();
}
return ok;
}
#endif
/* }}} */
#endif // defined(BUILD_UMM_MALLOC_C)