Skip to content

Commit 104a38c

Browse files
[3.13] gh-148518 fix index error in local part attribute (GH-148522) (#149199)
As part of fixing bpo-27931 code was introduced to get_bare_quoted_string that added an empty Terminal if the quoted string was empty. This isn't the best answer in terms of the parse tree; we really want the token list to be empty in that case. But having it be empty resulted in local_part raising the index error. We find that same problem if we try to parse an address consisting of a single dquote. By fixing local_part to not raise on an empty token list, we can have the bare_quoted_string code correctly return an empty token list for the empty string cases (two dquotes or a single dquote as the entire addrespec, at the end of a line). (cherry picked from commit bdbb55c) Co-authored-by: R. David Murray <rdmurray@bitdance.com>
1 parent b3e0c72 commit 104a38c

3 files changed

Lines changed: 46 additions & 6 deletions

File tree

Lib/email/_header_value_parser.py

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -639,11 +639,11 @@ def local_part(self):
639639
for tok in self[0] + [DOT]:
640640
if tok.token_type == 'cfws':
641641
continue
642-
if (last_is_tl and tok.token_type == 'dot' and
642+
if (last_is_tl and tok.token_type == 'dot' and last and
643643
last[-1].token_type == 'cfws'):
644644
res[-1] = TokenList(last[:-1])
645645
is_tl = isinstance(tok, TokenList)
646-
if (is_tl and last.token_type == 'dot' and
646+
if (is_tl and last.token_type == 'dot' and tok and
647647
tok[0].token_type == 'cfws'):
648648
res.append(TokenList(tok[1:]))
649649
else:
@@ -1245,8 +1245,7 @@ def get_bare_quoted_string(value):
12451245
bare_quoted_string = BareQuotedString()
12461246
value = value[1:]
12471247
if value and value[0] == '"':
1248-
token, value = get_qcontent(value)
1249-
bare_quoted_string.append(token)
1248+
return bare_quoted_string, value[1:]
12501249
while value and value[0] != '"':
12511250
if value[0] in WSP:
12521251
token, value = get_fws(value)

Lib/test/test_email/test_headerregistry.py

Lines changed: 39 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1263,12 +1263,12 @@ class TestAddressHeader(TestHeaderBase):
12631263
'example.com',
12641264
None),
12651265

1266-
}
1267-
12681266
# XXX: Need many more examples, and in particular some with names in
12691267
# trailing comments, which aren't currently handled. comments in
12701268
# general are not handled yet.
12711269

1270+
}
1271+
12721272
def example_as_address(self, source, defects, decoded, display_name,
12731273
addr_spec, username, domain, comment):
12741274
h = self.make_header('sender', source)
@@ -1286,6 +1286,43 @@ def example_as_address(self, source, defects, decoded, display_name,
12861286
# XXX: we have no comment support yet.
12871287
#self.assertEqual(a.comment, comment)
12881288

1289+
example_broken_header_params = {
1290+
1291+
'just_dquote':
1292+
('"',
1293+
[errors.InvalidHeaderDefect]*2,
1294+
'<>',
1295+
'',
1296+
'<>',
1297+
'',
1298+
'',
1299+
),
1300+
1301+
}
1302+
1303+
def example_broken_header_as_address(
1304+
self,
1305+
source,
1306+
defects,
1307+
decoded,
1308+
display_name,
1309+
addr_spec,
1310+
username,
1311+
domain,
1312+
):
1313+
h = self.make_header('sender', source)
1314+
self.assertEqual(h, decoded)
1315+
self.assertDefectsEqual(h.defects, defects)
1316+
a = h.address
1317+
self.assertEqual(str(a), decoded)
1318+
self.assertEqual(len(h.groups), 1)
1319+
self.assertEqual([a], list(h.groups[0].addresses))
1320+
self.assertEqual([a], list(h.addresses))
1321+
self.assertEqual(a.display_name, display_name)
1322+
self.assertEqual(a.addr_spec, addr_spec)
1323+
self.assertEqual(a.username, username)
1324+
self.assertEqual(a.domain, domain)
1325+
12891326
def example_as_group(self, source, defects, decoded, display_name,
12901327
addr_spec, username, domain, comment):
12911328
source = 'foo: {};'.format(source)
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
If an email containing an address header that ended in an open double quote
2+
was parsed with a non-``compat32`` policy, accessing the ``username`` attribute
3+
of the mailbox accessed through that header object would result in an
4+
``IndexError``. It now correctly returns an empty string as the result.

0 commit comments

Comments
 (0)