File CVE-2023-45803.patch of Package python-urllib3.34894

Index: urllib3-1.25.10/dummyserver/handlers.py
===================================================================
--- urllib3-1.25.10.orig/dummyserver/handlers.py
+++ urllib3-1.25.10/dummyserver/handlers.py
@@ -29,7 +29,10 @@ class Response(object):
         self.headers = headers or [("Content-type", "text/plain")]
 
     def __call__(self, request_handler):
-        status, reason = self.status.split(" ", 1)
+        if hasattr(self.status, "decode"):
+            status, reason = self.status.decode().split(" ", 1)
+        else:
+            status, reason = self.status.split(" ", 1)
         request_handler.set_status(int(status), reason)
         for header, value in self.headers:
             request_handler.add_header(header, value)
@@ -52,6 +55,13 @@ class Response(object):
 RETRY_TEST_NAMES = collections.defaultdict(int)
 
 
+def request_params(request):
+    params = {}
+    for k, v in request.arguments.items():
+        params[k] = next(iter(v))
+    return params
+
+
 class TestingApp(RequestHandler):
     """
     Simple app that performs various operations, useful for testing an HTTP
@@ -260,6 +270,12 @@ class TestingApp(RequestHandler):
     def headers(self, request):
         return Response(json.dumps(dict(request.headers)))
 
+    def headers_and_params(self, request):
+        params = request_params(request)
+        return Response(
+            json.dumps({"headers": dict(request.headers), "params": params})
+        )
+
     def successful_retry(self, request):
         """ Handler which will return an error and then success
 
Index: urllib3-1.25.10/src/urllib3/_collections.py
===================================================================
--- urllib3-1.25.10.orig/src/urllib3/_collections.py
+++ urllib3-1.25.10/src/urllib3/_collections.py
@@ -267,6 +267,24 @@ class HTTPHeaderDict(MutableMapping):
         else:
             return vals[1:]
 
+    def _prepare_for_method_change(self):
+        """
+        Remove content-specific header fields before changing the request
+        method to GET or HEAD according to RFC 9110, Section 15.4.
+        """
+        content_specific_headers = [
+            "Content-Encoding",
+            "Content-Language",
+            "Content-Location",
+            "Content-Type",
+            "Content-Length",
+            "Digest",
+            "Last-Modified",
+        ]
+        for header in content_specific_headers:
+            self.discard(header)
+        return self
+
     # Backwards compatibility for httplib
     getheaders = getlist
     getallmatchingheaders = getlist
Index: urllib3-1.25.10/src/urllib3/connectionpool.py
===================================================================
--- urllib3-1.25.10.orig/src/urllib3/connectionpool.py
+++ urllib3-1.25.10/src/urllib3/connectionpool.py
@@ -35,6 +35,7 @@ from .connection import (
     HTTPException,
     BaseSSLError,
 )
+from ._collections import HTTPHeaderDict
 from .request import RequestMethods
 from .response import HTTPResponse
 
@@ -771,7 +772,11 @@ class HTTPConnectionPool(ConnectionPool,
         redirect_location = redirect and response.get_redirect_location()
         if redirect_location:
             if response.status == 303:
+                # Change the method according to RFC 9110, Section 15.4.4.
                 method = "GET"
+                # And lose the body not to transfer anything sensitive.
+                body = None
+                headers = HTTPHeaderDict(headers)._prepare_for_method_change()
 
             try:
                 retries = retries.increment(method, url, response=response, _pool=self)
Index: urllib3-1.25.10/src/urllib3/poolmanager.py
===================================================================
--- urllib3-1.25.10.orig/src/urllib3/poolmanager.py
+++ urllib3-1.25.10/src/urllib3/poolmanager.py
@@ -4,7 +4,7 @@ import functools
 import logging
 import warnings
 
-from ._collections import RecentlyUsedContainer
+from ._collections import HTTPHeaderDict, RecentlyUsedContainer
 from .connectionpool import HTTPConnectionPool, HTTPSConnectionPool
 from .connectionpool import port_by_scheme
 from .exceptions import (
@@ -342,9 +342,12 @@ class PoolManager(RequestMethods):
         # Support relative URLs for redirecting.
         redirect_location = urljoin(url, redirect_location)
 
-        # RFC 7231, Section 6.4.4
         if response.status == 303:
+            # Change the method according to RFC 9110, Section 15.4.4.
             method = "GET"
+            # And lose the body not to transfer anything sensitive.
+            kw["body"] = None
+            kw["headers"] = HTTPHeaderDict(kw["headers"])._prepare_for_method_change()
 
         retries = kw.get("retries")
         if not isinstance(retries, Retry):
Index: urllib3-1.25.10/test/with_dummyserver/test_connectionpool.py
===================================================================
--- urllib3-1.25.10.orig/test/with_dummyserver/test_connectionpool.py
+++ urllib3-1.25.10/test/with_dummyserver/test_connectionpool.py
@@ -5,6 +5,7 @@ import sys
 import time
 import warnings
 import pytest
+import json
 
 import mock
 
@@ -24,6 +25,7 @@ from urllib3.packages.six import b, u
 from urllib3.packages.six.moves.urllib.parse import urlencode
 from urllib3.util.retry import Retry, RequestHistory
 from urllib3.util.timeout import Timeout
+from urllib3 import HTTPHeaderDict
 
 from test import SHORT_TIMEOUT, LONG_TIMEOUT
 from dummyserver.testcase import HTTPDummyServerTestCase, SocketDummyServerTestCase
@@ -403,6 +405,18 @@ class TestConnectionPool(HTTPDummyServer
             assert r.status == 200
             assert r.data == b"Dummy server!"
 
+    def test_303_redirect_makes_request_lose_body(self):
+        with HTTPConnectionPool(self.host, self.port) as pool:
+            response = pool.request(
+                "POST",
+                "/redirect",
+                fields={"target": "/headers_and_params", "status": "303 See Other"},
+            )
+        data = response.data.decode("utf-8")
+        data = json.loads(data)
+        assert data["params"] == {}
+        assert "Content-Type" not in HTTPHeaderDict(data["headers"])
+
     def test_bad_connect(self):
         with HTTPConnectionPool("badhost.invalid", self.port) as pool:
             with pytest.raises(MaxRetryError) as e:
Index: urllib3-1.25.10/src/urllib3/__init__.py
===================================================================
--- urllib3-1.25.10.orig/src/urllib3/__init__.py
+++ urllib3-1.25.10/src/urllib3/__init__.py
@@ -15,6 +15,7 @@ from .util.url import get_host
 from .util.timeout import Timeout
 from .util.retry import Retry
 from ._version import __version__
+from ._collections import HTTPHeaderDict
 
 
 # Set default logging handler to avoid "No handler found" warnings.
@@ -28,6 +29,7 @@ __version__ = __version__
 __all__ = (
     "HTTPConnectionPool",
     "HTTPSConnectionPool",
+    "HTTPHeaderDict",
     "PoolManager",
     "ProxyManager",
     "HTTPResponse",
openSUSE Build Service is sponsored by