Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit d1a1d1e

Browse files
committed
Remove PyInt_CheckExact. Add PyLong_AsLongAndOverflow.
1 parent 0fbab7f commit d1a1d1e

15 files changed

Lines changed: 134 additions & 54 deletions

File tree

Doc/c-api/concrete.rst

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -211,10 +211,6 @@ All integers are implemented as "long" integer objects of arbitrary size.
211211
:ctype:`PyLongObject`.
212212

213213

214-
.. XXX cfunction PyInt_CheckExact(PyObject *p) checks if argument is a long
215-
object and fits into a C long
216-
217-
218214
.. cfunction:: PyObject* PyLong_FromLong(long v)
219215

220216
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.
297293
single: OverflowError (built-in exception)
298294

299295
Return a C :ctype:`long` representation of the contents of *pylong*. If
300-
*pylong* is greater than :const:`LONG_MAX`, an :exc:`OverflowError` is raised.
296+
*pylong* is greater than :const:`LONG_MAX`, raise an :exc:`OverflowError`,
297+
and return -1. Convert non-long objects automatically to long first,
298+
and return -1 if that raises exceptions.
299+
300+
.. cfunction:: long PyLong_AsLongAndOverflow(PyObject *pylong, int* overflow)
301+
302+
Return a C :ctype:`long` representation of the contents of *pylong*. If
303+
*pylong* is greater than :const:`LONG_MAX`, return -1 and
304+
set `*overflow` to 1 (for overflow) or -1 (for underflow).
305+
If an exception is set because of type errors, also return -1.
301306

302307

303308
.. cfunction:: unsigned long PyLong_AsUnsignedLong(PyObject *pylong)

Include/longobject.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,14 +14,14 @@ PyAPI_DATA(PyTypeObject) PyLong_Type;
1414
#define PyLong_Check(op) \
1515
PyType_FastSubclass(Py_Type(op), Py_TPFLAGS_LONG_SUBCLASS)
1616
#define PyLong_CheckExact(op) (Py_Type(op) == &PyLong_Type)
17-
#define PyInt_CheckExact(op) (PyLong_CheckExact(op) && _PyLong_FitsInLong(op))
1817

1918
PyAPI_FUNC(PyObject *) PyLong_FromLong(long);
2019
PyAPI_FUNC(PyObject *) PyLong_FromUnsignedLong(unsigned long);
2120
PyAPI_FUNC(PyObject *) PyLong_FromSize_t(size_t);
2221
PyAPI_FUNC(PyObject *) PyLong_FromSsize_t(Py_ssize_t);
2322
PyAPI_FUNC(PyObject *) PyLong_FromDouble(double);
2423
PyAPI_FUNC(long) PyLong_AsLong(PyObject *);
24+
PyAPI_FUNC(long) PyLong_AsLongAndOverflow(PyObject *, int *);
2525
PyAPI_FUNC(Py_ssize_t) PyLong_AsSsize_t(PyObject *);
2626
PyAPI_FUNC(size_t) PyLong_AsSize_t(PyObject *);
2727
PyAPI_FUNC(unsigned long) PyLong_AsUnsignedLong(PyObject *);

Modules/_csv.c

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -181,12 +181,23 @@ _set_int(const char *name, int *target, PyObject *src, int dflt)
181181
if (src == NULL)
182182
*target = dflt;
183183
else {
184-
if (!PyInt_CheckExact(src)) {
184+
long value;
185+
if (!PyLong_CheckExact(src)) {
185186
PyErr_Format(PyExc_TypeError,
186187
"\"%s\" must be an integer", name);
187188
return -1;
188189
}
189-
*target = PyLong_AsLong(src);
190+
value = PyLong_AsLong(src);
191+
if (value == -1 && PyErr_Occurred())
192+
return -1;
193+
#if SIZEOF_LONG > SIZEOF_INT
194+
if (value > INT_MAX || value < INT_MIN) {
195+
PyErr_Format(PyExc_ValueError,
196+
"integer out of range for \"%s\"", name);
197+
return -1;
198+
}
199+
#endif
200+
*target = (int)value;
190201
}
191202
return 0;
192203
}
@@ -1385,12 +1396,16 @@ csv_field_size_limit(PyObject *module, PyObject *args)
13851396
if (!PyArg_UnpackTuple(args, "field_size_limit", 0, 1, &new_limit))
13861397
return NULL;
13871398
if (new_limit != NULL) {
1388-
if (!PyInt_CheckExact(new_limit)) {
1399+
if (!PyLong_CheckExact(new_limit)) {
13891400
PyErr_Format(PyExc_TypeError,
13901401
"limit must be an integer");
13911402
return NULL;
13921403
}
13931404
field_limit = PyLong_AsLong(new_limit);
1405+
if (field_limit == -1 && PyErr_Occurred()) {
1406+
field_limit = old_limit;
1407+
return NULL;
1408+
}
13941409
}
13951410
return PyLong_FromLong(old_limit);
13961411
}

Modules/_cursesmodule.c

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -196,8 +196,13 @@ PyCursesCheckERR(int code, char *fname)
196196
static int
197197
PyCurses_ConvertToChtype(PyObject *obj, chtype *ch)
198198
{
199-
if (PyInt_CheckExact(obj)) {
200-
*ch = (chtype) PyLong_AsLong(obj);
199+
if (PyLong_CheckExact(obj)) {
200+
int overflow;
201+
/* XXX should the truncation by the cast also be reported
202+
as an error? */
203+
*ch = (chtype) PyLong_AsLongAndOverflow(obj, &overflow);
204+
if (overflow)
205+
return 0;
201206
} else if(PyString_Check(obj)
202207
&& (PyString_Size(obj) == 1)) {
203208
*ch = (chtype) *PyString_AsString(obj);

Modules/_tkinter.c

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -863,14 +863,21 @@ static Tcl_Obj*
863863
AsObj(PyObject *value)
864864
{
865865
Tcl_Obj *result;
866+
long longVal;
867+
int overflow;
866868

867869
if (PyString_Check(value))
868870
return Tcl_NewStringObj(PyString_AS_STRING(value),
869871
PyString_GET_SIZE(value));
870872
else if (PyBool_Check(value))
871873
return Tcl_NewBooleanObj(PyObject_IsTrue(value));
872-
else if (PyInt_CheckExact(value))
873-
return Tcl_NewLongObj(PyLong_AS_LONG(value));
874+
else if (PyLong_CheckExact(value) &&
875+
((longVal = PyLong_AsLongAndOverflow(value, &overflow)),
876+
!overflow)) {
877+
/* If there is an overflow in the long conversion,
878+
fall through to default object handling. */
879+
return Tcl_NewLongObj(longVal);
880+
}
874881
else if (PyFloat_Check(value))
875882
return Tcl_NewDoubleObj(PyFloat_AS_DOUBLE(value));
876883
else if (PyTuple_Check(value)) {

Modules/datetimemodule.c

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3827,7 +3827,7 @@ datetime_strptime(PyObject *cls, PyObject *args)
38273827
Py_DECREF(module);
38283828

38293829
if (obj != NULL) {
3830-
int i, good_timetuple = 1;
3830+
int i, good_timetuple = 1, overflow;
38313831
long int ia[6];
38323832
if (PySequence_Check(obj) && PySequence_Size(obj) >= 6)
38333833
for (i=0; i < 6; i++) {
@@ -3836,8 +3836,11 @@ datetime_strptime(PyObject *cls, PyObject *args)
38363836
Py_DECREF(obj);
38373837
return NULL;
38383838
}
3839-
if (PyInt_CheckExact(p))
3840-
ia[i] = PyLong_AsLong(p);
3839+
if (PyLong_CheckExact(p)) {
3840+
ia[i] = PyLong_AsLongAndOverflow(p, &overflow);
3841+
if (overflow)
3842+
good_timetuple = 0;
3843+
}
38413844
else
38423845
good_timetuple = 0;
38433846
Py_DECREF(p);

Modules/socketmodule.c

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3595,8 +3595,11 @@ socket_getaddrinfo(PyObject *self, PyObject *args)
35953595
"getaddrinfo() argument 1 must be string or None");
35963596
return NULL;
35973597
}
3598-
if (PyInt_CheckExact(pobj)) {
3599-
PyOS_snprintf(pbuf, sizeof(pbuf), "%ld", PyLong_AsLong(pobj));
3598+
if (PyLong_CheckExact(pobj)) {
3599+
long value = PyLong_AsLong(pobj);
3600+
if (value == -1 && PyErr_Occurred())
3601+
goto err;
3602+
PyOS_snprintf(pbuf, sizeof(pbuf), "%ld", value);
36003603
pptr = pbuf;
36013604
} else if (PyUnicode_Check(pobj)) {
36023605
pptr = PyUnicode_AsString(pobj);

Modules/timemodule.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -392,8 +392,8 @@ gettmarg(PyObject *args, struct tm *p)
392392
if (y < 1900) {
393393
PyObject *accept = PyDict_GetItemString(moddict,
394394
"accept2dyear");
395-
if (accept == NULL || !PyInt_CheckExact(accept) ||
396-
PyLong_AsLong(accept) == 0) {
395+
if (accept == NULL || !PyLong_CheckExact(accept) ||
396+
!PyObject_IsTrue(accept)) {
397397
PyErr_SetString(PyExc_ValueError,
398398
"year >= 1900 required");
399399
return 0;

Objects/exceptions.c

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -929,14 +929,18 @@ SyntaxError_str(PySyntaxErrorObject *self)
929929
{
930930
int have_lineno = 0;
931931
char *filename = 0;
932+
/* Below, we always ignore overflow errors, just printing -1.
933+
Still, we cannot allow an OverflowError to be raised, so
934+
we need to call PyLong_AsLongAndOverflow. */
935+
int overflow;
932936

933937
/* XXX -- do all the additional formatting with filename and
934938
lineno here */
935939

936940
if (self->filename && PyUnicode_Check(self->filename)) {
937941
filename = PyUnicode_AsString(self->filename);
938942
}
939-
have_lineno = (self->lineno != NULL) && PyInt_CheckExact(self->lineno);
943+
have_lineno = (self->lineno != NULL) && PyLong_CheckExact(self->lineno);
940944

941945
if (!filename && !have_lineno)
942946
return PyObject_Str(self->msg ? self->msg : Py_None);
@@ -945,15 +949,15 @@ SyntaxError_str(PySyntaxErrorObject *self)
945949
return PyUnicode_FromFormat("%S (%s, line %ld)",
946950
self->msg ? self->msg : Py_None,
947951
my_basename(filename),
948-
PyLong_AsLong(self->lineno));
952+
PyLong_AsLongAndOverflow(self->lineno, &overflow));
949953
else if (filename)
950954
return PyUnicode_FromFormat("%S (%s)",
951955
self->msg ? self->msg : Py_None,
952956
my_basename(filename));
953957
else /* only have_lineno */
954958
return PyUnicode_FromFormat("%S (line %ld)",
955959
self->msg ? self->msg : Py_None,
956-
PyLong_AsLong(self->lineno));
960+
PyLong_AsLongAndOverflow(self->lineno, &overflow));
957961
}
958962

959963
static PyMemberDef SyntaxError_members[] = {

Objects/frameobject.c

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,8 @@ static int
6666
frame_setlineno(PyFrameObject *f, PyObject* p_new_lineno)
6767
{
6868
int new_lineno = 0; /* The new value of f_lineno */
69+
long l_new_lineno;
70+
int overflow;
6971
int new_lasti = 0; /* The new value of f_lasti */
7072
int new_iblock = 0; /* The new value of f_iblock */
7173
unsigned char *code = NULL; /* The bytecode for the frame... */
@@ -88,7 +90,7 @@ frame_setlineno(PyFrameObject *f, PyObject* p_new_lineno)
8890
unsigned char setup_op = 0; /* (ditto) */
8991

9092
/* f_lineno must be an integer. */
91-
if (!PyInt_CheckExact(p_new_lineno)) {
93+
if (!PyLong_CheckExact(p_new_lineno)) {
9294
PyErr_SetString(PyExc_ValueError,
9395
"lineno must be an integer");
9496
return -1;
@@ -104,7 +106,19 @@ frame_setlineno(PyFrameObject *f, PyObject* p_new_lineno)
104106
}
105107

106108
/* Fail if the line comes before the start of the code block. */
107-
new_lineno = (int) PyLong_AsLong(p_new_lineno);
109+
l_new_lineno = PyLong_AsLongAndOverflow(p_new_lineno, &overflow);
110+
if (overflow
111+
#if SIZEOF_LONG > SIZEOF_INT
112+
|| l_new_lineno > INT_MAX
113+
|| l_new_lineno < INT_MIN
114+
#endif
115+
) {
116+
PyErr_SetString(PyExc_ValueError,
117+
"lineno out of range");
118+
return -1;
119+
}
120+
new_lineno = (int)l_new_lineno;
121+
108122
if (new_lineno < f->f_code->co_firstlineno) {
109123
PyErr_Format(PyExc_ValueError,
110124
"line %d comes before the current code block",

0 commit comments

Comments
 (0)