diff options
-rwxr-xr-x | bun.lockb | bin | 73707 -> 74396 bytes | |||
-rw-r--r-- | src/bun.js/node/types.zig | 17 | ||||
-rw-r--r-- | src/resolver/resolve_path.zig | 20 | ||||
-rw-r--r-- | test/js/node/path/path.test.js | 13 |
4 files changed, 46 insertions, 4 deletions
Binary files differ diff --git a/src/bun.js/node/types.zig b/src/bun.js/node/types.zig index 72f1dff7e..7e9cdcd2d 100644 --- a/src/bun.js/node/types.zig +++ b/src/bun.js/node/types.zig @@ -2192,6 +2192,8 @@ pub const Path = struct { if (comptime is_bindgen) return JSC.JSValue.jsUndefined(); if (args_len == 0) return JSC.ZigString.init("").toValue(globalThis); var arena = @import("root").bun.ArenaAllocator.init(heap_allocator); + defer arena.deinit(); + var arena_allocator = arena.allocator(); var stack_fallback_allocator = std.heap.stackFallback( ((32 * @sizeOf(string)) + 1024), @@ -2199,18 +2201,27 @@ pub const Path = struct { ); var allocator = stack_fallback_allocator.get(); - defer arena.deinit(); var buf: [bun.MAX_PATH_BYTES]u8 = undefined; + var count: usize = 0; var to_join = allocator.alloc(string, args_len) catch unreachable; for (args_ptr[0..args_len], 0..) |arg, i| { const zig_str: JSC.ZigString = arg.getZigString(globalThis); to_join[i] = zig_str.toSlice(allocator).slice(); + count += to_join[i].len; + } + + var buf_to_use: []u8 = &buf; + if (count * 2 >= buf.len) { + buf_to_use = allocator.alloc(u8, count * 2) catch { + globalThis.throwOutOfMemory(); + return .zero; + }; } const out = if (!isWindows) - PathHandler.joinStringBuf(&buf, to_join, .posix) + PathHandler.joinStringBuf(buf_to_use, to_join, .posix) else - PathHandler.joinStringBuf(&buf, to_join, .windows); + PathHandler.joinStringBuf(buf_to_use, to_join, .windows); var str = bun.String.create(out); defer str.deref(); diff --git a/src/resolver/resolve_path.zig b/src/resolver/resolve_path.zig index f74211709..381abc648 100644 --- a/src/resolver/resolve_path.zig +++ b/src/resolver/resolve_path.zig @@ -829,7 +829,25 @@ pub fn joinStringBuf(buf: []u8, _parts: anytype, comptime _platform: Platform) [ var written: usize = 0; const platform = comptime _platform.resolve(); - var temp_buf: [4096]u8 = undefined; + var temp_buf_: [4096]u8 = undefined; + var temp_buf: []u8 = &temp_buf_; + var free_temp_buf = false; + defer { + if (free_temp_buf) { + bun.default_allocator.free(temp_buf); + } + } + + var count: usize = 0; + for (_parts) |part| { + count += if (part.len > 0) part.len + 1 else 0; + } + + if (count * 2 > temp_buf.len) { + temp_buf = bun.default_allocator.alloc(u8, count * 2) catch @panic("Out of memory"); + free_temp_buf = true; + } + temp_buf[0] = 0; for (_parts) |part| { diff --git a/test/js/node/path/path.test.js b/test/js/node/path/path.test.js index 26b6a3b6d..1d14e1d9e 100644 --- a/test/js/node/path/path.test.js +++ b/test/js/node/path/path.test.js @@ -271,6 +271,19 @@ it("path.basename", () => { strictEqual(path.posix.basename(`/a/b/${controlCharFilename}`), controlCharFilename); }); +describe("path.join #5769", () => { + for (let length of [4096, 4095, 4097, 65_432, 65_431, 65_433]) { + it("length " + length, () => { + const tooLengthyFolderName = Array.from({ length }).fill("b").join(""); + expect(path.join(tooLengthyFolderName)).toEqual("b".repeat(length)); + }); + it("length " + length + "joined", () => { + const tooLengthyFolderName = Array.from({ length }).fill("b"); + expect(path.join(...tooLengthyFolderName)).toEqual("b/".repeat(length).substring(0, 2 * length - 1)); + }); + } +}); + it("path.join", () => { const failures = []; const backslashRE = /\\/g; |