| author | |
| committer | |
| log | 2301f2ecdf3a4f823c1a66482af2574738ffb554 |
| tree | ac05f814a34d07aa704f04cc7a5e34a6fd38c320 |
| parent | 47cc233f220bcfb7b7183692861651423d965117 |
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/308023 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 |
| 5550 | 5550 | // FileDispositionInformation if the return value lets us know that some aspect of it is not supported. |
| 5551 | 5551 | const rc = rc: { |
| 5552 | 5552 | // 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 = .{ | |
| 5554 | 5554 | .DELETE = true, |
| 5555 | 5555 | .POSIX_SEMANTICS = true, |
| 5556 | 5556 | .IGNORE_READONLY_ATTRIBUTE = true, |
| ... | ... | @@ -5585,7 +5585,7 @@ fn dirDeleteWindows(userdata: ?*anyopaque, dir: Dir, sub_path: []const u8, remov |
| 5585 | 5585 | |
| 5586 | 5586 | // Deletion with file pending semantics, which requires waiting or moving |
| 5587 | 5587 | // files to get them removed (from here). |
| 5588 | const file_dispo: w.FILE.DISPOSITION.INFORMATION = .{ | |
| 5588 | var file_dispo: w.FILE.DISPOSITION.INFORMATION = .{ | |
| 5589 | 5589 | .DeleteFile = w.TRUE, |
| 5590 | 5590 | }; |
| 5591 | 5591 | |
| ... | ... | @@ -5801,7 +5801,7 @@ fn dirRenameWindowsInner( |
| 5801 | 5801 | // The strategy here is just to try using FileRenameInformationEx and fall back to |
| 5802 | 5802 | // FileRenameInformation if the return value lets us know that some aspect of it is not supported. |
| 5803 | 5803 | const need_fallback = need_fallback: { |
| 5804 | const rename_info: w.FILE.RENAME_INFORMATION = .init(.{ | |
| 5804 | var rename_info: w.FILE.RENAME_INFORMATION = .init(.{ | |
| 5805 | 5805 | .Flags = .{ |
| 5806 | 5806 | .REPLACE_IF_EXISTS = replace_if_exists, |
| 5807 | 5807 | .POSIX_SEMANTICS = true, |
| ... | ... | @@ -5834,7 +5834,7 @@ fn dirRenameWindowsInner( |
| 5834 | 5834 | }; |
| 5835 | 5835 | |
| 5836 | 5836 | if (need_fallback) { |
| 5837 | const rename_info: w.FILE.RENAME_INFORMATION = .init(.{ | |
| 5837 | var rename_info: w.FILE.RENAME_INFORMATION = .init(.{ | |
| 5838 | 5838 | .Flags = .{ .REPLACE_IF_EXISTS = replace_if_exists }, |
| 5839 | 5839 | .RootDirectory = if (Dir.path.isAbsoluteWindowsWtf16(new_path_w)) null else new_dir.handle, |
| 5840 | 5840 | .FileName = new_path_w, |
| ... | ... | @@ -7104,7 +7104,7 @@ fn fileSetLength(userdata: ?*anyopaque, file: File, length: u64) File.SetLengthE |
| 7104 | 7104 | |
| 7105 | 7105 | if (is_windows) { |
| 7106 | 7106 | 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 = .{ | |
| 7108 | 7108 | .EndOfFile = signed_len, |
| 7109 | 7109 | }; |
| 7110 | 7110 | |
| ... | ... | @@ -7195,7 +7195,7 @@ fn fileSetPermissions(userdata: ?*anyopaque, file: File, permissions: File.Permi |
| 7195 | 7195 | switch (native_os) { |
| 7196 | 7196 | .windows => { |
| 7197 | 7197 | var io_status_block: windows.IO_STATUS_BLOCK = undefined; |
| 7198 | const info: windows.FILE.BASIC_INFORMATION = .{ | |
| 7198 | var info: windows.FILE.BASIC_INFORMATION = .{ | |
| 7199 | 7199 | .CreationTime = 0, |
| 7200 | 7200 | .LastAccessTime = 0, |
| 7201 | 7201 | .LastWriteTime = 0, |
lib/std/os/windows.zig+6-6| ... | ... | @@ -265,8 +265,8 @@ pub const FILE = struct { |
| 265 | 265 | return ri.FileName[0..@divExact(ri.FileNameLength, @sizeOf(WCHAR))]; |
| 266 | 266 | } |
| 267 | 267 | |
| 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); | |
| 270 | 270 | // The ABI size of the documented struct is 24 bytes, and attempting to use any size |
| 271 | 271 | // less than that will trigger INFO_LENGTH_MISMATCH, so enforce a minimum in cases where, |
| 272 | 272 | // 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 |
| 3134 | 3134 | // FileDispositionInformation if the return value lets us know that some aspect of it is not supported. |
| 3135 | 3135 | const need_fallback = need_fallback: { |
| 3136 | 3136 | // 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 = .{ | |
| 3138 | 3138 | .DELETE = true, |
| 3139 | 3139 | .POSIX_SEMANTICS = true, |
| 3140 | 3140 | .IGNORE_READONLY_ATTRIBUTE = true, |
| ... | ... | @@ -3163,7 +3163,7 @@ pub fn DeleteFile(sub_path_w: []const u16, options: DeleteFileOptions) DeleteFil |
| 3163 | 3163 | if (need_fallback) { |
| 3164 | 3164 | // Deletion with file pending semantics, which requires waiting or moving |
| 3165 | 3165 | // files to get them removed (from here). |
| 3166 | const file_dispo: FILE.DISPOSITION.INFORMATION = .{ | |
| 3166 | var file_dispo: FILE.DISPOSITION.INFORMATION = .{ | |
| 3167 | 3167 | .DeleteFile = TRUE, |
| 3168 | 3168 | }; |
| 3169 | 3169 | rc = ntdll.NtSetInformationFile( |
| ... | ... | @@ -3242,7 +3242,7 @@ pub fn RenameFile( |
| 3242 | 3242 | // The strategy here is just to try using FileRenameInformationEx and fall back to |
| 3243 | 3243 | // FileRenameInformation if the return value lets us know that some aspect of it is not supported. |
| 3244 | 3244 | const need_fallback = need_fallback: { |
| 3245 | const rename_info: FILE.RENAME_INFORMATION = .init(.{ | |
| 3245 | var rename_info: FILE.RENAME_INFORMATION = .init(.{ | |
| 3246 | 3246 | .Flags = .{ |
| 3247 | 3247 | .REPLACE_IF_EXISTS = replace_if_exists, |
| 3248 | 3248 | .POSIX_SEMANTICS = true, |
| ... | ... | @@ -3275,7 +3275,7 @@ pub fn RenameFile( |
| 3275 | 3275 | }; |
| 3276 | 3276 | |
| 3277 | 3277 | if (need_fallback) { |
| 3278 | const rename_info: FILE.RENAME_INFORMATION = .init(.{ | |
| 3278 | var rename_info: FILE.RENAME_INFORMATION = .init(.{ | |
| 3279 | 3279 | .Flags = .{ .REPLACE_IF_EXISTS = replace_if_exists }, |
| 3280 | 3280 | .RootDirectory = if (std.fs.path.isAbsoluteWindowsWtf16(new_path_w)) null else new_dir_fd, |
| 3281 | 3281 | .FileName = new_path_w, |
lib/std/os/windows/ntdll.zig+4-1| ... | ... | @@ -203,7 +203,10 @@ pub extern "ntdll" fn NtReadFile( |
| 203 | 203 | pub extern "ntdll" fn NtSetInformationFile( |
| 204 | 204 | FileHandle: HANDLE, |
| 205 | 205 | 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, | |
| 207 | 210 | Length: ULONG, |
| 208 | 211 | FileInformationClass: FILE.INFORMATION_CLASS, |
| 209 | 212 | ) callconv(.winapi) NTSTATUS; |