tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

commit 77f736a623f12eb22e6c92e595deff767ec626b1
parent dfebe2194e084339e278009e2a7ae76e4d2b8c77
Author: pommicket <pommicket@gmail.com>
Date:   Thu, 23 Oct 2025 12:00:11 +0000

Bug 1995659 - Fix handling of duplicate transfer ArrayBuffers in ImageDecoder r=aosmond

Differential Revision: https://phabricator.services.mozilla.com/D269505

Diffstat:
Mdom/media/webcodecs/ImageDecoder.cpp | 6+++---
Mtesting/web-platform/tests/webcodecs/transfering.https.any.js | 17++++++++++++++++-
2 files changed, 19 insertions(+), 4 deletions(-)

diff --git a/dom/media/webcodecs/ImageDecoder.cpp b/dom/media/webcodecs/ImageDecoder.cpp @@ -497,11 +497,11 @@ void ImageDecoder::CheckOutstandingDecodes() { return nullptr; } - nsTHashSet<const ArrayBuffer*> transferSet; + nsTHashSet<const JSObject*> transferSet; for (const auto& buffer : aInit.mTransfer) { // 10.2.2.2. If init.transfer contains more than one reference to the same // ArrayBuffer, then throw a DataCloneError DOMException. - if (transferSet.Contains(&buffer)) { + if (transferSet.Contains(buffer.Obj())) { MOZ_LOG( gWebCodecsLog, LogLevel::Error, ("ImageDecoder Constructor -- duplicate transferred ArrayBuffer")); @@ -509,7 +509,7 @@ void ImageDecoder::CheckOutstandingDecodes() { "Transfer contains duplicate ArrayBuffer objects"); return nullptr; } - transferSet.Insert(&buffer); + transferSet.Insert(buffer.Obj()); // 10.2.2.3.1. If [[Detached]] internal slot is true, then throw a // DataCloneError DOMException. bool empty = buffer.ProcessData( diff --git a/testing/web-platform/tests/webcodecs/transfering.https.any.js b/testing/web-platform/tests/webcodecs/transfering.https.any.js @@ -168,7 +168,7 @@ promise_test(async t => { } // `data.buffer` didn't get detached assert_equals(data.length, 16, 'data.length'); -}, 'Test transfering same array buffer twice'); +}, 'Test transfering same array buffer twice to VideoFrame'); promise_test(async t => { const bytes = [ 0xBA, 0xDF, 0x00, 0xD0, 0xBA, 0xDF, 0x01, 0xD0, 0xBA, 0xDF ]; @@ -317,3 +317,18 @@ promise_test(async t => { assert_equals(result.image.displayWidth, 320); assert_equals(result.image.displayHeight, 240); }, 'Test transfering ArrayBuffer to ImageDecoder.'); + +promise_test(async t => { + // Not a valid PNG but that shouldn't matter. + let arraybuffer = new ArrayBuffer(16); + let data = new Uint8Array(arraybuffer); + let init = { + type: 'image/png', + data: data, + transfer: [arraybuffer, arraybuffer] + }; + + assert_throws_dom('DataCloneError', () => new ImageDecoder(init)); + // `data.buffer` didn't get detached + assert_equals(data.length, 16, 'data.length'); +}, 'Test transfering same array buffer twice to ImageDecoder');