authorgravatar for squeek502@hotmail.comRyan Liptak <squeek502@hotmail.com> 2022-01-15 04:56:32-08:00
committergravatar for squeek502@hotmail.comRyan Liptak <squeek502@hotmail.com> 2022-02-19 15:46:23-08:00
logc87f79c957a74fae16931a71d4c6414f9d58acf6
tree6d589478a61090141309f7daba0a40b45619134c
parent8841a71aa675f76c0ff7658339872a5faa5e4d5b

os.getenvW: Fix case-insensitivity for Unicode env var names

Windows does Unicode-aware case-insensitivity comparisons for environment variable names. Before, os.getenvW was only doing ASCII case-insensitivity. We can take advantage of RtlEqualUnicodeString in NtDll to get the proper Unicode case insensitivity.

2 files changed, 22 insertions(+), 15 deletions(-)

lib/std/os.zig+16-15
...@@ -1715,15 +1715,13 @@ pub fn getenvZ(key: [*:0]const u8) ?[]const u8 {...@@ -1715,15 +1715,13 @@ pub fn getenvZ(key: [*:0]const u8) ?[]const u8 {
17151715
1716/// Windows-only. Get an environment variable with a null-terminated, WTF-16 encoded name.1716/// Windows-only. Get an environment variable with a null-terminated, WTF-16 encoded name.
1717/// See also `getenv`.1717/// See also `getenv`.
1718/// This function first attempts a case-sensitive lookup. If no match is found, and `key`1718/// This function performs a Unicode-aware case-insensitive lookup using RtlEqualUnicodeString.
1719/// is ASCII, then it attempts a second case-insensitive lookup.
1720pub fn getenvW(key: [*:0]const u16) ?[:0]const u16 {1719pub fn getenvW(key: [*:0]const u16) ?[:0]const u16 {
1721 if (builtin.os.tag != .windows) {1720 if (builtin.os.tag != .windows) {
1722 @compileError("std.os.getenvW is a Windows-only API");1721 @compileError("std.os.getenvW is a Windows-only API");
1723 }1722 }
1724 const key_slice = mem.sliceTo(key, 0);1723 const key_slice = mem.sliceTo(key, 0);
1725 const ptr = windows.peb().ProcessParameters.Environment;1724 const ptr = windows.peb().ProcessParameters.Environment;
1726 var ascii_match: ?[:0]const u16 = null;
1727 var i: usize = 0;1725 var i: usize = 0;
1728 while (ptr[i] != 0) {1726 while (ptr[i] != 0) {
1729 const key_start = i;1727 const key_start = i;
...@@ -1737,22 +1735,25 @@ pub fn getenvW(key: [*:0]const u16) ?[:0]const u16 {...@@ -1737,22 +1735,25 @@ pub fn getenvW(key: [*:0]const u16) ?[:0]const u16 {
1737 while (ptr[i] != 0) : (i += 1) {}1735 while (ptr[i] != 0) : (i += 1) {}
1738 const this_value = ptr[value_start..i :0];1736 const this_value = ptr[value_start..i :0];
17391737
1740 if (mem.eql(u16, key_slice, this_key)) return this_value;1738 const key_string_bytes = @intCast(u16, key_slice.len * 2);
17411739 const key_string = windows.UNICODE_STRING{
1742 ascii_check: {1740 .Length = key_string_bytes,
1743 if (ascii_match != null) break :ascii_check;1741 .MaximumLength = key_string_bytes,
1744 if (key_slice.len != this_key.len) break :ascii_check;1742 .Buffer = @intToPtr([*]u16, @ptrToInt(key)),
1745 for (key_slice) |a_c, key_index| {1743 };
1746 const a = math.cast(u8, a_c) catch break :ascii_check;1744 const this_key_string_bytes = @intCast(u16, this_key.len * 2);
1747 const b = math.cast(u8, this_key[key_index]) catch break :ascii_check;1745 const this_key_string = windows.UNICODE_STRING{
1748 if (std.ascii.toLower(a) != std.ascii.toLower(b)) break :ascii_check;1746 .Length = this_key_string_bytes,
1749 }1747 .MaximumLength = this_key_string_bytes,
1750 ascii_match = this_value;1748 .Buffer = this_key.ptr,
1749 };
1750 if (windows.ntdll.RtlEqualUnicodeString(&key_string, &this_key_string, windows.TRUE) == windows.TRUE) {
1751 return this_value;
1751 }1752 }
17521753
1753 i += 1; // skip over null byte1754 i += 1; // skip over null byte
1754 }1755 }
1755 return ascii_match;1756 return null;
1756}1757}
17571758
1758pub const GetCwdError = error{1759pub const GetCwdError = error{
lib/std/os/windows/ntdll.zig+6
...@@ -223,6 +223,12 @@ pub extern "ntdll" fn RtlWaitOnAddress(...@@ -223,6 +223,12 @@ pub extern "ntdll" fn RtlWaitOnAddress(
223 Timeout: ?*const LARGE_INTEGER,223 Timeout: ?*const LARGE_INTEGER,
224) callconv(WINAPI) NTSTATUS;224) callconv(WINAPI) NTSTATUS;
225225
226pub extern "ntdll" fn RtlEqualUnicodeString(
227 String1: *const UNICODE_STRING,
228 String2: *const UNICODE_STRING,
229 CaseInSensitive: BOOLEAN,
230) callconv(WINAPI) BOOLEAN;
231
226pub extern "ntdll" fn NtLockFile(232pub extern "ntdll" fn NtLockFile(
227 FileHandle: HANDLE,233 FileHandle: HANDLE,
228 Event: ?HANDLE,234 Event: ?HANDLE,