summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMark Dickinson <dickinsm@gmail.com>2010-09-26 10:37:12 (GMT)
committerMark Dickinson <dickinsm@gmail.com>2010-09-26 10:37:12 (GMT)
commitcb61e5d9b59c1a5f18dd34edebb054d1e19f1581 (patch)
treea52fa36e6297747487027f5d2344696a112df566
parent3eac591a5c33f4bd0bdd60a76053cd3b6b6e5918 (diff)
downloadcpython-cb61e5d9b59c1a5f18dd34edebb054d1e19f1581.zip
cpython-cb61e5d9b59c1a5f18dd34edebb054d1e19f1581.tar.gz
cpython-cb61e5d9b59c1a5f18dd34edebb054d1e19f1581.tar.bz2
Issue #9869: Make long() and PyNumber_Long return something of type
long for a class whose __long__ method returns a plain int. This fixes an interpreter crash (due to long_subtype_new assuming PyNumber_Long returns a long) when initializing an instance of a long subclass from an object whose __long__ method returns a plain int.
-rw-r--r--Lib/test/test_class.py2
-rw-r--r--Lib/test/test_long.py16
-rw-r--r--Misc/NEWS5
-rw-r--r--Objects/abstract.c9
4 files changed, 30 insertions, 2 deletions
diff --git a/Lib/test/test_class.py b/Lib/test/test_class.py
index 914ea73..e7b7752 100644
--- a/Lib/test/test_class.py
+++ b/Lib/test/test_class.py
@@ -513,7 +513,7 @@ class ClassTests(unittest.TestCase):
callLst[:] = []
as_long = long(mixIntAndLong)
- self.assertEquals(type(as_long), int)
+ self.assertEquals(type(as_long), long)
self.assertEquals(as_long, 64)
self.assertCallStack([('__long__', (mixIntAndLong,))])
diff --git a/Lib/test/test_long.py b/Lib/test/test_long.py
index 412ec7c..9706a8e 100644
--- a/Lib/test/test_long.py
+++ b/Lib/test/test_long.py
@@ -601,6 +601,22 @@ class LongTest(unittest.TestCase):
slicemin, slicemax = X()[-2L**100:2L**100]
self.assertEqual(X()[slicemin:slicemax], (slicemin, slicemax))
+ def test_issue9869(self):
+ # Issue 9869: Interpreter crash when initializing an instance
+ # of a long subclass from an object whose __long__ method returns
+ # a plain int.
+ class BadLong(object):
+ def __long__(self):
+ return 1000000
+
+ class MyLong(long):
+ pass
+
+ x = MyLong(BadLong())
+ self.assertIsInstance(x, long)
+ self.assertEqual(x, 1000000)
+
+
# ----------------------------------- tests of auto int->long conversion
def test_auto_overflow(self):
diff --git a/Misc/NEWS b/Misc/NEWS
index 90a1761..99d905d 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -12,6 +12,11 @@ What's New in Python 2.7.1?
Core and Builtins
-----------------
+- Issue #9869: Make long() and PyNumber_Long return something of type
+ long for a class whose __long__ method returns a plain int. This
+ fixes an interpreter crash when initializing an instance of a long
+ subclass from an object whose __long__ method returns a plain int.
+
- Issue #9797: pystate.c wrongly assumed that zero couldn't be a valid
thread-local storage key.
diff --git a/Objects/abstract.c b/Objects/abstract.c
index 75de1aa..1e79ddf 100644
--- a/Objects/abstract.c
+++ b/Objects/abstract.c
@@ -1713,7 +1713,14 @@ PyNumber_Long(PyObject *o)
if (m && m->nb_long) { /* This should include subclasses of long */
/* Classic classes always take this branch. */
PyObject *res = m->nb_long(o);
- if (res && (!PyInt_Check(res) && !PyLong_Check(res))) {
+ if (res == NULL)
+ return NULL;
+ if (PyInt_Check(res)) {
+ long value = PyInt_AS_LONG(res);
+ Py_DECREF(res);
+ return PyLong_FromLong(value);
+ }
+ else if (!PyLong_Check(res)) {
PyErr_Format(PyExc_TypeError,
"__long__ returned non-long (type %.200s)",
res->ob_type->tp_name);