summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEric Blake <eblake@redhat.com>2012-03-31 09:45:48 -0600
committerDaniel Veillard <veillard@redhat.com>2012-04-05 11:37:51 +0800
commit410cb3c0e8a7e6d6db41a83b186ba2b2483822cf (patch)
tree9d86cd21efc3db39c573f3fc8592691c66ce4a4c
parent0354f6de747e8e2968cb28374f2488cd1a1b3aeb (diff)
downloadlibvirt-python-v6-410cb3c0e8a7e6d6db41a83b186ba2b2483822cf.tar.gz
libvirt-python-v6-410cb3c0e8a7e6d6db41a83b186ba2b2483822cf.tar.xz
libvirt-python-v6-410cb3c0e8a7e6d6db41a83b186ba2b2483822cf.zip
https://bugzilla.redhat.com/show_bug.cgi?id=807751 Laszlo Ersek pointed out that in trying to convert a long to an unsigned int, we used: long long_val = ...; if ((unsigned int)long_val == long_val) According to C99 integer promotion rules, the if statement is equivalent to: (unsigned long)(unsigned int)long_val == (unsigned long)long_val since you get an unsigned comparison if at least one side is unsigned, using the largest rank of the two sides; but on 32-bit platforms, where unsigned long and unsigned int are the same size, this comparison is always true and ends up converting negative long_val into posigive unsigned int values, rather than rejecting the negative value as we had originally intended (python longs are unbounded size, and we don't want to do silent modulo arithmetic when converting to C code). Fix this by using direct comparisons, rather than casting. * python/typewrappers.c (libvirt_intUnwrap, libvirt_uintUnwrap) (libvirt_ulongUnwrap, libvirt_ulonglongUnwrap): Fix conversion checks. (cherry picked from commit 4a86c2bb4b2d8183b76ba44659bb6d2eab1f1573)
-rw-r--r--typewrappers.c27
1 files changed, 20 insertions, 7 deletions
diff --git a/typewrappers.c b/typewrappers.c
index 8b9df75..252e239 100644
--- a/typewrappers.c
+++ b/typewrappers.c
@@ -132,7 +132,7 @@ libvirt_intUnwrap(PyObject *obj, int *val)
if ((long_val == -1) && PyErr_Occurred())
return -1;
- if ((int)long_val == long_val) {
+ if (long_val >= INT_MIN && long_val <= INT_MAX) {
*val = long_val;
} else {
PyErr_SetString(PyExc_OverflowError,
@@ -151,7 +151,7 @@ libvirt_uintUnwrap(PyObject *obj, unsigned int *val)
if ((long_val == -1) && PyErr_Occurred())
return -1;
- if ((unsigned int)long_val == long_val) {
+ if (long_val >= 0 && long_val <= UINT_MAX) {
*val = long_val;
} else {
PyErr_SetString(PyExc_OverflowError,
@@ -183,7 +183,13 @@ libvirt_ulongUnwrap(PyObject *obj, unsigned long *val)
if ((long_val == -1) && PyErr_Occurred())
return -1;
- *val = long_val;
+ if (long_val >= 0) {
+ *val = long_val;
+ } else {
+ PyErr_SetString(PyExc_OverflowError,
+ "negative Python int cannot be converted to C unsigned long");
+ return -1;
+ }
return 0;
}
@@ -207,16 +213,23 @@ int
libvirt_ulonglongUnwrap(PyObject *obj, unsigned long long *val)
{
unsigned long long ullong_val = -1;
+ long long llong_val;
/* The PyLong_AsUnsignedLongLong doesn't check the type of
* obj, only accept argument of PyLong_Type, so we check it instead.
*/
- if (PyInt_Check(obj))
- ullong_val = PyInt_AsLong(obj);
- else if (PyLong_Check(obj))
+ if (PyInt_Check(obj)) {
+ llong_val = PyInt_AsLong(obj);
+ if (llong_val < 0)
+ PyErr_SetString(PyExc_OverflowError,
+ "negative Python int cannot be converted to C unsigned long long");
+ else
+ ullong_val = llong_val;
+ } else if (PyLong_Check(obj)) {
ullong_val = PyLong_AsUnsignedLongLong(obj);
- else
+ } else {
PyErr_SetString(PyExc_TypeError, "an integer is required");
+ }
if ((ullong_val == -1) && PyErr_Occurred())
return -1;