diff options
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()); |