Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit da2f9d1

Browse files
[3.12] gh-117021: Fix integer overflow in PyLong_AsPid() on non-Windows 64-bit platforms (GH-117064) (GH-117070)
(cherry picked from commit 519b2ae)
1 parent 0325a8a commit da2f9d1

File tree

6 files changed

+60
-4
lines changed

6 files changed

+60
-4
lines changed

Include/Python.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,9 @@
4949
#include "bytearrayobject.h"
5050
#include "bytesobject.h"
5151
#include "unicodeobject.h"
52+
#include "cpython/initconfig.h"
53+
#include "pystate.h"
54+
#include "pyerrors.h"
5255
#include "longobject.h"
5356
#include "cpython/longintrepr.h"
5457
#include "boolobject.h"
@@ -74,8 +77,6 @@
7477
#include "sliceobject.h"
7578
#include "cpython/cellobject.h"
7679
#include "iterobject.h"
77-
#include "cpython/initconfig.h"
78-
#include "pystate.h"
7980
#include "cpython/genobject.h"
8081
#include "descrobject.h"
8182
#include "genericaliasobject.h"
@@ -85,7 +86,6 @@
8586
#include "cpython/picklebufobject.h"
8687
#include "cpython/pytime.h"
8788
#include "codecs.h"
88-
#include "pyerrors.h"
8989
#include "pythread.h"
9090
#include "cpython/context.h"
9191
#include "modsupport.h"

Include/longobject.h

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,24 @@ PyAPI_FUNC(PyObject *) PyLong_GetInfo(void);
3434
#if !defined(SIZEOF_PID_T) || SIZEOF_PID_T == SIZEOF_INT
3535
#define _Py_PARSE_PID "i"
3636
#define PyLong_FromPid PyLong_FromLong
37-
#define PyLong_AsPid PyLong_AsLong
37+
# ifndef Py_LIMITED_API
38+
# define PyLong_AsPid _PyLong_AsInt
39+
# elif SIZEOF_INT == SIZEOF_LONG
40+
# define PyLong_AsPid PyLong_AsLong
41+
# else
42+
static inline int
43+
PyLong_AsPid(PyObject *obj)
44+
{
45+
int overflow;
46+
long result = PyLong_AsLongAndOverflow(obj, &overflow);
47+
if (overflow || result > INT_MAX || result < INT_MIN) {
48+
PyErr_SetString(PyExc_OverflowError,
49+
"Python int too large to convert to C int");
50+
return -1;
51+
}
52+
return (int)result;
53+
}
54+
# endif
3855
#elif SIZEOF_PID_T == SIZEOF_LONG
3956
#define _Py_PARSE_PID "l"
4057
#define PyLong_FromPid PyLong_FromLong

Lib/test/test_capi/test_long.py

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -400,6 +400,29 @@ def test_long_asvoidptr(self):
400400
self.assertRaises(OverflowError, asvoidptr, -2**1000)
401401
# CRASHES asvoidptr(NULL)
402402

403+
def test_long_aspid(self):
404+
# Test PyLong_AsPid()
405+
aspid = _testcapi.pylong_aspid
406+
from _testcapi import SIZEOF_PID_T
407+
bits = 8 * SIZEOF_PID_T
408+
PID_T_MIN = -2**(bits-1)
409+
PID_T_MAX = 2**(bits-1) - 1
410+
# round trip (object -> long -> object)
411+
for value in (PID_T_MIN, PID_T_MAX, -1, 0, 1, 1234):
412+
with self.subTest(value=value):
413+
self.assertEqual(aspid(value), value)
414+
415+
self.assertEqual(aspid(IntSubclass(42)), 42)
416+
self.assertEqual(aspid(Index(42)), 42)
417+
self.assertEqual(aspid(MyIndexAndInt()), 10)
418+
419+
self.assertRaises(OverflowError, aspid, PID_T_MIN - 1)
420+
self.assertRaises(OverflowError, aspid, PID_T_MAX + 1)
421+
self.assertRaises(TypeError, aspid, 1.0)
422+
self.assertRaises(TypeError, aspid, b'2')
423+
self.assertRaises(TypeError, aspid, '3')
424+
self.assertRaises(SystemError, aspid, NULL)
425+
403426

404427
if __name__ == "__main__":
405428
unittest.main()
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Fix integer overflow in :c:func:`PyLong_AsPid` on non-Windows 64-bit
2+
platforms.

Modules/_testcapi/long.c

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -750,6 +750,18 @@ pylong_asvoidptr(PyObject *module, PyObject *arg)
750750
return Py_NewRef((PyObject *)value);
751751
}
752752

753+
static PyObject *
754+
pylong_aspid(PyObject *module, PyObject *arg)
755+
{
756+
NULLABLE(arg);
757+
pid_t value = PyLong_AsPid(arg);
758+
if (value == -1 && PyErr_Occurred()) {
759+
return NULL;
760+
}
761+
return PyLong_FromPid(value);
762+
}
763+
764+
753765
static PyMethodDef test_methods[] = {
754766
{"test_long_and_overflow", test_long_and_overflow, METH_NOARGS},
755767
{"test_long_api", test_long_api, METH_NOARGS},
@@ -778,6 +790,7 @@ static PyMethodDef test_methods[] = {
778790
{"pylong_as_size_t", pylong_as_size_t, METH_O},
779791
{"pylong_asdouble", pylong_asdouble, METH_O},
780792
{"pylong_asvoidptr", pylong_asvoidptr, METH_O},
793+
{"pylong_aspid", pylong_aspid, METH_O},
781794
{NULL},
782795
};
783796

Modules/_testcapimodule.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3986,6 +3986,7 @@ PyInit__testcapi(void)
39863986
PyModule_AddObject(m, "SIZEOF_WCHAR_T", PyLong_FromSsize_t(sizeof(wchar_t)));
39873987
PyModule_AddObject(m, "SIZEOF_VOID_P", PyLong_FromSsize_t(sizeof(void*)));
39883988
PyModule_AddObject(m, "SIZEOF_TIME_T", PyLong_FromSsize_t(sizeof(time_t)));
3989+
PyModule_AddObject(m, "SIZEOF_PID_T", PyLong_FromSsize_t(sizeof(pid_t)));
39893990
PyModule_AddObject(m, "Py_Version", PyLong_FromUnsignedLong(Py_Version));
39903991
Py_INCREF(&PyInstanceMethod_Type);
39913992
PyModule_AddObject(m, "instancemethod", (PyObject *)&PyInstanceMethod_Type);

0 commit comments

Comments
 (0)