|
8 | 8 |
|
9 | 9 |
|
10 | 10 | import numpy as np
|
| 11 | +from numcodecs.compat import ensure_contiguous_ndarray |
11 | 12 |
|
12 | 13 |
|
13 | 14 | from zarr.util import (is_total_slice, human_readable_size, normalize_resize_args,
|
@@ -1743,18 +1744,25 @@ def _decode_chunk(self, cdata):
|
1743 | 1744 | for f in self._filters[::-1]:
|
1744 | 1745 | chunk = f.decode(chunk)
|
1745 | 1746 |
|
1746 |
| - # view as correct dtype |
| 1747 | + # view as numpy array with correct dtype |
1747 | 1748 | if self._dtype == object:
|
1748 |
| - if isinstance(chunk, np.ndarray): |
1749 |
| - chunk = chunk.astype(self._dtype) |
| 1749 | + # special case object dtype, because incorrect handling can lead to |
| 1750 | + # segfaults and other bad things happening |
| 1751 | + if isinstance(chunk, np.ndarray) and chunk.dtype == object: |
| 1752 | + # chunk is already of correct dtype, good to carry on |
| 1753 | + # flatten just to be sure we can reshape later |
| 1754 | + chunk = chunk.reshape(-1, order='A') |
1750 | 1755 | else:
|
| 1756 | + # If we end up here, someone must have hacked around with the filters. |
| 1757 | + # We cannot deal with object arrays unless there is an object |
| 1758 | + # codec in the filter chain, i.e., a filter that converts from object |
| 1759 | + # array to something else during encoding, and converts back to object |
| 1760 | + # array during decoding. |
1751 | 1761 | raise RuntimeError('cannot read object array without object codec')
|
1752 |
| - elif isinstance(chunk, np.ndarray): |
1753 |
| - chunk = chunk.view(self._dtype) |
1754 | 1762 | else:
|
1755 |
| - chunk = np.frombuffer(chunk, dtype=self._dtype) |
| 1763 | + chunk = ensure_contiguous_ndarray(chunk).view(self._dtype) |
1756 | 1764 |
|
1757 |
| - # reshape |
| 1765 | + # ensure correct chunk shape |
1758 | 1766 | chunk = chunk.reshape(self._chunks, order=self._order)
|
1759 | 1767 |
|
1760 | 1768 | return chunk
|
|
0 commit comments