-
-
Notifications
You must be signed in to change notification settings - Fork 3k
Description
Zig Version
0.15.1
Steps to Reproduce and Observed Behavior
TLDR: posix.read
should return a catchable error on E.INVAL
and should not be mapped to unreachable
posix.read
maps E.INVAL
to unreachable
here:
Line 895 in 5bf52a6
.INVAL => unreachable, |
On linux, and likely any other Unix like OS, a return value of E.INVAL from a read syscall is not guaranteed to be a programming error. Especially given that file paths are very likely to be user input and may not represent readable entities. The kernel is allowed to return EINVAL for reasons not in control of the calling program.
For example:
test "posix read test" {
const file_path = "/proc/1/task/1/attr/current";
const file = try std.fs.cwd().openFile(file_path, .{ .mode = .read_only });
defer file.close();
var buf: [1024]u8 = undefined;
const size = try file.read(&buf);
std.debug.assert(size == 0);
}
This code is likely to panic at file.read()
on any common linux system, at least for safe builds. For ReleaseFast builds it is UB.
These kinds of issues should be catchable in user code to allow defensive systems programming. This should probably apply to all syscall errors that are currently mapped to unreachable
in the standard library as they may otherwise trigger UB in ReleaseFast builds. In other words, it is dangerous to map OS syscall errors to unreachable
because they generally are reachable.
Note that basic linux tools allow sensible handling of EINVAL. For example:
> /bin/cat /proc/1/task/1/attr/current
cat: /proc/1/task/1/attr/current: Invalid argument
Such tools cannot currently be written using the zig standard library.
Expected Behavior
posix.read
should return a catchable error.