[Python-checkins] r69228 - in python/branches/release26-maint: Include/abstract.h Lib/test/test_iterlen.py Misc/NEWS Objects/abstract.c Objects/bytearrayobject.c Objects/listobject.c Python/bltinmodule.c

raymond.hettinger python-checkins at python.org
Mon Feb 2 23:44:07 CET 2009


Author: raymond.hettinger
Date: Mon Feb 2 23:44:06 2009
New Revision: 69228
Log:
Issue 1242657: list(obj) can swallow KeyboardInterrupt
Modified:
 python/branches/release26-maint/Include/abstract.h
 python/branches/release26-maint/Lib/test/test_iterlen.py
 python/branches/release26-maint/Misc/NEWS
 python/branches/release26-maint/Objects/abstract.c
 python/branches/release26-maint/Objects/bytearrayobject.c
 python/branches/release26-maint/Objects/listobject.c
 python/branches/release26-maint/Python/bltinmodule.c
Modified: python/branches/release26-maint/Include/abstract.h
==============================================================================
--- python/branches/release26-maint/Include/abstract.h	(original)
+++ python/branches/release26-maint/Include/abstract.h	Mon Feb 2 23:44:06 2009
@@ -438,7 +438,7 @@
 /*
 Guess the size of object o using len(o) or o.__length_hint__().
 If neither of those return a non-negative value, then return the
- default value. This function never fails. All exceptions are cleared.
+ default value. If one of the calls fails, this function returns -1.
 */
 
 PyAPI_FUNC(PyObject *) PyObject_GetItem(PyObject *o, PyObject *key);
Modified: python/branches/release26-maint/Lib/test/test_iterlen.py
==============================================================================
--- python/branches/release26-maint/Lib/test/test_iterlen.py	(original)
+++ python/branches/release26-maint/Lib/test/test_iterlen.py	Mon Feb 2 23:44:06 2009
@@ -195,6 +195,36 @@
 d.extend(xrange(20))
 self.assertEqual(len(it), 0)
 
+## -- Check to make sure exceptions are not suppressed by __length_hint__()
+
+
+class BadLen(object):
+ def __iter__(self): return iter(range(10))
+ def __len__(self):
+ raise RuntimeError('hello')
+
+class BadLengthHint(object):
+ def __iter__(self): return iter(range(10))
+ def __length_hint__(self):
+ raise RuntimeError('hello')
+
+class TestLengthHintExceptions(unittest.TestCase):
+
+ def test_issue1242657(self):
+ self.assertRaises(RuntimeError, list, BadLen())
+ self.assertRaises(RuntimeError, list, BadLengthHint())
+ self.assertRaises(RuntimeError, [].extend, BadLen())
+ self.assertRaises(RuntimeError, [].extend, BadLengthHint())
+ self.assertRaises(RuntimeError, zip, BadLen())
+ self.assertRaises(RuntimeError, zip, BadLengthHint())
+ self.assertRaises(RuntimeError, filter, None, BadLen())
+ self.assertRaises(RuntimeError, filter, None, BadLengthHint())
+ self.assertRaises(RuntimeError, map, chr, BadLen())
+ self.assertRaises(RuntimeError, map, chr, BadLengthHint())
+ b = bytearray(range(10))
+ self.assertRaises(RuntimeError, b.extend, BadLen())
+ self.assertRaises(RuntimeError, b.extend, BadLengthHint())
+
 def test_main():
 unittests = [
 TestRepeat,
@@ -209,6 +239,7 @@
 TestSet,
 TestList,
 TestListReversed,
+ TestLengthHintExceptions,
 ]
 test_support.run_unittest(*unittests)
 
Modified: python/branches/release26-maint/Misc/NEWS
==============================================================================
--- python/branches/release26-maint/Misc/NEWS	(original)
+++ python/branches/release26-maint/Misc/NEWS	Mon Feb 2 23:44:06 2009
@@ -15,6 +15,10 @@
 - Issue #5013: Fixed a bug in FileHandler which occurred when the delay
 parameter was set.
 
+- Issue 1242657: the __len__() and __length_hint__() calls in several tools
+ were suppressing all exceptions. These include list(), filter(), map(),
+ zip(), and bytearray().
+
 - Issue #4935: The overflow checking code in the expandtabs() method common
 to str, bytes and bytearray could be optimized away by the compiler, letting
 the interpreter segfault instead of raising an error.
