Skip to content

Commit bb8b24f

Browse files
committed
Validate DOS path before returning
And some other minor refactors which address more review comments.
1 parent cd8e6b6 commit bb8b24f

File tree

1 file changed

+14
-6
lines changed

1 file changed

+14
-6
lines changed

lib/std/os/windows.zig

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -897,6 +897,7 @@ pub fn SetFilePointerEx_CURRENT_get(handle: HANDLE) SetFilePointerError!u64 {
897897
}
898898

899899
pub const GetFinalPathNameByHandleError = error{
900+
BadPathName,
900901
FileNotFound,
901902
NameTooLong,
902903
Unexpected,
@@ -925,11 +926,11 @@ pub fn GetFinalPathNameByHandle(
925926
) GetFinalPathNameByHandleError![]u16 {
926927
// Get normalized path; doesn't include volume name though.
927928
var path_buffer: [@sizeOf(FILE_NAME_INFORMATION) + PATH_MAX_WIDE * 2]u8 align(@alignOf(FILE_NAME_INFORMATION)) = undefined;
928-
try QueryInformationFile(hFile, FILE_INFORMATION_CLASS.FileNormalizedNameInformation, path_buffer[0..]);
929+
try QueryInformationFile(hFile, .FileNormalizedNameInformation, path_buffer[0..]);
929930

930931
// Get NT volume name.
931932
var volume_buffer: [@sizeOf(FILE_NAME_INFORMATION) + MAX_PATH]u8 align(@alignOf(FILE_NAME_INFORMATION)) = undefined; // MAX_PATH bytes should be enough since it's Windows-defined name
932-
try QueryInformationFile(hFile, FILE_INFORMATION_CLASS.FileVolumeNameInformation, volume_buffer[0..]);
933+
try QueryInformationFile(hFile, .FileVolumeNameInformation, volume_buffer[0..]);
933934

934935
const file_name = @ptrCast(*const FILE_NAME_INFORMATION, &path_buffer[0]);
935936
const file_name_u16 = @ptrCast([*]const u16, &file_name.FileName[0])[0 .. file_name.FileNameLength / 2];
@@ -1010,8 +1011,17 @@ pub fn GetFinalPathNameByHandle(
10101011

10111012
std.mem.copy(u16, out_buffer[0..], drive_letter);
10121013
std.mem.copy(u16, out_buffer[drive_letter.len..], file_name_u16);
1014+
const total_len = drive_letter.len + file_name_u16.len;
10131015

1014-
return out_buffer[0 .. drive_letter.len + file_name_u16.len];
1016+
// Validate that DOS does not contain any spurious nul bytes.
1017+
var iter = std.unicode.Utf16LeIterator.init(out_buffer[0..total_len]);
1018+
var next = iter.nextCodepoint() catch return error.BadPathName;
1019+
while (next) |cp| {
1020+
if (cp == 0) return error.BadPathName;
1021+
next = iter.nextCodepoint() catch return error.BadPathName;
1022+
}
1023+
1024+
return out_buffer[0 .. total_len];
10151025
}
10161026
}
10171027

@@ -1030,9 +1040,7 @@ pub fn QueryInformationFile(
10301040
out_buffer: []u8,
10311041
) QueryInformationFileError!void {
10321042
var io: IO_STATUS_BLOCK = undefined;
1033-
const len_bytes = std.math.cast(u32, out_buffer.len) catch |err| switch (err) {
1034-
error.Overflow => std.math.maxInt(u32), // If the provided buffer is larger than what we can handle, set size to max what we can handle
1035-
};
1043+
const len_bytes = std.math.cast(u32, out_buffer.len) catch unreachable;
10361044
const rc = ntdll.NtQueryInformationFile(handle, &io, out_buffer.ptr, len_bytes, info_class);
10371045
switch (rc) {
10381046
.SUCCESS => {},

0 commit comments

Comments
 (0)