gh-121650: Encode newlines in headers, and verify headers are sound (… · python/cpython@0976339 (original) (raw)
`@@ -6,6 +6,7 @@
`
6
6
`from email.generator import Generator, BytesGenerator
`
7
7
`from email.headerregistry import Address
`
8
8
`from email import policy
`
``
9
`+
import email.errors
`
9
10
`from test.test_email import TestEmailBase, parameterize
`
10
11
``
11
12
``
`@@ -249,6 +250,44 @@ def test_rfc2231_wrapping_switches_to_default_len_if_too_narrow(self):
`
249
250
`g.flatten(msg)
`
250
251
`self.assertEqual(s.getvalue(), self.typ(expected))
`
251
252
``
``
253
`+
def test_keep_encoded_newlines(self):
`
``
254
`+
msg = self.msgmaker(self.typ(textwrap.dedent("""\
`
``
255
`+
To: nobody
`
``
256
`+
Subject: Bad subject=?UTF-8?Q?=0A?=Bcc: injection@example.com
`
``
257
+
``
258
`+
None
`
``
259
`+
""")))
`
``
260
`+
expected = textwrap.dedent("""\
`
``
261
`+
To: nobody
`
``
262
`+
Subject: Bad subject=?UTF-8?Q?=0A?=Bcc: injection@example.com
`
``
263
+
``
264
`+
None
`
``
265
`+
""")
`
``
266
`+
s = self.ioclass()
`
``
267
`+
g = self.genclass(s, policy=self.policy.clone(max_line_length=80))
`
``
268
`+
g.flatten(msg)
`
``
269
`+
self.assertEqual(s.getvalue(), self.typ(expected))
`
``
270
+
``
271
`+
def test_keep_long_encoded_newlines(self):
`
``
272
`+
msg = self.msgmaker(self.typ(textwrap.dedent("""\
`
``
273
`+
To: nobody
`
``
274
`+
Subject: Bad subject=?UTF-8?Q?=0A?=Bcc: injection@example.com
`
``
275
+
``
276
`+
None
`
``
277
`+
""")))
`
``
278
`+
expected = textwrap.dedent("""\
`
``
279
`+
To: nobody
`
``
280
`+
Subject: Bad subject
`
``
281
`+
=?utf-8?q?=0A?=Bcc:
`
``
282
`+
`
``
283
+
``
284
`+
None
`
``
285
`+
""")
`
``
286
`+
s = self.ioclass()
`
``
287
`+
g = self.genclass(s, policy=self.policy.clone(max_line_length=30))
`
``
288
`+
g.flatten(msg)
`
``
289
`+
self.assertEqual(s.getvalue(), self.typ(expected))
`
``
290
+
252
291
``
253
292
`class TestGenerator(TestGeneratorBase, TestEmailBase):
`
254
293
``
`@@ -273,6 +312,29 @@ def test_flatten_unicode_linesep(self):
`
273
312
`g.flatten(msg)
`
274
313
`self.assertEqual(s.getvalue(), self.typ(expected))
`
275
314
``
``
315
`+
def test_verify_generated_headers(self):
`
``
316
`+
"""gh-121650: by default the generator prevents header injection"""
`
``
317
`+
class LiteralHeader(str):
`
``
318
`+
name = 'Header'
`
``
319
`+
def fold(self, **kwargs):
`
``
320
`+
return self
`
``
321
+
``
322
`+
for text in (
`
``
323
`+
'Value\r\nBad Injection\r\n',
`
``
324
`+
'NoNewLine'
`
``
325
`+
):
`
``
326
`+
with self.subTest(text=text):
`
``
327
`+
message = message_from_string(
`
``
328
`+
"Header: Value\r\n\r\nBody",
`
``
329
`+
policy=self.policy,
`
``
330
`+
)
`
``
331
+
``
332
`+
del message['Header']
`
``
333
`+
message['Header'] = LiteralHeader(text)
`
``
334
+
``
335
`+
with self.assertRaises(email.errors.HeaderWriteError):
`
``
336
`+
message.as_string()
`
``
337
+
276
338
``
277
339
`class TestBytesGenerator(TestGeneratorBase, TestEmailBase):
`
278
340
``