Modified: python/branches/release26-maint/Objects/abstract.c
==============================================================================
--- python/branches/release26-maint/Objects/abstract.c	(original)
+++ python/branches/release26-maint/Objects/abstract.c	Mon Feb 2 23:44:06 2009
@@ -85,8 +85,8 @@
 
 /* The length hint function returns a non-negative value from o.__len__()
 or o.__length_hint__(). If those methods aren't found or return a negative
- value, then the defaultvalue is returned. This function never fails. 
- Accordingly, it will mask exceptions raised in either method.
+ value, then the defaultvalue is returned. If one of the calls fails,
+ this function returns -1.
 */
 
 Py_ssize_t
@@ -100,29 +100,32 @@
 	rv = PyObject_Size(o);
 	if (rv >= 0)
 		return rv;
-	if (PyErr_Occurred())
+	if (PyErr_Occurred()) {
+		if (!PyErr_ExceptionMatches(PyExc_TypeError) &&
+			!PyErr_ExceptionMatches(PyExc_AttributeError))
+				return -1;
 		PyErr_Clear();
+	}
 
 	/* cache a hashed version of the attribute string */
 	if (hintstrobj == NULL) {
 		hintstrobj = PyString_InternFromString("__length_hint__");
 		if (hintstrobj == NULL)
-			goto defaultcase;
+			return -1;
 	}
 
 	/* try o.__length_hint__() */
 	ro = PyObject_CallMethodObjArgs(o, hintstrobj, NULL);
-	if (ro == NULL)
-		goto defaultcase;
+	if (ro == NULL) {
+		if (!PyErr_ExceptionMatches(PyExc_TypeError) &&
+			!PyErr_ExceptionMatches(PyExc_AttributeError))
+				return -1;
+		PyErr_Clear();
+		return defaultvalue;
+	}
 	rv = PyInt_AsLong(ro);
 	Py_DECREF(ro);
-	if (rv >= 0)
-		return rv;
-
-defaultcase:
-	if (PyErr_Occurred())
-		PyErr_Clear();
-	return defaultvalue;
+	return rv;
 }
 
 PyObject *
@@ -2114,7 +2117,7 @@
 {
 	PyObject *it; /* iter(v) */
 	Py_ssize_t n; /* guess for result tuple size */
-	PyObject *result;
+	PyObject *result = NULL;
 	Py_ssize_t j;
 
 	if (v == NULL)
@@ -2139,6 +2142,8 @@
 
 	/* Guess result size and allocate space. */
 	n = _PyObject_LengthHint(v, 10);
+	if (n == -1)
+		goto Fail;
 	result = PyTuple_New(n);
 	if (result == NULL)
 		goto Fail;
Modified: python/branches/release26-maint/Objects/bytearrayobject.c
==============================================================================
--- python/branches/release26-maint/Objects/bytearrayobject.c	(original)
+++ python/branches/release26-maint/Objects/bytearrayobject.c	Mon Feb 2 23:44:06 2009
@@ -2679,6 +2679,10 @@
 
 /* Try to determine the length of the argument. 32 is abitrary. */
 buf_size = _PyObject_LengthHint(arg, 32);
+	if (buf_size == -1) {
+		Py_DECREF(it);
+		return NULL;
+	}
 
 bytes_obj = PyByteArray_FromStringAndSize(NULL, buf_size);
 if (bytes_obj == NULL)
Modified: python/branches/release26-maint/Objects/listobject.c
==============================================================================
--- python/branches/release26-maint/Objects/listobject.c	(original)
+++ python/branches/release26-maint/Objects/listobject.c	Mon Feb 2 23:44:06 2009
@@ -838,6 +838,10 @@
 
 	/* Guess a result list size. */
 	n = _PyObject_LengthHint(b, 8);
+	if (n == -1) {
+		Py_DECREF(it);
+		return NULL;
+	}
 	m = Py_SIZE(self);
 	mn = m + n;
 	if (mn >= m) {
Modified: python/branches/release26-maint/Python/bltinmodule.c
==============================================================================
--- python/branches/release26-maint/Python/bltinmodule.c	(original)
+++ python/branches/release26-maint/Python/bltinmodule.c	Mon Feb 2 23:44:06 2009
@@ -268,6 +268,8 @@
 
 	/* Guess a result list size. */
 	len = _PyObject_LengthHint(seq, 8);
+	if (len == -1)
+		goto Fail_it;
 
 	/* Get a result list. */
 	if (PyList_Check(seq) && seq->ob_refcnt == 1) {


More information about the Python-checkins mailing list

AltStyle によって変換されたページ (->オリジナル) /