Merge pull request #1499 from marler8997/fixWindowsTmpDir

os: remove UB, tmpDir is returning stack memory on Windows
This commit is contained in:
Mitchell Hashimoto
2024-02-10 20:39:32 -08:00
committed by GitHub
3 changed files with 16 additions and 10 deletions

View File

@ -31,7 +31,8 @@ pub fn init() !TempDir {
const dir = dir: {
const cwd = std.fs.cwd();
const tmp_dir = internal_os.tmpDir() orelse break :dir cwd;
const tmp_dir = internal_os.allocTmpDir(std.heap.page_allocator) orelse break :dir cwd;
defer internal_os.freeTmpDir(std.heap.page_allocator, tmp_dir);
break :dir try cwd.openDir(tmp_dir, .{});
};

View File

@ -44,22 +44,26 @@ pub fn fixMaxFiles() void {
}
/// Return the recommended path for temporary files.
pub fn tmpDir() ?[]const u8 {
/// This may not actually allocate memory, use freeTmpDir to properly
/// free the memory when applicable.
pub fn allocTmpDir(allocator: std.mem.Allocator) ?[]const u8 {
if (builtin.os.tag == .windows) {
// TODO: what is a good fallback path on windows?
const v = std.os.getenvW(std.unicode.utf8ToUtf16LeStringLiteral("TMP")) orelse return null;
// MAX_PATH is very likely sufficient, but it's theoretically possible for someone to
// configure their os to allow paths as big as std.os.windows.PATH_MAX_WIDE, which is MUCH
// larger. Even if they did that, though, it's very unlikey that their Temp dir will use
// such a long path. We can switch if we see any issues, though it seems fairly unlikely.
var buf = [_]u8{0} ** std.os.windows.MAX_PATH;
const len = std.unicode.utf16leToUtf8(buf[0..], v[0..v.len]) catch |e| {
return std.unicode.utf16leToUtf8Alloc(allocator, v) catch |e| {
log.warn("failed to convert temp dir path from windows string: {}", .{e});
return null;
};
return buf[0..len];
}
if (std.os.getenv("TMPDIR")) |v| return v;
if (std.os.getenv("TMP")) |v| return v;
return "/tmp";
}
/// Free a path returned by tmpDir if it allocated memory.
/// This is a "no-op" for all platforms except windows.
pub fn freeTmpDir(allocator: std.mem.Allocator, dir: []const u8) void {
if (builtin.os.tag == .windows) {
allocator.free(dir);
}
}

View File

@ -192,7 +192,8 @@ pub const LoadingImage = struct {
fn isPathInTempDir(path: []const u8) bool {
if (std.mem.startsWith(u8, path, "/tmp")) return true;
if (std.mem.startsWith(u8, path, "/dev/shm")) return true;
if (internal_os.tmpDir()) |dir| {
if (internal_os.allocTmpDir(std.heap.page_allocator)) |dir| {
defer internal_os.freeTmpDir(std.heap.page_allocator, dir);
if (std.mem.startsWith(u8, path, dir)) return true;
// The temporary dir is sometimes a symlink. On macOS for