diff options
author | Andreas Pelme <andreas@pelme.se> | 2022-11-20 21:46:55 +0100 |
---|---|---|
committer | Mariusz Felisiak <felisiak.mariusz@gmail.com> | 2022-12-17 08:46:37 +0100 |
commit | ab7a85ac297464df82d8363455609979ca3603db (patch) | |
tree | d22374e4fee09779ce1fffedaac6678325462c33 /django/utils/text.py | |
parent | a1bcdc94da6d597c51b4eca0411a97a6460b482e (diff) | |
download | django-ab7a85ac297464df82d8363455609979ca3603db.tar.gz |
Fixed #34170 -- Implemented Heal The Breach (HTB) in GzipMiddleware.
Diffstat (limited to 'django/utils/text.py')
-rw-r--r-- | django/utils/text.py | 28 |
1 files changed, 24 insertions, 4 deletions
diff --git a/django/utils/text.py b/django/utils/text.py index dcfe3fba0e..86d3b52741 100644 --- a/django/utils/text.py +++ b/django/utils/text.py @@ -1,4 +1,6 @@ +import gzip import re +import secrets import unicodedata from gzip import GzipFile from gzip import compress as gzip_compress @@ -314,8 +316,23 @@ def phone2numeric(phone): return "".join(char2number.get(c, c) for c in phone.lower()) -def compress_string(s): - return gzip_compress(s, compresslevel=6, mtime=0) +def _get_random_filename(max_random_bytes): + return b"a" * secrets.randbelow(max_random_bytes) + + +def compress_string(s, *, max_random_bytes=None): + compressed_data = gzip_compress(s, compresslevel=6, mtime=0) + + if not max_random_bytes: + return compressed_data + + compressed_view = memoryview(compressed_data) + header = bytearray(compressed_view[:10]) + header[3] = gzip.FNAME + + filename = _get_random_filename(max_random_bytes) + b"\x00" + + return bytes(header) + filename + compressed_view[10:] class StreamingBuffer(BytesIO): @@ -327,9 +344,12 @@ class StreamingBuffer(BytesIO): # Like compress_string, but for iterators of strings. -def compress_sequence(sequence): +def compress_sequence(sequence, *, max_random_bytes=None): buf = StreamingBuffer() - with GzipFile(mode="wb", compresslevel=6, fileobj=buf, mtime=0) as zfile: + filename = _get_random_filename(max_random_bytes) if max_random_bytes else None + with GzipFile( + filename=filename, mode="wb", compresslevel=6, fileobj=buf, mtime=0 + ) as zfile: # Output headers... yield buf.read() for item in sequence: |