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.
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 @@
 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);
 
-	/* If no istep was supplied, default to 1. */
+	/* ihigh correct now; do ilow */
+	if (ilow == NULL)
+		ilow = zero;
+	Py_INCREF(ilow);
+
+	/* 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 @@
 		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;
 }