← index #17941Issue #18641
Related · high · value 2.297
QUERY · ISSUE

Segmentation fault in array sorting with GC interaction

openby MaksimFengopened 2025-08-17updated 2025-08-17
bug

Port, board and/or hardware

unix port

MicroPython version

v1.26.0-46-g1588c455c on 2025-08-17

Reproduction

  1. Create a comparison class that modifies the array being sorted
  2. Call gc.collect() within the comparison function
  3. Attempt to sort the array
import gc
class check:
    def __init__(self, arr1, arr2):
        self.arr1 = arr1
        self.arr2 = arr2
    
    def __lt__(self, other):
        # Clear one array, modify another
        self.arr1.clear()
        self.arr2.extend([777] * 5)
        gc.collect()
        self.arr2.clear()
        return True

d1 = []
d2 = []
contaminators = [check(d1, d2) for _ in range(3)]
d1.extend(contaminators)
d2.extend(contaminators)
d1.sort()

Expected behaviour

The code should either:

  1. Raise a Python exception (e.g., RuntimeError, ValueError)
  2. Handle the edge case gracefully without crashing

Observed behaviour

MicroPython crashes with a segmentation fault when array.clear() and gc.collect() are called within comparison functions during array sorting operations. This appears to be caused by a NULL pointer dereference in py/obj.c at line 61.

AddressSanitizer:DEADLYSIGNAL
=================================================================
==1758094==ERROR: AddressSanitizer: SEGV on unknown address 0x000000000000 (pc 0x64c7a2bd4b4b bp 0x000000000000 sp 0x7fffd2494c90 T0)
==1758094==The signal is caused by a READ memory access.
==1758094==Hint: address points to the zero page.
    #0 0x64c7a2bd4b4b in mp_obj_get_type ../../py/obj.c:61
    #1 0x64c7a2bccdac in mp_binary_op ../../py/runtime.c:640
    #2 0x64c7a2bf012d in mp_quicksort ../../py/objlist.c:288
    #3 0x64c7a2bf0405 in mp_obj_list_sort ../../py/objlist.c:330
    #4 0x64c7a2be8192 in fun_builtin_var_call ../../py/objfun.c:118
    #5 0x64c7a2bc6984 in mp_call_function_n_kw ../../py/runtime.c:727
    #6 0x64c7a2bc7547 in mp_call_method_n_kw ../../py/runtime.c:743
    #7 0x64c7a2c2b5cd in mp_execute_bytecode ../../py/vm.c:1069
    #8 0x64c7a2be85a9 in fun_bc_call ../../py/objfun.c:295
    #9 0x64c7a2bc6984 in mp_call_function_n_kw ../../py/runtime.c:727
    #10 0x64c7a2bcadb3 in mp_call_function_0 ../../py/runtime.c:701
    #11 0x64c7a2d4adc6 in execute_from_lexer /home/kai/project/hypothesmith/micropython/ports/unix/main.c:162
    #12 0x64c7a2d4aedc in do_file /home/kai/project/hypothesmith/micropython/ports/unix/main.c:311
    #13 0x64c7a2d4c825 in main_ /home/kai/project/hypothesmith/micropython/ports/unix/main.c:728
    #14 0x64c7a2d4ce63 in main /home/kai/project/hypothesmith/micropython/ports/unix/main.c:494
    #15 0x7b69f7c2a3b7 in __libc_start_call_main ../sysdeps/nptl/libc_start_call_main.h:58
    #16 0x7b69f7c2a47a in __libc_start_main_impl ../csu/libc-start.c:360
    #17 0x64c7a2b69734 in _start (micropython/ports/unix/build-coverage/micropython+0x1a8734) (BuildId: bb66085681e6f5a07b78002d60ef2779d5eae802)

The AddressSanitizer output shows a NULL pointer dereference at address 0x000000000000. The call stack reveals:

