PyO3 / PyO3/rust-numpy

panic in as_array_mut

Open
#527 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Rust
Stars
1.4k
Forks
141
Avg merge
16m
Merged PRs (30d)
3

Description

Hi

When trying to create an PyArray2 we stumbled upon a panic. The following code reproduces it:

src/main.rs:

use numpy::PyArray2;
use pyo3::PyResult;
use numpy::PyArrayMethods;
use pyo3::Python;

fn main() {
    let _ = Python::attach(|py| -> PyResult<()> {
        let array = PyArray2::<f64>::zeros(py, [2, 0], false);
        let mut array_rw = array.readwrite();
        let _array_rw = array_rw.as_array_mut();
        Ok(())
    });
}

Cargo.toml:

[package]
name = "numpy-repro"
version = "0.1.0"
edition = "2024"

[dependencies]
pyo3 = { version = "0.27", features = ["auto-initialize"] }
numpy = "0.27"

Backtrace:

thread 'main' (15879273) panicked at /Users/alexander.kjall/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/ndarray-0.17.2/src/impl_raw_views.rs:297:17:
The strides must not allow any element to be referenced by two different indices
stack backtrace:
   0: __rustc::rust_begin_unwind
             at /rustc/86a49fd71fecd25b0fd20247db0ba95eeceaba28/library/std/src/panicking.rs:689:5
   1: core::panicking::panic_fmt
             at /rustc/86a49fd71fecd25b0fd20247db0ba95eeceaba28/library/core/src/panicking.rs:80:14
   2: <ndarray::ArrayBase<ndarray::RawViewRepr<*mut f64>, ndarray::dimension::dim::Dim<[usize; 2]>, f64>>::from_shape_ptr::<ndarray::shape_builder::StrideShape<ndarray::dimension::dim::Dim<[usize; 2]>>>
             at /Users/alexander.kjall/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/ndarray-0.17.2/src/impl_raw_views.rs:297:17
   3: <ndarray::ArrayBase<ndarray::ViewRepr<&mut f64>, ndarray::dimension::dim::Dim<[usize; 2]>, f64>>::from_shape_ptr::<ndarray::shape_builder::StrideShape<ndarray::dimension::dim::Dim<[usize; 2]>>>
             at /Users/alexander.kjall/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/ndarray-0.17.2/src/impl_views/constructors.rs:220:9
   4: <pyo3::instance::Bound<numpy::array::PyArray<f64, ndarray::dimension::dim::Dim<[usize; 2]>>> as numpy::array::PyArrayMethods<f64, ndarray::dimension::dim::Dim<[usize; 2]>>>::as_array_mut::{closure#0}
             at /Users/alexander.kjall/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/numpy-0.27.1/src/array.rs:1499:36
   5: numpy::array::as_view::<f64, ndarray::dimension::dim::Dim<[usize; 2]>, ndarray::ViewRepr<&mut f64>, <pyo3::instance::Bound<numpy::array::PyArray<f64, ndarray::dimension::dim::Dim<[usize; 2]>>> as numpy::array::PyArrayMethods<f64, ndarray::dimension::dim::Dim<[usize; 2]>>>::as_array_mut::{closure#0}>
             at /Users/alexander.kjall/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/numpy-0.27.1/src/array.rs:1346:21
   6: <pyo3::instance::Bound<numpy::array::PyArray<f64, ndarray::dimension::dim::Dim<[usize; 2]>>> as numpy::array::PyArrayMethods<f64, ndarray::dimension::dim::Dim<[usize; 2]>>>::as_array_mut
             at /Users/alexander.kjall/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/numpy-0.27.1/src/array.rs:1499:9
   7: <numpy::borrow::PyReadwriteArray<f64, ndarray::dimension::dim::Dim<[usize; 2]>>>::as_array_mut
             at /Users/alexander.kjall/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/numpy-0.27.1/src/borrow/mod.rs:509:29
   8: numpy_repro::main::{closure#0}
             at ./src/main.rs:10:34
   9: <pyo3::marker::Python>::attach::<numpy_repro::main::{closure#0}, core::result::Result<(), pyo3::err::PyErr>>
             at /Users/alexander.kjall/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/pyo3-0.27.2/src/marker.rs:426:9
  10: numpy_repro::main
             at ./src/main.rs:7:13
  11: <fn() as core::ops::function::FnOnce<()>>::call_once
             at /rustc/86a49fd71fecd25b0fd20247db0ba95eeceaba28/library/core/src/ops/function.rs:250:5
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.

Running with python 3.14.

It would be simpler to expose this error to the python layer if as_array_mut() returned a Result instead of panicking on invalid input :)

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Reproduce the panic with the issue's src/main.rs example, then inspect numpy-0.27.1/src/array.rs around as_array_mut and borrow/mod.rs around PyReadwriteArray::as_array_mut. Check how the [2, 0] shape reaches ndarray's from_shape_ptr validation. Done means this input has defined failure behavior rather than an uncontrolled panic, with regression coverage for the reproducer.

Written by the indexing model from the issue text.

Assessment

Tech stack
numpy, python, rust
Domain
backend-api-design
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
45/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.