diff options
author | thestig@chromium.org <thestig@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-12-07 20:50:48 +0000 |
---|---|---|
committer | thestig@chromium.org <thestig@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-12-07 20:50:48 +0000 |
commit | 1c9735aa8747af43bddbe8c785af05f0d55538b1 (patch) | |
tree | bd5da102813cb974f52f6aaa0cf13519c996feaf /net/ftp | |
parent | 1ccab1dde4b84910e5d42461ee1cd5004be06eff (diff) | |
download | chromium_src-1c9735aa8747af43bddbe8c785af05f0d55538b1.zip chromium_src-1c9735aa8747af43bddbe8c785af05f0d55538b1.tar.gz chromium_src-1c9735aa8747af43bddbe8c785af05f0d55538b1.tar.bz2 |
net/ftp: Fix control response parsing for a corner cases where the first line of a continuation has 0 length.
BUG=29322
TEST=ftp://sourceware.org works.
Review URL: http://codereview.chromium.org/467032
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@33986 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'net/ftp')
-rw-r--r-- | net/ftp/ftp_ctrl_response_buffer.cc | 34 | ||||
-rw-r--r-- | net/ftp/ftp_ctrl_response_buffer.h | 6 | ||||
-rw-r--r-- | net/ftp/ftp_ctrl_response_buffer_unittest.cc | 19 |
3 files changed, 42 insertions, 17 deletions
diff --git a/net/ftp/ftp_ctrl_response_buffer.cc b/net/ftp/ftp_ctrl_response_buffer.cc index 02bbd08..8ea58cc 100644 --- a/net/ftp/ftp_ctrl_response_buffer.cc +++ b/net/ftp/ftp_ctrl_response_buffer.cc @@ -21,22 +21,7 @@ int FtpCtrlResponseBuffer::ConsumeData(const char* data, int data_length) { ParsedLine line = lines_.front(); lines_.pop(); - if (line_buf_.empty()) { - if (!line.is_complete) - return ERR_INVALID_RESPONSE; - - response_buf_.status_code = line.status_code; - if (line.is_multiline) { - line_buf_ = line.status_text; - } else { - response_buf_.lines.push_back(line.status_text); - responses_.push(response_buf_); - - // Prepare to handle following lines. - response_buf_ = FtpCtrlResponse(); - line_buf_.clear(); - } - } else { + if (multiline_) { if (!line.is_complete || line.status_code != response_buf_.status_code) { line_buf_.append(line.raw_text); continue; @@ -54,6 +39,23 @@ int FtpCtrlResponseBuffer::ConsumeData(const char* data, int data_length) { // Prepare to handle following lines. response_buf_ = FtpCtrlResponse(); line_buf_.clear(); + multiline_ = false; + } + } else { + if (!line.is_complete) + return ERR_INVALID_RESPONSE; + + response_buf_.status_code = line.status_code; + if (line.is_multiline) { + line_buf_ = line.status_text; + multiline_ = true; + } else { + response_buf_.lines.push_back(line.status_text); + responses_.push(response_buf_); + + // Prepare to handle following lines. + response_buf_ = FtpCtrlResponse(); + line_buf_.clear(); } } } diff --git a/net/ftp/ftp_ctrl_response_buffer.h b/net/ftp/ftp_ctrl_response_buffer.h index 66aae8b..6ea34cb 100644 --- a/net/ftp/ftp_ctrl_response_buffer.h +++ b/net/ftp/ftp_ctrl_response_buffer.h @@ -24,7 +24,8 @@ struct FtpCtrlResponse { class FtpCtrlResponseBuffer { public: - FtpCtrlResponseBuffer() {} + FtpCtrlResponseBuffer() : multiline_(false) { + } // Called when data is received from the control socket. Returns error code. int ConsumeData(const char* data, int data_length); @@ -81,6 +82,9 @@ class FtpCtrlResponseBuffer { std::queue<ParsedLine> lines_; + // True if we are in the middle of parsing a multi-line response. + bool multiline_; + // When parsing a multiline response, we don't know beforehand if a line // will have a continuation. So always store last line of multiline response // so we can append the continuation to it. diff --git a/net/ftp/ftp_ctrl_response_buffer_unittest.cc b/net/ftp/ftp_ctrl_response_buffer_unittest.cc index c2aeee2..1477c09 100644 --- a/net/ftp/ftp_ctrl_response_buffer_unittest.cc +++ b/net/ftp/ftp_ctrl_response_buffer_unittest.cc @@ -96,6 +96,25 @@ TEST_F(FtpCtrlResponseBufferTest, MultilineContinuation) { EXPECT_EQ("LastLine", response.lines[2]); } +TEST_F(FtpCtrlResponseBufferTest, MultilineContinuationZeroLength) { + // For the corner case from bug 29322. + EXPECT_EQ(net::OK, PushDataToBuffer("230-\r\n")); + EXPECT_FALSE(buffer_.ResponseAvailable()); + + EXPECT_EQ(net::OK, PushDataToBuffer("example.com\r\n")); + EXPECT_FALSE(buffer_.ResponseAvailable()); + + EXPECT_EQ(net::OK, PushDataToBuffer("230 LastLine\r\n")); + EXPECT_TRUE(buffer_.ResponseAvailable()); + + net::FtpCtrlResponse response = buffer_.PopResponse(); + EXPECT_FALSE(buffer_.ResponseAvailable()); + EXPECT_EQ(230, response.status_code); + ASSERT_EQ(2U, response.lines.size()); + EXPECT_EQ("example.com", response.lines[0]); + EXPECT_EQ("LastLine", response.lines[1]); +} + TEST_F(FtpCtrlResponseBufferTest, SimilarContinuation) { EXPECT_EQ(net::OK, PushDataToBuffer("230-FirstLine\r\n")); EXPECT_FALSE(buffer_.ResponseAvailable()); |