| ... | ... | @@ -390,15 +390,8 @@ pub const ChildProcess = struct { |
| 390 | 390 | // can fail between fork() and execve(). |
| 391 | 391 | // Therefore, we do all the allocation for the execve() before the fork(). |
| 392 | 392 | // This means we must do the null-termination of argv and env vars here. |
| 393 | | const argv_buf = try arena.alloc(?[*:0]u8, self.argv.len + 1); |
| 394 | | for (self.argv) |arg, i| { |
| 395 | | const arg_buf = try arena.alloc(u8, arg.len + 1); |
| 396 | | @memcpy(arg_buf.ptr, arg.ptr, arg.len); |
| 397 | | arg_buf[arg.len] = 0; |
| 398 | | argv_buf[i] = arg_buf[0..arg.len :0].ptr; |
| 399 | | } |
| 400 | | argv_buf[self.argv.len] = null; |
| 401 | | const argv_ptr = argv_buf[0..self.argv.len :null].ptr; |
| 393 | const argv_buf = try arena.allocSentinel(?[*:0]u8, self.argv.len, null); |
| 394 | for (self.argv) |arg, i| argv_buf[i] = (try arena.dupeZ(u8, arg)).ptr; |
| 402 | 395 | |
| 403 | 396 | const envp = m: { |
| 404 | 397 | if (self.env_map) |env_map| { |
| ... | ... | @@ -465,8 +458,8 @@ pub const ChildProcess = struct { |
| 465 | 458 | } |
| 466 | 459 | |
| 467 | 460 | const err = switch (self.expand_arg0) { |
| 468 | | .expand => os.execvpeZ_expandArg0(.expand, argv_buf.ptr[0].?, argv_ptr, envp), |
| 469 | | .no_expand => os.execvpeZ_expandArg0(.no_expand, argv_buf.ptr[0].?, argv_ptr, envp), |
| 461 | .expand => os.execvpeZ_expandArg0(.expand, argv_buf.ptr[0].?, argv_buf.ptr, envp), |
| 462 | .no_expand => os.execvpeZ_expandArg0(.no_expand, argv_buf.ptr[0].?, argv_buf.ptr, envp), |
| 470 | 463 | }; |
| 471 | 464 | forkChildErrReport(err_pipe[1], err); |
| 472 | 465 | } |
| ... | ... | @@ -914,21 +907,51 @@ pub fn createWindowsEnvBlock(allocator: *mem.Allocator, env_map: *const BufMap) |
| 914 | 907 | |
| 915 | 908 | pub fn createNullDelimitedEnvMap(arena: *mem.Allocator, env_map: *const std.BufMap) ![:null]?[*:0]u8 { |
| 916 | 909 | const envp_count = env_map.count(); |
| 917 | | const envp_buf = try arena.alloc(?[*:0]u8, envp_count + 1); |
| 918 | | mem.set(?[*:0]u8, envp_buf, null); |
| 910 | const envp_buf = try arena.allocSentinel(?[*:0]u8, envp_count, null); |
| 919 | 911 | { |
| 920 | 912 | var it = env_map.iterator(); |
| 921 | 913 | var i: usize = 0; |
| 922 | 914 | while (it.next()) |pair| : (i += 1) { |
| 923 | | const env_buf = try arena.alloc(u8, pair.key.len + pair.value.len + 2); |
| 924 | | @memcpy(env_buf.ptr, pair.key.ptr, pair.key.len); |
| 915 | const env_buf = try arena.allocSentinel(u8, pair.key.len + pair.value.len + 1, 0); |
| 916 | mem.copy(u8, env_buf, pair.key); |
| 925 | 917 | env_buf[pair.key.len] = '='; |
| 926 | | @memcpy(env_buf.ptr + pair.key.len + 1, pair.value.ptr, pair.value.len); |
| 927 | | const len = env_buf.len - 1; |
| 928 | | env_buf[len] = 0; |
| 929 | | envp_buf[i] = env_buf[0..len :0].ptr; |
| 918 | mem.copy(u8, env_buf[pair.key.len + 1 ..], pair.value); |
| 919 | envp_buf[i] = env_buf.ptr; |
| 930 | 920 | } |
| 931 | 921 | assert(i == envp_count); |
| 932 | 922 | } |
| 933 | | return envp_buf[0..envp_count :null]; |
| 923 | return envp_buf; |
| 924 | } |
| 925 | |
| 926 | test "createNullDelimitedEnvMap" { |
| 927 | const testing = std.testing; |
| 928 | const allocator = testing.allocator; |
| 929 | var envmap = BufMap.init(allocator); |
| 930 | defer envmap.deinit(); |
| 931 | |
| 932 | try envmap.set("HOME", "/home/ifreund"); |
| 933 | try envmap.set("WAYLAND_DISPLAY", "wayland-1"); |
| 934 | try envmap.set("DISPLAY", ":1"); |
| 935 | try envmap.set("DEBUGINFOD_URLS", " "); |
| 936 | try envmap.set("XCURSOR_SIZE", "24"); |
| 937 | |
| 938 | var arena = std.heap.ArenaAllocator.init(allocator); |
| 939 | defer arena.deinit(); |
| 940 | const environ = try createNullDelimitedEnvMap(&arena.allocator, &envmap); |
| 941 | |
| 942 | testing.expectEqual(@as(usize, 5), environ.len); |
| 943 | |
| 944 | inline for (.{ |
| 945 | "HOME=/home/ifreund", |
| 946 | "WAYLAND_DISPLAY=wayland-1", |
| 947 | "DISPLAY=:1", |
| 948 | "DEBUGINFOD_URLS= ", |
| 949 | "XCURSOR_SIZE=24", |
| 950 | }) |target| { |
| 951 | for (environ) |variable| { |
| 952 | if (mem.eql(u8, mem.span(variable orelse continue), target)) break; |
| 953 | } else { |
| 954 | testing.expect(false); // Environment variable not found |
| 955 | } |
| 956 | } |
| 934 | 957 | } |