Bug 1270689 - Null-check WidevineDecryptor::mCallback before use. r=gerald draft
authorChris Pearce <cpearce@mozilla.com>
Mon, 09 May 2016 14:21:26 +1200
changeset 364699 e175dd8556ad50316bc16232782e593eea3e2ec8
parent 364682 bae525a694e2dc0aa433885be8751330d4995a49
child 520372 a1f1a5413ee6d2a330192a4488ba328516e66ccf
push id17548
push usercpearce@mozilla.com
push dateMon, 09 May 2016 02:58:12 +0000
reviewersgerald
bugs1270689
milestone49.0a1
Bug 1270689 - Null-check WidevineDecryptor::mCallback before use. r=gerald We've observed some crashes derefing the callback pointer, which may be occuring due to shutdown happening before init has setup the callback pointer. MozReview-Commit-ID: JsOqfjejMVI
dom/media/gmp/widevine-adapter/WidevineDecryptor.cpp
--- a/dom/media/gmp/widevine-adapter/WidevineDecryptor.cpp
+++ b/dom/media/gmp/widevine-adapter/WidevineDecryptor.cpp
@@ -32,16 +32,17 @@ void
 WidevineDecryptor::SetCDM(RefPtr<CDMWrapper> aCDM)
 {
   mCDM = aCDM;
 }
 
 void
 WidevineDecryptor::Init(GMPDecryptorCallback* aCallback)
 {
+  MOZ_ASSERT(aCallback);
   mCallback = aCallback;
   mCallback->SetCapabilities(GMP_EME_CAP_DECRYPT_AND_DECODE_VIDEO |
                              GMP_EME_CAP_DECRYPT_AUDIO);
 }
 
 static SessionType
 ToCDMSessionType(GMPSessionType aSessionType)
 {
@@ -157,16 +158,20 @@ private:
   cdm::Buffer* mBuffer;
   int64_t mTimestamp;
 };
 
 void
 WidevineDecryptor::Decrypt(GMPBuffer* aBuffer,
                            GMPEncryptedBufferMetadata* aMetadata)
 {
+  if (!mCallback) {
+    Log("WidevineDecryptor::Decrypt() this=%p FAIL; !mCallback", this);
+    return;
+  }
   const GMPEncryptedBufferMetadata* crypto = aMetadata;
   InputBuffer sample;
   nsTArray<SubsampleEntry> subsamples;
   InitInputBuffer(crypto, aBuffer->Id(), aBuffer->Data(), aBuffer->Size(), sample, subsamples);
   WidevineDecryptedBlock decrypted;
   Status rv = CDM()->Decrypt(sample, &decrypted);
   Log("Decryptor::Decrypt(timestamp=%lld) rv=%d sz=%d",
       sample.timestamp, rv, decrypted.DecryptedBuffer()->Size());
@@ -256,30 +261,38 @@ WidevineDecryptor::GetCurrentWallTime()
   return t;
 }
 
 void
 WidevineDecryptor::OnResolveNewSessionPromise(uint32_t aPromiseId,
                                               const char* aSessionId,
                                               uint32_t aSessionIdSize)
 {
+  if (!mCallback) {
+    Log("Decryptor::OnResolveNewSessionPromise(aPromiseId=0x%d) FAIL; !mCallback", aPromiseId);
+    return;
+  }
   Log("Decryptor::OnResolveNewSessionPromise(aPromiseId=0x%d)", aPromiseId);
   auto iter = mPromiseIdToNewSessionTokens.find(aPromiseId);
   if (iter == mPromiseIdToNewSessionTokens.end()) {
     Log("FAIL: Decryptor::OnResolveNewSessionPromise(aPromiseId=%d) unknown aPromiseId", aPromiseId);
     return;
   }
   mCallback->SetSessionId(iter->second, aSessionId, aSessionIdSize);
   mCallback->ResolvePromise(aPromiseId);
   mPromiseIdToNewSessionTokens.erase(iter);
 }
 
 void
 WidevineDecryptor::OnResolvePromise(uint32_t aPromiseId)
 {
+  if (!mCallback) {
+    Log("Decryptor::OnResolvePromise(aPromiseId=0x%d) FAIL; !mCallback", aPromiseId);
+    return;
+  }
   Log("Decryptor::OnResolvePromise(aPromiseId=%d)", aPromiseId);
   mCallback->ResolvePromise(aPromiseId);
 }
 
 static GMPDOMException
 ToGMPDOMException(cdm::Error aError)
 {
   switch (aError) {
@@ -296,17 +309,22 @@ ToGMPDOMException(cdm::Error aError)
 
 void
 WidevineDecryptor::OnRejectPromise(uint32_t aPromiseId,
                                    Error aError,
                                    uint32_t aSystemCode,
                                    const char* aErrorMessage,
                                    uint32_t aErrorMessageSize)
 {
-  Log("Decryptor::OnRejectPromise(aPromiseId=%d, err=%d, sysCode=%d, msg=%s)",
+  if (!mCallback) {
+    Log("Decryptor::OnRejectPromise(aPromiseId=%d, err=%d, sysCode=%u, msg=%s) FAIL; !mCallback",
+        aPromiseId, (int)aError, aSystemCode, aErrorMessage);
+    return;
+  }
+  Log("Decryptor::OnRejectPromise(aPromiseId=%d, err=%d, sysCode=%u, msg=%s)",
       aPromiseId, (int)aError, aSystemCode, aErrorMessage);
   mCallback->RejectPromise(aPromiseId,
                            ToGMPDOMException(aError),
                            !aErrorMessageSize ? "" : aErrorMessage,
                            aErrorMessageSize);
 }
 
 static GMPSessionMessageType
@@ -324,16 +342,20 @@ void
 WidevineDecryptor::OnSessionMessage(const char* aSessionId,
                                     uint32_t aSessionIdSize,
                                     MessageType aMessageType,
                                     const char* aMessage,
                                     uint32_t aMessageSize,
                                     const char* aLegacyDestinationUrl,
                                     uint32_t aLegacyDestinationUrlLength)
 {
+  if (!mCallback) {
+    Log("Decryptor::OnSessionMessage() FAIL; !mCallback");
+    return;
+  }
   Log("Decryptor::OnSessionMessage()");
   mCallback->SessionMessage(aSessionId,
                             aSessionIdSize,
                             ToGMPMessageType(aMessageType),
                             reinterpret_cast<const uint8_t*>(aMessage),
                             aMessageSize);
 }
 
@@ -354,16 +376,20 @@ ToGMPKeyStatus(KeyStatus aStatus)
 
 void
 WidevineDecryptor::OnSessionKeysChange(const char* aSessionId,
                                        uint32_t aSessionIdSize,
                                        bool aHasAdditionalUsableKey,
                                        const KeyInformation* aKeysInfo,
                                        uint32_t aKeysInfoCount)
 {
+  if (!mCallback) {
+    Log("Decryptor::OnSessionKeysChange() FAIL; !mCallback");
+    return;
+  }
   Log("Decryptor::OnSessionKeysChange()");
   for (uint32_t i = 0; i < aKeysInfoCount; i++) {
     mCallback->KeyStatusChanged(aSessionId,
                                 aSessionIdSize,
                                 aKeysInfo[i].key_id,
                                 aKeysInfo[i].key_id_size,
                                 ToGMPKeyStatus(aKeysInfo[i].status));
   }
@@ -375,41 +401,55 @@ ToGMPTime(Time aCDMTime)
   return static_cast<GMPTimestamp>(aCDMTime * 1000);
 }
 
 void
 WidevineDecryptor::OnExpirationChange(const char* aSessionId,
                                       uint32_t aSessionIdSize,
                                       Time aNewExpiryTime)
 {
+  if (!mCallback) {
+    Log("Decryptor::OnExpirationChange(sid=%s) t=%lf FAIL; !mCallback",
+        aSessionId, aNewExpiryTime);
+    return;
+  }
   Log("Decryptor::OnExpirationChange(sid=%s) t=%lf", aSessionId, aNewExpiryTime);
   GMPTimestamp expiry = ToGMPTime(aNewExpiryTime);
   if (aNewExpiryTime == 0) {
     return;
   }
   mCallback->ExpirationChange(aSessionId, aSessionIdSize, expiry);
 }
 
 void
 WidevineDecryptor::OnSessionClosed(const char* aSessionId,
                                    uint32_t aSessionIdSize)
 {
+  if (!mCallback) {
+    Log("Decryptor::OnSessionClosed(sid=%s) FAIL; !mCallback", aSessionId);
+    return;
+  }
   Log("Decryptor::OnSessionClosed(sid=%s)", aSessionId);
   mCallback->SessionClosed(aSessionId, aSessionIdSize);
 }
 
 void
 WidevineDecryptor::OnLegacySessionError(const char* aSessionId,
                                         uint32_t aSessionIdLength,
                                         Error aError,
                                         uint32_t aSystemCode,
                                         const char* aErrorMessage,
                                         uint32_t aErrorMessageLength)
 {
-  Log("Decryptor::OnSessionClosed(sid=%s, error=%d)", aSessionId, (int)aError);
+  if (!mCallback) {
+    Log("Decryptor::OnLegacySessionError(sid=%s, error=%d) FAIL; !mCallback",
+        aSessionId, (int)aError);
+    return;
+  }
+  Log("Decryptor::OnLegacySessionError(sid=%s, error=%d)", aSessionId, (int)aError);
   mCallback->SessionError(aSessionId,
                           aSessionIdLength,
                           ToGMPDOMException(aError),
                           aSystemCode,
                           aErrorMessage,
                           aErrorMessageLength);
 }