]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-138401: Check arg count>=0 in os.sendfile() (#138403)
authorChristoph Walcher <christoph-wa@gmx.de>
Fri, 5 Sep 2025 09:16:55 +0000 (11:16 +0200)
committerGitHub <noreply@github.com>
Fri, 5 Sep 2025 09:16:55 +0000 (09:16 +0000)
Co-authored-by: Victor Stinner <vstinner@python.org>
Co-authored-by: Kumar Aditya <kumaraditya@python.org>
Lib/test/test_os.py
Misc/NEWS.d/next/Core_and_Builtins/2025-09-02-22-17-55.gh-issue-138401.uTRvue.rst [new file with mode: 0644]
Modules/clinic/posixmodule.c.h
Modules/posixmodule.c

index 9827a7f12ea21d63f7c33868ad521aafced1993a..b476b431ad6f9639209ceb316da863b223a1b5f6 100644 (file)
@@ -3957,6 +3957,11 @@ class TestSendfile(unittest.IsolatedAsyncioTestCase):
             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, msg="count cannot be negative"):
+            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 (file)
index 0000000..90496c0
--- /dev/null
@@ -0,0 +1,2 @@
+Add missing validation of argument ``count`` in :func:`os.sendfile` to be
+non-negative.
index 455c938afc75f0800164fabfc1120c84cf68b22b..45e7c0d6451c15971c5d27abc9fd3464ae1abcad 100644 (file)
@@ -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 @@ exit:
 #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]*/
index f7e721e52e11b034209142ad67e7b52a8aab1451..53b21e99376485d31ca684c6cc08704474a8d0ff 100644 (file)
@@ -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;