diff --git a/lib/std/child_process.zig b/lib/std/child_process.zig index 1cdbd2e9d1..7bff9fe089 100644 --- a/lib/std/child_process.zig +++ b/lib/std/child_process.zig @@ -1022,8 +1022,12 @@ pub const ChildProcess = struct { }; // If the app name had path separators, that disallows PATH searching, - // and there's no need to search the PATH if the cwd path is absolute. - if (app_dirname_w != null or fs.path.isAbsoluteWindowsWTF16(cwd_path_w)) { + // and there's no need to search the PATH if the app name is absolute. + // We still search the path if the cwd is absolute because of the + // "cwd set in ChildProcess is in effect when choosing the executable path + // to match posix semantics" behavior--we don't want to skip searching + // the PATH just because we were trying to set the cwd of the child process. + if (app_dirname_w != null or app_name_is_absolute) { return original_err; } diff --git a/test/standalone/windows_spawn/main.zig b/test/standalone/windows_spawn/main.zig index 970ff959f3..c0cfd15133 100644 --- a/test/standalone/windows_spawn/main.zig +++ b/test/standalone/windows_spawn/main.zig @@ -142,6 +142,10 @@ pub fn main() anyerror!void { defer allocator.free(goodbye_abs_path); // then the PATH should not be searched and we should get InvalidExe try testExecError(error.InvalidExe, allocator, goodbye_abs_path); + + // If we try to exec but provide a cwd that is an absolute path, the PATH + // should still be searched and the goodbye.exe in something should be found. + try testExecWithCwd(allocator, "goodbye", tmp_absolute_path, "hello from exe\n"); } fn testExecError(err: anyerror, allocator: std.mem.Allocator, command: []const u8) !void { @@ -149,9 +153,14 @@ fn testExecError(err: anyerror, allocator: std.mem.Allocator, command: []const u } fn testExec(allocator: std.mem.Allocator, command: []const u8, expected_stdout: []const u8) !void { + return testExecWithCwd(allocator, command, null, expected_stdout); +} + +fn testExecWithCwd(allocator: std.mem.Allocator, command: []const u8, cwd: ?[]const u8, expected_stdout: []const u8) !void { var result = try std.ChildProcess.exec(.{ .allocator = allocator, .argv = &[_][]const u8{command}, + .cwd = cwd, }); defer allocator.free(result.stdout); defer allocator.free(result.stderr);