authorgravatar for squeek502@hotmail.comRyan Liptak <squeek502@hotmail.com> 2026-01-12 20:28:03-08:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2026-01-13 20:45:38+01:00
log2301f2ecdf3a4f823c1a66482af2574738ffb554
treeac05f814a34d07aa704f04cc7a5e34a6fd38c320
parent47cc233f220bcfb7b7183692861651423d965117

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

3 files changed, 16 insertions(+), 13 deletions(-)

lib/std/Io/Threaded.zig+6-6
......@@ -5550,7 +5550,7 @@ fn dirDeleteWindows(userdata: ?*anyopaque, dir: Dir, sub_path: []const u8, remov
55505550 // FileDispositionInformation if the return value lets us know that some aspect of it is not supported.
55515551 const rc = rc: {
55525552 // Deletion with posix semantics if the filesystem supports it.
5553 const info: w.FILE.DISPOSITION.INFORMATION.EX = .{ .Flags = .{
5553 var info: w.FILE.DISPOSITION.INFORMATION.EX = .{ .Flags = .{
55545554 .DELETE = true,
55555555 .POSIX_SEMANTICS = true,
55565556 .IGNORE_READONLY_ATTRIBUTE = true,
......@@ -5585,7 +5585,7 @@ fn dirDeleteWindows(userdata: ?*anyopaque, dir: Dir, sub_path: []const u8, remov
55855585
55865586 // Deletion with file pending semantics, which requires waiting or moving
55875587 // files to get them removed (from here).
5588 const file_dispo: w.FILE.DISPOSITION.INFORMATION = .{
5588 var file_dispo: w.FILE.DISPOSITION.INFORMATION = .{
55895589 .DeleteFile = w.TRUE,
55905590 };
55915591
......@@ -5801,7 +5801,7 @@ fn dirRenameWindowsInner(
58015801 // The strategy here is just to try using FileRenameInformationEx and fall back to
58025802 // FileRenameInformation if the return value lets us know that some aspect of it is not supported.
58035803 const need_fallback = need_fallback: {
5804 const rename_info: w.FILE.RENAME_INFORMATION = .init(.{
5804 var rename_info: w.FILE.RENAME_INFORMATION = .init(.{
58055805 .Flags = .{
58065806 .REPLACE_IF_EXISTS = replace_if_exists,
58075807 .POSIX_SEMANTICS = true,
......@@ -5834,7 +5834,7 @@ fn dirRenameWindowsInner(
58345834 };
58355835
58365836 if (need_fallback) {
5837 const rename_info: w.FILE.RENAME_INFORMATION = .init(.{
5837 var rename_info: w.FILE.RENAME_INFORMATION = .init(.{
58385838 .Flags = .{ .REPLACE_IF_EXISTS = replace_if_exists },
58395839 .RootDirectory = if (Dir.path.isAbsoluteWindowsWtf16(new_path_w)) null else new_dir.handle,
58405840 .FileName = new_path_w,
......@@ -7104,7 +7104,7 @@ fn fileSetLength(userdata: ?*anyopaque, file: File, length: u64) File.SetLengthE
71047104
71057105 if (is_windows) {
71067106 var io_status_block: windows.IO_STATUS_BLOCK = undefined;
7107 const eof_info: windows.FILE.END_OF_FILE_INFORMATION = .{
7107 var eof_info: windows.FILE.END_OF_FILE_INFORMATION = .{
71087108 .EndOfFile = signed_len,
71097109 };
71107110
......@@ -7195,7 +7195,7 @@ fn fileSetPermissions(userdata: ?*anyopaque, file: File, permissions: File.Permi
71957195 switch (native_os) {
71967196 .windows => {
71977197 var io_status_block: windows.IO_STATUS_BLOCK = undefined;
7198 const info: windows.FILE.BASIC_INFORMATION = .{
7198 var info: windows.FILE.BASIC_INFORMATION = .{
71997199 .CreationTime = 0,
72007200 .LastAccessTime = 0,
72017201 .LastWriteTime = 0,
lib/std/os/windows.zig+6-6
......@@ -265,8 +265,8 @@ pub const FILE = struct {
265265 return ri.FileName[0..@divExact(ri.FileNameLength, @sizeOf(WCHAR))];
266266 }
267267
268 pub fn toBuffer(fri: *const RENAME_INFORMATION) []const u8 {
269 const start: [*]const u8 = @ptrCast(fri);
268 pub fn toBuffer(fri: *RENAME_INFORMATION) []u8 {
269 const start: [*]u8 = @ptrCast(fri);
270270 // The ABI size of the documented struct is 24 bytes, and attempting to use any size
271271 // less than that will trigger INFO_LENGTH_MISMATCH, so enforce a minimum in cases where,
272272 // 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
31343134 // FileDispositionInformation if the return value lets us know that some aspect of it is not supported.
31353135 const need_fallback = need_fallback: {
31363136 // Deletion with posix semantics if the filesystem supports it.
3137 const info: FILE.DISPOSITION.INFORMATION.EX = .{ .Flags = .{
3137 var info: FILE.DISPOSITION.INFORMATION.EX = .{ .Flags = .{
31383138 .DELETE = true,
31393139 .POSIX_SEMANTICS = true,
31403140 .IGNORE_READONLY_ATTRIBUTE = true,
......@@ -3163,7 +3163,7 @@ pub fn DeleteFile(sub_path_w: []const u16, options: DeleteFileOptions) DeleteFil
31633163 if (need_fallback) {
31643164 // Deletion with file pending semantics, which requires waiting or moving
31653165 // files to get them removed (from here).
3166 const file_dispo: FILE.DISPOSITION.INFORMATION = .{
3166 var file_dispo: FILE.DISPOSITION.INFORMATION = .{
31673167 .DeleteFile = TRUE,
31683168 };
31693169 rc = ntdll.NtSetInformationFile(
......@@ -3242,7 +3242,7 @@ pub fn RenameFile(
32423242 // The strategy here is just to try using FileRenameInformationEx and fall back to
32433243 // FileRenameInformation if the return value lets us know that some aspect of it is not supported.
32443244 const need_fallback = need_fallback: {
3245 const rename_info: FILE.RENAME_INFORMATION = .init(.{
3245 var rename_info: FILE.RENAME_INFORMATION = .init(.{
32463246 .Flags = .{
32473247 .REPLACE_IF_EXISTS = replace_if_exists,
32483248 .POSIX_SEMANTICS = true,
......@@ -3275,7 +3275,7 @@ pub fn RenameFile(
32753275 };
32763276
32773277 if (need_fallback) {
3278 const rename_info: FILE.RENAME_INFORMATION = .init(.{
3278 var rename_info: FILE.RENAME_INFORMATION = .init(.{
32793279 .Flags = .{ .REPLACE_IF_EXISTS = replace_if_exists },
32803280 .RootDirectory = if (std.fs.path.isAbsoluteWindowsWtf16(new_path_w)) null else new_dir_fd,
32813281 .FileName = new_path_w,
lib/std/os/windows/ntdll.zig+4-1
......@@ -203,7 +203,10 @@ pub extern "ntdll" fn NtReadFile(
203203pub extern "ntdll" fn NtSetInformationFile(
204204 FileHandle: HANDLE,
205205 IoStatusBlock: *IO_STATUS_BLOCK,
206 FileInformation: *const anyopaque,
206 /// This can't be const as providing read-only memory could result in ACCESS_VIOLATION
207 /// in certain scenarios. This has been seen when using FILE_DISPOSITION_INFORMATION_EX
208 /// and targeting x86-windows.
209 FileInformation: *anyopaque,
207210 Length: ULONG,
208211 FileInformationClass: FILE.INFORMATION_CLASS,
209212) callconv(.winapi) NTSTATUS;