mirror of
https://github.com/python/cpython.git
synced 2025-09-27 02:39:58 +00:00
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.
This commit is contained in:
parent
3eac591a5c
commit
cb61e5d9b5
4 changed files with 30 additions and 2 deletions
|
@ -513,7 +513,7 @@ class ClassTests(unittest.TestCase):
|
||||||
|
|
||||||
callLst[:] = []
|
callLst[:] = []
|
||||||
as_long = long(mixIntAndLong)
|
as_long = long(mixIntAndLong)
|
||||||
self.assertEquals(type(as_long), int)
|
self.assertEquals(type(as_long), long)
|
||||||
self.assertEquals(as_long, 64)
|
self.assertEquals(as_long, 64)
|
||||||
self.assertCallStack([('__long__', (mixIntAndLong,))])
|
self.assertCallStack([('__long__', (mixIntAndLong,))])
|
||||||
|
|
||||||
|
|
|
@ -601,6 +601,22 @@ class LongTest(unittest.TestCase):
|
||||||
slicemin, slicemax = X()[-2L**100:2L**100]
|
slicemin, slicemax = X()[-2L**100:2L**100]
|
||||||
self.assertEqual(X()[slicemin:slicemax], (slicemin, slicemax))
|
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
|
# ----------------------------------- tests of auto int->long conversion
|
||||||
|
|
||||||
def test_auto_overflow(self):
|
def test_auto_overflow(self):
|
||||||
|
|
|
@ -12,6 +12,11 @@ What's New in Python 2.7.1?
|
||||||
Core and Builtins
|
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
|
- Issue #9797: pystate.c wrongly assumed that zero couldn't be a valid
|
||||||
thread-local storage key.
|
thread-local storage key.
|
||||||
|
|
||||||
|
|
|
@ -1713,7 +1713,14 @@ PyNumber_Long(PyObject *o)
|
||||||
if (m && m->nb_long) { /* This should include subclasses of long */
|
if (m && m->nb_long) { /* This should include subclasses of long */
|
||||||
/* Classic classes always take this branch. */
|
/* Classic classes always take this branch. */
|
||||||
PyObject *res = m->nb_long(o);
|
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,
|
PyErr_Format(PyExc_TypeError,
|
||||||
"__long__ returned non-long (type %.200s)",
|
"__long__ returned non-long (type %.200s)",
|
||||||
res->ob_type->tp_name);
|
res->ob_type->tp_name);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue