diff options
author | Eric Wieser <wieser.eric@gmail.com> | 2019-06-05 00:18:09 -0700 |
---|---|---|
committer | Eric Wieser <wieser.eric@gmail.com> | 2019-06-05 19:49:39 -0700 |
commit | 2a1b2e5ed87a9dcf39342c394f815ccfbc93b7bd (patch) | |
tree | 031aed8e02f035e37d01ee2fa7c185149fdaddc1 /numpy | |
parent | 5971d6099fbb410d9cb0003361c755bee598a1dc (diff) | |
download | numpy-2a1b2e5ed87a9dcf39342c394f815ccfbc93b7bd.tar.gz |
BUG: Prevent unsafe string concatenation
This did not handle exceptions correctly.
Changed to use python to format the exception like all the others in this file.
This also adds quotes around the ufunc name.
Diffstat (limited to 'numpy')
-rw-r--r-- | numpy/core/_exceptions.py | 16 | ||||
-rw-r--r-- | numpy/core/src/umath/ufunc_type_resolution.c | 34 | ||||
-rw-r--r-- | numpy/core/tests/test_datetime.py | 2 |
3 files changed, 39 insertions, 13 deletions
diff --git a/numpy/core/_exceptions.py b/numpy/core/_exceptions.py index 1dcea6255..a1af7a78d 100644 --- a/numpy/core/_exceptions.py +++ b/numpy/core/_exceptions.py @@ -37,6 +37,22 @@ class UFuncTypeError(TypeError): @_display_as_base +class _UFuncBinaryResolutionError(UFuncTypeError): + """ Thrown when a binary resolution fails """ + def __init__(self, ufunc, dtypes): + super().__init__(ufunc) + self.dtypes = tuple(dtypes) + assert len(self.dtypes) == 2 + + def __str__(self): + return ( + "ufunc {!r} cannot use operands with types {!r} and {!r}" + ).format( + self.ufunc.__name__, *self.dtypes + ) + + +@_display_as_base class _UFuncNoLoopError(UFuncTypeError): """ Thrown when a ufunc loop cannot be found """ def __init__(self, ufunc, dtypes): diff --git a/numpy/core/src/umath/ufunc_type_resolution.c b/numpy/core/src/umath/ufunc_type_resolution.c index 8207be666..58f915c6e 100644 --- a/numpy/core/src/umath/ufunc_type_resolution.c +++ b/numpy/core/src/umath/ufunc_type_resolution.c @@ -74,18 +74,28 @@ npy_casting_to_string(NPY_CASTING casting) */ static int raise_binary_type_reso_error(PyUFuncObject *ufunc, PyArrayObject **operands) { - PyObject *errmsg; - const char *ufunc_name = ufunc_get_name_cstr(ufunc); - errmsg = PyUString_FromFormat("ufunc %s cannot use operands " - "with types ", ufunc_name); - PyUString_ConcatAndDel(&errmsg, - PyObject_Repr((PyObject *)PyArray_DESCR(operands[0]))); - PyUString_ConcatAndDel(&errmsg, - PyUString_FromString(" and ")); - PyUString_ConcatAndDel(&errmsg, - PyObject_Repr((PyObject *)PyArray_DESCR(operands[1]))); - PyErr_SetObject(PyExc_TypeError, errmsg); - Py_DECREF(errmsg); + static PyObject *exc_type = NULL; + PyObject *exc_value; + + npy_cache_import( + "numpy.core._exceptions", "_UFuncBinaryResolutionError", + &exc_type); + if (exc_type == NULL) { + return -1; + } + + /* produce an error object */ + exc_value = Py_BuildValue( + "O(OO)", ufunc, + (PyObject *)PyArray_DESCR(operands[0]), + (PyObject *)PyArray_DESCR(operands[1]) + ); + if (exc_value == NULL){ + return -1; + } + PyErr_SetObject(exc_type, exc_value); + Py_DECREF(exc_value); + return -1; } diff --git a/numpy/core/tests/test_datetime.py b/numpy/core/tests/test_datetime.py index f48bfdf9b..f99c0f72b 100644 --- a/numpy/core/tests/test_datetime.py +++ b/numpy/core/tests/test_datetime.py @@ -1825,7 +1825,7 @@ class TestDateTime(object): # NOTE: some of the operations may be supported # in the future with assert_raises_regex(TypeError, - "remainder cannot use operands with types"): + "'remainder' cannot use operands with types"): val1 % val2 def test_timedelta_arange_no_dtype(self): |