Reentrant equality can invalidate list storage in count and comparison

Abierto
#19,753 0 comentarios 0 reacciones 0 asignados Ver en GitHub

Los mantenedores suelen responder en 1 día

Nadie ha tomado este issue todavía.

Evaluación

Dificultad
4/5
Tiempo estimado
3-5 días
Aptitud para principiantes
30/100
Tipo de issue
Error
Claridad
Bastante claro
Estado de actividad
Activo
Stack tecnológico
c, python
Área
backend

Línea de trabajo

Start with the two reproducers in the issue, run under the ASan build from the unix port. The crashes go through list_count in py/objlist.c and mp_seq_count_obj in py/sequence.c, and through list_binary_op and mp_seq_cmp_objs for the comparison case, with mp_obj_equal_not_equal in py/obj.c at the crash site. Done means both scripts finish or raise a Python exception under ASan, without a SEGV. The fix needs to re-check the list's length and storage after each user eq call.

Escrito por el modelo de indexación a partir del texto del issue.

Descripción

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

List operations retain element storage and bounds across calls to user-defined __eq__. If the callback clears or shrinks a participating list, the operation later reads invalid elements.

Build: VARIANT=coverage with the repository's official ASan flags: -fsanitize=address --param asan-use-after-return=0 -DMP_ASAN=1.

Reproduction

list.count continues after __eq__ clears the searched list
class Boom:
    def __eq__(self, other):
        # Re-entrant mutation: free the list backing store while count() still uses it.
        lst.clear()
        return False


lst = [Boom(), 1]
lst.count(0)

Observed: SUMMARY: AddressSanitizer: SEGV ../../py/obj.c:233 in mp_obj_equal_not_equal

Complete ASan output
AddressSanitizer:DEADLYSIGNAL
=================================================================
==37==ERROR: AddressSanitizer: SEGV on unknown address 0x000000000000 (pc 0xaaaab110fbc4 bp 0xffffccce3020 sp 0xffffccce3020 T0)
==37==The signal is caused by a READ memory access.
==37==Hint: address points to the zero page.
    #0 0xaaaab110fbc4 in mp_obj_equal_not_equal ../../py/obj.c:233
    #1 0xaaaab111057c in mp_obj_equal ../../py/obj.c:303
    #2 0xaaaab11504b0 in mp_seq_count_obj ../../py/sequence.c:209
    #3 0xaaaab1127e40 in list_count ../../py/objlist.c:369
    #4 0xaaaab11204cc in fun_builtin_2_call ../../py/objfun.c:82
    #5 0xaaaab1100618 in mp_call_function_n_kw ../../py/runtime.c:719
    #6 0xaaaab1100fbc in mp_call_method_n_kw ../../py/runtime.c:735
    #7 0xaaaab11678f4 in mp_execute_bytecode ../../py/vm.c:1069
    #8 0xaaaab1120c64 in fun_bc_call ../../py/objfun.c:294
    #9 0xaaaab1100618 in mp_call_function_n_kw ../../py/runtime.c:719
    #10 0xaaaab1104720 in mp_call_function_0 ../../py/runtime.c:693
    #11 0xaaaab128a60c in parse_compile_execute ../../shared/runtime/pyexec.c:137
    #12 0xaaaab128b774 in pyexec_file ../../shared/runtime/pyexec.c:739
    #13 0xaaaab12803f0 in do_file /src/ports/unix/main.c:269
    #14 0xaaaab1281a18 in main_ /src/ports/unix/main.c:692
    #15 0xaaaab1282000 in main /src/ports/unix/main.c:452
    #16 0xffffb1a62258  (/lib/aarch64-linux-gnu/libc.so.6+0x22258) (BuildId: 4c1eca4527d1163b2dde55860b69f270158febb4)
    #17 0xffffb1a62338 in __libc_start_main (/lib/aarch64-linux-gnu/libc.so.6+0x22338) (BuildId: 4c1eca4527d1163b2dde55860b69f270158febb4)
    #18 0xaaaab10bccac 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:233 in mp_obj_equal_not_equal
==37==ABORTING
List comparison continues after __eq__ shrinks the right-hand list
class Boom:
    def __eq__(self, other):
        rhs.pop()
        return True

rhs = [Boom(), 1]
lhs = [Boom(), 1]
lhs == rhs

Observed: SUMMARY: AddressSanitizer: SEGV ../../py/obj.c:247 in mp_obj_equal_not_equal

Complete ASan output
AddressSanitizer:DEADLYSIGNAL
=================================================================
==70==ERROR: AddressSanitizer: SEGV on unknown address 0x000000000000 (pc 0xaaaadda4fc28 bp 0xffffec615a50 sp 0xffffec615a50 T0)
==70==The signal is caused by a READ memory access.
==70==Hint: address points to the zero page.
    #0 0xaaaadda4fc28 in mp_obj_equal_not_equal ../../py/obj.c:247
    #1 0xaaaadda5057c in mp_obj_equal ../../py/obj.c:303
    #2 0xaaaadda90068 in mp_seq_cmp_objs ../../py/sequence.c:153
    #3 0xaaaadda69648 in list_binary_op ../../py/objlist.c:152
    #4 0xaaaadda5030c in mp_obj_equal_not_equal ../../py/obj.c:280
    #5 0xaaaadda45594 in mp_binary_op ../../py/runtime.c:403
    #6 0xaaaaddaa562c in mp_execute_bytecode ../../py/vm.c:1302
    #7 0xaaaadda60c64 in fun_bc_call ../../py/objfun.c:294
    #8 0xaaaadda40618 in mp_call_function_n_kw ../../py/runtime.c:719
    #9 0xaaaadda44720 in mp_call_function_0 ../../py/runtime.c:693
    #10 0xaaaaddbca60c in parse_compile_execute ../../shared/runtime/pyexec.c:137
    #11 0xaaaaddbcb774 in pyexec_file ../../shared/runtime/pyexec.c:739
    #12 0xaaaaddbc03f0 in do_file /src/ports/unix/main.c:269
    #13 0xaaaaddbc1a18 in main_ /src/ports/unix/main.c:692
    #14 0xaaaaddbc2000 in main /src/ports/unix/main.c:452
    #15 0xffff7f062258  (/lib/aarch64-linux-gnu/libc.so.6+0x22258) (BuildId: 4c1eca4527d1163b2dde55860b69f270158febb4)
    #16 0xffff7f062338 in __libc_start_main (/lib/aarch64-linux-gnu/libc.so.6+0x22338) (BuildId: 4c1eca4527d1163b2dde55860b69f270158febb4)
    #17 0xaaaadd9fccac 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:247 in mp_obj_equal_not_equal
==70==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-11, MicroPython-22.

Lenguaje dominante
C
Estrellas
22.2k
Forks
9.1k
Merge medio
6 d 8 h
PR fusionados (30 d)
33

Preparar el entorno

Primeros pasos

  1. Lee el issue completo y luego la guía de contribución del proyecto.
  2. Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
  3. Haz un fork del repositorio y trabaja en una rama.
  4. Abre un pull request que haga referencia al número del issue.

Más de micropython/micropython

Todos los issues de micropython/micropython

Issues similares

Más issues de C

Recibe los nuevos issues en tu correo

Un resumen breve de issues de GitHub para principiantes.