From fcc2f4d7f49c362bbbfd787aa5640dde972efcb8 Mon Sep 17 00:00:00 2001 From: ALSAMEEMA Date: Mon, 22 Jun 2026 11:50:10 +0530 Subject: [PATCH 01/12] RDKEMW-19892: [RDKEMW] [BCM Rogers Monarch IUI V2] Linear trick play (FF/RW/Seek) leads to blank screen, device hang, followed by automatic reboot. Multiple critical processes (gmem, WPENetworkProce, WorkerPoolType: etc.) crash were observed. Signed-off-by: ALSAMEEMA --- drm/helper/WidevineDrmHelper.cpp | 36 +- test/utests/tests/DrmTests/DrmHelperTests.cpp | 318 ++++++++++++++++++ 2 files changed, 350 insertions(+), 4 deletions(-) diff --git a/drm/helper/WidevineDrmHelper.cpp b/drm/helper/WidevineDrmHelper.cpp index 1305f064..c67f0385 100755 --- a/drm/helper/WidevineDrmHelper.cpp +++ b/drm/helper/WidevineDrmHelper.cpp @@ -185,17 +185,44 @@ void WidevineDrmHelper::setDrmMetaData(const std::string& metaData) void WidevineDrmHelper::setDefaultKeyID(const std::string& cencData) { std::vector defaultKeyID(cencData.begin(), cencData.end()); + + // Also convert UUID string (e.g. "f3dff538-b8c9-58e4-e8cd-96cf811d32dc") to 16-byte binary + // for comparison against binary keyIDs parsed from PSSH + std::vector defaultKeyIDBinary; + std::string uuidHex; + for (char c : cencData) + { + if (c != '-') + { + uuidHex += c; + } + } + if (uuidHex.size() == 32) + { + for (size_t i = 0; i < uuidHex.size(); i += 2) + { + uint8_t byte = (uint8_t)strtoul(uuidHex.substr(i, 2).c_str(), nullptr, 16); + defaultKeyIDBinary.push_back(byte); + } + } + if(!mKeyIDs.empty()) { for(auto& it : mKeyIDs) { - if(defaultKeyID == it.second) + if(defaultKeyID == it.second || defaultKeyIDBinary == it.second) { mDefaultKeySlot = it.first; - MW_LOG_WARN("setDefaultKeyID : %s slot : %d", PlayerLogManager::getHexDebugStr(defaultKeyID).c_str(), mDefaultKeySlot); + MW_LOG_WARN("setDefaultKeyID : %s slot : %d", PlayerLogManager::getHexDebugStr(it.second).c_str(), mDefaultKeySlot); + break; } } } + if (mDefaultKeySlot < 0 && !mKeyIDs.empty()) + { + MW_LOG_WARN("setDefaultKeyID: no match found for cencData, defaulting to slot 0"); + mDefaultKeySlot = 0; + } } @@ -217,17 +244,18 @@ void WidevineDrmHelper::getKey(std::vector& keyID) const std::string keyStr = PlayerLogManager::getHexDebugStr(keyPair.second); MW_LOG_DEBUG("Key ID [%d]: %s", keyPair.first, keyStr.c_str()); } - if ((mDefaultKeySlot >= 0) && (mDefaultKeySlot < mKeyIDs.size())) + if ((mDefaultKeySlot >= 0) && ((size_t)mDefaultKeySlot < mKeyIDs.size())) { keyID = this->mKeyIDs.at(mDefaultKeySlot); } else if (mKeyIDs.size() > 0) { + MW_LOG_WARN("mDefaultKeySlot(%d) invalid, falling back to slot 0", mDefaultKeySlot); keyID = this->mKeyIDs.at(0); } else { - MW_LOG_ERR("No key"); + MW_LOG_ERR("No key available - mKeyIDs is empty"); } } diff --git a/test/utests/tests/DrmTests/DrmHelperTests.cpp b/test/utests/tests/DrmTests/DrmHelperTests.cpp index 397faac4..672540d6 100644 --- a/test/utests/tests/DrmTests/DrmHelperTests.cpp +++ b/test/utests/tests/DrmTests/DrmHelperTests.cpp @@ -540,6 +540,324 @@ TEST_F(DrmHelperTests, TestWidevineHelperParsePsshDrmMetaData) } } +/***************************************************************************** + * RDKEMW-19892: setDefaultKeyID / getKey test suite + * + * These tests verify both WORKING and NON-WORKING (previously broken) scenarios + * to confirm the fix for the defaultkey:-1 issue during trick play. + * + * WORKING SCENARIOS (pass before AND after fix): + * - Raw binary bytes as string (how existing tests called setDefaultKeyID) + * - getKey fallback to slot 0 when setDefaultKeyID not called + * + * PREVIOUSLY BROKEN SCENARIOS (FAIL before fix, PASS after fix): + * - UUID string with hyphens (real DASH manifest cenc:default_KID format) + * - Multi-key PSSH with UUID selecting non-zero slot + * - UUID lowercase/uppercase variants + *****************************************************************************/ + +/** + * WORKING SCENARIO 1: Raw binary bytes as string (old test pattern) + * + * This is how existing tests used setDefaultKeyID — passing the raw binary + * key bytes directly as a std::string. This trivially matches because the + * comparison is byte-for-byte identical. + * + * STATUS: PASS before fix, PASS after fix + */ +TEST_F(DrmHelperTests, RDKEMW19892_Working_RawBinaryBytesAsString) +{ + // PSSH Version 1 with single key: 2db6c48d-301f-48ea-bb77-1ba7a8ac9042 + const char *psshBase64 = "AAAANHBzc2gBAAAA7e+LqXnWSs6jyCfc1R0h7QAAAAEttsSNMB9I6rt3G6eorJBCAAAAAA=="; + size_t psshDataLen = 0; + unsigned char *psshDataPtr = base64_Decode(psshBase64, &psshDataLen, strlen(psshBase64)); + ASSERT_NE(psshDataPtr, nullptr); + + DrmInfo drmInfo = createDrmInfo(eMETHOD_AES_128, eMEDIAFORMAT_DASH, "file.key", "", + "edef8ba9-79d6-4ace-a3c8-27dcd51d21ed"); + std::shared_ptr widevineHelper = DrmHelperEngine::getInstance().createHelper(drmInfo); + ASSERT_NE(widevineHelper, nullptr); + ASSERT_TRUE(widevineHelper->parsePssh(psshDataPtr, (uint32_t)psshDataLen)); + + std::map> keyIDs; + widevineHelper->getKeys(keyIDs); + ASSERT_GE(keyIDs.size(), 1u); + + std::vector expectedKey = {0x2D, 0xB6, 0xC4, 0x8D, 0x30, 0x1F, 0x48, 0xEA, + 0xBB, 0x77, 0x1B, 0xA7, 0xA8, 0xAC, 0x90, 0x42}; + ASSERT_EQ(keyIDs[0], expectedKey); + + // Pass raw binary as string (this is how old tests did it — always worked) + std::string defaultKeyStr(keyIDs[0].begin(), keyIDs[0].end()); + widevineHelper->setDefaultKeyID(defaultKeyStr); + + std::vector keyID; + widevineHelper->getKey(keyID); + EXPECT_EQ(keyID, expectedKey) << "Raw binary setDefaultKeyID must work (always worked)"; + + free(psshDataPtr); +} + +/** + * WORKING SCENARIO 2: getKey without setDefaultKeyID (fallback to slot 0) + * + * Simulates the race condition during trick play where createHelper completes + * and parsePssh populates mKeyIDs, but setDefaultKeyID hasn't been called yet. + * getKey must still return a valid key (slot 0 fallback). + * + * STATUS: PASS before fix, PASS after fix + */ +TEST_F(DrmHelperTests, RDKEMW19892_Working_GetKeyFallbackWithoutSetDefault) +{ + const char *psshBase64 = "AAAANHBzc2gBAAAA7e+LqXnWSs6jyCfc1R0h7QAAAAEttsSNMB9I6rt3G6eorJBCAAAAAA=="; + size_t psshDataLen = 0; + unsigned char *psshDataPtr = base64_Decode(psshBase64, &psshDataLen, strlen(psshBase64)); + ASSERT_NE(psshDataPtr, nullptr); + + DrmInfo drmInfo = createDrmInfo(eMETHOD_AES_128, eMEDIAFORMAT_DASH, "file.key", "", + "edef8ba9-79d6-4ace-a3c8-27dcd51d21ed"); + std::shared_ptr widevineHelper = DrmHelperEngine::getInstance().createHelper(drmInfo); + ASSERT_NE(widevineHelper, nullptr); + ASSERT_TRUE(widevineHelper->parsePssh(psshDataPtr, (uint32_t)psshDataLen)); + + // DO NOT call setDefaultKeyID — mDefaultKeySlot stays -1 + // getKey should still return slot 0 key (fallback behavior) + std::vector keyID; + widevineHelper->getKey(keyID); + EXPECT_FALSE(keyID.empty()) << "getKey must return a valid key even without setDefaultKeyID"; + + std::vector expectedKey = {0x2D, 0xB6, 0xC4, 0x8D, 0x30, 0x1F, 0x48, 0xEA, + 0xBB, 0x77, 0x1B, 0xA7, 0xA8, 0xAC, 0x90, 0x42}; + EXPECT_EQ(keyID, expectedKey) << "Fallback to slot 0 must return the first key"; + + free(psshDataPtr); +} + +/** + * WORKING SCENARIO 3: Multi-key, raw binary setDefaultKeyID selects slot 1 + * + * STATUS: PASS before fix, PASS after fix + */ +TEST_F(DrmHelperTests, RDKEMW19892_Working_MultiKeyRawBinarySelectsCorrectSlot) +{ + // PSSH Version 1 with 2 keys: + // Key 0: all zeros, Key 1: all 0x11 + const char *psshBase64 = "AAAARHBzc2gBAAAA7e+LqXnWSs6jyCfc1R0h7QAAAAIAAAAAAAAAAAAAAAAAAAAAEREREREREREREREREREREQAAAAA="; + size_t psshDataLen = 0; + unsigned char *psshDataPtr = base64_Decode(psshBase64, &psshDataLen, strlen(psshBase64)); + ASSERT_NE(psshDataPtr, nullptr); + + DrmInfo drmInfo = createDrmInfo(eMETHOD_AES_128, eMEDIAFORMAT_DASH, "file.key", "", + "edef8ba9-79d6-4ace-a3c8-27dcd51d21ed"); + std::shared_ptr widevineHelper = DrmHelperEngine::getInstance().createHelper(drmInfo); + ASSERT_NE(widevineHelper, nullptr); + ASSERT_TRUE(widevineHelper->parsePssh(psshDataPtr, (uint32_t)psshDataLen)); + + std::map> keyIDs; + widevineHelper->getKeys(keyIDs); + ASSERT_EQ(keyIDs.size(), 2u); + + std::vector key1 = {0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11, + 0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11}; + + // Pass raw binary of key1 as string — this always worked + std::string defaultKeyStr(keyIDs[1].begin(), keyIDs[1].end()); + widevineHelper->setDefaultKeyID(defaultKeyStr); + + std::vector keyID; + widevineHelper->getKey(keyID); + EXPECT_EQ(keyID, key1) << "Raw binary setDefaultKeyID must select correct slot (slot 1)"; + + free(psshDataPtr); +} + +/** + * NON-WORKING SCENARIO 1 (BROKEN BEFORE FIX): + * UUID string with hyphens — real DASH manifest format + * + * This is the ACTUAL format from cenc:default_KID in production DASH manifests. + * The manifest has: cenc:default_KID="2db6c48d-301f-48ea-bb77-1ba7a8ac9042" + * CreateDrmHelper extracts this string and passes it directly to setDefaultKeyID. + * + * BEFORE FIX: setDefaultKeyID converts "2db6c48d-301f-48ea-bb77-1ba7a8ac9042" + * to 36 ASCII bytes and compares against 16-byte binary keys. + * NEVER matches → mDefaultKeySlot stays -1 → defaultkey:-1 in logs + * + * AFTER FIX: UUID string is hex-decoded to 16-byte binary before comparison. + * Matches correctly → mDefaultKeySlot = 0 → correct key returned + * + * STATUS: FAIL before fix, PASS after fix + */ +TEST_F(DrmHelperTests, RDKEMW19892_Broken_UUIDFormatNeverMatchedBinaryKeys) +{ + // PSSH with single 16-byte binary key: 2db6c48d301f48eabb771ba7a8ac9042 + const char *psshBase64 = "AAAANHBzc2gBAAAA7e+LqXnWSs6jyCfc1R0h7QAAAAEttsSNMB9I6rt3G6eorJBCAAAAAA=="; + size_t psshDataLen = 0; + unsigned char *psshDataPtr = base64_Decode(psshBase64, &psshDataLen, strlen(psshBase64)); + ASSERT_NE(psshDataPtr, nullptr); + + DrmInfo drmInfo = createDrmInfo(eMETHOD_AES_128, eMEDIAFORMAT_DASH, "file.key", "", + "edef8ba9-79d6-4ace-a3c8-27dcd51d21ed"); + ASSERT_TRUE(DrmHelperEngine::getInstance().hasDRM(drmInfo)); + std::shared_ptr widevineHelper = DrmHelperEngine::getInstance().createHelper(drmInfo); + ASSERT_NE(widevineHelper, nullptr); + ASSERT_TRUE(widevineHelper->parsePssh(psshDataPtr, (uint32_t)psshDataLen)); + + std::map> keyIDs; + widevineHelper->getKeys(keyIDs); + ASSERT_GE(keyIDs.size(), 1u); + + std::vector expectedBinaryKey = {0x2D, 0xB6, 0xC4, 0x8D, 0x30, 0x1F, 0x48, 0xEA, + 0xBB, 0x77, 0x1B, 0xA7, 0xA8, 0xAC, 0x90, 0x42}; + ASSERT_EQ(keyIDs[0], expectedBinaryKey); + + // THIS IS THE REAL PRODUCTION FORMAT: UUID with hyphens from manifest + // + std::string cencDefaultKID = "2db6c48d-301f-48ea-bb77-1ba7a8ac9042"; + widevineHelper->setDefaultKeyID(cencDefaultKID); + + // BEFORE FIX: getKey would log "defaultkey: -1" and fall to slot 0 by luck + // (which happens to be correct here since there's only 1 key, but wrong for multi-key) + // AFTER FIX: mDefaultKeySlot is properly set to 0 + std::vector keyID; + widevineHelper->getKey(keyID); + EXPECT_FALSE(keyID.empty()) << "getKey must not return empty with UUID format cenc:default_KID"; + EXPECT_EQ(keyID, expectedBinaryKey) << "UUID format must correctly match binary PSSH key"; + + free(psshDataPtr); +} + +/** + * NON-WORKING SCENARIO 2 (BROKEN BEFORE FIX): + * Multi-key PSSH with UUID selecting a NON-ZERO slot + * + * This is the CRITICAL case that caused the production crash. + * With 2+ keys, if setDefaultKeyID fails to match, getKey falls back to slot 0. + * But the manifest's cenc:default_KID may point to slot 1, 2, or 3. + * Returning the WRONG key causes the decryptor to fail → NULL caps → crash. + * + * BEFORE FIX: UUID "11111111-1111-1111-1111-111111111111" → 36 ASCII bytes + * compared against 16-byte binary → NO MATCH → mDefaultKeySlot=-1 + * → getKey returns slot 0 (key0 = all zeros) → WRONG KEY USED + * → decryptor fails → GStreamer-CRITICAL: gst_caps_merge NULL + * + * AFTER FIX: UUID hex-decoded to {0x11,0x11,...} → matches slot 1 → correct key + * + * STATUS: FAIL before fix, PASS after fix + */ +TEST_F(DrmHelperTests, RDKEMW19892_Broken_MultiKeyUUIDSelectsWrongSlot) +{ + // PSSH Version 1 with 2 key IDs: + // Key 0: 00000000-0000-0000-0000-000000000000 (all zeros) + // Key 1: 11111111-1111-1111-1111-111111111111 (all 0x11) + const char *psshBase64 = "AAAARHBzc2gBAAAA7e+LqXnWSs6jyCfc1R0h7QAAAAIAAAAAAAAAAAAAAAAAAAAAEREREREREREREREREREREQAAAAA="; + size_t psshDataLen = 0; + unsigned char *psshDataPtr = base64_Decode(psshBase64, &psshDataLen, strlen(psshBase64)); + ASSERT_NE(psshDataPtr, nullptr); + + DrmInfo drmInfo = createDrmInfo(eMETHOD_AES_128, eMEDIAFORMAT_DASH, "file.key", "", + "edef8ba9-79d6-4ace-a3c8-27dcd51d21ed"); + std::shared_ptr widevineHelper = DrmHelperEngine::getInstance().createHelper(drmInfo); + ASSERT_NE(widevineHelper, nullptr); + ASSERT_TRUE(widevineHelper->parsePssh(psshDataPtr, (uint32_t)psshDataLen)); + + std::map> keyIDs; + widevineHelper->getKeys(keyIDs); + ASSERT_EQ(keyIDs.size(), 2u); + + std::vector key0 = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; + std::vector key1 = {0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11, + 0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11}; + ASSERT_EQ(keyIDs[0], key0); + ASSERT_EQ(keyIDs[1], key1); + + // Manifest says: cenc:default_KID="11111111-1111-1111-1111-111111111111" + // This should select KEY 1 (slot 1) + std::string cencDefaultKID = "11111111-1111-1111-1111-111111111111"; + widevineHelper->setDefaultKeyID(cencDefaultKID); + + std::vector keyID; + widevineHelper->getKey(keyID); + + // BEFORE FIX: Returns key0 (slot 0 fallback) → WRONG KEY → crash downstream + // AFTER FIX: Returns key1 (slot 1 correct) → correct decryption + EXPECT_NE(keyID, key0) << "BEFORE-FIX BEHAVIOR: fell back to slot 0 (wrong key!)"; + EXPECT_EQ(keyID, key1) << "AFTER-FIX: UUID must correctly select slot 1"; + + free(psshDataPtr); +} + +/** + * NON-WORKING SCENARIO 3 (BROKEN BEFORE FIX): + * UUID with uppercase hex digits + * + * Some DASH manifest generators use uppercase in cenc:default_KID. + * e.g., cenc:default_KID="2DB6C48D-301F-48EA-BB77-1BA7A8AC9042" + * The fix must handle case-insensitive hex conversion. + * + * STATUS: FAIL before fix, PASS after fix + */ +TEST_F(DrmHelperTests, RDKEMW19892_Broken_UUIDUppercaseHex) +{ + const char *psshBase64 = "AAAANHBzc2gBAAAA7e+LqXnWSs6jyCfc1R0h7QAAAAEttsSNMB9I6rt3G6eorJBCAAAAAA=="; + size_t psshDataLen = 0; + unsigned char *psshDataPtr = base64_Decode(psshBase64, &psshDataLen, strlen(psshBase64)); + ASSERT_NE(psshDataPtr, nullptr); + + DrmInfo drmInfo = createDrmInfo(eMETHOD_AES_128, eMEDIAFORMAT_DASH, "file.key", "", + "edef8ba9-79d6-4ace-a3c8-27dcd51d21ed"); + std::shared_ptr widevineHelper = DrmHelperEngine::getInstance().createHelper(drmInfo); + ASSERT_NE(widevineHelper, nullptr); + ASSERT_TRUE(widevineHelper->parsePssh(psshDataPtr, (uint32_t)psshDataLen)); + + std::vector expectedKey = {0x2D, 0xB6, 0xC4, 0x8D, 0x30, 0x1F, 0x48, 0xEA, + 0xBB, 0x77, 0x1B, 0xA7, 0xA8, 0xAC, 0x90, 0x42}; + + // UPPERCASE UUID — some CDN/manifest generators produce this + std::string cencDefaultKID = "2DB6C48D-301F-48EA-BB77-1BA7A8AC9042"; + widevineHelper->setDefaultKeyID(cencDefaultKID); + + std::vector keyID; + widevineHelper->getKey(keyID); + EXPECT_EQ(keyID, expectedKey) << "Uppercase UUID must also correctly match binary PSSH key"; + + free(psshDataPtr); +} + +/** + * NON-WORKING SCENARIO 4 (BROKEN BEFORE FIX): + * UUID without hyphens (some implementations strip hyphens) + * + * STATUS: FAIL before fix, PASS after fix (due to fallback to slot 0) + */ +TEST_F(DrmHelperTests, RDKEMW19892_Broken_UUIDWithoutHyphens) +{ + const char *psshBase64 = "AAAANHBzc2gBAAAA7e+LqXnWSs6jyCfc1R0h7QAAAAEttsSNMB9I6rt3G6eorJBCAAAAAA=="; + size_t psshDataLen = 0; + unsigned char *psshDataPtr = base64_Decode(psshBase64, &psshDataLen, strlen(psshBase64)); + ASSERT_NE(psshDataPtr, nullptr); + + DrmInfo drmInfo = createDrmInfo(eMETHOD_AES_128, eMEDIAFORMAT_DASH, "file.key", "", + "edef8ba9-79d6-4ace-a3c8-27dcd51d21ed"); + std::shared_ptr widevineHelper = DrmHelperEngine::getInstance().createHelper(drmInfo); + ASSERT_NE(widevineHelper, nullptr); + ASSERT_TRUE(widevineHelper->parsePssh(psshDataPtr, (uint32_t)psshDataLen)); + + std::vector expectedKey = {0x2D, 0xB6, 0xC4, 0x8D, 0x30, 0x1F, 0x48, 0xEA, + 0xBB, 0x77, 0x1B, 0xA7, 0xA8, 0xAC, 0x90, 0x42}; + + // UUID without hyphens (32 hex chars) — also valid + std::string cencDefaultKID = "2db6c48d301f48eabb771ba7a8ac9042"; + widevineHelper->setDefaultKeyID(cencDefaultKID); + + std::vector keyID; + widevineHelper->getKey(keyID); + EXPECT_EQ(keyID, expectedKey) << "UUID without hyphens must also match binary PSSH key"; + + free(psshDataPtr); +} + TEST_F(DrmHelperTests, TestCreateWidevineHelper) { const std::vector testData = { From bd753ba99f19153323e65b3a1258641c2d09d6f8 Mon Sep 17 00:00:00 2001 From: Alsameema Date: Mon, 22 Jun 2026 11:56:29 +0530 Subject: [PATCH 02/12] Merge branch 'develop' into feature/RDKEMW-19892 --- drm/ocdm/OcdmGstSessionAdapter.cpp | 2 +- gst-plugins/drm/gst/gstcdmidecryptor.cpp | 28 +++++++++++++++++++++--- gst-plugins/drm/gst/gstcdmidecryptor.h | 1 + 3 files changed, 27 insertions(+), 4 deletions(-) diff --git a/drm/ocdm/OcdmGstSessionAdapter.cpp b/drm/ocdm/OcdmGstSessionAdapter.cpp index f05993ed..999b1698 100755 --- a/drm/ocdm/OcdmGstSessionAdapter.cpp +++ b/drm/ocdm/OcdmGstSessionAdapter.cpp @@ -325,7 +325,7 @@ int OCDMGSTSessionAdapter::decrypt(GstBuffer *keyIDBuffer, GstBuffer *ivBuffer, /* Added GST_IS_CAPS check also before passing gst caps to OCDM decrypt() as gst_caps_is_empty returns false when caps object is not of type GST_TYPE_CAPS. This will avoid crash when caps is not of type GST_TYPE_CAPS. */ - if (OCDMGSTSessionDecrypt && !gst_caps_is_empty(caps) && GST_IS_CAPS(caps)) + if (OCDMGSTSessionDecrypt && caps != nullptr && GST_IS_CAPS(caps) && !gst_caps_is_empty(caps)) { GstProtectionMeta* protectionMeta = reinterpret_cast(gst_buffer_get_protection_meta(buffer)); diff --git a/gst-plugins/drm/gst/gstcdmidecryptor.cpp b/gst-plugins/drm/gst/gstcdmidecryptor.cpp index dad25fbd..4482a34c 100755 --- a/gst-plugins/drm/gst/gstcdmidecryptor.cpp +++ b/gst-plugins/drm/gst/gstcdmidecryptor.cpp @@ -219,6 +219,7 @@ static void gst_cdmidecryptor_init( g_mutex_init(&cdmidecryptor->mutex); //GST_DEBUG_OBJECT(cdmidecryptor, "\n Initialized plugin mutex\n"); g_cond_init(&cdmidecryptor->condition); + g_cond_init(&cdmidecryptor->sinkCapsCond); cdmidecryptor->streamReceived = false; // Lock access to protect shared state to keep Coverity happy g_mutex_lock(&cdmidecryptor->mutex); @@ -269,8 +270,9 @@ void gst_cdmidecryptor_dispose(GObject * object) cdmidecryptor->sinkCaps = NULL; } - g_mutex_clear(&cdmidecryptor->mutex); + g_cond_clear(&cdmidecryptor->sinkCapsCond); g_cond_clear(&cdmidecryptor->condition); + g_mutex_clear(&cdmidecryptor->mutex); G_OBJECT_CLASS(gst_cdmidecryptor_parent_class)->dispose(object); } @@ -467,6 +469,7 @@ gst_cdmidecryptor_transform_caps(GstBaseTransform * trans, cdmidecryptor->sinkCaps = NULL; } cdmidecryptor->sinkCaps = gst_caps_copy(transformedCaps); + g_cond_signal(&cdmidecryptor->sinkCapsCond); g_mutex_unlock(&cdmidecryptor->mutex); GST_DEBUG_OBJECT(trans, "Set sinkCaps to %" GST_PTR_FORMAT, cdmidecryptor->sinkCaps); } @@ -512,6 +515,19 @@ static GstFlowReturn gst_cdmidecryptor_transform_ip( g_mutex_lock(&cdmidecryptor->mutex); mutexLocked = TRUE; + + if (cdmidecryptor->sinkCaps == NULL && cdmidecryptor->streamReceived) { + // Caps negotiation hasn't completed yet - wait briefly + gint64 end_time = g_get_monotonic_time() + 500 * G_TIME_SPAN_MILLISECOND; + while (cdmidecryptor->sinkCaps == NULL) { + if (!g_cond_wait_until(&cdmidecryptor->sinkCapsCond, &cdmidecryptor->mutex, end_time)) { + GST_WARNING_OBJECT(cdmidecryptor, "Timeout waiting for sinkCaps"); + result = GST_FLOW_NOT_SUPPORTED; + goto free_resources; + } + } + } + if (!protectionMeta) { GST_DEBUG_OBJECT(cdmidecryptor, @@ -520,12 +536,12 @@ static GstFlowReturn gst_cdmidecryptor_transform_ip( { // call decrypt even for clear samples in order to copy it to a secure buffer. If secure buffers are not supported // decrypt() call will return without doing anything - if (cdmidecryptor->drmSession != NULL) + if (cdmidecryptor->drmSession != NULL && cdmidecryptor->sinkCaps != NULL) errorCode = cdmidecryptor->drmSession->decrypt(keyIDBuffer, ivBuffer, buffer, subSampleCount, subsamplesBuffer, cdmidecryptor->sinkCaps); else { /* If drmSession creation failed, then the call will be aborted here */ result = GST_FLOW_NOT_SUPPORTED; - GST_ERROR_OBJECT(cdmidecryptor, "drmSession is **** NULL ****, returning GST_FLOW_NOT_SUPPORTED"); + GST_ERROR_OBJECT(cdmidecryptor, "drmSession or sinkCaps is NULL, returning GST_FLOW_NOT_SUPPORTED"); } } goto free_resources; @@ -638,6 +654,12 @@ static GstFlowReturn gst_cdmidecryptor_transform_ip( } } + if (cdmidecryptor->sinkCaps == NULL) { + GST_WARNING_OBJECT(cdmidecryptor, "sinkCaps is NULL, skipping decrypt"); + result = GST_FLOW_NOT_SUPPORTED; + goto free_resources; + } + errorCode = cdmidecryptor->drmSession->decrypt(keyIDBuffer, ivBuffer, buffer, subSampleCount, subsamplesBuffer, cdmidecryptor->sinkCaps); cdmidecryptor->streamEncrypted = true; diff --git a/gst-plugins/drm/gst/gstcdmidecryptor.h b/gst-plugins/drm/gst/gstcdmidecryptor.h index aeaff207..2e2cc33d 100644 --- a/gst-plugins/drm/gst/gstcdmidecryptor.h +++ b/gst-plugins/drm/gst/gstcdmidecryptor.h @@ -55,6 +55,7 @@ struct _GstCDMIDecryptor GMutex mutex; GCond condition; + GCond sinkCapsCond; GstEvent* protectionEvent; const gchar* selectedProtection; From a37494f2af9ce5d08d6d255d93b9fd0c6d1f0ab0 Mon Sep 17 00:00:00 2001 From: Alsameema Date: Mon, 22 Jun 2026 12:14:57 +0530 Subject: [PATCH 03/12] Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- drm/helper/WidevineDrmHelper.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drm/helper/WidevineDrmHelper.cpp b/drm/helper/WidevineDrmHelper.cpp index c67f0385..4a8531c2 100755 --- a/drm/helper/WidevineDrmHelper.cpp +++ b/drm/helper/WidevineDrmHelper.cpp @@ -184,8 +184,8 @@ void WidevineDrmHelper::setDrmMetaData(const std::string& metaData) void WidevineDrmHelper::setDefaultKeyID(const std::string& cencData) { + mDefaultKeySlot = -1; std::vector defaultKeyID(cencData.begin(), cencData.end()); - // Also convert UUID string (e.g. "f3dff538-b8c9-58e4-e8cd-96cf811d32dc") to 16-byte binary // for comparison against binary keyIDs parsed from PSSH std::vector defaultKeyIDBinary; From 85fbba0c17d8d2d01cf7248bd62185126bb18269 Mon Sep 17 00:00:00 2001 From: Alsameema Date: Mon, 22 Jun 2026 12:22:50 +0530 Subject: [PATCH 04/12] RDKEMW-19892: [RDKEMW] [BCM Rogers Monarch IUI V2] Linear trick play (FF/RW/Seek) leads to blank screen, device hang, followed by automatic reboot. Multiple critical processes (gmem, WPENetworkProce, WorkerPoolType: etc.) crash were observed. --- drm/helper/WidevineDrmHelper.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drm/helper/WidevineDrmHelper.cpp b/drm/helper/WidevineDrmHelper.cpp index 4a8531c2..9d58db26 100755 --- a/drm/helper/WidevineDrmHelper.cpp +++ b/drm/helper/WidevineDrmHelper.cpp @@ -201,8 +201,11 @@ void WidevineDrmHelper::setDefaultKeyID(const std::string& cencData) { for (size_t i = 0; i < uuidHex.size(); i += 2) { - uint8_t byte = (uint8_t)strtoul(uuidHex.substr(i, 2).c_str(), nullptr, 16); - defaultKeyIDBinary.push_back(byte); + std::string hexPair = uuidHex.substr(i, 2); // lives until end of iteration + char* end = nullptr; + unsigned long v = strtoul(hexPair.c_str(), &end, 16); + if (!end || *end != '\0') { defaultKeyIDBinary.clear(); break; } + defaultKeyIDBinary.push_back(static_cast(v)); } } From f80c2b47358813c40839616c144d5051db0c6567 Mon Sep 17 00:00:00 2001 From: ALSAMEEMA Date: Mon, 22 Jun 2026 12:34:01 +0530 Subject: [PATCH 05/12] RDKEMW-19892: [RDKEMW] [BCM Rogers Monarch IUI V2] Linear trick play (FF/RW/Seek) leads to blank screen, device hang, followed by automatic reboot. Multiple critical processes (gmem, WPENetworkProce, WorkerPoolType: etc.) crash were observed. Signed-off-by: ALSAMEEMA --- test/utests/tests/DrmTests/DrmHelperTests.cpp | 303 +++--------------- 1 file changed, 42 insertions(+), 261 deletions(-) diff --git a/test/utests/tests/DrmTests/DrmHelperTests.cpp b/test/utests/tests/DrmTests/DrmHelperTests.cpp index 672540d6..646bbb52 100644 --- a/test/utests/tests/DrmTests/DrmHelperTests.cpp +++ b/test/utests/tests/DrmTests/DrmHelperTests.cpp @@ -541,7 +541,7 @@ TEST_F(DrmHelperTests, TestWidevineHelperParsePsshDrmMetaData) } /***************************************************************************** - * RDKEMW-19892: setDefaultKeyID / getKey test suite + * setDefaultKeyID / getKey test suite * * These tests verify both WORKING and NON-WORKING (previously broken) scenarios * to confirm the fix for the defaultkey:-1 issue during trick play. @@ -681,17 +681,19 @@ TEST_F(DrmHelperTests, RDKEMW19892_Working_MultiKeyRawBinarySelectsCorrectSlot) * * BEFORE FIX: setDefaultKeyID converts "2db6c48d-301f-48ea-bb77-1ba7a8ac9042" * to 36 ASCII bytes and compares against 16-byte binary keys. - * NEVER matches → mDefaultKeySlot stays -1 → defaultkey:-1 in logs + * NEVER matches → mDefaultKeySlot stays -1 → getKey falls back to slot 0 + * → returns dummy key (0xAA...) instead of the real key at slot 1 * * AFTER FIX: UUID string is hex-decoded to 16-byte binary before comparison. - * Matches correctly → mDefaultKeySlot = 0 → correct key returned + * Matches correctly → mDefaultKeySlot = 1 → correct key returned * * STATUS: FAIL before fix, PASS after fix */ TEST_F(DrmHelperTests, RDKEMW19892_Broken_UUIDFormatNeverMatchedBinaryKeys) { - // PSSH with single 16-byte binary key: 2db6c48d301f48eabb771ba7a8ac9042 - const char *psshBase64 = "AAAANHBzc2gBAAAA7e+LqXnWSs6jyCfc1R0h7QAAAAEttsSNMB9I6rt3G6eorJBCAAAAAA=="; + // Multi-key PSSH: Key0 = all 0xAA (dummy), Key1 = 2db6c48d301f48eabb771ba7a8ac9042 (target) + // The target key is at slot 1, so slot-0 fallback returns the WRONG key. + const char *psshBase64 = "AAAARHBzc2gBAAAA7e+LqXnWSs6jyCfc1R0h7QAAAAKqqqqqqqqqqqqqqqqqqqqqLbbEjTAfSOq7dxunqKyQQgAAAAA="; size_t psshDataLen = 0; unsigned char *psshDataPtr = base64_Decode(psshBase64, &psshDataLen, strlen(psshBase64)); ASSERT_NE(psshDataPtr, nullptr); @@ -705,24 +707,27 @@ TEST_F(DrmHelperTests, RDKEMW19892_Broken_UUIDFormatNeverMatchedBinaryKeys) std::map> keyIDs; widevineHelper->getKeys(keyIDs); - ASSERT_GE(keyIDs.size(), 1u); + ASSERT_EQ(keyIDs.size(), 2u); - std::vector expectedBinaryKey = {0x2D, 0xB6, 0xC4, 0x8D, 0x30, 0x1F, 0x48, 0xEA, - 0xBB, 0x77, 0x1B, 0xA7, 0xA8, 0xAC, 0x90, 0x42}; - ASSERT_EQ(keyIDs[0], expectedBinaryKey); + std::vector dummyKey = {0xAA,0xAA,0xAA,0xAA,0xAA,0xAA,0xAA,0xAA, + 0xAA,0xAA,0xAA,0xAA,0xAA,0xAA,0xAA,0xAA}; + std::vector targetKey = {0x2D, 0xB6, 0xC4, 0x8D, 0x30, 0x1F, 0x48, 0xEA, + 0xBB, 0x77, 0x1B, 0xA7, 0xA8, 0xAC, 0x90, 0x42}; + ASSERT_EQ(keyIDs[0], dummyKey); + ASSERT_EQ(keyIDs[1], targetKey); // THIS IS THE REAL PRODUCTION FORMAT: UUID with hyphens from manifest // std::string cencDefaultKID = "2db6c48d-301f-48ea-bb77-1ba7a8ac9042"; widevineHelper->setDefaultKeyID(cencDefaultKID); - // BEFORE FIX: getKey would log "defaultkey: -1" and fall to slot 0 by luck - // (which happens to be correct here since there's only 1 key, but wrong for multi-key) - // AFTER FIX: mDefaultKeySlot is properly set to 0 + // BEFORE FIX: UUID (36 ASCII bytes) never matches binary keys → mDefaultKeySlot=-1 + // → getKey falls back to slot 0 (dummyKey) → WRONG KEY + // AFTER FIX: UUID hex-decoded to binary → matches slot 1 → correct key std::vector keyID; widevineHelper->getKey(keyID); - EXPECT_FALSE(keyID.empty()) << "getKey must not return empty with UUID format cenc:default_KID"; - EXPECT_EQ(keyID, expectedBinaryKey) << "UUID format must correctly match binary PSSH key"; + EXPECT_NE(keyID, dummyKey) << "BEFORE-FIX BEHAVIOR: fell back to slot 0 (wrong key!)"; + EXPECT_EQ(keyID, targetKey) << "UUID format must correctly select slot 1 (target key)"; free(psshDataPtr); } @@ -800,7 +805,8 @@ TEST_F(DrmHelperTests, RDKEMW19892_Broken_MultiKeyUUIDSelectsWrongSlot) */ TEST_F(DrmHelperTests, RDKEMW19892_Broken_UUIDUppercaseHex) { - const char *psshBase64 = "AAAANHBzc2gBAAAA7e+LqXnWSs6jyCfc1R0h7QAAAAEttsSNMB9I6rt3G6eorJBCAAAAAA=="; + // Multi-key PSSH: Key0 = all 0xAA (dummy), Key1 = 2db6c48d301f48eabb771ba7a8ac9042 (target) + const char *psshBase64 = "AAAARHBzc2gBAAAA7e+LqXnWSs6jyCfc1R0h7QAAAAKqqqqqqqqqqqqqqqqqqqqqLbbEjTAfSOq7dxunqKyQQgAAAAA="; size_t psshDataLen = 0; unsigned char *psshDataPtr = base64_Decode(psshBase64, &psshDataLen, strlen(psshBase64)); ASSERT_NE(psshDataPtr, nullptr); @@ -811,16 +817,20 @@ TEST_F(DrmHelperTests, RDKEMW19892_Broken_UUIDUppercaseHex) ASSERT_NE(widevineHelper, nullptr); ASSERT_TRUE(widevineHelper->parsePssh(psshDataPtr, (uint32_t)psshDataLen)); - std::vector expectedKey = {0x2D, 0xB6, 0xC4, 0x8D, 0x30, 0x1F, 0x48, 0xEA, - 0xBB, 0x77, 0x1B, 0xA7, 0xA8, 0xAC, 0x90, 0x42}; + std::vector dummyKey = {0xAA,0xAA,0xAA,0xAA,0xAA,0xAA,0xAA,0xAA, + 0xAA,0xAA,0xAA,0xAA,0xAA,0xAA,0xAA,0xAA}; + std::vector targetKey = {0x2D, 0xB6, 0xC4, 0x8D, 0x30, 0x1F, 0x48, 0xEA, + 0xBB, 0x77, 0x1B, 0xA7, 0xA8, 0xAC, 0x90, 0x42}; // UPPERCASE UUID — some CDN/manifest generators produce this + // Must select slot 1 (targetKey), NOT fall back to slot 0 (dummyKey) std::string cencDefaultKID = "2DB6C48D-301F-48EA-BB77-1BA7A8AC9042"; widevineHelper->setDefaultKeyID(cencDefaultKID); std::vector keyID; widevineHelper->getKey(keyID); - EXPECT_EQ(keyID, expectedKey) << "Uppercase UUID must also correctly match binary PSSH key"; + EXPECT_NE(keyID, dummyKey) << "BEFORE-FIX BEHAVIOR: fell back to slot 0 (wrong key!)"; + EXPECT_EQ(keyID, targetKey) << "Uppercase UUID must correctly select slot 1"; free(psshDataPtr); } @@ -829,11 +839,16 @@ TEST_F(DrmHelperTests, RDKEMW19892_Broken_UUIDUppercaseHex) * NON-WORKING SCENARIO 4 (BROKEN BEFORE FIX): * UUID without hyphens (some implementations strip hyphens) * - * STATUS: FAIL before fix, PASS after fix (due to fallback to slot 0) + * BEFORE FIX: 32-char hex string (32 ASCII bytes) compared against 16-byte binary + * → no match → slot-0 fallback → wrong key + * AFTER FIX: Hex-decoded to 16 bytes → matches slot 1 → correct key + * + * STATUS: FAIL before fix, PASS after fix */ TEST_F(DrmHelperTests, RDKEMW19892_Broken_UUIDWithoutHyphens) { - const char *psshBase64 = "AAAANHBzc2gBAAAA7e+LqXnWSs6jyCfc1R0h7QAAAAEttsSNMB9I6rt3G6eorJBCAAAAAA=="; + // Multi-key PSSH: Key0 = all 0xAA (dummy), Key1 = 2db6c48d301f48eabb771ba7a8ac9042 (target) + const char *psshBase64 = "AAAARHBzc2gBAAAA7e+LqXnWSs6jyCfc1R0h7QAAAAKqqqqqqqqqqqqqqqqqqqqqLbbEjTAfSOq7dxunqKyQQgAAAAA="; size_t psshDataLen = 0; unsigned char *psshDataPtr = base64_Decode(psshBase64, &psshDataLen, strlen(psshBase64)); ASSERT_NE(psshDataPtr, nullptr); @@ -844,16 +859,20 @@ TEST_F(DrmHelperTests, RDKEMW19892_Broken_UUIDWithoutHyphens) ASSERT_NE(widevineHelper, nullptr); ASSERT_TRUE(widevineHelper->parsePssh(psshDataPtr, (uint32_t)psshDataLen)); - std::vector expectedKey = {0x2D, 0xB6, 0xC4, 0x8D, 0x30, 0x1F, 0x48, 0xEA, - 0xBB, 0x77, 0x1B, 0xA7, 0xA8, 0xAC, 0x90, 0x42}; + std::vector dummyKey = {0xAA,0xAA,0xAA,0xAA,0xAA,0xAA,0xAA,0xAA, + 0xAA,0xAA,0xAA,0xAA,0xAA,0xAA,0xAA,0xAA}; + std::vector targetKey = {0x2D, 0xB6, 0xC4, 0x8D, 0x30, 0x1F, 0x48, 0xEA, + 0xBB, 0x77, 0x1B, 0xA7, 0xA8, 0xAC, 0x90, 0x42}; // UUID without hyphens (32 hex chars) — also valid + // Must select slot 1 (targetKey), NOT fall back to slot 0 (dummyKey) std::string cencDefaultKID = "2db6c48d301f48eabb771ba7a8ac9042"; widevineHelper->setDefaultKeyID(cencDefaultKID); std::vector keyID; widevineHelper->getKey(keyID); - EXPECT_EQ(keyID, expectedKey) << "UUID without hyphens must also match binary PSSH key"; + EXPECT_NE(keyID, dummyKey) << "BEFORE-FIX BEHAVIOR: fell back to slot 0 (wrong key!)"; + EXPECT_EQ(keyID, targetKey) << "UUID without hyphens must correctly select slot 1"; free(psshDataPtr); } @@ -1139,242 +1158,4 @@ TEST_F(DrmHelperTests, TestCompareHelpers) playreadyHelper3->parsePssh((const unsigned char*)pssh3.data(), (uint32_t)pssh3.size()); ASSERT_FALSE(playreadyHelper->compare(playreadyHelper3)); } -/** - * @brief Verify that the default initialization of ChallengeInfo sets all member variables to their expected default values. - * - * This test verifies that when the default constructor of ChallengeInfo is invoked, the member variable 'data' is set to nullptr, - * and both 'url' and 'accessToken' are initialized to empty strings. This ensures that the object is in a valid and predictable state for further operations. - * - * **Test Group ID:** Basic: 01 - * **Test Case ID:** 001 - * **Priority:** High - * - * **Pre-Conditions:** None - * **Dependencies:** None - * **User Interaction:** None - * - * **Test Procedure:** - * | Variation / Step | Description | Test Data | Expected Result | Notes | - * | :--------------: | ------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------- | ----------- | - * | 01 | Invoke the default constructor for ChallengeInfo to create a new object | No input, default constructor call, expected output: data = nullptr, url = "", accessToken = "" | The object is initialized with data as nullptr, and both url and accessToken as empty strings; all assertions pass | Should Pass | - */ -TEST_F(DrmHelperTests, VerifyDefaultInitialization) { - - std::cout << "Entering VerifyDefaultInitialization test" << "\n"; - - std::cout << "Invoking default constructor for ChallengeInfo" << "\n"; - - ChallengeInfo challengeInfo; - - std::cout << "Default constructor invoked. Checking initial values" << "\n"; - - if (challengeInfo.data == nullptr) { - std::cout << "challengeInfo.data is null" << "\n"; - } - else { - std::cout << "challengeInfo.data is not null" << "\n"; - } - - std::cout << "challengeInfo.url value: '" << challengeInfo.url << "'" << "\n"; - std::cout << "challengeInfo.accessToken value: '" << challengeInfo.accessToken << "'" << "\n"; - - EXPECT_EQ(challengeInfo.data, nullptr); - EXPECT_EQ(challengeInfo.url, ""); - EXPECT_EQ(challengeInfo.accessToken, ""); - - std::cout << "Exiting VerifyDefaultInitialization test" << "\n"; -} -/** - * @brief Validate the default constructor initializes LicenseRequest object with correct defaults. - * - * This test verifies that the LicenseRequest class's default constructor correctly initializes all members with appropriate default values. It confirms that the method field is set to one of the allowed values (DRM_RETRIEVE, GET, or POST), licenseAnonymousRequest is set to false, url and payload are empty strings, and the headers map is empty. - * - * **Test Group ID:** Basic: 01 - * **Test Case ID:** 002 - * **Priority:** High - * - * **Pre-Conditions:** None - * **Dependencies:** None - * **User Interaction:** None - * - * **Test Procedure:** - * | Variation / Step | Description | Test Data | Expected Result | Notes | - * | :----: | --------- | ---------- |-------------- | ----- | - * | 01 | Invoke default constructor for LicenseRequest object | None | LicenseRequest object is created with default field values | Should be successful | - * | 02 | Validate that the method field is set to one of (DRM_RETRIEVE, GET, POST) | licenseRequestObject.method = DRM_RETRIEVE, GET, or POST | Method field matches one of the allowed values | Should Pass | - * | 03 | Check that licenseAnonymousRequest is false by default | licenseRequestObject.licenseAnonymousRequest = false | The field evaluates to false as expected | Should Pass | - * | 04 | Verify that the url field is an empty string | licenseRequestObject.url = "" | Url field is an empty string | Should Pass | - * | 05 | Verify that the payload field is an empty string | licenseRequestObject.payload = "" | Payload field is an empty string | Should Pass | - * | 06 | Ensure that the headers map is empty | licenseRequestObject.headers = {} | Headers map is empty | Should Pass | - */ -TEST_F(DrmHelperTests, DefaultConstructorInitialization_PositiveTest) -{ - std::cout<<"Entering DefaultConstructorInitialization_PositiveTest test"< systemIds; - std::cout << "Initial systemIds vector size: " << systemIds.size() << std::endl; - - std::cout << "Invoking getSystemIds method" << std::endl; - EXPECT_NO_THROW(engine.getSystemIds(systemIds)); - - std::cout << "After Invoking getSystemIds, systemIds vector size: " << systemIds.size() << std::endl; - for (size_t i = 0; i < systemIds.size(); ++i) - { - std::cout << "systemIds[" << i << "]: " << systemIds[i] << std::endl; - } - - std::cout << "Exiting GetSystemIds_EmptyVector test" << std::endl; -} -/** - * @brief Verify that registerFactory handles a null input gracefully without altering internal state. - * - * This test ensures that the API `registerFactory` does not register a null factory pointer - * and maintains internal consistency. It verifies that the factory count remains unchanged (zero), - * demonstrating proper handling of invalid input without exceptions or side effects. - * - * **Test Group ID:** Basic: 01 @n - * **Test Case ID:** 008 @n - * **Priority:** High @n - * - * **Pre-Conditions:** None @n - * **Dependencies:** None @n - * **User Interaction:** None @n - * - * **Test Procedure:** @n - * | Variation / Step | Description | Test Data | Expected Result | Notes | - * | :--------------: | --------------------------------------------------------------------- | --------------- | ------------------------------------------ | ------------------ | - * | 01 | Invoke registerFactory with a null pointer | factory = null | Factory count remains zero | Should Not Change | - * | 02 | Retrieve factory count after attempted registration with null pointer | | Count = 0 | Verifies no effect | - */ -TEST_F(DrmHelperTests, NullFactoryRegistrationTest) -{ - std::cout << "Entering NullFactoryRegistrationTest test" << std::endl; - - DrmHelperEngine engine; - - std::cout << "Invoking registerFactory with nullptr" << std::endl; - EXPECT_NO_THROW(engine.registerFactory(nullptr);); - std::cout << "Exiting NullFactoryRegistrationTest test" << std::endl; -} \ No newline at end of file From 641dfdccf5e714c32e848be9314fd03c9f24e608 Mon Sep 17 00:00:00 2001 From: Alsameema Date: Mon, 22 Jun 2026 12:47:12 +0530 Subject: [PATCH 06/12] Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- drm/helper/WidevineDrmHelper.cpp | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/drm/helper/WidevineDrmHelper.cpp b/drm/helper/WidevineDrmHelper.cpp index 9d58db26..a52bf883 100755 --- a/drm/helper/WidevineDrmHelper.cpp +++ b/drm/helper/WidevineDrmHelper.cpp @@ -199,13 +199,14 @@ void WidevineDrmHelper::setDefaultKeyID(const std::string& cencData) } if (uuidHex.size() == 32) { + defaultKeyIDBinary.reserve(16); for (size_t i = 0; i < uuidHex.size(); i += 2) { - std::string hexPair = uuidHex.substr(i, 2); // lives until end of iteration - char* end = nullptr; - unsigned long v = strtoul(hexPair.c_str(), &end, 16); - if (!end || *end != '\0') { defaultKeyIDBinary.clear(); break; } - defaultKeyIDBinary.push_back(static_cast(v)); + char hexPair[3] = {uuidHex[i], uuidHex[i + 1], '\0'}; + char* end = nullptr; + unsigned long v = strtoul(hexPair, &end, 16); + if (!end || *end != '\0' || v > 0xFF) { defaultKeyIDBinary.clear(); break; } + defaultKeyIDBinary.push_back(static_cast(v)); } } From e10527f6d264fe6cece99913a2c58682742cb230 Mon Sep 17 00:00:00 2001 From: Alsameema Date: Mon, 22 Jun 2026 12:48:45 +0530 Subject: [PATCH 07/12] Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- test/utests/tests/DrmTests/DrmHelperTests.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/utests/tests/DrmTests/DrmHelperTests.cpp b/test/utests/tests/DrmTests/DrmHelperTests.cpp index 646bbb52..aef25657 100644 --- a/test/utests/tests/DrmTests/DrmHelperTests.cpp +++ b/test/utests/tests/DrmTests/DrmHelperTests.cpp @@ -689,7 +689,7 @@ TEST_F(DrmHelperTests, RDKEMW19892_Working_MultiKeyRawBinarySelectsCorrectSlot) * * STATUS: FAIL before fix, PASS after fix */ -TEST_F(DrmHelperTests, RDKEMW19892_Broken_UUIDFormatNeverMatchedBinaryKeys) +TEST_F(DrmHelperTests, RDKEMW19892_PreviouslyBroken_UUIDFormatNeverMatchedBinaryKeys) { // Multi-key PSSH: Key0 = all 0xAA (dummy), Key1 = 2db6c48d301f48eabb771ba7a8ac9042 (target) // The target key is at slot 1, so slot-0 fallback returns the WRONG key. From eea1a6521be6b572fdea9c01034c3b6826fcaa50 Mon Sep 17 00:00:00 2001 From: Alsameema Date: Mon, 22 Jun 2026 12:49:42 +0530 Subject: [PATCH 08/12] Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- test/utests/tests/DrmTests/DrmHelperTests.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/utests/tests/DrmTests/DrmHelperTests.cpp b/test/utests/tests/DrmTests/DrmHelperTests.cpp index aef25657..c974d82f 100644 --- a/test/utests/tests/DrmTests/DrmHelperTests.cpp +++ b/test/utests/tests/DrmTests/DrmHelperTests.cpp @@ -750,7 +750,7 @@ TEST_F(DrmHelperTests, RDKEMW19892_PreviouslyBroken_UUIDFormatNeverMatchedBinary * * STATUS: FAIL before fix, PASS after fix */ -TEST_F(DrmHelperTests, RDKEMW19892_Broken_MultiKeyUUIDSelectsWrongSlot) +TEST_F(DrmHelperTests, RDKEMW19892_PreviouslyBroken_MultiKeyUUIDSelectsWrongSlot) { // PSSH Version 1 with 2 key IDs: // Key 0: 00000000-0000-0000-0000-000000000000 (all zeros) From d37d0c3d35311181440106613a5b78074fa782eb Mon Sep 17 00:00:00 2001 From: Alsameema Date: Mon, 22 Jun 2026 12:49:53 +0530 Subject: [PATCH 09/12] Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- test/utests/tests/DrmTests/DrmHelperTests.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/utests/tests/DrmTests/DrmHelperTests.cpp b/test/utests/tests/DrmTests/DrmHelperTests.cpp index c974d82f..d4e3affc 100644 --- a/test/utests/tests/DrmTests/DrmHelperTests.cpp +++ b/test/utests/tests/DrmTests/DrmHelperTests.cpp @@ -803,7 +803,7 @@ TEST_F(DrmHelperTests, RDKEMW19892_PreviouslyBroken_MultiKeyUUIDSelectsWrongSlot * * STATUS: FAIL before fix, PASS after fix */ -TEST_F(DrmHelperTests, RDKEMW19892_Broken_UUIDUppercaseHex) +TEST_F(DrmHelperTests, RDKEMW19892_PreviouslyBroken_UUIDUppercaseHex) { // Multi-key PSSH: Key0 = all 0xAA (dummy), Key1 = 2db6c48d301f48eabb771ba7a8ac9042 (target) const char *psshBase64 = "AAAARHBzc2gBAAAA7e+LqXnWSs6jyCfc1R0h7QAAAAKqqqqqqqqqqqqqqqqqqqqqLbbEjTAfSOq7dxunqKyQQgAAAAA="; From 54fd638e8ce935a4950f85da2f817c42da75a1d8 Mon Sep 17 00:00:00 2001 From: Alsameema Date: Mon, 22 Jun 2026 12:50:04 +0530 Subject: [PATCH 10/12] Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- test/utests/tests/DrmTests/DrmHelperTests.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/utests/tests/DrmTests/DrmHelperTests.cpp b/test/utests/tests/DrmTests/DrmHelperTests.cpp index d4e3affc..640a210c 100644 --- a/test/utests/tests/DrmTests/DrmHelperTests.cpp +++ b/test/utests/tests/DrmTests/DrmHelperTests.cpp @@ -845,7 +845,7 @@ TEST_F(DrmHelperTests, RDKEMW19892_PreviouslyBroken_UUIDUppercaseHex) * * STATUS: FAIL before fix, PASS after fix */ -TEST_F(DrmHelperTests, RDKEMW19892_Broken_UUIDWithoutHyphens) +TEST_F(DrmHelperTests, RDKEMW19892_PreviouslyBroken_UUIDWithoutHyphens) { // Multi-key PSSH: Key0 = all 0xAA (dummy), Key1 = 2db6c48d301f48eabb771ba7a8ac9042 (target) const char *psshBase64 = "AAAARHBzc2gBAAAA7e+LqXnWSs6jyCfc1R0h7QAAAAKqqqqqqqqqqqqqqqqqqqqqLbbEjTAfSOq7dxunqKyQQgAAAAA="; From 8b35ec636cb686f901565f1503e00488e57c9552 Mon Sep 17 00:00:00 2001 From: Alsameema Date: Mon, 22 Jun 2026 12:55:58 +0530 Subject: [PATCH 11/12] Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- drm/helper/WidevineDrmHelper.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/drm/helper/WidevineDrmHelper.cpp b/drm/helper/WidevineDrmHelper.cpp index a52bf883..ef416a47 100755 --- a/drm/helper/WidevineDrmHelper.cpp +++ b/drm/helper/WidevineDrmHelper.cpp @@ -190,6 +190,7 @@ void WidevineDrmHelper::setDefaultKeyID(const std::string& cencData) // for comparison against binary keyIDs parsed from PSSH std::vector defaultKeyIDBinary; std::string uuidHex; + uuidHex.reserve(cencData.size()); for (char c : cencData) { if (c != '-') From 49b59ba238905e3419e75d638477033924bdbbd1 Mon Sep 17 00:00:00 2001 From: Alsameema Date: Mon, 22 Jun 2026 12:58:08 +0530 Subject: [PATCH 12/12] Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- drm/helper/WidevineDrmHelper.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drm/helper/WidevineDrmHelper.cpp b/drm/helper/WidevineDrmHelper.cpp index ef416a47..216c3795 100755 --- a/drm/helper/WidevineDrmHelper.cpp +++ b/drm/helper/WidevineDrmHelper.cpp @@ -206,7 +206,7 @@ void WidevineDrmHelper::setDefaultKeyID(const std::string& cencData) char hexPair[3] = {uuidHex[i], uuidHex[i + 1], '\0'}; char* end = nullptr; unsigned long v = strtoul(hexPair, &end, 16); - if (!end || *end != '\0' || v > 0xFF) { defaultKeyIDBinary.clear(); break; } + if (*end != '\0' || v > 0xFF) { defaultKeyIDBinary.clear(); break; } defaultKeyIDBinary.push_back(static_cast(v)); } }