Repository navigation
Crash: mmap access can SIGBUS after backing file is truncated #148650
Description
Activity
- addedtype-bugAn unexpected behavior, bug, or errorAn unexpected behavior, bug, or error
on Apr 16, 2026 - addedextension-modulesC modules in the Modules dirC modules in the Modules dir
on Apr 19, 2026 Is it a hard crash (interpreter exits) or is there an exception raised? in the first case we need to fix it and decide what to do, in the second, I think it is legitimate that reading from an invalid mmap does not behave as expected.
No exception, hard crash
mjbommar@workstation1:~$ uv run --python 3.14 python -c '''import mmap import tempfile f = tempfile.NamedTemporaryFile() f.write(b"\0" * 4096) f.flush() m = mmap.mmap(f.fileno(), 4096) f.truncate(0) f.flush() print(m.size()) # 0 print(len(m)) # 4096 print(m[0]) # SIGBUS print("i live!") ''' 0 4096 mjbommar@workstation1:~$ echo $? 135- addedtype-crashA hard crash of the interpreter, possibly with a core dumpA hard crash of the interpreter, possibly with a core dumpand removedtype-bugAn unexpected behavior, bug, or errorAn unexpected behavior, bug, or error
on Apr 19, 2026 These kinds of core dumps are only producible on Unix, not on Windows.
This is because on Windows, we can use SEH to catch exceptions and raise errors safely on the python level, preventing a core dump.
On Unix, however, we lack a similar method to catch page errors and access violations when reading/writing the mmap pointer, so the process crashes directly. See #118213 (comment)
Hi,
I’d be interested in investigating this further.
My initial concern is that checking the current backing-file size before each mmap operation may reduce some crashes but cannot fully prevent them, because the file can be truncated between the check and the actual memory access. Exported buffers such as
memoryview(m)also appear harder to protect from withinmmapmodule.c.I’ll first reproduce the affected operations on current
main, inspect the Unix mmap and buffer-protocol paths, and review the historical SIGBUS discussions before proposing any implementation.I’ll report back with findings and possible mitigation options before opening a PR.
Hi @picnixz,
spent some time investigating this on current
main.From what I found, the SIGBUS is fundamentally caused by Unix mmap semantics after the backing file is truncated. CPython still exposes the original mapping length (
len(m)), whilem.size()reflects the new file size, but once the kernel faults the page there isn't a reliable mechanism for CPython to recover and raise a Python exception instead.I evaluated several approaches (pre-access size checks, remapping, SIGBUS handlers, wrapping individual operations), but each appears to have significant limitations or races, especially once the mapping has been exported through the buffer protocol (
memoryview) or used by extension modules.My current impression is that this is unlikely to have a complete runtime fix inside CPython, and a documentation warning may be the most realistic improvement unless there's a different design direction the maintainers have in mind.
Happy to share more detailed investigation notes if they're useful.
Bug report
Bug description:
Summary
An
mmap.mmapobject can become internally inconsistent after itsbacking file is truncated to zero.
After truncation:
m.size()reports the new file size correctlylen(m)still reports the original mapping lengthm[0]can crash the process withSIGBUSI think it's a genuine question whether the correct "fix" is a
paternalistic change in C behavior or just adding a more prominent
warning in the docs about the pattern and OS differences, but it
does seem particularly pathological in its current form.
Minimal Reproducer
On my system this exits with
SIGBUS/ exit code135. I tested all the wayto 3.8 and got the same SIGBUS every time, so at least this isn't new.
Expected Behavior
If the mapping becomes invalid because the backing file shrank, I would
expect CPython not to keep exposing the old length and then hard-crash
on a normal operation.
Actual Behavior
The object still looks readable according to
len(m), but using thatrange can crash the interpreter.
Additional Affected Operations
I was able to hit the same
SIGBUSwith more than justm[0],including:
findrfindreadlineread_bytewrite_bytemovememoryview(m)bytes(m)Behavior Sketch
flowchart TD A["create mmap of 4096-byte file"] --> B["length is 4096"] B --> C["truncate backing file to zero"] C --> D["reported file size becomes zero"] D --> E["reported mapping length stays 4096"] E --> F["access first byte"] F --> G["SIGBUS"]Related Issues
I realize there have been older
mmap/SIGBUSreports aroundresized underlying files, but this truncate-to-zero case still
reproduces for me on a currently supported CPython release.
#60416
mmap() dumps core upon resizing the underlying fileClosest historical peer. Same broad pattern: the backing file changes
after mapping, and later access crashes. Old migrated issue, but still
the strongest prior-art reference I found.
#84897
accessing mmap of file that is overwritten causes bus errorRelated. Same end result (
SIGBUS) after the underlying filecontents/extent change, but a different trigger than truncate-to-zero.
#119817
SIGBUS: writing to mmaped device beyond file sizeRelated, but not a duplicate. Same bug class: the Python-visible
mapping range still looks usable, but the OS faults on real access.
Different scenario: mapped device / write beyond real extent.
#114390
SharedMemory crashes on linux with SIGBUS on insufficient shmRelated, but not a duplicate. Same OS-level failure mode: mapping
succeeds, later access faults with
SIGBUS. Different subsystem:multiprocessing.shared_memory.CPython versions tested on:
3.14
Operating systems tested on:
Linux