https://github.com/python/cpython/commit/9070cd5386e0478d680f3d2f18b9077303ce15df
commit: 9070cd5386e0478d680f3d2f18b9077303ce15df
branch: 3.15
author: Miss Islington (bot) <[email protected]>
committer: vstinner <[email protected]>
date: 2026-10-28T07:39:45Z
summary:

[3.15] gh-160561: Close the duplicated descriptor when socket.fromfd() fails 
(GH-160579) (#160785)

gh-160561: Close the duplicated descriptor when socket.fromfd() fails 
(GH-160579)
(cherry picked from commit 6c695bfad45ddde73d0d674286800fbe295f0627)

Co-authored-by: scrieve <[email protected]>
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 2a4f875f76b069..6de403d393f8d5 100644
--- a/Lib/socket.py
+++ b/Lib/socket.py
@@ -561,7 +561,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 100b71074bf35e..5609244b2b7976 100644
--- a/Lib/test/test_socket.py
+++ b/Lib/test/test_socket.py
@@ -3175,6 +3175,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 00000000000000..c49cd6a83e90bf
--- /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