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.
This commit is contained in:
Christoph M. Becker 2020-02-11 09:43:15 +01:00
parent f649adedfe
commit 7b464ce6f3
3 changed files with 69 additions and 25 deletions

3
NEWS
View file

@ -13,6 +13,9 @@ PHP NEWS
. Fixed bug #79188 (Memory corruption in preg_replace/preg_replace_callback . Fixed bug #79188 (Memory corruption in preg_replace/preg_replace_callback
and unicode). (Nikita) and unicode). (Nikita)
- Standard:
. Fixed bug #79254 (getenv() w/o arguments not showing changes). (cmb)
20 Feb 2020, PHP 7.3.15 20 Feb 2020, PHP 7.3.15
- Core: - Core:

View file

@ -0,0 +1,22 @@
--TEST--
Bug #79254 (getenv() w/o arguments not showing changes)
--FILE--
<?php
$old = getenv();
var_dump(getenv("PHP_BUG_79254", true));
putenv("PHP_BUG_79254=BAR");
$new = getenv();
var_dump(array_diff($new, $old));
var_dump(getenv("PHP_BUG_79254", true));
?>
--EXPECT--
bool(false)
array(1) {
["PHP_BUG_79254"]=>
string(3) "BAR"
}
string(3) "BAR"

View file

@ -541,37 +541,56 @@ static zend_always_inline int valid_environment_name(const char *name, const cha
return 1; return 1;
} }
void _php_import_environment_variables(zval *array_ptr) static zend_always_inline void import_environment_variable(HashTable *ht, char *env)
{ {
char **env, *p; char *p;
size_t name_len, len; size_t name_len, len;
zval val; zval val;
zend_ulong idx; zend_ulong idx;
for (env = environ; env != NULL && *env != NULL; env++) { p = strchr(env, '=');
p = strchr(*env, '='); if (!p
if (!p || p == env
|| p == *env || !valid_environment_name(env, p)) {
|| !valid_environment_name(*env, p)) { /* malformed entry? */
/* malformed entry? */ return;
continue;
}
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(Z_ARRVAL_P(array_ptr), idx, &val);
} else {
php_register_variable_quick(*env, name_len, &val, Z_ARRVAL_P(array_ptr));
}
} }
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
char **env;
#else
char *environment, *env;
#endif
#ifndef PHP_WIN32
for (env = environ; env != NULL && *env != NULL; env++) {
import_environment_variable(Z_ARRVAL_P(array_ptr), *env);
}
#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
} }
zend_bool php_std_auto_global_callback(char *name, uint32_t name_len) zend_bool php_std_auto_global_callback(char *name, uint32_t name_len)