aboutsummaryrefslogtreecommitdiff
path: root/lib/std/os.zig
diff options
context:
space:
mode:
authorAndrew Kelley <andrew@ziglang.org>2020-02-22 13:43:48 -0500
committerAndrew Kelley <andrew@ziglang.org>2020-02-22 13:56:02 -0500
commit0cd89e9176ab36fc5e267120dc4d75cb79d32684 (patch)
treec2109735be89fdaf86b55a95d98a4797d086217c /lib/std/os.zig
parentdca19b67573dc46260b318e9253370fbc628834d (diff)
downloadzig-0cd89e9176ab36fc5e267120dc4d75cb79d32684.tar.gz
zig-0cd89e9176ab36fc5e267120dc4d75cb79d32684.zip
std.os.execvpeZ_expandArg0: fix not restoring argv[0]
This function expands argv[0] into the absolute path resolved with PATH environment variable before making the execve syscall. However, in case the execve fails, e.g. with ENOENT, it did not restore argv to how it was before it was passed in. This resulted in the caller performing an invalid free. This commit also adds verbose debug info when native system C compiler detection fails. See #4521.
Diffstat (limited to 'lib/std/os.zig')
-rw-r--r--lib/std/os.zig9
1 files changed, 9 insertions, 0 deletions
diff --git a/lib/std/os.zig b/lib/std/os.zig
index 0f492a25f2..766b678c46 100644
--- a/lib/std/os.zig
+++ b/lib/std/os.zig
@@ -955,6 +955,7 @@ pub const Arg0Expand = enum {
/// Like `execvpeZ` except if `arg0_expand` is `.expand`, then `argv` is mutable,
/// and `argv[0]` is expanded to be the same absolute path that is passed to the execve syscall.
+/// If this function returns with an error, `argv[0]` will be restored to the value it was when it was passed in.
pub fn execvpeZ_expandArg0(
comptime arg0_expand: Arg0Expand,
file: [*:0]const u8,
@@ -972,6 +973,14 @@ pub fn execvpeZ_expandArg0(
var it = mem.tokenize(PATH, ":");
var seen_eacces = false;
var err: ExecveError = undefined;
+
+ // In case of expanding arg0 we must put it back if we return with an error.
+ const prev_arg0 = child_argv[0];
+ defer switch (arg0_expand) {
+ .expand => child_argv[0] = prev_arg0,
+ .no_expand => {},
+ };
+
while (it.next()) |search_path| {
if (path_buf.len < search_path.len + file_slice.len + 1) return error.NameTooLong;
mem.copy(u8, &path_buf, search_path);