summaryrefslogtreecommitdiff
path: root/chromium/net/server
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@qt.io>2017-04-05 17:15:33 +0200
committerAllan Sandfeld Jensen <allan.jensen@qt.io>2017-04-11 07:47:18 +0000
commit7324afb043a0b1e623d8e8eb906cdc53bdeb4685 (patch)
treea3fe2d74ea9c9e142c390dac4ca0e219382ace46 /chromium/net/server
parent6a4cabb866f66d4128a97cdc6d9d08ce074f1247 (diff)
downloadqtwebengine-chromium-7324afb043a0b1e623d8e8eb906cdc53bdeb4685.tar.gz
BASELINE: Update Chromium to 58.0.3029.54
Change-Id: I67f57065a7afdc8e4614adb5c0230281428df4d1 Reviewed-by: Peter Varga <pvarga@inf.u-szeged.hu>
Diffstat (limited to 'chromium/net/server')
-rw-r--r--chromium/net/server/http_server.cc4
-rw-r--r--chromium/net/server/http_server_fuzzer.cc109
-rw-r--r--chromium/net/server/http_server_unittest.cc72
-rw-r--r--chromium/net/server/web_socket.cc11
4 files changed, 185 insertions, 11 deletions
diff --git a/chromium/net/server/http_server.cc b/chromium/net/server/http_server.cc
index 7300a38f8c1..77c2c0d9b6c 100644
--- a/chromium/net/server/http_server.cc
+++ b/chromium/net/server/http_server.cc
@@ -449,8 +449,8 @@ bool HttpServer::ParseHeaders(const char* data,
buffer.append(&ch, 1);
break;
case ST_DONE:
- DCHECK(input == INPUT_LF);
- return true;
+ // We got CR to get this far, also need the LF
+ return (input == INPUT_LF);
case ST_ERR:
return false;
}
diff --git a/chromium/net/server/http_server_fuzzer.cc b/chromium/net/server/http_server_fuzzer.cc
new file mode 100644
index 00000000000..55cdaf8661f
--- /dev/null
+++ b/chromium/net/server/http_server_fuzzer.cc
@@ -0,0 +1,109 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/logging.h"
+#include "base/macros.h"
+#include "base/memory/ptr_util.h"
+#include "base/run_loop.h"
+#include "base/test/fuzzed_data_provider.h"
+#include "net/base/net_errors.h"
+#include "net/log/test_net_log.h"
+#include "net/server/http_server.h"
+#include "net/socket/fuzzed_server_socket.h"
+
+namespace {
+
+class WaitTillHttpCloseDelegate : public net::HttpServer::Delegate {
+ public:
+ WaitTillHttpCloseDelegate(base::FuzzedDataProvider* data_provider,
+ const base::Closure& done_closure)
+ : server_(nullptr),
+ data_provider_(data_provider),
+ done_closure_(done_closure),
+ action_flags_(data_provider_->ConsumeUint8()) {}
+
+ void set_server(net::HttpServer* server) { server_ = server; }
+
+ void OnConnect(int connection_id) override {
+ if (!(action_flags_ & ACCEPT_CONNECTION))
+ server_->Close(connection_id);
+ }
+
+ void OnHttpRequest(int connection_id,
+ const net::HttpServerRequestInfo& info) override {
+ if (!(action_flags_ & ACCEPT_MESSAGE)) {
+ server_->Close(connection_id);
+ return;
+ }
+
+ if (action_flags_ & REPLY_TO_MESSAGE) {
+ server_->Send200(connection_id,
+ data_provider_->ConsumeRandomLengthString(64),
+ "text/html");
+ }
+ }
+
+ void OnWebSocketRequest(int connection_id,
+ const net::HttpServerRequestInfo& info) override {
+ if (action_flags_ & CLOSE_WEBSOCKET_RATHER_THAN_ACCEPT) {
+ server_->Close(connection_id);
+ return;
+ }
+
+ if (action_flags_ & ACCEPT_WEBSOCKET)
+ server_->AcceptWebSocket(connection_id, info);
+ }
+
+ void OnWebSocketMessage(int connection_id, const std::string& data) override {
+ if (!(action_flags_ & ACCEPT_MESSAGE)) {
+ server_->Close(connection_id);
+ return;
+ }
+
+ if (action_flags_ & REPLY_TO_MESSAGE) {
+ server_->SendOverWebSocket(connection_id,
+ data_provider_->ConsumeRandomLengthString(64));
+ }
+ }
+
+ void OnClose(int connection_id) override { done_closure_.Run(); }
+
+ private:
+ enum {
+ ACCEPT_CONNECTION = 1,
+ ACCEPT_MESSAGE = 2,
+ REPLY_TO_MESSAGE = 4,
+ ACCEPT_WEBSOCKET = 8,
+ CLOSE_WEBSOCKET_RATHER_THAN_ACCEPT = 16
+ };
+
+ net::HttpServer* server_;
+ base::FuzzedDataProvider* const data_provider_;
+ base::Closure done_closure_;
+ const uint8_t action_flags_;
+
+ DISALLOW_COPY_AND_ASSIGN(WaitTillHttpCloseDelegate);
+};
+
+} // namespace
+
+// Fuzzer for HttpServer
+//
+// |data| is used to create a FuzzedServerSocket.
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+ net::TestNetLog test_net_log;
+ base::FuzzedDataProvider data_provider(data, size);
+
+ std::unique_ptr<net::ServerSocket> server_socket(
+ base::MakeUnique<net::FuzzedServerSocket>(&data_provider, &test_net_log));
+ CHECK_EQ(net::OK,
+ server_socket->ListenWithAddressAndPort("127.0.0.1", 80, 5));
+
+ base::RunLoop run_loop;
+ WaitTillHttpCloseDelegate delegate(&data_provider, run_loop.QuitClosure());
+ net::HttpServer server(std::move(server_socket), &delegate);
+ delegate.set_server(&server);
+ run_loop.Run();
+ return 0;
+}
diff --git a/chromium/net/server/http_server_unittest.cc b/chromium/net/server/http_server_unittest.cc
index 9b6dee1bea9..a9168c91374 100644
--- a/chromium/net/server/http_server_unittest.cc
+++ b/chromium/net/server/http_server_unittest.cc
@@ -133,6 +133,17 @@ class TestHttpClient {
return true;
}
+ void ExpectUsedThenDisconnectedWithNoData() {
+ // Check that the socket was opened...
+ ASSERT_TRUE(socket_->WasEverUsed());
+
+ // ...then closed when the server disconnected. Verify that the socket was
+ // closed by checking that a Read() fails.
+ std::string response;
+ ASSERT_FALSE(Read(&response, 1u));
+ ASSERT_TRUE(response.empty());
+ }
+
TCPClientSocket& socket() { return *socket_; }
private:
@@ -191,7 +202,8 @@ class TestHttpClient {
class HttpServerTest : public testing::Test,
public HttpServer::Delegate {
public:
- HttpServerTest() : quit_after_request_count_(0) {}
+ HttpServerTest()
+ : quit_after_request_count_(0), quit_on_close_connection_(-1) {}
void SetUp() override {
std::unique_ptr<ServerSocket> server_socket(
@@ -201,6 +213,12 @@ class HttpServerTest : public testing::Test,
ASSERT_THAT(server_->GetLocalAddress(&server_address_), IsOk());
}
+ void TearDown() override {
+ // Run the event loop some to make sure that the memory handed over to
+ // DeleteSoon gets fully freed.
+ base::RunLoop().RunUntilIdle();
+ }
+
void OnConnect(int connection_id) override {
DCHECK(connection_map_.find(connection_id) == connection_map_.end());
connection_map_[connection_id] = true;
@@ -225,6 +243,8 @@ class HttpServerTest : public testing::Test,
void OnClose(int connection_id) override {
DCHECK(connection_map_.find(connection_id) != connection_map_.end());
connection_map_[connection_id] = false;
+ if (connection_id == quit_on_close_connection_)
+ run_loop_quit_func_.Run();
}
bool RunUntilRequestsReceived(size_t count) {
@@ -239,10 +259,27 @@ class HttpServerTest : public testing::Test,
return success;
}
+ bool RunUntilConnectionIdClosed(int connection_id) {
+ quit_on_close_connection_ = connection_id;
+ auto iter = connection_map_.find(connection_id);
+ if (iter != connection_map_.end() && !iter->second) {
+ // Already disconnected.
+ return true;
+ }
+
+ base::RunLoop run_loop;
+ run_loop_quit_func_ = run_loop.QuitClosure();
+ bool success = RunLoopWithTimeout(&run_loop);
+ run_loop_quit_func_.Reset();
+ return success;
+ }
+
HttpServerRequestInfo GetRequest(size_t request_index) {
return requests_[request_index].first;
}
+ size_t num_requests() const { return requests_.size(); }
+
int GetConnectionId(size_t request_index) {
return requests_[request_index].second;
}
@@ -264,6 +301,7 @@ class HttpServerTest : public testing::Test,
private:
size_t quit_after_request_count_;
+ int quit_on_close_connection_;
};
namespace {
@@ -296,6 +334,15 @@ TEST_F(HttpServerTest, Request) {
base::CompareCase::SENSITIVE));
}
+TEST_F(HttpServerTest, RequestBrokenTermination) {
+ TestHttpClient client;
+ ASSERT_THAT(client.ConnectAndWait(server_address_), IsOk());
+ client.Send("GET /test HTTP/1.1\r\n\r)");
+ ASSERT_TRUE(RunUntilConnectionIdClosed(1));
+ EXPECT_EQ(0u, num_requests());
+ client.ExpectUsedThenDisconnectedWithNoData();
+}
+
TEST_F(HttpServerTest, RequestWithHeaders) {
TestHttpClient client;
ASSERT_THAT(client.ConnectAndWait(server_address_), IsOk());
@@ -421,6 +468,20 @@ TEST_F(WebSocketTest, RequestWebSocket) {
ASSERT_TRUE(RunUntilRequestsReceived(1));
}
+TEST_F(WebSocketTest, RequestWebSocketTrailingJunk) {
+ TestHttpClient client;
+ ASSERT_THAT(client.ConnectAndWait(server_address_), IsOk());
+ client.Send(
+ "GET /test HTTP/1.1\r\n"
+ "Upgrade: WebSocket\r\n"
+ "Connection: SomethingElse, Upgrade\r\n"
+ "Sec-WebSocket-Version: 8\r\n"
+ "Sec-WebSocket-Key: key\r\n"
+ "\r\nHello? Anyone");
+ ASSERT_TRUE(RunUntilConnectionIdClosed(1));
+ client.ExpectUsedThenDisconnectedWithNoData();
+}
+
TEST_F(HttpServerTest, RequestWithTooLargeBody) {
class TestURLFetcherDelegate : public URLFetcherDelegate {
public:
@@ -503,14 +564,7 @@ TEST_F(HttpServerTest, WrongProtocolRequest) {
ASSERT_EQ(1u, connection_map().size());
ASSERT_FALSE(connection_map().begin()->second);
- // Assert that the socket was opened...
- ASSERT_TRUE(client.socket().WasEverUsed());
-
- // ...then closed when the server disconnected. Verify that the socket was
- // closed by checking that a Read() fails.
- std::string response;
- ASSERT_FALSE(client.Read(&response, 1u));
- ASSERT_EQ(std::string(), response);
+ client.ExpectUsedThenDisconnectedWithNoData();
// Reset the state of the connection map.
connection_map().clear();
diff --git a/chromium/net/server/web_socket.cc b/chromium/net/server/web_socket.cc
index 79ffcecb7ad..bd3d9e494ab 100644
--- a/chromium/net/server/web_socket.cc
+++ b/chromium/net/server/web_socket.cc
@@ -98,6 +98,17 @@ WebSocket::ParseResult WebSocket::Read(std::string* message) {
if (closed_)
return FRAME_CLOSE;
+ if (!encoder_) {
+ // RFC6455, section 4.1 says "Once the client's opening handshake has been
+ // sent, the client MUST wait for a response from the server before sending
+ // any further data". If |encoder_| is null here, ::Accept either has not
+ // been called at all, or has rejected a request rather than producing
+ // a server handshake. Either way, the client clearly couldn't have gotten
+ // a proper server handshake, so error out, especially since this method
+ // can't proceed without an |encoder_|.
+ return FRAME_ERROR;
+ }
+
HttpConnection::ReadIOBuffer* read_buf = connection_->read_buf();
base::StringPiece frame(read_buf->StartOfBuffer(), read_buf->GetSize());
int bytes_consumed = 0;