Skip to content

Commit

Permalink
Check PID range before any cext call (#2266)
Browse files Browse the repository at this point in the history
Signed-off-by: Xuehai Pan <[email protected]>

Giampaolo:

I think it makes sense. The error originates from PyArg_ParseTuple (used pretty much everywhere). The Process class can invoke PyArg_ParseTuple on __init__ (hence only once) and turn OverflowError into NoSuchProcess.

The reason why I think this is a good idea is because OverflowError is only raised when invoking C functions. On Linux most of Process APIs are implemented in python instead, by reading /proc, so we do not get OverflowError in those cases (we get NoSuchProcess). As such, making this change would make things more consistent across all platforms, which will always rase NoSuchProcess.
  • Loading branch information
XuehaiPan committed Jun 8, 2023
1 parent 49aba75 commit f24a824
Show file tree
Hide file tree
Showing 12 changed files with 45 additions and 1 deletion.
2 changes: 1 addition & 1 deletion CREDITS
Original file line number Diff line number Diff line change
Expand Up @@ -765,7 +765,7 @@ I: 1598

N: Xuehai Pan
W: https://github.com/XuehaiPan
I: 1948
I: 1948, 2264

N: Saeed Rasooli
W: https://github.com/ilius
Expand Down
2 changes: 2 additions & 0 deletions HISTORY.rst
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ XXXX-XX-XX

- 2241_, [NetBSD]: can't compile On NetBSD 10.99.3/amd64. (patch by Thomas
Klausner)
- 2266_: if `Process`_ class is passed a very high PID, raise `NoSuchProcess`_
instead of OverflowError. (patch by Xuehai Pan)

5.9.5
=====
Expand Down
8 changes: 8 additions & 0 deletions psutil/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -340,6 +340,14 @@ def _init(self, pid, _ignore_nsp=False):
if pid < 0:
raise ValueError('pid must be a positive integer (got %s)'
% pid)
try:
_psplatform.cext.check_pid_range(pid)
except OverflowError:
raise NoSuchProcess(
pid,
msg='process PID out of range (got %s)' % pid,
)

self._pid = pid
self._name = None
self._exe = None
Expand Down
1 change: 1 addition & 0 deletions psutil/_psutil_aix.c
Original file line number Diff line number Diff line change
Expand Up @@ -1019,6 +1019,7 @@ PsutilMethods[] =
{"net_if_stats", psutil_net_if_stats, METH_VARARGS},

// --- others
{"check_pid_range", psutil_check_pid_range, METH_VARARGS},
{"set_debug", psutil_set_debug, METH_VARARGS},

{NULL, NULL, 0, NULL}
Expand Down
1 change: 1 addition & 0 deletions psutil/_psutil_bsd.c
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@ static PyMethodDef mod_methods[] = {
{"sensors_cpu_temperature", psutil_sensors_cpu_temperature, METH_VARARGS},
#endif
// --- others
{"check_pid_range", psutil_check_pid_range, METH_VARARGS},
{"set_debug", psutil_set_debug, METH_VARARGS},

{NULL, NULL, 0, NULL}
Expand Down
21 changes: 21 additions & 0 deletions psutil/_psutil_common.c
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,27 @@ AccessDenied(const char *syscall) {
return NULL;
}

/*
* Raise OverflowError if Python int value overflowed when converting to pid_t.
* Raise ValueError if Python int value is negative.
* Otherwise, return None.
*/
PyObject *
psutil_check_pid_range(PyObject *self, PyObject *args) {
#ifdef PSUTIL_WINDOWS
DWORD pid;
#else
pid_t pid;
#endif

if (!PyArg_ParseTuple(args, _Py_PARSE_PID, &pid))
return NULL;
if (pid < 0) {
PyErr_SetString(PyExc_ValueError, "pid must be a positive integer");
return NULL;
}
Py_RETURN_NONE;
}

// Enable or disable PSUTIL_DEBUG messages.
PyObject *
Expand Down
1 change: 1 addition & 0 deletions psutil/_psutil_common.h
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ PyObject* PyErr_SetFromOSErrnoWithSyscall(const char *syscall);
// --- Global utils
// ====================================================================

PyObject* psutil_check_pid_range(PyObject *self, PyObject *args);
PyObject* psutil_set_debug(PyObject *self, PyObject *args);
int psutil_setup(void);

Expand Down
1 change: 1 addition & 0 deletions psutil/_psutil_linux.c
Original file line number Diff line number Diff line change
Expand Up @@ -518,6 +518,7 @@ static PyMethodDef mod_methods[] = {
// --- linux specific
{"linux_sysinfo", psutil_linux_sysinfo, METH_VARARGS},
// --- others
{"check_pid_range", psutil_check_pid_range, METH_VARARGS},
{"set_debug", psutil_set_debug, METH_VARARGS},

{NULL, NULL, 0, NULL}
Expand Down
1 change: 1 addition & 0 deletions psutil/_psutil_osx.c
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ static PyMethodDef mod_methods[] = {
{"virtual_mem", psutil_virtual_mem, METH_VARARGS},

// --- others
{"check_pid_range", psutil_check_pid_range, METH_VARARGS},
{"set_debug", psutil_set_debug, METH_VARARGS},

{NULL, NULL, 0, NULL}
Expand Down
1 change: 1 addition & 0 deletions psutil/_psutil_sunos.c
Original file line number Diff line number Diff line change
Expand Up @@ -1659,6 +1659,7 @@ PsutilMethods[] = {
{"users", psutil_users, METH_VARARGS},

// --- others
{"check_pid_range", psutil_check_pid_range, METH_VARARGS},
{"set_debug", psutil_set_debug, METH_VARARGS},

{NULL, NULL, 0, NULL}
Expand Down
1 change: 1 addition & 0 deletions psutil/_psutil_windows.c
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ PsutilMethods[] = {
{"QueryDosDevice", psutil_QueryDosDevice, METH_VARARGS},

// --- others
{"check_pid_range", psutil_check_pid_range, METH_VARARGS},
{"set_debug", psutil_set_debug, METH_VARARGS},

{NULL, NULL, 0, NULL}
Expand Down
6 changes: 6 additions & 0 deletions psutil/tests/test_misc.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,12 @@

class TestSpecialMethods(PsutilTestCase):

def test_check_pid_range(self):
with self.assertRaises(OverflowError):
psutil._psplatform.cext.check_pid_range(2 ** 128)
with self.assertRaises(psutil.NoSuchProcess):
psutil.Process(2 ** 128)

def test_process__repr__(self, func=repr):
p = psutil.Process(self.spawn_testproc().pid)
r = func(p)
Expand Down

0 comments on commit f24a824

Please sign in to comment.