Skip to content

BUG: Internal copyswap/copyswapn calls segfault for new-style user DTypes #30795

Closed as duplicate

Description

@SwayamInSync

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:

* 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 backfires
// 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

  • copyswap should not be become a first-class new DType API
  • Byte-Swapping should be should be handled via casting and byteswap itself is not important as a first-class operation

Possible direction

  • For call sites that only copy (swap=0), replace copyswap with memcpy or the strided cast (np.place use 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 a byteorder parameter (eg new_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

  1. ngoldbaum commented on Feb 6, 2026

    @ngoldbaum
    Member

    I think this is a dupe of #24859.

  2. SwayamInSync commented on Feb 6, 2026

    @SwayamInSync
    MemberAuthor

    I think this is a dupe of #24859.

    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!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions