Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/main' into dave/crash-handler
Browse files Browse the repository at this point in the history
  • Loading branch information
paperclover committed Apr 13, 2024
2 parents f9d1ee6 + 8d49a3e commit 82e3894
Show file tree
Hide file tree
Showing 15 changed files with 347 additions and 59 deletions.
25 changes: 15 additions & 10 deletions src/bun.js/api/bun/socket.zig
Original file line number Diff line number Diff line change
Expand Up @@ -218,8 +218,9 @@ const Handlers = struct {
this.unprotect();
// will deinit when is not wrapped or when is the TCP wrapped connection
if (wrapped != .tls) {
if (ctx) |ctx_|
if (ctx) |ctx_| {
ctx_.deinit(ssl);
}
}
bun.default_allocator.destroy(this);
}
Expand Down Expand Up @@ -825,23 +826,27 @@ pub const Listener = struct {
const arguments = callframe.arguments(1);
log("close", .{});

if (arguments.len > 0 and arguments.ptr[0].isBoolean() and arguments.ptr[0].toBoolean() and this.socket_context != null) {
this.socket_context.?.close(this.ssl);
this.listener = null;
} else {
var listener = this.listener orelse return JSValue.jsUndefined();
this.listener = null;
listener.close(this.ssl);
}
var listener = this.listener orelse return JSValue.jsUndefined();
this.listener = null;

this.poll_ref.unref(this.handlers.vm);
// if we already have no active connections, we can deinit the context now
if (this.handlers.active_connections == 0) {
this.handlers.unprotect();
this.socket_context.?.close(this.ssl);
// deiniting the context will also close the listener
this.socket_context.?.deinit(this.ssl);
this.socket_context = null;
this.strong_self.clear();
this.strong_data.clear();
} else {
const forceClose = arguments.len > 0 and arguments.ptr[0].isBoolean() and arguments.ptr[0].toBoolean() and this.socket_context != null;
if (forceClose) {
// close all connections in this context and wait for them to close
this.socket_context.?.close(this.ssl);
} else {
// only close the listener and wait for the connections to close by it self
listener.close(this.ssl);
}
}

return JSValue.jsUndefined();
Expand Down
4 changes: 3 additions & 1 deletion src/bun.js/node/node_fs.zig
Original file line number Diff line number Diff line change
Expand Up @@ -5474,7 +5474,9 @@ pub const NodeFS = struct {
}
} else {
// https://github.com/oven-sh/bun/issues/2931
if ((@intFromEnum(args.flag) & std.os.O.APPEND) == 0) {
// https://github.com/oven-sh/bun/issues/10222
// only truncate if we're not appending and writing to a path
if ((@intFromEnum(args.flag) & std.os.O.APPEND) == 0 and args.file != .fd) {
_ = ftruncateSync(.{ .fd = fd, .len = @as(JSC.WebCore.Blob.SizeType, @truncate(written)) });
}
}
Expand Down
37 changes: 15 additions & 22 deletions src/bun.js/node/types.zig
Original file line number Diff line number Diff line change
Expand Up @@ -248,7 +248,9 @@ pub fn Maybe(comptime ReturnTypeT: type, comptime ErrorTypeT: type) type {

pub inline fn errnoSysFd(rc: anytype, syscall: Syscall.Tag, fd: bun.FileDescriptor) ?@This() {
if (comptime Environment.isWindows) {
if (rc != 0) return null;
if (comptime @TypeOf(rc) == std.os.windows.NTSTATUS) {} else {
if (rc != 0) return null;
}
}
return switch (Syscall.getErrno(rc)) {
.SUCCESS => null,
Expand All @@ -268,7 +270,9 @@ pub fn Maybe(comptime ReturnTypeT: type, comptime ErrorTypeT: type) type {
@compileError("Do not pass WString path to errnoSysP, it needs the path encoded as utf8");
}
if (comptime Environment.isWindows) {
if (rc != 0) return null;
if (comptime @TypeOf(rc) == std.os.windows.NTSTATUS) {} else {
if (rc != 0) return null;
}
}
return switch (Syscall.getErrno(rc)) {
.SUCCESS => null,
Expand Down Expand Up @@ -926,12 +930,9 @@ pub const Valid = struct {
0...bun.MAX_PATH_BYTES => return true,
else => {
// TODO: should this be an EINVAL?
JSC.throwInvalidArguments(
comptime std.fmt.comptimePrint("Invalid path string: path is too long (max: {d})", .{bun.MAX_PATH_BYTES}),
.{},
ctx,
exception,
);
var system_error = bun.sys.Error.fromCode(.NAMETOOLONG, .open).withPath(zig_str.slice()).toSystemError();
system_error.syscall = bun.String.dead;
exception.* = system_error.toErrorInstance(ctx).asObjectRef();
return false;
},
}
Expand All @@ -944,12 +945,9 @@ pub const Valid = struct {
0...bun.MAX_PATH_BYTES => return true,
else => {
// TODO: should this be an EINVAL?
JSC.throwInvalidArguments(
comptime std.fmt.comptimePrint("Invalid path string: path is too long (max: {d})", .{bun.MAX_PATH_BYTES}),
.{},
ctx,
exception,
);
var system_error = bun.sys.Error.fromCode(.NAMETOOLONG, .open).toSystemError();
system_error.syscall = bun.String.dead;
exception.* = system_error.toErrorInstance(ctx).asObjectRef();
return false;
},
}
Expand All @@ -970,14 +968,9 @@ pub const Valid = struct {
},

else => {

// TODO: should this be an EINVAL?
JSC.throwInvalidArguments(
comptime std.fmt.comptimePrint("Invalid path buffer: path is too long (max: {d})", .{bun.MAX_PATH_BYTES}),
.{},
ctx,
exception,
);
var system_error = bun.sys.Error.fromCode(.NAMETOOLONG, .open).toSystemError();
system_error.syscall = bun.String.dead;
exception.* = system_error.toErrorInstance(ctx).asObjectRef();
return false;
},
1...bun.MAX_PATH_BYTES => return true,
Expand Down
21 changes: 7 additions & 14 deletions src/bun.js/webcore/streams.zig
Original file line number Diff line number Diff line change
Expand Up @@ -1964,6 +1964,7 @@ pub fn HTTPServerWritable(comptime ssl: bool) type {
}

fn handleWrote(this: *@This(), amount1: usize) void {
defer log("handleWrote: {d} offset: {d}, {d}", .{ amount1, this.offset, this.buffer.len });
const amount = @as(Blob.SizeType, @truncate(amount1));
this.offset += amount;
this.wrote += amount;
Expand Down Expand Up @@ -1996,8 +1997,11 @@ pub fn HTTPServerWritable(comptime ssl: bool) type {
if (this.requested_end and !this.res.state().isHttpWriteCalled()) {
this.handleFirstWriteIfNecessary();
const success = this.res.tryEnd(buf, this.end_len, false);
this.has_backpressure = !success;
if (this.has_backpressure) {
if (success) {
this.has_backpressure = false;
this.handleWrote(this.end_len);
} else {
this.has_backpressure = true;
this.res.onWritable(*@This(), onWritable, this);
}
return success;
Expand All @@ -2018,7 +2022,7 @@ pub fn HTTPServerWritable(comptime ssl: bool) type {
} else {
this.has_backpressure = !this.res.write(buf);
}

this.handleWrote(buf.len);
return true;
}

Expand Down Expand Up @@ -2064,7 +2068,6 @@ pub fn HTTPServerWritable(comptime ssl: bool) type {
// if we were unable to send it, retry
return false;
}
this.handleWrote(@as(Blob.SizeType, @truncate(chunk.len)));
total_written = chunk.len;

if (this.requested_end) {
Expand Down Expand Up @@ -2150,7 +2153,6 @@ pub fn HTTPServerWritable(comptime ssl: bool) type {

const success = this.send(slice);
if (success) {
this.handleWrote(@as(Blob.SizeType, @truncate(slice.len)));
return .{ .result = JSValue.jsNumber(slice.len) };
}

Expand Down Expand Up @@ -2178,7 +2180,6 @@ pub fn HTTPServerWritable(comptime ssl: bool) type {
assert(slice.len > 0);
const success = this.send(slice);
if (success) {
this.handleWrote(@as(Blob.SizeType, @truncate(slice.len)));
return .{ .result = JSC.JSPromise.resolvedPromiseValue(globalThis, JSValue.jsNumber(slice.len)) };
}
}
Expand Down Expand Up @@ -2221,7 +2222,6 @@ pub fn HTTPServerWritable(comptime ssl: bool) type {
// - large-ish chunk
// - no backpressure
if (this.send(bytes)) {
this.handleWrote(len);
return .{ .owned = len };
}

Expand All @@ -2236,7 +2236,6 @@ pub fn HTTPServerWritable(comptime ssl: bool) type {
};
const slice = this.readableSlice();
if (this.send(slice)) {
this.handleWrote(slice.len);
return .{ .owned = len };
}
} else {
Expand Down Expand Up @@ -2274,7 +2273,6 @@ pub fn HTTPServerWritable(comptime ssl: bool) type {
// - large-ish chunk
// - no backpressure
if (this.send(bytes)) {
this.handleWrote(bytes.len);
return .{ .owned = len };
}
do_send = false;
Expand All @@ -2286,7 +2284,6 @@ pub fn HTTPServerWritable(comptime ssl: bool) type {

if (do_send) {
if (this.send(this.readableSlice())) {
this.handleWrote(bytes.len);
return .{ .owned = len };
}
}
Expand All @@ -2299,7 +2296,6 @@ pub fn HTTPServerWritable(comptime ssl: bool) type {
};
const readable = this.readableSlice();
if (this.send(readable)) {
this.handleWrote(readable.len);
return .{ .owned = len };
}
} else {
Expand Down Expand Up @@ -2336,7 +2332,6 @@ pub fn HTTPServerWritable(comptime ssl: bool) type {
const readable = this.readableSlice();
if (readable.len >= this.highWaterMark or this.hasBackpressure()) {
if (this.send(readable)) {
this.handleWrote(readable.len);
return .{ .owned = @as(Blob.SizeType, @intCast(written)) };
}
}
Expand Down Expand Up @@ -2464,8 +2459,6 @@ pub fn HTTPServerWritable(comptime ssl: bool) type {
this.auto_flusher.registered = true;
return true;
}

this.handleWrote(readable.len);
this.auto_flusher.registered = false;
return false;
}
Expand Down
2 changes: 1 addition & 1 deletion src/cli/create_command.zig
Original file line number Diff line number Diff line change
Expand Up @@ -378,7 +378,7 @@ pub const CreateCommand = struct {
progress.refresh();

var pluckers: [1]Archive.Plucker = if (!create_options.skip_package_json)
[1]Archive.Plucker{try Archive.Plucker.init("package.json", 2048, ctx.allocator)}
[1]Archive.Plucker{try Archive.Plucker.init(comptime strings.literal(bun.OSPathChar, "package.json"), 2048, ctx.allocator)}
else
[1]Archive.Plucker{undefined};

Expand Down
43 changes: 43 additions & 0 deletions src/deps/uws.zig
Original file line number Diff line number Diff line change
Expand Up @@ -893,6 +893,47 @@ pub const SocketContext = opaque {
us_socket_context_free(@as(i32, 0), this);
}

pub fn cleanCallbacks(ctx: *SocketContext, is_ssl: bool) void {
const ssl_int: i32 = @intFromBool(is_ssl);
// replace callbacks with dummy ones
const DummyCallbacks = struct {
fn open(socket: *Socket, _: i32, _: [*c]u8, _: i32) callconv(.C) ?*Socket {
return socket;
}
fn close(socket: *Socket, _: i32, _: ?*anyopaque) callconv(.C) ?*Socket {
return socket;
}
fn data(socket: *Socket, _: [*c]u8, _: i32) callconv(.C) ?*Socket {
return socket;
}
fn writable(socket: *Socket) callconv(.C) ?*Socket {
return socket;
}
fn timeout(socket: *Socket) callconv(.C) ?*Socket {
return socket;
}
fn connect_error(socket: *Socket, _: i32) callconv(.C) ?*Socket {
return socket;
}
fn end(socket: *Socket) callconv(.C) ?*Socket {
return socket;
}
fn handshake(_: *Socket, _: i32, _: us_bun_verify_error_t, _: ?*anyopaque) callconv(.C) void {}
fn long_timeout(socket: *Socket) callconv(.C) ?*Socket {
return socket;
}
};
us_socket_context_on_open(ssl_int, ctx, DummyCallbacks.open);
us_socket_context_on_close(ssl_int, ctx, DummyCallbacks.close);
us_socket_context_on_data(ssl_int, ctx, DummyCallbacks.data);
us_socket_context_on_writable(ssl_int, ctx, DummyCallbacks.writable);
us_socket_context_on_timeout(ssl_int, ctx, DummyCallbacks.timeout);
us_socket_context_on_connect_error(ssl_int, ctx, DummyCallbacks.connect_error);
us_socket_context_on_end(ssl_int, ctx, DummyCallbacks.end);
us_socket_context_on_handshake(ssl_int, ctx, DummyCallbacks.handshake, null);
us_socket_context_on_long_timeout(ssl_int, ctx, DummyCallbacks.long_timeout);
}

fn getLoop(this: *SocketContext, ssl: bool) ?*Loop {
if (ssl) {
return us_socket_context_loop(@as(i32, 1), this);
Expand All @@ -902,6 +943,8 @@ pub const SocketContext = opaque {

/// closes and deinit the SocketContexts
pub fn deinit(this: *SocketContext, ssl: bool) void {
// we clean the callbacks to avoid UAF because we are deiniting
this.cleanCallbacks(ssl);
this.close(ssl);
//always deinit in next iteration
if (ssl) {
Expand Down
2 changes: 1 addition & 1 deletion src/deps/zig
5 changes: 1 addition & 4 deletions src/install/install.zig
Original file line number Diff line number Diff line change
Expand Up @@ -3324,10 +3324,7 @@ pub const PackageManager = struct {
}

pub fn isFolderInCache(this: *PackageManager, folder_path: stringZ) bool {
// TODO: is this slow?
var dir = this.getCacheDirectory().openDirZ(folder_path, .{}) catch return false;
dir.close();
return true;
return bun.sys.directoryExistsAt(this.getCacheDirectory(), folder_path).unwrap() catch false;
}

pub fn pathForCachedNPMPath(
Expand Down
12 changes: 10 additions & 2 deletions src/js/node/fs.js
Original file line number Diff line number Diff line change
Expand Up @@ -138,8 +138,16 @@ var access = function access(...args) {
appendFile = function appendFile(...args) {
callbackify(fs.appendFile, args);
},
close = function close(...args) {
callbackify(fs.close, args);
close = function close(fd, callback) {
if ($isCallable(callback)) {
fs.close(fd).then(() => callback(), callback);
} else if (callback == undefined) {
fs.close(fd).then(() => {});
} else {
const err = new TypeError("Callback must be a function");
err.code = "ERR_INVALID_ARG_TYPE";
throw err;
}
},
rm = function rm(...args) {
callbackify(fs.rm, args);
Expand Down
4 changes: 2 additions & 2 deletions src/libarchive/libarchive.zig
Original file line number Diff line number Diff line change
Expand Up @@ -376,10 +376,10 @@ pub const Archive = struct {
filename_hash: u64 = 0,
found: bool = false,
fd: FileDescriptorType = .zero,
pub fn init(filepath: string, estimated_size: usize, allocator: std.mem.Allocator) !Plucker {
pub fn init(filepath: bun.OSPathSlice, estimated_size: usize, allocator: std.mem.Allocator) !Plucker {
return Plucker{
.contents = try MutableString.init(allocator, estimated_size),
.filename_hash = bun.hash(filepath),
.filename_hash = bun.hash(std.mem.sliceAsBytes(filepath)),
.fd = .zero,
.found = false,
};
Expand Down
Loading

0 comments on commit 82e3894

Please sign in to comment.