From ac4f6abf1da04d95d67f3d650da8b78f71052c25 Mon Sep 17 00:00:00 2001 From: "Christoph M. Becker" Date: Tue, 11 Feb 2020 09:42:57 +0100 Subject: [PATCH 1/2] Fix #79254: getenv() w/o arguments not showing changes To be able to see changes done only with `SetEnvironmentVariable()`, we have to use `GetEnvironmentStrings()` instead of `environ`, because the latter sees only changes done with `putenv()`. For best backward compatibility we're using `GetEnvironmentStringsA()`; switching to the wide string version likely makes sense for master, though. --- .../tests/general_functions/bug79254.phpt | 22 +++++++++++++++ main/php_variables.c | 27 +++++++++++++------ 2 files changed, 41 insertions(+), 8 deletions(-) create mode 100644 ext/standard/tests/general_functions/bug79254.phpt diff --git a/ext/standard/tests/general_functions/bug79254.phpt b/ext/standard/tests/general_functions/bug79254.phpt new file mode 100644 index 0000000000000..d2b86aa606c54 --- /dev/null +++ b/ext/standard/tests/general_functions/bug79254.phpt @@ -0,0 +1,22 @@ +--TEST-- +Bug #79254 (getenv() w/o arguments not showing changes) +--FILE-- + +--EXPECT-- +bool(false) +array(1) { + ["PHP_BUG_79254"]=> + string(3) "BAR" +} +string(3) "BAR" diff --git a/main/php_variables.c b/main/php_variables.c index 5ac61a4fa09a1..335e597a5ccfc 100644 --- a/main/php_variables.c +++ b/main/php_variables.c @@ -543,20 +543,28 @@ static zend_always_inline int valid_environment_name(const char *name, const cha void _php_import_environment_variables(zval *array_ptr) { - char **env, *p; + char **env, *ep, *p; +#ifdef PHP_WIN32 + char *envir; +#endif size_t name_len, len; zval val; zend_ulong idx; - for (env = environ; env != NULL && *env != NULL; env++) { - p = strchr(*env, '='); +#ifndef PHP_WIN32 + for (env = environ; env != NULL && (ep = *env) != NULL; env++) { +#else + envir = GetEnvironmentStringsA(); + for (ep = envir; ep != NULL && *ep; ep += strlen(ep) + 1) { +#endif + p = strchr(ep, '='); if (!p - || p == *env - || !valid_environment_name(*env, p)) { + || p == ep + || !valid_environment_name(ep, p)) { /* malformed entry? */ continue; } - name_len = p - *env; + name_len = p - ep; p++; len = strlen(p); if (len == 0) { @@ -566,12 +574,15 @@ void _php_import_environment_variables(zval *array_ptr) } else { ZVAL_NEW_STR(&val, zend_string_init(p, len, 0)); } - if (ZEND_HANDLE_NUMERIC_STR(*env, name_len, idx)) { + if (ZEND_HANDLE_NUMERIC_STR(ep, name_len, idx)) { zend_hash_index_update(Z_ARRVAL_P(array_ptr), idx, &val); } else { - php_register_variable_quick(*env, name_len, &val, Z_ARRVAL_P(array_ptr)); + php_register_variable_quick(ep, name_len, &val, Z_ARRVAL_P(array_ptr)); } } +#ifdef PHP_WIN32 + FreeEnvironmentStringsA(envir); +#endif } zend_bool php_std_auto_global_callback(char *name, uint32_t name_len) From eedeb575bde25522c6d85ad6b07969fac8c115e7 Mon Sep 17 00:00:00 2001 From: "Christoph M. Becker" Date: Tue, 11 Feb 2020 09:43:15 +0100 Subject: [PATCH 2/2] Refactor --- main/php_variables.c | 72 ++++++++++++++++++++++++-------------------- 1 file changed, 40 insertions(+), 32 deletions(-) diff --git a/main/php_variables.c b/main/php_variables.c index 335e597a5ccfc..d804a3860f4e0 100644 --- a/main/php_variables.c +++ b/main/php_variables.c @@ -541,47 +541,55 @@ static zend_always_inline int valid_environment_name(const char *name, const cha return 1; } -void _php_import_environment_variables(zval *array_ptr) +static zend_always_inline void import_environment_variable(HashTable *ht, char *env) { - char **env, *ep, *p; -#ifdef PHP_WIN32 - char *envir; -#endif + char *p; size_t name_len, len; zval val; zend_ulong idx; + p = strchr(env, '='); + if (!p + || p == env + || !valid_environment_name(env, p)) { + /* malformed entry? */ + return; + } + name_len = p - env; + p++; + len = strlen(p); + if (len == 0) { + ZVAL_EMPTY_STRING(&val); + } else if (len == 1) { + ZVAL_INTERNED_STR(&val, ZSTR_CHAR((zend_uchar)*p)); + } else { + ZVAL_NEW_STR(&val, zend_string_init(p, len, 0)); + } + if (ZEND_HANDLE_NUMERIC_STR(env, name_len, idx)) { + zend_hash_index_update(ht, idx, &val); + } else { + php_register_variable_quick(env, name_len, &val, ht); + } +} + +void _php_import_environment_variables(zval *array_ptr) +{ #ifndef PHP_WIN32 - for (env = environ; env != NULL && (ep = *env) != NULL; env++) { + char **env; #else - envir = GetEnvironmentStringsA(); - for (ep = envir; ep != NULL && *ep; ep += strlen(ep) + 1) { + char *environment, *env; #endif - p = strchr(ep, '='); - if (!p - || p == ep - || !valid_environment_name(ep, p)) { - /* malformed entry? */ - continue; - } - name_len = p - ep; - p++; - len = strlen(p); - if (len == 0) { - ZVAL_EMPTY_STRING(&val); - } else if (len == 1) { - ZVAL_INTERNED_STR(&val, ZSTR_CHAR((zend_uchar)*p)); - } else { - ZVAL_NEW_STR(&val, zend_string_init(p, len, 0)); - } - if (ZEND_HANDLE_NUMERIC_STR(ep, name_len, idx)) { - zend_hash_index_update(Z_ARRVAL_P(array_ptr), idx, &val); - } else { - php_register_variable_quick(ep, name_len, &val, Z_ARRVAL_P(array_ptr)); - } + +#ifndef PHP_WIN32 + for (env = environ; env != NULL && *env != NULL; env++) { + import_environment_variable(Z_ARRVAL_P(array_ptr), *env); } -#ifdef PHP_WIN32 - FreeEnvironmentStringsA(envir); +#else + environment = GetEnvironmentStringsA(); + for (env = environment; env != NULL && *env; env += strlen(env) + 1) { + import_environment_variable(Z_ARRVAL_P(array_ptr), env); + } + FreeEnvironmentStringsA(environment); #endif }