diff --git a/src/HttpHeaderProcessor.cc b/src/HttpHeaderProcessor.cc index 1b027c5b..6baf7595 100644 --- a/src/HttpHeaderProcessor.cc +++ b/src/HttpHeaderProcessor.cc @@ -269,6 +269,9 @@ bool HttpHeaderProcessor::parse(const unsigned char* data, size_t length) break; case PREV_FIELD_NAME: if(util::isLws(c)) { + if(lastFieldName_.empty()) { + throw DL_ABORT_EX("Bad HTTP header: field name starts with LWS"); + } // Evil Multi-line header field state_ = FIELD_VALUE; } else { @@ -282,6 +285,8 @@ bool HttpHeaderProcessor::parse(const unsigned char* data, size_t length) state_ = HEADERS_COMPLETE; } else if(c == '\r') { state_ = PREV_EOH; + } else if(c == ':') { + throw DL_ABORT_EX("Bad HTTP header: field name starts with ':'"); } else { state_ = FIELD_NAME; i = getFieldNameToken(lastFieldName_, data, length, i); diff --git a/test/HttpHeaderProcessorTest.cc b/test/HttpHeaderProcessorTest.cc index 7dc9cd0f..a46480e6 100644 --- a/test/HttpHeaderProcessorTest.cc +++ b/test/HttpHeaderProcessorTest.cc @@ -21,6 +21,7 @@ class HttpHeaderProcessorTest:public CppUnit::TestFixture { CPPUNIT_TEST(testGetHttpResponseHeader); CPPUNIT_TEST(testGetHttpResponseHeader_statusOnly); CPPUNIT_TEST(testGetHttpResponseHeader_insufficientStatusLength); + CPPUNIT_TEST(testGetHttpResponseHeader_nameStartsWs); CPPUNIT_TEST(testBeyondLimit); CPPUNIT_TEST(testGetHeaderString); CPPUNIT_TEST(testGetHttpRequestHeader); @@ -35,6 +36,7 @@ public: void testGetHttpResponseHeader(); void testGetHttpResponseHeader_statusOnly(); void testGetHttpResponseHeader_insufficientStatusLength(); + void testGetHttpResponseHeader_nameStartsWs(); void testBeyondLimit(); void testGetHeaderString(); void testGetHttpRequestHeader(); @@ -71,6 +73,7 @@ void HttpHeaderProcessorTest::testParse3() " text3\r\n" "Duplicate: foo\r\n" "Duplicate: bar\r\n" + "No-value:\r\n" "\r\n"; CPPUNIT_ASSERT(proc.parse(s)); SharedHandle h = proc.getResult(); @@ -84,6 +87,8 @@ void HttpHeaderProcessorTest::testParse3() h->findAll("duplicate")[0]); CPPUNIT_ASSERT_EQUAL(std::string("bar"), h->findAll("duplicate")[1]); + CPPUNIT_ASSERT_EQUAL(std::string(""), h->find("no-value")); + CPPUNIT_ASSERT(h->defined("no-value")); } void HttpHeaderProcessorTest::testGetLastBytesProcessed() @@ -172,6 +177,46 @@ void HttpHeaderProcessorTest::testGetHttpResponseHeader_insufficientStatusLength } } +void HttpHeaderProcessorTest::testGetHttpResponseHeader_nameStartsWs() +{ + HttpHeaderProcessor proc(HttpHeaderProcessor::CLIENT_PARSER); + + std::string hd = + "HTTP/1.1 200\r\n" + " foo:bar\r\n" + "\r\n"; + try { + proc.parse(hd); + CPPUNIT_FAIL("Exception must be thrown."); + } catch(DlAbortEx& ex) { + // Success + } + + proc.clear(); + hd = + "HTTP/1.1 200\r\n" + ":foo:bar\r\n" + "\r\n"; + try { + proc.parse(hd); + CPPUNIT_FAIL("Exception must be thrown."); + } catch(DlAbortEx& ex) { + // Success + } + + proc.clear(); + hd = + "HTTP/1.1 200\r\n" + ":foo\r\n" + "\r\n"; + try { + proc.parse(hd); + CPPUNIT_FAIL("Exception must be thrown."); + } catch(DlAbortEx& ex) { + // Success + } +} + void HttpHeaderProcessorTest::testBeyondLimit() { HttpHeaderProcessor proc(HttpHeaderProcessor::CLIENT_PARSER);