Handle errors when generating a warning.

The value is always written to the returned pointer if getting it was
successful, even if a warning causes an error. (This probably doesn't matter
as the caller will probably discard the value.)

Will backport.
This commit is contained in:
Neal Norwitz 2007-08-05 03:23:31 +00:00
parent f3e93a0268
commit 2ef7582b52
1 changed files with 31 additions and 30 deletions

View File

@ -156,6 +156,12 @@ PyMember_Set(char *addr, struct memberlist *mlist, const char *name, PyObject *v
return -1; return -1;
} }
#define WARN(msg) \
do { \
if (PyErr_Warn(PyExc_RuntimeWarning, msg) < 0) \
return -1; \
} while (0)
int int
PyMember_SetOne(char *addr, PyMemberDef *l, PyObject *v) PyMember_SetOne(char *addr, PyMemberDef *l, PyObject *v)
{ {
@ -178,60 +184,54 @@ PyMember_SetOne(char *addr, PyMemberDef *l, PyObject *v)
addr += l->offset; addr += l->offset;
switch (l->type) { switch (l->type) {
case T_BYTE:{ case T_BYTE:{
long long_val; long long_val = PyInt_AsLong(v);
long_val = PyInt_AsLong(v);
if ((long_val == -1) && PyErr_Occurred()) if ((long_val == -1) && PyErr_Occurred())
return -1; return -1;
*(char*)addr = (char)long_val;
/* XXX: For compatibility, only warn about truncations /* XXX: For compatibility, only warn about truncations
for now. */ for now. */
if ((long_val > CHAR_MAX) || (long_val < CHAR_MIN)) if ((long_val > CHAR_MAX) || (long_val < CHAR_MIN))
PyErr_Warn(PyExc_RuntimeWarning, "Truncation of value to char"); WARN("Truncation of value to char");
*(char*)addr = (char)long_val;
break; break;
} }
case T_UBYTE:{ case T_UBYTE:{
long long_val; long long_val = PyInt_AsLong(v);
long_val = PyInt_AsLong(v);
if ((long_val == -1) && PyErr_Occurred()) if ((long_val == -1) && PyErr_Occurred())
return -1; return -1;
if ((long_val > UCHAR_MAX) || (long_val < 0))
PyErr_Warn(PyExc_RuntimeWarning, "Truncation of value to unsigned char");
*(unsigned char*)addr = (unsigned char)long_val; *(unsigned char*)addr = (unsigned char)long_val;
if ((long_val > UCHAR_MAX) || (long_val < 0))
WARN("Truncation of value to unsigned char");
break; break;
} }
case T_SHORT:{ case T_SHORT:{
long long_val; long long_val = PyInt_AsLong(v);
long_val = PyInt_AsLong(v);
if ((long_val == -1) && PyErr_Occurred()) if ((long_val == -1) && PyErr_Occurred())
return -1; return -1;
if ((long_val > SHRT_MAX) || (long_val < SHRT_MIN))
PyErr_Warn(PyExc_RuntimeWarning, "Truncation of value to short");
*(short*)addr = (short)long_val; *(short*)addr = (short)long_val;
if ((long_val > SHRT_MAX) || (long_val < SHRT_MIN))
WARN("Truncation of value to short");
break; break;
} }
case T_USHORT:{ case T_USHORT:{
long long_val; long long_val = PyInt_AsLong(v);
long_val = PyInt_AsLong(v);
if ((long_val == -1) && PyErr_Occurred()) if ((long_val == -1) && PyErr_Occurred())
return -1; return -1;
if ((long_val > USHRT_MAX) || (long_val < 0))
PyErr_Warn(PyExc_RuntimeWarning, "Truncation of value to unsigned short");
*(unsigned short*)addr = (unsigned short)long_val; *(unsigned short*)addr = (unsigned short)long_val;
if ((long_val > USHRT_MAX) || (long_val < 0))
WARN("Truncation of value to unsigned short");
break; break;
} }
case T_INT:{ case T_INT:{
long long_val; long long_val = PyInt_AsLong(v);
long_val = PyInt_AsLong(v);
if ((long_val == -1) && PyErr_Occurred()) if ((long_val == -1) && PyErr_Occurred())
return -1; return -1;
if ((long_val > INT_MAX) || (long_val < INT_MIN))
PyErr_Warn(PyExc_RuntimeWarning, "Truncation of value to int");
*(int *)addr = (int)long_val; *(int *)addr = (int)long_val;
if ((long_val > INT_MAX) || (long_val < INT_MIN))
WARN("Truncation of value to int");
break; break;
} }
case T_UINT:{ case T_UINT:{
unsigned long ulong_val; unsigned long ulong_val = PyLong_AsUnsignedLong(v);
ulong_val = PyLong_AsUnsignedLong(v);
if ((ulong_val == (unsigned int)-1) && PyErr_Occurred()) { if ((ulong_val == (unsigned int)-1) && PyErr_Occurred()) {
/* XXX: For compatibility, accept negative int values /* XXX: For compatibility, accept negative int values
as well. */ as well. */
@ -239,11 +239,12 @@ PyMember_SetOne(char *addr, PyMemberDef *l, PyObject *v)
ulong_val = PyLong_AsLong(v); ulong_val = PyLong_AsLong(v);
if ((ulong_val == (unsigned int)-1) && PyErr_Occurred()) if ((ulong_val == (unsigned int)-1) && PyErr_Occurred())
return -1; return -1;
PyErr_Warn(PyExc_RuntimeWarning, "Writing negative value into unsigned field"); *(unsigned int *)addr = (unsigned int)ulong_val;
} WARN("Writing negative value into unsigned field");
} else
*(unsigned int *)addr = (unsigned int)ulong_val;
if (ulong_val > UINT_MAX) if (ulong_val > UINT_MAX)
PyErr_Warn(PyExc_RuntimeWarning, "Truncation of value to unsigned int"); WARN("Truncation of value to unsigned int");
*(unsigned int *)addr = (unsigned int)ulong_val;
break; break;
} }
case T_LONG:{ case T_LONG:{
@ -260,9 +261,10 @@ PyMember_SetOne(char *addr, PyMemberDef *l, PyObject *v)
as well. */ as well. */
PyErr_Clear(); PyErr_Clear();
*(unsigned long*)addr = PyLong_AsLong(v); *(unsigned long*)addr = PyLong_AsLong(v);
if ((*(unsigned long*)addr == (unsigned int)-1) && PyErr_Occurred()) if ((*(unsigned long*)addr == (unsigned int)-1)
&& PyErr_Occurred())
return -1; return -1;
PyErr_Warn(PyExc_RuntimeWarning, "Writing negative value into unsigned field"); WARN("Writing negative value into unsigned field");
} }
break; break;
} }
@ -274,8 +276,7 @@ PyMember_SetOne(char *addr, PyMemberDef *l, PyObject *v)
break; break;
} }
case T_FLOAT:{ case T_FLOAT:{
double double_val; double double_val = PyFloat_AsDouble(v);
double_val = PyFloat_AsDouble(v);
if ((double_val == -1) && PyErr_Occurred()) if ((double_val == -1) && PyErr_Occurred())
return -1; return -1;
*(float*)addr = (float)double_val; *(float*)addr = (float)double_val;