Blame SOURCES/CVE-2019-20916.patch

da3530
diff --git a/pip/download.py b/pip/download.py
da3530
index 54d3131..b55d694 100644
da3530
--- a/pip/download.py
da3530
+++ b/pip/download.py
da3530
@@ -54,7 +54,8 @@ __all__ = ['get_file_content',
da3530
            'is_url', 'url_to_path', 'path_to_url',
da3530
            'is_archive_file', 'unpack_vcs_link',
da3530
            'unpack_file_url', 'is_vcs_url', 'is_file_url',
da3530
-           'unpack_http_url', 'unpack_url']
da3530
+           'unpack_http_url', 'unpack_url',
da3530
+           'parse_content_disposition', 'sanitize_content_filename']
da3530
 
da3530
 
da3530
 logger = logging.getLogger(__name__)
da3530
@@ -823,6 +824,28 @@ def unpack_url(link, location, download_dir=None,
da3530
     if only_download:
da3530
         write_delete_marker_file(location)
da3530
 
da3530
+def sanitize_content_filename(filename):
da3530
+    # type: (str) -> str
da3530
+    """
da3530
+    Sanitize the "filename" value from a Content-Disposition header.
da3530
+    """
da3530
+    return os.path.basename(filename)
da3530
+
da3530
+
da3530
+def parse_content_disposition(content_disposition, default_filename):
da3530
+    # type: (str, str) -> str
da3530
+    """
da3530
+    Parse the "filename" value from a Content-Disposition header, and
da3530
+    return the default filename if the result is empty.
da3530
+    """
da3530
+    _type, params = cgi.parse_header(content_disposition)
da3530
+    filename = params.get('filename')
da3530
+    if filename:
da3530
+        # We need to sanitize the filename to prevent directory traversal
da3530
+        # in case the filename contains ".." path parts.
da3530
+        filename = sanitize_content_filename(filename)
da3530
+    return filename or default_filename
da3530
+
da3530
 
da3530
 def _download_http_url(link, session, temp_dir, hashes):
da3530
     """Download link url into temp_dir using provided session"""
da3530
@@ -864,10 +887,7 @@ def _download_http_url(link, session, temp_dir, hashes):
da3530
     # Have a look at the Content-Disposition header for a better guess
da3530
     content_disposition = resp.headers.get('content-disposition')
da3530
     if content_disposition:
da3530
-        type, params = cgi.parse_header(content_disposition)
da3530
-        # We use ``or`` here because we don't want to use an "empty" value
da3530
-        # from the filename param.
da3530
-        filename = params.get('filename') or filename
da3530
+        filename = parse_content_disposition(content_disposition, filename)
da3530
     ext = splitext(filename)[1]
da3530
     if not ext:
da3530
         ext = mimetypes.guess_extension(content_type)