From 423761bb6de68bec9482dbc3b3c21b2b5c74a2b9 Mon Sep 17 00:00:00 2001 From: Ryan Liptak Date: Mon, 17 Mar 2025 17:53:12 -0700 Subject: [PATCH] createWindowsEnvBlock: Reduce NUL terminator count to only what's required This code previously added 4 NUL code units, but that was likely due to a misinterpretation of this part of the CreateProcess documentation: > A Unicode environment block is terminated by four zero bytes: two for the last string, two more to terminate the block. (four zero *bytes* means *two* zero code units) Additionally, the second zero code unit is only actually needed when the environment is empty due to a quirk of the CreateProcess implementation. In the case of a non-empty environment, there always ends up being two trailing NUL code units since one will come after the last environment variable in the block. --- lib/std/process.zig | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/lib/std/process.zig b/lib/std/process.zig index b734276444..4efb58c3df 100644 --- a/lib/std/process.zig +++ b/lib/std/process.zig @@ -2036,7 +2036,8 @@ test createNullDelimitedEnvMap { pub fn createWindowsEnvBlock(allocator: mem.Allocator, env_map: *const EnvMap) ![]u16 { // count bytes needed const max_chars_needed = x: { - var max_chars_needed: usize = 4; // 4 for the final 4 null bytes + // Only need 2 trailing NUL code units for an empty environment + var max_chars_needed: usize = if (env_map.count() == 0) 2 else 1; var it = env_map.iterator(); while (it.next()) |pair| { // +1 for '=' @@ -2060,12 +2061,14 @@ pub fn createWindowsEnvBlock(allocator: mem.Allocator, env_map: *const EnvMap) ! } result[i] = 0; i += 1; - result[i] = 0; - i += 1; - result[i] = 0; - i += 1; - result[i] = 0; - i += 1; + // An empty environment is a special case that requires a redundant + // NUL terminator. CreateProcess will read the second code unit even + // though theoretically the first should be enough to recognize that the + // environment is empty (see https://nullprogram.com/blog/2023/08/23/) + if (env_map.count() == 0) { + result[i] = 0; + i += 1; + } return try allocator.realloc(result, i); }