authorgravatar for johnnymarler@gmail.comJonathan Marler <johnnymarler@gmail.com> 2021-05-20 23:23:10-06:00
committergravatar for johnnymarler@gmail.comJonathan Marler <johnnymarler@gmail.com> 2021-05-21 01:29:40-06:00
logb0116afd8adbc73d820fee418ec74104f43bff6e
tree4df1fb91ca3f5a3709042edc75e6f309b387b895
parent59de5d0350f76933549e5402f090785351d9498d

handle relative paths with too many ".."


5 files changed, 36 insertions(+), 7 deletions(-)

lib/std/fs/test.zig+2-2
...@@ -95,8 +95,8 @@ test "openDirAbsolute" {...@@ -95,8 +95,8 @@ test "openDirAbsolute" {
95test "openDir cwd parent .." {95test "openDir cwd parent .." {
96 if (builtin.os.tag == .wasi) return error.SkipZigTest;96 if (builtin.os.tag == .wasi) return error.SkipZigTest;
9797
98 var cwd = try fs.cwd().openDir("..", .{});98 var dir = try fs.cwd().openDir("..", .{});
99 defer cwd.close();99 defer dir.close();
100}100}
101101
102test "readLinkAbsolute" {102test "readLinkAbsolute" {
lib/std/mem.zig+1-1
...@@ -2151,7 +2151,7 @@ pub fn collapseRepeats(comptime T: type, slice: []T, elem: T) []T {...@@ -2151,7 +2151,7 @@ pub fn collapseRepeats(comptime T: type, slice: []T, elem: T) []T {
2151fn testCollapseRepeats(str: []const u8, elem: u8, expected: []const u8) !void {2151fn testCollapseRepeats(str: []const u8, elem: u8, expected: []const u8) !void {
2152 const mutable = try std.testing.allocator.dupe(u8, str);2152 const mutable = try std.testing.allocator.dupe(u8, str);
2153 defer std.testing.allocator.free(mutable);2153 defer std.testing.allocator.free(mutable);
2154 testing.expect(std.mem.eql(u8, collapseRepeats(u8, mutable, elem), expected));2154 try testing.expect(std.mem.eql(u8, collapseRepeats(u8, mutable, elem), expected));
2155}2155}
2156test "collapseRepeats" {2156test "collapseRepeats" {
2157 try testCollapseRepeats("", '/', "");2157 try testCollapseRepeats("", '/', "");
lib/std/os/windows.zig+24-2
...@@ -1817,20 +1817,42 @@ pub fn sliceToPrefixedFileW(s: []const u8) !PathSpace {...@@ -1817,20 +1817,42 @@ pub fn sliceToPrefixedFileW(s: []const u8) !PathSpace {
1817 else => {},1817 else => {},
1818 }1818 }
1819 }1819 }
1820 const prefix_u16 = [_]u16{ '\\', '?', '?', '\\' };
1820 const start_index = if (prefix_index > 0 or !std.fs.path.isAbsolute(s)) 0 else blk: {1821 const start_index = if (prefix_index > 0 or !std.fs.path.isAbsolute(s)) 0 else blk: {
1821 const prefix_u16 = [_]u16{ '\\', '?', '?', '\\' };
1822 mem.copy(u16, path_space.data[0..], prefix_u16[0..]);1822 mem.copy(u16, path_space.data[0..], prefix_u16[0..]);
1823 break :blk prefix_u16.len;1823 break :blk prefix_u16.len;
1824 };1824 };
1825 path_space.len = start_index + try std.unicode.utf8ToUtf16Le(path_space.data[start_index..], s);1825 path_space.len = start_index + try std.unicode.utf8ToUtf16Le(path_space.data[start_index..], s);
1826 if (path_space.len > path_space.data.len) return error.NameTooLong;1826 if (path_space.len > path_space.data.len) return error.NameTooLong;
1827 path_space.len = start_index + (normalizePath(u16, path_space.data[start_index..path_space.len]) catch |err| switch (err) {1827 path_space.len = start_index + (normalizePath(u16, path_space.data[start_index..path_space.len]) catch |err| switch (err) {
1828 error.TooManyParentDirs => return error.BadPathName,1828 error.TooManyParentDirs => {
1829 if (!std.fs.path.isAbsolute(s)) {
1830 var temp_path: PathSpace = undefined;
1831 temp_path.len = try std.unicode.utf8ToUtf16Le(&temp_path.data, s);
1832 std.debug.assert(temp_path.len == path_space.len);
1833 temp_path.data[path_space.len] = 0;
1834 path_space.len = prefix_u16.len + try getFullPathNameW(&temp_path.data, path_space.data[prefix_u16.len..]);
1835 mem.copy(u16, &path_space.data, &prefix_u16);
1836 std.debug.assert(path_space.data[path_space.len] == 0);
1837 return path_space;
1838 }
1839 return error.BadPathName;
1840 },
1829 });1841 });
1830 path_space.data[path_space.len] = 0;1842 path_space.data[path_space.len] = 0;
1831 return path_space;1843 return path_space;
1832}1844}
18331845
1846fn getFullPathNameW(path: [*:0]const u16, out: []u16) !usize {
1847 const result= kernel32.GetFullPathNameW(path, @intCast(u32, out.len), std.meta.assumeSentinel(out.ptr, 0), null);
1848 if (result == 0) {
1849 switch (kernel32.GetLastError()) {
1850 else => |err| return unexpectedError(err),
1851 }
1852 }
1853 return result;
1854}
1855
1834/// Assumes an absolute path.1856/// Assumes an absolute path.
1835pub fn wToPrefixedFileW(s: []const u16) !PathSpace {1857pub fn wToPrefixedFileW(s: []const u16) !PathSpace {
1836 // TODO https://github.com/ziglang/zig/issues/27651858 // TODO https://github.com/ziglang/zig/issues/2765
lib/std/os/windows/kernel32.zig+7
...@@ -136,6 +136,13 @@ pub extern "kernel32" fn GetFinalPathNameByHandleW(...@@ -136,6 +136,13 @@ pub extern "kernel32" fn GetFinalPathNameByHandleW(
136 dwFlags: DWORD,136 dwFlags: DWORD,
137) callconv(WINAPI) DWORD;137) callconv(WINAPI) DWORD;
138138
139pub extern "kernel32" fn GetFullPathNameW(
140 lpFileName: [*:0]const u16,
141 nBufferLength: u32,
142 lpBuffer: ?[*:0]u16,
143 lpFilePart: ?*?[*:0]u16,
144) callconv(@import("std").os.windows.WINAPI) u32;
145
139pub extern "kernel32" fn GetOverlappedResult(hFile: HANDLE, lpOverlapped: *OVERLAPPED, lpNumberOfBytesTransferred: *DWORD, bWait: BOOL) callconv(WINAPI) BOOL;146pub extern "kernel32" fn GetOverlappedResult(hFile: HANDLE, lpOverlapped: *OVERLAPPED, lpNumberOfBytesTransferred: *DWORD, bWait: BOOL) callconv(WINAPI) BOOL;
140147
141pub extern "kernel32" fn GetProcessHeap() callconv(WINAPI) ?HANDLE;148pub extern "kernel32" fn GetProcessHeap() callconv(WINAPI) ?HANDLE;
lib/std/os/windows/test.zig+2-2
...@@ -14,12 +14,12 @@ fn testRemoveDotDirs(str: []const u8, expected: []const u8) !void {...@@ -14,12 +14,12 @@ fn testRemoveDotDirs(str: []const u8, expected: []const u8) !void {
14 const mutable = try testing.allocator.dupe(u8, str);14 const mutable = try testing.allocator.dupe(u8, str);
15 defer testing.allocator.free(mutable);15 defer testing.allocator.free(mutable);
16 const actual = mutable[0..try windows.removeDotDirsSanitized(u8, mutable)];16 const actual = mutable[0..try windows.removeDotDirsSanitized(u8, mutable)];
17 testing.expect(mem.eql(u8, actual, expected));17 try testing.expect(mem.eql(u8, actual, expected));
18}18}
19fn testRemoveDotDirsError(err: anyerror, str: []const u8) !void {19fn testRemoveDotDirsError(err: anyerror, str: []const u8) !void {
20 const mutable = try testing.allocator.dupe(u8, str);20 const mutable = try testing.allocator.dupe(u8, str);
21 defer testing.allocator.free(mutable);21 defer testing.allocator.free(mutable);
22 testing.expectError(err, windows.removeDotDirsSanitized(u8, mutable));22 try testing.expectError(err, windows.removeDotDirsSanitized(u8, mutable));
23}23}
24test "removeDotDirs" {24test "removeDotDirs" {
25 try testRemoveDotDirs("", "");25 try testRemoveDotDirs("", "");