Skip to content

Commit

Permalink
[Merge M92] Speculative fix for crash in URLLoader::OnBeforeSendHeade…
Browse files Browse the repository at this point in the history
…rsComplete

I wasn't able to reproduce the crash, but this should prevent crashing
when accessing an invalid pointer for the HttpRequestHeaders. Instead of
passing a raw pointer, OnBeforeStartTransaction will now take optional
headers in the callback to modify the extra headers. If the job has been
destroyed, the callback will not be run since it was bound with a
WeakPtr to the job.

(cherry picked from commit c06b392)

Bug: 1221047
Change-Id: I93d5838b778e7283f7043fd2c841844941f52a85
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3042975
Commit-Queue: Clark DuVall <cduvall@chromium.org>
Reviewed-by: Matt Mueller <mattm@chromium.org>
Cr-Original-Commit-Position: refs/heads/master@{#905539}
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3108058
Auto-Submit: Clark DuVall <cduvall@chromium.org>
Cr-Commit-Position: refs/branch-heads/4515@{#2070}
Cr-Branched-From: 488fc70-refs/heads/master@{#885287}
  • Loading branch information
clarkduvall authored and Chromium LUCI CQ committed Aug 20, 2021
1 parent 6dbabb7 commit d1eade9
Show file tree
Hide file tree
Showing 18 changed files with 107 additions and 87 deletions.
7 changes: 3 additions & 4 deletions net/base/network_delegate.cc
Original file line number Diff line number Diff line change
Expand Up @@ -35,14 +35,13 @@ int NetworkDelegate::NotifyBeforeURLRequest(URLRequest* request,

int NetworkDelegate::NotifyBeforeStartTransaction(
URLRequest* request,
CompletionOnceCallback callback,
HttpRequestHeaders* headers) {
const HttpRequestHeaders& headers,
OnBeforeStartTransactionCallback callback) {
TRACE_EVENT0(NetTracingCategory(),
"NetworkDelegate::NotifyBeforeStartTransation");
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
DCHECK(headers);
DCHECK(!callback.is_null());
return OnBeforeStartTransaction(request, std::move(callback), headers);
return OnBeforeStartTransaction(request, headers, std::move(callback));
}

int NetworkDelegate::NotifyHeadersReceived(
Expand Down
19 changes: 11 additions & 8 deletions net/base/network_delegate.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,9 +55,11 @@ class NET_EXPORT NetworkDelegate {
int NotifyBeforeURLRequest(URLRequest* request,
CompletionOnceCallback callback,
GURL* new_url);
using OnBeforeStartTransactionCallback =
base::OnceCallback<void(int, const absl::optional<HttpRequestHeaders>&)>;
int NotifyBeforeStartTransaction(URLRequest* request,
CompletionOnceCallback callback,
HttpRequestHeaders* headers);
const HttpRequestHeaders& headers,
OnBeforeStartTransactionCallback callback);
int NotifyHeadersReceived(
URLRequest* request,
CompletionOnceCallback callback,
Expand Down Expand Up @@ -132,7 +134,8 @@ class NET_EXPORT NetworkDelegate {
GURL* new_url) = 0;

// Called right before the network transaction starts. Allows the delegate to
// read/write |headers| before they get sent out.
// read |headers| and modify them by passing a new copy to |callback| before
// they get sent out.
//
// Returns OK to continue with the request, ERR_IO_PENDING if the result is
// not ready yet, and any other status code to cancel the request. If
Expand All @@ -141,11 +144,11 @@ class NET_EXPORT NetworkDelegate {
// or OnCompleted. Once cancelled, |request| and |headers| become invalid and
// |callback| may not be called.
//
// The default implementation returns OK (continue with request) without
// modifying |headers|.
virtual int OnBeforeStartTransaction(URLRequest* request,
CompletionOnceCallback callback,
HttpRequestHeaders* headers) = 0;
// The default implementation returns OK (continue with request).
virtual int OnBeforeStartTransaction(
URLRequest* request,
const HttpRequestHeaders& headers,
OnBeforeStartTransactionCallback callback) = 0;

// Called for HTTP requests when the headers have been received.
// |original_response_headers| contains the headers as received over the
Expand Down
4 changes: 2 additions & 2 deletions net/base/network_delegate_impl.cc
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ int NetworkDelegateImpl::OnBeforeURLRequest(URLRequest* request,

int NetworkDelegateImpl::OnBeforeStartTransaction(
URLRequest* request,
CompletionOnceCallback callback,
HttpRequestHeaders* headers) {
const HttpRequestHeaders& headers,
OnBeforeStartTransactionCallback callback) {
return OK;
}

Expand Down
7 changes: 4 additions & 3 deletions net/base/network_delegate_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,10 @@ class NET_EXPORT NetworkDelegateImpl : public NetworkDelegate {
CompletionOnceCallback callback,
GURL* new_url) override;

int OnBeforeStartTransaction(URLRequest* request,
CompletionOnceCallback callback,
HttpRequestHeaders* headers) override;
int OnBeforeStartTransaction(
URLRequest* request,
const HttpRequestHeaders& headers,
OnBeforeStartTransactionCallback callback) override;

int OnHeadersReceived(
URLRequest* request,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,10 @@ class TestNetworkDelegate : public NetworkDelegateImpl {
GURL* new_url) override {
return OK;
}
int OnBeforeStartTransaction(URLRequest* request,
CompletionOnceCallback callback,
HttpRequestHeaders* headers) override {
int OnBeforeStartTransaction(
URLRequest* request,
const HttpRequestHeaders& headers,
OnBeforeStartTransactionCallback callback) override {
return OK;
}
int OnHeadersReceived(
Expand Down
7 changes: 4 additions & 3 deletions net/proxy_resolution/pac_file_fetcher_impl_unittest.cc
Original file line number Diff line number Diff line change
Expand Up @@ -146,9 +146,10 @@ class BasicNetworkDelegate : public NetworkDelegateImpl {
return OK;
}

int OnBeforeStartTransaction(URLRequest* request,
CompletionOnceCallback callback,
HttpRequestHeaders* headers) override {
int OnBeforeStartTransaction(
URLRequest* request,
const HttpRequestHeaders& headers,
OnBeforeStartTransactionCallback callback) override {
return OK;
}

Expand Down
7 changes: 4 additions & 3 deletions net/url_request/url_request_context_builder.cc
Original file line number Diff line number Diff line change
Expand Up @@ -80,9 +80,10 @@ class BasicNetworkDelegate : public NetworkDelegateImpl {
return OK;
}

int OnBeforeStartTransaction(URLRequest* request,
CompletionOnceCallback callback,
HttpRequestHeaders* headers) override {
int OnBeforeStartTransaction(
URLRequest* request,
const HttpRequestHeaders& headers,
OnBeforeStartTransactionCallback callback) override {
return OK;
}

Expand Down
15 changes: 7 additions & 8 deletions net/url_request/url_request_http_job.cc
Original file line number Diff line number Diff line change
Expand Up @@ -391,15 +391,10 @@ void URLRequestHttpJob::StartTransaction() {
if (network_delegate) {
OnCallToDelegate(
NetLogEventType::NETWORK_DELEGATE_BEFORE_START_TRANSACTION);
// The NetworkDelegate must watch for OnRequestDestroyed and not modify
// |extra_headers| after it's called.
// TODO(mattm): change the API to remove the out-params and take the
// results as params of the callback.
int rv = network_delegate->NotifyBeforeStartTransaction(
request_,
request_, request_info_.extra_headers,
base::BindOnce(&URLRequestHttpJob::NotifyBeforeStartTransactionCallback,
weak_factory_.GetWeakPtr()),
&request_info_.extra_headers);
weak_factory_.GetWeakPtr()));
// If an extension blocks the request, we rely on the callback to
// MaybeStartTransactionInternal().
if (rv == ERR_IO_PENDING)
Expand All @@ -410,10 +405,14 @@ void URLRequestHttpJob::StartTransaction() {
StartTransactionInternal();
}

void URLRequestHttpJob::NotifyBeforeStartTransactionCallback(int result) {
void URLRequestHttpJob::NotifyBeforeStartTransactionCallback(
int result,
const absl::optional<HttpRequestHeaders>& headers) {
// The request should not have been cancelled or have already completed.
DCHECK(!is_done());

if (headers)
request_info_.extra_headers = headers.value();
MaybeStartTransactionInternal(result);
}

Expand Down
4 changes: 3 additions & 1 deletion net/url_request/url_request_http_job.h
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,9 @@ class NET_EXPORT_PRIVATE URLRequestHttpJob : public URLRequestJob {
void OnHeadersReceivedCallback(int result);
void OnStartCompleted(int result);
void OnReadCompleted(int result);
void NotifyBeforeStartTransactionCallback(int result);
void NotifyBeforeStartTransactionCallback(
int result,
const absl::optional<HttpRequestHeaders>& headers);
// This just forwards the call to URLRequestJob::NotifyConnected().
// We need it because that method is protected and cannot be bound in a
// callback in this class.
Expand Down
4 changes: 2 additions & 2 deletions net/url_request/url_request_test_util.cc
Original file line number Diff line number Diff line change
Expand Up @@ -450,8 +450,8 @@ int TestNetworkDelegate::OnBeforeURLRequest(URLRequest* request,

int TestNetworkDelegate::OnBeforeStartTransaction(
URLRequest* request,
CompletionOnceCallback callback,
HttpRequestHeaders* headers) {
const HttpRequestHeaders& headers,
OnBeforeStartTransactionCallback callback) {
if (before_start_transaction_fails_)
return ERR_FAILED;

Expand Down
7 changes: 4 additions & 3 deletions net/url_request/url_request_test_util.h
Original file line number Diff line number Diff line change
Expand Up @@ -346,9 +346,10 @@ class TestNetworkDelegate : public NetworkDelegateImpl {
int OnBeforeURLRequest(URLRequest* request,
CompletionOnceCallback callback,
GURL* new_url) override;
int OnBeforeStartTransaction(URLRequest* request,
CompletionOnceCallback callback,
HttpRequestHeaders* headers) override;
int OnBeforeStartTransaction(
URLRequest* request,
const HttpRequestHeaders& headers,
OnBeforeStartTransactionCallback callback) override;
int OnHeadersReceived(
URLRequest* request,
CompletionOnceCallback callback,
Expand Down
37 changes: 25 additions & 12 deletions net/url_request/url_request_unittest.cc
Original file line number Diff line number Diff line change
Expand Up @@ -445,9 +445,10 @@ class BlockingNetworkDelegate : public TestNetworkDelegate {
CompletionOnceCallback callback,
GURL* new_url) override;

int OnBeforeStartTransaction(URLRequest* request,
CompletionOnceCallback callback,
HttpRequestHeaders* headers) override;
int OnBeforeStartTransaction(
URLRequest* request,
const HttpRequestHeaders& headers,
OnBeforeStartTransactionCallback callback) override;

int OnHeadersReceived(
URLRequest* request,
Expand Down Expand Up @@ -546,13 +547,19 @@ int BlockingNetworkDelegate::OnBeforeURLRequest(URLRequest* request,

int BlockingNetworkDelegate::OnBeforeStartTransaction(
URLRequest* request,
CompletionOnceCallback callback,
HttpRequestHeaders* headers) {
const HttpRequestHeaders& headers,
OnBeforeStartTransactionCallback callback) {
// TestNetworkDelegate always completes synchronously.
CHECK_NE(ERR_IO_PENDING, TestNetworkDelegate::OnBeforeStartTransaction(
request, base::NullCallback(), headers));
request, headers, base::NullCallback()));

return MaybeBlockStage(ON_BEFORE_SEND_HEADERS, std::move(callback));
return MaybeBlockStage(
ON_BEFORE_SEND_HEADERS,
base::BindOnce(
[](OnBeforeStartTransactionCallback callback, int result) {
std::move(callback).Run(result, absl::nullopt);
},
std::move(callback)));
}

int BlockingNetworkDelegate::OnHeadersReceived(
Expand Down Expand Up @@ -4878,13 +4885,19 @@ class AsyncLoggingNetworkDelegate : public TestNetworkDelegate {
return RunCallbackAsynchronously(request, std::move(callback));
}

int OnBeforeStartTransaction(URLRequest* request,
CompletionOnceCallback callback,
HttpRequestHeaders* headers) override {
int OnBeforeStartTransaction(
URLRequest* request,
const HttpRequestHeaders& headers,
OnBeforeStartTransactionCallback callback) override {
// TestNetworkDelegate always completes synchronously.
CHECK_NE(ERR_IO_PENDING, TestNetworkDelegate::OnBeforeStartTransaction(
request, base::NullCallback(), headers));
return RunCallbackAsynchronously(request, std::move(callback));
request, headers, base::NullCallback()));
return RunCallbackAsynchronously(
request, base::BindOnce(
[](OnBeforeStartTransactionCallback callback, int result) {
std::move(callback).Run(result, absl::nullopt);
},
std::move(callback)));
}

int OnHeadersReceived(
Expand Down
8 changes: 4 additions & 4 deletions services/network/network_service_network_delegate.cc
Original file line number Diff line number Diff line change
Expand Up @@ -103,16 +103,16 @@ int NetworkServiceNetworkDelegate::OnBeforeURLRequest(

int NetworkServiceNetworkDelegate::OnBeforeStartTransaction(
net::URLRequest* request,
net::CompletionOnceCallback callback,
net::HttpRequestHeaders* headers) {
const net::HttpRequestHeaders& headers,
OnBeforeStartTransactionCallback callback) {
URLLoader* url_loader = URLLoader::ForRequest(*request);
if (url_loader)
return url_loader->OnBeforeStartTransaction(std::move(callback), headers);
return url_loader->OnBeforeStartTransaction(headers, std::move(callback));

#if !defined(OS_IOS)
WebSocket* web_socket = WebSocket::ForRequest(*request);
if (web_socket)
return web_socket->OnBeforeStartTransaction(std::move(callback), headers);
return web_socket->OnBeforeStartTransaction(headers, std::move(callback));
#endif // !defined(OS_IOS)

return net::OK;
Expand Down
7 changes: 4 additions & 3 deletions services/network/network_service_network_delegate.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,10 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) NetworkServiceNetworkDelegate
int OnBeforeURLRequest(net::URLRequest* request,
net::CompletionOnceCallback callback,
GURL* new_url) override;
int OnBeforeStartTransaction(net::URLRequest* request,
net::CompletionOnceCallback callback,
net::HttpRequestHeaders* headers) override;
int OnBeforeStartTransaction(
net::URLRequest* request,
const net::HttpRequestHeaders& headers,
OnBeforeStartTransactionCallback callback) override;
int OnHeadersReceived(
net::URLRequest* request,
net::CompletionOnceCallback callback,
Expand Down
18 changes: 8 additions & 10 deletions services/network/url_loader.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1643,13 +1643,14 @@ void URLLoader::OnReadCompleted(net::URLRequest* url_request, int bytes_read) {
// |this| may have been deleted.
}

int URLLoader::OnBeforeStartTransaction(net::CompletionOnceCallback callback,
net::HttpRequestHeaders* headers) {
int URLLoader::OnBeforeStartTransaction(
const net::HttpRequestHeaders& headers,
net::NetworkDelegate::OnBeforeStartTransactionCallback callback) {
if (header_client_) {
header_client_->OnBeforeSendHeaders(
*headers, base::BindOnce(&URLLoader::OnBeforeSendHeadersComplete,
weak_ptr_factory_.GetWeakPtr(),
std::move(callback), headers));
headers,
base::BindOnce(&URLLoader::OnBeforeSendHeadersComplete,
weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
return net::ERR_IO_PENDING;
}
return net::OK;
Expand Down Expand Up @@ -2017,13 +2018,10 @@ void URLLoader::ResumeStart() {
}

void URLLoader::OnBeforeSendHeadersComplete(
net::CompletionOnceCallback callback,
net::HttpRequestHeaders* out_headers,
net::NetworkDelegate::OnBeforeStartTransactionCallback callback,
int result,
const absl::optional<net::HttpRequestHeaders>& headers) {
if (headers)
*out_headers = headers.value();
std::move(callback).Run(result);
std::move(callback).Run(result, headers);
}

void URLLoader::OnHeadersReceivedComplete(
Expand Down
9 changes: 5 additions & 4 deletions services/network/url_loader.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
#include "mojo/public/cpp/system/data_pipe.h"
#include "mojo/public/cpp/system/simple_watcher.h"
#include "net/base/load_states.h"
#include "net/base/network_delegate.h"
#include "net/http/http_raw_request_headers.h"
#include "net/traffic_annotation/network_traffic_annotation.h"
#include "net/url_request/url_request.h"
Expand Down Expand Up @@ -172,8 +173,9 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) URLLoader

// These methods are called by the network delegate to forward these events to
// the |header_client_|.
int OnBeforeStartTransaction(net::CompletionOnceCallback callback,
net::HttpRequestHeaders* headers);
int OnBeforeStartTransaction(
const net::HttpRequestHeaders& headers,
net::NetworkDelegate::OnBeforeStartTransactionCallback callback);
int OnHeadersReceived(
net::CompletionOnceCallback callback,
const net::HttpResponseHeaders* original_response_headers,
Expand Down Expand Up @@ -342,8 +344,7 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) URLLoader
void RecordBodyReadFromNetBeforePausedIfNeeded();
void ResumeStart();
void OnBeforeSendHeadersComplete(
net::CompletionOnceCallback callback,
net::HttpRequestHeaders* out_headers,
net::NetworkDelegate::OnBeforeStartTransactionCallback callback,
int result,
const absl::optional<net::HttpRequestHeaders>& headers);
void OnHeadersReceivedComplete(
Expand Down
18 changes: 8 additions & 10 deletions services/network/websocket.cc
Original file line number Diff line number Diff line change
Expand Up @@ -537,13 +537,14 @@ bool WebSocket::AllowCookies(const GURL& url) const {
url, site_for_cookies_) == net::OK;
}

int WebSocket::OnBeforeStartTransaction(net::CompletionOnceCallback callback,
net::HttpRequestHeaders* headers) {
int WebSocket::OnBeforeStartTransaction(
const net::HttpRequestHeaders& headers,
net::NetworkDelegate::OnBeforeStartTransactionCallback callback) {
if (header_client_) {
header_client_->OnBeforeSendHeaders(
*headers, base::BindOnce(&WebSocket::OnBeforeSendHeadersComplete,
weak_ptr_factory_.GetWeakPtr(),
std::move(callback), headers));
headers,
base::BindOnce(&WebSocket::OnBeforeSendHeadersComplete,
weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
return net::ERR_IO_PENDING;
}
return net::OK;
Expand Down Expand Up @@ -840,17 +841,14 @@ void WebSocket::OnAuthRequiredComplete(
}

void WebSocket::OnBeforeSendHeadersComplete(
net::CompletionOnceCallback callback,
net::HttpRequestHeaders* out_headers,
net::NetworkDelegate::OnBeforeStartTransactionCallback callback,
int result,
const absl::optional<net::HttpRequestHeaders>& headers) {
if (!channel_) {
// Something happened before the OnBeforeSendHeaders response arrives.
return;
}
if (headers)
*out_headers = headers.value();
std::move(callback).Run(result);
std::move(callback).Run(result, headers);
}

void WebSocket::OnHeadersReceivedComplete(
Expand Down

0 comments on commit d1eade9

Please sign in to comment.