Compare commits

...

4 Commits

Author SHA1 Message Date
Meghan Denny
04ab4758da use isNumber() here 2024-08-05 23:40:39 -07:00
Meghan Denny
078e31a2a5 DerivedArrayType is also an array 2024-08-05 22:44:32 -07:00
Meghan Denny
c3b00f589c add more test types 2024-08-05 22:44:20 -07:00
Meghan Denny
b8e388e573 node:buffer: fix crashes when unexpected types are passed to constructor functions 2024-08-05 21:27:25 -07:00
2 changed files with 58 additions and 1 deletions

View File

@@ -2283,6 +2283,20 @@ JSC_DEFINE_HOST_FUNCTION(constructJSBuffer, (JSC::JSGlobalObject * lexicalGlobal
if (distinguishingArg.isAnyInt()) {
throwScope.release();
return JSBuffer__bufferFromLength(lexicalGlobalObject, distinguishingArg.asAnyInt());
} else if (distinguishingArg.isNumber()) {
double lengthDouble = distinguishingArg.toIntegerWithTruncation(lexicalGlobalObject);
size_t length = static_cast<size_t>(lengthDouble);
if (UNLIKELY(length < 0 || length > 9007199254740991)) {
throwNodeRangeError(lexicalGlobalObject, throwScope, "Buffer size must be 0...9007199254740991"_s);
return {};
}
return JSBuffer__bufferFromLength(lexicalGlobalObject, length);
} else if (distinguishingArg.isUndefinedOrNull() || distinguishingArg.isBoolean()) {
auto arg_string = distinguishingArg.toWTFString(globalObject);
auto message = makeString("The first argument must be of type string or an instance of Buffer, ArrayBuffer, or Array or an Array-like Object. Received "_s, arg_string);
throwTypeError(lexicalGlobalObject, throwScope, message);
return {};
} else if (distinguishingArg.isCell()) {
auto type = distinguishingArg.asCell()->type();
@@ -2400,8 +2414,15 @@ JSC_DEFINE_HOST_FUNCTION(constructJSBuffer, (JSC::JSGlobalObject * lexicalGlobal
RELEASE_AND_RETURN(throwScope, JSC::JSValue::encode(uint8Array));
}
default: {
case ArrayType:
case DerivedArrayType:
break;
default: {
auto arg_string = distinguishingArg.toWTFString(globalObject);
RETURN_IF_EXCEPTION(throwScope, {});
auto message = makeString("The first argument must be of type string or an instance of Buffer, ArrayBuffer, or Array or an Array-like Object. Received "_s, arg_string);
throwTypeError(lexicalGlobalObject, throwScope, message);
return {};
}
}
}

View File

@@ -2755,3 +2755,39 @@ it("new Buffer.from()", () => {
const buf = new Buffer.from("🥶");
expect(buf.length).toBe(4);
});
describe("fuzzing constructors with new", () => {
const zeroArray = new Uint32Array(10).fill(0);
const sizes = [1e20, 0, 0.1, -1, "a", undefined, null, NaN, 5n, Symbol("xyz"), true, () => {}, {}];
const allocators = [Buffer, SlowBuffer, Buffer.alloc, Buffer.allocUnsafe, Buffer.allocUnsafeSlow];
for (const allocator of allocators) {
for (const size of sizes) {
it(`${allocator.name}(${String(size)})`, () => {
try {
// Some of these allocations are known to fail. If they do, Uint32Array should still produce a zeroed out result.
new allocator(size);
} catch {
expect(zeroArray).toEqual(new Uint32Array(10));
}
});
}
}
});
describe("fuzzing constructors with call", () => {
const zeroArray = new Uint32Array(10).fill(0);
const sizes = [1e20, 0, 0.1, -1, "a", undefined, null, NaN, 5n, Symbol("xyz"), true, () => {}, {}];
const allocators = [Buffer, SlowBuffer, Buffer.alloc, Buffer.allocUnsafe, Buffer.allocUnsafeSlow];
for (const allocator of allocators) {
for (const size of sizes) {
it(`${allocator.name}(${String(size)})`, () => {
try {
// Some of these allocations are known to fail. If they do, Uint32Array should still produce a zeroed out result.
allocator(size);
} catch {
expect(zeroArray).toEqual(new Uint32Array(10));
}
});
}
}
});