summaryrefslogtreecommitdiff
path: root/django/utils/text.py
diff options
context:
space:
mode:
authorAndreas Pelme <andreas@pelme.se>2022-11-20 21:46:55 +0100
committerMariusz Felisiak <felisiak.mariusz@gmail.com>2022-12-17 08:46:37 +0100
commitab7a85ac297464df82d8363455609979ca3603db (patch)
treed22374e4fee09779ce1fffedaac6678325462c33 /django/utils/text.py
parenta1bcdc94da6d597c51b4eca0411a97a6460b482e (diff)
downloaddjango-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.py28
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: