From 7fac5602306489d0c90370c31622b007f15ad82e Mon Sep 17 00:00:00 2001 From: Filip Skokan Date: Sun, 6 Sep 2026 10:12:33 +0200 Subject: [PATCH] lib: validate sequence iterator objects Reject primitive iterator factory results before accessing next, as required by GetIteratorFromMethod. Signed-off-by: Filip Skokan --- lib/internal/webidl.js | 7 +++++- test/parallel/test-internal-webidl.js | 33 +++++++++++++++++++++++++++ 2 files changed, 39 insertions(+), 1 deletion(-) diff --git a/lib/internal/webidl.js b/lib/internal/webidl.js index 71513bbe86f4..837e0fa788e4 100644 --- a/lib/internal/webidl.js +++ b/lib/internal/webidl.js @@ -836,7 +836,12 @@ function createSequenceConverter(converter) { // Step 4 and create-sequence step 1: get the iterator record. const iterator = FunctionPrototypeCall(method, V); - const nextMethod = iterator?.next; + if (type(iterator) !== 'Object') { + throw makeException( + 'cannot be converted to sequence.', + options); + } + const nextMethod = iterator.next; if (typeof nextMethod !== 'function') { throw makeException( 'cannot be converted to sequence.', diff --git a/test/parallel/test-internal-webidl.js b/test/parallel/test-internal-webidl.js index bd08648549be..5084d80efd93 100644 --- a/test/parallel/test-internal-webidl.js +++ b/test/parallel/test-internal-webidl.js @@ -510,6 +510,39 @@ assert.throws(() => webidl.requiredArguments(1, 2, opts), { }), []); } +for (const [prototype, value] of [ + [Number.prototype, 1], + [String.prototype, 'iterator'], + [Boolean.prototype, true], + [BigInt.prototype, 1n], + [Symbol.prototype, Symbol()], +]) { + let nextReads = 0; + Object.defineProperty(prototype, 'next', { + configurable: true, + get() { + nextReads++; + return () => ({ done: true }); + }, + }); + try { + const iterable = { [Symbol.iterator]: () => value }; + assertInvalidArgType(() => converters['sequence'](iterable)); + assertInvalidArgType(() => structuredClone(null, { transfer: iterable })); + assert.strictEqual(nextReads, 0); + } finally { + delete prototype.next; + } +} + +{ + function iterator() {} + iterator.next = () => ({ done: true }); + assert.deepStrictEqual(converters['sequence']({ + [Symbol.iterator]: () => iterator, + }), []); +} + { class Example {} const converter = webidl.createInterfaceConverter(