From b57b98dcd39f9aff03096ff2b94e6bdeb455bc15 Mon Sep 17 00:00:00 2001 From: Christoph Walcher Date: Tue, 2 Sep 2025 22:18:03 +0200 Subject: [PATCH 1/3] gh-138401: Check arg `count>=0` in `os.sendfile` --- Lib/test/test_os.py | 5 +++++ ...5-09-02-22-17-55.gh-issue-138401.uTRvue.rst | 2 ++ Modules/clinic/posixmodule.c.h | 12 +++++++++++- Modules/posixmodule.c | 18 ++++++++++++++---- 4 files changed, 32 insertions(+), 5 deletions(-) create mode 100644 Misc/NEWS.d/next/Core_and_Builtins/2025-09-02-22-17-55.gh-issue-138401.uTRvue.rst diff --git a/Lib/test/test_os.py b/Lib/test/test_os.py index 9827a7f12ea21d..33c3e1dc52bf50 100644 --- a/Lib/test/test_os.py +++ b/Lib/test/test_os.py @@ -3957,6 +3957,11 @@ async def test_invalid_offset(self): await self.async_sendfile(self.sockno, self.fileno, -1, 4096) self.assertEqual(cm.exception.errno, errno.EINVAL) + async def test_invalid_count(self): + with self.assertRaises(ValueError): + await self.sendfile_wrapper(self.sockno, self.fileno, offset=0, + count=-1) + async def test_keywords(self): # Keyword arguments should be supported await self.async_sendfile(out_fd=self.sockno, in_fd=self.fileno, diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2025-09-02-22-17-55.gh-issue-138401.uTRvue.rst b/Misc/NEWS.d/next/Core_and_Builtins/2025-09-02-22-17-55.gh-issue-138401.uTRvue.rst new file mode 100644 index 00000000000000..be257d23691c84 --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2025-09-02-22-17-55.gh-issue-138401.uTRvue.rst @@ -0,0 +1,2 @@ +Add missing validation of argument ``count`` in ``os.sendfile`` to be +non-negative. diff --git a/Modules/clinic/posixmodule.c.h b/Modules/clinic/posixmodule.c.h index 455c938afc75f0..45e7c0d6451c15 100644 --- a/Modules/clinic/posixmodule.c.h +++ b/Modules/clinic/posixmodule.c.h @@ -8100,6 +8100,11 @@ os_sendfile(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject goto exit; } count = ival; + if (count < 0) { + PyErr_SetString(PyExc_ValueError, + "count cannot be negative"); + goto exit; + } } if (!noptargs) { goto skip_optional_pos; @@ -8206,6 +8211,11 @@ os_sendfile(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject goto exit; } count = ival; + if (count < 0) { + PyErr_SetString(PyExc_ValueError, + "count cannot be negative"); + goto exit; + } } return_value = os_sendfile_impl(module, out_fd, in_fd, offobj, count); @@ -13434,4 +13444,4 @@ os__emscripten_log(PyObject *module, PyObject *const *args, Py_ssize_t nargs, Py #ifndef OS__EMSCRIPTEN_LOG_METHODDEF #define OS__EMSCRIPTEN_LOG_METHODDEF #endif /* !defined(OS__EMSCRIPTEN_LOG_METHODDEF) */ -/*[clinic end generated code: output=77c20b53c34ccae4 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=92662828d49f5d88 input=a9049054013a1b77]*/ diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c index f7e721e52e11b0..53b21e99376485 100644 --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -11874,7 +11874,7 @@ os.sendfile out_fd: int in_fd: int offset: Py_off_t - count: Py_ssize_t + count: Py_ssize_t(allow_negative=False) headers: object(c_default="NULL") = () trailers: object(c_default="NULL") = () flags: int = 0 @@ -11886,7 +11886,7 @@ static PyObject * os_sendfile_impl(PyObject *module, int out_fd, int in_fd, Py_off_t offset, Py_ssize_t count, PyObject *headers, PyObject *trailers, int flags) -/*[clinic end generated code: output=329ea009bdd55afc input=338adb8ff84ae8cd]*/ +/*[clinic end generated code: output=329ea009bdd55afc input=dcb026b94effa922]*/ #else /*[clinic input] os.sendfile @@ -11894,7 +11894,7 @@ os.sendfile out_fd: int in_fd: int offset as offobj: object - count: Py_ssize_t + count: Py_ssize_t(allow_negative=False) Copy count bytes from file descriptor in_fd to file descriptor out_fd. [clinic start generated code]*/ @@ -11902,12 +11902,22 @@ Copy count bytes from file descriptor in_fd to file descriptor out_fd. static PyObject * os_sendfile_impl(PyObject *module, int out_fd, int in_fd, PyObject *offobj, Py_ssize_t count) -/*[clinic end generated code: output=ae81216e40f167d8 input=76d64058c74477ba]*/ +/*[clinic end generated code: output=ae81216e40f167d8 input=424df0949059ea5b]*/ #endif { Py_ssize_t ret; int async_err = 0; +#ifdef __APPLE__ + if(sbytes < 0) { + PyErr_SetString(PyExc_ValueError, + "count cannot be negative"); + return NULL; + } +#else + assert(count >= 0); +#endif + #if defined(__FreeBSD__) || defined(__DragonFly__) || defined(__APPLE__) #ifndef __APPLE__ off_t sbytes; From 09b5a9035fea8953d31aa8671a2b95aeb8b815b2 Mon Sep 17 00:00:00 2001 From: Christoph Walcher Date: Thu, 4 Sep 2025 18:54:20 +0200 Subject: [PATCH 2/3] assert error msg in test --- Lib/test/test_os.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Lib/test/test_os.py b/Lib/test/test_os.py index 33c3e1dc52bf50..b476b431ad6f96 100644 --- a/Lib/test/test_os.py +++ b/Lib/test/test_os.py @@ -3958,7 +3958,7 @@ async def test_invalid_offset(self): self.assertEqual(cm.exception.errno, errno.EINVAL) async def test_invalid_count(self): - with self.assertRaises(ValueError): + with self.assertRaises(ValueError, msg="count cannot be negative"): await self.sendfile_wrapper(self.sockno, self.fileno, offset=0, count=-1) From 49597941c608bb4a86d3f3c8bb63d2bb88362ab1 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Fri, 5 Sep 2025 10:50:46 +0200 Subject: [PATCH 3/3] Update Misc/NEWS.d/next/Core_and_Builtins/2025-09-02-22-17-55.gh-issue-138401.uTRvue.rst Co-authored-by: Kumar Aditya --- .../2025-09-02-22-17-55.gh-issue-138401.uTRvue.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2025-09-02-22-17-55.gh-issue-138401.uTRvue.rst b/Misc/NEWS.d/next/Core_and_Builtins/2025-09-02-22-17-55.gh-issue-138401.uTRvue.rst index be257d23691c84..90496c05c56e13 100644 --- a/Misc/NEWS.d/next/Core_and_Builtins/2025-09-02-22-17-55.gh-issue-138401.uTRvue.rst +++ b/Misc/NEWS.d/next/Core_and_Builtins/2025-09-02-22-17-55.gh-issue-138401.uTRvue.rst @@ -1,2 +1,2 @@ -Add missing validation of argument ``count`` in ``os.sendfile`` to be +Add missing validation of argument ``count`` in :func:`os.sendfile` to be non-negative.