From 5c1cd64e2965fd09ae8061d2f935b88fb53d5145 Mon Sep 17 00:00:00 2001 From: Giampaolo Rodola Date: Tue, 9 May 2023 18:58:24 +0200 Subject: [PATCH 1/3] small README changes Signed-off-by: Giampaolo Rodola --- README.rst | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/README.rst b/README.rst index 683044f6d..95a7f359f 100644 --- a/README.rst +++ b/README.rst @@ -1,6 +1,6 @@ | |downloads| |stars| |forks| |contributors| |coverage| -| |version| |py-versions| |packages| |license| |twitter| |tidelift| -| |github-actions-wheels| |github-actions-bsd| |appveyor| |doc| +| |version| |py-versions| |packages| |license| +| |github-actions-wheels| |github-actions-bsd| |appveyor| |doc| |twitter| |tidelift| .. |downloads| image:: https://img.shields.io/pypi/dm/psutil.svg :target: https://pepy.tech/project/psutil @@ -488,6 +488,7 @@ Here's some I find particularly interesting: - https://github.com/google/grr - https://github.com/facebook/osquery/ - https://github.com/nicolargo/glances +- https://github.com/aristocratos/bpytop - https://github.com/Jahaja/psdash - https://github.com/ajenti/ajenti - https://github.com/home-assistant/home-assistant/ From f24a82439d56396d911e17e734184571ee692cf7 Mon Sep 17 00:00:00 2001 From: Xuehai Pan Date: Thu, 8 Jun 2023 19:05:06 +0800 Subject: [PATCH 2/3] Check PID range before any `cext` call (#2266) Signed-off-by: Xuehai Pan 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. --- CREDITS | 2 +- HISTORY.rst | 2 ++ psutil/__init__.py | 8 ++++++++ psutil/_psutil_aix.c | 1 + psutil/_psutil_bsd.c | 1 + psutil/_psutil_common.c | 21 +++++++++++++++++++++ psutil/_psutil_common.h | 1 + psutil/_psutil_linux.c | 1 + psutil/_psutil_osx.c | 1 + psutil/_psutil_sunos.c | 1 + psutil/_psutil_windows.c | 1 + psutil/tests/test_misc.py | 6 ++++++ 12 files changed, 45 insertions(+), 1 deletion(-) diff --git a/CREDITS b/CREDITS index f5888fb79..0461d2eca 100644 --- a/CREDITS +++ b/CREDITS @@ -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 diff --git a/HISTORY.rst b/HISTORY.rst index 8a6b880d2..c0cfe9d2d 100644 --- a/HISTORY.rst +++ b/HISTORY.rst @@ -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 ===== diff --git a/psutil/__init__.py b/psutil/__init__.py index 2b0b3c6b0..bb3880840 100644 --- a/psutil/__init__.py +++ b/psutil/__init__.py @@ -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 diff --git a/psutil/_psutil_aix.c b/psutil/_psutil_aix.c index 8a1b8de94..ce89a7bd7 100644 --- a/psutil/_psutil_aix.c +++ b/psutil/_psutil_aix.c @@ -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} diff --git a/psutil/_psutil_bsd.c b/psutil/_psutil_bsd.c index a1b4a3e5b..fde3916d3 100644 --- a/psutil/_psutil_bsd.c +++ b/psutil/_psutil_bsd.c @@ -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} diff --git a/psutil/_psutil_common.c b/psutil/_psutil_common.c index 096e2f373..d8d78bf64 100644 --- a/psutil/_psutil_common.c +++ b/psutil/_psutil_common.c @@ -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 * diff --git a/psutil/_psutil_common.h b/psutil/_psutil_common.h index 591f5521f..a425f8685 100644 --- a/psutil/_psutil_common.h +++ b/psutil/_psutil_common.h @@ -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); diff --git a/psutil/_psutil_linux.c b/psutil/_psutil_linux.c index a6ee60254..3e6b3b900 100644 --- a/psutil/_psutil_linux.c +++ b/psutil/_psutil_linux.c @@ -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} diff --git a/psutil/_psutil_osx.c b/psutil/_psutil_osx.c index dd7168eb7..369fbbfb4 100644 --- a/psutil/_psutil_osx.c +++ b/psutil/_psutil_osx.c @@ -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} diff --git a/psutil/_psutil_sunos.c b/psutil/_psutil_sunos.c index 5422005fe..11335993f 100644 --- a/psutil/_psutil_sunos.c +++ b/psutil/_psutil_sunos.c @@ -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} diff --git a/psutil/_psutil_windows.c b/psutil/_psutil_windows.c index 54678f755..bb6e12ff8 100644 --- a/psutil/_psutil_windows.c +++ b/psutil/_psutil_windows.c @@ -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} diff --git a/psutil/tests/test_misc.py b/psutil/tests/test_misc.py index a7b5d02d5..53c640121 100755 --- a/psutil/tests/test_misc.py +++ b/psutil/tests/test_misc.py @@ -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) From 962cb9ad58ca3bc21b20130f435f8d507d931051 Mon Sep 17 00:00:00 2001 From: Giampaolo Rodola Date: Fri, 9 Jun 2023 15:37:14 +0200 Subject: [PATCH 3/3] bytes2human() is unable to print negative values (#2268) Signed-off-by: Giampaolo Rodola The bug: ``` >>> from psutil._common import bytes2human >>> bytes2human(212312454) 202.5M >>> bytes2human(-212312454) -212312454 ``` --- HISTORY.rst | 4 +++- docs/index.rst | 2 +- psutil/_common.py | 2 +- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/HISTORY.rst b/HISTORY.rst index c0cfe9d2d..6e1f065f4 100644 --- a/HISTORY.rst +++ b/HISTORY.rst @@ -7,8 +7,10 @@ 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`_ +- 2266_: if `Process`_ class is passed a very high PID, raise `NoSuchProcess`_ instead of OverflowError. (patch by Xuehai Pan) +- 2268_: ``bytes2human()`` utility function was unable to properly represent + negative values. 5.9.5 ===== diff --git a/docs/index.rst b/docs/index.rst index 2bf050a11..31d5d7ef5 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -2544,7 +2544,7 @@ Bytes conversion for i, s in enumerate(symbols): prefix[s] = 1 << (i + 1) * 10 for s in reversed(symbols): - if n >= prefix[s]: + if abs(n) >= prefix[s]: value = float(n) / prefix[s] return '%.1f%s' % (value, s) return "%sB" % n diff --git a/psutil/_common.py b/psutil/_common.py index 922867464..63792edbd 100644 --- a/psutil/_common.py +++ b/psutil/_common.py @@ -827,7 +827,7 @@ def bytes2human(n, format="%(value).1f%(symbol)s"): for i, s in enumerate(symbols[1:]): prefix[s] = 1 << (i + 1) * 10 for symbol in reversed(symbols[1:]): - if n >= prefix[symbol]: + if abs(n) >= prefix[symbol]: value = float(n) / prefix[symbol] return format % locals() return format % dict(symbol=symbols[0], value=n)