summaryrefslogtreecommitdiffstats
path: root/Python
diff options
context:
space:
mode:
authorMartin v. Löwis <martin@v.loewis.de>2006-10-27 06:16:31 (GMT)
committerMartin v. Löwis <martin@v.loewis.de>2006-10-27 06:16:31 (GMT)
commitb5bc537c5eac8115c2bbc6e7ec75578632e2164c (patch)
tree8e06807e7f12b01c3e6cd2e852afb4ce0d6b131a /Python
parentefb57072feb9da7ff7870e36f0fc9272a103de80 (diff)
downloadcpython-b5bc537c5eac8115c2bbc6e7ec75578632e2164c.zip
cpython-b5bc537c5eac8115c2bbc6e7ec75578632e2164c.tar.gz
cpython-b5bc537c5eac8115c2bbc6e7ec75578632e2164c.tar.bz2
Patch #1549049: Rewrite type conversion in structmember.
Fixes #1545696 and #1566140. Will backport to 2.5.
Diffstat (limited to 'Python')
-rw-r--r--Python/structmember.c144
1 files changed, 91 insertions, 53 deletions
diff --git a/Python/structmember.c b/Python/structmember.c
index 54eb055..94d222a 100644
--- a/Python/structmember.c
+++ b/Python/structmember.c
@@ -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);
+ 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;
- case T_UINT:
- case T_INT:
- 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;
}
- *(int*)addr = (int) PyInt_AsLong(v);
+ 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_LONG:
- if (!PyInt_Check(v)) {
- PyErr_BadArgument();
+ }
+ 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");
}
- *(long*)addr = PyInt_AsLong(v);
+ 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_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_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: