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