PyArray_DescrFromType can return NULL
static PyArray_Descr *
PyArray_DescrFromType(int type)
{
PyArray_Descr *ret = NULL;
if (type < PyArray_NTYPES) {
ret = _builtin_descrs[type];
}
else if (type == PyArray_NOTYPE) {
/*
* This needs to not raise an error so
* that PyArray_DescrFromType(PyArray_NOTYPE)
* works for backwards-compatible C-API
*/
return NULL;
}
else if ((type == PyArray_CHAR) || (type == PyArray_CHARLTR)) {
ret = PyArray_DescrNew(_builtin_descrs[PyArray_STRING]);
if (ret == NULL) {
return NULL;
}
ret->elsize = 1;
ret->type = PyArray_CHARLTR;
return ret;
}
else if (PyTypeNum_ISUSERDEF(type)) {
ret = userdescrs[type - PyArray_USERDEF];
}
else {
int num = PyArray_NTYPES;
if (type < _MAX_LETTER) {
num = (int) _letter_to_num[type];
}
if (num >= PyArray_NTYPES) {
ret = NULL;
}
else {
ret = _builtin_descrs[num];
}
}
if (ret == NULL) {
PyErr_SetString(PyExc_ValueError,
"Invalid data-type for array");
}
else {
Py_INCREF(ret);
}
return ret;
}
Yet it is unchecked in several places:
static int
PyArray_CanCastSafely(int fromtype, int totype)
{
PyArray_Descr *from, *to;
register int felsize, telsize;
if (fromtype == totype) return 1;
if (fromtype == PyArray_BOOL) return 1;
if (totype == PyArray_BOOL) return 0;
if (totype == PyArray_OBJECT || totype == PyArray_VOID) return 1;
if (fromtype == PyArray_OBJECT || fromtype == PyArray_VOID) return 0;
from = PyArray_DescrFromType(fromtype);
/*
* cancastto is a PyArray_NOTYPE terminated C-int-array of types that
* the data-type can be cast to safely.
*/
if (from->f->cancastto) {
int *curtype;
curtype = from->f->cancastto;
while (*curtype != PyArray_NOTYPE) {
if (*curtype++ == totype) return 1;
}
}
if (PyTypeNum_ISUSERDEF(totype)) return 0;
to = PyArray_DescrFromType(totype);
telsize = to->elsize;
felsize = from->elsize;
Py_DECREF(from);
Py_DECREF(to);
switch(fromtype) {
case PyArray_BYTE:
case PyArray_SHORT:
case PyArray_INT:
case PyArray_LONG:
case PyArray_LONGLONG:
if (PyTypeNum_ISINTEGER(totype)) {
if (PyTypeNum_ISUNSIGNED(totype)) {
return 0;
}
else {
return (telsize >= felsize);
}
}
else if (PyTypeNum_ISFLOAT(totype)) {
if (felsize < 8)
return (telsize > felsize);
else
return (telsize >= felsize);
}
else if (PyTypeNum_ISCOMPLEX(totype)) {
if (felsize < 8)
return ((telsize >> 1) > felsize);
else
return ((telsize >> 1) >= felsize);
}
else return totype > fromtype;
case PyArray_UBYTE:
case PyArray_USHORT:
case PyArray_UINT:
case PyArray_ULONG:
case PyArray_ULONGLONG:
if (PyTypeNum_ISINTEGER(totype)) {
if (PyTypeNum_ISSIGNED(totype)) {
return (telsize > felsize);
}
else {
return (telsize >= felsize);
}
}
else if (PyTypeNum_ISFLOAT(totype)) {
if (felsize < 8)
return (telsize > felsize);
else
return (telsize >= felsize);
}
else if (PyTypeNum_ISCOMPLEX(totype)) {
if (felsize < 8)
return ((telsize >> 1) > felsize);
else
return ((telsize >> 1) >= felsize);
}
else return totype > fromtype;
case PyArray_FLOAT:
case PyArray_DOUBLE:
case PyArray_LONGDOUBLE:
if (PyTypeNum_ISCOMPLEX(totype))
return ((telsize >> 1) >= felsize);
else
return (totype > fromtype);
case PyArray_CFLOAT:
case PyArray_CDOUBLE:
case PyArray_CLONGDOUBLE:
return (totype > fromtype);
case PyArray_STRING:
case PyArray_UNICODE:
return (totype > fromtype);
default:
return 0;
}
}
Furthermore, the last function can fail, but doesn't seem to have an error return. What is the best way to go about cleaning this up?
Chuck