bottleneck icon indicating copy to clipboard operation
bottleneck copied to clipboard

[BUG] Segmentation fault when working on a transposed numpy array with first dimension 1.

Open RubendeBruin opened this issue 4 years ago • 2 comments

Issue raised as follow-up to: https://github.com/pydata/xarray/issues/6002

Reproduce

import numpy as np
import bottleneck as bn

n_time = 1
spec_data = np.random.random(size=(n_time,192,121))

bn.nanmax(spec_data.transpose(0, 2, 1))


 ---> Segmentation fault

numpy.transpose returns a view, so I guess that's what causes bottleneck to segfault? Not sure, though, especially since changing the order does not trigger the segfault: spec_data.transpose(1, 0, 2)... maybe bottleneck doesn't like views with a first dimension of size 1?

Expected behaviour Should not crash

Environment Confirmed Windows & Linux , P37 and P39.

confirmed with: bottleneck: 1.3.2 numpy: 1.21.4

RubendeBruin avatar Nov 19 '21 13:11 RubendeBruin

The issue seems that the transposed array is F_CONTIGUOUS and bottleneck wrongly uses the first non-zero stride for iteration. This patch fixes this issue for me ~~but I have not tested it thoroughly~~ on Windows:

diff --git a/bottleneck/include/iterators.h b/bottleneck/include/iterators.h
index 1f5120a..c70c46a 100644
--- a/bottleneck/include/iterators.h
+++ b/bottleneck/include/iterators.h
@@ -108,7 +108,7 @@ static inline void init_iter_all(iter *it, PyArrayObject *a, int ravel, int anyo
         for (i = ndim - 1; i > -1; i--) {
             /* protect against length zero  strides such as in
        * np.ones((2, 2))[..., np.newaxis] */
-            if (strides[i] == 0) {
+            if ((strides[i] == 0) || (shape[i] == 1)) {
                 continue;
             }
             it->astride = strides[i];
@@ -122,7 +122,7 @@ static inline void init_iter_all(iter *it, PyArrayObject *a, int ravel, int anyo
             for (i = 0; i < ndim; i++) {
                 /* protect against length zero  strides such as in
          * np.ones((2, 2), order='F')[np.newaxis, ...] */
-                if (strides[i] == 0) {
+                if ((strides[i] == 0) || (shape[i] == 1)) {
                     continue;
                 }
                 it->astride = strides[i];

The shape, strides, and flags of the transposed array are:

(1, 121, 192)

(185856, 8, 968)

  C_CONTIGUOUS : False
  F_CONTIGUOUS : True
  OWNDATA : False
  WRITEABLE : True
  ALIGNED : True
  WRITEBACKIFCOPY : False
  UPDATEIFCOPY : False

cgohlke avatar Nov 21 '21 18:11 cgohlke

Probably a duplicate of #381 and fixed by #382.

cgohlke avatar Nov 24 '21 16:11 cgohlke