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_slice->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)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy