|
1 | 1 | const std = @import("std");
|
| 2 | + |
2 | 3 | const windows = std.os.windows;
|
3 | 4 | const utf16Literal = std.unicode.utf8ToUtf16LeStringLiteral;
|
4 | 5 |
|
@@ -39,6 +40,9 @@ pub fn main() anyerror!void {
|
39 | 40 | // No PATH, so it should fail to find anything not in the cwd
|
40 | 41 | try testExecError(error.FileNotFound, allocator, "something_missing");
|
41 | 42 |
|
| 43 | + // Regression test - make sure we don't get error.BadPath traversing out of cwd with a relative path |
| 44 | + try testExecError(error.FileNotFound, allocator, "..\\.\\.\\.\\\\..\\more_missing"); |
| 45 | + |
42 | 46 | std.debug.assert(windows.kernel32.SetEnvironmentVariableW(
|
43 | 47 | utf16Literal("PATH"),
|
44 | 48 | tmp_absolute_path_w,
|
@@ -149,6 +153,42 @@ pub fn main() anyerror!void {
|
149 | 153 | // If we try to exec but provide a cwd that is an absolute path, the PATH
|
150 | 154 | // should still be searched and the goodbye.exe in something should be found.
|
151 | 155 | try testExecWithCwd(allocator, "goodbye", tmp_absolute_path, "hello from exe\n");
|
| 156 | + |
| 157 | + // introduce some extra path separators into the path which is dealt with inside the spawn call. |
| 158 | + const denormed_something_subdir_size = std.mem.replacementSize(u16, something_subdir_abs_path, utf16Literal("\\"), utf16Literal("\\\\\\\\")); |
| 159 | + |
| 160 | + const denormed_something_subdir_abs_path = try allocator.allocSentinel(u16, denormed_something_subdir_size, 0); |
| 161 | + defer allocator.free(denormed_something_subdir_abs_path); |
| 162 | + |
| 163 | + _ = std.mem.replace(u16, something_subdir_abs_path, utf16Literal("\\"), utf16Literal("\\\\\\\\"), denormed_something_subdir_abs_path); |
| 164 | + |
| 165 | + const denormed_something_subdir_wtf8 = try std.unicode.wtf16LeToWtf8Alloc(allocator, denormed_something_subdir_abs_path); |
| 166 | + defer allocator.free(denormed_something_subdir_wtf8); |
| 167 | + |
| 168 | + try testExecWithCwd(allocator, "goodbye", denormed_something_subdir_wtf8, "hello from exe\n"); |
| 169 | + |
| 170 | + // normalization should also work if the non-normalized path is found in the PATH var. |
| 171 | + std.debug.assert(windows.kernel32.SetEnvironmentVariableW( |
| 172 | + utf16Literal("PATH"), |
| 173 | + denormed_something_subdir_abs_path, |
| 174 | + ) == windows.TRUE); |
| 175 | + try testExec(allocator, "goodbye", "hello from exe\n"); |
| 176 | + |
| 177 | + // now make sure we can launch executables "outside" of the cwd |
| 178 | + var subdir_cwd = try tmp.dir.openDir(denormed_something_subdir_wtf8, .{}); |
| 179 | + defer subdir_cwd.close(); |
| 180 | + |
| 181 | + try tmp.dir.rename("something/goodbye.exe", "hello.exe"); |
| 182 | + try subdir_cwd.setAsCwd(); |
| 183 | + |
| 184 | + // clear the PATH again |
| 185 | + std.debug.assert(windows.kernel32.SetEnvironmentVariableW( |
| 186 | + utf16Literal("PATH"), |
| 187 | + null, |
| 188 | + ) == windows.TRUE); |
| 189 | + |
| 190 | + // while we're at it make sure non-windows separators work fine |
| 191 | + try testExec(allocator, "..\\hello", "hello from exe\n"); |
152 | 192 | }
|
153 | 193 |
|
154 | 194 | fn testExecError(err: anyerror, allocator: std.mem.Allocator, command: []const u8) !void {
|
|
0 commit comments