]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
Remove PyInt_CheckExact. Add PyLong_AsLongAndOverflow.
authorMartin v. Löwis <martin@v.loewis.de>
Tue, 4 Dec 2007 22:10:37 +0000 (22:10 +0000)
committerMartin v. Löwis <martin@v.loewis.de>
Tue, 4 Dec 2007 22:10:37 +0000 (22:10 +0000)
15 files changed:
Doc/c-api/concrete.rst
Include/longobject.h
Modules/_csv.c
Modules/_cursesmodule.c
Modules/_tkinter.c
Modules/datetimemodule.c
Modules/socketmodule.c
Modules/timemodule.c
Objects/exceptions.c
Objects/frameobject.c
Objects/listobject.c
Objects/longobject.c
PC/_msi.c
Python/bltinmodule.c
Python/ceval.c

index eefd927f889f4f5c7baa6c36a7a1dfe26e8b7363..f90ab4f2ad1d7b9f4e422ec950f6d9b5274774d0 100644 (file)
@@ -211,10 +211,6 @@ All integers are implemented as "long" integer objects of arbitrary size.
    :ctype:`PyLongObject`.
 
 
-.. XXX cfunction PyInt_CheckExact(PyObject *p) checks if argument is a long
-   object and fits into a C long
-
-
 .. cfunction:: PyObject* PyLong_FromLong(long v)
 
    Return a new :ctype:`PyLongObject` object from *v*, or *NULL* on failure.
@@ -297,7 +293,16 @@ All integers are implemented as "long" integer objects of arbitrary size.
       single: OverflowError (built-in exception)
 
    Return a C :ctype:`long` representation of the contents of *pylong*.  If
-   *pylong* is greater than :const:`LONG_MAX`, an :exc:`OverflowError` is raised.
+   *pylong* is greater than :const:`LONG_MAX`, raise an :exc:`OverflowError`,
+   and return -1. Convert non-long objects automatically to long first,
+   and return -1 if that raises exceptions.
+
+.. cfunction:: long PyLong_AsLongAndOverflow(PyObject *pylong, int* overflow)
+
+   Return a C :ctype:`long` representation of the contents of *pylong*.  If
+   *pylong* is greater than :const:`LONG_MAX`, return -1 and
+   set `*overflow` to 1 (for overflow) or -1 (for underflow). 
+   If an exception is set because of type errors, also return -1.
 
 
 .. cfunction:: unsigned long PyLong_AsUnsignedLong(PyObject *pylong)
index 5740f98deba09611b0c430825980bc814f7686e6..e1ee5eead9e32f62e70b2f3f1826933f600918f7 100644 (file)
@@ -14,7 +14,6 @@ PyAPI_DATA(PyTypeObject) PyLong_Type;
 #define PyLong_Check(op) \
                PyType_FastSubclass(Py_Type(op), Py_TPFLAGS_LONG_SUBCLASS)
 #define PyLong_CheckExact(op) (Py_Type(op) == &PyLong_Type)
-#define PyInt_CheckExact(op) (PyLong_CheckExact(op) && _PyLong_FitsInLong(op))
 
 PyAPI_FUNC(PyObject *) PyLong_FromLong(long);
 PyAPI_FUNC(PyObject *) PyLong_FromUnsignedLong(unsigned long);
@@ -22,6 +21,7 @@ PyAPI_FUNC(PyObject *) PyLong_FromSize_t(size_t);
 PyAPI_FUNC(PyObject *) PyLong_FromSsize_t(Py_ssize_t);
 PyAPI_FUNC(PyObject *) PyLong_FromDouble(double);
 PyAPI_FUNC(long) PyLong_AsLong(PyObject *);
+PyAPI_FUNC(long) PyLong_AsLongAndOverflow(PyObject *, int *);
 PyAPI_FUNC(Py_ssize_t) PyLong_AsSsize_t(PyObject *);
 PyAPI_FUNC(size_t) PyLong_AsSize_t(PyObject *);
 PyAPI_FUNC(unsigned long) PyLong_AsUnsignedLong(PyObject *);
index c30cea98d93b33f1459e547ed8753d8088d41f60..aee490ccd329a511245e5a146d59ef77b2839687 100644 (file)
@@ -181,12 +181,23 @@ _set_int(const char *name, int *target, PyObject *src, int dflt)
        if (src == NULL)
                *target = dflt;
        else {
-               if (!PyInt_CheckExact(src)) {
+               long value;
+               if (!PyLong_CheckExact(src)) {
                        PyErr_Format(PyExc_TypeError, 
                                     "\"%s\" must be an integer", name);
                        return -1;
                }
-               *target = PyLong_AsLong(src);
+               value = PyLong_AsLong(src);
+               if (value == -1 && PyErr_Occurred())
+                       return -1;
+#if SIZEOF_LONG > SIZEOF_INT
+               if (value > INT_MAX || value < INT_MIN) {
+                       PyErr_Format(PyExc_ValueError,
+                                    "integer out of range for \"%s\"", name);
+                       return -1;
+               }
+#endif
+               *target = (int)value;
        }
        return 0;
 }
@@ -1385,12 +1396,16 @@ csv_field_size_limit(PyObject *module, PyObject *args)
        if (!PyArg_UnpackTuple(args, "field_size_limit", 0, 1, &new_limit))
                return NULL;
        if (new_limit != NULL) {
-               if (!PyInt_CheckExact(new_limit)) {
+               if (!PyLong_CheckExact(new_limit)) {
                        PyErr_Format(PyExc_TypeError, 
                                     "limit must be an integer");
                        return NULL;
                }
                field_limit = PyLong_AsLong(new_limit);
+               if (field_limit == -1 && PyErr_Occurred()) {
+                       field_limit = old_limit;
+                       return NULL;
+               }
        }
        return PyLong_FromLong(old_limit);
 }
