Skip to content

Commit 4c414fe

Browse files
committed
Detect infinite redirection loops in URLFetcher
Fix #2686.
1 parent ebcbb92 commit 4c414fe

File tree

2 files changed

+13
-1
lines changed

2 files changed

+13
-1
lines changed

tests/test_api.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,8 @@ def http_server():
139139
(b'<html test=accept-encoding-header-fail>', {})
140140
),
141141
'/redirect': lambda env: (b'', {'Location': '/gzip'}),
142+
'/redirect-loop': lambda env: (b'', {'Location': '/redirect-loop-2'}),
143+
'/redirect-loop-2': lambda env: (b'', {'Location': '/redirect-loop'}),
142144
}
143145

144146
def wsgi_app(environ, start_response):
@@ -729,6 +731,13 @@ def test_disallowed_protocols(command):
729731
assert 'URI uses disallowed protocol' in logs[0]
730732

731733

734+
@assert_no_logs
735+
def test_redirect_loop():
736+
with http_server() as root_url:
737+
with pytest.raises(URLFetchingError, match='infinite loop'):
738+
_run(f'{root_url}/redirect-loop -')
739+
740+
732741
@pytest.mark.parametrize(('html', 'fields'), [
733742
('<input>', ['/Tx', '/V ()']),
734743
('<input value="">', ['/Tx', '/V ()']),

weasyprint/urls.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -312,6 +312,7 @@ def __init__(self, timeout=10, ssl_context=None, http_headers=None,
312312
self._http_headers = {**HTTP_HEADERS, **(http_headers or {})}
313313
self._allowed_protocols = allowed_protocols
314314
self._fail_on_errors = fail_on_errors
315+
self._request = None
315316

316317
def fetch(self, url, headers=None):
317318
"""Fetch a given URL.
@@ -342,7 +343,8 @@ def fetch(self, url, headers=None):
342343

343344
# Open URL.
344345
headers = {**self._http_headers, **(headers or {})}
345-
http_request = request.Request(url, headers=headers)
346+
http_request = self._request or request.Request(url, headers=headers)
347+
self._request = None
346348
response = super().open(http_request, timeout=self._timeout)
347349

348350
# Decompress response.
@@ -364,6 +366,7 @@ def fetch(self, url, headers=None):
364366

365367
def open(self, url, data=None, timeout=None):
366368
if isinstance(url, request.Request):
369+
self._request = url
367370
return self.fetch(url.full_url, url.headers)
368371
return self.fetch(url)
369372

0 commit comments

Comments
 (0)