fix: use safe version of posix.read for tree walking
std.posix.read will panic when walking trees with unreadable files such as `/proc` on linux.
This commit is contained in:
parent
0503357509
commit
a581bef152
1 changed files with 76 additions and 1 deletions
|
|
@ -642,7 +642,7 @@ pub fn guess_file_type(file_path: []const u8) struct { []const u8, []const u8, u
|
|||
const content: []const u8 = blk: {
|
||||
const file = std.fs.cwd().openFile(file_path, .{ .mode = .read_only }) catch break :blk &.{};
|
||||
defer file.close();
|
||||
const size = file.read(&buf) catch break :blk &.{};
|
||||
const size = safe_file_read(file, &buf) catch break :blk &.{};
|
||||
break :blk buf[0..size];
|
||||
};
|
||||
return if (file_type_config.guess_file_type(file_path, content)) |ft| .{
|
||||
|
|
@ -652,6 +652,81 @@ pub fn guess_file_type(file_path: []const u8) struct { []const u8, []const u8, u
|
|||
} else default_ft();
|
||||
}
|
||||
|
||||
fn safe_file_read(self: std.fs.File, buffer: []u8) (error{FileHandleInvalidForReading} || std.fs.File.ReadError)!usize {
|
||||
if (builtin.os.tag == .windows) {
|
||||
return std.os.windows.ReadFile(self.handle, buffer, null);
|
||||
}
|
||||
|
||||
return safe_posix_read(self.handle, buffer);
|
||||
}
|
||||
|
||||
fn safe_posix_read(fd: std.posix.fd_t, buf: []u8) (error{FileHandleInvalidForReading} || std.fs.File.ReadError)!usize {
|
||||
const native_os = builtin.os.tag;
|
||||
const unexpectedErrno = std.posix.unexpectedErrno;
|
||||
const maxInt = std.math.maxInt;
|
||||
const system = std.posix.system;
|
||||
const errno = std.posix.errno;
|
||||
if (buf.len == 0) return 0;
|
||||
if (native_os == .windows) {
|
||||
return std.os.windows.ReadFile(fd, buf, null);
|
||||
}
|
||||
if (native_os == .wasi and !builtin.link_libc) {
|
||||
const iovec = std.os.posix.iovec;
|
||||
const wasi = std.os.wasi;
|
||||
const iovs = [1]iovec{iovec{
|
||||
.base = buf.ptr,
|
||||
.len = buf.len,
|
||||
}};
|
||||
|
||||
var nread: usize = undefined;
|
||||
switch (wasi.fd_read(fd, &iovs, iovs.len, &nread)) {
|
||||
.SUCCESS => return nread,
|
||||
.INTR => unreachable,
|
||||
.INVAL => return error.FileHandleInvalidForReading,
|
||||
.FAULT => unreachable,
|
||||
.AGAIN => unreachable,
|
||||
.BADF => return error.NotOpenForReading, // Can be a race condition.
|
||||
.IO => return error.InputOutput,
|
||||
.ISDIR => return error.IsDir,
|
||||
.NOBUFS => return error.SystemResources,
|
||||
.NOMEM => return error.SystemResources,
|
||||
.NOTCONN => return error.SocketNotConnected,
|
||||
.CONNRESET => return error.ConnectionResetByPeer,
|
||||
.TIMEDOUT => return error.ConnectionTimedOut,
|
||||
.NOTCAPABLE => return error.AccessDenied,
|
||||
else => |err| return unexpectedErrno(err),
|
||||
}
|
||||
}
|
||||
|
||||
// Prevents EINVAL.
|
||||
const max_count = switch (native_os) {
|
||||
.linux => 0x7ffff000,
|
||||
.macos, .ios, .watchos, .tvos, .visionos => maxInt(i32),
|
||||
else => maxInt(isize),
|
||||
};
|
||||
while (true) {
|
||||
const rc = system.read(fd, buf.ptr, @min(buf.len, max_count));
|
||||
switch (errno(rc)) {
|
||||
.SUCCESS => return @intCast(rc),
|
||||
.INTR => continue,
|
||||
.INVAL => return error.FileHandleInvalidForReading,
|
||||
.FAULT => unreachable,
|
||||
.SRCH => return error.ProcessNotFound,
|
||||
.AGAIN => return error.WouldBlock,
|
||||
.CANCELED => return error.Canceled,
|
||||
.BADF => return error.NotOpenForReading, // Can be a race condition.
|
||||
.IO => return error.InputOutput,
|
||||
.ISDIR => return error.IsDir,
|
||||
.NOBUFS => return error.SystemResources,
|
||||
.NOMEM => return error.SystemResources,
|
||||
.NOTCONN => return error.SocketNotConnected,
|
||||
.CONNRESET => return error.ConnectionResetByPeer,
|
||||
.TIMEDOUT => return error.ConnectionTimedOut,
|
||||
else => |err| return unexpectedErrno(err),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn merge_pending_files(self: *Self) OutOfMemoryError!void {
|
||||
defer self.sort_files_by_mtime();
|
||||
const existing = try self.files.toOwnedSlice(self.allocator);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue