summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael BrĂ¼ning <michael.bruning@qt.io>2022-12-13 01:02:30 +0100
committerMichael BrĂ¼ning <michael.bruning@qt.io>2022-12-14 12:39:33 +0100
commitdf26edf16ab6012f741efca4bb6372ac4f1b1e02 (patch)
tree89227ec541de986e25fa8dbc15a63bef3a037b78
parent5d89f26414471689a9626515d098104e38bacbda (diff)
Recreate response head objects on multiple redirect
The previous response head gets moved when redirecting, which lead to dereferencing a null pointer on the next redirect. Fixes: QTBUG-109357 Change-Id: Iaad1c46b8d4ca9720f1749980a9e06337ca0f3d8 Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io> (cherry picked from commit c6b2b5d8038b3ec0de6233c1e21df60ade11c81b)
-rw-r--r--src/core/net/proxying_url_loader_factory_qt.cpp26
-rw-r--r--tests/auto/core/qwebengineurlrequestinterceptor/resources/content3.html6
-rw-r--r--tests/auto/core/qwebengineurlrequestinterceptor/tst_qwebengineurlrequestinterceptor.cpp47
-rw-r--r--tests/auto/core/qwebengineurlrequestinterceptor/tst_qwebengineurlrequestinterceptor.qrc2
4 files changed, 73 insertions, 8 deletions
diff --git a/src/core/net/proxying_url_loader_factory_qt.cpp b/src/core/net/proxying_url_loader_factory_qt.cpp
index a9b774086..a016cbc72 100644
--- a/src/core/net/proxying_url_loader_factory_qt.cpp
+++ b/src/core/net/proxying_url_loader_factory_qt.cpp
@@ -66,6 +66,18 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+namespace {
+ network::mojom::URLResponseHeadPtr createResponse(const network::ResourceRequest &request) {
+ const bool disable_web_security = base::CommandLine::ForCurrentProcess()->HasSwitch(switches::kDisableWebSecurity);
+ network::mojom::URLResponseHeadPtr response = network::mojom::URLResponseHead::New();
+ response->response_type = network::cors::CalculateResponseType(
+ request.mode, disable_web_security || (
+ request.request_initiator && request.request_initiator->IsSameOriginWith(url::Origin::Create(request.url))));
+
+ return response;
+ }
+}
+
namespace QtWebEngineCore {
ASSERT_ENUMS_MATCH(QWebEngineUrlRequestInfo::ResourceTypeMainFrame, blink::mojom::ResourceType::kMainFrame)
@@ -211,11 +223,7 @@ InterceptedRequest::InterceptedRequest(ProfileAdapter *profile_adapter,
, weak_factory_(this)
{
const bool disable_web_security = base::CommandLine::ForCurrentProcess()->HasSwitch(switches::kDisableWebSecurity);
- current_response_ = network::mojom::URLResponseHead::New();
- current_response_->response_type = network::cors::CalculateResponseType(
- request_.mode,
- disable_web_security || (
- request_.request_initiator && request_.request_initiator->IsSameOriginWith(url::Origin::Create(request_.url))));
+ current_response_ = createResponse(request_);
// If there is a client error, clean up the request.
target_client_.set_disconnect_handler(
base::BindOnce(&InterceptedRequest::OnURLLoaderClientError, base::Unretained(this)));
@@ -381,9 +389,6 @@ void InterceptedRequest::ContinueAfterIntercept()
first_party_url_policy, request_.referrer_policy, request_.referrer.spec(),
net::HTTP_TEMPORARY_REDIRECT, toGurl(info.url), base::nullopt,
false /*insecure_scheme_was_upgraded*/);
-
- // FIXME: Should probably create a new header.
- current_response_->encoded_data_length = 0;
request_.method = redirectInfo.new_method;
request_.url = redirectInfo.new_url;
request_.site_for_cookies = redirectInfo.new_site_for_cookies;
@@ -391,6 +396,11 @@ void InterceptedRequest::ContinueAfterIntercept()
request_.referrer_policy = redirectInfo.new_referrer_policy;
if (request_.method == net::HttpRequestHeaders::kGetMethod)
request_.request_body = nullptr;
+ // In case of multiple sequential rediredts, current_response_ has previously been moved to target_client_
+ // so we create a new one using the redirect url.
+ if (!current_response_)
+ current_response_ = createResponse(request_);
+ current_response_->encoded_data_length = 0;
target_client_->OnReceiveRedirect(redirectInfo, std::move(current_response_));
return;
}
diff --git a/tests/auto/core/qwebengineurlrequestinterceptor/resources/content3.html b/tests/auto/core/qwebengineurlrequestinterceptor/resources/content3.html
new file mode 100644
index 000000000..84bf55036
--- /dev/null
+++ b/tests/auto/core/qwebengineurlrequestinterceptor/resources/content3.html
@@ -0,0 +1,6 @@
+<html>
+<head><link rel="icon" href="data:,"></head>
+<body>
+<a>Simple test page without favicon (meaning no separate request from http server)</a>
+</body>
+</html>
diff --git a/tests/auto/core/qwebengineurlrequestinterceptor/tst_qwebengineurlrequestinterceptor.cpp b/tests/auto/core/qwebengineurlrequestinterceptor/tst_qwebengineurlrequestinterceptor.cpp
index 642e5db7c..32a618de3 100644
--- a/tests/auto/core/qwebengineurlrequestinterceptor/tst_qwebengineurlrequestinterceptor.cpp
+++ b/tests/auto/core/qwebengineurlrequestinterceptor/tst_qwebengineurlrequestinterceptor.cpp
@@ -79,6 +79,7 @@ private Q_SLOTS:
void replaceInterceptor_data();
void replaceInterceptor();
void replaceOnIntercept();
+ void multipleRedirects();
};
tst_QWebEngineUrlRequestInterceptor::tst_QWebEngineUrlRequestInterceptor()
@@ -211,6 +212,29 @@ public:
}
};
+class TestMultipleRedirectsInterceptor : public QWebEngineUrlRequestInterceptor {
+public:
+ QList<RequestInfo> requestInfos;
+ QMap<QUrl, QUrl> redirectPairs;
+ int redirectCount = 0;
+ void interceptRequest(QWebEngineUrlRequestInfo &info) override
+ {
+ QVERIFY(QThread::currentThread() == QCoreApplication::instance()->thread());
+ qCDebug(lc) << this << "Type:" << info.resourceType() << info.requestMethod() << "Navigation:" << info.navigationType()
+ << info.requestUrl() << "Initiator:" << info.initiator();
+ auto redirectUrl = redirectPairs.constFind(info.requestUrl());
+ if (redirectUrl != redirectPairs.constEnd()) {
+ info.redirect(redirectUrl.value());
+ requestInfos.append(info);
+ redirectCount++;
+ }
+ }
+
+ TestMultipleRedirectsInterceptor()
+ {
+ }
+};
+
class ConsolePage : public QWebEnginePage {
Q_OBJECT
public:
@@ -915,5 +939,28 @@ void tst_QWebEngineUrlRequestInterceptor::replaceOnIntercept()
QCOMPARE(profileInterceptor.requestInfos.size(), pageInterceptor2.requestInfos.size());
}
+void tst_QWebEngineUrlRequestInterceptor::multipleRedirects()
+{
+ HttpServer server;
+ server.setResourceDirs({ ":/resources" });
+ QVERIFY(server.start());
+
+ TestMultipleRedirectsInterceptor multiInterceptor;
+ multiInterceptor.redirectPairs.insert(QUrl(server.url("/content.html")), QUrl(server.url("/content2.html")));
+ multiInterceptor.redirectPairs.insert(QUrl(server.url("/content2.html")), QUrl(server.url("/content3.html")));
+
+ QWebEngineProfile profile;
+ profile.settings()->setAttribute(QWebEngineSettings::ErrorPageEnabled, false);
+ profile.setUrlRequestInterceptor(&multiInterceptor);
+ QWebEnginePage page(&profile);
+ QSignalSpy spy(&page, SIGNAL(loadFinished(bool)));
+
+ page.setUrl(server.url("/content.html"));
+
+ QTRY_COMPARE_WITH_TIMEOUT(spy.count(), 1, 20000);
+ QTRY_COMPARE(multiInterceptor.redirectCount, 2);
+ QTRY_COMPARE(multiInterceptor.requestInfos.size(), 2);
+}
+
QTEST_MAIN(tst_QWebEngineUrlRequestInterceptor)
#include "tst_qwebengineurlrequestinterceptor.moc"
diff --git a/tests/auto/core/qwebengineurlrequestinterceptor/tst_qwebengineurlrequestinterceptor.qrc b/tests/auto/core/qwebengineurlrequestinterceptor/tst_qwebengineurlrequestinterceptor.qrc
index 6a34635f7..df9c81a7b 100644
--- a/tests/auto/core/qwebengineurlrequestinterceptor/tst_qwebengineurlrequestinterceptor.qrc
+++ b/tests/auto/core/qwebengineurlrequestinterceptor/tst_qwebengineurlrequestinterceptor.qrc
@@ -1,6 +1,8 @@
<!DOCTYPE RCC><RCC version="1.0">
<qresource prefix="/">
<file>resources/content.html</file>
+ <file>resources/content2.html</file>
+ <file>resources/content3.html</file>
<file>resources/favicon.html</file>
<file>resources/firstparty.html</file>
<file>resources/fontawesome.woff</file>