Skip to content

Commit 24af346

Browse files
committed
gh-151857: Fix IndexError in the email header parser on empty input
Guard two empty-input index escapes in the modern email header parser that raised a bare IndexError instead of a parse defect: a MIME parameter name ending with '*', and an address display name that is only a comment.
1 parent 8270ae5 commit 24af346

4 files changed

Lines changed: 53 additions & 1 deletion

File tree

Lib/email/_header_value_parser.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -580,6 +580,8 @@ def display_name(self):
580580
return res.value
581581
if res[0].token_type == 'cfws':
582582
res.pop(0)
583+
if len(res) == 0:
584+
return res.value
583585
else:
584586
if (isinstance(res[0], TokenList) and
585587
res[0][0].token_type == 'cfws'):
@@ -2511,7 +2513,7 @@ def get_parameter(value):
25112513
param.append(ValueTerminal('*', 'extended-parameter-marker'))
25122514
value = value[1:]
25132515
param.extended = True
2514-
if value[0] != '=':
2516+
if not value or value[0] != '=':
25152517
raise errors.HeaderParseError("Parameter not followed by '='")
25162518
param.append(ValueTerminal('=', 'parameter-separator'))
25172519
value = value[1:]

Lib/test/test_email/test__header_value_parser.py

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1862,6 +1862,16 @@ def test_get_display_name_for_invalid_address_field(self):
18621862
':Foo ', '', '', [errors.InvalidHeaderDefect], ':Foo ')
18631863
self.assertEqual(display_name.value, '')
18641864

1865+
def test_get_display_name_comment_only(self):
1866+
# A display name consisting only of a comment (CFWS) used to raise an
1867+
# uncaught IndexError; it now degrades to an empty display name.
1868+
display_name = self._test_get_x(
1869+
parser.get_display_name,
1870+
'(c)', '(c)', ' "" ',
1871+
[errors.InvalidHeaderDefect, errors.ObsoleteHeaderDefect], '')
1872+
self.assertEqual(display_name.display_name, '')
1873+
self.assertEqual(display_name.value, ' "" ')
1874+
18651875
# get_name_addr
18661876

18671877
def test_get_name_addr_angle_addr_only(self):
@@ -3144,6 +3154,32 @@ def mime_parameters_as_value(self,
31443154
'r*=\'a\'"',
31453155
[('r', '"')],
31463156
[errors.InvalidHeaderDefect]*2),
3157+
3158+
# gh-151857: A parameter name ending with the extended marker
3159+
# '*' but with no value used to raise an uncaught IndexError instead
3160+
# of degrading to a defect. Each case below IndexErrors unpatched.
3161+
'extended_marker_no_value': (
3162+
'name*',
3163+
'',
3164+
'name*',
3165+
[],
3166+
[errors.InvalidHeaderDefect]),
3167+
3168+
# Sectioned form ('*0*') reaches the same marker-consuming branch.
3169+
'extended_marker_no_value_sectioned': (
3170+
'name*0*',
3171+
'',
3172+
'name*0*',
3173+
[],
3174+
[errors.InvalidHeaderDefect]),
3175+
3176+
# A trailing marker-only parameter after a valid one.
3177+
'extended_marker_no_value_after_param': (
3178+
'x=1; name*',
3179+
' x="1"',
3180+
'x=1; name*',
3181+
[('x', '1')],
3182+
[errors.InvalidHeaderDefect]),
31473183
}
31483184

31493185
@parameterize

Lib/test/test_email/test_headerregistry.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1426,6 +1426,16 @@ def test_groups_types(self):
14261426
self.assertIsInstance(h.groups, tuple)
14271427
self.assertIsInstance(h.groups[0], Group)
14281428

1429+
def test_comment_only_group_display_name(self):
1430+
# A group whose display name is only a comment used to raise an
1431+
# uncaught IndexError while parsing; it now degrades gracefully.
1432+
h = self.make_header('to', '(c):')
1433+
self.assertEqual(h.groups[0].display_name, '')
1434+
self.assertEqual(h.addresses, ())
1435+
h = self.make_header('cc', '(x): a@b.com;')
1436+
self.assertEqual(h.groups[0].display_name, '')
1437+
self.assertEqual(h.addresses[0].addr_spec, 'a@b.com')
1438+
14291439
def test_set_from_Address(self):
14301440
h = self.make_header('to', Address('me', 'foo', 'example.com'))
14311441
self.assertEqual(h, 'me <foo@example.com>')
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
Fixed two cases where the :mod:`email` header parser (under
2+
:class:`~email.policy.EmailPolicy`) raised an uncaught :exc:`IndexError` on
3+
malformed input: a MIME parameter name ending with ``*``, and an address
4+
header whose display name is only a comment. Both now degrade gracefully.

0 commit comments

Comments
 (0)