Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 155ceaa

Browse files
committed
handle headers with no key (closes #19996)
Patch by Cory Benfield.
1 parent 7e4b905 commit 155ceaa

4 files changed

Lines changed: 29 additions & 1 deletion

File tree

Lib/email/feedparser.py

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@
3333
NLCRE_crack = re.compile('(\r\n|\r|\n)')
3434
# RFC 2822 $3.6.8 Optional fields. ftext is %d33-57 / %d59-126, Any character
3535
# except controls, SP, and ":".
36-
headerRE = re.compile(r'^(From |[\041-\071\073-\176]{1,}:|[\t ])')
36+
headerRE = re.compile(r'^(From |[\041-\071\073-\176]*:|[\t ])')
3737
EMPTYSTRING = ''
3838
NL = '\n'
3939

@@ -511,6 +511,15 @@ def _parse_headers(self, lines):
511511
# There will always be a colon, because if there wasn't the part of
512512
# the parser that calls us would have started parsing the body.
513513
i = line.find(':')
514+
515+
# If the colon is on the start of the line the header is clearly
516+
# malformed, but we might be able to salvage the rest of the
517+
# message. Track the error but keep going.
518+
if i == 0:
519+
defect = errors.InvalidHeaderDefect("Missing header name.")
520+
self._cur.defects.append(defect)
521+
continue
522+
514523
assert i>0, "_parse_headers fed line with no : and no leading WS"
515524
lastheader = line[:i]
516525
lastvalue = [line]

Lib/test/test_email/test_email.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3389,6 +3389,12 @@ def parse(self, chunks):
33893389
feedparser.feed(chunk)
33903390
return feedparser.close()
33913391

3392+
def test_empty_header_name_handled(self):
3393+
# Issue 19996
3394+
msg = self.parse("First: val\n: bad\nSecond: val")
3395+
self.assertEqual(msg['First'], 'val')
3396+
self.assertEqual(msg['Second'], 'val')
3397+
33923398
def test_newlines(self):
33933399
m = self.parse(['a:\nb:\rc:\r\nd:\n'])
33943400
self.assertEqual(m.keys(), ['a', 'b', 'c', 'd'])

Lib/test/test_httplib.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,16 @@ def test_ipv6host_header(self):
167167
conn.request('GET', '/foo')
168168
self.assertTrue(sock.data.startswith(expected))
169169

170+
def test_malformed_headers_coped_with(self):
171+
# Issue 19996
172+
body = "HTTP/1.1 200 OK\r\nFirst: val\r\n: nval\r\nSecond: val\r\n\r\n"
173+
sock = FakeSocket(body)
174+
resp = client.HTTPResponse(sock)
175+
resp.begin()
176+
177+
self.assertEqual(resp.getheader('First'), 'val')
178+
self.assertEqual(resp.getheader('Second'), 'val')
179+
170180

171181
class BasicTest(TestCase):
172182
def test_status_lines(self):

Misc/NEWS

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,9 @@ Core and Builtins
4747
Library
4848
-------
4949

50+
- Issue #19996: :class:`email.feedparser.FeedParser` now handles (malformed)
51+
headers with no key rather than amusing the body has started.
52+
5053
- Issue #23248: Update ssl error codes from latest OpenSSL git master.
5154

5255
- Issue #23098: 64-bit dev_t is now supported in the os module.

0 commit comments

Comments
 (0)