Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit2eaf9ba

Browse files
miss-islingtonqsserhiy-storchaka
authored
[3.12]bpo-40944: Fix IndexError when parse emails with truncated Message-ID, address, routes, etc (GH-20790) (GH-117974)
(cherry picked from commit1aa8bbe)Co-authored-by: Ivan Savin <acccko@gmail.com>Co-authored-by: Serhiy Storchaka <storchaka@gmail.com>
1 parent4d34b7f commit2eaf9ba

File tree

3 files changed

+51
-5
lines changed

3 files changed

+51
-5
lines changed

‎Lib/email/_header_value_parser.py

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1213,7 +1213,7 @@ def get_bare_quoted_string(value):
12131213
value is the text between the quote marks, with whitespace
12141214
preserved and quoted pairs decoded.
12151215
"""
1216-
ifvalue[0]!='"':
1216+
ifnotvalueorvalue[0]!='"':
12171217
raiseerrors.HeaderParseError(
12181218
"expected '\"' but found '{}'".format(value))
12191219
bare_quoted_string=BareQuotedString()
@@ -1454,7 +1454,7 @@ def get_local_part(value):
14541454
"""
14551455
local_part=LocalPart()
14561456
leader=None
1457-
ifvalue[0]inCFWS_LEADER:
1457+
ifvalueandvalue[0]inCFWS_LEADER:
14581458
leader,value=get_cfws(value)
14591459
ifnotvalue:
14601460
raiseerrors.HeaderParseError(
@@ -1613,7 +1613,7 @@ def get_domain(value):
16131613
"""
16141614
domain=Domain()
16151615
leader=None
1616-
ifvalue[0]inCFWS_LEADER:
1616+
ifvalueandvalue[0]inCFWS_LEADER:
16171617
leader,value=get_cfws(value)
16181618
ifnotvalue:
16191619
raiseerrors.HeaderParseError(
@@ -1689,6 +1689,8 @@ def get_obs_route(value):
16891689
ifvalue[0]inCFWS_LEADER:
16901690
token,value=get_cfws(value)
16911691
obs_route.append(token)
1692+
ifnotvalue:
1693+
break
16921694
ifvalue[0]=='@':
16931695
obs_route.append(RouteComponentMarker)
16941696
token,value=get_domain(value[1:])
@@ -1707,7 +1709,7 @@ def get_angle_addr(value):
17071709
17081710
"""
17091711
angle_addr=AngleAddr()
1710-
ifvalue[0]inCFWS_LEADER:
1712+
ifvalueandvalue[0]inCFWS_LEADER:
17111713
token,value=get_cfws(value)
17121714
angle_addr.append(token)
17131715
ifnotvalueorvalue[0]!='<':
@@ -1717,7 +1719,7 @@ def get_angle_addr(value):
17171719
value=value[1:]
17181720
# Although it is not legal per RFC5322, SMTP uses '<>' in certain
17191721
# circumstances.
1720-
ifvalue[0]=='>':
1722+
ifvalueandvalue[0]=='>':
17211723
angle_addr.append(ValueTerminal('>','angle-addr-end'))
17221724
angle_addr.defects.append(errors.InvalidHeaderDefect(
17231725
"null addr-spec in angle-addr"))
@@ -1769,6 +1771,9 @@ def get_name_addr(value):
17691771
name_addr=NameAddr()
17701772
# Both the optional display name and the angle-addr can start with cfws.
17711773
leader=None
1774+
ifnotvalue:
1775+
raiseerrors.HeaderParseError(
1776+
"expected name-addr but found '{}'".format(value))
17721777
ifvalue[0]inCFWS_LEADER:
17731778
leader,value=get_cfws(value)
17741779
ifnotvalue:

‎Lib/test/test_email/test__header_value_parser.py

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -801,6 +801,10 @@ def test_get_quoted_string_header_ends_in_qcontent(self):
801801
self.assertEqual(qs.content,'bob')
802802
self.assertEqual(qs.quoted_value,' "bob"')
803803

804+
deftest_get_quoted_string_cfws_only_raises(self):
805+
withself.assertRaises(errors.HeaderParseError):
806+
parser.get_quoted_string(' (foo) ')
807+
804808
deftest_get_quoted_string_no_quoted_string(self):
805809
withself.assertRaises(errors.HeaderParseError):
806810
parser.get_quoted_string(' (ab) xyz')
@@ -1135,6 +1139,10 @@ def test_get_local_part_complex_obsolete_invalid(self):
11351139
'@python.org')
11361140
self.assertEqual(local_part.local_part,'Fred.A.Johnson and dogs')
11371141

1142+
deftest_get_local_part_empty_raises(self):
1143+
withself.assertRaises(errors.HeaderParseError):
1144+
parser.get_local_part('')
1145+
11381146
deftest_get_local_part_no_part_raises(self):
11391147
withself.assertRaises(errors.HeaderParseError):
11401148
parser.get_local_part(' (foo) ')
@@ -1387,6 +1395,10 @@ def test_get_domain_obsolete(self):
13871395
'')
13881396
self.assertEqual(domain.domain,'example.com')
13891397

1398+
deftest_get_domain_empty_raises(self):
1399+
withself.assertRaises(errors.HeaderParseError):
1400+
parser.get_domain("")
1401+
13901402
deftest_get_domain_no_non_cfws_raises(self):
13911403
withself.assertRaises(errors.HeaderParseError):
13921404
parser.get_domain(" (foo)\t")
@@ -1512,6 +1524,10 @@ def test_get_obs_route_no_route_before_end_raises(self):
15121524
withself.assertRaises(errors.HeaderParseError):
15131525
parser.get_obs_route('(foo) @example.com,')
15141526

1527+
deftest_get_obs_route_no_route_before_end_raises2(self):
1528+
withself.assertRaises(errors.HeaderParseError):
1529+
parser.get_obs_route('(foo) @example.com, (foo) ')
1530+
15151531
deftest_get_obs_route_no_route_before_special_raises(self):
15161532
withself.assertRaises(errors.HeaderParseError):
15171533
parser.get_obs_route('(foo) [abc],')
@@ -1520,6 +1536,14 @@ def test_get_obs_route_no_route_before_special_raises2(self):
15201536
withself.assertRaises(errors.HeaderParseError):
15211537
parser.get_obs_route('(foo) @example.com [abc],')
15221538

1539+
deftest_get_obs_route_no_domain_after_at_raises(self):
1540+
withself.assertRaises(errors.HeaderParseError):
1541+
parser.get_obs_route('@')
1542+
1543+
deftest_get_obs_route_no_domain_after_at_raises2(self):
1544+
withself.assertRaises(errors.HeaderParseError):
1545+
parser.get_obs_route('@example.com, @')
1546+
15231547
# get_angle_addr
15241548

15251549
deftest_get_angle_addr_simple(self):
@@ -1646,6 +1670,14 @@ def test_get_angle_addr_ends_at_special(self):
16461670
self.assertIsNone(angle_addr.route)
16471671
self.assertEqual(angle_addr.addr_spec,'dinsdale@example.com')
16481672

1673+
deftest_get_angle_addr_empty_raise(self):
1674+
withself.assertRaises(errors.HeaderParseError):
1675+
parser.get_angle_addr('')
1676+
1677+
deftest_get_angle_addr_left_angle_only_raise(self):
1678+
withself.assertRaises(errors.HeaderParseError):
1679+
parser.get_angle_addr('<')
1680+
16491681
deftest_get_angle_addr_no_angle_raise(self):
16501682
withself.assertRaises(errors.HeaderParseError):
16511683
parser.get_angle_addr('(foo) ')
@@ -1857,6 +1889,10 @@ def test_get_name_addr_ends_at_special(self):
18571889
self.assertIsNone(name_addr.route)
18581890
self.assertEqual(name_addr.addr_spec,'dinsdale@example.com')
18591891

1892+
deftest_get_name_addr_empty_raises(self):
1893+
withself.assertRaises(errors.HeaderParseError):
1894+
parser.get_name_addr('')
1895+
18601896
deftest_get_name_addr_no_content_raises(self):
18611897
withself.assertRaises(errors.HeaderParseError):
18621898
parser.get_name_addr(' (foo) ')
@@ -2732,6 +2768,10 @@ def test_get_msg_id_empty_id_right(self):
27322768
withself.assertRaises(errors.HeaderParseError):
27332769
parser.get_msg_id("<simplelocal@>")
27342770

2771+
deftest_get_msg_id_no_id_right(self):
2772+
withself.assertRaises(errors.HeaderParseError):
2773+
parser.get_msg_id("<simplelocal@")
2774+
27352775
deftest_get_msg_id_with_brackets(self):
27362776
# Microsof Outlook generates non-standard one-off addresses:
27372777
# https://learn.microsoft.com/en-us/office/client-developer/outlook/mapi/one-off-addresses
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Fix several IndexError when parse emails with truncated Message-ID, address, routes, etc, e.g. ``example@``.

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp