Skip to content

Commit

Permalink
node:fs: fix assertion when chown is passed non-numbers (#13113)
Browse files Browse the repository at this point in the history
  • Loading branch information
nektro authored Aug 7, 2024
1 parent 6d09772 commit c63c55c
Show file tree
Hide file tree
Showing 4 changed files with 45 additions and 15 deletions.
18 changes: 18 additions & 0 deletions src/bun.js/bindings/ErrorCode.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ static JSC::JSObject* createErrorPrototype(JSC::VM& vm, JSC::JSGlobalObject* glo
}

extern "C" JSC::EncodedJSValue Bun__ERR_INVALID_ARG_TYPE(JSC::JSGlobalObject* globalObject, JSC::EncodedJSValue val_arg_name, JSC::EncodedJSValue val_expected_type, JSC::EncodedJSValue val_actual_value);
extern "C" JSC::EncodedJSValue Bun__ERR_INVALID_ARG_TYPE_static(JSC::JSGlobalObject* globalObject, const ZigString* val_arg_name, const ZigString* val_expected_type, JSC::EncodedJSValue val_actual_value);
extern "C" JSC::EncodedJSValue Bun__ERR_MISSING_ARGS(JSC::JSGlobalObject* globalObject, JSC::EncodedJSValue arg1, JSC::EncodedJSValue arg2, JSC::EncodedJSValue arg3);
extern "C" JSC::EncodedJSValue Bun__ERR_IPC_CHANNEL_CLOSED(JSC::JSGlobalObject* globalObject);

Expand Down Expand Up @@ -224,6 +225,23 @@ extern "C" JSC::EncodedJSValue Bun__ERR_INVALID_ARG_TYPE(JSC::JSGlobalObject* gl
auto message = makeString("The \""_s, arg_name, "\" argument must be of type "_s, expected_type, ". Received "_s, actual_value);
return JSValue::encode(createError(globalObject, ErrorCode::ERR_INVALID_ARG_TYPE, message));
}
extern "C" JSC::EncodedJSValue Bun__ERR_INVALID_ARG_TYPE_static(JSC::JSGlobalObject* globalObject, const ZigString* val_arg_name, const ZigString* val_expected_type, JSC::EncodedJSValue val_actual_value)
{
JSC::VM& vm = globalObject->vm();
auto scope = DECLARE_THROW_SCOPE(vm);

auto arg_name = std::span<const unsigned char>(val_arg_name->ptr, val_arg_name->len);
ASSERT(WTF::charactersAreAllASCII(arg_name));

auto expected_type = std::span<const unsigned char>(val_expected_type->ptr, val_expected_type->len);
ASSERT(WTF::charactersAreAllASCII(expected_type));

auto actual_value = JSValueToStringSafe(globalObject, JSValue::decode(val_actual_value));
RETURN_IF_EXCEPTION(scope, {});

auto message = makeString("The \""_s, arg_name, "\" argument must be of type "_s, expected_type, ". Received "_s, actual_value);
return JSValue::encode(createError(globalObject, ErrorCode::ERR_INVALID_ARG_TYPE, message));
}

JSC_DEFINE_HOST_FUNCTION(jsFunction_ERR_OUT_OF_RANGE, (JSC::JSGlobalObject * globalObject, JSC::CallFrame* callFrame))
{
Expand Down
21 changes: 6 additions & 15 deletions src/bun.js/bindings/bindings.zig
Original file line number Diff line number Diff line change
Expand Up @@ -93,21 +93,6 @@ pub const JSObject = extern struct {
});
}

extern fn Bun__ERR_INVALID_ARG_TYPE(*JSGlobalObject, JSValue, JSValue, JSValue) JSValue;
pub fn ERR_INVALID_ARG_TYPE(this: *JSGlobalObject, arg_name: JSValue, etype: JSValue, atype: JSValue) JSValue {
return Bun__ERR_INVALID_ARG_TYPE(this, arg_name, etype, atype);
}

extern fn Bun__ERR_MISSING_ARGS(*JSGlobalObject, JSValue, JSValue, JSValue) JSValue;
pub fn ERR_MISSING_ARGS(this: *JSGlobalObject, arg1: JSValue, arg2: JSValue, arg3: JSValue) JSValue {
return Bun__ERR_MISSING_ARGS(this, arg1, arg2, arg3);
}

extern fn Bun__ERR_IPC_CHANNEL_CLOSED(*JSGlobalObject) JSValue;
pub fn ERR_IPC_CHANNEL_CLOSED(this: *JSGlobalObject) JSValue {
return Bun__ERR_IPC_CHANNEL_CLOSED(this);
}

pub const Extern = [_][]const u8{
"putRecord",
"getArrayLength",
Expand Down Expand Up @@ -3225,6 +3210,12 @@ pub const JSGlobalObject = opaque {
if (bun.Environment.allow_assert) this.bunVM().assertOnJSThread();
}

extern fn Bun__ERR_INVALID_ARG_TYPE_static(*JSGlobalObject, *const ZigString, *const ZigString, JSValue) JSValue;
/// Caller asserts 'arg_name' and 'etype' are utf-8 literals.
pub fn ERR_INVALID_ARG_TYPE_static(this: *JSGlobalObject, arg_name: *const ZigString, etype: *const ZigString, atype: JSValue) JSValue {
return Bun__ERR_INVALID_ARG_TYPE_static(this, arg_name, etype, atype);
}

pub usingnamespace @import("ErrorCode").JSGlobalObjectExtensions;
};

Expand Down
16 changes: 16 additions & 0 deletions src/bun.js/node/node_fs.zig
Original file line number Diff line number Diff line change
Expand Up @@ -1444,6 +1444,14 @@ pub const Arguments = struct {
};

arguments.eat();
if (!uid_value.isNumber()) {
ctx.throwValue(ctx.ERR_INVALID_ARG_TYPE_static(
JSC.ZigString.static("uid"),
JSC.ZigString.static("number"),
uid_value,
));
return null;
}
break :brk @as(uid_t, @intCast(uid_value.toInt32()));
};

Expand All @@ -1461,6 +1469,14 @@ pub const Arguments = struct {
};

arguments.eat();
if (!gid_value.isNumber()) {
ctx.throwValue(ctx.ERR_INVALID_ARG_TYPE_static(
JSC.ZigString.static("gid"),
JSC.ZigString.static("number"),
gid_value,
));
return null;
}
break :brk @as(gid_t, @intCast(gid_value.toInt32()));
};

Expand Down
5 changes: 5 additions & 0 deletions test/js/node/fs/fs.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3285,3 +3285,8 @@ it("promises.appendFile should accept a FileHandle", async () => {
await fs.promises.appendFile(file, "data");
expect(await Bun.file(x_path).text()).toBe("datadata");
});

it("chown should verify its arguments", () => {
expect(() => fs.chown("doesnt-matter.txt", "a", 0)).toThrowWithCode(TypeError, "ERR_INVALID_ARG_TYPE");
expect(() => fs.chown("doesnt-matter.txt", 0, "a")).toThrowWithCode(TypeError, "ERR_INVALID_ARG_TYPE");
});

0 comments on commit c63c55c

Please sign in to comment.