Skip to content

PyObject_Realloc(NULL, size) crashes free-threaded 32-bit Python 3.15.0b2 #151297

@godlygeek

Description

@godlygeek

Crash report

What happened?

I haven't managed to reproduce this with a build of CPython from source, but it reproduces using the manylinux images shipped by the PyPA on an x86-64 machine:

docker run -it quay.io/pypa/manylinux_2_34_i686 /usr/local/bin/python3.15t -c 'import ctypes; PyObject_Realloc = ctypes.pythonapi.PyObject_Realloc; PyObject_Realloc.argtypes = [ctypes.c_void_p, ctypes.c_size_t]; PyObject_Realloc.restype = ctypes.c_void_p; print(PyObject_Realloc(None, 984))'

It only crashes for python3.15t, not for python3.15 or python3.14t.

It only crashes for the i686 image, not the x86-64 image.

(gdb) bt
#0  0x5ebd5a4e in ?? ()
#1  0x5ebd7a21 in PyObject_Realloc ()
#2  0xf2cc37dc in ffi_call_i386 () at ../src/x86/sysv.S:121
...
(gdb) x/30i 0x5ebd5a4e - 50
   0x5ebd5a1c:  nopl   0x0(%eax)
   0x5ebd5a20:  mov    0xc(%ebp),%edi
   0x5ebd5a23:  mov    (%edi,%edx,1),%edi
   0x5ebd5a26:  mov    %edi,(%esi,%edx,1)
   0x5ebd5a29:  mov    0xc(%ebp),%edi
   0x5ebd5a2c:  add    $0x4,%edx
   0x5ebd5a2f:  cmp    %edx,%eax
   0x5ebd5a31:  jne    0x5ebd5a20
   0x5ebd5a33:  lea    (%esi,%eax,1),%edx
   0x5ebd5a36:  add    %edi,%eax
   0x5ebd5a38:  sub    $0x4,%esp
   0x5ebd5a3b:  push   %ecx
   0x5ebd5a3c:  push   %eax
   0x5ebd5a3d:  push   %edx
   0x5ebd5a3e:  call   0x5edd6220 <memcpy@plt>
   0x5ebd5a43:  add    $0x10,%esp
   0x5ebd5a46:  lea    -0x1(%edi),%eax
   0x5ebd5a49:  and    $0xffc00000,%eax
=> 0x5ebd5a4e:  mov    0x6c(%eax),%edx
   0x5ebd5a51:  sub    %eax,%edi
   0x5ebd5a53:  shr    $0x9,%edi
   0x5ebd5a56:  and    $0xffffffc0,%edi
   0x5ebd5a59:  lea    (%eax,%edi,1),%ecx
   0x5ebd5a5c:  sub    0x74(%eax,%edi,1),%ecx
   0x5ebd5a60:  mov    %gs:0x0,%edi
   0x5ebd5a67:  add    $0x70,%ecx
   0x5ebd5a6a:  cmp    %edx,%edi
   0x5ebd5a6c:  jne    0x5ebd5acf
   0x5ebd5a6e:  cmpb   $0x0,0xe(%ecx)
   0x5ebd5a72:  jne    0x5ebd5ad6

It looks like it's crashing after the memcpy call that realloc makes to copy from the old buffer to the new. The only other thing _PyObject_MiRealloc does after that point is call mi_free(ptr) to free the old pointer, but that should be special casing null...

The crash is from trying to access:

(gdb) p $_siginfo._sifields._sigfault.si_addr
$1 = (void *) 0xffc0006c

The address's high byte being 0xFF on a 32-bit address space makes me think something has wrapped around by subtracting from the null pointer to find the malloc housekeeping structures or something, but I haven't figured out why, since all of the code does seem to be properly guarded against null pointers.

CPython versions tested on:

3.15

Operating systems tested on:

Linux

Output from running 'python -VV' on the command line:

Python 3.15.0b2 free-threading build (main, Jun 6 2026, 08:05:01) [Clang 22.1.7 ]

Linked PRs

Metadata

Metadata

Assignees

No one assigned
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions