Skip to content

Commit

Permalink
BUG: Prevent unsafe string concatenation
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
eric-wieser committed Jun 6, 2019
1 parent 5971d60 commit 2a1b2e5
Show file tree
Hide file tree
Showing 3 changed files with 39 additions and 13 deletions.
16 changes: 16 additions & 0 deletions numpy/core/_exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,22 @@ def __init__(self, ufunc):
self.ufunc = ufunc


@_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 """
Expand Down
34 changes: 22 additions & 12 deletions numpy/core/src/umath/ufunc_type_resolution.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand Down
2 changes: 1 addition & 1 deletion numpy/core/tests/test_datetime.py
Original file line number Diff line number Diff line change
Expand Up @@ -1825,7 +1825,7 @@ def test_timedelta_modulus_type_resolution(self, val1, val2):
# 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):
Expand Down

0 comments on commit 2a1b2e5

Please sign in to comment.