summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Doc/c-api/concrete.rst15
-rw-r--r--Include/longobject.h2
-rw-r--r--Modules/_csv.c21
-rw-r--r--Modules/_cursesmodule.c9
-rw-r--r--Modules/_tkinter.c11
-rw-r--r--Modules/datetimemodule.c9
-rw-r--r--Modules/socketmodule.c7
-rw-r--r--Modules/timemodule.c4
-rw-r--r--Objects/exceptions.c10
-rw-r--r--Objects/frameobject.c18
-rw-r--r--Objects/listobject.c6
-rw-r--r--Objects/longobject.c24
-rw-r--r--PC/_msi.c8
-rw-r--r--Python/bltinmodule.c35
-rw-r--r--Python/ceval.c9
15 files changed, 134 insertions, 54 deletions
diff --git a/Doc/c-api/concrete.rst b/Doc/c-api/concrete.rst
index eefd927f88..f90ab4f2ad 100644
--- a/Doc/c-api/concrete.rst
+++ b/Doc/c-api/concrete.rst
@@ -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)
diff --git a/Include/longobject.h b/Include/longobject.h
index 5740f98deb..e1ee5eead9 100644
--- a/Include/longobject.h
+++ b/Include/longobject.h
@@ -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 *);
diff --git a/Modules/_csv.c b/Modules/_csv.c
index c30cea98d9..aee490ccd3 100644
--- a/Modules/_csv.c
+++ b/Modules/_csv.c
@@ -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);
}
diff --git a/Modules/_cursesmodule.c b/Modules/_cursesmodule.c
index 1fc7da7f1b..d1cd15518c 100644
--- a/Modules/_cursesmodule.c
+++ b/Modules/_cursesmodule.c
@@ -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);
diff --git a/Modules/_tkinter.c b/Modules/_tkinter.c
index c755f89ba3..2a341abb9d 100644
--- a/Modules/_tkinter.c
+++ b/Modules/_tkinter.c
@@ -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)) {
diff --git a/Modules/datetimemodule.c b/Modules/datetimemodule.c
index 6955c78443..8eb7e045d9 100644
--- a/Modules/datetimemodule.c
+++ b/Modules/datetimemodule.c
@@ -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);
diff --git a/Modules/socketmodule.c b/Modules/socketmodule.c
index 926f059ed5..c1fb5aa9e6 100644
--- a/Modules/socketmodule.c
+++ b/Modules/socketmodule.c
@@ -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);
diff --git a/Modules/timemodule.c b/Modules/timemodule.c
index 4196381baa..c64a356471 100644
--- a/Modules/timemodule.c
+++ b/Modules/timemodule.c
@@ -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;
diff --git a/Objects/exceptions.c b/Objects/exceptions.c
index cbcda7b066..9655733300 100644
--- a/Objects/exceptions.c
+++ b/Objects/exceptions.c
@@ -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[] = {
diff --git a/Objects/frameobject.c b/Objects/frameobject.c
index 0e6d9f8e5d..266cbd2caa 100644
--- a/Objects/frameobject.c
+++ b/Objects/frameobject.c
@@ -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",
diff --git a/Objects/listobject.c b/Objects/listobject.c
index 59674bf0ee..18d3b901a2 100644
--- a/Objects/listobject.c
+++ b/Objects/listobject.c
@@ -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;
}
diff --git a/Objects/longobject.c b/Objects/longobject.c
index 1e20485f16..cf7cb4713b 100644
--- a/Objects/longobject.c
+++ b/Objects/longobject.c
@@ -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)
{
diff --git a/PC/_msi.c b/PC/_msi.c
index 8dc77344c4..80c3cae9a4 100644
--- 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;
diff --git a/Python/bltinmodule.c b/Python/bltinmodule.c
index b57083b455..56ec738f30 100644
--- a/Python/bltinmodule.c
+++ b/Python/bltinmodule.c
@@ -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);
diff --git a/Python/ceval.c b/Python/ceval.c
index 9aa83c74e7..813f6f636a 100644
--- a/Python/ceval.c
+++ b/Python/ceval.c
@@ -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;