]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
[3.7] bpo-38643: Raise SystemError instead of crashing when PyNumber_ToBase is called...
authorSerhiy Storchaka <storchaka@gmail.com>
Thu, 12 Mar 2020 08:15:17 +0000 (10:15 +0200)
committerGitHub <noreply@github.com>
Thu, 12 Mar 2020 08:15:17 +0000 (10:15 +0200)
(cherry picked from commit e5ccc94bbb153431698b2391df625e8d47a93276)

Lib/test/test_capi.py
Misc/NEWS.d/next/C API/2020-03-08-22-56-22.bpo-38643.k2ixx6.rst [new file with mode: 0644]
Modules/_testcapimodule.c
Objects/abstract.c

index d94ee0227c87664aa81dab310e89c339d792d0d1..3ed2263fda7cbe1b7f8059cd134b1a3379674a3b 100644 (file)
@@ -315,6 +315,20 @@ class CAPITest(unittest.TestCase):
         self.assertRaises(TypeError, _testcapi.get_mapping_values, bad_mapping)
         self.assertRaises(TypeError, _testcapi.get_mapping_items, bad_mapping)
 
+    def test_pynumber_tobase(self):
+        from _testcapi import pynumber_tobase
+        self.assertEqual(pynumber_tobase(123, 2), '0b1111011')
+        self.assertEqual(pynumber_tobase(123, 8), '0o173')
+        self.assertEqual(pynumber_tobase(123, 10), '123')
+        self.assertEqual(pynumber_tobase(123, 16), '0x7b')
+        self.assertEqual(pynumber_tobase(-123, 2), '-0b1111011')
+        self.assertEqual(pynumber_tobase(-123, 8), '-0o173')
+        self.assertEqual(pynumber_tobase(-123, 10), '-123')
+        self.assertEqual(pynumber_tobase(-123, 16), '-0x7b')
+        self.assertRaises(TypeError, pynumber_tobase, 123.0, 10)
+        self.assertRaises(TypeError, pynumber_tobase, '123', 10)
+        self.assertRaises(SystemError, pynumber_tobase, 123, 0)
+
 
 class TestPendingCalls(unittest.TestCase):
 
diff --git a/Misc/NEWS.d/next/C API/2020-03-08-22-56-22.bpo-38643.k2ixx6.rst b/Misc/NEWS.d/next/C API/2020-03-08-22-56-22.bpo-38643.k2ixx6.rst
new file mode 100644 (file)
index 0000000..1e6472f
--- /dev/null
@@ -0,0 +1,2 @@
+:c:func:`PyNumber_ToBase` now raises a :exc:`SystemError` instead of
+crashing when called with invalid base.
index 16ea9c2d665545a4663b43e38f5d570d0c165c96..6996d2268488459a3a3f4fee966b5d5a9e7b4712 100644 (file)
@@ -4653,6 +4653,19 @@ get_main_config(PyObject *self, PyObject *Py_UNUSED(args))
 }
 
 
+static PyObject*
+pynumber_tobase(PyObject *module, PyObject *args)
+{
+    PyObject *obj;
+    int base;
+    if (!PyArg_ParseTuple(args, "Oi:pynumber_tobase",
+                          &obj, &base)) {
+        return NULL;
+    }
+    return PyNumber_ToBase(obj, base);
+}
+
+
 static PyMethodDef TestMethods[] = {
     {"raise_exception",         raise_exception,                 METH_VARARGS},
     {"raise_memoryerror",   (PyCFunction)raise_memoryerror,  METH_NOARGS},
@@ -4888,6 +4901,7 @@ static PyMethodDef TestMethods[] = {
     {"get_global_config", get_global_config, METH_NOARGS},
     {"get_core_config", get_core_config, METH_NOARGS},
     {"get_main_config", get_main_config, METH_NOARGS},
+    {"pynumber_tobase", pynumber_tobase, METH_VARARGS},
     {NULL, NULL} /* sentinel */
 };
 
index e6831feb82433178dff215dd67a99cfdbe2f2353..4acb87266b8b9847c6af472e56eb5d0019c6fcc1 100644 (file)
@@ -1480,18 +1480,15 @@ PyNumber_Float(PyObject *o)
 PyObject *
 PyNumber_ToBase(PyObject *n, int base)
 {
-    PyObject *res = NULL;
+    if (!(base == 2 || base == 8 || base == 10 || base == 16)) {
+        PyErr_SetString(PyExc_SystemError,
+                        "PyNumber_ToBase: base must be 2, 8, 10 or 16");
+        return NULL;
+    }
     PyObject *index = PyNumber_Index(n);
-
     if (!index)
         return NULL;
-    if (PyLong_Check(index))
-        res = _PyLong_Format(index, base);
-    else
-        /* It should not be possible to get here, as
-           PyNumber_Index already has a check for the same
-           condition */
-        PyErr_SetString(PyExc_ValueError, "PyNumber_ToBase: index not int");
+    PyObject *res = _PyLong_Format(index, base);
     Py_DECREF(index);
     return res;
 }