mp_quicksort (objlist.c:288) - Sorting algorithm in progress
mp_binary_op (runtime.c:640) - Calls comparison operation
mp_obj_get_type (obj.c:61) - CRASH HERE - Dereferencing NULL pointer

Additional Information

No, I've provided everything above.

Code of Conduct

Yes, I agree

CANDIDATE · ISSUE

Segmentation Fault (NULL Pointer Dereference) in mp_obj_get_type via mp_binary_op

closedby oneafteropened 2026-01-05updated 2026-01-10

Port, board and/or hardware

unix

MicroPython version

v1.27.0 and master-branch

Issue Report

Description

We discovered a Segmentation Fault vulnerability in MicroPython. The crash occurs within mp_obj_get_type when it is called by mp_binary_op.

The ASAN report indicates a READ memory access violation at address 0x000000000000, confirming a NULL Pointer Dereference. The runtime attempts to retrieve the type of a NULL object pointer during a binary operation.

Environment

  • OS: Linux x86_64
  • Complier: gcc 11.5.0
  • Tools: AddressSanitizer
  • Affected Version: master branch
  • Build Configure:
make CFLAGS_EXTRA="-fsanitize=address --param asan-use-after-return=0" \
       LDFLAGS_EXTRA="-fsanitize=address --param asan-use-after-return=0" \
       CC=gcc STRIP= -j$(nproc)

Vulnerability Details

  • Target: MicroPython (Unix Port)
  • Vulnerability Type: Segmentation Fault (NULL Pointer Dereference)
  • Function: mp_obj_get_type (called from mp_binary_op)
  • Location: py/obj.c:61
  • Root Cause Analysis: The crash occurs when the VM executes a binary operation (e.g., addition, subtraction, or comparison). The stack trace shows:
#0 0x56082b58782e in mp_obj_get_type ../../py/obj.c:61
#1 0x56082b584a14 in mp_binary_op ../../py/runtime.c:625

mp_binary_op typically calls mp_obj_get_type on its operands (LHS or RHS) to dispatch the operation to the correct type handler. The crash at 0x0 implies that one of the operands passed to mp_binary_op is NULL. This suggests that a previous bytecode instruction or internal routine pushed a NULL pointer onto the stack (or failed to initialize an object), which was then consumed by the binary operator.

Reproduce

  1. Compile the micropython with gcc compiler and AddressSanitizer enabled
  2. Run the micropython with the POC input.

Proof of Concept:

@micropython.native
def f(n):
    while n:v+=0
f(2)

ASAN report

AddressSanitizer:DEADLYSIGNAL
=================================================================
==36398==ERROR: AddressSanitizer: SEGV on unknown address 0x000000000000 (pc 0x56082b58782e bp 0x000000000003 sp 0x7fff63474370 T0)
==36398==The signal is caused by a READ memory access.
==36398==Hint: address points to the zero page.
    #0 0x56082b58782e in mp_obj_get_type ../../py/obj.c:61
    #1 0x56082b584a14 in mp_binary_op ../../py/runtime.c:625
    #2 0x7f08871c70fd  (<unknown module>)

AddressSanitizer can not provide additional info.
SUMMARY: AddressSanitizer: SEGV ../../py/obj.c:61 in mp_obj_get_type
==36398==ABORTING

What does this issue allow an attacker to do?

Denial of Service (DoS). An attacker can crash the MicroPython interpreter by executing a specific script that triggers a binary operation on an invalid (NULL) object state.

How does the attacker exploit this issue?

The attacker provides a Python script that likely contains a sequence of operations leading to an invalid object state on the stack. When a binary operator (like +, -, or a comparison) is subsequently executed, the VM attempts to inspect the type of this NULL object, triggering the segmentation fault.

Code of Conduct

Yes, I agree

Keyboard

j / / n
next pair
k / / p
previous pair
1 / / h
show query pane
2 / / l
show candidate pane
c
copy suggested comment
r
toggle reasoning
g i
go to index
?
show this help
esc
close overlays

press ? or esc to close

copied