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> 2010-07-10 Tatsuhiro Tsujikawa <t-tujikawa@users.sourceforge.net>
Removed unusable typedefs Removed unusable typedefs

View File

@ -64,6 +64,27 @@ static bool readChunkSize(uint64_t& chunkSize, std::string& in)
return true; 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) static bool readData(std::string& out, uint64_t& chunkSize, std::string& in)
{ {
uint64_t readlen = std::min(chunkSize, static_cast<uint64_t>(in.size())); 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(state_ == READ_SIZE) {
if(readChunkSize(chunkSize_, buf_)) { if(readChunkSize(chunkSize_, buf_)) {
if(chunkSize_ == 0) { if(chunkSize_ == 0) {
state_ = STREAM_END; state_ = READ_TRAILER;
break;
} else { } else {
state_ = READ_DATA; state_ = READ_DATA;
} }
@ -105,6 +125,13 @@ std::string ChunkedDecoder::decode(const unsigned char* inbuf, size_t inlen)
} else { } else {
break; break;
} }
} else if(state_ == READ_TRAILER) {
if(readTrailer(buf_)) {
state_ = STREAM_END;
break;
} else {
break;
}
} }
} }
return outbuf; return outbuf;

View File

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

View File

@ -9,6 +9,7 @@ class ChunkedDecoderTest:public CppUnit::TestFixture {
CPPUNIT_TEST_SUITE(ChunkedDecoderTest); CPPUNIT_TEST_SUITE(ChunkedDecoderTest);
CPPUNIT_TEST(testDecode); CPPUNIT_TEST(testDecode);
CPPUNIT_TEST(testDecode_withoutTrailer);
CPPUNIT_TEST(testDecode_tooLargeChunkSize); CPPUNIT_TEST(testDecode_tooLargeChunkSize);
CPPUNIT_TEST(testDecode_chunkSizeMismatch); CPPUNIT_TEST(testDecode_chunkSizeMismatch);
CPPUNIT_TEST(testGetName); CPPUNIT_TEST(testGetName);
@ -17,6 +18,7 @@ public:
void setUp() {} void setUp() {}
void testDecode(); void testDecode();
void testDecode_withoutTrailer();
void testDecode_tooLargeChunkSize(); void testDecode_tooLargeChunkSize();
void testDecode_chunkSizeMismatch(); void testDecode_chunkSizeMismatch();
void testGetName(); void testGetName();
@ -102,12 +104,35 @@ void ChunkedDecoderTest::testDecode()
CPPUNIT_ASSERT_EQUAL(std::string(), CPPUNIT_ASSERT_EQUAL(std::string(),
decoder.decode(msg.c_str(), msg.size())); 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 // input is over
CPPUNIT_ASSERT(decoder.finished()); CPPUNIT_ASSERT(decoder.finished());
decoder.release(); 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() void ChunkedDecoderTest::testDecode_tooLargeChunkSize()
{ {
// chunkSize should be under 2^64-1 // chunkSize should be under 2^64-1