diff --git a/py/obj.h b/py/obj.h index 5bf5352a1e..35c98d3714 100644 --- a/py/obj.h +++ b/py/obj.h @@ -539,3 +539,5 @@ bool mp_seq_cmp_bytes(int op, const byte *data1, uint len1, const byte *data2, u bool mp_seq_cmp_objs(int op, const mp_obj_t *items1, uint len1, const mp_obj_t *items2, uint len2); mp_obj_t mp_seq_index_obj(const mp_obj_t *items, uint len, uint n_args, const mp_obj_t *args); mp_obj_t mp_seq_count_obj(const mp_obj_t *items, uint len, mp_obj_t value); +// Helper to clear stale pointers from allocated, but unused memory, to preclude GC problems +#define mp_seq_clear(start, len, alloc_len, item_sz) memset((byte*)(start) + (len) * (item_sz), 0, ((alloc_len) - (len)) * (item_sz)) diff --git a/py/objarray.c b/py/objarray.c index ce107ddf25..ea37655762 100644 --- a/py/objarray.c +++ b/py/objarray.c @@ -125,6 +125,7 @@ STATIC mp_obj_t array_append(mp_obj_t self_in, mp_obj_t arg) { // TODO: alloc policy self->free = 8; self->items = m_realloc(self->items, item_sz * self->len, item_sz * (self->len + self->free)); + mp_seq_clear(self->items, self->len + 1, self->len + self->free, item_sz); } mp_binary_set_val_array(self->typecode, self->items, self->len++, arg); self->free--; diff --git a/py/objlist.c b/py/objlist.c index 6de07cf578..0c55f524da 100644 --- a/py/objlist.c +++ b/py/objlist.c @@ -163,6 +163,7 @@ mp_obj_t mp_obj_list_append(mp_obj_t self_in, mp_obj_t arg) { if (self->len >= self->alloc) { self->items = m_renew(mp_obj_t, self->items, self->alloc, self->alloc * 2); self->alloc *= 2; + mp_seq_clear(self->items, self->len + 1, self->alloc, sizeof(*self->items)); } self->items[self->len++] = arg; return mp_const_none; // return None, as per CPython @@ -178,6 +179,7 @@ STATIC mp_obj_t list_extend(mp_obj_t self_in, mp_obj_t arg_in) { // TODO: use alloc policy for "4" self->items = m_renew(mp_obj_t, self->items, self->alloc, self->len + arg->len + 4); self->alloc = self->len + arg->len + 4; + mp_seq_clear(self->items, self->len + arg->len, self->alloc, sizeof(*self->items)); } memcpy(self->items + self->len, arg->items, sizeof(mp_obj_t) * arg->len); @@ -199,6 +201,8 @@ STATIC mp_obj_t list_pop(uint n_args, const mp_obj_t *args) { mp_obj_t ret = self->items[index]; self->len -= 1; memcpy(self->items + index, self->items + index + 1, (self->len - index) * sizeof(mp_obj_t)); + // Clear stale pointer from slot which just got freed to prevent GC issues + self->items[self->len] = MP_OBJ_NULL; if (self->alloc > LIST_MIN_ALLOC && self->alloc > 2 * self->len) { self->items = m_renew(mp_obj_t, self->items, self->alloc, self->alloc/2); self->alloc /= 2; @@ -253,6 +257,7 @@ STATIC mp_obj_t list_clear(mp_obj_t self_in) { self->len = 0; self->items = m_renew(mp_obj_t, self->items, self->alloc, LIST_MIN_ALLOC); self->alloc = LIST_MIN_ALLOC; + mp_seq_clear(self->items, 0, self->alloc, sizeof(*self->items)); return mp_const_none; } @@ -368,6 +373,7 @@ void mp_obj_list_init(mp_obj_list_t *o, uint n) { o->alloc = n < LIST_MIN_ALLOC ? LIST_MIN_ALLOC : n; o->len = n; o->items = m_new(mp_obj_t, o->alloc); + mp_seq_clear(o->items, n, o->alloc, sizeof(*o->items)); } STATIC mp_obj_list_t *list_new(uint n) {