Handling of misaligned arrays
Dieses Issue hat noch niemand übernommen.
Bewertung
- Schwierigkeit
- 4/5
- Geschätzter Aufwand
- 3-5 Tage
- Anfängerfreundlichkeit
- 58/100
Rechercherichtung
Beginne damit, das Beispiel mit dem falsch ausgerichteten Array zu reproduzieren, und untersuche PyArrayMethods::as_slice, PyArrayMethods::get und PyReadonlyArray::as_slice, wobei die gemeldete Panic als Ausgangspunkt dient. Prüfe, wie vorhandene nicht zusammenhängende Arrays behandelt werden und ob zugehörige Tests Arrays der Länge null abdecken. Als abgeschlossen gelten eine sichere Rückgabe für falsch ausgerichtete Eingaben, eine sichere Behandlung von Arrays der Länge null sowie Tests, die beide Fälle abdecken.
Vom Indexierungsmodell aus dem Issue-Text verfasst.
Beschreibung
There are a few methods that produce references to items in Numpy arrays, such as PyArrayMethods::get and PyArrayMethods::as_slice. Rust references are required to be to aligned data, while Numpy arrays aren't (but usually are in practice, unless you try hard). When passing a misaligned array and using a reference-returning method, rust-numpy current invokes UB in safe code by attempting to create the reference.
I'm not sure how practical it is to handle misaligned arrays in all cases. One place where it would be convenient, however, is for zero-length arrays in as_slice. With Pickle 5 and its PickleBuffer objects now the default pickling method from Python 3.14+, Numpy arrays roundtrip through pickle using them, which in the case of an empty array causes the imported array to be produced by (effectively) numpy.frombuffer(bytearray()). Since bytearray() is concerned with bytes, its alignment is only guaranteed as on 1s. I observed Python 3.14 on Linux x86-64 to reliably put the bytearray() singleton buffer on an odd memory address (see python/cpython#140557), which was causing array-extraction failures in my library when trying to implement custom pickling handling when the object happened to be empty.
For example:
use numpy::{PyArray1, PyArrayMethods};
use pyo3::prelude::*;
use pyo3::types::IntoPyDict;
fn main() -> PyResult<()> {
Python::initialize();
Python::attach(|py| {
let array = PyArray1::<u16>::zeros(py, 4, false);
let view = py
.eval(
c"array.view('u1')[1:-1].view('u2')",
None,
Some(&[("array", array)].into_py_dict(py)?),
)?
.cast_into::<PyArray1<u16>>()?;
assert_eq!(view.readonly().as_slice()?, &[0, 0, 0]);
Ok(())
})
}
will panic in debug mode in the as_slice call without returning an error variant:
thread 'main' (30956354) panicked at /Users/jake/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/numpy-0.27.1/src/array.rs:748:16:
unsafe precondition(s) violated: slice::from_raw_parts requires the pointer to be aligned and non-null, and the total size of the slice not to exceed `isize::MAX`
This indicates a bug in the program. This Undefined Behavior check is optional, and cannot be relied on for safety.
stack backtrace:
0: __rustc::rust_begin_unwind
at /rustc/ded5c06cf21d2b93bffd5d884aa6e96934ee4234/library/std/src/panicking.rs:698:5
1: core::panicking::panic_nounwind_fmt::runtime
at /rustc/ded5c06cf21d2b93bffd5d884aa6e96934ee4234/library/core/src/panicking.rs:122:22
2: core::panicking::panic_nounwind_fmt
at /rustc/ded5c06cf21d2b93bffd5d884aa6e96934ee4234/library/core/src/intrinsics/mod.rs:2435:9
3: core::slice::raw::from_raw_parts::precondition_check
at /Users/jake/.rustup/toolchains/stable-aarch64-apple-darwin/lib/rustlib/src/rust/library/core/src/ub_checks.rs:73:21
4: core::slice::raw::from_raw_parts
at /Users/jake/.rustup/toolchains/stable-aarch64-apple-darwin/lib/rustlib/src/rust/library/core/src/ub_checks.rs:78:17
5: numpy::array::PyArrayMethods::as_slice
at /Users/jake/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/numpy-0.27.1/src/array.rs:748:16
6: numpy::borrow::PyReadonlyArray<T,D>::as_slice
at /Users/jake/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/numpy-0.27.1/src/borrow/mod.rs:273:29
7: rust_numpy_test::main::{{closure}}
at ./src/main.rs:16:36
8: pyo3::marker::Python::attach
at /Users/jake/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/pyo3-0.27.2/src/marker.rs:426:9
9: rust_numpy_test::main
at ./src/main.rs:7:5
10: core::ops::function::FnOnce::call_once
at /Users/jake/.rustup/toolchains/stable-aarch64-apple-darwin/lib/rustlib/src/rust/library/core/src/ops/function.rs:250:5
I would be interested in:
PyArrayMethods::as_slicereturning a safeErrvariant if the array is misaligned, not just if it's non-contiguous (though this would potentially be an API break to change the return type)PyArrayMethods::as_slicesafely returning&[]if the length is zero, regardless of the alignment of the internal pointer of the array- any discussion on how to handle data alignment concerns elsewhere in the library
I can easily prepare a patch that addresses the first two points.
- Vorherrschende Sprache
- Rust
- Sterne
- 1.4k
- Forks
- 141
- Ø Merge
- 20 Std. 27 Min.
- Gemergte PRs (30 T.)
- 3
Entwicklungsumgebung
Dieses Projekt bietet weder Dev-Container noch Dockerfile noch Beitragsleitfaden – die Einrichtung liegt bei Ihnen. Beginnen Sie mit der README; die allgemeinen Schritte stehen in unserem Leitfaden für den ersten Beitrag.
Erste Schritte
- Lesen Sie das ganze Issue und danach den Beitragsleitfaden des Projekts.
- Schreiben Sie ins Issue, dass Sie es übernehmen — das erspart doppelte Arbeit.
- Forken Sie das Repository und arbeiten Sie in einem Branch.
- Öffnen Sie einen Pull Request, der die Issue-Nummer nennt.
Mehr aus PyO3/rust-numpy
-
Make borrow-state tests portable to 32-bit targetsEvtl. vergeben @heiserhorn hat das vor 59 Tagen übernommen. Offen
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 65/100
PyO3/rust-numpy#565 · 1 Kommentar ·
-
Schwierigkeit 3/5 1-2 Tage Anfängerfreundlichkeit 58/100
PyO3/rust-numpy#563 ·
-
Schwierigkeit 3/5 1-2 Tage Anfängerfreundlichkeit 56/100
PyO3/rust-numpy#557 ·
-
Schwierigkeit 3/5 1-2 Tage Anfängerfreundlichkeit 45/100
PyO3/rust-numpy#547 · 2 Kommentare ·
-
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 20/100
PyO3/rust-numpy#535 ·
Alle Issues in PyO3/rust-numpy
Ähnliche Issues
-
The book has a Nix install section that chelis.ch lacks, and it names two of the three systemsOffenarea:ecosystem documentation
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 78/100
Chelis-Lang/chelis#3866 ·
Maintainer antworten meist innerhalb von 1 Tag
-
bug documentation sev-0
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 72/100
-
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 86/100
Maintainer antworten meist innerhalb von 1 Tag
-
bug
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 85/100
dekobon/big-code-analysis#1620 ·
Maintainer antworten meist innerhalb von 3 Tagen
-
bug
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 65/100