From bfd976fc171bd89080ecbbb2d64ed1bc315fa2a9 Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Sun, 25 Jan 2015 23:34:42 -0500 Subject: [PATCH] simply ignore headers with no name (#19996) Patch by Cory Benfield. --- Lib/httplib.py | 5 +++++ Lib/rfc822.py | 7 ++++++- Lib/test/test_httplib.py | 10 ++++++++++ Lib/test/test_rfc822.py | 6 ++++++ Misc/NEWS | 3 +++ 5 files changed, 30 insertions(+), 1 deletion(-) diff --git a/Lib/httplib.py b/Lib/httplib.py index 194e130f17..8a6ad814b7 100644 --- a/Lib/httplib.py +++ b/Lib/httplib.py @@ -313,6 +313,11 @@ class HTTPMessage(mimetools.Message): hlist.append(line) self.addheader(headerseen, line[len(headerseen)+1:].strip()) continue + elif headerseen is not None: + # An empty header name. These aren't allowed in HTTP, but it's + # probably a benign mistake. Don't add the header, just keep + # going. + continue else: # It's not a header line; throw it back and stop here. if not self.dict: diff --git a/Lib/rfc822.py b/Lib/rfc822.py index b65d8da0d2..c1d0865bbb 100644 --- a/Lib/rfc822.py +++ b/Lib/rfc822.py @@ -179,6 +179,11 @@ class Message: lst.append(line) self.dict[headerseen] = line[len(headerseen)+1:].strip() continue + elif headerseen is not None: + # An empty header name. These aren't allowed in HTTP, but it's + # probably a benign mistake. Don't add the header, just keep + # going. + continue else: # It's not a header line; throw it back and stop here. if not self.dict: @@ -202,7 +207,7 @@ class Message: data in RFC 2822-like formats with special header formats. """ i = line.find(':') - if i > 0: + if i > -1: return line[:i].lower() return None diff --git a/Lib/test/test_httplib.py b/Lib/test/test_httplib.py index 0892d5ab63..c071411f58 100644 --- a/Lib/test/test_httplib.py +++ b/Lib/test/test_httplib.py @@ -164,6 +164,16 @@ class HeaderTests(TestCase): conn.request('GET', '/foo') self.assertTrue(sock.data.startswith(expected)) + def test_malformed_headers_coped_with(self): + # Issue 19996 + body = "HTTP/1.1 200 OK\r\nFirst: val\r\n: nval\r\nSecond: val\r\n\r\n" + sock = FakeSocket(body) + resp = httplib.HTTPResponse(sock) + resp.begin() + + self.assertEqual(resp.getheader('First'), 'val') + self.assertEqual(resp.getheader('Second'), 'val') + class BasicTest(TestCase): def test_status_lines(self): diff --git a/Lib/test/test_rfc822.py b/Lib/test/test_rfc822.py index d8a0280f51..cdd8c9c5a2 100644 --- a/Lib/test/test_rfc822.py +++ b/Lib/test/test_rfc822.py @@ -248,6 +248,12 @@ A test message. eq(rfc822.quote('foo\\wacky"name'), 'foo\\\\wacky\\"name') eq(rfc822.unquote('"foo\\\\wacky\\"name"'), 'foo\\wacky"name') + def test_invalid_headers(self): + eq = self.assertEqual + msg = self.create_message("First: val\n: otherval\nSecond: val2\n") + eq(msg.getheader('First'), 'val') + eq(msg.getheader('Second'), 'val2') + def test_main(): test_support.run_unittest(MessageTestCase) diff --git a/Misc/NEWS b/Misc/NEWS index f21dbe83f7..6582bab868 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -15,6 +15,9 @@ Core and Builtins Library ------- +- Issue #19996: Make :mod:`httplib` ignore headers with no name rather than + assuming the body has started. + - Issue #20188: Support Application-Layer Protocol Negotiation (ALPN) in the ssl module. -- 2.50.1