]> granicus.if.org Git - python/commitdiff
Issue #9869: Make long() and PyNumber_Long return something of type
authorMark Dickinson <dickinsm@gmail.com>
Sun, 26 Sep 2010 10:37:12 +0000 (10:37 +0000)
committerMark Dickinson <dickinsm@gmail.com>
Sun, 26 Sep 2010 10:37:12 +0000 (10:37 +0000)
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.

Lib/test/test_class.py
Lib/test/test_long.py
Misc/NEWS
Objects/abstract.c

index 914ea73c40d3f0f06cc5d5da9cb7bdcbe476f65b..e7b775250aed3382b9c1fae72914e1f9eb541e09 100644 (file)
@@ -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,))])
 
index 412ec7c52517c96b5dfdb183d30c7f464be261dc..9706a8e0c93c86c6e964f639396b306b7e2f072e 100644 (file)
@@ -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):
index 90a17617fa7c711053346f5b60a71a30a8dc7f5c..99d905df2c5ce587a18613e84b0e1d32579613d9 100644 (file)
--- 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.
 
index 75de1aa047a66b246e591ba9baf59cf48cc917bd..1e79ddf4a35be7e583b50064e83a570c1dab507c 100644 (file)
@@ -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);