summaryrefslogtreecommitdiffstats
path: root/Python
diff options
context:
space:
mode:
authorTim Peters <tim.peters@gmail.com>2003-04-13 22:13:08 (GMT)
committerTim Peters <tim.peters@gmail.com>2003-04-13 22:13:08 (GMT)
commit874e1f7ed3911b3290d095891082041b122e7030 (patch)
treeb0e7dec80255cc929f428ff725a7a589d1acf26e /Python
parentd39078ba2d77daeac74505ac13417bc5ed625ce1 (diff)
downloadcpython-874e1f7ed3911b3290d095891082041b122e7030.zip
cpython-874e1f7ed3911b3290d095891082041b122e7030.tar.gz
cpython-874e1f7ed3911b3290d095891082041b122e7030.tar.bz2
handle_range_longs(): refcount handling is very delicate here, and
the code erroneously decrefed the istep argument in an error case. This caused a co_consts tuple to lose a float constant prematurely, which eventually caused gc to try executing static data in floatobject.c (don't ask <wink>). So reworked this extensively to ensure refcount correctness.
Diffstat (limited to 'Python')
-rw-r--r--Python/bltinmodule.c81
1 files changed, 50 insertions, 31 deletions
diff --git a/Python/bltinmodule.c b/Python/bltinmodule.c
index c2ddb24..c8b784a 100644
--- a/Python/bltinmodule.c
+++ b/Python/bltinmodule.c
@@ -1319,61 +1319,76 @@ static PyObject *
handle_range_longs(PyObject *self, PyObject *args)
{
PyObject *ilow;
- PyObject *ihigh;
- PyObject *zero = NULL;
+ PyObject *ihigh = NULL;
PyObject *istep = NULL;
+
PyObject *curnum = NULL;
PyObject *v = NULL;
long bign;
int i, n;
int cmp_result;
- zero = PyLong_FromLong(0L);
+ PyObject *zero = PyLong_FromLong(0);
+
if (zero == NULL)
return NULL;
- ilow = zero; /* Default lower bound */
- if (!PyArg_ParseTuple(args, "O", &ihigh, &istep)) {
- PyErr_Clear();
- if (!PyArg_ParseTuple(args,
- "OO|O;range() requires 1-3 int arguments",
- &ilow, &ihigh, &istep))
- goto Fail;
- }
-
- if (!PyInt_Check(ilow) && !PyLong_Check(ilow)) {
- PyErr_SetString(PyExc_ValueError,
- "integer start argument expected, got float.");
- goto Fail;
+ if (!PyArg_UnpackTuple(args, "range", 1, 3, &ilow, &ihigh, &istep)) {
+ Py_DECREF(zero);
return NULL;
}
- if (!PyInt_Check(ihigh) && !PyLong_Check(ihigh)) {
- PyErr_SetString(PyExc_ValueError,
- "integer end argument expected, got float.");
- goto Fail;
- return NULL;
+ /* Figure out which way we were called, supply defaults, and be
+ * sure to incref everything so that the decrefs at the end
+ * are correct.
+ */
+ assert(ilow != NULL);
+ if (ihigh == NULL) {
+ /* only 1 arg -- it's the upper limit */
+ ihigh = ilow;
+ ilow = NULL;
}
+ assert(ihigh != NULL);
+ Py_INCREF(ihigh);
+
+ /* ihigh correct now; do ilow */
+ if (ilow == NULL)
+ ilow = zero;
+ Py_INCREF(ilow);
- /* If no istep was supplied, default to 1. */
+ /* ilow and ihigh correct now; do istep */
if (istep == NULL) {
istep = PyLong_FromLong(1L);
if (istep == NULL)
goto Fail;
}
else {
- if (!PyInt_Check(istep) && !PyLong_Check(istep)) {
- PyErr_SetString(PyExc_ValueError,
- "integer step argument expected, got float.");
- goto Fail;
- }
Py_INCREF(istep);
}
- if (PyObject_Cmp(istep, zero, &cmp_result) == -1) {
+ /* XXX What reason do we have to believe that if an arg isn't an
+ * XXX int, it must be a float?
+ */
+ if (!PyInt_Check(ilow) && !PyLong_Check(ilow)) {
+ PyErr_SetString(PyExc_ValueError,
+ "integer start argument expected, got float.");
+ goto Fail;
+ }
+
+ if (!PyInt_Check(ihigh) && !PyLong_Check(ihigh)) {
+ PyErr_SetString(PyExc_ValueError,
+ "integer end argument expected, got float.");
goto Fail;
}
+ if (!PyInt_Check(istep) && !PyLong_Check(istep)) {
+ PyErr_SetString(PyExc_ValueError,
+ "integer step argument expected, got float.");
+ goto Fail;
+ }
+
+ if (PyObject_Cmp(istep, zero, &cmp_result) == -1)
+ goto Fail;
if (cmp_result == 0) {
PyErr_SetString(PyExc_ValueError,
"range() arg 3 must not be zero");
@@ -1419,15 +1434,19 @@ handle_range_longs(PyObject *self, PyObject *args)
Py_DECREF(curnum);
curnum = tmp_num;
}
- Py_DECREF(curnum);
+ Py_DECREF(ilow);
+ Py_DECREF(ihigh);
Py_DECREF(istep);
Py_DECREF(zero);
+ Py_DECREF(curnum);
return v;
Fail:
- Py_XDECREF(curnum);
+ Py_DECREF(ilow);
+ Py_DECREF(ihigh);
Py_XDECREF(istep);
- Py_XDECREF(zero);
+ Py_DECREF(zero);
+ Py_XDECREF(curnum);
Py_XDECREF(v);
return NULL;
}