summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSerhiy Storchaka <storchaka@gmail.com>2024-03-20 14:44:05 (GMT)
committerGitHub <noreply@github.com>2024-03-20 14:44:05 (GMT)
commitda2f9d1417a7d28df6e1ced87d64ecf28acb0a5f (patch)
tree9b1c411e9c5ba14971109cc512c10dcdde2bcd5a
parent0325a8a8cdba6c091bcbbb3c995f3bf1d1217012 (diff)
downloadcpython-da2f9d1417a7d28df6e1ced87d64ecf28acb0a5f.zip
cpython-da2f9d1417a7d28df6e1ced87d64ecf28acb0a5f.tar.gz
cpython-da2f9d1417a7d28df6e1ced87d64ecf28acb0a5f.tar.bz2
[3.12] gh-117021: Fix integer overflow in PyLong_AsPid() on non-Windows 64-bit platforms (GH-117064) (GH-117070)
(cherry picked from commit 519b2ae22b54760475bbf62b9558d453c703f9c6)
-rw-r--r--Include/Python.h6
-rw-r--r--Include/longobject.h19
-rw-r--r--Lib/test/test_capi/test_long.py23
-rw-r--r--Misc/NEWS.d/next/C API/2024-03-20-13-13-22.gh-issue-117021.0Q5jBx.rst2
-rw-r--r--Modules/_testcapi/long.c13
-rw-r--r--Modules/_testcapimodule.c1
6 files changed, 60 insertions, 4 deletions
diff --git a/Include/Python.h b/Include/Python.h
index 52a7aac..5eddda6 100644
--- a/Include/Python.h
+++ b/Include/Python.h
@@ -49,6 +49,9 @@
#include "bytearrayobject.h"
#include "bytesobject.h"
#include "unicodeobject.h"
+#include "cpython/initconfig.h"
+#include "pystate.h"
+#include "pyerrors.h"
#include "longobject.h"
#include "cpython/longintrepr.h"
#include "boolobject.h"
@@ -74,8 +77,6 @@
#include "sliceobject.h"
#include "cpython/cellobject.h"
#include "iterobject.h"
-#include "cpython/initconfig.h"
-#include "pystate.h"
#include "cpython/genobject.h"
#include "descrobject.h"
#include "genericaliasobject.h"
@@ -85,7 +86,6 @@
#include "cpython/picklebufobject.h"
#include "cpython/pytime.h"
#include "codecs.h"
-#include "pyerrors.h"
#include "pythread.h"
#include "cpython/context.h"
#include "modsupport.h"
diff --git a/Include/longobject.h b/Include/longobject.h
index e090dd0..c8b7497 100644
--- a/Include/longobject.h
+++ b/Include/longobject.h
@@ -34,7 +34,24 @@ PyAPI_FUNC(PyObject *) PyLong_GetInfo(void);
#if !defined(SIZEOF_PID_T) || SIZEOF_PID_T == SIZEOF_INT
#define _Py_PARSE_PID "i"
#define PyLong_FromPid PyLong_FromLong
-#define PyLong_AsPid PyLong_AsLong
+# ifndef Py_LIMITED_API
+# define PyLong_AsPid _PyLong_AsInt
+# elif SIZEOF_INT == SIZEOF_LONG
+# define PyLong_AsPid PyLong_AsLong
+# else
+static inline int
+PyLong_AsPid(PyObject *obj)
+{
+ int overflow;
+ long result = PyLong_AsLongAndOverflow(obj, &overflow);
+ if (overflow || result > INT_MAX || result < INT_MIN) {
+ PyErr_SetString(PyExc_OverflowError,
+ "Python int too large to convert to C int");
+ return -1;
+ }
+ return (int)result;
+}
+# endif
#elif SIZEOF_PID_T == SIZEOF_LONG
#define _Py_PARSE_PID "l"
#define PyLong_FromPid PyLong_FromLong
diff --git a/Lib/test/test_capi/test_long.py b/Lib/test/test_capi/test_long.py
index 8261cc3..39fef24 100644
--- a/Lib/test/test_capi/test_long.py
+++ b/Lib/test/test_capi/test_long.py
@@ -400,6 +400,29 @@ class LongTests(unittest.TestCase):
self.assertRaises(OverflowError, asvoidptr, -2**1000)
# CRASHES asvoidptr(NULL)
+ def test_long_aspid(self):
+ # Test PyLong_AsPid()
+ aspid = _testcapi.pylong_aspid
+ from _testcapi import SIZEOF_PID_T
+ bits = 8 * SIZEOF_PID_T
+ PID_T_MIN = -2**(bits-1)
+ PID_T_MAX = 2**(bits-1) - 1
+ # round trip (object -> long -> object)
+ for value in (PID_T_MIN, PID_T_MAX, -1, 0, 1, 1234):
+ with self.subTest(value=value):
+ self.assertEqual(aspid(value), value)
+
+ self.assertEqual(aspid(IntSubclass(42)), 42)
+ self.assertEqual(aspid(Index(42)), 42)
+ self.assertEqual(aspid(MyIndexAndInt()), 10)
+
+ self.assertRaises(OverflowError, aspid, PID_T_MIN - 1)
+ self.assertRaises(OverflowError, aspid, PID_T_MAX + 1)
+ self.assertRaises(TypeError, aspid, 1.0)
+ self.assertRaises(TypeError, aspid, b'2')
+ self.assertRaises(TypeError, aspid, '3')
+ self.assertRaises(SystemError, aspid, NULL)
+
if __name__ == "__main__":
unittest.main()
diff --git a/Misc/NEWS.d/next/C API/2024-03-20-13-13-22.gh-issue-117021.0Q5jBx.rst b/Misc/NEWS.d/next/C API/2024-03-20-13-13-22.gh-issue-117021.0Q5jBx.rst
new file mode 100644
index 0000000..2f93e1e
--- /dev/null
+++ b/Misc/NEWS.d/next/C API/2024-03-20-13-13-22.gh-issue-117021.0Q5jBx.rst
@@ -0,0 +1,2 @@
+Fix integer overflow in :c:func:`PyLong_AsPid` on non-Windows 64-bit
+platforms.
diff --git a/Modules/_testcapi/long.c b/Modules/_testcapi/long.c
index 213c676..9c5a0e3 100644
--- a/Modules/_testcapi/long.c
+++ b/Modules/_testcapi/long.c
@@ -750,6 +750,18 @@ pylong_asvoidptr(PyObject *module, PyObject *arg)
return Py_NewRef((PyObject *)value);
}
+static PyObject *
+pylong_aspid(PyObject *module, PyObject *arg)
+{
+ NULLABLE(arg);
+ pid_t value = PyLong_AsPid(arg);
+ if (value == -1 && PyErr_Occurred()) {
+ return NULL;
+ }
+ return PyLong_FromPid(value);
+}
+
+
static PyMethodDef test_methods[] = {
{"test_long_and_overflow", test_long_and_overflow, METH_NOARGS},
{"test_long_api", test_long_api, METH_NOARGS},
@@ -778,6 +790,7 @@ static PyMethodDef test_methods[] = {
{"pylong_as_size_t", pylong_as_size_t, METH_O},
{"pylong_asdouble", pylong_asdouble, METH_O},
{"pylong_asvoidptr", pylong_asvoidptr, METH_O},
+ {"pylong_aspid", pylong_aspid, METH_O},
{NULL},
};
diff --git a/Modules/_testcapimodule.c b/Modules/_testcapimodule.c
index 48c8f92..e906658 100644
--- a/Modules/_testcapimodule.c
+++ b/Modules/_testcapimodule.c
@@ -3986,6 +3986,7 @@ PyInit__testcapi(void)
PyModule_AddObject(m, "SIZEOF_WCHAR_T", PyLong_FromSsize_t(sizeof(wchar_t)));
PyModule_AddObject(m, "SIZEOF_VOID_P", PyLong_FromSsize_t(sizeof(void*)));
PyModule_AddObject(m, "SIZEOF_TIME_T", PyLong_FromSsize_t(sizeof(time_t)));
+ PyModule_AddObject(m, "SIZEOF_PID_T", PyLong_FromSsize_t(sizeof(pid_t)));
PyModule_AddObject(m, "Py_Version", PyLong_FromUnsignedLong(Py_Version));
Py_INCREF(&PyInstanceMethod_Type);
PyModule_AddObject(m, "instancemethod", (PyObject *)&PyInstanceMethod_Type);