]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
[3.14] gh-145335: Fix crash when passing -1 as fd in os.pathconf (GH-145390) (#145433)
authorMiss Islington (bot) <31488909+miss-islington@users.noreply.github.com>
Mon, 2 Mar 2026 18:33:47 +0000 (19:33 +0100)
committerGitHub <noreply@github.com>
Mon, 2 Mar 2026 18:33:47 +0000 (18:33 +0000)
gh-145335: Fix crash when passing -1 as fd in os.pathconf (GH-145390)
(cherry picked from commit 5c3a47b94a39f87c36b1f36704d80775802ad034)

Co-authored-by: AN Long <aisk@users.noreply.github.com>
Co-authored-by: blurb-it[bot] <43283697+blurb-it[bot]@users.noreply.github.com>
Lib/test/test_os.py
Misc/NEWS.d/next/Core_and_Builtins/2026-03-01-13-37-31.gh-issue-145335.e36kPJ.rst [new file with mode: 0644]
Modules/posixmodule.c

index 7a28e7b4598c16cb9afad99650af8282f3597a5f..555c85f4857c2d7e69dda2f390847c7f02123cb5 100644 (file)
@@ -2607,6 +2607,16 @@ class TestInvalidFD(unittest.TestCase):
         self.check(os.pathconf, "PC_NAME_MAX")
         self.check(os.fpathconf, "PC_NAME_MAX")
 
+    @unittest.skipUnless(hasattr(os, 'pathconf'), 'test needs os.pathconf()')
+    @unittest.skipIf(
+        support.linked_to_musl(),
+        'musl fpathconf ignores the file descriptor and returns a constant',
+        )
+    def test_pathconf_negative_fd_uses_fd_semantics(self):
+        with self.assertRaises(OSError) as ctx:
+            os.pathconf(-1, 1)
+        self.assertEqual(ctx.exception.errno, errno.EBADF)
+
     @unittest.skipUnless(hasattr(os, 'ftruncate'), 'test needs os.ftruncate()')
     def test_ftruncate(self):
         self.check(os.truncate, 0)
diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-03-01-13-37-31.gh-issue-145335.e36kPJ.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-03-01-13-37-31.gh-issue-145335.e36kPJ.rst
new file mode 100644 (file)
index 0000000..42ed85c
--- /dev/null
@@ -0,0 +1,2 @@
+Fix a crash in :func:`os.pathconf` when called with ``-1`` as the path\r
+argument.
index cb4fe1e6c8ca03ba56cc7509000120006be4750f..bb9ef0e6da6c77da48ba38639aaf3d529b80f28d 100644 (file)
@@ -1251,6 +1251,8 @@ get_posix_state(PyObject *module)
  *     Contains a file descriptor if path.accept_fd was true
  *     and the caller provided a signed integer instead of any
  *     sort of string.
+ *   path.is_fd
+ *     True if path was provided as a file descriptor.
  *
  *     WARNING: if your "path" parameter is optional, and is
  *     unspecified, path_converter will never get called.
@@ -1303,6 +1305,7 @@ typedef struct {
     const wchar_t *wide;
     const char *narrow;
     int fd;
+    bool is_fd;
     int value_error;
     Py_ssize_t length;
     PyObject *object;
@@ -1312,7 +1315,7 @@ typedef struct {
 #define PATH_T_INITIALIZE(function_name, argument_name, nullable, nonstrict, \
                           make_wide, suppress_value_error, allow_fd) \
     {function_name, argument_name, nullable, nonstrict, make_wide, \
-     suppress_value_error, allow_fd, NULL, NULL, -1, 0, 0, NULL, NULL}
+     suppress_value_error, allow_fd, NULL, NULL, -1, false, 0, 0, NULL, NULL}
 #ifdef MS_WINDOWS
 #define PATH_T_INITIALIZE_P(function_name, argument_name, nullable, \
                             nonstrict, suppress_value_error, allow_fd) \
@@ -1446,6 +1449,7 @@ path_converter(PyObject *o, void *p)
         }
         path->wide = NULL;
         path->narrow = NULL;
+        path->is_fd = true;
         goto success_exit;
     }
     else {
@@ -13841,8 +13845,9 @@ os_pathconf_impl(PyObject *module, path_t *path, int name)
 
     errno = 0;
 #ifdef HAVE_FPATHCONF
-    if (path->fd != -1)
+    if (path->is_fd) {
         limit = fpathconf(path->fd, name);
+    }
     else
 #endif
         limit = pathconf(path->narrow, name);