From 3ad0cf0271141d92d69a9c70114f7ade66713c30 Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Sun, 3 Aug 2025 13:16:42 +0300 Subject: [PATCH 1/8] gh-137044: Support large limit values in getrlimit() and setrlimit() * Return large limit values as positive integers instead of negative integers in resource.getrlimit(). * Accept large values and reject negative values (except RLIM_INFINITY) for limits in resource.setrlimit(). --- Lib/test/test_resource.py | 198 +++++++++++------- ...-08-03-13-16-39.gh-issue-137044.0hPVL_.rst | 4 + Modules/resource.c | 84 ++++---- 3 files changed, 172 insertions(+), 114 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2025-08-03-13-16-39.gh-issue-137044.0hPVL_.rst diff --git a/Lib/test/test_resource.py b/Lib/test/test_resource.py index d23d3623235f38..517c501f7ffc23 100644 --- a/Lib/test/test_resource.py +++ b/Lib/test/test_resource.py @@ -14,89 +14,133 @@ class ResourceTest(unittest.TestCase): def test_args(self): self.assertRaises(TypeError, resource.getrlimit) - self.assertRaises(TypeError, resource.getrlimit, 42, 42) + self.assertRaises(TypeError, resource.getrlimit, 0, 42) + self.assertRaises(OverflowError, resource.getrlimit, 2**1000) + self.assertRaises(OverflowError, resource.getrlimit, -2**1000) + self.assertRaises(TypeError, resource.getrlimit, '0') self.assertRaises(TypeError, resource.setrlimit) - self.assertRaises(TypeError, resource.setrlimit, 42, 42, 42) + self.assertRaises(TypeError, resource.setrlimit, 0) + self.assertRaises(TypeError, resource.setrlimit, 0, 42) + self.assertRaises(TypeError, resource.setrlimit, 0, 42, 42) + self.assertRaises(OverflowError, resource.setrlimit, 2**1000, (42, 42)) + self.assertRaises(OverflowError, resource.setrlimit, -2**1000, (42, 42)) + self.assertRaises(ValueError, resource.setrlimit, 0, (42,)) + self.assertRaises(ValueError, resource.setrlimit, 0, (42, 42, 42)) + self.assertRaises(TypeError, resource.setrlimit, '0', (42, 42)) + self.assertRaises(TypeError, resource.setrlimit, 0, ('42', 42)) + self.assertRaises(TypeError, resource.setrlimit, 0, (42, '42')) @unittest.skipIf(sys.platform == "vxworks", "setting RLIMIT_FSIZE is not supported on VxWorks") + @unittest.skipUnless(hasattr(resource, 'RLIMIT_FSIZE'), 'requires resource.RLIMIT_FSIZE') def test_fsize_ismax(self): - try: - (cur, max) = resource.getrlimit(resource.RLIMIT_FSIZE) - except AttributeError: - pass - else: - # RLIMIT_FSIZE should be RLIM_INFINITY, which will be a really big - # number on a platform with large file support. On these platforms, - # we need to test that the get/setrlimit functions properly convert - # the number to a C long long and that the conversion doesn't raise - # an error. - self.assertEqual(resource.RLIM_INFINITY, max) - resource.setrlimit(resource.RLIMIT_FSIZE, (cur, max)) + (cur, max) = resource.getrlimit(resource.RLIMIT_FSIZE) + # RLIMIT_FSIZE should be RLIM_INFINITY, which will be a really big + # number on a platform with large file support. On these platforms, + # we need to test that the get/setrlimit functions properly convert + # the number to a C long long and that the conversion doesn't raise + # an error. + self.assertEqual(resource.RLIM_INFINITY, max) + resource.setrlimit(resource.RLIMIT_FSIZE, (cur, max)) + @unittest.skipIf(sys.platform == "vxworks", + "setting RLIMIT_FSIZE is not supported on VxWorks") + @unittest.skipUnless(hasattr(resource, 'RLIMIT_FSIZE'), 'requires resource.RLIMIT_FSIZE') def test_fsize_enforced(self): + (cur, max) = resource.getrlimit(resource.RLIMIT_FSIZE) + # Check to see what happens when the RLIMIT_FSIZE is small. Some + # versions of Python were terminated by an uncaught SIGXFSZ, but + # pythonrun.c has been fixed to ignore that exception. If so, the + # write() should return EFBIG when the limit is exceeded. + + # At least one platform has an unlimited RLIMIT_FSIZE and attempts + # to change it raise ValueError instead. try: - (cur, max) = resource.getrlimit(resource.RLIMIT_FSIZE) - except AttributeError: - pass - else: - # Check to see what happens when the RLIMIT_FSIZE is small. Some - # versions of Python were terminated by an uncaught SIGXFSZ, but - # pythonrun.c has been fixed to ignore that exception. If so, the - # write() should return EFBIG when the limit is exceeded. - - # At least one platform has an unlimited RLIMIT_FSIZE and attempts - # to change it raise ValueError instead. try: + resource.setrlimit(resource.RLIMIT_FSIZE, (1024, max)) + limit_set = True + except ValueError: + limit_set = False + f = open(os_helper.TESTFN, "wb") + try: + f.write(b"X" * 1024) try: - resource.setrlimit(resource.RLIMIT_FSIZE, (1024, max)) - limit_set = True - except ValueError: - limit_set = False - f = open(os_helper.TESTFN, "wb") - try: - f.write(b"X" * 1024) - try: - f.write(b"Y") + f.write(b"Y") + f.flush() + # On some systems (e.g., Ubuntu on hppa) the flush() + # doesn't always cause the exception, but the close() + # does eventually. Try flushing several times in + # an attempt to ensure the file is really synced and + # the exception raised. + for i in range(5): + time.sleep(.1) f.flush() - # On some systems (e.g., Ubuntu on hppa) the flush() - # doesn't always cause the exception, but the close() - # does eventually. Try flushing several times in - # an attempt to ensure the file is really synced and - # the exception raised. - for i in range(5): - time.sleep(.1) - f.flush() - except OSError: - if not limit_set: - raise - if limit_set: - # Close will attempt to flush the byte we wrote - # Restore limit first to avoid getting a spurious error - resource.setrlimit(resource.RLIMIT_FSIZE, (cur, max)) - finally: - f.close() - finally: + except OSError: + if not limit_set: + raise if limit_set: + # Close will attempt to flush the byte we wrote + # Restore limit first to avoid getting a spurious error resource.setrlimit(resource.RLIMIT_FSIZE, (cur, max)) - os_helper.unlink(os_helper.TESTFN) + finally: + f.close() + finally: + if limit_set: + resource.setrlimit(resource.RLIMIT_FSIZE, (cur, max)) + os_helper.unlink(os_helper.TESTFN) - def test_fsize_toobig(self): + @unittest.skipIf(sys.platform == "vxworks", + "setting RLIMIT_FSIZE is not supported on VxWorks") + @unittest.skipUnless(hasattr(resource, 'RLIMIT_FSIZE'), 'requires resource.RLIMIT_FSIZE') + def test_fsize_too_big(self): # Be sure that setrlimit is checking for really large values too_big = 10**50 + (cur, max) = resource.getrlimit(resource.RLIMIT_FSIZE) + try: + resource.setrlimit(resource.RLIMIT_FSIZE, (too_big, max)) + except (OverflowError, ValueError): + pass try: - (cur, max) = resource.getrlimit(resource.RLIMIT_FSIZE) - except AttributeError: + resource.setrlimit(resource.RLIMIT_FSIZE, (max, too_big)) + except (OverflowError, ValueError): + pass + + @unittest.skipIf(sys.platform == "vxworks", + "setting RLIMIT_FSIZE is not supported on VxWorks") + @unittest.skipUnless(hasattr(resource, 'RLIMIT_FSIZE'), 'requires resource.RLIMIT_FSIZE') + def test_fsize_not_too_big(self): + (cur, max) = resource.getrlimit(resource.RLIMIT_FSIZE) + self.addCleanup(resource.setrlimit, resource.RLIMIT_FSIZE, (cur, max)) + + resource.setrlimit(resource.RLIMIT_FSIZE, (2**31-1, max)) + self.assertEqual(resource.getrlimit(resource.RLIMIT_FSIZE), (2**31-1, max)) + resource.setrlimit(resource.RLIMIT_FSIZE, (2**31, max)) + self.assertEqual(resource.getrlimit(resource.RLIMIT_FSIZE), (2**31, max)) + resource.setrlimit(resource.RLIMIT_FSIZE, (2**32-2, max)) + self.assertEqual(resource.getrlimit(resource.RLIMIT_FSIZE), (2**32-2, max)) + + try: + resource.setrlimit(resource.RLIMIT_FSIZE, (2**32, max)) + except OverflowError: pass else: - try: - resource.setrlimit(resource.RLIMIT_FSIZE, (too_big, max)) - except (OverflowError, ValueError): - pass - try: - resource.setrlimit(resource.RLIMIT_FSIZE, (max, too_big)) - except (OverflowError, ValueError): - pass + self.assertEqual(resource.getrlimit(resource.RLIMIT_FSIZE), (2**32, max)) + resource.setrlimit(resource.RLIMIT_FSIZE, (2**63-1, max)) + self.assertEqual(resource.getrlimit(resource.RLIMIT_FSIZE), (2**63-1, max)) + resource.setrlimit(resource.RLIMIT_FSIZE, (2**63, max)) + self.assertEqual(resource.getrlimit(resource.RLIMIT_FSIZE), (2**63, max)) + resource.setrlimit(resource.RLIMIT_FSIZE, (2**64-2, max)) + self.assertEqual(resource.getrlimit(resource.RLIMIT_FSIZE), (2**64-2, max)) + + @unittest.skipIf(sys.platform == "vxworks", + "setting RLIMIT_FSIZE is not supported on VxWorks") + @unittest.skipUnless(hasattr(resource, 'RLIMIT_FSIZE'), 'requires resource.RLIMIT_FSIZE') + def test_fsize_negative(self): + (cur, max) = resource.getrlimit(resource.RLIMIT_FSIZE) + for value in -2, -2**31, -2**32-1, -2**63, -2**64-1, -2**1000: + with self.subTest(value=value): + self.assertRaises(ValueError, resource.setrlimit, resource.RLIMIT_FSIZE, (value, max)) + self.assertRaises(ValueError, resource.setrlimit, resource.RLIMIT_FSIZE, (cur, value)) @unittest.skipUnless(hasattr(resource, "getrusage"), "needs getrusage") def test_getrusage(self): @@ -117,21 +161,18 @@ def test_getrusage(self): # Issue 6083: Reference counting bug @unittest.skipIf(sys.platform == "vxworks", "setting RLIMIT_CPU is not supported on VxWorks") + @unittest.skipUnless(hasattr(resource, 'RLIMIT_CPU'), 'requires resource.RLIMIT_CPU') def test_setrusage_refcount(self): - try: - limits = resource.getrlimit(resource.RLIMIT_CPU) - except AttributeError: - pass - else: - class BadSequence: - def __len__(self): - return 2 - def __getitem__(self, key): - if key in (0, 1): - return len(tuple(range(1000000))) - raise IndexError + limits = resource.getrlimit(resource.RLIMIT_CPU) + class BadSequence: + def __len__(self): + return 2 + def __getitem__(self, key): + if key in (0, 1): + return len(tuple(range(1000000))) + raise IndexError - resource.setrlimit(resource.RLIMIT_CPU, BadSequence()) + resource.setrlimit(resource.RLIMIT_CPU, BadSequence()) def test_pagesize(self): pagesize = resource.getpagesize() @@ -168,7 +209,8 @@ class BadSeq: def __len__(self): return 2 def __getitem__(self, key): - return limits[key] - 1 # new reference + lim = limits[key] + return lim - 1 if lim > 0 else lim + 0xFFFF_FFFF # new reference limits = resource.getrlimit(resource.RLIMIT_AS) self.assertEqual(resource.prlimit(0, resource.RLIMIT_AS, BadSeq()), diff --git a/Misc/NEWS.d/next/Library/2025-08-03-13-16-39.gh-issue-137044.0hPVL_.rst b/Misc/NEWS.d/next/Library/2025-08-03-13-16-39.gh-issue-137044.0hPVL_.rst new file mode 100644 index 00000000000000..f5f96263823e86 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2025-08-03-13-16-39.gh-issue-137044.0hPVL_.rst @@ -0,0 +1,4 @@ +Return large limit values as positive integers instead of negative integers +in :func:`resource.getrlimit`. Accept large values and reject negative +values (except :data:`~resource.RLIM_INFINITY`) for limits in +:func:`resource.setrlimit`. diff --git a/Modules/resource.c b/Modules/resource.c index 3fe18e7c98e3d8..2d63236f3eb709 100644 --- a/Modules/resource.c +++ b/Modules/resource.c @@ -1,9 +1,3 @@ -// Need limited C API version 3.13 for PySys_Audit() -#include "pyconfig.h" // Py_GIL_DISABLED -#ifndef Py_GIL_DISABLED -# define Py_LIMITED_API 0x030d0000 -#endif - #include "Python.h" #include // errno #include @@ -150,6 +144,35 @@ resource_getrusage_impl(PyObject *module, int who) } #endif +static int +py2rlim(PyObject *obj, rlim_t *out) +{ + obj = PyNumber_Index(obj); + if (obj == NULL) { + return -1; + } + int neg = PyLong_IsNegative(obj); + assert(neg >= 0); + Py_ssize_t bytes = PyLong_AsNativeBytes(obj, out, sizeof(*out), + Py_ASNATIVEBYTES_NATIVE_ENDIAN | + Py_ASNATIVEBYTES_UNSIGNED_BUFFER); + Py_DECREF(obj); + if (bytes < 0) { + return -1; + } + else if (neg && (*out != RLIM_INFINITY || bytes > (Py_ssize_t)sizeof(*out))) { + PyErr_SetString(PyExc_ValueError, + "Cannot convert negative int"); + return -1; + } + else if (bytes > (Py_ssize_t)sizeof(*out)) { + PyErr_SetString(PyExc_OverflowError, + "Python int too large to convert to C rlim_t"); + return -1; + } + return 0; +} + static int py2rlimit(PyObject *limits, struct rlimit *rl_out) { @@ -166,26 +189,13 @@ py2rlimit(PyObject *limits, struct rlimit *rl_out) } curobj = PyTuple_GetItem(limits, 0); // borrowed maxobj = PyTuple_GetItem(limits, 1); // borrowed -#if !defined(HAVE_LARGEFILE_SUPPORT) - rl_out->rlim_cur = PyLong_AsLong(curobj); - if (rl_out->rlim_cur == (rlim_t)-1 && PyErr_Occurred()) - goto error; - rl_out->rlim_max = PyLong_AsLong(maxobj); - if (rl_out->rlim_max == (rlim_t)-1 && PyErr_Occurred()) - goto error; -#else - /* The limits are probably bigger than a long */ - rl_out->rlim_cur = PyLong_AsLongLong(curobj); - if (rl_out->rlim_cur == (rlim_t)-1 && PyErr_Occurred()) - goto error; - rl_out->rlim_max = PyLong_AsLongLong(maxobj); - if (rl_out->rlim_max == (rlim_t)-1 && PyErr_Occurred()) + if (py2rlim(curobj, &rl_out->rlim_cur) < 0 || + py2rlim(maxobj, &rl_out->rlim_max) < 0) + { goto error; -#endif + } Py_DECREF(limits); - rl_out->rlim_cur = rl_out->rlim_cur & RLIM_INFINITY; - rl_out->rlim_max = rl_out->rlim_max & RLIM_INFINITY; return 0; error: @@ -193,15 +203,24 @@ py2rlimit(PyObject *limits, struct rlimit *rl_out) return -1; } +static PyObject* +rlim2py(rlim_t value) +{ + if (value == RLIM_INFINITY) { + return PyLong_FromNativeBytes(&value, sizeof(value), -1); + } + return PyLong_FromUnsignedNativeBytes(&value, sizeof(value), -1); +} + static PyObject* rlimit2py(struct rlimit rl) { - if (sizeof(rl.rlim_cur) > sizeof(long)) { - return Py_BuildValue("LL", - (long long) rl.rlim_cur, - (long long) rl.rlim_max); + PyObject *cur = rlim2py(rl.rlim_cur); + if (cur == NULL) { + return NULL; } - return Py_BuildValue("ll", (long) rl.rlim_cur, (long) rl.rlim_max); + PyObject *max = rlim2py(rl.rlim_max); + return Py_BuildValue("NN", cur, max); } /*[clinic input] @@ -495,14 +514,7 @@ resource_exec(PyObject *module) ADD_INT(module, RLIMIT_KQUEUES); #endif - PyObject *v; - if (sizeof(RLIM_INFINITY) > sizeof(long)) { - v = PyLong_FromLongLong((long long) RLIM_INFINITY); - } else - { - v = PyLong_FromLong((long) RLIM_INFINITY); - } - if (PyModule_Add(module, "RLIM_INFINITY", v) < 0) { + if (PyModule_Add(module, "RLIM_INFINITY", rlim2py(RLIM_INFINITY)) < 0) { return -1; } return 0; From 70a5e11704760e6966fdcfa2d81c7e1d24c0b339 Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Sun, 3 Aug 2025 13:59:06 +0300 Subject: [PATCH 2/8] Regenerate clinic files. --- Modules/clinic/resource.c.h | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/Modules/clinic/resource.c.h b/Modules/clinic/resource.c.h index 9eda7de27532a1..e4ef93900d1797 100644 --- a/Modules/clinic/resource.c.h +++ b/Modules/clinic/resource.c.h @@ -2,6 +2,8 @@ preserve [clinic start generated code]*/ +#include "pycore_modsupport.h" // _PyArg_CheckPositional() + #if defined(HAVE_GETRUSAGE) PyDoc_STRVAR(resource_getrusage__doc__, @@ -66,7 +68,7 @@ PyDoc_STRVAR(resource_setrlimit__doc__, "\n"); #define RESOURCE_SETRLIMIT_METHODDEF \ - {"setrlimit", (PyCFunction)(void(*)(void))resource_setrlimit, METH_FASTCALL, resource_setrlimit__doc__}, + {"setrlimit", _PyCFunction_CAST(resource_setrlimit), METH_FASTCALL, resource_setrlimit__doc__}, static PyObject * resource_setrlimit_impl(PyObject *module, int resource, PyObject *limits); @@ -78,8 +80,7 @@ resource_setrlimit(PyObject *module, PyObject *const *args, Py_ssize_t nargs) int resource; PyObject *limits; - if (nargs != 2) { - PyErr_Format(PyExc_TypeError, "setrlimit expected 2 arguments, got %zd", nargs); + if (!_PyArg_CheckPositional("setrlimit", nargs, 2, 2)) { goto exit; } resource = PyLong_AsInt(args[0]); @@ -101,7 +102,7 @@ PyDoc_STRVAR(resource_prlimit__doc__, "\n"); #define RESOURCE_PRLIMIT_METHODDEF \ - {"prlimit", (PyCFunction)(void(*)(void))resource_prlimit, METH_FASTCALL, resource_prlimit__doc__}, + {"prlimit", _PyCFunction_CAST(resource_prlimit), METH_FASTCALL, resource_prlimit__doc__}, static PyObject * resource_prlimit_impl(PyObject *module, pid_t pid, int resource, @@ -115,12 +116,7 @@ resource_prlimit(PyObject *module, PyObject *const *args, Py_ssize_t nargs) int resource; PyObject *limits = Py_None; - if (nargs < 2) { - PyErr_Format(PyExc_TypeError, "prlimit expected at least 2 arguments, got %zd", nargs); - goto exit; - } - if (nargs > 3) { - PyErr_Format(PyExc_TypeError, "prlimit expected at most 3 arguments, got %zd", nargs); + if (!_PyArg_CheckPositional("prlimit", nargs, 2, 3)) { goto exit; } pid = PyLong_AsPid(args[0]); @@ -178,4 +174,4 @@ resource_getpagesize(PyObject *module, PyObject *Py_UNUSED(ignored)) #ifndef RESOURCE_PRLIMIT_METHODDEF #define RESOURCE_PRLIMIT_METHODDEF #endif /* !defined(RESOURCE_PRLIMIT_METHODDEF) */ -/*[clinic end generated code: output=e45883ace510414a input=a9049054013a1b77]*/ +/*[clinic end generated code: output=8e905b2f5c35170e input=a9049054013a1b77]*/ From 61592f43df19ce17840620e53c1a2e2735d02df1 Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Sun, 3 Aug 2025 13:59:52 +0300 Subject: [PATCH 3/8] Fix tests on macOS. --- Lib/test/test_resource.py | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/Lib/test/test_resource.py b/Lib/test/test_resource.py index 517c501f7ffc23..ec0410c4e54699 100644 --- a/Lib/test/test_resource.py +++ b/Lib/test/test_resource.py @@ -127,10 +127,15 @@ def test_fsize_not_too_big(self): self.assertEqual(resource.getrlimit(resource.RLIMIT_FSIZE), (2**32, max)) resource.setrlimit(resource.RLIMIT_FSIZE, (2**63-1, max)) self.assertEqual(resource.getrlimit(resource.RLIMIT_FSIZE), (2**63-1, max)) - resource.setrlimit(resource.RLIMIT_FSIZE, (2**63, max)) - self.assertEqual(resource.getrlimit(resource.RLIMIT_FSIZE), (2**63, max)) - resource.setrlimit(resource.RLIMIT_FSIZE, (2**64-2, max)) - self.assertEqual(resource.getrlimit(resource.RLIMIT_FSIZE), (2**64-2, max)) + try: + resource.setrlimit(resource.RLIMIT_FSIZE, (2**63, max)) + except ValueError: + # There is a hard limit on macOS. + pass + else: + self.assertEqual(resource.getrlimit(resource.RLIMIT_FSIZE), (2**63, max)) + resource.setrlimit(resource.RLIMIT_FSIZE, (2**64-2, max)) + self.assertEqual(resource.getrlimit(resource.RLIMIT_FSIZE), (2**64-2, max)) @unittest.skipIf(sys.platform == "vxworks", "setting RLIMIT_FSIZE is not supported on VxWorks") From 4c0bf2c98c4efca947bb3f9de2c4596144f16453 Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Sun, 3 Aug 2025 14:04:07 +0300 Subject: [PATCH 4/8] Fix build on macOS. --- Modules/resource.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Modules/resource.c b/Modules/resource.c index 2d63236f3eb709..2353bc6653abd8 100644 --- a/Modules/resource.c +++ b/Modules/resource.c @@ -1,3 +1,7 @@ +#ifndef Py_BUILD_CORE_BUILTIN +# define Py_BUILD_CORE_MODULE 1 +#endif + #include "Python.h" #include // errno #include From 7c1fea77085ec586bf3f168fdc750b5ac1f8552b Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Sun, 3 Aug 2025 16:47:08 +0300 Subject: [PATCH 5/8] Fix tests on ASAN build. --- Lib/test/test_resource.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Lib/test/test_resource.py b/Lib/test/test_resource.py index ec0410c4e54699..36c4581954308f 100644 --- a/Lib/test/test_resource.py +++ b/Lib/test/test_resource.py @@ -215,7 +215,7 @@ def __len__(self): return 2 def __getitem__(self, key): lim = limits[key] - return lim - 1 if lim > 0 else lim + 0xFFFF_FFFF # new reference + return lim - 1 if lim > 0 else lim + sys.maxsize*2 # new reference limits = resource.getrlimit(resource.RLIMIT_AS) self.assertEqual(resource.prlimit(0, resource.RLIMIT_AS, BadSeq()), From a55413670d6ae9315459ffc860aea7eddc0ac562 Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Wed, 6 Aug 2025 20:45:58 +0300 Subject: [PATCH 6/8] Fix tests on FreeBSD and OpenIndiana. --- Lib/test/test_resource.py | 40 +++++++++++++++++++++++++-------------- 1 file changed, 26 insertions(+), 14 deletions(-) diff --git a/Lib/test/test_resource.py b/Lib/test/test_resource.py index 36c4581954308f..f6c0cf46acd90f 100644 --- a/Lib/test/test_resource.py +++ b/Lib/test/test_resource.py @@ -112,37 +112,49 @@ def test_fsize_not_too_big(self): (cur, max) = resource.getrlimit(resource.RLIMIT_FSIZE) self.addCleanup(resource.setrlimit, resource.RLIMIT_FSIZE, (cur, max)) - resource.setrlimit(resource.RLIMIT_FSIZE, (2**31-1, max)) - self.assertEqual(resource.getrlimit(resource.RLIMIT_FSIZE), (2**31-1, max)) - resource.setrlimit(resource.RLIMIT_FSIZE, (2**31, max)) - self.assertEqual(resource.getrlimit(resource.RLIMIT_FSIZE), (2**31, max)) - resource.setrlimit(resource.RLIMIT_FSIZE, (2**32-2, max)) - self.assertEqual(resource.getrlimit(resource.RLIMIT_FSIZE), (2**32-2, max)) + def expected(cur): + if resource.RLIM_INFINITY < 0: + return [(cur, max), (resource.RLIM_INFINITY, max)] + elif resource.RLIM_INFINITY < cur: + return [(resource.RLIM_INFINITY, max)] + else: + return [(cur, max)] + + resource.setrlimit(resource.RLIMIT_FSIZE, (2**31-5, max)) + self.assertEqual(resource.getrlimit(resource.RLIMIT_FSIZE), (2**31-5, max)) try: resource.setrlimit(resource.RLIMIT_FSIZE, (2**32, max)) except OverflowError: - pass + resource.setrlimit(resource.RLIMIT_FSIZE, (2**31, max)) + self.assertIn(resource.getrlimit(resource.RLIMIT_FSIZE), expected(2**31)) + resource.setrlimit(resource.RLIMIT_FSIZE, (2**32-5, max)) + self.assertIn(resource.getrlimit(resource.RLIMIT_FSIZE), expected(2**32-5)) else: - self.assertEqual(resource.getrlimit(resource.RLIMIT_FSIZE), (2**32, max)) - resource.setrlimit(resource.RLIMIT_FSIZE, (2**63-1, max)) - self.assertEqual(resource.getrlimit(resource.RLIMIT_FSIZE), (2**63-1, max)) + self.assertIn(resource.getrlimit(resource.RLIMIT_FSIZE), expected(2**32)) + resource.setrlimit(resource.RLIMIT_FSIZE, (2**31, max)) + self.assertEqual(resource.getrlimit(resource.RLIMIT_FSIZE), (2**31, max)) + resource.setrlimit(resource.RLIMIT_FSIZE, (2**32-5, max)) + self.assertEqual(resource.getrlimit(resource.RLIMIT_FSIZE), (2**32-5, max)) + + resource.setrlimit(resource.RLIMIT_FSIZE, (2**63-5, max)) + self.assertEqual(resource.getrlimit(resource.RLIMIT_FSIZE), (2**63-5, max)) try: resource.setrlimit(resource.RLIMIT_FSIZE, (2**63, max)) except ValueError: # There is a hard limit on macOS. pass else: - self.assertEqual(resource.getrlimit(resource.RLIMIT_FSIZE), (2**63, max)) - resource.setrlimit(resource.RLIMIT_FSIZE, (2**64-2, max)) - self.assertEqual(resource.getrlimit(resource.RLIMIT_FSIZE), (2**64-2, max)) + self.assertIn(resource.getrlimit(resource.RLIMIT_FSIZE), expected(2**63)) + resource.setrlimit(resource.RLIMIT_FSIZE, (2**64-5, max)) + self.assertIn(resource.getrlimit(resource.RLIMIT_FSIZE), expected(2**64-5)) @unittest.skipIf(sys.platform == "vxworks", "setting RLIMIT_FSIZE is not supported on VxWorks") @unittest.skipUnless(hasattr(resource, 'RLIMIT_FSIZE'), 'requires resource.RLIMIT_FSIZE') def test_fsize_negative(self): (cur, max) = resource.getrlimit(resource.RLIMIT_FSIZE) - for value in -2, -2**31, -2**32-1, -2**63, -2**64-1, -2**1000: + for value in -5, -2**31, -2**32-5, -2**63, -2**64-5, -2**1000: with self.subTest(value=value): self.assertRaises(ValueError, resource.setrlimit, resource.RLIMIT_FSIZE, (value, max)) self.assertRaises(ValueError, resource.setrlimit, resource.RLIMIT_FSIZE, (cur, value)) From 4774421542281691dc6f769e7f3cfd90aa5a16ca Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Wed, 6 Aug 2025 20:47:06 +0300 Subject: [PATCH 7/8] Update Lib/test/test_resource.py Co-authored-by: Petr Viktorin --- Lib/test/test_resource.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Lib/test/test_resource.py b/Lib/test/test_resource.py index f6c0cf46acd90f..70f6763f78388d 100644 --- a/Lib/test/test_resource.py +++ b/Lib/test/test_resource.py @@ -156,6 +156,10 @@ def test_fsize_negative(self): (cur, max) = resource.getrlimit(resource.RLIMIT_FSIZE) for value in -5, -2**31, -2**32-5, -2**63, -2**64-5, -2**1000: with self.subTest(value=value): + # This test assumes that the values don't map to RLIM_INFINITY, + # though Posix doesn't guarantee it. + self.assertNotEqual(value, resource.RLIM_INFINITY) + self.assertRaises(ValueError, resource.setrlimit, resource.RLIMIT_FSIZE, (value, max)) self.assertRaises(ValueError, resource.setrlimit, resource.RLIMIT_FSIZE, (cur, value)) From 244687008f17a28fa459d7e1b455fca0f840c385 Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Thu, 7 Aug 2025 00:45:29 +0300 Subject: [PATCH 8/8] Try to fix tests on 32-bit Linux. --- Lib/test/test_resource.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Lib/test/test_resource.py b/Lib/test/test_resource.py index 70f6763f78388d..fe05224828bd27 100644 --- a/Lib/test/test_resource.py +++ b/Lib/test/test_resource.py @@ -138,7 +138,7 @@ def expected(cur): self.assertEqual(resource.getrlimit(resource.RLIMIT_FSIZE), (2**32-5, max)) resource.setrlimit(resource.RLIMIT_FSIZE, (2**63-5, max)) - self.assertEqual(resource.getrlimit(resource.RLIMIT_FSIZE), (2**63-5, max)) + self.assertIn(resource.getrlimit(resource.RLIMIT_FSIZE), expected(2**63-5)) try: resource.setrlimit(resource.RLIMIT_FSIZE, (2**63, max)) except ValueError: pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy