← index #17718Issue #17925
Off-topic · high · value 5.777
QUERY · ISSUE

crash in btree module

openby jepleropened 2025-07-19updated 2025-07-19
bug

Port, board and/or hardware

unix coverage build

MicroPython version

MicroPython v1.26.0-preview.387.g67acac257f.dirty on 2025-07-19; linux [GCC 12.2.0] version

Reproduction

Run the following script on the unix coverage build:

import btree, io

N = 62

db = btree.open(io.BytesIO(), pagesize=512)

e = b"a" * 78

for i in range(N):
    db[b"thekey{}".format(i)] = e + str(i)

for i in range(N):
    db[b"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + str(i)] = e + str(i)

The script is a hand-minimized version of a longer version found by automated fuzzing. Small changes to the final long key string can cause the test to succeed or to fail instead with a MemoryError.

Expected behaviour

The script completes. It produces no useful output.

Observed behaviour

The script crashes.

With added instrumentation, I was able to trace the problem back to the use of an undefined value in __bt_split:

188                 case P_BLEAF:
189                         bl = GETBLEAF(rchild, 0);
190                         VALGRIND_CHECK_VALUE_IS_DEFINED(bl->ksize);
191                         nbytes = NBINTERNAL(bl->ksize);
192                         if (t->bt_pfx && !(bl->flags & P_BIGKEY) &&
==2795256== Uninitialised byte(s) found during client check request
==2795256==    at 0x6424C1: __bt_split (bt_split.c:191)
==2795256==    by 0x635343: __bt_put (bt_put.c:202)
==2795256==    by 0x471C19: btree_subscr (modbtree.c:328)
==2795256==    by 0x3BB297: mp_obj_subscr (obj.c:575)
==2795256==    by 0x446E75: mp_execute_bytecode (vm.c:503)
==2795256==    by 0x3DA130: fun_bc_call (objfun.c:295)
==2795256==    by 0x39F14F: mp_call_function_n_kw (runtime.c:727)
==2795256==    by 0x3A41DB: mp_call_function_0 (runtime.c:701)
==2795256==    by 0x658253: execute_from_lexer (main.c:162)
==2795256==    by 0x658346: do_file (main.c:311)
==2795256==    by 0x65A865: main_ (main.c:741)
==2795256==    by 0x65ADE9: main (main.c:494)
==2795256==  Address 0x55d164f is 463 bytes inside a block of size 560 alloc'd
==2795256==    at 0x48417B4: malloc (vg_replace_malloc.c:381)
==2795256==    by 0x649EAF: mpool_bkt (mpool.c:335)
==2795256==    by 0x64B846: mpool_new (mpool.c:124)
==2795256==    by 0x632B96: __bt_new (bt_page.c:96)
==2795256==    by 0x63F954: bt_page (bt_split.c:371)
==2795256==    by 0x640BC6: __bt_split (bt_split.c:110)
==2795256==    by 0x635343: __bt_put (bt_put.c:202)
==2795256==    by 0x471C19: btree_subscr (modbtree.c:328)
==2795256==    by 0x3BB297: mp_obj_subscr (obj.c:575)
==2795256==    by 0x446E75: mp_execute_bytecode (vm.c:503)
==2795256==    by 0x3DA130: fun_bc_call (objfun.c:295)
==2795256==    by 0x39F14F: mp_call_function_n_kw (runtime.c:727)
==2795256==  Uninitialised value was created by a heap allocation
==2795256==    at 0x48417B4: malloc (vg_replace_malloc.c:381)
==2795256==    by 0x649EAF: mpool_bkt (mpool.c:335)
==2795256==    by 0x64B846: mpool_new (mpool.c:124)
==2795256==    by 0x62E481: nroot (bt_open.c:360)
==2795256==    by 0x63094B: __bt_open (bt_open.c:306)
==2795256==    by 0x47179E: mod_btree_open (modbtree.c:416)
==2795256==    by 0x3DB1BF: fun_builtin_var_call (objfun.c:118)
==2795256==    by 0x39F14F: mp_call_function_n_kw (runtime.c:727)
==2795256==    by 0x39FC01: mp_call_method_n_kw (runtime.c:743)
==2795256==    by 0x43EDFB: mp_execute_bytecode (vm.c:1068)
==2795256==    by 0x3DA130: fun_bc_call (objfun.c:295)
==2795256==    by 0x39F14F: mp_call_function_n_kw (runtime.c:727)

Additional Information

The cause for the bug is almost certainly in the btree submodule but as I'm not 100% sure, I chose to file the issue here.

Code of Conduct

Yes, I agree

CANDIDATE · ISSUE

hard crash when producing a large string via "*"

openby jepleropened 2025-08-15updated 2025-08-25
bug

Port, board and/or hardware

unix port, coverage variant, x86_64 linux

MicroPython version

v1.27.0-preview-32-g141f7d0c35

Reproduction

Run micropython with the following script (via -c for example): 'a' * 8 * (1 << 62)

Expected behaviour

A Python exception occurs, which can be caught and continued from.

Observed behaviour

A crash inside memcpy, or other low level misbehavior (e.g., unicorn hangs)

Starting program: /home/jepler/src/micropython/ports/unix/build-coverage/micropython -c "'aaaa' * (1 << 62)"
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".

Program received signal SIGSEGV, Segmentation fault.
__memcpy_avx_unaligned_erms () at ../sysdeps/x86_64/multiarch/memmove-vec-unaligned-erms.S:366
warning: 366	../sysdeps/x86_64/multiarch/memmove-vec-unaligned-erms.S: No such file or directory
(gdb) where
#0  __memcpy_avx_unaligned_erms () at ../sysdeps/x86_64/multiarch/memmove-vec-unaligned-erms.S:366
#1  0x0000555555619c62 in mp_seq_multiply (items=items@entry=0x7ffff7c15c20, item_sz=item_sz@entry=1, len=8, 
    times=4611686018427387904, dest=0x7ffff7c97000) at ../../py/sequence.c:41
#2  0x0000555555610ef1 in mp_obj_str_binary_op (op=MP_BINARY_OP_MULTIPLY, lhs_in=<optimized out>, 
    rhs_in=<optimized out>) at ../../py/objstr.c:391

Additional Information

Many variants (such as 1<<59) instead give the message MemoryError: memory allocation failed, allocating 1 bytes. This is due to always printing the size as a int; a proposed fix for that is in https://github.com/micropython/micropython/pull/17931

This finding is from a fuzzer.

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