https://github.com/python/cpython/commit/85318d6557c666b3947b03cad893a18db500a4c1
commit: 85318d6557c666b3947b03cad893a18db500a4c1
branch: 3.14
author: Miss Islington (bot) <[email protected]>
committer: vstinner <[email protected]>
date: 2026-10-28T07:40:23Z
summary:

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

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 9ac0badc6606c1..1dc80724817af5 100644
--- a/Lib/socket.py
+++ b/Lib/socket.py
@@ -552,7 +552,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 4b29273b7a240a..3d7be767a8bb29 100644
--- a/Lib/test/test_socket.py
+++ b/Lib/test/test_socket.py
@@ -3090,6 +3090,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