From 7be871eb601f9a0da205e11573481d147fb11cd8 Mon Sep 17 00:00:00 2001 From: Charalampos Stratakis Date: Tue, 7 Jul 2026 23:04:24 +0200 Subject: [PATCH] Fix issues identified via Coverity static analysis Resolves: RHEL-193002 --- coverity-fixes.patch | 249 ++++++++++++++++++++++++++++++++++++++++++ python3.14-numpy.spec | 15 ++- 2 files changed, 263 insertions(+), 1 deletion(-) create mode 100644 coverity-fixes.patch diff --git a/coverity-fixes.patch b/coverity-fixes.patch new file mode 100644 index 0000000..51e6e54 --- /dev/null +++ b/coverity-fixes.patch @@ -0,0 +1,249 @@ +From 78bcbebe048bbc16c771ca96a328c01d6f299c06 Mon Sep 17 00:00:00 2001 +From: stratakis +Date: Fri, 19 Dec 2025 18:43:45 +0100 +Subject: [PATCH 1/4] MAINT: fix array size declarations in + string_partition_resolve_descriptors (#30475) + +--- + numpy/_core/src/umath/string_ufuncs.cpp | 6 +++--- + numpy/_core/src/umath/stringdtype_ufuncs.cpp | 6 +++--- + 2 files changed, 6 insertions(+), 6 deletions(-) + +diff --git a/numpy/_core/src/umath/string_ufuncs.cpp b/numpy/_core/src/umath/string_ufuncs.cpp +index 9b3d86c..4a65227 100644 +--- a/numpy/_core/src/umath/string_ufuncs.cpp ++++ b/numpy/_core/src/umath/string_ufuncs.cpp +@@ -1125,9 +1125,9 @@ string_partition_promoter(PyObject *NPY_UNUSED(ufunc), + static NPY_CASTING + string_partition_resolve_descriptors( + PyArrayMethodObject *self, +- PyArray_DTypeMeta *const NPY_UNUSED(dtypes[3]), +- PyArray_Descr *const given_descrs[3], +- PyArray_Descr *loop_descrs[3], ++ PyArray_DTypeMeta *const NPY_UNUSED(dtypes[6]), ++ PyArray_Descr *const given_descrs[6], ++ PyArray_Descr *loop_descrs[6], + npy_intp *NPY_UNUSED(view_offset)) + { + if (!given_descrs[3] || !given_descrs[4] || !given_descrs[5]) { +diff --git a/numpy/_core/src/umath/stringdtype_ufuncs.cpp b/numpy/_core/src/umath/stringdtype_ufuncs.cpp +index ca574f6..7f29a3e 100644 +--- a/numpy/_core/src/umath/stringdtype_ufuncs.cpp ++++ b/numpy/_core/src/umath/stringdtype_ufuncs.cpp +@@ -1928,9 +1928,9 @@ zfill_strided_loop(PyArrayMethod_Context *context, + static NPY_CASTING + string_partition_resolve_descriptors( + PyArrayMethodObject *self, +- PyArray_DTypeMeta *const NPY_UNUSED(dtypes[3]), +- PyArray_Descr *const given_descrs[3], +- PyArray_Descr *loop_descrs[3], ++ PyArray_DTypeMeta *const NPY_UNUSED(dtypes[5]), ++ PyArray_Descr *const given_descrs[5], ++ PyArray_Descr *loop_descrs[5], + npy_intp *NPY_UNUSED(view_offset)) + { + if (given_descrs[2] || given_descrs[3] || given_descrs[4]) { +-- +2.55.0 + + +From b8efba3ffd3f9687d90d815643ac22f750f3af31 Mon Sep 17 00:00:00 2001 +From: stratakis +Date: Thu, 26 Feb 2026 15:17:50 +0100 +Subject: [PATCH 2/4] BUG: Fix buffer overrun in CPU baseline validation + (#30877) + +Co-authored-by: Sebastian Berg +--- + numpy/_core/src/common/npy_cpu_features.c | 5 ++--- + 1 file changed, 2 insertions(+), 3 deletions(-) + +diff --git a/numpy/_core/src/common/npy_cpu_features.c b/numpy/_core/src/common/npy_cpu_features.c +index e9239a2..3c6d517 100644 +--- a/numpy/_core/src/common/npy_cpu_features.c ++++ b/numpy/_core/src/common/npy_cpu_features.c +@@ -222,14 +222,13 @@ npy__cpu_validate_baseline(void) + + #define NPY__CPU_VALIDATE_CB(FEATURE, DUMMY) \ + if (!npy__cpu_have[NPY_CAT(NPY_CPU_FEATURE_, FEATURE)]) { \ +- const int size = sizeof(NPY_TOSTRING(FEATURE)); \ ++ const int size = sizeof(NPY_TOSTRING(FEATURE)) - 1; \ + memcpy(fptr, NPY_TOSTRING(FEATURE), size); \ + fptr[size] = ' '; fptr += size + 1; \ + } + NPY_WITH_CPU_BASELINE_CALL(NPY__CPU_VALIDATE_CB, DUMMY) // extra arg for msvc +- *fptr = '\0'; + +- if (baseline_failure[0] != '\0') { ++ if (fptr > baseline_failure) { + *(fptr-1) = '\0'; // trim the last space + PyErr_Format(PyExc_RuntimeError, + "NumPy was built with baseline optimizations: \n" +-- +2.55.0 + + +From a42fc7e094b9f2f01c14973f80e4236549297bcd Mon Sep 17 00:00:00 2001 +From: Charalampos Stratakis +Date: Wed, 1 Jul 2026 04:45:53 +0200 +Subject: [PATCH 3/4] BUG: Fix MaskedRecords.view() dtype reset and _fill_value + handling + +Reset dtype after an ndarray subclass is interpreted as the view type in +MaskedRecords.view(), matching MaskedArray.view(). Reset _fill_value +for real dtype views and add test coverage. + +Closes #30441 + +Co-authored-by: Saba Siddique +--- + numpy/ma/mrecords.py | 5 +++++ + numpy/ma/tests/test_mrecords.py | 18 ++++++++++++++++++ + 2 files changed, 23 insertions(+) + +diff --git a/numpy/ma/mrecords.py b/numpy/ma/mrecords.py +index 835f3ce..29e3e39 100644 +--- a/numpy/ma/mrecords.py ++++ b/numpy/ma/mrecords.py +@@ -364,6 +364,7 @@ def view(self, dtype=None, type=None): + try: + if issubclass(dtype, np.ndarray): + output = np.ndarray.view(self, dtype) ++ dtype = None + else: + output = np.ndarray.view(self, dtype) + # OK, there's the change +@@ -386,6 +387,10 @@ def view(self, dtype=None, type=None): + mdtype = ma.make_mask_descr(output.dtype) + output._mask = self._mask.view(mdtype, np.ndarray) + output._mask.shape = output.shape ++ # Make sure to reset the _fill_value if needed ++ if getattr(output, '_fill_value', None) is not None: ++ if dtype is not None: ++ output._fill_value = None + return output + + def harden_mask(self): +diff --git a/numpy/ma/tests/test_mrecords.py b/numpy/ma/tests/test_mrecords.py +index 0da9151..5d9d09b 100644 +--- a/numpy/ma/tests/test_mrecords.py ++++ b/numpy/ma/tests/test_mrecords.py +@@ -386,6 +386,24 @@ def test_view_flexible_type(self): + assert_equal(test.dtype, np.dtype(alttype)) + assert_(test._fill_value is None) + ++ def test_view_ndarray_subclass_preserves_dtype(self): ++ mrec = self.data[0] ++ ++ class MySub(np.ndarray): ++ pass ++ ++ test = mrec.view(MySub) ++ assert_(isinstance(test, MySub)) ++ assert_equal(test.dtype, mrec.dtype) ++ ++ def test_view_maskedarray_preserves_fill_value(self): ++ mrec = self.data[0] ++ original_fv = mrec.fill_value ++ ++ test = mrec.view(ma.MaskedArray) ++ assert_(isinstance(test, ma.MaskedArray)) ++ assert_equal(test.fill_value, original_fv) ++ + + ############################################################################## + class TestMRecordsImport: +-- +2.55.0 + + +From d85dde322beb59450f728b505534206c230fe993 Mon Sep 17 00:00:00 2001 +From: Iason Krommydas +Date: Wed, 14 Jan 2026 13:41:18 +0100 +Subject: [PATCH 4/4] BUG: unrelated error raised when a dtype's `__setstate__` + is called with an invalid state tuple size (#30647) + +Raise a simple error rather than trying to correctly raise a more precise on in +__setstate__ for some bad inputs. +--- + numpy/_core/src/multiarray/descriptor.c | 15 ++++++--------- + numpy/_core/tests/test_dtype.py | 23 +++++++++++++++++++++++ + 2 files changed, 29 insertions(+), 9 deletions(-) + +diff --git a/numpy/_core/src/multiarray/descriptor.c b/numpy/_core/src/multiarray/descriptor.c +index abe737a..de08037 100644 +--- a/numpy/_core/src/multiarray/descriptor.c ++++ b/numpy/_core/src/multiarray/descriptor.c +@@ -852,7 +852,7 @@ _try_convert_from_inherit_tuple(PyArray_Descr *type, PyObject *newobj) + return (PyArray_Descr *)Py_NotImplemented; + } + if (!PyDataType_ISLEGACY(type) || !PyDataType_ISLEGACY(conv)) { +- /* ++ /* + * This specification should probably be never supported, but + * certainly not for new-style DTypes. + */ +@@ -1978,7 +1978,7 @@ NPY_NO_EXPORT PyArray_Descr * + PyArray_DescrNew(PyArray_Descr *base_descr) + { + if (!PyDataType_ISLEGACY(base_descr)) { +- /* ++ /* + * The main use of this function is mutating strings, so probably + * disallowing this is fine in practice. + */ +@@ -2923,13 +2923,10 @@ arraydescr_setstate(_PyArray_LegacyDescr *self, PyObject *args) + } + break; + default: +- /* raise an error */ +- if (PyTuple_GET_SIZE(PyTuple_GET_ITEM(args,0)) > 5) { +- version = PyLong_AsLong(PyTuple_GET_ITEM(args, 0)); +- } +- else { +- version = -1; +- } ++ PyErr_SetString(PyExc_ValueError, ++ "Invalid state while unpickling. Is the pickle corrupted " ++ "or created with a newer NumPy version?"); ++ return NULL; + } + + /* +diff --git a/numpy/_core/tests/test_dtype.py b/numpy/_core/tests/test_dtype.py +index 684672a..086d93c 100644 +--- a/numpy/_core/tests/test_dtype.py ++++ b/numpy/_core/tests/test_dtype.py +@@ -1440,6 +1440,29 @@ def test_pickle_dtype(self, dt): + assert roundtrip_dt == dt + assert hash(dt) == pre_pickle_hash + ++ @pytest.mark.parametrize('dt', [ ++ np.dtype([('a', 'i4'), ('b', 'f8')]), ++ np.dtype('i4, i1', align=True), ++ ]) ++ def test_setstate_invalid_tuple_size(self, dt): ++ # gh-30476 ++ valid_state = dt.__reduce__()[2] ++ dt.__setstate__(valid_state) ++ ++ for size in [1, 2, 3, 4]: ++ with pytest.raises( ++ ValueError, match="Invalid state while unpickling" ++ ): ++ dt.__setstate__(valid_state[:size]) ++ ++ min_extra = 10 - len(valid_state) ++ for extra in range(min_extra, min_extra + 5): ++ extended = valid_state + (None,) * extra ++ with pytest.raises( ++ ValueError, match="Invalid state while unpickling" ++ ): ++ dt.__setstate__(extended) ++ + + class TestPromotion: + """Test cases related to more complex DType promotions. Further promotion +-- +2.55.0 + diff --git a/python3.14-numpy.spec b/python3.14-numpy.spec index 83f70a2..fedfe05 100644 --- a/python3.14-numpy.spec +++ b/python3.14-numpy.spec @@ -22,7 +22,7 @@ Name: python%{python3_pkgversion}-numpy Version: 2.3.4 -Release: 1%{?dist} +Release: 2%{?dist} Summary: A fast multidimensional array facility for Python # Everything is BSD-3-Clause except... @@ -35,6 +35,15 @@ License: BSD-3-Clause AND MIT AND Apache-2.0 AND (Zlib OR BSL-1.0) URL: http://www.numpy.org/ Source0: https://github.com/%{modname}/%{modname}/releases/download/v%{version}/%{modname}-%{version}.tar.gz +# Resolve issues identified by coverity static analysis +# Resolved upstream: +# https://github.com/numpy/numpy/pull/30877 +# https://github.com/numpy/numpy/pull/30647 +# https://github.com/numpy/numpy/pull/30475 +# Sent upstream: +# https://github.com/numpy/numpy/pull/31819 +Patch: coverity-fixes.patch + BuildRequires: python%{python3_pkgversion}-devel BuildRequires: gcc-gfortran gcc gcc-c++ BuildRequires: lapack-devel @@ -230,6 +239,10 @@ export PYTHONPATH=%{buildroot}%{python3_sitearch} %changelog +* Tue Jul 07 2026 Charalampos Stratakis - 2.3.4-2 +- Fix issues identified via Coverity static analysis +- Fixes: RHEL-193002 + * Thu Oct 23 2025 Tomáš Hrnčiar - 2.3.4-1 - Initial import - Fedora contributions by: