fix(env.c): drop envmap, free os_getenv() result #32683

Problem:
vim.uv.os_setenv gets "stuck" per-key. #32550
Caused by the internal `envmap` cache. #7920

    :echo $FOO  <-- prints nothing
    :lua vim.uv.os_setenv("FOO", "bar")
    :echo $FOO  <-- prints bar (as expected)
    :lua vim.uv.os_setenv("FOO", "fizz")
    :echo $FOO  <-- prints bar, still (not expected. Should be "fizz")
    :lua vim.uv.os_unsetenv("FOO")
    :echo $FOO  <-- prints bar, still (not expected. Should be nothing)
    :lua vim.uv.os_setenv("FOO", "buzz")
    :echo $FOO  <-- prints bar, still (not expected. Should be "buzz")

Solution:
- Remove the `envmap` cache.
  - Callers to `os_getenv` must free the result.
- Update all call-sites.
- Introduce `os_getenv_noalloc`.
- Extend `os_env_exists()` the `nonempty` parameter.
This commit is contained in:
Judit Novak
2025-04-16 12:36:07 +02:00
committed by GitHub
parent 7432781e71
commit fd973c0a4e
26 changed files with 281 additions and 146 deletions

View File

@@ -1556,7 +1556,7 @@ static void f_exists(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
const char *p = tv_get_string(&argvars[0]);
if (*p == '$') { // Environment variable.
// First try "normal" environment variables (fast).
if (os_env_exists(p + 1)) {
if (os_env_exists(p + 1, false)) {
n = true;
} else {
// Try expanding things like $VIM and ${HOME}.
@@ -3881,9 +3881,9 @@ dict_T *create_environment(const dictitem_T *job_env, const bool clear_env, cons
size_t len = strlen(required_env_vars[i]);
dictitem_T *dv = tv_dict_find(env, required_env_vars[i], (ptrdiff_t)len);
if (!dv) {
const char *env_var = os_getenv(required_env_vars[i]);
char *env_var = os_getenv(required_env_vars[i]);
if (env_var) {
tv_dict_add_str(env, required_env_vars[i], len, env_var);
tv_dict_add_allocated_str(env, required_env_vars[i], len, env_var);
}
}
}