8000 py/objarray: Fix use-after-free if extending a slice. · micropython/micropython@7eb2a0c · GitHub
[go: up one dir, main page]

Skip to content

Commit 7eb2a0c

Browse files
committed
py/objarray: Fix use-after-free if extending a slice.
Closes #13283 Reproducing this bug and confirming the fix requires running under valgrind with GC-aware extensions. Note in default configurations with GIL this bug exists but has no impact (the free buffer won't be reused while the function is still executing, and is no longer referenced after it returns). Signed-off-by: Angus Gratton <angus@redyak.com.au>
1 parent 90e5178 commit 7eb2a0c

File tree

1 file changed

+11
-5
lines changed

1 file changed

+11
-5
lines changed

py/objarray.c

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -456,7 +456,8 @@ STATIC mp_obj_t array_subscr(mp_obj_t self_in, mp_obj_t index_in, mp_obj_t value
456456
#if MICROPY_PY_ARRAY_SLICE_ASSIGN
457457
// Assign
458458
size_t src_len;
459-
void *src_items;
459+
uint8_t *src_items;
460+
size_t src_offs = 0;
460461
size_t item_sz = mp_binary_get_size('@', o->typecode & TYPECODE_MASK, NULL);
461462
if (mp_obj_is_obj(value) && MP_OBJ_TYPE_GET_SLOT_OR_NULL(((mp_obj_base_t *)MP_OBJ_TO_PTR(value))->type, subscr) == array_subscr) {
462463
// value is array, bytearray or memoryview
@@ -469,7 +470,7 @@ STATIC mp_obj_t array_subscr(mp_obj_t self_in, mp_obj_t index_in, mp_obj_t value
469470
src_items = src_s E8A3 lice->items;
470471
#if MICROPY_PY_BUILTINS_MEMORYVIEW
471472
if (mp_obj_is_type(value, &mp_type_memoryview)) {
472-
src_items = (uint8_t *)src_items + (src_slice->memview_offset * item_sz);
473+
src_offs = src_slice->memview_offset * item_sz;
473474
}
474475
#endif
475476
} else if (mp_obj_is_type(value, &mp_type_bytes)) {
@@ -504,13 +505,18 @@ STATIC mp_obj_t array_subscr(mp_obj_t self_in, mp_obj_t index_in, mp_obj_t value
504505
// TODO: alloc policy; at the moment we go conservative
505506
o->items = m_renew(byte, o->items, (o->len + o->free) * item_sz, (o->len + len_adj) * item_sz);
506507
o->free = len_adj;
507-
dest_items = o->items;
508+
if (o->items != dest_items) { // m_renew moved o->items
509+
if (src_items == dest_items) {
510+
src_items = o->items;
511+
}
512+
dest_items = o->items;
513+
}
508514
}
509515
mp_seq_replace_slice_grow_inplace(dest_items, o->len,
510-
slice.start, slice.stop, src_items, src_len, len_adj, item_sz);
516+
slice.start, slice.stop, src_items + src_offs, src_len, len_adj, item_sz);
511517
} else {
512518
mp_seq_replace_slice_no_grow(dest_items, o->len,
513-
slice.start, slice.stop, src_items, src_len, item_sz);
519+
slice.start, slice.stop, src_items + src_offs, src_len, item_sz);
514520
// Clear "freed" elements at the end of list
515521
// TODO: This is actually only needed for typecode=='O'
516522
mp_seq_clear(dest_items, o->len + len_adj, o->len, item_sz);

0 commit comments

Comments
 (0)
0