Skip to content

fix: pyo3_ffi's PyObject_GET_WEAKREFS_LISTPTR and PyHeapType_GET_MEMBERS fail with address sanitizer#6145

Open
IvanIsCoding wants to merge 5 commits into
PyO3:mainfrom
IvanIsCoding:pyo3_ffi_asan
Open

fix: pyo3_ffi's PyObject_GET_WEAKREFS_LISTPTR and PyHeapType_GET_MEMBERS fail with address sanitizer#6145
IvanIsCoding wants to merge 5 commits into
PyO3:mainfrom
IvanIsCoding:pyo3_ffi_asan

Conversation

@IvanIsCoding

Copy link
Copy Markdown
Contributor

Related to #5916

This small module:

use pyo3::prelude::*;
use pyo3::ffi;

#[pyfunction]
fn trigger_oob() -> PyResult<()> {
    Python::attach(|py| {
        let obj = PyModule::new(py, "test_module")?;
        let ptr = obj.as_ptr();

        unsafe {
            let wild_ptr = pyo3_ffi::PyObject_GET_WEAKREFS_LISTPTR(ptr);
            
            // This will crash or be caught by ASAN/MSAN.
            let _val = *wild_ptr;
        }

        Ok(())
    })
}

#[pymodule]
fn smoke_test(m: &Bound<'_, PyModule>) -> PyResult<()> {
    m.add_function(wrap_pyfunction!(trigger_oob, m)?)?;
    Ok(())
}

Fails unit tests when running with an address sanitizer:

SanitizerError
AddressSanitizer: heap-buffer-overflow smoke_test/src/lib.rs:17 in smoke_test_rs::trigger_oob::{closure#0}

Comparing with the implementation in C, this bug happens when size_of::<PyHeapTypeObject>() is not 1.

The initial finding was made by @Manishearth when checking unsafe code blocks (using LLMs)

@alex

alex commented Jun 20, 2026

Copy link
Copy Markdown
Member

@davidhewitt I think this one was one of the claude findings, does that sound right?

@alex alex left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the code itself looks correct. I feel like either we should have a test, or we should just delete this binding if we're not using it though.

@IvanIsCoding

Copy link
Copy Markdown
Contributor Author
PyObject_GET_WEAKREFS_LISTPTR

With regards to correctness: https://github.com/dgrunwald/rust-cpython/blob/a60f149f2f64be2d533cf72364fdaeaa8b08893f/python3-sys/src/objimpl.rs#L131

I think the (ancient) version pre-fork had a correct implementation, so somewhere along the way the bug was introduced.

It does look that usage is extremely low, so feel free to remove the code. I couldn't find a single call by PyO3 itself and the GitHub search points more to PyO3 forks than real users.

Comment thread pyo3-ffi/src/cpython/object.rs Outdated
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.

3 participants