https://github.com/python/cpython/commit/6c695bfad45ddde73d0d674286800fbe295f0627
commit: 6c695bfad45ddde73d0d674286800fbe295f0627
branch: main
author: scrieve <[email protected]>
committer: vstinner <[email protected]>
date: 2026-10-27T22:56:42Z
summary:

gh-160561: Close the duplicated descriptor when socket.fromfd() fails (#160579)

Co-authored-by: wlkr73 <[email protected]>
Co-authored-by: lumenyr <[email protected]>
Co-authored-by: Victor Stinner <[email protected]>

files:
A Misc/NEWS.d/next/Library/2026-10-24-07-58-00.gh-issue-160561.b3Kq1z.rst
M Lib/socket.py
M Lib/test/test_socket.py

diff --git a/Lib/socket.py b/Lib/socket.py
index 21a852155abb3b3..df99cc04ca85546 100644
--- a/Lib/socket.py
+++ b/Lib/socket.py
@@ -572,7 +572,11 @@ def fromfd(fd, family, type, proto=0):
     descriptor.  The remaining arguments are the same as for socket().
     """
     nfd = dup(fd)
-    return socket(family, type, proto, nfd)
+    try:
+        return socket(family, type, proto, nfd)
+    except:
+        close(nfd)
+        raise
 
 if hasattr(_socket.socket, "sendmsg"):
     def send_fds(sock, buffers, fds, flags=0, address=None):
diff --git a/Lib/test/test_socket.py b/Lib/test/test_socket.py
index e4b3d848923f8c9..51b666bbaba8271 100644
--- a/Lib/test/test_socket.py
+++ b/Lib/test/test_socket.py
@@ -3195,6 +3195,23 @@ def testFromFd(self):
     def _testFromFd(self):
         self.serv_conn.send(MSG)
 
+    def testFromFdError(self):
+        # Make sure that the fromfd() duplicated socket is closed on error.
+        fd = self.cli_conn.fileno()
+        fd_count_before = os_helper.fd_count()
+
+        with self.assertRaises(TypeError):
+            socket.fromfd(fd, "not-a-valid-family", socket.SOCK_STREAM)
+        with self.assertRaises(TypeError):
+            socket.fromfd(fd, socket.AF_INET, "not-a-valid-type")
+        with self.assertRaises(OverflowError):
+            socket.fromfd(fd, socket.AF_INET, 1 << 100)
+
+        self.assertEqual(os_helper.fd_count(), fd_count_before)
+
+    def _testFromFdError(self):
+        pass
+
     def testDup(self):
         # Testing dup()
         sock = self.cli_conn.dup()
diff --git 
a/Misc/NEWS.d/next/Library/2026-10-24-07-58-00.gh-issue-160561.b3Kq1z.rst 
b/Misc/NEWS.d/next/Library/2026-10-24-07-58-00.gh-issue-160561.b3Kq1z.rst
new file mode 100644
index 000000000000000..c49cd6a83e90bf4
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2026-10-24-07-58-00.gh-issue-160561.b3Kq1z.rst
@@ -0,0 +1 @@
+Fix a descriptor leak in :func:`socket.fromfd` when the socket constructor 
rejects its arguments. The duplicated descriptor was never closed.

_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3//lists/python-checkins.python.org
Member address: [email protected]

Reply via email to