Skip to content

PyString::from_object does not convert rust strings to c-strings before calling FFI, causing OOB reads #5005

Closed
@vthib

Description

@vthib

Bug Description

PyString::from_object takes &str parameters and passes them through to a ffi function that expects c-style strings. This causes OOB accesses and potential crashes.

Steps to Reproduce

use pyo3::prelude::*;
use pyo3::types::{PyBytes, PyString};

fn main() {
    pyo3::prepare_freethreaded_python();
    Python::with_gil(|py| {
        let py_bytes = PyBytes::new(py, b"ab\xFFcd");

        // The following line is faulty
        let py_string = PyString::from_object(&py_bytes, "utf-8", "ignore").unwrap();
        // This would work:
        // let py_string = PyString::from_object(&py_bytes, "utf-8\0", "ignore\0").unwrap();

        let result = py_string.to_str().unwrap();
        assert_eq!(result, "abcd");
    });
}

This returns something like this when executed:

thread 'main' panicked at src/main.rs:8:77:
called `Result::unwrap()` on an `Err` value: PyErr { type: <class 'LookupError'>, value: LookupError('unknown encoding: utf-8ignoresrc/main.rsabcd/home/foo/.cargo/registry/src/index.crates.io-1949cf8c6b...

which seems expected since those strings are in .rdata, but will depend a lot depending on how those strings are built.

Your operating system and version

Any

Your Python version (python --version)

3.11.2

Your Rust version (rustc --version)

1.85.1

Your PyO3 version

0.24.0

How did you install python? Did you use a virtualenv?

apt, no virtualenv

Additional Info

Thanks a lot for this great project :)

I stumbled upon this issue when trying to use this function to guarantee the same bytes => string conversion with an existing python library.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions