Port, board and hardware
Unix port on Linux ARM64.
MicroPython version
MicroPython a129b2fba1 on 2026-10-10; linux [GCC 14.2.0] version (a129b2fba1a3348088c94d0462eef16d20874dea)
Summary
struct.pack_into and stream readinto obtain a writable buffer pointer before converting a user object to an integer. The conversion callback can resize the bytearray, after which the operation writes through the old pointer.
Build: VARIANT=coverage with the repository's official ASan flags: -fsanitize=address --param asan-use-after-return=0 -DMP_ASAN=1.
Reproduction
struct.pack_into writes through a pointer invalidated by __int__
import struct
buf = bytearray(8)
victim = None
class Evil:
def __int__(self):
global buf, victim
buf.extend(b"B" * 1024) # reallocates and frees the original data pointer
victim = [123] # list items array often reuses the freed block
return 0
struct.pack_into('<I', buf, 0, Evil())
print(victim[0])
Observed: SUMMARY: AddressSanitizer: SEGV ../../py/obj.c:574 in mp_obj_subscr
Complete ASan output
AddressSanitizer:DEADLYSIGNAL
=================================================================
==58==ERROR: AddressSanitizer: SEGV on unknown address 0xaaaa00000012 (pc 0xaaaaafd005e8 bp 0xffffc42899f0 sp 0xffffc42899f0 T0)
==58==The signal is caused by a READ memory access.
#0 0xaaaaafd005e8 in mp_obj_subscr ../../py/obj.c:574
#1 0xaaaaafd5e560 in mp_execute_bytecode ../../py/vm.c:462
#2 0xaaaaafd10c64 in fun_bc_call ../../py/objfun.c:294
#3 0xaaaaafcf0618 in mp_call_function_n_kw ../../py/runtime.c:719
#4 0xaaaaafcf4720 in mp_call_function_0 ../../py/runtime.c:693
#5 0xaaaaafe7a60c in parse_compile_execute ../../shared/runtime/pyexec.c:137
#6 0xaaaaafe7b774 in pyexec_file ../../shared/runtime/pyexec.c:739
#7 0xaaaaafe703f0 in do_file /src/ports/unix/main.c:269
#8 0xaaaaafe71a18 in main_ /src/ports/unix/main.c:692
#9 0xaaaaafe72000 in main /src/ports/unix/main.c:452
#10 0xffffbb262258 (/lib/aarch64-linux-gnu/libc.so.6+0x22258) (BuildId: 4c1eca4527d1163b2dde55860b69f270158febb4)
#11 0xffffbb262338 in __libc_start_main (/lib/aarch64-linux-gnu/libc.so.6+0x22338) (BuildId: 4c1eca4527d1163b2dde55860b69f270158febb4)
#12 0xaaaaafcaccac in _start (/workspace/work/micropython-current/ports/unix/build-asan-linux-official/micropython+0x19ccac) (BuildId: d745232daadafece431463287d3aa5e506209b85)
AddressSanitizer can not provide additional info.
SUMMARY: AddressSanitizer: SEGV ../../py/obj.c:574 in mp_obj_subscr
==58==ABORTING
Stream readinto writes through a pointer invalidated by limit conversion
import io
buf = bytearray(64)
bio = io.BytesIO(b"A" * 128)
class Limit:
def __int__(self):
global victim
buf.extend(b"B" * 128) # grow buffer so mp_get_buffer's pointer goes stale
victim = [1, 2, 3, 4] # reuse the freed chunk
return 64
bio.readinto(buf, Limit()) # mp_get_buffer + mp_obj_get_int reenter
print(victim)
Observed: SUMMARY: AddressSanitizer: SEGV ../../py/obj.c:128 in mp_obj_print_helper
Complete ASan output
AddressSanitizer:DEADLYSIGNAL
=================================================================
==85==ERROR: AddressSanitizer: SEGV on unknown address 0x28283828282829 (pc 0xaaaac457d7f0 bp 0xffffd0c837d0 sp 0xffffd0c837d0 T0)
==85==The signal is caused by a READ memory access.
#0 0xaaaac457d7f0 in mp_obj_print_helper ../../py/obj.c:128
#1 0xaaaac45cacf4 in mp_builtin_print ../../py/modbuiltins.c:424
#2 0xaaaac45909c0 in fun_builtin_var_call ../../py/objfun.c:118
#3 0xaaaac4570618 in mp_call_function_n_kw ../../py/runtime.c:719
#4 0xaaaac45d7c20 in mp_execute_bytecode ../../py/vm.c:984
#5 0xaaaac4590c64 in fun_bc_call ../../py/objfun.c:294
#6 0xaaaac4570618 in mp_call_function_n_kw ../../py/runtime.c:719
#7 0xaaaac4574720 in mp_call_function_0 ../../py/runtime.c:693
#8 0xaaaac46fa60c in parse_compile_execute ../../shared/runtime/pyexec.c:137
#9 0xaaaac46fb774 in pyexec_file ../../shared/runtime/pyexec.c:739
#10 0xaaaac46f03f0 in do_file /src/ports/unix/main.c:269
#11 0xaaaac46f1a18 in main_ /src/ports/unix/main.c:692
#12 0xaaaac46f2000 in main /src/ports/unix/main.c:452
#13 0xffff9fa62258 (/lib/aarch64-linux-gnu/libc.so.6+0x22258) (BuildId: 4c1eca4527d1163b2dde55860b69f270158febb4)
#14 0xffff9fa62338 in __libc_start_main (/lib/aarch64-linux-gnu/libc.so.6+0x22338) (BuildId: 4c1eca4527d1163b2dde55860b69f270158febb4)
#15 0xaaaac452ccac in _start (/workspace/work/micropython-current/ports/unix/build-asan-linux-official/micropython+0x19ccac) (BuildId: d745232daadafece431463287d3aa5e506209b85)
AddressSanitizer can not provide additional info.
SUMMARY: AddressSanitizer: SEGV ../../py/obj.c:128 in mp_obj_print_helper
==85==ABORTING
Expected behaviour
The operation should complete safely or raise a Python exception without terminating the interpreter.
Observed behaviour
Each reproducer terminates the interpreter under AddressSanitizer in 3/3 runs.
Additional information
No exploitability claim is intended; these are interpreter robustness failures reachable from Python code.
Tracking references: MicroPython-18, MicroPython-27.
Port, board and hardware
Unix port on Linux ARM64.
MicroPython version
MicroPython a129b2fba1 on 2026-10-10; linux [GCC 14.2.0] version(a129b2fba1a3348088c94d0462eef16d20874dea)Summary
struct.pack_intoand streamreadintoobtain a writable buffer pointer before converting a user object to an integer. The conversion callback can resize the bytearray, after which the operation writes through the old pointer.Build:
VARIANT=coveragewith the repository's official ASan flags:-fsanitize=address --param asan-use-after-return=0 -DMP_ASAN=1.Reproduction
struct.pack_intowrites through a pointer invalidated by__int__Observed:
SUMMARY: AddressSanitizer: SEGV ../../py/obj.c:574 in mp_obj_subscrComplete ASan output
Stream
readintowrites through a pointer invalidated by limit conversionObserved:
SUMMARY: AddressSanitizer: SEGV ../../py/obj.c:128 in mp_obj_print_helperComplete ASan output
Expected behaviour
The operation should complete safely or raise a Python exception without terminating the interpreter.
Observed behaviour
Each reproducer terminates the interpreter under AddressSanitizer in 3/3 runs.
Additional information
No exploitability claim is intended; these are interpreter robustness failures reachable from Python code.
Tracking references: MicroPython-18, MicroPython-27.