From 2b01764d86d8c1b808a1ffb5913442e8f055762f Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Wed, 14 Jan 2026 23:37:36 -0800 Subject: [PATCH] std: fix handling of EBADF error code In the context of read/write it's ambiguous, means file was opened without read/write respectively. --- lib/std/Io/File.zig | 4 ++++ lib/std/Io/File/Reader.zig | 3 ++- lib/std/Io/Threaded.zig | 20 +++++++++----------- lib/std/posix.zig | 2 +- lib/std/zig/system.zig | 2 +- src/link/Dwarf.zig | 4 ---- 6 files changed, 17 insertions(+), 18 deletions(-) diff --git a/lib/std/Io/File.zig b/lib/std/Io/File.zig index e7114653517573be5a27d0573f3e41c06fb0c2ac..cc1a58a15e2fa78878eca1fd84458397cb4b6412 100644 --- a/lib/std/Io/File.zig +++ b/lib/std/Io/File.zig @@ -554,6 +554,8 @@ pub const ReadPositionalError = error{ LockViolation, /// This file cannot be read positionally. Unseekable, + /// File was not opened with read capability. + NotOpenForReading, } || Io.Cancelable || Io.UnexpectedError; /// Returns 0 on stream end or if `buffer` has no space available for data. @@ -588,6 +590,8 @@ pub const WritePositionalError = error{ FileBusy, /// This file cannot be written positionally. Unseekable, + /// File was not opened with write capability. + NotOpenForWriting, } || Io.Cancelable || Io.UnexpectedError; /// See also: diff --git a/lib/std/Io/File/Reader.zig b/lib/std/Io/File/Reader.zig index c2842ee45ffbbeb55fd898fa34d4a4f58d7cc869..f400f2c51439b65bbe7e11ef3dfa0d5b49b4f3bf 100644 --- a/lib/std/Io/File/Reader.zig +++ b/lib/std/Io/File/Reader.zig @@ -33,7 +33,8 @@ pub const Error = error{ IsDir, BrokenPipe, ConnectionResetByPeer, - Timeout, + /// File was not opened with read capability. + NotOpenForReading, SocketUnconnected, /// Non-blocking has been enabled, and reading from the file descriptor /// would block. diff --git a/lib/std/Io/Threaded.zig b/lib/std/Io/Threaded.zig index 87b47b4a1e7af19991f45c8910165d263624a4ce..a02c190330fddb75e53de379907b7a11a432692e 100644 --- a/lib/std/Io/Threaded.zig +++ b/lib/std/Io/Threaded.zig @@ -7954,7 +7954,7 @@ fn fileReadStreamingPosix(userdata: ?*anyopaque, file: File, data: []const []u8) syscall.finish(); return nread; }, - .INTR => { + .INTR, .TIMEDOUT => { try syscall.checkCancel(); continue; }, @@ -7970,7 +7970,6 @@ fn fileReadStreamingPosix(userdata: ?*anyopaque, file: File, data: []const []u8) .NOMEM => return error.SystemResources, .NOTCONN => return error.SocketUnconnected, .CONNRESET => return error.ConnectionResetByPeer, - .TIMEDOUT => return error.Timeout, .NOTCAPABLE => return error.AccessDenied, else => |err| return posix.unexpectedErrno(err), } @@ -7987,7 +7986,7 @@ fn fileReadStreamingPosix(userdata: ?*anyopaque, file: File, data: []const []u8) syscall.finish(); return @intCast(rc); }, - .INTR => { + .INTR, .TIMEDOUT => { try syscall.checkCancel(); continue; }, @@ -7997,9 +7996,9 @@ fn fileReadStreamingPosix(userdata: ?*anyopaque, file: File, data: []const []u8) .INVAL => |err| return errnoBug(err), .FAULT => |err| return errnoBug(err), .AGAIN => return error.WouldBlock, - .BADF => |err| { + .BADF => { if (native_os == .wasi) return error.IsDir; // File operation on directory. - return errnoBug(err); // File descriptor used after closed. + return error.NotOpenForReading; }, .IO => return error.InputOutput, .ISDIR => return error.IsDir, @@ -8007,7 +8006,6 @@ fn fileReadStreamingPosix(userdata: ?*anyopaque, file: File, data: []const []u8) .NOMEM => return error.SystemResources, .NOTCONN => return error.SocketUnconnected, .CONNRESET => return error.ConnectionResetByPeer, - .TIMEDOUT => return error.Timeout, else => |err| return posix.unexpectedErrno(err), } }, @@ -8136,10 +8134,10 @@ fn fileReadPositionalPosix(userdata: ?*anyopaque, file: File, data: []const []u8 .CONNRESET => |err| return syscall.errnoBug(err), // not a socket .INVAL => |err| return syscall.errnoBug(err), .FAULT => |err| return syscall.errnoBug(err), - .BADF => |err| { + .BADF => { syscall.finish(); if (native_os == .wasi) return error.IsDir; // File operation on directory. - return errnoBug(err); // File descriptor used after closed. + return error.NotOpenForReading; }, else => |err| return syscall.unexpectedErrno(err), } @@ -8793,7 +8791,7 @@ fn fileWritePositional( .INVAL => |err| return errnoBug(err), .FAULT => |err| return errnoBug(err), .AGAIN => |err| return errnoBug(err), - .BADF => |err| return errnoBug(err), // use after free + .BADF => return error.NotOpenForWriting, .DESTADDRREQ => |err| return errnoBug(err), // `connect` was never called. .DQUOT => return error.DiskQuota, .FBIG => return error.FileTooBig, @@ -8828,7 +8826,7 @@ fn fileWritePositional( .FAULT => |err| return syscall.errnoBug(err), .DESTADDRREQ => |err| return syscall.errnoBug(err), // `connect` was never called. .CONNRESET => |err| return syscall.errnoBug(err), // Not a socket handle. - .BADF => |err| return syscall.errnoBug(err), // use after free + .BADF => return syscall.fail(error.NotOpenForWriting), .AGAIN => return syscall.fail(error.WouldBlock), .DQUOT => return syscall.fail(error.DiskQuota), .FBIG => return syscall.fail(error.FileTooBig), @@ -16636,7 +16634,7 @@ fn mmSyncWrite(file: File, memory: []u8, offset: u64) File.WritePositionalError! .FAULT => |err| return syscall.errnoBug(err), .DESTADDRREQ => |err| return syscall.errnoBug(err), // not a socket .CONNRESET => |err| return syscall.errnoBug(err), // not a socket - .BADF => |err| return syscall.errnoBug(err), // use after free + .BADF => return syscall.fail(error.NotOpenForWriting), .AGAIN => return syscall.fail(error.WouldBlock), .DQUOT => return syscall.fail(error.DiskQuota), .FBIG => return syscall.fail(error.FileTooBig), diff --git a/lib/std/posix.zig b/lib/std/posix.zig index 6b029141622d4a9eaec35183e8200c26e2efcf84..f1f4e279d1726ad4997dc2f2009755887aa3c520 100644 --- a/lib/std/posix.zig +++ b/lib/std/posix.zig @@ -441,7 +441,7 @@ pub fn read(fd: fd_t, buf: []u8) ReadError!usize { .NOMEM => return error.SystemResources, .NOTCONN => return error.SocketUnconnected, .CONNRESET => return error.ConnectionResetByPeer, - .TIMEDOUT => return error.Timeout, + .TIMEDOUT => return error.Unexpected, else => |err| return unexpectedErrno(err), } } diff --git a/lib/std/zig/system.zig b/lib/std/zig/system.zig index d0cd0721bbff3218818bce17b3e07a561e1c3bf8..0e7d814a71f1f28f424509d481a1106282924bd2 100644 --- a/lib/std/zig/system.zig +++ b/lib/std/zig/system.zig @@ -420,7 +420,7 @@ pub fn resolveTargetQuery(io: Io, query: Target.Query) DetectError!Target { error.WouldBlock => return error.Unexpected, error.BrokenPipe => return error.Unexpected, error.ConnectionResetByPeer => return error.Unexpected, - error.Timeout => return error.Unexpected, + error.NotOpenForReading => return error.Unexpected, error.SocketUnconnected => return error.Unexpected, error.AccessDenied, diff --git a/src/link/Dwarf.zig b/src/link/Dwarf.zig index 8bf1dccbcbde557f230a526cbea90240704162ea..19bbee45b3a12d6883f3e7803475eb960c5a1784 100644 --- a/src/link/Dwarf.zig +++ b/src/link/Dwarf.zig @@ -50,13 +50,9 @@ pub const UpdateError = error{ UnexpectedEndOfFile, NonResizable, /// TODO why is this in the error set? - Timeout, - /// TODO why is this in the error set? ConnectionResetByPeer, /// TODO why is this in the error set? SocketUnconnected, - /// TODO why is this in the error set? - NotOpenForWriting, } || codegen.GenerateSymbolError || Io.File.OpenError || -- 2.54.0