Skip to content

Commit e2bc9b8

Browse files
jeplerdpgeorge
authored andcommitted
py/gc: Ensure a gap of one byte after the ATB.
Closes: adafruit#5021 Closes: micropython#7116 Signed-off-by: Jeff Epler <[email protected]>
1 parent 2490a8a commit e2bc9b8

File tree

1 file changed

+14
-7
lines changed

1 file changed

+14
-7
lines changed

py/gc.c

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,12 @@
9595
#define BLOCK_FROM_PTR(area, ptr) (((byte *)(ptr) - area->gc_pool_start) / BYTES_PER_BLOCK)
9696
#define PTR_FROM_BLOCK(area, block) (((block) * BYTES_PER_BLOCK + (uintptr_t)area->gc_pool_start))
9797

98+
// After the ATB, there must be a byte filled with AT_FREE so that gc_mark_tree
99+
// cannot erroneously conclude that a block extends past the end of the GC heap
100+
// due to bit patterns in the FTB (or first block, if finalizers are disabled)
101+
// being interpreted as AT_TAIL.
102+
#define ALLOC_TABLE_GAP_BYTE (1)
103+
98104
#if MICROPY_ENABLE_FINALISER
99105
// FTB = finaliser table byte
100106
// if set, then the corresponding block may have a finaliser
@@ -123,7 +129,8 @@ STATIC void gc_setup_area(mp_state_mem_area_t *area, void *start, void *end) {
123129
// => T = A * (1 + BLOCKS_PER_ATB / BLOCKS_PER_FTB + BLOCKS_PER_ATB * BYTES_PER_BLOCK)
124130
size_t total_byte_len = (byte *)end - (byte *)start;
125131
#if MICROPY_ENABLE_FINALISER
126-
area->gc_alloc_table_byte_len = total_byte_len * MP_BITS_PER_BYTE / (MP_BITS_PER_BYTE + MP_BITS_PER_BYTE * BLOCKS_PER_ATB / BLOCKS_PER_FTB + MP_BITS_PER_BYTE * BLOCKS_PER_ATB * BYTES_PER_BLOCK);
132+
size_t gc_alloc_table_byte_len = (total_byte_len - ALLOC_TABLE_GAP_BYTE) * MP_BITS_PER_BYTE / (MP_BITS_PER_BYTE + MP_BITS_PER_BYTE * BLOCKS_PER_ATB / BLOCKS_PER_FTB + MP_BITS_PER_BYTE * BLOCKS_PER_ATB * BYTES_PER_BLOCK);
133+
area->gc_alloc_table_byte_len = gc_alloc_table_byte_len;
127134
#else
128135
area->gc_alloc_table_byte_len = total_byte_len / (1 + MP_BITS_PER_BYTE / 2 * BYTES_PER_BLOCK);
129136
#endif
@@ -132,7 +139,7 @@ STATIC void gc_setup_area(mp_state_mem_area_t *area, void *start, void *end) {
132139

133140
#if MICROPY_ENABLE_FINALISER
134141
size_t gc_finaliser_table_byte_len = (area->gc_alloc_table_byte_len * BLOCKS_PER_ATB + BLOCKS_PER_FTB - 1) / BLOCKS_PER_FTB;
135-
area->gc_finaliser_table_start = area->gc_alloc_table_start + area->gc_alloc_table_byte_len;
142+
area->gc_finaliser_table_start = area->gc_alloc_table_start + area->gc_alloc_table_byte_len + ALLOC_TABLE_GAP_BYTE;
136143
#endif
137144

138145
size_t gc_pool_block_len = area->gc_alloc_table_byte_len * BLOCKS_PER_ATB;
@@ -143,12 +150,12 @@ STATIC void gc_setup_area(mp_state_mem_area_t *area, void *start, void *end) {
143150
assert(area->gc_pool_start >= area->gc_finaliser_table_start + gc_finaliser_table_byte_len);
144151
#endif
145152

146-
// clear ATBs
147-
memset(area->gc_alloc_table_start, 0, area->gc_alloc_table_byte_len);
148-
149153
#if MICROPY_ENABLE_FINALISER
150-
// clear FTBs
151-
memset(area->gc_finaliser_table_start, 0, gc_finaliser_table_byte_len);
154+
// clear ATBs and FTBs
155+
memset(area->gc_alloc_table_start, 0, gc_finaliser_table_byte_len + gc_alloc_table_byte_len + ALLOC_TABLE_GAP_BYTE);
156+
#else
157+
// clear ATBs
158+
memset(area->gc_alloc_table_start, 0, area->gc_alloc_table_byte_len + ALLOC_TABLE_GAP_BYTE);
152159
#endif
153160

154161
area->gc_last_free_atb_index = 0;

0 commit comments

Comments
 (0)