[libvirt] [PATCH] python: improve conversion validation
Osier Yang
jyang at redhat.com
Sat Mar 31 07:36:23 UTC 2012
On 03/31/2012 02:49 AM, Eric Blake wrote:
> 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.
> ---
> python/typewrappers.c | 27 ++++++++++++++++++++-------
> 1 files changed, 20 insertions(+), 7 deletions(-)
>
> diff --git a/python/typewrappers.c b/python/typewrappers.c
> index af209e6..4ae3ee1 100644
> --- a/python/typewrappers.c
> +++ b/python/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_MAX&& long_val>= INT_MIN) {
> *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;
Looks good, ACK
Osier
More information about the libvir-list
mailing list