Compare commits

...

1 Commits

Author SHA1 Message Date
Claude Bot
eb65381769 fix: prevent PathBuffer overflow when path length equals MAX_PATH_BYTES
On Windows, MAX_PATH_BYTES is 98302 (32767 * 3 + 1). When a path string
is exactly this length, the code would attempt to:
1. Copy all 98302 bytes to buf[0..98302]
2. Write a null terminator at buf[98302] - which is out of bounds

This fix adds a bounds check before the memcpy to ensure we have room
for the null terminator. If the path is too long, we panic with a clear
error message instead of triggering an out-of-bounds panic.

The panic occurred in PathLike.sliceZWithForceCopy at types.zig:601.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-19 04:14:42 +00:00
2 changed files with 57 additions and 0 deletions

View File

@@ -598,6 +598,12 @@ pub const PathLike = union(enum) {
}
}
// Check if we have room for the null terminator
// buf.len is MAX_PATH_BYTES, but we need sliced.len + 1 bytes
if (sliced.len >= buf.len) {
@panic("Path is too long");
}
@memcpy(buf[0..sliced.len], sliced);
buf[sliced.len] = 0;
return buf[0..sliced.len :0];

View File

@@ -0,0 +1,51 @@
// https://github.com/oven-sh/bun/issues/XXXXX
// Regression test for PathBuffer overflow on Windows
// When a path is exactly MAX_PATH_BYTES (98302 on Windows), the null terminator
// would be written out of bounds, causing a panic.
import { expect, test } from "bun:test";
import fs from "fs";
import { isWindows } from "harness";
test("path exactly MAX_PATH_BYTES should not panic", () => {
if (!isWindows) {
return; // This bug is Windows-specific
}
// On Windows, MAX_PATH_BYTES = 32767 * 3 + 1 = 98302
const MAX_PATH_BYTES = 98302;
// Create a path that's exactly MAX_PATH_BYTES
// Use a simple pattern to make it look like a valid path
const longPath = "C:\\" + "a".repeat(MAX_PATH_BYTES - 3);
expect(longPath.length).toBe(MAX_PATH_BYTES);
// This should throw an error about the path being too long,
// not panic with "index out of bounds"
expect(() => {
fs.existsSync(longPath);
}).toThrow();
});
test("path just under MAX_PATH_BYTES should work or error gracefully", () => {
if (!isWindows) {
return; // This bug is Windows-specific
}
// On Windows, MAX_PATH_BYTES = 32767 * 3 + 1 = 98302
const MAX_PATH_BYTES = 98302;
// Create a path that's just under MAX_PATH_BYTES
const longPath = "C:\\" + "a".repeat(MAX_PATH_BYTES - 4);
expect(longPath.length).toBe(MAX_PATH_BYTES - 1);
// This should work without panicking
// It will return false since the path doesn't exist, but shouldn't panic
expect(() => {
const result = fs.existsSync(longPath);
// We expect this to be false (path doesn't exist)
expect(result).toBe(false);
}).not.toThrow();
});