2010-07-11 Tatsuhiro Tsujikawa <t-tujikawa@users.sourceforge.net>

Fixed ChunkedDecoder. It does not read trailer and final CRLF.
	* src/ChunkedDecoder.cc
	* src/ChunkedDecoder.h
	* test/ChunkedDecoderTest.cc
pull/1/head
Tatsuhiro Tsujikawa 2010-07-11 14:15:36 +00:00
parent eecb81dc60
commit 20cea7f693
4 changed files with 62 additions and 2 deletions

View File

@ -1,3 +1,10 @@
2010-07-11 Tatsuhiro Tsujikawa <t-tujikawa@users.sourceforge.net>
Fixed ChunkedDecoder. It does not read trailer and final CRLF.
* src/ChunkedDecoder.cc
* src/ChunkedDecoder.h
* test/ChunkedDecoderTest.cc
2010-07-10 Tatsuhiro Tsujikawa <t-tujikawa@users.sourceforge.net>
Removed unusable typedefs

View File

@ -64,6 +64,27 @@ static bool readChunkSize(uint64_t& chunkSize, std::string& in)
return true;
}
static bool readTrailer(std::string& in)
{
std::string::size_type crlfPos = in.find(A2STR::CRLF);
if(crlfPos == std::string::npos) {
return false;
}
if(crlfPos == 0) {
return true;
} else {
if(in.size() > crlfPos+3) {
if(in[crlfPos+2] == '\r' && in[crlfPos+3] == '\n') {
return true;
} else {
throw DL_ABORT_EX("No CRLF at the end of chunk stream.");
}
} else {
return false;
}
}
}
static bool readData(std::string& out, uint64_t& chunkSize, std::string& in)
{
uint64_t readlen = std::min(chunkSize, static_cast<uint64_t>(in.size()));
@ -91,8 +112,7 @@ std::string ChunkedDecoder::decode(const unsigned char* inbuf, size_t inlen)
if(state_ == READ_SIZE) {
if(readChunkSize(chunkSize_, buf_)) {
if(chunkSize_ == 0) {
state_ = STREAM_END;
break;
state_ = READ_TRAILER;
} else {
state_ = READ_DATA;
}
@ -105,6 +125,13 @@ std::string ChunkedDecoder::decode(const unsigned char* inbuf, size_t inlen)
} else {
break;
}
} else if(state_ == READ_TRAILER) {
if(readTrailer(buf_)) {
state_ = STREAM_END;
break;
} else {
break;
}
}
}
return outbuf;

View File

@ -44,6 +44,7 @@ private:
enum STATE {
READ_SIZE,
READ_DATA,
READ_TRAILER,
STREAM_END
};

View File

@ -9,6 +9,7 @@ class ChunkedDecoderTest:public CppUnit::TestFixture {
CPPUNIT_TEST_SUITE(ChunkedDecoderTest);
CPPUNIT_TEST(testDecode);
CPPUNIT_TEST(testDecode_withoutTrailer);
CPPUNIT_TEST(testDecode_tooLargeChunkSize);
CPPUNIT_TEST(testDecode_chunkSizeMismatch);
CPPUNIT_TEST(testGetName);
@ -17,6 +18,7 @@ public:
void setUp() {}
void testDecode();
void testDecode_withoutTrailer();
void testDecode_tooLargeChunkSize();
void testDecode_chunkSizeMismatch();
void testGetName();
@ -102,12 +104,35 @@ void ChunkedDecoderTest::testDecode()
CPPUNIT_ASSERT_EQUAL(std::string(),
decoder.decode(msg.c_str(), msg.size()));
}
// feed trailer
{
CPPUNIT_ASSERT_EQUAL
(std::string(),
decoder.decode
(reinterpret_cast<const unsigned char*>("trailer\r\n"), 9));
}
// feed final CRLF
{
CPPUNIT_ASSERT_EQUAL
(std::string(),
decoder.decode(reinterpret_cast<const unsigned char*>("\r\n"), 2));
}
// input is over
CPPUNIT_ASSERT(decoder.finished());
decoder.release();
}
void ChunkedDecoderTest::testDecode_withoutTrailer()
{
ChunkedDecoder decoder;
decoder.init();
CPPUNIT_ASSERT_EQUAL
(std::string(),
decoder.decode(reinterpret_cast<const unsigned char*>("0\r\n\r\n"), 5));
CPPUNIT_ASSERT(decoder.finished());
}
void ChunkedDecoderTest::testDecode_tooLargeChunkSize()
{
// chunkSize should be under 2^64-1