Skip to content

Commit a207204

Browse files
committed
Prevent many crashes caused by unreachable
1 parent deab5c9 commit a207204

File tree

3 files changed

+333
-331
lines changed

3 files changed

+333
-331
lines changed

Diff for: lib/std/fs/Dir.zig

+50-48
Original file line numberDiff line numberDiff line change
@@ -60,10 +60,10 @@ pub const Iterator = switch (native_os) {
6060
if (rc == 0) return null;
6161
if (rc < 0) {
6262
switch (posix.errno(rc)) {
63-
.BADF => unreachable, // Dir is invalid or was opened without iteration ability
64-
.FAULT => unreachable,
65-
.NOTDIR => unreachable,
66-
.INVAL => unreachable,
63+
// .BADF => unreachable, // Dir is invalid or was opened without iteration ability
64+
// .FAULT => unreachable,
65+
// .NOTDIR => unreachable,
66+
// .INVAL => unreachable,
6767
else => |err| return posix.unexpectedErrno(err),
6868
}
6969
}
@@ -242,10 +242,10 @@ pub const Iterator = switch (native_os) {
242242
if (self.first_iter) {
243243
switch (@as(posix.E, @enumFromInt(posix.system._kern_rewind_dir(self.dir.fd)))) {
244244
.SUCCESS => {},
245-
.BADF => unreachable, // Dir is invalid
246-
.FAULT => unreachable,
247-
.NOTDIR => unreachable,
248-
.INVAL => unreachable,
245+
// .BADF => unreachable, // Dir is invalid
246+
// .FAULT => unreachable,
247+
// .NOTDIR => unreachable,
248+
// .INVAL => unreachable,
249249
.ACCES => return error.AccessDenied,
250250
.PERM => return error.AccessDenied,
251251
else => |err| return posix.unexpectedErrno(err),
@@ -261,11 +261,11 @@ pub const Iterator = switch (native_os) {
261261
if (rc == 0) return null;
262262
if (rc < 0) {
263263
switch (@as(posix.E, @enumFromInt(rc))) {
264-
.BADF => unreachable, // Dir is invalid
265-
.FAULT => unreachable,
266-
.NOTDIR => unreachable,
267-
.INVAL => unreachable,
268-
.OVERFLOW => unreachable,
264+
// .BADF => unreachable, // Dir is invalid
265+
// .FAULT => unreachable,
266+
// .NOTDIR => unreachable,
267+
// .INVAL => unreachable,
268+
// .OVERFLOW => unreachable,
269269
.ACCES => return error.AccessDenied,
270270
.PERM => return error.AccessDenied,
271271
else => |err| return posix.unexpectedErrno(err),
@@ -290,14 +290,14 @@ pub const Iterator = switch (native_os) {
290290
0,
291291
)))) {
292292
.SUCCESS => {},
293-
.INVAL => unreachable,
294-
.BADF => unreachable, // Dir is invalid
293+
// .INVAL => unreachable,
294+
// .BADF => unreachable, // Dir is invalid
295295
.NOMEM => return error.SystemResources,
296296
.ACCES => return error.AccessDenied,
297297
.PERM => return error.AccessDenied,
298-
.FAULT => unreachable,
299-
.NAMETOOLONG => unreachable,
300-
.LOOP => unreachable,
298+
// .FAULT => unreachable,
299+
// .NAMETOOLONG => unreachable,
300+
// .LOOP => unreachable,
301301
.NOENT => continue,
302302
else => |err| return posix.unexpectedErrno(err),
303303
}
@@ -364,9 +364,9 @@ pub const Iterator = switch (native_os) {
364364
const rc = linux.getdents64(self.dir.fd, &self.buf, self.buf.len);
365365
switch (linux.E.init(rc)) {
366366
.SUCCESS => {},
367-
.BADF => unreachable, // Dir is invalid or was opened without iteration ability
368-
.FAULT => unreachable,
369-
.NOTDIR => unreachable,
367+
// .BADF => unreachable, // Dir is invalid or was opened without iteration ability
368+
// .FAULT => unreachable,
369+
// .NOTDIR => unreachable,
370370
.NOENT => return error.DirNotFound, // The directory being iterated was deleted during iteration.
371371
.INVAL => return error.Unexpected, // Linux may in some cases return EINVAL when reading /proc/$PID/net.
372372
.ACCES => return error.AccessDenied, // Do not have permission to iterate this directory.
@@ -527,10 +527,10 @@ pub const Iterator = switch (native_os) {
527527
var bufused: usize = undefined;
528528
switch (w.fd_readdir(self.dir.fd, &self.buf, self.buf.len, self.cookie, &bufused)) {
529529
.SUCCESS => {},
530-
.BADF => unreachable, // Dir is invalid or was opened without iteration ability
531-
.FAULT => unreachable,
532-
.NOTDIR => unreachable,
533-
.INVAL => unreachable,
530+
// .BADF => unreachable, // Dir is invalid or was opened without iteration ability
531+
// .FAULT => unreachable,
532+
// .NOTDIR => unreachable,
533+
// .INVAL => unreachable,
534534
.NOENT => return error.DirNotFound, // The directory being iterated was deleted during iteration.
535535
.NOTCAPABLE => return error.AccessDenied,
536536
.ILSEQ => return error.InvalidUtf8, // An entry's name cannot be encoded as UTF-8.
@@ -698,7 +698,7 @@ pub const Walker = struct {
698698
self.name_buffer.appendAssumeCapacity(0);
699699
if (base.kind == .directory) {
700700
var new_dir = top.iter.dir.openDir(base.name, .{ .iterate = true }) catch |err| switch (err) {
701-
error.NameTooLong => unreachable, // no path sep in base.name
701+
error.NameTooLong => return error.Unexpected, // no path sep in base.name
702702
else => |e| return e,
703703
};
704704
{
@@ -1574,11 +1574,12 @@ pub fn openDirW(self: Dir, sub_path_w: [*:0]const u16, args: OpenOptions) OpenEr
15741574
.no_follow = args.no_follow,
15751575
.create_disposition = w.FILE_OPEN,
15761576
}) catch |err| switch (err) {
1577-
error.ReadOnlyFileSystem => unreachable,
1578-
error.DiskQuota => unreachable,
1579-
error.NoSpaceLeft => unreachable,
1580-
error.PathAlreadyExists => unreachable,
1581-
error.LinkQuotaExceeded => unreachable,
1577+
error.ReadOnlyFileSystem,
1578+
error.DiskQuota,
1579+
error.NoSpaceLeft,
1580+
error.PathAlreadyExists,
1581+
error.LinkQuotaExceeded,
1582+
=> if (builtin.mode == .Debug) unreachable else return error.Unexpected,
15821583
else => |e| return e,
15831584
};
15841585
return dir;
@@ -1588,13 +1589,14 @@ pub fn openDirW(self: Dir, sub_path_w: [*:0]const u16, args: OpenOptions) OpenEr
15881589
fn openDirFlagsZ(self: Dir, sub_path_c: [*:0]const u8, flags: posix.O) OpenError!Dir {
15891590
assert(flags.DIRECTORY);
15901591
const fd = posix.openatZ(self.fd, sub_path_c, flags, 0) catch |err| switch (err) {
1591-
error.FileTooBig => unreachable, // can't happen for directories
1592-
error.IsDir => unreachable, // we're setting DIRECTORY
1593-
error.NoSpaceLeft => unreachable, // not setting CREAT
1594-
error.PathAlreadyExists => unreachable, // not setting CREAT
1595-
error.FileLocksNotSupported => unreachable, // locking folders is not supported
1596-
error.WouldBlock => unreachable, // can't happen for directories
1597-
error.FileBusy => unreachable, // can't happen for directories
1592+
error.FileTooBig, // can't happen for directories
1593+
error.IsDir, // we're setting DIRECTORY
1594+
error.NoSpaceLeft, // not setting CREAT
1595+
error.PathAlreadyExists, // not setting CREAT
1596+
error.FileLocksNotSupported, // locking folders is not supported
1597+
error.WouldBlock, // can't happen for directories
1598+
error.FileBusy, // can't happen for directories
1599+
=> if (builtin.mode == .Debug) unreachable else return error.Unexpected,
15981600
else => |e| return e,
15991601
};
16001602
return Dir{ .fd = fd };
@@ -1670,7 +1672,7 @@ pub fn deleteFile(self: Dir, sub_path: []const u8) DeleteFileError!void {
16701672
return self.deleteFileW(sub_path_w.span());
16711673
} else if (native_os == .wasi and !builtin.link_libc) {
16721674
posix.unlinkat(self.fd, sub_path, 0) catch |err| switch (err) {
1673-
error.DirNotEmpty => unreachable, // not passing AT.REMOVEDIR
1675+
error.DirNotEmpty => if (builtin.mode == .Debug) unreachable else return error.Unexpected, // not passing AT.REMOVEDIR
16741676
else => |e| return e,
16751677
};
16761678
} else {
@@ -1682,7 +1684,7 @@ pub fn deleteFile(self: Dir, sub_path: []const u8) DeleteFileError!void {
16821684
/// Same as `deleteFile` except the parameter is null-terminated.
16831685
pub fn deleteFileZ(self: Dir, sub_path_c: [*:0]const u8) DeleteFileError!void {
16841686
posix.unlinkatZ(self.fd, sub_path_c, 0) catch |err| switch (err) {
1685-
error.DirNotEmpty => unreachable, // not passing AT.REMOVEDIR
1687+
error.DirNotEmpty => if (builtin.mode == .Debug) unreachable else return error.Unexpected, // not passing AT.REMOVEDIR
16861688
error.AccessDenied => |e| switch (native_os) {
16871689
// non-Linux POSIX systems return EPERM when trying to delete a directory, so
16881690
// we need to handle that case specifically and translate the error
@@ -1701,7 +1703,7 @@ pub fn deleteFileZ(self: Dir, sub_path_c: [*:0]const u8) DeleteFileError!void {
17011703
/// Same as `deleteFile` except the parameter is WTF-16 LE encoded.
17021704
pub fn deleteFileW(self: Dir, sub_path_w: []const u16) DeleteFileError!void {
17031705
posix.unlinkatW(self.fd, sub_path_w, 0) catch |err| switch (err) {
1704-
error.DirNotEmpty => unreachable, // not passing AT.REMOVEDIR
1706+
error.DirNotEmpty => if (builtin.mode == .Debug) unreachable else return error.Unexpected, // not passing AT.REMOVEDIR
17051707
else => |e| return e,
17061708
};
17071709
}
@@ -1740,7 +1742,7 @@ pub fn deleteDir(self: Dir, sub_path: []const u8) DeleteDirError!void {
17401742
return self.deleteDirW(sub_path_w.span());
17411743
} else if (native_os == .wasi and !builtin.link_libc) {
17421744
posix.unlinkat(self.fd, sub_path, posix.AT.REMOVEDIR) catch |err| switch (err) {
1743-
error.IsDir => unreachable, // not possible since we pass AT.REMOVEDIR
1745+
error.IsDir => if (builtin.mode == .Debug) unreachable else return error.Unexpected, // not possible since we pass AT.REMOVEDIR
17441746
else => |e| return e,
17451747
};
17461748
} else {
@@ -1752,7 +1754,7 @@ pub fn deleteDir(self: Dir, sub_path: []const u8) DeleteDirError!void {
17521754
/// Same as `deleteDir` except the parameter is null-terminated.
17531755
pub fn deleteDirZ(self: Dir, sub_path_c: [*:0]const u8) DeleteDirError!void {
17541756
posix.unlinkatZ(self.fd, sub_path_c, posix.AT.REMOVEDIR) catch |err| switch (err) {
1755-
error.IsDir => unreachable, // not possible since we pass AT.REMOVEDIR
1757+
error.IsDir => if (builtin.mode == .Debug) unreachable else return error.Unexpected, // not possible since we pass AT.REMOVEDIR
17561758
else => |e| return e,
17571759
};
17581760
}
@@ -1761,7 +1763,7 @@ pub fn deleteDirZ(self: Dir, sub_path_c: [*:0]const u8) DeleteDirError!void {
17611763
/// This function is Windows-only.
17621764
pub fn deleteDirW(self: Dir, sub_path_w: []const u16) DeleteDirError!void {
17631765
posix.unlinkatW(self.fd, sub_path_w, posix.AT.REMOVEDIR) catch |err| switch (err) {
1764-
error.IsDir => unreachable, // not possible since we pass AT.REMOVEDIR
1766+
error.IsDir => if (builtin.mode == .Debug) unreachable else return error.Unexpected, // not possible since we pass AT.REMOVEDIR
17651767
else => |e| return e,
17661768
};
17671769
}
@@ -2135,7 +2137,7 @@ pub fn deleteTree(self: Dir, sub_path: []const u8) DeleteTreeError!void {
21352137
error.FileNotFound => break :handle_entry,
21362138

21372139
// Impossible because we do not pass any path separators.
2138-
error.NotDir => unreachable,
2140+
error.NotDir => if (builtin.mode == .Debug) unreachable else return error.Unexpected,
21392141

21402142
error.IsDir => {
21412143
treat_as_dir = true;
@@ -2220,7 +2222,7 @@ pub fn deleteTree(self: Dir, sub_path: []const u8) DeleteTreeError!void {
22202222
error.FileNotFound => continue :process_stack,
22212223

22222224
// Impossible because we do not pass any path separators.
2223-
error.NotDir => unreachable,
2225+
error.NotDir => if (builtin.mode == .Debug) unreachable else return error.Unexpected,
22242226

22252227
error.IsDir => {
22262228
treat_as_dir = true;
@@ -2332,7 +2334,7 @@ fn deleteTreeMinStackSizeWithKindHint(self: Dir, sub_path: []const u8, kind_hint
23322334
error.FileNotFound => continue :dir_it,
23332335

23342336
// Impossible because we do not pass any path separators.
2335-
error.NotDir => unreachable,
2337+
error.NotDir => if (builtin.mode == .Debug) unreachable else return error.Unexpected,
23362338

23372339
error.IsDir => {
23382340
treat_as_dir = true;
@@ -2622,7 +2624,7 @@ fn copy_file(fd_in: posix.fd_t, fd_out: posix.fd_t, maybe_size: ?u64) CopyFileRa
26222624
const rc = posix.system.fcopyfile(fd_in, fd_out, null, .{ .DATA = true });
26232625
switch (posix.errno(rc)) {
26242626
.SUCCESS => return,
2625-
.INVAL => unreachable,
2627+
// .INVAL => unreachable,
26262628
.NOMEM => return error.SystemResources,
26272629
// The source file is not a directory, symbolic link, or regular file.
26282630
// Try with the fallback path before giving up.

Diff for: lib/std/os/windows.zig

+11-11
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,7 @@ pub fn OpenFile(sub_path_w: []const u16, options: OpenFileOptions) OpenError!HAN
137137
.FILE_IS_A_DIRECTORY => return error.IsDir,
138138
.NOT_A_DIRECTORY => return error.NotDir,
139139
.USER_MAPPED_FILE => return error.AccessDenied,
140-
.INVALID_HANDLE => unreachable,
140+
// .INVALID_HANDLE => unreachable,
141141
.FILE_DELETED, .DELETE_PENDING => {
142142
return error.AccessDenied;
143143
},
@@ -899,19 +899,19 @@ pub fn ReadLink(dir: ?HANDLE, sub_path_w: []const u16, out_buffer: []u8) ReadLin
899899
);
900900
switch (rc) {
901901
.SUCCESS => {},
902-
.OBJECT_NAME_INVALID => unreachable,
902+
// .OBJECT_NAME_INVALID => unreachable,
903903
.OBJECT_NAME_NOT_FOUND => return error.FileNotFound,
904904
.OBJECT_PATH_NOT_FOUND => return error.FileNotFound,
905905
.NO_MEDIA_IN_DEVICE => return error.FileNotFound,
906906
.BAD_NETWORK_PATH => return error.NetworkNotFound, // \\server was not found
907907
.BAD_NETWORK_NAME => return error.NetworkNotFound, // \\server was found but \\server\share wasn't
908-
.INVALID_PARAMETER => unreachable,
908+
// .INVALID_PARAMETER => unreachable,
909909
.SHARING_VIOLATION => return error.AccessDenied,
910910
.ACCESS_DENIED => return error.AccessDenied,
911911
.PIPE_BUSY => return error.AccessDenied,
912-
.OBJECT_PATH_SYNTAX_BAD => unreachable,
913-
.OBJECT_NAME_COLLISION => unreachable,
914-
.FILE_IS_A_DIRECTORY => unreachable,
912+
// .OBJECT_PATH_SYNTAX_BAD => unreachable,
913+
// .OBJECT_NAME_COLLISION => unreachable,
914+
// .FILE_IS_A_DIRECTORY => unreachable,
915915
else => return unexpectedStatus(rc),
916916
}
917917
defer CloseHandle(result_handle);
@@ -1089,7 +1089,7 @@ pub fn DeleteFile(sub_path_w: []const u16, options: DeleteFileOptions) DeleteFil
10891089
switch (rc) {
10901090
.SUCCESS => {},
10911091
.DIRECTORY_NOT_EMPTY => return error.DirNotEmpty,
1092-
.INVALID_PARAMETER => unreachable,
1092+
// .INVALID_PARAMETER => unreachable,
10931093
.CANNOT_DELETE => return error.AccessDenied,
10941094
.MEDIA_WRITE_PROTECTED => return error.AccessDenied,
10951095
.ACCESS_DENIED => return error.AccessDenied,
@@ -1140,7 +1140,7 @@ pub fn SetFilePointerEx_BEGIN(handle: HANDLE, offset: u64) SetFilePointerError!v
11401140
const ipos = @as(LARGE_INTEGER, @bitCast(offset));
11411141
if (kernel32.SetFilePointerEx(handle, ipos, null, FILE_BEGIN) == 0) {
11421142
switch (GetLastError()) {
1143-
.INVALID_HANDLE => unreachable,
1143+
// .INVALID_HANDLE => unreachable,
11441144
else => |err| return unexpectedError(err),
11451145
}
11461146
}
@@ -1150,7 +1150,7 @@ pub fn SetFilePointerEx_BEGIN(handle: HANDLE, offset: u64) SetFilePointerError!v
11501150
pub fn SetFilePointerEx_CURRENT(handle: HANDLE, offset: i64) SetFilePointerError!void {
11511151
if (kernel32.SetFilePointerEx(handle, offset, null, FILE_CURRENT) == 0) {
11521152
switch (GetLastError()) {
1153-
.INVALID_HANDLE => unreachable,
1153+
// .INVALID_HANDLE => unreachable,
11541154
else => |err| return unexpectedError(err),
11551155
}
11561156
}
@@ -1160,7 +1160,7 @@ pub fn SetFilePointerEx_CURRENT(handle: HANDLE, offset: i64) SetFilePointerError
11601160
pub fn SetFilePointerEx_END(handle: HANDLE, offset: i64) SetFilePointerError!void {
11611161
if (kernel32.SetFilePointerEx(handle, offset, null, FILE_END) == 0) {
11621162
switch (GetLastError()) {
1163-
.INVALID_HANDLE => unreachable,
1163+
// .INVALID_HANDLE => unreachable,
11641164
else => |err| return unexpectedError(err),
11651165
}
11661166
}
@@ -1171,7 +1171,7 @@ pub fn SetFilePointerEx_CURRENT_get(handle: HANDLE) SetFilePointerError!u64 {
11711171
var result: LARGE_INTEGER = undefined;
11721172
if (kernel32.SetFilePointerEx(handle, 0, &result, FILE_CURRENT) == 0) {
11731173
switch (GetLastError()) {
1174-
.INVALID_HANDLE => unreachable,
1174+
// .INVALID_HANDLE => unreachable,
11751175
else => |err| return unexpectedError(err),
11761176
}
11771177
}

0 commit comments

Comments
 (0)