Repository navigation
Description
Describe the issue:
Several NumPy functions internally call copyswap/copyswapn through PyDataType_GetArrFuncs(descr)->copyswap without NULL checks. For new-style user DTypes registered via PyArrayInitDTypeMeta_FromSpec, these function pointers default to NULL, causing segfaults.
Comment at dtypemeta.c says:
numpy/numpy/_core/src/multiarray/dtypemeta.c
Lines 1432 to 1434 in 0d79864
| * The use of any slot besides getitem, setitem, copyswap, and copyswapn | |
| * is only valid after checking for NULL. Checking for NULL is generally | |
| * encouraged. |
but since they are disabled for user-dtypes so not doing
NULL check backfiresnumpy/numpy/_core/include/numpy/dtype_api.h
Lines 415 to 417 in 0d79864
| // Copyswap is disabled | |
| // #define NPY_DT_PyArray_ArrFuncs_copyswapn 3 + _NPY_DT_ARRFUNCS_OFFSET | |
| // #define NPY_DT_PyArray_ArrFuncs_copyswap 4 + _NPY_DT_ARRFUNCS_OFFSET |
With the reference to the conversation happened with @seberg in numpy/numpy-quaddtype#13 the points discussed are
copyswapshould not be become a first-class new DType API- Byte-Swapping should be should be handled via casting and
byteswapitself is not important as a first-class operation
Possible direction
- For call sites that only copy (
swap=0), replacecopyswapwithmemcpyor the strided cast (np.placeuse it just for copy) - For actual byte-swapping, these should go through the casting. A "byteswapped view" + cast to native byte order can be the equivalent.
PyArray_DescrNewByteorder()support for new style DTypes, or DTypes supporting abyteorderparameter (egnew_dtype(byteorder='>'))
Immediate fix
Add NULL guards at call sites to convert segfaults into clear errors (TypeError or similar), independent of the longer-term casting-based approach.
Reproduce the code example:
import numpy_quaddtype as npq
# Segfault 1: scalar byteswap
npq.QuadPrecision(1).byteswap()
# Segfault 2: np.place
import numpy as np
from numpy_quaddtype import QuadPrecDType
a = np.zeros((18, 1), dtype=QuadPrecDType())
m = np.zeros((18, 1), dtype=np.bool)
m[3:-3] = True
v = np.ones(12, dtype=QuadPrecDType())
np.place(a, m, v)Error message:
Segmentation fault (core dumped)Python and NumPy Versions:
2.5.0.dev0+git20251208.7eec5e2
3.12.11 | packaged by Anaconda, Inc. | (main, Jun 5 2025, 13:09:17) [GCC 11.2.0]
Runtime Environment:
[{'numpy_version': '2.5.0.dev0+git20251208.7eec5e2',
'python': '3.12.11 | packaged by Anaconda, Inc. | (main, Jun 5 2025, '
'13:09:17) [GCC 11.2.0]',
'uname': uname_result(system='Linux', node='', release='6.8.0-1044-azure', version='#50~22.04.1-Ubuntu SMP Wed Dec 3 15:13:22 UTC 2025', machine='x86_64')},
{'simd_extensions': {'baseline': ['X86_V2'],
'found': ['X86_V3'],
'not_found': ['X86_V4', 'AVX512_ICL']}},
{'ignore_floating_point_errors_in_matmul': False},
{'architecture': 'Zen',
'filepath': '/home/miniconda3/envs/quaddtype/lib/libopenblasp-r0.3.29.so',
'internal_api': 'openblas',
'num_threads': 96,
'prefix': 'libopenblas',
'threading_layer': 'pthreads',
'user_api': 'blas',
'version': '0.3.29'}]
How does this issue affect you or how did you find it:
No response
Activity
ngoldbaum commentedon Feb 6, 2026
I think this is a dupe of #24859.
SwayamInSync commentedon Feb 6, 2026
Ah yes, and "Byte-swapping => A "byteswapped view" + cast to native byte order" might be a long shot? (within NumPy native dtypes op maybe?) indeed as per the motivation.
Please feel free to close this one if not needed!