From 94f55837775f00eade742fa015d818633ab68318 Mon Sep 17 00:00:00 2001 From: Raymond Hettinger Date: Fri, 12 Jun 2009 18:40:16 +0000 Subject: [PATCH] Fix SystemError and a wasps nest of ref counting issues. --- Lib/test/test_range.py | 7 +++++++ Misc/NEWS | 2 ++ Objects/rangeobject.c | 32 ++++++++++++++++++++++++-------- 3 files changed, 33 insertions(+), 8 deletions(-) diff --git a/Lib/test/test_range.py b/Lib/test/test_range.py index 43fadf01d1f..7650103bd0c 100644 --- a/Lib/test/test_range.py +++ b/Lib/test/test_range.py @@ -71,6 +71,13 @@ class RangeTest(unittest.TestCase): self.assertEquals(list(pickle.loads(pickle.dumps(r, proto))), list(r)) + def test_odd_bug(self): + # This used to raise a "SystemError: NULL result without error" + # because the range validation step was eating the exception + # before NULL was returned. + with self.assertRaises(TypeError): + range([], 1, -1) + def test_main(): test.support.run_unittest(RangeTest) diff --git a/Misc/NEWS b/Misc/NEWS index f12c6d105b8..627dcf4f2a9 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -12,6 +12,8 @@ What's New in Python 3.1 Release Candidate 2? Core and Builtins ----------------- +- Fixed SystemError triggered by "range([], 1, -1)". + - Issue #5924: On Windows, a large PYTHONPATH environment variable (more than 255 characters) would be completely ignored. diff --git a/Objects/rangeobject.c b/Objects/rangeobject.c index 01114bb6adb..f8174caa426 100644 --- a/Objects/rangeobject.c +++ b/Objects/rangeobject.c @@ -59,26 +59,42 @@ range_new(PyTypeObject *type, PyObject *args, PyObject *kw) if (PyTuple_Size(args) <= 1) { if (!PyArg_UnpackTuple(args, "range", 1, 1, &stop)) - goto Fail; + return NULL; stop = PyNumber_Index(stop); if (!stop) - goto Fail; + return NULL; start = PyLong_FromLong(0); + if (!start) { + Py_DECREF(stop); + return NULL; + } step = PyLong_FromLong(1); - if (!start || !step) - goto Fail; + if (!step) { + Py_DECREF(stop); + Py_DECREF(start); + return NULL; + } } else { if (!PyArg_UnpackTuple(args, "range", 2, 3, &start, &stop, &step)) - goto Fail; + return NULL; /* Convert borrowed refs to owned refs */ start = PyNumber_Index(start); + if (!start) + return NULL; stop = PyNumber_Index(stop); - step = validate_step(step); - if (!start || !stop || !step) - goto Fail; + if (!stop) { + Py_DECREF(start); + return NULL; + } + step = validate_step(step); /* Caution, this can clear exceptions */ + if (!step) { + Py_DECREF(start); + Py_DECREF(stop); + return NULL; + } } obj = PyObject_New(rangeobject, &PyRange_Type);