Changeset 259363 in webkit


Ignore:
Timestamp:
Apr 1, 2020 2:15:18 PM (4 years ago)
Author:
jer.noble@apple.com
Message:

CRASH in MediaPlayerPrivateMediaSourceAVFObjC::addAudioRenderer(), uncaught ObjC exception
https://bugs.webkit.org/show_bug.cgi?id=209827
<rdar://problem/61113080>

Reviewed by Eric Carlson.

-[AVSampleBufferAudioRenderer init] can, in exceptional conditions, return nil. Passing a
nil object, or another object that AVSampleBufferRenderSynchronizer considers "invalid", into
-[AVSampleBufferRenderSynchronizer addRenderer:] will throw an exception. Protect against this
scenario in two ways:

  • Check the return value of -[AVSampleBufferAudioRenderer init], and if nil, log an error, log to console, and set the network state to "DecodeError".
  • Wrap calls to -addRenderer: in @try/@catch blocks, which if caught, log an error, assert, and set the network state to "DecodeError".
  • Modules/mediasource/MediaSource.cpp:

(WebCore::MediaSource::failedToCreateRenderer):

  • Modules/mediasource/MediaSource.h:
  • platform/graphics/MediaSourcePrivateClient.h:
  • platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaSourceAVFObjC.mm:

(WebCore::MediaPlayerPrivateMediaSourceAVFObjC::ensureLayer):

  • platform/graphics/avfoundation/objc/MediaSourcePrivateAVFObjC.h:
  • platform/graphics/avfoundation/objc/MediaSourcePrivateAVFObjC.mm:

(WebCore::MediaSourcePrivateAVFObjC::failedToCreateAudioRenderer):
(WebCore::MediaSourcePrivateAVFObjC::failedToCreateVideoRenderer):

  • platform/graphics/avfoundation/objc/SourceBufferPrivateAVFObjC.mm:

(WebCore::SourceBufferPrivateAVFObjC::trackDidChangeEnabled):

