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

Reply via email to