Patch #1549049: Rewrite type conversion in structmember.

Fixes #1545696 and #1566140. Will backport to 2.5.
This commit is contained in:
Martin v. Löwis 2006-10-27 06:16:31 +00:00
parent efb57072fe
commit b5bc537c5e
5 changed files with 299 additions and 64 deletions

View file

@ -62,29 +62,28 @@ PyMember_GetOne(const char *addr, PyMemberDef *l)
addr += l->offset;
switch (l->type) {
case T_BYTE:
v = PyInt_FromLong(
(long) (((*(char*)addr & 0xff) ^ 0x80) - 0x80));
v = PyInt_FromLong(*(char*)addr);
break;
case T_UBYTE:
v = PyInt_FromLong((long) *(char*)addr & 0xff);
v = PyLong_FromUnsignedLong(*(unsigned char*)addr);
break;
case T_SHORT:
v = PyInt_FromLong((long) *(short*)addr);
v = PyInt_FromLong(*(short*)addr);
break;
case T_USHORT:
v = PyInt_FromLong((long) *(unsigned short*)addr);
v = PyLong_FromUnsignedLong(*(unsigned short*)addr);
break;
case T_INT:
v = PyInt_FromLong((long) *(int*)addr);
v = PyInt_FromLong(*(int*)addr);
break;
case T_UINT:
v = PyInt_FromLong((long) *(unsigned int*)addr);
v = PyLong_FromUnsignedLong(*(unsigned int*)addr);
break;
case T_LONG:
v = PyInt_FromLong(*(long*)addr);
break;
case T_ULONG:
v = PyLong_FromDouble((double) *(unsigned long*)addr);
v = PyLong_FromUnsignedLong(*(unsigned long*)addr);
break;
case T_FLOAT:
v = PyFloat_FromDouble((double)*(float*)addr);
@ -175,68 +174,107 @@ PyMember_SetOne(char *addr, PyMemberDef *l, PyObject *v)
}
addr += l->offset;
switch (l->type) {
case T_BYTE:
case T_UBYTE:
if (!PyInt_Check(v)) {
PyErr_BadArgument();
case T_BYTE:{
long long_val;
long_val = PyInt_AsLong(v);
if ((long_val == -1) && PyErr_Occurred())
return -1;
}
*(char*)addr = (char) PyInt_AsLong(v);
/* XXX: For compatibility, only warn about truncations
for now. */
if ((long_val > CHAR_MAX) || (long_val < CHAR_MIN))
PyErr_Warn(PyExc_RuntimeWarning, "Truncation of value to char");
*(char*)addr = (char)long_val;
break;
case T_SHORT:
case T_USHORT:
if (!PyInt_Check(v)) {
PyErr_BadArgument();
return -1;
}
*(short*)addr = (short) PyInt_AsLong(v);
break;
case T_UINT:
case T_INT:
if (!PyInt_Check(v)) {
PyErr_BadArgument();
case T_UBYTE:{
long long_val;
long_val = PyInt_AsLong(v);
if ((long_val == -1) && PyErr_Occurred())
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;
break;
}
*(int*)addr = (int) PyInt_AsLong(v);
break;
case T_LONG:
if (!PyInt_Check(v)) {
PyErr_BadArgument();
case T_SHORT:{
long long_val;
long_val = PyInt_AsLong(v);
if ((long_val == -1) && PyErr_Occurred())
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;
break;
}
*(long*)addr = PyInt_AsLong(v);
break;
case T_ULONG:
if (PyInt_Check(v))
*(long*)addr = PyInt_AsLong(v);
else if (PyLong_Check(v))
*(long*)addr = PyLong_AsLong(v);
else {
PyErr_BadArgument();
case T_USHORT:{
long long_val;
long_val = PyInt_AsLong(v);
if ((long_val == -1) && PyErr_Occurred())
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;
break;
}
case T_INT:{
long long_val;
long_val = PyInt_AsLong(v);
if ((long_val == -1) && PyErr_Occurred())
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;
break;
}
case T_UINT:{
unsigned long ulong_val;
ulong_val = PyLong_AsUnsignedLong(v);
if ((ulong_val == (unsigned int)-1) && PyErr_Occurred()) {
/* XXX: For compatibility, accept negative int values
as well. */
PyErr_Clear();
ulong_val = PyLong_AsLong(v);
if ((ulong_val == (unsigned int)-1) && PyErr_Occurred())
return -1;
PyErr_Warn(PyExc_RuntimeWarning, "Writing negative value into unsigned field");
}
if (ulong_val > UINT_MAX)
PyErr_Warn(PyExc_RuntimeWarning, "Truncation of value to unsigned int");
*(unsigned int *)addr = (unsigned int)ulong_val;
break;
}
case T_LONG:{
*(long*)addr = PyLong_AsLong(v);
if ((*(long*)addr == -1) && PyErr_Occurred())
return -1;
break;
}
case T_ULONG:{
*(unsigned long*)addr = PyLong_AsUnsignedLong(v);
if ((*(unsigned long*)addr == (unsigned long)-1)
&& PyErr_Occurred()) {
/* XXX: For compatibility, accept negative int values
as well. */
PyErr_Clear();
*(unsigned long*)addr = PyLong_AsLong(v);
if ((*(unsigned long*)addr == (unsigned int)-1) && PyErr_Occurred())
return -1;
PyErr_Warn(PyExc_RuntimeWarning, "Writing negative value into unsigned field");
}
break;
case T_FLOAT:
if (PyInt_Check(v))
*(float*)addr =
(float) PyInt_AsLong(v);
else if (PyFloat_Check(v))
*(float*)addr =
(float) PyFloat_AsDouble(v);
else {
PyErr_BadArgument();
return -1;
}
case T_FLOAT:{
double double_val;
double_val = PyFloat_AsDouble(v);
if ((double_val == -1) && PyErr_Occurred())
return -1;
*(float*)addr = (float)double_val;
break;
}
case T_DOUBLE:
if (PyInt_Check(v))
*(double*)addr = (double) PyInt_AsLong(v);
else if (PyFloat_Check(v))
*(double*)addr = PyFloat_AsDouble(v);
else {
PyErr_BadArgument();
*(double*)addr = PyFloat_AsDouble(v);
if ((*(double*)addr == -1) && PyErr_Occurred())
return -1;
}
break;
case T_OBJECT:
case T_OBJECT_EX: