@@ -14,6 +14,44 @@ uint8_t __aligned(8) heapmem[HEAP_SZ];
14
14
/* Heap metadata sizes */
15
15
uint8_t * heap_start , * heap_end ;
16
16
17
+ static void fill (void * mem , size_t size )
18
+ {
19
+ uint32_t * word32 = mem ;
20
+
21
+ /*
22
+ * No need to fill the entire memory block. Only touching the edges
23
+ * is sufficient to trip heap validation with off-by-one errors.
24
+ * Strictly speaking we may overflow the boundary if given size
25
+ * is not a multiple of 4 but the actual allocation is always
26
+ * rounded up to at least the next 4-byte boundary anyway.
27
+ */
28
+ if (size != 0 ) {
29
+ word32 [0 ] = 0 ;
30
+ word32 [(size - 1 )/4 ] = 0 ;
31
+ }
32
+ }
33
+
34
+ /*
35
+ * The align argument may contain a "rewind" bit.
36
+ * See comment in sys_heap_aligned_alloc().
37
+ */
38
+ static bool alignment_ok (void * ptr , size_t align )
39
+ {
40
+ uintptr_t addr = (uintptr_t )ptr ;
41
+ size_t rew ;
42
+
43
+ /* split rewind bit from alignment */
44
+ rew = (align & - align );
45
+ rew = (rew == align ) ? 0 : rew ;
46
+ align -= rew ;
47
+
48
+ /* undo the pointer rewind */
49
+ addr += rew ;
50
+
51
+ /* validate pointer alignment */
52
+ return (addr & (align - 1 )) == 0 ;
53
+ }
54
+
17
55
/* Note that this test is making whitebox assumptions about the
18
56
* behavior of the heap in order to exercise coverage of the
19
57
* underlying code: that chunk headers are 8 bytes, that heap chunks
@@ -24,25 +62,34 @@ static void check_heap_align(struct sys_heap *h,
24
62
size_t prefix , size_t align , size_t size )
25
63
{
26
64
void * p , * q , * r , * s ;
65
+ size_t suffix ;
27
66
28
67
p = sys_heap_alloc (h , prefix );
29
68
zassert_true (prefix == 0 || p != NULL , "prefix allocation failed" );
30
69
31
70
q = sys_heap_aligned_alloc (h , align , size );
32
71
zassert_true (q != NULL , "first aligned allocation failed" );
33
- zassert_true (((( uintptr_t ) q ) & ( align - 1 )) == 0 , "block not aligned" );
72
+ zassert_true (alignment_ok ( q , align ) , "block not aligned" );
34
73
35
74
r = sys_heap_aligned_alloc (h , align , size );
36
75
zassert_true (r != NULL , "second aligned allocation failed" );
37
- zassert_true (((( uintptr_t ) r ) & ( align - 1 )) == 0 , "block not aligned" );
76
+ zassert_true (alignment_ok ( r , align ) , "block not aligned" );
38
77
39
78
/* Make sure ALL the split memory goes back into the heap and
40
79
* we can allocate the full remaining suffix
41
80
*/
42
- s = sys_heap_alloc (h , (heap_end - (uint8_t * )r ) - size - 8 );
81
+ suffix = (heap_end - (uint8_t * )r ) - size - 8 ;
82
+ s = sys_heap_alloc (h , suffix );
43
83
zassert_true (s != NULL , "suffix allocation failed (%zd/%zd/%zd)" ,
44
84
prefix , align , size );
45
85
86
+ /* Touch some of the allocated memory */
87
+ fill (p , prefix );
88
+ fill (q , size );
89
+ fill (r , size );
90
+ fill (s , suffix );
91
+ zassert_true (sys_heap_validate (h ), "heap invalid" );
92
+
46
93
sys_heap_free (h , p );
47
94
sys_heap_free (h , q );
48
95
sys_heap_free (h , r );
@@ -76,8 +123,12 @@ ZTEST(lib_heap_align, test_aligned_alloc)
76
123
77
124
for (size_t align = 8 ; align < HEAP_SZ / 4 ; align *= 2 ) {
78
125
for (size_t prefix = 0 ; prefix <= align ; prefix += 8 ) {
79
- for (size_t size = 8 ; size <= align ; size += 8 ) {
126
+ for (size_t size = 4 ; size <= align ; size += 12 ) {
80
127
check_heap_align (& heap , prefix , align , size );
128
+ for (size_t rew = 4 ; rew < MIN (align , 32 ); rew *= 2 ) {
129
+ check_heap_align (& heap , prefix ,
130
+ align | rew , size );
131
+ }
81
132
}
82
133
}
83
134
}
0 commit comments