Skip to content

Commit

Permalink
Fix typed array subclasses in crypto.getRandomValues()
Browse files Browse the repository at this point in the history
Closes #3395.
  • Loading branch information
sebamarynissen committed Oct 1, 2022
1 parent b1c0072 commit fd00838
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 6 deletions.
28 changes: 22 additions & 6 deletions lib/jsdom/living/crypto/Crypto-impl.js
Expand Up @@ -11,11 +11,7 @@ class CryptoImpl {

// https://w3c.github.io/webcrypto/#Crypto-method-getRandomValues
getRandomValues(array) {
// Note: this rejects Float32Array, Float64Array and DataView.
//
// We perform "instance tests" by comparing `array.constructor.name` so
// that the tests will be successful across realms.
const typeName = array.constructor.name;
const typeName = getTypedArrayTypeName(array);
if (!(typeName === "Int8Array" ||
typeName === "Uint8Array" ||
typeName === "Uint8ClampedArray" ||
Expand All @@ -38,10 +34,30 @@ class CryptoImpl {
"QuotaExceededError"
]);
}

nodeCrypto.randomFillSync(array);
return array;
}
}

exports.implementation = CryptoImpl;

// See #3395. Subclasses of TypedArrays should properly work, but we can't rely
// on instanceof because Uint8Array may be different across different windows -
// which can happen in JSDOM when running { runScripts: "dangerously" }. As a
// solution, we imitate the behavior of instanceof by walking the proottype
// chain.
function getTypedArrayTypeName(array) {
const target = array.constructor;
const chain = [target.name];
let proto = Object.getPrototypeOf(target);
while (proto) {
chain.push(proto.name);
proto = Object.getPrototypeOf(proto);
}

while (chain.length > 0 && chain[chain.length - 1] !== "TypedArray") {
chain.pop();
}
chain.reverse();
return chain[1];
}
@@ -0,0 +1,22 @@
"use strict";

const arrays = [
"Int8Array",
"Int16Array",
"Int32Array",
"BigInt64Array",
"Uint8Array",
"Uint8ClampedArray",
"Uint16Array",
"Uint32Array",
"BigUint64Array"
];

for (const array of arrays) {
const ctor = globalThis[array];
test(() => {
class Buffer extends ctor {}
// Must not throw for the test to pass
self.crypto.getRandomValues(new Buffer(256));
}, "Subclass of " + array);
}

0 comments on commit fd00838

Please sign in to comment.