← index #17848PR #18753
Duplicate · high · value 0.218
QUERY · ISSUE

vfs_blockdev: crash when readblocks inappropriately enlarges buf via slice assignment

openby jepleropened 2025-08-06updated 2025-08-06
bug

Port, board and/or hardware

unix port, coverage variant, x86_64 linux

MicroPython version

MicroPython v1.26.0-preview.524.g255d74b5a8 on 2025-08-06; linux [GCC 12.2.0] version

Reproduction

try:
    import os, vfs

    vfs.VfsFat
except (ImportError, AttributeError):
    print("SKIP")
    raise SystemExit


class RAMBDevSparse:
    SEC_SIZE = 512

    def __init__(self, blocks):
        print(blocks)
        self.blocks = blocks
        self.data = {}

    def readblocks(self, n, buf):
        print(f"readblocks {n} {buf}")
        buf[:] = bytearray(1 + self.SEC_SIZE)

    def ioctl(self, op, arg):
        if op == 4:
            return self.SEC_SIZE

bdev = RAMBDevSparse(40)
fs = vfs.VfsFat(bdev)

Expected behaviour

Some kind of Python exception occurs. This might require a new notion that some buffers may not be resized (but are otherwise mutable).

Observed behaviour

An assertion error occurs:

micropython: ../../py/gc.c:1047: gc_realloc: Assertion `area' failed.

Program received signal SIGABRT, Aborted.

The stack trace includes

#6  0x00005555555ba9ad in gc_realloc (ptr_in=0x7ffff7c31e70, n_bytes=n_bytes@entry=513, 
    allow_move=allow_move@entry=true) at ../../py/gc.c:1047
#7  0x00005555555b85fe in m_realloc (ptr=<optimized out>, old_num_bytes=512, 
    new_num_bytes=513) at ../../py/malloc.c:141
#8  0x00005555555f5918 in array_subscr (self_in=0x7fffffffd780, index_in=<optimized out>, 
    value=<optimized out>) at ../../py/objarray.c:519
#9  0x00005555555f4ae6 in mp_obj_subscr (base=0x7fffffffd780, 
    index=index@entry=0x7fffffffd560, value=0x7ffff7c30f80) at ../../py/obj.c:575
#10 0x00005555556217e7 in build_slice_stack_allocated (op=<optimized out>, 
    sp=sp@entry=0x7fffffffd6b0, step=step@entry=0x6) at ../../py/vm.c:207
#11 0x0000555555626950 in mp_execute_bytecode (code_state=code_state@entry=0x7fffffffd670, 
    inject_exc=<optimized out>, inject_exc@entry=0x0) at ../../py/vm.c:876
#12 0x00005555555fe288 in fun_bc_call (self_in=0x7ffff7c30f40, n_args=3, n_kw=0, 
    args=0x7ffff7c31dc0) at ../../py/objfun.c:295
#13 0x00005555555ea61f in mp_call_function_n_kw (fun_in=0x7ffff7c30f40, n_args=3, 
    n_kw=n_kw@entry=0, args=0x7ffff7c31dc0) at ../../py/runtime.c:727
#14 0x00005555555eab59 in mp_call_method_n_kw (n_args=n_args@entry=2, n_kw=n_kw@entry=0, 
    args=<optimized out>) at ../../py/runtime.c:743
#15 0x00005555556437c8 in mp_vfs_blockdev_call_rw (args=<optimized out>, 
    block_num=<optimized out>, block_off=block_off@entry=0, len=<optimized out>, 
    buf=buf@entry=0x7ffff7c31e70, n_args=n_args@entry=2) at ../../extmod/vfs_blockdev.c:56

Additional Information

Found via fuzzing and manually minimized.

Code of Conduct

Yes, I agree

CANDIDATE · PULL REQUEST

extmod/vfs: Add buffer resize check to prevent memory corruption

closedby bob10042opened 2026-01-30updated 2026-01-31

Fixes #17848

Problem:
mp_vfs_blockdev_call_rw() creates a bytearray wrapper around a fixed-size buffer. If user's readblocks()/writeblocks() implementation resizes the buffer (e.g., buf[:] = larger_data), it triggers gc_realloc() on the fixed buffer, causing assertion failure or memory corruption.

Solution:

  • Verify buffer length hasn't changed after calling user block device method
  • Raise ValueError if user code attempted to resize the buffer
  • Prevents memory corruption from invalid buffer manipulation

Impact:

  • Prevents crashes from incorrectly implemented block device drivers
  • Provides clear error message for invalid operations
  • Protects against memory corruption vulnerabilities

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