Commit cb61e5d9 authored by Mark Dickinson's avatar Mark Dickinson

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.
parent 3eac591a
......@@ -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,))])
......
......@@ -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):
......
......@@ -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.
......
......@@ -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);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment