Skip to content

Commit f5fe2ba

Browse files
committed
Make PyArray::from_(exact_)iter sound by avoiding to free uninitialized memory if the iterator panics.
1 parent c8a2d8c commit f5fe2ba

File tree

1 file changed

+16
-2
lines changed

1 file changed

+16
-2
lines changed

src/array.rs

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -776,7 +776,14 @@ impl<T: Element> PyArray<T, Ix1> {
776776
/// });
777777
/// ```
778778
pub fn from_exact_iter(py: Python<'_>, iter: impl ExactSizeIterator<Item = T>) -> &Self {
779-
let array = Self::new(py, [iter.len()], false);
779+
// Use zero-initialized pointers for object arrays
780+
// so that partially initialized arrays can be dropped safely
781+
// in case the iterator implementation panics.
782+
let array = if T::DATA_TYPE == DataType::Object {
783+
Self::zeros(py, [iter.len()], false)
784+
} else {
785+
Self::new(py, [iter.len()], false)
786+
};
780787
unsafe {
781788
for (i, item) in iter.enumerate() {
782789
*array.uget_mut([i]) = item;
@@ -804,7 +811,14 @@ impl<T: Element> PyArray<T, Ix1> {
804811
let iter = iter.into_iter();
805812
let (min_len, max_len) = iter.size_hint();
806813
let mut capacity = max_len.unwrap_or_else(|| min_len.max(512 / mem::size_of::<T>()));
807-
let array = Self::new(py, [capacity], false);
814+
// Use zero-initialized pointers for object arrays
815+
// so that partially initialized arrays can be dropped safely
816+
// in case the iterator implementation panics.
817+
let array = if T::DATA_TYPE == DataType::Object {
818+
Self::zeros(py, [capacity], false)
819+
} else {
820+
Self::new(py, [capacity], false)
821+
};
808822
let mut length = 0;
809823
unsafe {
810824
for (i, item) in iter.enumerate() {

0 commit comments

Comments
 (0)