aboutsummaryrefslogtreecommitdiff
path: root/lib/std/process.zig
diff options
context:
space:
mode:
authorRyan Liptak <squeek502@hotmail.com>2025-03-17 17:53:12 -0700
committerRyan Liptak <squeek502@hotmail.com>2025-03-17 17:53:38 -0700
commit423761bb6de68bec9482dbc3b3c21b2b5c74a2b9 (patch)
tree62b4db263493430c1966e16851c020e558c832f5 /lib/std/process.zig
parent2a4e06bcb30f71e83b14026bcbade6aac3aece84 (diff)
downloadzig-423761bb6de68bec9482dbc3b3c21b2b5c74a2b9.tar.gz
zig-423761bb6de68bec9482dbc3b3c21b2b5c74a2b9.zip
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.
Diffstat (limited to 'lib/std/process.zig')
-rw-r--r--lib/std/process.zig17
1 files 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);
}