From fc78d00e916b0f4e9c9d5efeb78d00bff97320af Mon Sep 17 00:00:00 2001 From: barneygale Date: Mon, 14 Apr 2025 18:18:39 +0100 Subject: [PATCH 1/3] GH-123599: Match `file:` URL hostname against machine hostname in urllib In `_is_local_authority()`, return early if the authority matches the machine hostname from `socket.gethostname()`, rather than resolving the names and matching IP addresses. --- Lib/urllib/request.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/Lib/urllib/request.py b/Lib/urllib/request.py index 2c9c7b6ca5394d..a9127bf775931a 100644 --- a/Lib/urllib/request.py +++ b/Lib/urllib/request.py @@ -1485,6 +1485,13 @@ def open_local_file(self, req): def _is_local_authority(authority): if not authority or authority == 'localhost': return True + try: + hostname = socket.gethostname() + except socket.gaierror: + pass + else: + if authority == hostname: + return True try: address = socket.gethostbyname(authority) except (socket.gaierror, AttributeError): From d3f25559c93f7b14f301d2a3b19764b8296d798b Mon Sep 17 00:00:00 2001 From: barneygale Date: Mon, 14 Apr 2025 18:55:59 +0100 Subject: [PATCH 2/3] Fix WASI --- Lib/urllib/request.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Lib/urllib/request.py b/Lib/urllib/request.py index a9127bf775931a..d42a3d774c7256 100644 --- a/Lib/urllib/request.py +++ b/Lib/urllib/request.py @@ -1487,7 +1487,7 @@ def _is_local_authority(authority): return True try: hostname = socket.gethostname() - except socket.gaierror: + except (socket.gaierror, AttributeError): pass else: if authority == hostname: From 17b4814bb3abed1b7de0abccc5e8f2e683ce0077 Mon Sep 17 00:00:00 2001 From: barneygale Date: Mon, 14 Apr 2025 19:06:53 +0100 Subject: [PATCH 3/3] Tweak versionchanged content, add comments --- Doc/library/urllib.request.rst | 6 +++--- Lib/urllib/request.py | 2 ++ 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/Doc/library/urllib.request.rst b/Doc/library/urllib.request.rst index a5f1b9b292a85a..b7c0c7d5099806 100644 --- a/Doc/library/urllib.request.rst +++ b/Doc/library/urllib.request.rst @@ -199,9 +199,9 @@ The :mod:`urllib.request` module defines the following functions: .. versionchanged:: next This function calls :func:`socket.gethostbyname` if the URL authority - isn't empty or ``localhost``. If the authority resolves to a local IP - address then it is discarded; otherwise, on Windows a UNC path is - returned (as before), and on other platforms a + isn't empty, ``localhost``, or the machine hostname. If the authority + resolves to a local IP address then it is discarded; otherwise, on + Windows a UNC path is returned (as before), and on other platforms a :exc:`~urllib.error.URLError` is raised. .. versionchanged:: next diff --git a/Lib/urllib/request.py b/Lib/urllib/request.py index d42a3d774c7256..9a6b29a90a2968 100644 --- a/Lib/urllib/request.py +++ b/Lib/urllib/request.py @@ -1483,6 +1483,7 @@ def open_local_file(self, req): file_open = open_local_file def _is_local_authority(authority): + # Compare hostnames if not authority or authority == 'localhost': return True try: @@ -1492,6 +1493,7 @@ def _is_local_authority(authority): else: if authority == hostname: return True + # Compare IP addresses try: address = socket.gethostbyname(authority) except (socket.gaierror, AttributeError):