changeset: 94284:9a4882b12218 branch: 2.7 parent: 94275:5db28a3199b2 user: Benjamin Peterson date: Sun Jan 25 23:34:42 2015 -0500 files: Lib/httplib.py Lib/rfc822.py Lib/test/test_httplib.py Lib/test/test_rfc822.py Misc/NEWS description: simply ignore headers with no name (#19996) Patch by Cory Benfield. diff -r 5db28a3199b2 -r 9a4882b12218 Lib/httplib.py --- a/Lib/httplib.py Sun Jan 25 15:48:47 2015 -0500 +++ b/Lib/httplib.py Sun Jan 25 23:34:42 2015 -0500 @@ -313,6 +313,11 @@ 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 -r 5db28a3199b2 -r 9a4882b12218 Lib/rfc822.py --- a/Lib/rfc822.py Sun Jan 25 15:48:47 2015 -0500 +++ b/Lib/rfc822.py Sun Jan 25 23:34:42 2015 -0500 @@ -179,6 +179,11 @@ 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 @@ 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 -r 5db28a3199b2 -r 9a4882b12218 Lib/test/test_httplib.py --- a/Lib/test/test_httplib.py Sun Jan 25 15:48:47 2015 -0500 +++ b/Lib/test/test_httplib.py Sun Jan 25 23:34:42 2015 -0500 @@ -164,6 +164,16 @@ 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 -r 5db28a3199b2 -r 9a4882b12218 Lib/test/test_rfc822.py --- a/Lib/test/test_rfc822.py Sun Jan 25 15:48:47 2015 -0500 +++ b/Lib/test/test_rfc822.py Sun Jan 25 23:34:42 2015 -0500 @@ -248,6 +248,12 @@ 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 -r 5db28a3199b2 -r 9a4882b12218 Misc/NEWS --- a/Misc/NEWS Sun Jan 25 15:48:47 2015 -0500 +++ b/Misc/NEWS Sun Jan 25 23:34:42 2015 -0500 @@ -15,6 +15,9 @@ 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.