summaryrefslogtreecommitdiffstats
path: root/net/ftp
diff options
context:
space:
mode:
Diffstat (limited to 'net/ftp')
-rw-r--r--net/ftp/ftp_ctrl_response_buffer.cc34
-rw-r--r--net/ftp/ftp_ctrl_response_buffer.h6
-rw-r--r--net/ftp/ftp_ctrl_response_buffer_unittest.cc19
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());