Skip to content

Fix crash when loading model files from Python file-like object - #2110

Merged
jordimas merged 4 commits into
OpenNMT:masterfrom
Purfview:patch-6
Oct 11, 2026
Merged

jordimas merged 4 commits into
OpenNMT:masterfrom
Purfview:patch-6

Conversation

@Purfview

Copy link
Copy Markdown
Contributor

When a file-like object is passed, CTranslate2 crashes with Windows error 0xC0000005 (access violation). [bytes object works]
Loading model files from memory (a file-like or bytes objects) was implemented here: #1030 [files arg documentation ]
I tested the fix on Windows with both file-like and bytes objects - works fine.

Code to reproduce a file-like object crash:

import os
import ctranslate2

model_dir = r"D:\faster-whisper-tiny"

files = {
    filename: open(os.path.join(model_dir, filename), "rb")
    for filename in os.listdir(model_dir)
    if os.path.isfile(os.path.join(model_dir, filename))
}

model = ctranslate2.models.Whisper("test-tiny", files=files)

print("No crash!", flush=True)

AI generated explanation:

Problem

When loading model files from file-like objects, create_model_reader() stores the dictionary value in auto content, which deduces to a non-owning py::handle.

When content = read() assigns the result of a file-like object's read() method, only the underlying Python object pointer is copied. The temporary owning py::object returned by read() is destroyed at the end of the statement, potentially leaving content pointing to a deallocated object.

For ordinary binary file handles, the returned bytes object is not otherwise retained. The subsequent conversion to std::string therefore accesses a dangling Python object, causing a use-after-free that can crash the process.

Fix

Store the dictionary value in an owning py::object, created with py::reinterpret_borrow<py::object>(). This ensures the contents returned by read() remain alive while being converted and registered with the in-memory model reader.

Comment thread python/cpp/replica_pool.h Resolved
@Purfview
Purfview marked this pull request as draft October 11, 2026 03:00
@Purfview
Purfview marked this pull request as ready for review October 11, 2026 03:50
@jordimas

Copy link
Copy Markdown
Collaborator

Thanks so much!

@jordimas
jordimas merged commit 58af5f6 into OpenNMT:master Oct 11, 2026
23 checks passed
@Purfview
Purfview deleted the patch-6 branch October 11, 2026 18:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants