fix(node:fs): set allow above root (#16814)

Co-authored-by: Dylan Conway <dylan.conway567@gmail.com>
This commit is contained in:
chloe caruso
2025-01-27 16:02:15 -08:00
committed by GitHub
parent ce532901ce
commit c08f4abb6a
2 changed files with 49 additions and 6 deletions

View File

@@ -932,15 +932,15 @@ pub const PathLike = union(enum) {
return buf[0..sliced.len :0];
}
pub inline fn sliceZ(this: PathLike, buf: *bun.PathBuffer) [:0]const u8 {
pub fn sliceZ(this: PathLike, buf: *bun.PathBuffer) callconv(bun.callconv_inline) [:0]const u8 {
return sliceZWithForceCopy(this, buf, false);
}
pub inline fn sliceW(this: PathLike, buf: *bun.WPathBuffer) [:0]const u16 {
pub fn sliceW(this: PathLike, buf: *bun.WPathBuffer) callconv(bun.callconv_inline) [:0]const u16 {
return strings.toWPath(buf, this.slice());
}
pub inline fn osPath(this: PathLike, buf: *bun.OSPathBuffer) bun.OSPathSliceZ {
pub fn osPath(this: PathLike, buf: *bun.OSPathBuffer) callconv(bun.callconv_inline) bun.OSPathSliceZ {
if (comptime Environment.isWindows) {
return sliceW(this, buf);
}
@@ -948,7 +948,7 @@ pub const PathLike = union(enum) {
return sliceZWithForceCopy(this, buf, false);
}
pub inline fn osPathKernel32(this: PathLike, buf: *bun.PathBuffer) bun.OSPathSliceZ {
pub fn osPathKernel32(this: PathLike, buf: *bun.PathBuffer) callconv(bun.callconv_inline) bun.OSPathSliceZ {
if (comptime Environment.isWindows) {
const s = this.slice();
const b = bun.PathBufferPool.get();
@@ -958,7 +958,7 @@ pub const PathLike = union(enum) {
const normal = path_handler.normalizeBuf(resolve, b, .windows);
return strings.toKernel32Path(@alignCast(std.mem.bytesAsSlice(u16, buf)), normal);
}
const normal = path_handler.normalizeBuf(s, b, .windows);
const normal = path_handler.normalizeStringBuf(s, b, true, .windows, false);
return strings.toKernel32Path(@alignCast(std.mem.bytesAsSlice(u16, buf)), normal);
}

View File

@@ -42,7 +42,7 @@ import fs, {
writevSync,
} from "node:fs";
import * as os from "node:os";
import { dirname, relative, resolve } from "node:path";
import path, { dirname, relative, resolve } from "node:path";
import { promisify } from "node:util";
import _promises, { type FileHandle } from "node:fs/promises";
@@ -3603,3 +3603,46 @@ it("fs.Stat.atime reflects date matching Node.js behavior", () => {
expect(stats.atime).toEqual(new Date(0));
}
});
describe('kernel32 long path conversion does not mangle "../../path" into "path"', () => {
const tmp1 = tempDirWithFiles("longpath", {
"a/b/config": "true",
});
const tmp2 = tempDirWithFiles("longpath", {
"a/b/hello": "true",
"config": "true",
});
const workingDir1 = path.join(tmp1, "a/b");
const workingDir2 = path.join(tmp2, "a/b");
const nonExistTests = [
["existsSync", 'assert.strictEqual(fs.existsSync("../../config"), false)'],
["accessSync", 'assert.throws(() => fs.accessSync("../../config"), { code: "ENOENT" })'],
];
const existTests = [
["existsSync", 'assert.strictEqual(fs.existsSync("../../config"), true)'],
["accessSync", 'assert.strictEqual(fs.accessSync("../../config"), null)'],
];
for (const [name, code] of nonExistTests) {
it(`${name} (not existing)`, () => {
const { success } = spawnSync({
cmd: [bunExe(), "-e", code],
cwd: workingDir1,
stdio: ["ignore", "inherit", "inherit"],
env: bunEnv,
});
expect(success).toBeTrue();
});
}
for (const [name, code] of existTests) {
it(`${name} (existing)`, () => {
const { success } = spawnSync({
cmd: [bunExe(), "-e", code],
cwd: workingDir2,
stdio: ["ignore", "inherit", "inherit"],
env: bunEnv,
});
expect(success).toBeTrue();
});
}
});