From 3b5042430fc4b82d44e0430f9ecc21a9228d1651 Mon Sep 17 00:00:00 2001 From: Ron Yorston Date: Thu, 5 May 2022 15:14:10 +0100 Subject: win32: better fix for empty environment variables It appears the CRT and OS each have a copy of the environment. mingw_putenv() fools the CRT into accepting an empty environment variable by calling _putenv("V=0") then truncating the new value by hand. But _putenv() also updates the OS environment with the fake 'V=0' value. Commit 5b48ca53b (win32: pass NULL to spawnve, not environ) resulted in this fake value being used and hence empty variables getting the value '0'. - Add a call to SetEnvironmentVariable() in mingw_putenv() to update the OS environment. - Restore the use of NULL environment pointers in mingw_spawnvp(). - Add a test. (GitHub issue #250) --- testsuite/env.tests | 67 +++++++++++++++++++++++++++++++++++++++++++++++++++++ win32/env.c | 4 ++++ win32/process.c | 13 ++++------- 3 files changed, 75 insertions(+), 9 deletions(-) create mode 100755 testsuite/env.tests diff --git a/testsuite/env.tests b/testsuite/env.tests new file mode 100755 index 000000000..456808728 --- /dev/null +++ b/testsuite/env.tests @@ -0,0 +1,67 @@ +#!/bin/sh +# Copyright 2022 by Ron Yorston +# Licensed under GPLv2, see file LICENSE in this source tree. + +. ./testing.sh + +# testing "test name" "commands" "expected result" "file input" "stdin" + +# Not so much a test of 'env' as of whether environment variables +# (or the lack thereof) are correctly passed to child processes. +testing "environment variables 1a" \ + "V=set env sh -c 'env | grep ^V='" \ + "V=set +" "" "" + +testing "environment variables 1b" \ + "V= env sh -c 'env | grep ^V='" \ + "V= +" "" "" + +testing "environment variables 1c" \ + "env sh -c 'env | grep ^V='" \ + "" "" "" + +testing "environment variables 2a" \ + "V=set sh -c 'env | grep ^V='" \ + "V=set +" "" "" + +testing "environment variables 2b" \ + "V= sh -c 'env | grep ^V='" \ + "V= +" "" "" + +testing "environment variables 2c" \ + "sh -c 'env | grep ^V='" \ + "" "" "" + +testing "environment variables 3a" \ + "V=set env sh -c 'echo \${V-unset}'" \ + "set +" "" "" + +testing "environment variables 3b" \ + "V= env sh -c 'echo \${V-unset}'" \ + " +" "" "" + +testing "environment variables 3c" \ + "env sh -c 'echo \${V-unset}'" \ + "unset +" "" "" + +testing "environment variables 4a" \ + "V=set sh -c 'echo \${V-unset}'" \ + "set +" "" "" + +testing "environment variables 4b" \ + "V= sh -c 'echo \${V-unset}'" \ + " +" "" "" + +testing "environment variables 4c" \ + "sh -c 'echo \${V-unset}'" \ + "unset +" "" "" diff --git a/win32/env.c b/win32/env.c index 4d4e9c8fd..8e54c4c5e 100644 --- a/win32/env.c +++ b/win32/env.c @@ -100,6 +100,10 @@ int mingw_putenv(const char *env) break; } } + + /* tell the OS environment about the change */ + envstr[s - env] = '\0'; + SetEnvironmentVariable(envstr, ""); free(envstr); } diff --git a/win32/process.c b/win32/process.c index 5978226f0..d4ab07ad8 100644 --- a/win32/process.c +++ b/win32/process.c @@ -345,32 +345,27 @@ mingw_spawnvp(int mode, const char *cmd, char *const *argv) { char *prog; intptr_t ret; -#if !defined(_UCRT) - char *const *envp = environ; -#else - char *const *envp = NULL; -#endif #if ENABLE_FEATURE_PREFER_APPLETS && NUM_APPLETS > 1 if (find_applet_by_name(cmd) >= 0) - return mingw_spawn_applet(mode, argv, envp); + return mingw_spawn_applet(mode, argv, NULL); else #endif if (has_path(cmd)) { char *path = alloc_system_drive(cmd); add_win32_extension(path); - ret = mingw_spawn_interpreter(mode, path, argv, envp, 0); + ret = mingw_spawn_interpreter(mode, path, argv, NULL, 0); free(path); #if ENABLE_FEATURE_PREFER_APPLETS && NUM_APPLETS > 1 if (ret == -1 && unix_path(cmd) && find_applet_by_name(bb_basename(cmd)) >= 0) { - return mingw_spawn_applet(mode, argv, envp); + return mingw_spawn_applet(mode, argv, NULL); } #endif return ret; } else if ((prog=find_first_executable(cmd)) != NULL) { - ret = mingw_spawn_interpreter(mode, prog, argv, envp, 0); + ret = mingw_spawn_interpreter(mode, prog, argv, NULL, 0); free(prog); return ret; } -- cgit v1.2.3-55-g6feb