index 1fc7da7f1b378ccee06f72a4411b9bc7fda101bd..d1cd15518c991d3f824f76e99ca37659571fac3d 100644 (file)
@@ -196,8 +196,13 @@ PyCursesCheckERR(int code, char *fname)
 static int 
 PyCurses_ConvertToChtype(PyObject *obj, chtype *ch)
 {
-  if (PyInt_CheckExact(obj)) {
-    *ch = (chtype) PyLong_AsLong(obj);
+  if (PyLong_CheckExact(obj)) {
+    int overflow;
+    /* XXX should the truncation by the cast also be reported
+       as an error? */
+    *ch = (chtype) PyLong_AsLongAndOverflow(obj, &overflow);
+    if (overflow)
+      return 0;
   } else if(PyString_Check(obj) 
            && (PyString_Size(obj) == 1)) {
     *ch = (chtype) *PyString_AsString(obj);
index c755f89ba3265bda00d3b85445c522e3a3432185..2a341abb9ddddd04fbf52cf9fcde3e9ed6349c71 100644 (file)
@@ -863,14 +863,21 @@ static Tcl_Obj*
 AsObj(PyObject *value)
 {
        Tcl_Obj *result;
+       long longVal;
+       int overflow;
 
        if (PyString_Check(value))
                return Tcl_NewStringObj(PyString_AS_STRING(value),
                                        PyString_GET_SIZE(value));
        else if (PyBool_Check(value))
                return Tcl_NewBooleanObj(PyObject_IsTrue(value));
-       else if (PyInt_CheckExact(value))
-               return Tcl_NewLongObj(PyLong_AS_LONG(value));
+       else if (PyLong_CheckExact(value) &&
+                ((longVal = PyLong_AsLongAndOverflow(value, &overflow)),
+                 !overflow)) {
+               /* If there is an overflow in the long conversion,
+                  fall through to default object handling. */
+               return Tcl_NewLongObj(longVal);
+       }
        else if (PyFloat_Check(value))
                return Tcl_NewDoubleObj(PyFloat_AS_DOUBLE(value));
        else if (PyTuple_Check(value)) {
index 6955c784433297090d657fb825c9dcb65e69826e..8eb7e045d9bf17c630d750374885f2bd31554e41 100644 (file)
@@ -3827,7 +3827,7 @@ datetime_strptime(PyObject *cls, PyObject *args)
        Py_DECREF(module);
 
        if (obj != NULL) {
-               int i, good_timetuple = 1;
+               int i, good_timetuple = 1, overflow;
                long int ia[6];
                if (PySequence_Check(obj) && PySequence_Size(obj) >= 6)
                        for (i=0; i < 6; i++) {
@@ -3836,8 +3836,11 @@ datetime_strptime(PyObject *cls, PyObject *args)
                                        Py_DECREF(obj);
                                        return NULL;
                                }
-                               if (PyInt_CheckExact(p))
-                                       ia[i] = PyLong_AsLong(p);
+                               if (PyLong_CheckExact(p)) {
+                                       ia[i] = PyLong_AsLongAndOverflow(p, &overflow);
+                                       if (overflow)
+                                               good_timetuple = 0;
+                               }
                                else
                                        good_timetuple = 0;
                                Py_DECREF(p);
index 926f059ed543bfc90b350cf32e5f04547c6494fd..c1fb5aa9e6c02d7c1c5b5c5f4deba0accf7a791d 100644 (file)
@@ -3595,8 +3595,11 @@ socket_getaddrinfo(PyObject *self, PyObject *args)
                                "getaddrinfo() argument 1 must be string or None");
                return NULL;
        }
-       if (PyInt_CheckExact(pobj)) {
-               PyOS_snprintf(pbuf, sizeof(pbuf), "%ld", PyLong_AsLong(pobj));
+       if (PyLong_CheckExact(pobj)) {
+               long value = PyLong_AsLong(pobj);
+               if (value == -1 && PyErr_Occurred())
+                       goto err;
+               PyOS_snprintf(pbuf, sizeof(pbuf), "%ld", value);
                pptr = pbuf;
        } else if (PyUnicode_Check(pobj)) {
                pptr = PyUnicode_AsString(pobj);
index 4196381baad42116634609124195e460142802ec..c64a3564713d36057ad8ffe943c8732754e13b3f 100644 (file)
@@ -392,8 +392,8 @@ gettmarg(PyObject *args, struct tm *p)
        if (y < 1900) {
                PyObject *accept = PyDict_GetItemString(moddict,
                                                        "accept2dyear");
-               if (accept == NULL || !PyInt_CheckExact(accept) ||
-                   PyLong_AsLong(accept) == 0) {
+               if (accept == NULL || !PyLong_CheckExact(accept) ||
+                   !PyObject_IsTrue(accept)) {
                        PyErr_SetString(PyExc_ValueError,
                                        "year >= 1900 required");
                        return 0;
index cbcda7b06602d57b83b44f94dea931e6cd2a952e..965573330012d600380c05539aaeb841488f5c0b 100644 (file)
@@ -929,6 +929,10 @@ SyntaxError_str(PySyntaxErrorObject *self)
 {
     int have_lineno = 0;
     char *filename = 0;
+    /* Below, we always ignore overflow errors, just printing -1.
+       Still, we cannot allow an OverflowError to be raised, so
+       we need to call PyLong_AsLongAndOverflow. */
+    int overflow;
 
     /* XXX -- do all the additional formatting with filename and
        lineno here */
@@ -936,7 +940,7 @@ SyntaxError_str(PySyntaxErrorObject *self)
     if (self->filename && PyUnicode_Check(self->filename)) {
            filename = PyUnicode_AsString(self->filename);
     }
-    have_lineno = (self->lineno != NULL) && PyInt_CheckExact(self->lineno);
+    have_lineno = (self->lineno != NULL) && PyLong_CheckExact(self->lineno);
 
     if (!filename && !have_lineno)
         return PyObject_Str(self->msg ? self->msg : Py_None);
@@ -945,7 +949,7 @@ SyntaxError_str(PySyntaxErrorObject *self)
         return PyUnicode_FromFormat("%S (%s, line %ld)",
                    self->msg ? self->msg : Py_None,
                    my_basename(filename),
-                   PyLong_AsLong(self->lineno));
+                  PyLong_AsLongAndOverflow(self->lineno, &overflow));
     else if (filename)
         return PyUnicode_FromFormat("%S (%s)",
                    self->msg ? self->msg : Py_None,
@@ -953,7 +957,7 @@ SyntaxError_str(PySyntaxErrorObject *self)
     else /* only have_lineno */
         return PyUnicode_FromFormat("%S (line %ld)",
                    self->msg ? self->msg : Py_None,
-                   PyLong_AsLong(self->lineno));
+                   PyLong_AsLongAndOverflow(self->lineno, &overflow));
 }
 
 static PyMemberDef SyntaxError_members[] = {
index 0e6d9f8e5d519f118dbf3549ce271410be4baa2b..266cbd2caa135a7583d5251a1a7ea93900b0e391 100644 (file)
@@ -66,6 +66,8 @@ static int
 frame_setlineno(PyFrameObject *f, PyObject* p_new_lineno)
 {
        int new_lineno = 0;             /* The new value of f_lineno */
+       long l_new_lineno;
+       int overflow;
        int new_lasti = 0;              /* The new value of f_lasti */
        int new_iblock = 0;             /* The new value of f_iblock */
        unsigned char *code = NULL;     /* The bytecode for the frame... */
@@ -88,7 +90,7 @@ frame_setlineno(PyFrameObject *f, PyObject* p_new_lineno)
        unsigned char setup_op = 0;     /* (ditto) */
 
        /* f_lineno must be an integer. */
-       if (!PyInt_CheckExact(p_new_lineno)) {
+       if (!PyLong_CheckExact(p_new_lineno)) {
                PyErr_SetString(PyExc_ValueError,
                                "lineno must be an integer");
                return -1;
@@ -104,7 +106,19 @@ frame_setlineno(PyFrameObject *f, PyObject* p_new_lineno)
        }
 
        /* Fail if the line comes before the start of the code block. */
-       new_lineno = (int) PyLong_AsLong(p_new_lineno);
+       l_new_lineno = PyLong_AsLongAndOverflow(p_new_lineno, &overflow);
+       if (overflow
+#if SIZEOF_LONG > SIZEOF_INT
+           || l_new_lineno > INT_MAX
+           || l_new_lineno < INT_MIN
+#endif
+          ) {
+               PyErr_SetString(PyExc_ValueError,
+                               "lineno out of range");
+               return -1;
+       }
+       new_lineno = (int)l_new_lineno;
+           
        if (new_lineno < f->f_code->co_firstlineno) {
                PyErr_Format(PyExc_ValueError,
                             "line %d comes before the current code block",
index 59674bf0ee591003322db9f7695fcff97135facf..18d3b901a2745a3440032b9ad3d563ea72298756 100644 (file)
@@ -925,7 +925,7 @@ islt(PyObject *x, PyObject *y, PyObject *compare)
        Py_DECREF(args);
        if (res == NULL)
                return -1;
-       if (!PyInt_CheckExact(res)) {
+       if (!PyLong_CheckExact(res)) {
                PyErr_Format(PyExc_TypeError,
                             "comparison function must return int, not %.200s",
                             res->ob_type->tp_name);
@@ -934,6 +934,10 @@ islt(PyObject *x, PyObject *y, PyObject *compare)
        }
        i = PyLong_AsLong(res);
        Py_DECREF(res);
+       if (i == -1 && PyErr_Occurred()) {
+               /* Overflow in long conversion. */
+               return -1;
+       }
        return i < 0;
 }
 
index 1e20485f16c506933db830801ff7e270d9658f7f..cf7cb4713b18ac4d1e3786e8f9ad6c1b5514ecf1 100644 (file)
@@ -299,7 +299,7 @@ PyLong_FromDouble(double dval)
    Returns -1 and sets an error condition if overflow occurs. */
 
 long
-PyLong_AsLong(PyObject *vv)
+PyLong_AsLongAndOverflow(PyObject *vv, int *overflow)
 {
        /* This version by Tim Peters */
        register PyLongObject *v;
@@ -309,6 +309,7 @@ PyLong_AsLong(PyObject *vv)
        int sign;
        int do_decref = 0; /* if nb_int was called */
 
+       *overflow = 0;
        if (vv == NULL) {
                PyErr_BadInternalCall();
                return -1;
@@ -358,8 +359,7 @@ PyLong_AsLong(PyObject *vv)
                        prev = x;
                        x = (x << PyLong_SHIFT) + v->ob_digit[i];
                        if ((x >> PyLong_SHIFT) != prev) {
-                               PyErr_SetString(PyExc_OverflowError,
-                                       "Python int too large to convert to C long");
+                               *overflow = Py_Size(v) > 0 ? 1 : -1;
                                goto exit;
                        }
                }
@@ -373,8 +373,8 @@ PyLong_AsLong(PyObject *vv)
                        res = LONG_MIN;
                }
                else {
-                       PyErr_SetString(PyExc_OverflowError,
-                               "Python int too large to convert to C long");
+                       *overflow = Py_Size(v) > 0 ? 1 : -1;
+                       /* res is already set to -1 */
                }       
        }
  exit:
@@ -384,6 +384,20 @@ PyLong_AsLong(PyObject *vv)
        return res;
 }
 
+long 
+PyLong_AsLong(PyObject *obj)
+{
+       int overflow;
+       long result = PyLong_AsLongAndOverflow(obj, &overflow);
+       if (overflow) {
+               /* XXX: could be cute and give a different 
+                  message for overflow == -1 */
+               PyErr_SetString(PyExc_OverflowError,
+                               "Python int too large to convert to C long");
+       }
+       return result;
+}
+
 int
 _PyLong_FitsInLong(PyObject *vv)
 {
index 8dc77344c4bc93d66b3001b189a0f8cf8eff5458..80c3cae9a4ffd1a90636bb59b942bbdf69115aa1 100644 (file)
--- a/PC/_msi.c
+++ b/PC/_msi.c
@@ -542,9 +542,13 @@ summary_setproperty(msiobj* si, PyObject *args)
     if (PyString_Check(data)) {
        status = MsiSummaryInfoSetProperty(si->h, field, VT_LPSTR,
            0, NULL, PyString_AsString(data));
-    } else if (PyInt_CheckExact(data)) {
+    } else if (PyLong_CheckExact(data)) {
+       long value = PyLong_AsLong(data);
+       if (value == -1 && PyErr_Occurred()) {
+           return NULL;
+       }
        status = MsiSummaryInfoSetProperty(si->h, field, VT_I4,
-           PyLong_AsLong(data), NULL, NULL);
+           value, NULL, NULL);
     } else {
        PyErr_SetString(PyExc_TypeError, "unsupported type");
        return NULL;
index b57083b45500ca79154ca7219bd22074e15266fa..56ec738f30ad6c6d3012d9d9a91f2ab32b6ce5f3 100644 (file)
@@ -1623,10 +1623,14 @@ builtin_sum(PyObject *self, PyObject *args)
            Assumes all inputs are the same type.  If the assumption fails, default
            to the more general routine.
        */
-       if (PyInt_CheckExact(result)) {
-               long i_result = PyLong_AS_LONG(result);
-               Py_DECREF(result);
-               result = NULL;
+       if (PyLong_CheckExact(result)) {
+               int overflow;
+               long i_result = PyLong_AsLongAndOverflow(result, &overflow);
+               /* If this already overflowed, don't even enter the loop. */
+               if (overflow == 0) {
+                       Py_DECREF(result);
+                       result = NULL;
+               }
                while(result == NULL) {
                        item = PyIter_Next(iter);
                        if (item == NULL) {
@@ -1635,10 +1639,10 @@ builtin_sum(PyObject *self, PyObject *args)
                                        return NULL;
                                return PyLong_FromLong(i_result);
                        }
-                       if (PyInt_CheckExact(item)) {
-                               long b = PyLong_AS_LONG(item);
+                       if (PyLong_CheckExact(item)) {
+                               long b = PyLong_AsLongAndOverflow(item, &overflow);
                                long x = i_result + b;
-                               if ((x^i_result) >= 0 || (x^b) >= 0) {
+                               if (overflow == 0 && ((x^i_result) >= 0 || (x^b) >= 0)) {
                                        i_result = x;
                                        Py_DECREF(item);
                                        continue;
@@ -1676,12 +1680,17 @@ builtin_sum(PyObject *self, PyObject *args)
                                Py_DECREF(item);
                                continue;
                        }
-                       if (PyInt_CheckExact(item)) {
-                               PyFPE_START_PROTECT("add", return 0)
-                               f_result += (double)PyLong_AS_LONG(item);
-                               PyFPE_END_PROTECT(f_result)
-                               Py_DECREF(item);
-                               continue;
+                       if (PyLong_CheckExact(item)) {
+                               long value;
+                               int overflow;
+                               value = PyLong_AsLongAndOverflow(item, &overflow);
+                               if (!overflow) {
+                                       PyFPE_START_PROTECT("add", return 0)
+                                       f_result += (double)value;
+                                       PyFPE_END_PROTECT(f_result)
+                                       Py_DECREF(item);
+                                       continue;
+                               }
                        }
                        result = PyFloat_FromDouble(f_result);
                        temp = PyNumber_Add(result, item);
index 9aa83c74e78823a44157f13033640b04fd755b14..813f6f636a94186050ac9bfe1e9764dd54ffb394 100644 (file)
@@ -3711,14 +3711,7 @@ _PyEval_SliceIndex(PyObject *v, Py_ssize_t *pi)
 {
        if (v != NULL) {
                Py_ssize_t x;
-               if (PyInt_CheckExact(v)) {
-                       /* XXX(nnorwitz): I think PyLong_AS_LONG is correct,
-                          however, it looks like it should be AsSsize_t.
-                          There should be a comment here explaining why.
-                       */
-                       x = PyLong_AS_LONG(v);
-               }
-               else if (PyIndex_Check(v)) {
+               if (PyIndex_Check(v)) {
                        x = PyNumber_AsSsize_t(v, NULL);
                        if (x == -1 && PyErr_Occurred())
                                return 0;