summaryrefslogtreecommitdiffstats
path: root/net/ftp
diff options
context:
space:
mode:
authorthestig@chromium.org <thestig@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-12-07 20:50:48 +0000
committerthestig@chromium.org <thestig@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-12-07 20:50:48 +0000
commit1c9735aa8747af43bddbe8c785af05f0d55538b1 (patch)
treebd5da102813cb974f52f6aaa0cf13519c996feaf /net/ftp
parent1ccab1dde4b84910e5d42461ee1cd5004be06eff (diff)
downloadchromium_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.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());