zig

fork of https://codeberg.org/ziglang/zig
Log | Files | Refs | README | LICENSE

commit 2301f2ecdf3a4f823c1a66482af2574738ffb554 (tree)
parent 47cc233f220bcfb7b7183692861651423d965117
Author: Ryan Liptak <squeek502@hotmail.com>
Date:   Mon, 12 Jan 2026 20:28:03 -0800

NtSetInformationFile: remove const from FileInformation buffer param

When targeting x86-windows, this parameter referring to read-only memory can result in an ACCESS_VIOLATION error, and this has been seen when using FILE_DISPOSITION_INFORMATION_EX. It's unclear how exactly this ACCESS_VIOLATION is occurring, though, as the memory does not actually change before/after the call.

Closes https://codeberg.org/ziglang/zig/issues/30802

Diffstat:
Mlib/std/Io/Threaded.zig | 12++++++------
Mlib/std/os/windows.zig | 12++++++------
Mlib/std/os/windows/ntdll.zig | 5++++-
3 files changed, 16 insertions(+), 13 deletions(-)

diff --git a/lib/std/Io/Threaded.zig b/lib/std/Io/Threaded.zig @@ -5550,7 +5550,7 @@ fn dirDeleteWindows(userdata: ?*anyopaque, dir: Dir, sub_path: []const u8, remov // FileDispositionInformation if the return value lets us know that some aspect of it is not supported. const rc = rc: { // Deletion with posix semantics if the filesystem supports it. - const info: w.FILE.DISPOSITION.INFORMATION.EX = .{ .Flags = .{ + var info: w.FILE.DISPOSITION.INFORMATION.EX = .{ .Flags = .{ .DELETE = true, .POSIX_SEMANTICS = true, .IGNORE_READONLY_ATTRIBUTE = true, @@ -5585,7 +5585,7 @@ fn dirDeleteWindows(userdata: ?*anyopaque, dir: Dir, sub_path: []const u8, remov // Deletion with file pending semantics, which requires waiting or moving // files to get them removed (from here). - const file_dispo: w.FILE.DISPOSITION.INFORMATION = .{ + var file_dispo: w.FILE.DISPOSITION.INFORMATION = .{ .DeleteFile = w.TRUE, }; @@ -5801,7 +5801,7 @@ fn dirRenameWindowsInner( // The strategy here is just to try using FileRenameInformationEx and fall back to // FileRenameInformation if the return value lets us know that some aspect of it is not supported. const need_fallback = need_fallback: { - const rename_info: w.FILE.RENAME_INFORMATION = .init(.{ + var rename_info: w.FILE.RENAME_INFORMATION = .init(.{ .Flags = .{ .REPLACE_IF_EXISTS = replace_if_exists, .POSIX_SEMANTICS = true, @@ -5834,7 +5834,7 @@ fn dirRenameWindowsInner( }; if (need_fallback) { - const rename_info: w.FILE.RENAME_INFORMATION = .init(.{ + var rename_info: w.FILE.RENAME_INFORMATION = .init(.{ .Flags = .{ .REPLACE_IF_EXISTS = replace_if_exists }, .RootDirectory = if (Dir.path.isAbsoluteWindowsWtf16(new_path_w)) null else new_dir.handle, .FileName = new_path_w, @@ -7104,7 +7104,7 @@ fn fileSetLength(userdata: ?*anyopaque, file: File, length: u64) File.SetLengthE if (is_windows) { var io_status_block: windows.IO_STATUS_BLOCK = undefined; - const eof_info: windows.FILE.END_OF_FILE_INFORMATION = .{ + var eof_info: windows.FILE.END_OF_FILE_INFORMATION = .{ .EndOfFile = signed_len, }; @@ -7195,7 +7195,7 @@ fn fileSetPermissions(userdata: ?*anyopaque, file: File, permissions: File.Permi switch (native_os) { .windows => { var io_status_block: windows.IO_STATUS_BLOCK = undefined; - const info: windows.FILE.BASIC_INFORMATION = .{ + var info: windows.FILE.BASIC_INFORMATION = .{ .CreationTime = 0, .LastAccessTime = 0, .LastWriteTime = 0, diff --git a/lib/std/os/windows.zig b/lib/std/os/windows.zig @@ -265,8 +265,8 @@ pub const FILE = struct { return ri.FileName[0..@divExact(ri.FileNameLength, @sizeOf(WCHAR))]; } - pub fn toBuffer(fri: *const RENAME_INFORMATION) []const u8 { - const start: [*]const u8 = @ptrCast(fri); + pub fn toBuffer(fri: *RENAME_INFORMATION) []u8 { + const start: [*]u8 = @ptrCast(fri); // The ABI size of the documented struct is 24 bytes, and attempting to use any size // less than that will trigger INFO_LENGTH_MISMATCH, so enforce a minimum in cases where, // for example, FileNameLength is 1 so only 22 bytes are technically needed. @@ -3134,7 +3134,7 @@ pub fn DeleteFile(sub_path_w: []const u16, options: DeleteFileOptions) DeleteFil // FileDispositionInformation if the return value lets us know that some aspect of it is not supported. const need_fallback = need_fallback: { // Deletion with posix semantics if the filesystem supports it. - const info: FILE.DISPOSITION.INFORMATION.EX = .{ .Flags = .{ + var info: FILE.DISPOSITION.INFORMATION.EX = .{ .Flags = .{ .DELETE = true, .POSIX_SEMANTICS = true, .IGNORE_READONLY_ATTRIBUTE = true, @@ -3163,7 +3163,7 @@ pub fn DeleteFile(sub_path_w: []const u16, options: DeleteFileOptions) DeleteFil if (need_fallback) { // Deletion with file pending semantics, which requires waiting or moving // files to get them removed (from here). - const file_dispo: FILE.DISPOSITION.INFORMATION = .{ + var file_dispo: FILE.DISPOSITION.INFORMATION = .{ .DeleteFile = TRUE, }; rc = ntdll.NtSetInformationFile( @@ -3242,7 +3242,7 @@ pub fn RenameFile( // The strategy here is just to try using FileRenameInformationEx and fall back to // FileRenameInformation if the return value lets us know that some aspect of it is not supported. const need_fallback = need_fallback: { - const rename_info: FILE.RENAME_INFORMATION = .init(.{ + var rename_info: FILE.RENAME_INFORMATION = .init(.{ .Flags = .{ .REPLACE_IF_EXISTS = replace_if_exists, .POSIX_SEMANTICS = true, @@ -3275,7 +3275,7 @@ pub fn RenameFile( }; if (need_fallback) { - const rename_info: FILE.RENAME_INFORMATION = .init(.{ + var rename_info: FILE.RENAME_INFORMATION = .init(.{ .Flags = .{ .REPLACE_IF_EXISTS = replace_if_exists }, .RootDirectory = if (std.fs.path.isAbsoluteWindowsWtf16(new_path_w)) null else new_dir_fd, .FileName = new_path_w, diff --git a/lib/std/os/windows/ntdll.zig b/lib/std/os/windows/ntdll.zig @@ -203,7 +203,10 @@ pub extern "ntdll" fn NtReadFile( pub extern "ntdll" fn NtSetInformationFile( FileHandle: HANDLE, IoStatusBlock: *IO_STATUS_BLOCK, - FileInformation: *const anyopaque, + /// This can't be const as providing read-only memory could result in ACCESS_VIOLATION + /// in certain scenarios. This has been seen when using FILE_DISPOSITION_INFORMATION_EX + /// and targeting x86-windows. + FileInformation: *anyopaque, Length: ULONG, FileInformationClass: FILE.INFORMATION_CLASS, ) callconv(.winapi) NTSTATUS;