From 5bff877eaeb11ef0db72c570768e3b1f9256a7c2 Mon Sep 17 00:00:00 2001 From: Tatsuhiro Tsujikawa Date: Mon, 5 Mar 2012 12:45:05 +0900 Subject: [PATCH] Fixed assertion failure if Chunked encoding along with Content-Length is used. --- src/SinkStreamFilter.cc | 20 ++++++-- test/Makefile.am | 3 +- test/SinkStreamFilterTest.cc | 94 ++++++++++++++++++++++++++++++++++++ 3 files changed, 112 insertions(+), 5 deletions(-) create mode 100644 test/SinkStreamFilterTest.cc diff --git a/src/SinkStreamFilter.cc b/src/SinkStreamFilter.cc index dadec822..089cf37e 100644 --- a/src/SinkStreamFilter.cc +++ b/src/SinkStreamFilter.cc @@ -49,16 +49,28 @@ ssize_t SinkStreamFilter::transform const SharedHandle& segment, const unsigned char* inbuf, size_t inlen) { + size_t wlen; if(inlen > 0) { - out->writeData(inbuf, inlen, segment->getPositionToWrite()); + if(segment->getLength() > 0) { + // We must not write data larger than available space in + // segment. + assert(segment->getLength() >= segment->getWrittenLength()); + size_t lenAvail = segment->getLength()-segment->getWrittenLength(); + wlen = std::min(inlen, lenAvail); + } else { + wlen = inlen; + } + out->writeData(inbuf, wlen, segment->getPositionToWrite()); #ifdef ENABLE_MESSAGE_DIGEST if(hashUpdate_) { - segment->updateHash(segment->getWrittenLength(), inbuf, inlen); + segment->updateHash(segment->getWrittenLength(), inbuf, wlen); } #endif // ENABLE_MESSAGE_DIGEST - segment->updateWrittenLength(inlen); + segment->updateWrittenLength(wlen); + } else { + wlen = 0; } - bytesProcessed_ = inlen; + bytesProcessed_ = wlen; return bytesProcessed_; } diff --git a/test/Makefile.am b/test/Makefile.am index 5e328c8c..5164b372 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -81,7 +81,8 @@ aria2c_SOURCES = AllTest.cc\ SegListTest.cc\ ParamedStringTest.cc\ RpcHelperTest.cc\ - AbstractCommandTest.cc + AbstractCommandTest.cc\ + SinkStreamFilterTest.cc if ENABLE_XML_RPC aria2c_SOURCES += XmlRpcRequestParserControllerTest.cc diff --git a/test/SinkStreamFilterTest.cc b/test/SinkStreamFilterTest.cc new file mode 100644 index 00000000..91bc6bfc --- /dev/null +++ b/test/SinkStreamFilterTest.cc @@ -0,0 +1,94 @@ +#include "SinkStreamFilter.h" + +#include +#include +#include + +#include "Segment.h" +#include "ByteArrayDiskWriter.h" +#include "SinkStreamFilter.h" +#include "MockSegment.h" + +namespace aria2 { + +class SinkStreamFilterTest:public CppUnit::TestFixture { + + CPPUNIT_TEST_SUITE(SinkStreamFilterTest); + CPPUNIT_TEST(testTransform_with_length); + CPPUNIT_TEST(testTransform_without_length); + CPPUNIT_TEST_SUITE_END(); + + class MockSegment2:public MockSegment { + public: + MockSegment2(int32_t length):length(length), writtenLength(0) {} + + virtual int32_t getLength() const + { + return length; + } + + virtual int32_t getWrittenLength() const + { + return writtenLength; + } + + virtual void updateWrittenLength(int32_t bytes) + { + writtenLength += bytes; + } + + int32_t length; + int32_t writtenLength; + }; + + SharedHandle filter_; + SharedHandle sinkFilter_; + SharedHandle writer_; + SharedHandle segment_; + + void clearWriter() + { + writer_->setString(""); + } +public: + void setUp() + { + writer_.reset(new ByteArrayDiskWriter()); + sinkFilter_.reset(new SinkStreamFilter()); + filter_.reset(new SinkStreamFilter(sinkFilter_)); + sinkFilter_->init(); + filter_->init(); + segment_.reset(new MockSegment2(16)); + } + + void testTransform_with_length(); + void testTransform_without_length(); +}; + + +CPPUNIT_TEST_SUITE_REGISTRATION( SinkStreamFilterTest ); + +void SinkStreamFilterTest::testTransform_with_length() +{ + // If segment_->getLength() > 0, make sure that at most + // segment_->getLength()-segment_->getWrittenLength() bytes are + // written. + std::string msg("01234567890123456"); + ssize_t r = filter_->transform + (writer_, segment_, + reinterpret_cast(msg.c_str()), msg.size()); + CPPUNIT_ASSERT_EQUAL((ssize_t)16, r); +} + +void SinkStreamFilterTest::testTransform_without_length() +{ + // If segment_->getLength() == 0, all incoming bytes are written. + segment_->length = 0; + std::string msg("01234567890123456"); + ssize_t r = filter_->transform + (writer_, segment_, + reinterpret_cast(msg.c_str()), msg.size()); + CPPUNIT_ASSERT_EQUAL((ssize_t)17, r); +} + +} // namespace aria2