Location:
trunk/Source/WebCore
Files:
8 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r259359 r259363  
     12020-04-01  Jer Noble  <jer.noble@apple.com>
     2
     3        CRASH in MediaPlayerPrivateMediaSourceAVFObjC::addAudioRenderer(), uncaught ObjC exception
     4        https://bugs.webkit.org/show_bug.cgi?id=209827
     5        <rdar://problem/61113080>
     6
     7        Reviewed by Eric Carlson.
     8
     9        -[AVSampleBufferAudioRenderer init] can, in exceptional conditions, return nil. Passing a
     10        nil object, or another object that AVSampleBufferRenderSynchronizer considers "invalid", into
     11        -[AVSampleBufferRenderSynchronizer addRenderer:] will throw an exception. Protect against this
     12        scenario in two ways:
     13
     14        - Check the return value of -[AVSampleBufferAudioRenderer init], and if nil, log an error,
     15          log to console, and set the network state to "DecodeError".
     16        - Wrap calls to -addRenderer: in @try/@catch blocks, which if caught, log an error, assert,
     17          and set the network state to "DecodeError".
     18
     19        * Modules/mediasource/MediaSource.cpp:
     20        (WebCore::MediaSource::failedToCreateRenderer):
     21        * Modules/mediasource/MediaSource.h:
     22        * platform/graphics/MediaSourcePrivateClient.h:
     23        * platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaSourceAVFObjC.mm:
     24        (WebCore::MediaPlayerPrivateMediaSourceAVFObjC::ensureLayer):
     25        * platform/graphics/avfoundation/objc/MediaSourcePrivateAVFObjC.h:
     26        * platform/graphics/avfoundation/objc/MediaSourcePrivateAVFObjC.mm:
     27        (WebCore::MediaSourcePrivateAVFObjC::failedToCreateAudioRenderer):
     28        (WebCore::MediaSourcePrivateAVFObjC::failedToCreateVideoRenderer):
     29        * platform/graphics/avfoundation/objc/SourceBufferPrivateAVFObjC.mm:
     30        (WebCore::SourceBufferPrivateAVFObjC::trackDidChangeEnabled):
     31
    1322020-04-01  Chris Dumez  <cdumez@apple.com>
    233
  • trunk/Source/WebCore/Modules/mediasource/MediaSource.cpp

    r259299 r259363  
    10941094#endif
    10951095
     1096void MediaSource::failedToCreateRenderer(RendererType type)
     1097{
     1098    if (auto context = scriptExecutionContext())
     1099        context->addConsoleMessage(MessageSource::JS, MessageLevel::Error, makeString("MediaSource ", type == RendererType::Video ? "video" : "audio", " renderer creation failed."));
     1100}
     1101
    10961102}
    10971103
  • trunk/Source/WebCore/Modules/mediasource/MediaSource.h

    r259252 r259363  
    123123#endif
    124124
     125    void failedToCreateRenderer(RendererType) final;
     126
    125127private:
    126128    explicit MediaSource(ScriptExecutionContext&);
  • trunk/Source/WebCore/platform/graphics/MediaSourcePrivateClient.h

    r241148 r259363  
    5151    virtual void setLogIdentifier(const void*) = 0;
    5252#endif
     53
     54    enum class RendererType { Audio, Video };
     55    virtual void failedToCreateRenderer(RendererType) = 0;
    5356};
    5457
  • trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaSourceAVFObjC.mm

    r259303 r259363  
    767767#endif
    768768
     769    if (!m_sampleBufferDisplayLayer) {
     770        ERROR_LOG(LOGIDENTIFIER, "Failed to create AVSampleBufferDisplayLayer");
     771        if (m_mediaSourcePrivate)
     772            m_mediaSourcePrivate->failedToCreateRenderer(MediaSourcePrivateAVFObjC::RendererType::Video);
     773        setNetworkState(MediaPlayer::NetworkState::DecodeError);
     774        return;
     775    }
     776
    769777#if HAVE(AVSAMPLEBUFFERVIDEOOUTPUT)
    770778    ASSERT(!m_videoOutput);
     
    776784#endif
    777785
    778     ASSERT(m_sampleBufferDisplayLayer);
    779     if (!m_sampleBufferDisplayLayer) {
    780         ERROR_LOG(LOGIDENTIFIER, "Failed to create AVSampleBufferDisplayLayer");
    781         setNetworkState(MediaPlayer::NetworkState::DecodeError);
    782         return;
    783     }
    784 
    785786    if ([m_sampleBufferDisplayLayer respondsToSelector:@selector(setPreventsDisplaySleepDuringVideoPlayback:)])
    786787        m_sampleBufferDisplayLayer.get().preventsDisplaySleepDuringVideoPlayback = NO;
    787788
    788     [m_synchronizer addRenderer:m_sampleBufferDisplayLayer.get()];
     789    @try {
     790        [m_synchronizer addRenderer:m_sampleBufferDisplayLayer.get()];
     791    } @catch(NSException *exception) {
     792        ERROR_LOG(LOGIDENTIFIER, "-[AVSampleBufferRenderSynchronizer addRenderer:] threw an exception: ", [[exception name] UTF8String], ", reason : ", [[exception reason] UTF8String]);
     793        ASSERT_NOT_REACHED();
     794
     795        setNetworkState(MediaPlayer::NetworkState::DecodeError);
     796        return;
     797    }
     798
    789799    if (m_mediaSourcePrivate)
    790800        m_mediaSourcePrivate->setVideoLayer(m_sampleBufferDisplayLayer.get());
     
    11541164ALLOW_NEW_API_WITHOUT_GUARDS_END
    11551165{
     1166    if (!audioRenderer) {
     1167        ASSERT_NOT_REACHED();
     1168        return;
     1169    }
     1170
    11561171    if (!m_sampleBufferAudioRendererMap.add((__bridge CFTypeRef)audioRenderer, AudioRendererProperties()).isNewEntry)
    11571172        return;
     
    11611176    [audioRenderer setAudioTimePitchAlgorithm:(m_player->preservesPitch() ? AVAudioTimePitchAlgorithmSpectral : AVAudioTimePitchAlgorithmVarispeed)];
    11621177
    1163     [m_synchronizer addRenderer:audioRenderer];
     1178    @try {
     1179        [m_synchronizer addRenderer:audioRenderer];
     1180    } @catch(NSException *exception) {
     1181        ERROR_LOG(LOGIDENTIFIER, "-[AVSampleBufferRenderSynchronizer addRenderer:] threw an exception: ", [[exception name] UTF8String], ", reason : ", [[exception reason] UTF8String]);
     1182        ASSERT_NOT_REACHED();
     1183
     1184        setNetworkState(MediaPlayer::NetworkState::DecodeError);
     1185        return;
     1186    }
    11641187    m_player->renderingModeChanged();
    11651188}
  • trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaSourcePrivateAVFObjC.h

    r256353 r259363  
    3030
    3131#include "MediaSourcePrivate.h"
     32#include "MediaSourcePrivateClient.h"
    3233#include <wtf/Deque.h>
    3334#include <wtf/LoggerHelper.h>
     
    111112#endif
    112113
     114    using RendererType = MediaSourcePrivateClient::RendererType;
     115    void failedToCreateRenderer(RendererType);
     116
    113117private:
    114118    MediaSourcePrivateAVFObjC(MediaPlayerPrivateMediaSourceAVFObjC*, MediaSourcePrivateClient*);
  • trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaSourcePrivateAVFObjC.mm

    r253397 r259363  
    326326#endif
    327327
     328void MediaSourcePrivateAVFObjC::failedToCreateRenderer(RendererType type)
     329{
     330    m_client->failedToCreateRenderer(type);
     331}
     332
    328333}
    329334
  • trunk/Source/WebCore/platform/graphics/avfoundation/objc/SourceBufferPrivateAVFObjC.mm

    r258846 r259363  
    898898        if (!m_audioRenderers.contains(trackID)) {
    899899            renderer = adoptNS([PAL::allocAVSampleBufferAudioRendererInstance() init]);
     900
     901            if (!renderer) {
     902                ERROR_LOG(LOGIDENTIFIER, "-[AVSampleBufferAudioRenderer init] returned nil! bailing!");
     903                if (m_mediaSource)
     904                    m_mediaSource->failedToCreateRenderer(MediaSourcePrivateAVFObjC::RendererType::Audio);
     905                m_mediaSource->player()->setNetworkState(MediaPlayer::NetworkState::DecodeError);
     906                return;
     907            }
     908
    900909            auto weakThis = makeWeakPtr(*this);
    901910            [renderer requestMediaDataWhenReadyOnQueue:dispatch_get_main_queue() usingBlock:^{
Note: See TracChangeset for help on using the changeset viewer.