diff --git a/ChangeLog b/ChangeLog index 1da163fb..1e135c3a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,11 @@ +2008-09-14 Tatsuhiro Tsujikawa + + Added upper limit of FTP response buffer. The current implementation + uses 4096bytes as a limit. + * src/FtpConnection.cc + * src/FtpConnection.h + * test/FtpConnectionTest.cc + 2008-09-14 Tatsuhiro Tsujikawa Use non-blocking socket for TCP communication to avoid possible diff --git a/src/FtpConnection.cc b/src/FtpConnection.cc index ac052a9b..35a437b9 100644 --- a/src/FtpConnection.cc +++ b/src/FtpConnection.cc @@ -47,6 +47,7 @@ #include "DlAbortEx.h" #include "Socket.h" #include "A2STR.h" +#include "StringFormat.h" #include #include @@ -265,13 +266,16 @@ bool FtpConnection::bulkReceiveResponse(std::pair& re { char buf[1024]; while(socket->isReadable(0)) { - size_t size = sizeof(buf)-1; + size_t size = sizeof(buf); socket->readData(buf, size); if(size == 0) { throw DlRetryEx(EX_GOT_EOF); } - buf[size] = '\0'; - strbuf += buf; + if(strbuf.size()+size > MAX_RECV_BUFFER) { + throw DlRetryEx(StringFormat("Max FTP recv buffer reached. length=%zu", + strbuf.size()+size).str()); + } + strbuf.append(&buf[0], &buf[size]); } unsigned int status; if(strbuf.size() >= 4) { diff --git a/src/FtpConnection.h b/src/FtpConnection.h index 78a586d1..b88bdc0e 100644 --- a/src/FtpConnection.h +++ b/src/FtpConnection.h @@ -71,6 +71,7 @@ private: static const std::string I; + static const size_t MAX_RECV_BUFFER = 4096; public: FtpConnection(int32_t cuid, const SharedHandle& socket, const SharedHandle& req, const Option* op); diff --git a/test/FtpConnectionTest.cc b/test/FtpConnectionTest.cc index 2cf9056e..5a764f8b 100644 --- a/test/FtpConnectionTest.cc +++ b/test/FtpConnectionTest.cc @@ -4,7 +4,9 @@ #include "SocketCore.h" #include "Request.h" #include "Option.h" +#include "DlRetryEx.h" #include +#include #include namespace aria2 { @@ -13,6 +15,7 @@ class FtpConnectionTest:public CppUnit::TestFixture { CPPUNIT_TEST_SUITE(FtpConnectionTest); CPPUNIT_TEST(testReceiveResponse); + CPPUNIT_TEST(testReceiveResponse_overflow); CPPUNIT_TEST(testSendMdtm); CPPUNIT_TEST(testReceiveMdtmResponse); CPPUNIT_TEST_SUITE_END(); @@ -50,6 +53,7 @@ public: void testSendMdtm(); void testReceiveMdtmResponse(); void testReceiveResponse(); + void testReceiveResponse_overflow(); }; @@ -137,4 +141,22 @@ void FtpConnectionTest::testReceiveMdtmResponse() } } +void FtpConnectionTest::testReceiveResponse_overflow() +{ + char data[1024]; + memset(data, 0, sizeof(data)); + memcpy(data, "213 ", 4); + for(int i = 0; i < 4; ++i) { + _serverSocket->writeData(data, sizeof(data)); + CPPUNIT_ASSERT_EQUAL((unsigned int)0, _ftp->receiveResponse()); + } + _serverSocket->writeData(data, sizeof(data)); + try { + _ftp->receiveResponse(); + CPPUNIT_FAIL("exception must be thrown."); + } catch(DlRetryEx& e) { + // success + } +} + } // namespace aria2