Remove PyInt_CheckExact. Add PyLong_AsLongAndOverflow.

This commit is contained in:
Martin v. Löwis 2007-12-04 22:10:37 +00:00
parent 0fbab7ff8d
commit d1a1d1ed80
15 changed files with 134 additions and 54 deletions

View File

@ -211,10 +211,6 @@ All integers are implemented as "long" integer objects of arbitrary size.
:ctype:`PyLongObject`. :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) .. cfunction:: PyObject* PyLong_FromLong(long v)
Return a new :ctype:`PyLongObject` object from *v*, or *NULL* on failure. 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) single: OverflowError (built-in exception)
Return a C :ctype:`long` representation of the contents of *pylong*. If 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) .. cfunction:: unsigned long PyLong_AsUnsignedLong(PyObject *pylong)

View File

@ -14,7 +14,6 @@ PyAPI_DATA(PyTypeObject) PyLong_Type;
#define PyLong_Check(op) \ #define PyLong_Check(op) \
PyType_FastSubclass(Py_Type(op), Py_TPFLAGS_LONG_SUBCLASS) PyType_FastSubclass(Py_Type(op), Py_TPFLAGS_LONG_SUBCLASS)
#define PyLong_CheckExact(op) (Py_Type(op) == &PyLong_Type) #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_FromLong(long);
PyAPI_FUNC(PyObject *) PyLong_FromUnsignedLong(unsigned 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_FromSsize_t(Py_ssize_t);
PyAPI_FUNC(PyObject *) PyLong_FromDouble(double); PyAPI_FUNC(PyObject *) PyLong_FromDouble(double);
PyAPI_FUNC(long) PyLong_AsLong(PyObject *); PyAPI_FUNC(long) PyLong_AsLong(PyObject *);
PyAPI_FUNC(long) PyLong_AsLongAndOverflow(PyObject *, int *);
PyAPI_FUNC(Py_ssize_t) PyLong_AsSsize_t(PyObject *); PyAPI_FUNC(Py_ssize_t) PyLong_AsSsize_t(PyObject *);
PyAPI_FUNC(size_t) PyLong_AsSize_t(PyObject *); PyAPI_FUNC(size_t) PyLong_AsSize_t(PyObject *);
PyAPI_FUNC(unsigned long) PyLong_AsUnsignedLong(PyObject *); PyAPI_FUNC(unsigned long) PyLong_AsUnsignedLong(PyObject *);

View File

@ -181,12 +181,23 @@ _set_int(const char *name, int *target, PyObject *src, int dflt)
if (src == NULL) if (src == NULL)
*target = dflt; *target = dflt;
else { else {
if (!PyInt_CheckExact(src)) { long value;
if (!PyLong_CheckExact(src)) {
PyErr_Format(PyExc_TypeError, PyErr_Format(PyExc_TypeError,
"\"%s\" must be an integer", name); "\"%s\" must be an integer", name);
return -1; 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; 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)) if (!PyArg_UnpackTuple(args, "field_size_limit", 0, 1, &new_limit))
return NULL; return NULL;
if (new_limit != NULL) { if (new_limit != NULL) {
if (!PyInt_CheckExact(new_limit)) { if (!PyLong_CheckExact(new_limit)) {
PyErr_Format(PyExc_TypeError, PyErr_Format(PyExc_TypeError,
"limit must be an integer"); "limit must be an integer");
return NULL; return NULL;
} }
field_limit = PyLong_AsLong(new_limit); field_limit = PyLong_AsLong(new_limit);
if (field_limit == -1 && PyErr_Occurred()) {
field_limit = old_limit;
return NULL;
}
} }
return PyLong_FromLong(old_limit); return PyLong_FromLong(old_limit);
} }

View File

@ -196,8 +196,13 @@ PyCursesCheckERR(int code, char *fname)
static int static int
PyCurses_ConvertToChtype(PyObject *obj, chtype *ch) PyCurses_ConvertToChtype(PyObject *obj, chtype *ch)
{ {
if (PyInt_CheckExact(obj)) { if (PyLong_CheckExact(obj)) {
*ch = (chtype) PyLong_AsLong(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) } else if(PyString_Check(obj)
&& (PyString_Size(obj) == 1)) { && (PyString_Size(obj) == 1)) {
*ch = (chtype) *PyString_AsString(obj); *ch = (chtype) *PyString_AsString(obj);

View File

@ -863,14 +863,21 @@ static Tcl_Obj*
AsObj(PyObject *value) AsObj(PyObject *value)
{ {
Tcl_Obj *result; Tcl_Obj *result;
long longVal;
int overflow;
if (PyString_Check(value)) if (PyString_Check(value))
return Tcl_NewStringObj(PyString_AS_STRING(value), return Tcl_NewStringObj(PyString_AS_STRING(value),
PyString_GET_SIZE(value)); PyString_GET_SIZE(value));
else if (PyBool_Check(value)) else if (PyBool_Check(value))
return Tcl_NewBooleanObj(PyObject_IsTrue(value)); return Tcl_NewBooleanObj(PyObject_IsTrue(value));
else if (PyInt_CheckExact(value)) else if (PyLong_CheckExact(value) &&
return Tcl_NewLongObj(PyLong_AS_LONG(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)) else if (PyFloat_Check(value))
return Tcl_NewDoubleObj(PyFloat_AS_DOUBLE(value)); return Tcl_NewDoubleObj(PyFloat_AS_DOUBLE(value));
else if (PyTuple_Check(value)) { else if (PyTuple_Check(value)) {

View File

@ -3827,7 +3827,7 @@ datetime_strptime(PyObject *cls, PyObject *args)
Py_DECREF(module); Py_DECREF(module);
if (obj != NULL) { if (obj != NULL) {
int i, good_timetuple = 1; int i, good_timetuple = 1, overflow;
long int ia[6]; long int ia[6];
if (PySequence_Check(obj) && PySequence_Size(obj) >= 6) if (PySequence_Check(obj) && PySequence_Size(obj) >= 6)
for (i=0; i < 6; i++) { for (i=0; i < 6; i++) {
@ -3836,8 +3836,11 @@ datetime_strptime(PyObject *cls, PyObject *args)
Py_DECREF(obj); Py_DECREF(obj);
return NULL; return NULL;
} }
if (PyInt_CheckExact(p)) if (PyLong_CheckExact(p)) {
ia[i] = PyLong_AsLong(p); ia[i] = PyLong_AsLongAndOverflow(p, &overflow);
if (overflow)
good_timetuple = 0;
}
else else
good_timetuple = 0; good_timetuple = 0;
Py_DECREF(p); Py_DECREF(p);

View File

@ -3595,8 +3595,11 @@ socket_getaddrinfo(PyObject *self, PyObject *args)
"getaddrinfo() argument 1 must be string or None"); "getaddrinfo() argument 1 must be string or None");
return NULL; return NULL;
} }
if (PyInt_CheckExact(pobj)) { if (PyLong_CheckExact(pobj)) {
PyOS_snprintf(pbuf, sizeof(pbuf), "%ld", PyLong_AsLong(pobj)); long value = PyLong_AsLong(pobj);
if (value == -1 && PyErr_Occurred())
goto err;
PyOS_snprintf(pbuf, sizeof(pbuf), "%ld", value);
pptr = pbuf; pptr = pbuf;
} else if (PyUnicode_Check(pobj)) { } else if (PyUnicode_Check(pobj)) {
pptr = PyUnicode_AsString(pobj); pptr = PyUnicode_AsString(pobj);

View File

@ -392,8 +392,8 @@ gettmarg(PyObject *args, struct tm *p)
if (y < 1900) { if (y < 1900) {
PyObject *accept = PyDict_GetItemString(moddict, PyObject *accept = PyDict_GetItemString(moddict,
"accept2dyear"); "accept2dyear");
if (accept == NULL || !PyInt_CheckExact(accept) || if (accept == NULL || !PyLong_CheckExact(accept) ||
PyLong_AsLong(accept) == 0) { !PyObject_IsTrue(accept)) {
PyErr_SetString(PyExc_ValueError, PyErr_SetString(PyExc_ValueError,
"year >= 1900 required"); "year >= 1900 required");
return 0; return 0;

View File

@ -929,6 +929,10 @@ SyntaxError_str(PySyntaxErrorObject *self)
{ {
int have_lineno = 0; int have_lineno = 0;
char *filename = 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 /* XXX -- do all the additional formatting with filename and
lineno here */ lineno here */
@ -936,7 +940,7 @@ SyntaxError_str(PySyntaxErrorObject *self)
if (self->filename && PyUnicode_Check(self->filename)) { if (self->filename && PyUnicode_Check(self->filename)) {
filename = PyUnicode_AsString(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) if (!filename && !have_lineno)
return PyObject_Str(self->msg ? self->msg : Py_None); return PyObject_Str(self->msg ? self->msg : Py_None);
@ -945,7 +949,7 @@ SyntaxError_str(PySyntaxErrorObject *self)
return PyUnicode_FromFormat("%S (%s, line %ld)", return PyUnicode_FromFormat("%S (%s, line %ld)",
self->msg ? self->msg : Py_None, self->msg ? self->msg : Py_None,
my_basename(filename), my_basename(filename),
PyLong_AsLong(self->lineno)); PyLong_AsLongAndOverflow(self->lineno, &overflow));
else if (filename) else if (filename)
return PyUnicode_FromFormat("%S (%s)", return PyUnicode_FromFormat("%S (%s)",
self->msg ? self->msg : Py_None, self->msg ? self->msg : Py_None,
@ -953,7 +957,7 @@ SyntaxError_str(PySyntaxErrorObject *self)
else /* only have_lineno */ else /* only have_lineno */
return PyUnicode_FromFormat("%S (line %ld)", return PyUnicode_FromFormat("%S (line %ld)",
self->msg ? self->msg : Py_None, self->msg ? self->msg : Py_None,
PyLong_AsLong(self->lineno)); PyLong_AsLongAndOverflow(self->lineno, &overflow));
} }
static PyMemberDef SyntaxError_members[] = { static PyMemberDef SyntaxError_members[] = {

View File

@ -66,6 +66,8 @@ static int
frame_setlineno(PyFrameObject *f, PyObject* p_new_lineno) frame_setlineno(PyFrameObject *f, PyObject* p_new_lineno)
{ {
int new_lineno = 0; /* The new value of f_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_lasti = 0; /* The new value of f_lasti */
int new_iblock = 0; /* The new value of f_iblock */ int new_iblock = 0; /* The new value of f_iblock */
unsigned char *code = NULL; /* The bytecode for the frame... */ 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) */ unsigned char setup_op = 0; /* (ditto) */
/* f_lineno must be an integer. */ /* f_lineno must be an integer. */
if (!PyInt_CheckExact(p_new_lineno)) { if (!PyLong_CheckExact(p_new_lineno)) {
PyErr_SetString(PyExc_ValueError, PyErr_SetString(PyExc_ValueError,
"lineno must be an integer"); "lineno must be an integer");
return -1; 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. */ /* 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) { if (new_lineno < f->f_code->co_firstlineno) {
PyErr_Format(PyExc_ValueError, PyErr_Format(PyExc_ValueError,
"line %d comes before the current code block", "line %d comes before the current code block",

View File

@ -925,7 +925,7 @@ islt(PyObject *x, PyObject *y, PyObject *compare)
Py_DECREF(args); Py_DECREF(args);
if (res == NULL) if (res == NULL)
return -1; return -1;
if (!PyInt_CheckExact(res)) { if (!PyLong_CheckExact(res)) {
PyErr_Format(PyExc_TypeError, PyErr_Format(PyExc_TypeError,
"comparison function must return int, not %.200s", "comparison function must return int, not %.200s",
res->ob_type->tp_name); res->ob_type->tp_name);
@ -934,6 +934,10 @@ islt(PyObject *x, PyObject *y, PyObject *compare)
} }
i = PyLong_AsLong(res); i = PyLong_AsLong(res);
Py_DECREF(res); Py_DECREF(res);
if (i == -1 && PyErr_Occurred()) {
/* Overflow in long conversion. */
return -1;
}
return i < 0; return i < 0;
} }

View File

@ -299,7 +299,7 @@ PyLong_FromDouble(double dval)
Returns -1 and sets an error condition if overflow occurs. */ Returns -1 and sets an error condition if overflow occurs. */
long long
PyLong_AsLong(PyObject *vv) PyLong_AsLongAndOverflow(PyObject *vv, int *overflow)
{ {
/* This version by Tim Peters */ /* This version by Tim Peters */
register PyLongObject *v; register PyLongObject *v;
@ -309,6 +309,7 @@ PyLong_AsLong(PyObject *vv)
int sign; int sign;
int do_decref = 0; /* if nb_int was called */ int do_decref = 0; /* if nb_int was called */
*overflow = 0;
if (vv == NULL) { if (vv == NULL) {
PyErr_BadInternalCall(); PyErr_BadInternalCall();
return -1; return -1;
@ -358,8 +359,7 @@ PyLong_AsLong(PyObject *vv)
prev = x; prev = x;
x = (x << PyLong_SHIFT) + v->ob_digit[i]; x = (x << PyLong_SHIFT) + v->ob_digit[i];
if ((x >> PyLong_SHIFT) != prev) { if ((x >> PyLong_SHIFT) != prev) {
PyErr_SetString(PyExc_OverflowError, *overflow = Py_Size(v) > 0 ? 1 : -1;
"Python int too large to convert to C long");
goto exit; goto exit;
} }
} }
@ -373,8 +373,8 @@ PyLong_AsLong(PyObject *vv)
res = LONG_MIN; res = LONG_MIN;
} }
else { else {
PyErr_SetString(PyExc_OverflowError, *overflow = Py_Size(v) > 0 ? 1 : -1;
"Python int too large to convert to C long"); /* res is already set to -1 */
} }
} }
exit: exit:
@ -384,6 +384,20 @@ PyLong_AsLong(PyObject *vv)
return res; 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 int
_PyLong_FitsInLong(PyObject *vv) _PyLong_FitsInLong(PyObject *vv)
{ {

View File

@ -542,9 +542,13 @@ summary_setproperty(msiobj* si, PyObject *args)
if (PyString_Check(data)) { if (PyString_Check(data)) {
status = MsiSummaryInfoSetProperty(si->h, field, VT_LPSTR, status = MsiSummaryInfoSetProperty(si->h, field, VT_LPSTR,
0, NULL, PyString_AsString(data)); 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, status = MsiSummaryInfoSetProperty(si->h, field, VT_I4,
PyLong_AsLong(data), NULL, NULL); value, NULL, NULL);
} else { } else {
PyErr_SetString(PyExc_TypeError, "unsupported type"); PyErr_SetString(PyExc_TypeError, "unsupported type");
return NULL; return NULL;

View File

@ -1623,10 +1623,14 @@ builtin_sum(PyObject *self, PyObject *args)
Assumes all inputs are the same type. If the assumption fails, default Assumes all inputs are the same type. If the assumption fails, default
to the more general routine. to the more general routine.
*/ */
if (PyInt_CheckExact(result)) { if (PyLong_CheckExact(result)) {
long i_result = PyLong_AS_LONG(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); Py_DECREF(result);
result = NULL; result = NULL;
}
while(result == NULL) { while(result == NULL) {
item = PyIter_Next(iter); item = PyIter_Next(iter);
if (item == NULL) { if (item == NULL) {
@ -1635,10 +1639,10 @@ builtin_sum(PyObject *self, PyObject *args)
return NULL; return NULL;
return PyLong_FromLong(i_result); return PyLong_FromLong(i_result);
} }
if (PyInt_CheckExact(item)) { if (PyLong_CheckExact(item)) {
long b = PyLong_AS_LONG(item); long b = PyLong_AsLongAndOverflow(item, &overflow);
long x = i_result + b; 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; i_result = x;
Py_DECREF(item); Py_DECREF(item);
continue; continue;
@ -1676,13 +1680,18 @@ builtin_sum(PyObject *self, PyObject *args)
Py_DECREF(item); Py_DECREF(item);
continue; continue;
} }
if (PyInt_CheckExact(item)) { if (PyLong_CheckExact(item)) {
long value;
int overflow;
value = PyLong_AsLongAndOverflow(item, &overflow);
if (!overflow) {
PyFPE_START_PROTECT("add", return 0) PyFPE_START_PROTECT("add", return 0)
f_result += (double)PyLong_AS_LONG(item); f_result += (double)value;
PyFPE_END_PROTECT(f_result) PyFPE_END_PROTECT(f_result)
Py_DECREF(item); Py_DECREF(item);
continue; continue;
} }
}
result = PyFloat_FromDouble(f_result); result = PyFloat_FromDouble(f_result);
temp = PyNumber_Add(result, item); temp = PyNumber_Add(result, item);
Py_DECREF(result); Py_DECREF(result);

View File

@ -3711,14 +3711,7 @@ _PyEval_SliceIndex(PyObject *v, Py_ssize_t *pi)
{ {
if (v != NULL) { if (v != NULL) {
Py_ssize_t x; Py_ssize_t x;
if (PyInt_CheckExact(v)) { if (PyIndex_Check(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)) {
x = PyNumber_AsSsize_t(v, NULL); x = PyNumber_AsSsize_t(v, NULL);
if (x == -1 && PyErr_Occurred()) if (x == -1 && PyErr_Occurred())
return 0; return 0;