From fa2eb5c96a6d0cb4309d281a62394f0611753886 Mon Sep 17 00:00:00 2001 From: Sarah Rimron-Soutter Date: Wed, 9 Jul 2025 17:08:43 +0100 Subject: [PATCH] fix: prevent errors in getKeyIdSet if `playlist.contentProtection` object is incomplete --- src/playlist-loader.js | 18 +++++++++++------- test/playlist-loader.test.js | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 44 insertions(+), 7 deletions(-) diff --git a/src/playlist-loader.js b/src/playlist-loader.js index d07755a8d..4bdc2c39e 100644 --- a/src/playlist-loader.js +++ b/src/playlist-loader.js @@ -1317,17 +1317,21 @@ export default class PlaylistLoader extends EventTarget { * @return a Set of 32 digit hex strings that represent the unique keyIds for that playlist. */ getKeyIdSet(playlist) { - if (playlist.contentProtection) { - const keyIds = new Set(); + const keyIds = new Set(); - for (const keysystem in playlist.contentProtection) { + if (!playlist || !playlist.contentProtection) { + return keyIds; + } + + for (const keysystem in playlist.contentProtection) { + if (playlist.contentProtection[keysystem] && + playlist.contentProtection[keysystem].attributes && + playlist.contentProtection[keysystem].attributes.keyId) { const keyId = playlist.contentProtection[keysystem].attributes.keyId; - if (keyId) { - keyIds.add(keyId.toLowerCase()); - } + keyIds.add(keyId.toLowerCase()); } - return keyIds; } + return keyIds; } } diff --git a/test/playlist-loader.test.js b/test/playlist-loader.test.js index 702d5f8e0..977d8921e 100644 --- a/test/playlist-loader.test.js +++ b/test/playlist-loader.test.js @@ -49,6 +49,39 @@ QUnit.module('Playlist Loader', function(hooks) { assert.ok(keyIdSet.has(keyId.toLowerCase()), 'keyId is expected hex string'); }); + QUnit.test('does not error if keyId or keysystem.attributes is missing', function(assert) { + assert.expect(6); + const loader = new PlaylistLoader('variant.m3u8', this.fakeVhs); + const playlists = [ + { + contentProtection: { + 'fake.keysystem': {} + } + }, + { + contentProtection: { + 'fake.keysystem': { + attributes: {} + } + } + } + ]; + + let errorHappened = false; + + for (const playlist of playlists) { + let keyIdSet; + + try { + keyIdSet = loader.getKeyIdSet(playlist); + } catch (e) { + errorHappened = true; + } + assert.notOk(errorHappened, 'no error was thrown'); + assert.notOk(keyIdSet.size, 'keyIdSet is empty'); + } + }); + QUnit.test('updateSegments copies over properties', function(assert) { assert.deepEqual( [