mirror of
https://github.com/python/cpython.git
synced 2025-07-27 21:24:32 +00:00
Patch #1549049: Rewrite type conversion in structmember.
Fixes #1545696 and #1566140. Will backport to 2.5.
This commit is contained in:
parent
efb57072fe
commit
b5bc537c5e
5 changed files with 299 additions and 64 deletions
|
@ -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:
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue