Skip to content

Commit e7b851b

Browse files
authored
Merge pull request #262 from PyO3/exact-size-iter-soundness
ExactSizeIterator is a optimization hint but unsafe code cannot trust it
2 parents ab2d214 + 7f7c0d0 commit e7b851b

File tree

2 files changed

+22
-11
lines changed

2 files changed

+22
-11
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
- Support object arrays ([#216](https://github.com/PyO3/rust-numpy/pull/216))
55
- Support borrowing arrays that are part of other Python objects via `PyArray::borrow_from_array` ([#230](https://github.com/PyO3/rust-numpy/pull/216))
66
- `PyArray::new` is now `unsafe`, as it produces uninitialized arrays ([#220](https://github.com/PyO3/rust-numpy/pull/220))
7+
- `PyArray::from_exact_iter` does not unsoundly trust `ExactSizeIterator::len` any more ([#262](https://github.com/PyO3/rust-numpy/pull/262))
78
- `rayon` feature is now removed, and directly specifying the feature via `ndarray` dependency is recommended ([#250](https://github.com/PyO3/rust-numpy/pull/250))
89
- Descriptors rework and related changes ([#256](https://github.com/PyO3/rust-numpy/pull/256)):
910
- Remove `DataType`

src/array.rs

Lines changed: 21 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,27 @@
11
//! Safe interface for NumPy ndarray
2-
use crate::npyffi::{self, npy_intp, NPY_ORDER, PY_ARRAY_API};
3-
use ndarray::*;
4-
use num_traits::AsPrimitive;
5-
use pyo3::{
6-
ffi, prelude::*, pyobject_native_type_info, pyobject_native_type_named, type_object,
7-
types::PyAny, AsPyPointer, PyDowncastError, PyNativeType, PyResult,
8-
};
92
use std::{
103
cell::Cell,
4+
marker::PhantomData,
115
mem,
126
os::raw::{c_int, c_void},
137
ptr, slice,
148
};
15-
use std::{iter::ExactSizeIterator, marker::PhantomData};
9+
10+
use ndarray::{
11+
Array, ArrayBase, ArrayView, ArrayViewMut, Axis, Data, Dim, Dimension, IntoDimension, Ix0, Ix1,
12+
Ix2, Ix3, Ix4, Ix5, Ix6, IxDyn, RawData, Shape, ShapeBuilder, StrideShape,
13+
};
14+
use num_traits::AsPrimitive;
15+
use pyo3::{
16+
ffi, pyobject_native_type_info, pyobject_native_type_named, type_object, types::PyModule,
17+
AsPyPointer, FromPyObject, IntoPy, Py, PyAny, PyDowncastError, PyErr, PyNativeType, PyObject,
18+
PyResult, Python, ToPyObject,
19+
};
1620

1721
use crate::convert::{ArrayExt, IntoPyArray, NpyIndex, ToNpyDims, ToPyArray};
1822
use crate::dtype::Element;
1923
use crate::error::{DimensionalityError, FromVecError, NotContiguousError, TypeError};
24+
use crate::npyffi::{self, npy_intp, NPY_ORDER, PY_ARRAY_API};
2025
use crate::slice_container::PySliceContainer;
2126

2227
/// A safe, static-typed interface for
@@ -919,10 +924,15 @@ impl<T: Element> PyArray<T, Ix1> {
919924
// NumPy will always zero-initialize object pointers,
920925
// so the array can be dropped safely if the iterator panics.
921926
unsafe {
922-
let array = Self::new(py, [iter.len()], false);
923-
for (i, item) in iter.enumerate() {
924-
array.uget_raw([i]).write(item);
927+
let len = iter.len();
928+
let array = Self::new(py, [len], false);
929+
let mut idx = 0;
930+
for item in iter {
931+
assert!(idx < len);
932+
array.uget_raw([idx]).write(item);
933+
idx += 1;
925934
}
935+
assert!(idx == len);
926936
array
927937
}
928938
}

0 commit comments

Comments
 (0)