diff options
Diffstat (limited to 'Python/structmember.c')
| -rw-r--r-- | Python/structmember.c | 83 | 
1 files changed, 55 insertions, 28 deletions
diff --git a/Python/structmember.c b/Python/structmember.c index 7a5a6a4..18bd486 100644 --- a/Python/structmember.c +++ b/Python/structmember.c @@ -197,45 +197,72 @@ PyMember_SetOne(char *addr, PyMemberDef *l, PyObject *v)              WARN("Truncation of value to int");          break;          } -    case Py_T_UINT:{ -        unsigned long ulong_val = PyLong_AsUnsignedLong(v); -        if ((ulong_val == (unsigned long)-1) && PyErr_Occurred()) { -            /* XXX: For compatibility, accept negative int values -               as well. */ -            PyErr_Clear(); -            ulong_val = PyLong_AsLong(v); -            if ((ulong_val == (unsigned long)-1) && -                PyErr_Occurred()) +    case Py_T_UINT: { +        /* XXX: For compatibility, accept negative int values +           as well. */ +        int overflow; +        long long_val = PyLong_AsLongAndOverflow(v, &overflow); +        if (long_val == -1 && PyErr_Occurred()) { +            return -1; +        } +        if (overflow < 0) { +            PyErr_SetString(PyExc_OverflowError, +                            "Python int too large to convert to C long"); +        } +        else if (!overflow) { +            *(unsigned int *)addr = (unsigned int)(unsigned long)long_val; +            if (long_val < 0) { +                WARN("Writing negative value into unsigned field"); +            } +            else if ((unsigned long)long_val > UINT_MAX) { +                WARN("Truncation of value to unsigned short"); +            } +        } +        else { +            unsigned long ulong_val = PyLong_AsUnsignedLong(v); +            if (ulong_val == (unsigned long)-1 && PyErr_Occurred()) {                  return -1; -            *(unsigned int *)addr = (unsigned int)ulong_val; -            WARN("Writing negative value into unsigned field"); -        } else -            *(unsigned int *)addr = (unsigned int)ulong_val; -        if (ulong_val > UINT_MAX) -            WARN("Truncation of value to unsigned int"); -        break; +            } +            *(unsigned int*)addr = (unsigned int)ulong_val; +            if (ulong_val > UINT_MAX) { +                WARN("Truncation of value to unsigned int"); +            }          } +        break; +    }      case Py_T_LONG:{          *(long*)addr = PyLong_AsLong(v);          if ((*(long*)addr == -1) && PyErr_Occurred())              return -1;          break;          } -    case Py_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 long)-1) -                && PyErr_Occurred()) +    case Py_T_ULONG: { +        /* XXX: For compatibility, accept negative int values +           as well. */ +        int overflow; +        long long_val = PyLong_AsLongAndOverflow(v, &overflow); +        if (long_val == -1 && PyErr_Occurred()) { +            return -1; +        } +        if (overflow < 0) { +            PyErr_SetString(PyExc_OverflowError, +                            "Python int too large to convert to C long"); +        } +        else if (!overflow) { +            *(unsigned long *)addr = (unsigned long)long_val; +            if (long_val < 0) { +                WARN("Writing negative value into unsigned field"); +            } +        } +        else { +            unsigned long ulong_val = PyLong_AsUnsignedLong(v); +            if (ulong_val == (unsigned long)-1 && PyErr_Occurred()) {                  return -1; -            WARN("Writing negative value into unsigned field"); +            } +            *(unsigned long*)addr = ulong_val;          }          break; -        } +    }      case Py_T_PYSSIZET:{          *(Py_ssize_t*)addr = PyLong_AsSsize_t(v);          if ((*(Py_ssize_t*)addr == (Py_ssize_t)-1)  | 
