Branch: refs/heads/main
Home: https://github.com/WebKit/WebKit
Commit: fb20d4d63ba2a3a5c6618befe58aebaba605dcad
https://github.com/WebKit/WebKit/commit/fb20d4d63ba2a3a5c6618befe58aebaba605dcad
Author: Tyler Wilcock <[email protected]>
Date: 2026-09-11 (Fri, 11 Sep 2026)
Changed paths:
M Source/WebCore/platform/PlatformSpeechSynthesizer.cpp
M Source/WebCore/platform/PlatformSpeechSynthesizer.h
M Source/WebCore/platform/cocoa/PlatformSpeechSynthesizerCocoa.mm
M Source/WebCore/platform/gstreamer/PlatformSpeechSynthesizerGStreamer.cpp
M Source/WebCore/platform/mock/PlatformSpeechSynthesizerMock.cpp
M Source/WebCore/platform/spiel/PlatformSpeechSynthesizerSpiel.cpp
M Source/WebCore/testing/Internals.cpp
Log Message:
-----------
PlatformSpeechSynthesizerClient should prevent use-after-free via weak
back-reference to client
https://bugs.webkit.org/show_bug.cgi?id=312793
rdar://172854014
Reviewed by Joshua Hoffman.
PlatformSpeechSynthesizer held a raw C++ reference
(PlatformSpeechSynthesizerClient&) back to its client
(SpeechSynthesis). When cancel() was made asynchronous via
callOnMainThread in 309349@main, the deferred lambda could fire after
SpeechSynthesis had been destroyed, dereferencing freed memory. ASan
caught this as a heap-use-after-free in 131 media/track layout tests.
This commit makes PlatformSpeechSynthesizerClient inherit from
AbstractRefCountedAndCanMakeWeakPtr so it supports both WeakPtr (for
the non-owning back-reference) and RefPtr (for strong promotion at
call sites). Convert the raw reference member to a WeakPtr, and update
all ~29 call sites across all platform implementations to promote to
RefPtr before calling through the client.
This also fixes two latent async bugs with the same pattern: the Cocoa
voicesDidChange async callback and the Spiel initializeVoiceList
lambda both accessed the client in a deferred context without lifetime
protection.
* Source/WebCore/platform/PlatformSpeechSynthesizer.cpp:
(WebCore::PlatformSpeechSynthesizer::voicesDidChange):
* Source/WebCore/platform/PlatformSpeechSynthesizer.h:
* Source/WebCore/platform/cocoa/PlatformSpeechSynthesizerCocoa.mm:
(-[WebSpeechSynthesisWrapper speakUtterance:]):
(-[WebSpeechSynthesisWrapper speechSynthesizer:didStartSpeechUtterance:]):
(-[WebSpeechSynthesisWrapper speechSynthesizer:didFinishSpeechUtterance:]):
(-[WebSpeechSynthesisWrapper speechSynthesizer:didPauseSpeechUtterance:]):
(-[WebSpeechSynthesisWrapper speechSynthesizer:didContinueSpeechUtterance:]):
(-[WebSpeechSynthesisWrapper speechSynthesizer:didCancelSpeechUtterance:]):
(-[WebSpeechSynthesisWrapper
speechSynthesizer:willSpeakRangeOfSpeechString:utterance:]):
(WebCore::PlatformSpeechSynthesizer::initializeVoiceList):
* Source/WebCore/platform/gstreamer/PlatformSpeechSynthesizerGStreamer.cpp:
(WebCore::GstSpeechSynthesisWrapper::pause):
(WebCore::GstSpeechSynthesisWrapper::resume):
(WebCore::GstSpeechSynthesisWrapper::speakUtterance):
(WebCore::GstSpeechSynthesisWrapper::cancel):
* Source/WebCore/platform/mock/PlatformSpeechSynthesizerMock.cpp:
(WebCore::PlatformSpeechSynthesizerMock::speakingFinished):
(WebCore::PlatformSpeechSynthesizerMock::speak):
(WebCore::PlatformSpeechSynthesizerMock::cancel):
(WebCore::PlatformSpeechSynthesizerMock::pause):
(WebCore::PlatformSpeechSynthesizerMock::resume):
* Source/WebCore/platform/spiel/PlatformSpeechSynthesizerSpiel.cpp:
(WebCore::SpielSpeechWrapper::finishSpeakerInitialization):
(WebCore::SpielSpeechWrapper::speakUtterance):
(WebCore::PlatformSpeechSynthesizer::initializeVoiceList):
* Source/WebCore/testing/Internals.cpp:
(WebCore::Internals::simulateSpeechSynthesizerVoiceListChange):
Originally-landed-as: 305413.715@safari-7624-branch (71471a83ed2d).
rdar://184744850
Canonical link: https://commits.webkit.org/320970@main
To unsubscribe from these emails, change your notification settings at
https://github.com/WebKit/WebKit/settings/notifications