Skip to content

Commit baef96f

Browse files
committed
Address safer CPP failures in FetchBodyOwner
https://bugs.webkit.org/show_bug.cgi?id=290291 Reviewed by Geoffrey Garen. * Source/WebCore/Modules/fetch/FetchBody.h: (WebCore::FetchBody::protectedReadableStream const): (WebCore::FetchBody::protectedReadableStream): * Source/WebCore/Modules/fetch/FetchBodyOwner.cpp: (WebCore::FetchBodyOwner::~FetchBodyOwner): (WebCore::FetchBodyOwner::isDisturbed const): (WebCore::FetchBodyOwner::isDisturbedOrLocked const): (WebCore::FetchBodyOwner::formData): (WebCore::FetchBodyOwner::loadBlob): (WebCore::FetchBodyOwner::blobLoadingSucceeded): (WebCore::FetchBodyOwner::blobLoadingFailed): (WebCore::FetchBodyOwner::blobChunk): (WebCore::FetchBodyOwner::BlobLoader::didFail): (WebCore::FetchBodyOwner::BlobLoader::didSucceed): (WebCore::FetchBodyOwner::createReadableStream): (WebCore::FetchBodyOwner::consumeBodyAsStream): * Source/WebCore/Modules/fetch/FetchBodyOwner.h: * Source/WebCore/Modules/fetch/FetchResponse.cpp: (WebCore::FetchResponse::create): (WebCore::FetchResponse::clone): * Source/WebCore/Modules/fetch/FetchResponse.h: * Source/WebCore/SaferCPPExpectations/NoUncountedMemberCheckerExpectations: * Source/WebCore/SaferCPPExpectations/UncountedCallArgsCheckerExpectations: Canonical link: https://commits.webkit.org/292575@main
1 parent 87f47a8 commit baef96f

7 files changed

Lines changed: 42 additions & 36 deletions

File tree

Source/WebCore/Modules/fetch/FetchBody.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,8 @@ class FetchBody {
8989
bool hasReadableStream() const { return !!m_readableStream; }
9090
const ReadableStream* readableStream() const { return m_readableStream.get(); }
9191
ReadableStream* readableStream() { return m_readableStream.get(); }
92+
RefPtr<const ReadableStream> protectedReadableStream() const { return readableStream(); }
93+
RefPtr<ReadableStream> protectedReadableStream() { return readableStream(); }
9294
void setReadableStream(Ref<ReadableStream>&& stream)
9395
{
9496
ASSERT(!m_readableStream);

Source/WebCore/Modules/fetch/FetchBodyOwner.cpp

Lines changed: 24 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -56,8 +56,8 @@ FetchBodyOwner::FetchBodyOwner(ScriptExecutionContext* context, std::optional<Fe
5656

5757
FetchBodyOwner::~FetchBodyOwner()
5858
{
59-
if (m_readableStreamSource)
60-
m_readableStreamSource->detach();
59+
if (RefPtr readableStreamSource = m_readableStreamSource)
60+
readableStreamSource->detach();
6161
}
6262

6363
void FetchBodyOwner::stop()
@@ -83,8 +83,8 @@ bool FetchBodyOwner::isDisturbed() const
8383
if (m_isDisturbed)
8484
return true;
8585

86-
if (body().readableStream())
87-
return body().readableStream()->isDisturbed();
86+
if (RefPtr readableStream = body().readableStream())
87+
return readableStream->isDisturbed();
8888

8989
return false;
9090
}
@@ -97,8 +97,8 @@ bool FetchBodyOwner::isDisturbedOrLocked() const
9797
if (m_isDisturbed)
9898
return true;
9999

100-
if (body().readableStream())
101-
return body().readableStream()->isDisturbed() || body().readableStream()->isLocked();
100+
if (RefPtr readableStream = body().readableStream())
101+
return readableStream->isDisturbed() || readableStream->isLocked();
102102

103103
return false;
104104
}
@@ -211,7 +211,7 @@ void FetchBodyOwner::formData(Ref<DeferredPromise>&& promise)
211211
if (isBodyNullOrOpaque()) {
212212
if (isBodyNull()) {
213213
// If the content-type is 'application/x-www-form-urlencoded', a body is not required and we should package an empty byte sequence as per the specification.
214-
if (auto formData = FetchBodyConsumer::packageFormData(promise->scriptExecutionContext(), contentType(), { })) {
214+
if (auto formData = FetchBodyConsumer::packageFormData(promise->protectedScriptExecutionContext().get(), contentType(), { })) {
215215
promise->resolve<IDLInterface<DOMFormData>>(*formData);
216216
return;
217217
}
@@ -277,7 +277,7 @@ void FetchBodyOwner::loadBlob(const Blob& blob, FetchBodyConsumer* consumer)
277277
m_blobLoader.emplace(*this);
278278
m_blobLoader->loader = makeUnique<FetchLoader>(*m_blobLoader, consumer);
279279

280-
m_blobLoader->loader->start(*scriptExecutionContext(), blob);
280+
m_blobLoader->loader->start(*protectedScriptExecutionContext(), blob);
281281
if (!m_blobLoader->loader->isStarted()) {
282282
m_body->loadingFailed(Exception { ExceptionCode::TypeError, "Blob loading failed"_s });
283283
m_blobLoader = std::nullopt;
@@ -295,10 +295,8 @@ void FetchBodyOwner::finishBlobLoading()
295295
void FetchBodyOwner::blobLoadingSucceeded()
296296
{
297297
ASSERT(!isBodyNull());
298-
if (m_readableStreamSource) {
299-
m_readableStreamSource->close();
300-
m_readableStreamSource = nullptr;
301-
}
298+
if (RefPtr readableStreamSource = std::exchange(m_readableStreamSource, nullptr))
299+
readableStreamSource->close();
302300

303301
m_body->loadingSucceeded(contentType());
304302
if (!m_blobLoader)
@@ -310,19 +308,19 @@ void FetchBodyOwner::blobLoadingSucceeded()
310308
void FetchBodyOwner::blobLoadingFailed()
311309
{
312310
ASSERT(!isBodyNull());
313-
if (m_readableStreamSource) {
314-
if (!m_readableStreamSource->isCancelling())
315-
m_readableStreamSource->error(Exception { ExceptionCode::TypeError, "Blob loading failed"_s });
316-
m_readableStreamSource = nullptr;
311+
if (RefPtr readableStreamSource = std::exchange(m_readableStreamSource, nullptr)) {
312+
if (!readableStreamSource->isCancelling())
313+
readableStreamSource->error(Exception { ExceptionCode::TypeError, "Blob loading failed"_s });
317314
} else
318315
m_body->loadingFailed(Exception { ExceptionCode::TypeError, "Blob loading failed"_s });
319316
finishBlobLoading();
320317
}
321318

322319
void FetchBodyOwner::blobChunk(const SharedBuffer& buffer)
323320
{
324-
ASSERT(m_readableStreamSource);
325-
if (!m_readableStreamSource->enqueue(buffer.tryCreateArrayBuffer()))
321+
RefPtr readableStreamSource = m_readableStreamSource;
322+
ASSERT(readableStreamSource);
323+
if (!readableStreamSource->enqueue(buffer.tryCreateArrayBuffer()))
326324
stop();
327325
}
328326

@@ -341,13 +339,12 @@ void FetchBodyOwner::BlobLoader::didFail(const ResourceError&)
341339
{
342340
// didFail might be called within FetchLoader::start call.
343341
if (loader->isStarted())
344-
owner.blobLoadingFailed();
342+
protectedOwner()->blobLoadingFailed();
345343
}
346344

347345
void FetchBodyOwner::BlobLoader::didSucceed(const NetworkLoadMetrics&)
348346
{
349-
Ref protectedOwner = Ref { owner };
350-
protectedOwner->blobLoadingSucceeded();
347+
protectedOwner()->blobLoadingSucceeded();
351348
}
352349

353350
ExceptionOr<RefPtr<ReadableStream>> FetchBodyOwner::readableStream(JSC::JSGlobalObject& state)
@@ -372,7 +369,7 @@ ExceptionOr<void> FetchBodyOwner::createReadableStream(JSC::JSGlobalObject& stat
372369
if (UNLIKELY(streamOrException.hasException()))
373370
return streamOrException.releaseException();
374371
m_body->setReadableStream(streamOrException.releaseReturnValue());
375-
m_body->readableStream()->lock();
372+
m_body->protectedReadableStream()->lock();
376373
return { };
377374
}
378375

@@ -388,15 +385,16 @@ ExceptionOr<void> FetchBodyOwner::createReadableStream(JSC::JSGlobalObject& stat
388385

389386
void FetchBodyOwner::consumeBodyAsStream()
390387
{
391-
ASSERT(m_readableStreamSource);
388+
RefPtr readableStreamSource = m_readableStreamSource;
389+
ASSERT(readableStreamSource);
392390

393391
if (auto exception = loadingException()) {
394-
m_readableStreamSource->error(*exception);
392+
readableStreamSource->error(*exception);
395393
return;
396394
}
397395

398-
body().consumeAsStream(*this, *m_readableStreamSource);
399-
if (!m_readableStreamSource->isPulling())
396+
body().consumeAsStream(*this, *readableStreamSource);
397+
if (!readableStreamSource->isPulling())
400398
m_readableStreamSource = nullptr;
401399
}
402400

Source/WebCore/Modules/fetch/FetchBodyOwner.h

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -126,19 +126,21 @@ class FetchBodyOwner : public RefCountedAndCanMakeWeakPtr<FetchBodyOwner>, publi
126126

127127
// FetchLoaderClient API
128128
void didReceiveResponse(const ResourceResponse&) final;
129-
void didReceiveData(const SharedBuffer& buffer) final { owner.blobChunk(buffer); }
129+
void didReceiveData(const SharedBuffer& buffer) final { protectedOwner()->blobChunk(buffer); }
130130
void didFail(const ResourceError&) final;
131131
void didSucceed(const NetworkLoadMetrics&) final;
132132

133-
FetchBodyOwner& owner;
133+
Ref<FetchBodyOwner> protectedOwner() const { return owner.get(); }
134+
135+
WeakRef<FetchBodyOwner> owner;
134136
std::unique_ptr<FetchLoader> loader;
135137
};
136138

137139
protected:
138140
std::optional<FetchBody> m_body;
139141
bool m_isDisturbed { false };
140142
RefPtr<FetchBodySource> m_readableStreamSource;
141-
Ref<FetchHeaders> m_headers;
143+
const Ref<FetchHeaders> m_headers;
142144

143145
private:
144146
std::optional<BlobLoader> m_blobLoader;

Source/WebCore/Modules/fetch/FetchResponse.cpp

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -56,12 +56,18 @@ static inline bool isNullBodyStatus(int status)
5656
FetchResponse::~FetchResponse() = default;
5757

5858
Ref<FetchResponse> FetchResponse::create(ScriptExecutionContext* context, std::optional<FetchBody>&& body, FetchHeaders::Guard guard, ResourceResponse&& response)
59+
{
60+
bool isOpaque = response.tainting() == ResourceResponse::Tainting::Opaque;
61+
Ref headers = isOpaque ? FetchHeaders::create(guard) : FetchHeaders::create(guard, HTTPHeaderMap { response.httpHeaderFields() });
62+
return FetchResponse::create(context, WTFMove(body), WTFMove(headers), WTFMove(response));
63+
}
64+
65+
Ref<FetchResponse> FetchResponse::create(ScriptExecutionContext* context, std::optional<FetchBody>&& body, Ref<FetchHeaders>&& headers, ResourceResponse&& response)
5966
{
6067
bool isSynthetic = response.type() == ResourceResponse::Type::Default || response.type() == ResourceResponse::Type::Error;
6168
bool isOpaque = response.tainting() == ResourceResponse::Tainting::Opaque;
62-
auto headers = isOpaque ? FetchHeaders::create(guard) : FetchHeaders::create(guard, HTTPHeaderMap { response.httpHeaderFields() });
6369

64-
auto fetchResponse = adoptRef(*new FetchResponse(context, WTFMove(body), WTFMove(headers), WTFMove(response)));
70+
Ref fetchResponse = adoptRef(*new FetchResponse(context, WTFMove(body), WTFMove(headers), WTFMove(response)));
6571
fetchResponse->suspendIfNeeded();
6672
if (!isSynthetic)
6773
fetchResponse->m_filteredResponse = ResourceResponseBase::filter(fetchResponse->m_internalResponse, ResourceResponse::PerformExposeAllHeadersCheck::Yes);
@@ -211,9 +217,9 @@ ExceptionOr<Ref<FetchResponse>> FetchResponse::clone()
211217
if (m_internalResponse.type() == ResourceResponse::Type::Default)
212218
m_internalResponse.setHTTPHeaderFields(HTTPHeaderMap { headers().internalHeaders() });
213219

214-
auto clone = FetchResponse::create(scriptExecutionContext(), std::nullopt, headers().guard(), ResourceResponse { m_internalResponse });
220+
Ref headers = FetchHeaders::create(this->headers());
221+
auto clone = FetchResponse::create(scriptExecutionContext(), std::nullopt, WTFMove(headers), ResourceResponse { m_internalResponse });
215222
clone->cloneBody(*this);
216-
clone->m_headers = FetchHeaders::create(headers());
217223
clone->m_opaqueLoadIdentifier = m_opaqueLoadIdentifier;
218224
clone->m_bodySizeWithPadding = m_bodySizeWithPadding;
219225
return clone;

Source/WebCore/Modules/fetch/FetchResponse.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ class FetchResponse final : public FetchBodyOwner {
6363
virtual ~FetchResponse();
6464

6565
WEBCORE_EXPORT static Ref<FetchResponse> create(ScriptExecutionContext*, std::optional<FetchBody>&&, FetchHeaders::Guard, ResourceResponse&&);
66+
static Ref<FetchResponse> create(ScriptExecutionContext*, std::optional<FetchBody>&&, Ref<FetchHeaders>&&, ResourceResponse&&);
6667

6768
static ExceptionOr<Ref<FetchResponse>> create(ScriptExecutionContext&, std::optional<FetchBody::Init>&&, Init&&);
6869
static ExceptionOr<Ref<FetchResponse>> create(ScriptExecutionContext&, std::optional<FetchBodyWithType>&&, Init&&);

Source/WebCore/SaferCPPExpectations/NoUncountedMemberCheckerExpectations

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
Modules/WebGPU/GPUPresentationContextDescriptor.h
22
Modules/encryptedmedia/MediaKeyStatusMap.h
3-
Modules/fetch/FetchBodyOwner.h
43
Modules/mediastream/RTCPeerConnection.h
54
Modules/mediastream/libwebrtc/LibWebRTCObservers.h
65
Modules/notifications/NotificationResourcesLoader.h

Source/WebCore/SaferCPPExpectations/UncountedCallArgsCheckerExpectations

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,8 +58,6 @@ Modules/entriesapi/FileSystemEntry.cpp
5858
Modules/entriesapi/FileSystemFileEntry.cpp
5959
Modules/fetch/FetchBody.cpp
6060
Modules/fetch/FetchBodyConsumer.cpp
61-
Modules/fetch/FetchBodyOwner.cpp
62-
Modules/fetch/FetchBodyOwner.h
6361
Modules/fetch/FetchBodySource.cpp
6462
Modules/fetch/FetchLoader.cpp
6563
Modules/fetch/FetchRequest.cpp

0 commit comments

Comments
 (0)