#17873 BUG: numpy.putmask respecting writeable flag

Closed a-elhag
Coverage Reach
core/src/multiarray/multiarraymodule.c core/src/multiarray/dtype_transfer.c core/src/multiarray/datetime.c core/src/multiarray/arraytypes.c.src core/src/multiarray/descriptor.c core/src/multiarray/ctors.c core/src/multiarray/scalartypes.c.src core/src/multiarray/nditer_api.c core/src/multiarray/mapping.c core/src/multiarray/item_selection.c core/src/multiarray/nditer_constr.c core/src/multiarray/methods.c core/src/multiarray/nditer_pywrap.c core/src/multiarray/_multiarray_tests.c.src core/src/multiarray/convert_datatype.c core/src/multiarray/compiled_base.c core/src/multiarray/einsum_sumprod.c.src core/src/multiarray/dragon4.c core/src/multiarray/iterators.c core/src/multiarray/arrayobject.c core/src/multiarray/datetime_strings.c core/src/multiarray/calculation.c core/src/multiarray/datetime_busday.c core/src/multiarray/lowlevel_strided_loops.c.src core/src/multiarray/buffer.c core/src/multiarray/getset.c core/src/multiarray/array_coercion.c core/src/multiarray/conversion_utils.c core/src/multiarray/einsum.c.src core/src/multiarray/number.c core/src/multiarray/shape.c core/src/multiarray/scalarapi.c core/src/multiarray/legacy_dtype_implementation.c core/src/multiarray/flagsobject.c core/src/multiarray/convert.c core/src/multiarray/dtypemeta.c core/src/multiarray/array_method.c core/src/multiarray/usertypes.c core/src/multiarray/datetime_busdaycal.c core/src/multiarray/nditer_templ.c.src core/src/multiarray/common.c core/src/multiarray/arrayfunction_override.c core/src/multiarray/refcount.c core/src/multiarray/array_assign_array.c core/src/multiarray/hashdescr.c core/src/multiarray/temp_elide.c core/src/multiarray/alloc.c core/src/multiarray/array_assign_scalar.c core/src/multiarray/vdot.c core/src/multiarray/common.h core/src/multiarray/abstractdtypes.c core/src/multiarray/strfuncs.c core/src/multiarray/typeinfo.c core/src/multiarray/sequence.c core/src/multiarray/methods.h core/src/multiarray/nditer_impl.h core/src/multiarray/dtypemeta.h core/src/multiarray/alloc.h core/src/umath/ufunc_object.c core/src/umath/loops.c.src core/src/umath/simd.inc.src core/src/umath/ufunc_type_resolution.c core/src/umath/_rational_tests.c.src core/src/umath/override.c core/src/umath/scalarmath.c.src core/src/umath/_umath_tests.c.src core/src/umath/matmul.c.src core/src/umath/funcs.inc.src core/src/umath/umathmodule.c core/src/umath/extobj.c core/src/umath/reduction.c core/src/umath/_struct_ufunc_tests.c.src core/src/umath/loops_unary_fp.dispatch.c.src core/src/umath/_operand_flag_tests.c.src core/src/umath/clip.c.src core/src/umath/loops_utils.h core/src/umath/_umath_tests.dispatch.c core/src/umath/fast_loop_macros.h core/src/npysort/timsort.c.src core/src/npysort/quicksort.c.src core/src/npysort/mergesort.c.src core/src/npysort/heapsort.c.src core/src/npysort/selection.c.src core/src/npysort/radixsort.c.src core/src/npysort/npysort_common.h core/src/npysort/binsearch.c.src core/src/common/simd/sse/memory.h core/src/common/simd/sse/arithmetic.h core/src/common/simd/sse/operators.h core/src/common/simd/sse/reorder.h core/src/common/simd/sse/misc.h core/src/common/simd/sse/math.h core/src/common/simd/avx2/memory.h core/src/common/simd/avx2/reorder.h core/src/common/simd/avx2/operators.h core/src/common/simd/avx2/arithmetic.h core/src/common/simd/avx2/misc.h core/src/common/simd/avx2/math.h core/src/common/simd/avx2/utils.h core/src/common/simd/avx512/memory.h core/src/common/simd/avx512/reorder.h core/src/common/simd/avx512/arithmetic.h core/src/common/simd/avx512/operators.h core/src/common/simd/avx512/misc.h core/src/common/simd/avx512/math.h core/src/common/cblasfuncs.c core/src/common/numpyos.c core/src/common/npy_extint128.h core/src/common/npy_cpu_features.c.src core/src/common/npy_longdouble.c core/src/common/lowlevel_strided_loops.h core/src/common/array_assign.c core/src/common/ufunc_override.c core/src/common/get_attr_string.h core/src/common/ucsnarrow.c core/src/common/binop_override.h core/src/common/npy_binsearch.h.src core/src/common/python_xerbla.c core/src/common/npy_ctypes.h core/src/common/npy_partition.h.src core/src/common/npy_import.h core/src/common/npy_cblas.h core/src/common/npy_sort.h.src core/src/common/templ_common.h.src core/src/npymath/halffloat.c core/src/npymath/ieee754.c.src core/src/npymath/npy_math_internal.h.src core/src/npymath/npy_math_complex.c.src core/src/_simd/_simd.dispatch.c.src core/src/_simd/_simd_convert.inc core/src/_simd/_simd_vector.inc core/src/_simd/_simd_arg.inc core/src/_simd/_simd.c core/include/numpy/npy_3kcompat.h core/include/numpy/ndarraytypes.h core/include/numpy/npy_math.h core/include/numpy/ndarrayobject.h core/include/numpy/_neighborhood_iterator_imp.h core/include/numpy/random/distributions.h fft/_pocketfft.c linalg/umath_linalg.c.src linalg/lapack_litemodule.c linalg/lapack_lite/python_xerbla.c random/src/legacy/legacy-distributions.c random/src/mt19937/mt19937-jump.c random/src/mt19937/mt19937.c random/src/mt19937/mt19937.h random/src/distributions/random_hypergeometric.c random/src/distributions/random_mvhg_count.c random/src/distributions/random_mvhg_marginals.c random/src/distributions/logfactorial.c random/src/philox/philox.h random/src/philox/philox.c random/src/pcg64/pcg64.c random/src/pcg64/pcg64.h random/src/sfc64/sfc64.c random/src/sfc64/sfc64.h

No flags found

Use flags to group coverage reports by test type, project and/or folders.
Then setup custom commit statuses and notifications for each flag.

e.g., #unittest #integration

#production #enterprise

#frontend #backend

Learn more about Codecov Flags here.


@@ -2395,6 +2395,10 @@
Loading
2395 2395
                self);
2396 2396
        return -1;
2397 2397
    }
2398 +
    if ((flags & PyBUF_WRITEABLE) == PyBUF_WRITEABLE) {
2399 +
        PyErr_SetString(PyExc_BufferError, "scalar buffer is readonly");
2400 +
        return -1;
2401 +
    }
2398 2402
    PyArray_Descr *descr = PyArray_DescrFromScalar(self);
2399 2403
    if (descr == NULL) {
2400 2404
        return -1;
@@ -2413,6 +2417,7 @@
Loading
2413 2417
    view->shape = NULL;
2414 2418
    view->strides = NULL;
2415 2419
    view->suboffsets = NULL;
2420 +
    view->readonly = 1;  /* assume general (user) scalars are readonly. */
2416 2421
    Py_INCREF(self);
2417 2422
    view->obj = self;
2418 2423
    view->buf = scalar_value(self, descr);
@@ -2444,6 +2449,7 @@
Loading
2444 2449
@name@_getbuffer(PyObject *self, Py_buffer *view, int flags)
2445 2450
{
2446 2451
    if ((flags & PyBUF_WRITEABLE) == PyBUF_WRITEABLE) {
2452 +
        PyErr_SetString(PyExc_BufferError, "scalar buffer is readonly");
2447 2453
        return -1;
2448 2454
    }
2449 2455
    Py@Name@ScalarObject *scalar = (Py@Name@ScalarObject *)self;
@@ -2456,6 +2462,7 @@
Loading
2456 2462
    view->shape = NULL;
2457 2463
    view->strides = NULL;
2458 2464
    view->suboffsets = NULL;
2465 +
    view->readonly = 1;
2459 2466
    Py_INCREF(self);
2460 2467
    view->obj = self;
2461 2468
    view->buf = &(scalar->obval);
@@ -2482,6 +2489,7 @@
Loading
2482 2489
unicode_getbuffer(PyObject *self, Py_buffer *view, int flags)
2483 2490
{
2484 2491
    if ((flags & PyBUF_WRITEABLE) == PyBUF_WRITEABLE) {
2492 +
        PyErr_SetString(PyExc_BufferError, "scalar buffer is readonly");
2485 2493
        return -1;
2486 2494
    }
2487 2495
    PyUnicodeScalarObject *scalar = (PyUnicodeScalarObject *)self;
@@ -2493,6 +2501,7 @@
Loading
2493 2501
    view->shape = NULL;
2494 2502
    view->strides = NULL;
2495 2503
    view->suboffsets = NULL;
2504 +
    view->readonly = 1;
2496 2505
    Py_INCREF(self);
2497 2506
    view->obj = self;
2498 2507
@@ -2522,7 +2531,7 @@
Loading
2522 2531
        view->format = scalar->buffer_fmt;
2523 2532
    }
2524 2533
    else {
2525 -
        scalar->buffer_fmt = PyObject_Malloc(22);
2534 +
        scalar->buffer_fmt = PyMem_Malloc(22);
2526 2535
        if (scalar->buffer_fmt == NULL) {
2527 2536
            Py_SETREF(view->obj, NULL);
2528 2537
            return -1;
@@ -2549,6 +2558,7 @@
Loading
2549 2558
@name@_getbuffer(PyObject *self, Py_buffer *view, int flags)
2550 2559
{
2551 2560
    if ((flags & PyBUF_WRITEABLE) == PyBUF_WRITEABLE) {
2561 +
        PyErr_SetString(PyExc_BufferError, "scalar buffer is readonly");
2552 2562
        return -1;
2553 2563
    }
2554 2564
    Py@Name@ScalarObject *scalar = (Py@Name@ScalarObject *)self;
@@ -2560,6 +2570,7 @@
Loading
2560 2570
    view->shape = &length;
2561 2571
    view->strides = NULL;
2562 2572
    view->suboffsets = NULL;
2573 +
    view->readonly = 1;
2563 2574
    Py_INCREF(self);
2564 2575
    view->obj = self;
2565 2576
@@ -2651,6 +2662,7 @@
Loading
2651 2662
{
2652 2663
    /* note: may be null if it was never requested */
2653 2664
    PyMem_Free(PyArrayScalar_VAL(v, Unicode));
2665 +
    PyMem_Free(((PyUnicodeScalarObject *)v)->buffer_fmt);
2654 2666
    /* delegate to the base class */
2655 2667
    PyUnicode_Type.tp_dealloc(v);
2656 2668
}

@@ -576,6 +576,10 @@
Loading
576 576
        return NULL;
577 577
    }
578 578
579 +
    if (PyArray_FailUnlessWriteable(self, "putmask: output array") < 0) {
580 +
        return NULL;
581 +
    }
582 +
579 583
    mask = (PyArrayObject *)PyArray_FROM_OTF(mask0, NPY_BOOL,
580 584
                                NPY_ARRAY_CARRAY | NPY_ARRAY_FORCECAST);
581 585
    if (mask == NULL) {

@@ -3194,9 +3194,10 @@
Loading
3194 3194
    }
3195 3195
3196 3196
    PyObject *shape2 = convert_shape_to_string(mit->nd, mit->dimensions, "");
3197 -
    if (shape2 == NULL)
3197 +
    if (shape2 == NULL) {
3198 3198
        Py_DECREF(shape1);
3199 3199
        goto finish;
3200 +
    }
3200 3201
3201 3202
    PyErr_Format(PyExc_ValueError,
3202 3203
            "shape mismatch: value array of shape %S could not be broadcast "

@@ -677,11 +677,12 @@
Loading
677 677
                "invalid error argument to test function.");
678 678
    }
679 679
    if (PyArray_RegisterDataType(dtype) < 0) {
680 -
        /* Fix original type in the error_path == 2 case. */
680 +
        /* Fix original type in the error_path == 2 case and delete it */
681 681
        Py_SET_TYPE(dtype, original_type);
682 +
        Py_DECREF(dtype);
682 683
        return NULL;
683 684
    }
684 -
    Py_INCREF(dtype);
685 +
    Py_INCREF(dtype);  /* hold on to the original (leaks a reference) */
685 686
    return (PyObject *)dtype;
686 687
}
687 688

Learn more Showing 14 files with coverage changes found.

Changes in numpy/core/src/multiarray/mapping.c
+2
Loading file...
Changes in numpy/core/src/umath/ufunc_object.c
-1
+1
Loading file...
Changes in numpy/core/src/multiarray/_multiarray_tests.c.src
-1
+1
Loading file...
Changes in numpy/core/src/multiarray/buffer.c
-2
+2
Loading file...
Changes in numpy/core/src/umath/loops.c.src
-39
+39
Loading file...
Changes in numpy/core/src/common/npy_cpu_features.c.src
-26
+26
Loading file...
Changes in numpy/core/src/umath/simd.inc.src
-264
+264
Loading file...
Changes in numpy/core/src/_simd/_simd_vector.inc
-29
+29
Loading file...
Changes in numpy/core/src/common/simd/avx512/misc.h
-9
+9
Loading file...
Changes in numpy/core/src/common/simd/avx512/memory.h
-62
+62
Loading file...
Changes in numpy/core/src/common/simd/avx512/math.h
-6
+6
Loading file...
Changes in numpy/core/src/common/simd/avx512/reorder.h
-39
+39
Loading file...
Changes in numpy/core/src/common/simd/avx512/arithmetic.h
-18
+18
Loading file...
Changes in numpy/core/src/common/simd/avx512/operators.h
-17
+17
Loading file...

14 Commits

Files Coverage
numpy +1.12% 83.75%
Project Totals (157 files) 83.75%
Loading