diff --git a/src/bun.zig b/src/bun.zig index 214f69b033..e1d24f5d8f 100644 --- a/src/bun.zig +++ b/src/bun.zig @@ -2139,7 +2139,7 @@ pub fn initArgv(allocator: std.mem.Allocator) !void { }; const argvu16 = argvu16_ptr[0..@intCast(length)]; - var out_argv = try allocator.alloc([:0]u8, @intCast(length)); + const out_argv = try allocator.alloc([:0]u8, @intCast(length)); var string_builder = StringBuilder{}; for (argvu16) |argraw| { @@ -2149,11 +2149,12 @@ pub fn initArgv(allocator: std.mem.Allocator) !void { try string_builder.allocate(allocator); - for (argvu16, 0..) |argraw, i| { + for (argvu16, out_argv) |argraw, *out| { const arg = std.mem.span(argraw); - // Command line is expected to be valid UTF-16le so this never - // fails and it's okay to unwrap pointer - out_argv[i] = string_builder.append16(arg).?; + + // Command line is expected to be valid UTF-16le + // ...but sometimes, it's not valid. https://github.com/oven-sh/bun/issues/11610 + out.* = string_builder.append16(arg, default_allocator) orelse @panic("Failed to allocate memory for argv"); } argv = out_argv; diff --git a/src/string_builder.zig b/src/string_builder.zig index c4c243d81d..60b46dbd32 100644 --- a/src/string_builder.zig +++ b/src/string_builder.zig @@ -48,20 +48,29 @@ pub fn count16(this: *StringBuilder, slice: []const u16) void { } pub fn count16Z(this: *StringBuilder, slice: [:0]const u16) void { - const result = bun.simdutf.length.utf8.from.utf16.le(slice); + const result = bun.strings.elementLengthUTF16IntoUTF8([:0]const u16, slice); this.cap += result + 1; } -pub fn append16(this: *StringBuilder, slice: []const u16) ?[:0]u8 { +pub fn append16(this: *StringBuilder, slice: []const u16, fallback_allocator: std.mem.Allocator) ?[:0]u8 { var buf = this.writable(); + if (slice.len == 0) { + buf[0] = 0; + this.len += 1; + return buf[0..0 :0]; + } + const result = bun.simdutf.convert.utf16.to.utf8.with_errors.le(slice, buf); if (result.status == .success) { this.len += result.count + 1; buf[result.count] = 0; return buf[0..result.count :0]; + } else { + var list = std.ArrayList(u8).init(fallback_allocator); + var out = bun.strings.toUTF8ListWithTypeBun(&list, []const u16, slice) catch return null; + out.append(0) catch return null; + return list.items[0 .. list.items.len - 1 :0]; } - - return null; } pub fn appendZ(this: *StringBuilder, slice: string) [:0]const u8 {