Crash under WebCore::AudioSourceProviderAVFObjC::process().
authorpvollan@apple.com <pvollan@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 17 May 2017 21:53:01 +0000 (21:53 +0000)
committerpvollan@apple.com <pvollan@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 17 May 2017 21:53:01 +0000 (21:53 +0000)
https://bugs.webkit.org/show_bug.cgi?id=172101
rdar://problem/27446589

Reviewed by Jer Noble.

Calling the function MTAudioProcessingTapGetSourceAudio when the value of the
MTAudioProcessingTapRef parameter is null, will lead to a null dereference.
This can for example happen if MediaPlayerPrivateAVFoundationObjC::cancelLoad()
is called on the main thread while MediaToolbox is calling the
WebCore::AudioSourceProviderAVFObjC::processCallback function on a secondary
thread. MediaPlayerPrivateAVFoundationObjC::cancelLoad() will then call
AudioSourceProviderAVFObjC::setPlayerItem(nullptr), which will call
AudioSourceProviderAVFObjC::destroyMix(), which will set m_tap to null. When
AudioSourceProviderAVFObjC::process is called on the secondary thread, using
the m_tap member in the call to MTAudioProcessingTapGetSourceAudio, the process
will crash.

No new tests since I am not able to reproduce.

* platform/graphics/avfoundation/AudioSourceProviderAVFObjC.mm:
(WebCore::AudioSourceProviderAVFObjC::initCallback):
(WebCore::AudioSourceProviderAVFObjC::process):

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@217005 268f45cc-cd09-0410-ab3c-d52691b4dbfc

Source/WebCore/ChangeLog
Source/WebCore/platform/graphics/avfoundation/AudioSourceProviderAVFObjC.mm

index 900a4d7..35cf4f9 100644 (file)
@@ -1,3 +1,29 @@
+2017-05-17  Per Arne Vollan  <pvollan@apple.com>
+
+        Crash under WebCore::AudioSourceProviderAVFObjC::process().
+        https://bugs.webkit.org/show_bug.cgi?id=172101
+        rdar://problem/27446589
+
+        Reviewed by Jer Noble.
+
+        Calling the function MTAudioProcessingTapGetSourceAudio when the value of the
+        MTAudioProcessingTapRef parameter is null, will lead to a null dereference.
+        This can for example happen if MediaPlayerPrivateAVFoundationObjC::cancelLoad()
+        is called on the main thread while MediaToolbox is calling the
+        WebCore::AudioSourceProviderAVFObjC::processCallback function on a secondary
+        thread. MediaPlayerPrivateAVFoundationObjC::cancelLoad() will then call
+        AudioSourceProviderAVFObjC::setPlayerItem(nullptr), which will call
+        AudioSourceProviderAVFObjC::destroyMix(), which will set m_tap to null. When
+        AudioSourceProviderAVFObjC::process is called on the secondary thread, using
+        the m_tap member in the call to MTAudioProcessingTapGetSourceAudio, the process
+        will crash.
+
+        No new tests since I am not able to reproduce.
+
+        * platform/graphics/avfoundation/AudioSourceProviderAVFObjC.mm:
+        (WebCore::AudioSourceProviderAVFObjC::initCallback):
+        (WebCore::AudioSourceProviderAVFObjC::process):
+
 2017-05-17  Chris Dumez  <cdumez@apple.com>
 
         Setting URL.search to '' results in a stringified URL ending in '?'
index 70f564c..4c8c97e 100644 (file)
@@ -237,6 +237,7 @@ void AudioSourceProviderAVFObjC::createMix()
 
 void AudioSourceProviderAVFObjC::initCallback(MTAudioProcessingTapRef tap, void* clientInfo, void** tapStorageOut)
 {
+    ASSERT(tap);
     AudioSourceProviderAVFObjC* _this = static_cast<AudioSourceProviderAVFObjC*>(clientInfo);
     _this->m_tap = tap;
     _this->m_tapStorage = new TapStorage(_this);
@@ -359,10 +360,14 @@ void AudioSourceProviderAVFObjC::unprepare()
 void AudioSourceProviderAVFObjC::process(CMItemCount numberOfFrames, MTAudioProcessingTapFlags flags, AudioBufferList* bufferListInOut, CMItemCount* numberFramesOut, MTAudioProcessingTapFlags* flagsOut)
 {
     UNUSED_PARAM(flags);
+    
+    RetainPtr<MTAudioProcessingTapRef> tap = m_tap;
+    if (!tap)
+        return;
 
     CMItemCount itemCount = 0;
     CMTimeRange rangeOut;
-    OSStatus status = MTAudioProcessingTapGetSourceAudio(m_tap.get(), numberOfFrames, bufferListInOut, flagsOut, &rangeOut, &itemCount);
+    OSStatus status = MTAudioProcessingTapGetSourceAudio(tap.get(), numberOfFrames, bufferListInOut, flagsOut, &rangeOut, &itemCount);
     if (status != noErr || !itemCount)
         return;