Skip to content

Commit 7b464ce

Browse files
committed
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.
1 parent f649ade commit 7b464ce

File tree

3 files changed

+68
-24
lines changed

3 files changed

+68
-24
lines changed

NEWS

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,9 @@ PHP NEWS
1313
. Fixed bug #79188 (Memory corruption in preg_replace/preg_replace_callback
1414
and unicode). (Nikita)
1515

16+
- Standard:
17+
. Fixed bug #79254 (getenv() w/o arguments not showing changes). (cmb)
18+
1619
20 Feb 2020, PHP 7.3.15
1720

1821
- Core:
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
--TEST--
2+
Bug #79254 (getenv() w/o arguments not showing changes)
3+
--FILE--
4+
<?php
5+
6+
$old = getenv();
7+
var_dump(getenv("PHP_BUG_79254", true));
8+
9+
putenv("PHP_BUG_79254=BAR");
10+
11+
$new = getenv();
12+
var_dump(array_diff($new, $old));
13+
var_dump(getenv("PHP_BUG_79254", true));
14+
15+
?>
16+
--EXPECT--
17+
bool(false)
18+
array(1) {
19+
["PHP_BUG_79254"]=>
20+
string(3) "BAR"
21+
}
22+
string(3) "BAR"

main/php_variables.c

Lines changed: 43 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -541,37 +541,56 @@ static zend_always_inline int valid_environment_name(const char *name, const cha
541541
return 1;
542542
}
543543

544-
void _php_import_environment_variables(zval *array_ptr)
544+
static zend_always_inline void import_environment_variable(HashTable *ht, char *env)
545545
{
546-
char **env, *p;
546+
char *p;
547547
size_t name_len, len;
548548
zval val;
549549
zend_ulong idx;
550550

551+
p = strchr(env, '=');
552+
if (!p
553+
|| p == env
554+
|| !valid_environment_name(env, p)) {
555+
/* malformed entry? */
556+
return;
557+
}
558+
name_len = p - env;
559+
p++;
560+
len = strlen(p);
561+
if (len == 0) {
562+
ZVAL_EMPTY_STRING(&val);
563+
} else if (len == 1) {
564+
ZVAL_INTERNED_STR(&val, ZSTR_CHAR((zend_uchar)*p));
565+
} else {
566+
ZVAL_NEW_STR(&val, zend_string_init(p, len, 0));
567+
}
568+
if (ZEND_HANDLE_NUMERIC_STR(env, name_len, idx)) {
569+
zend_hash_index_update(ht, idx, &val);
570+
} else {
571+
php_register_variable_quick(env, name_len, &val, ht);
572+
}
573+
}
574+
575+
void _php_import_environment_variables(zval *array_ptr)
576+
{
577+
#ifndef PHP_WIN32
578+
char **env;
579+
#else
580+
char *environment, *env;
581+
#endif
582+
583+
#ifndef PHP_WIN32
551584
for (env = environ; env != NULL && *env != NULL; env++) {
552-
p = strchr(*env, '=');
553-
if (!p
554-
|| p == *env
555-
|| !valid_environment_name(*env, p)) {
556-
/* malformed entry? */
557-
continue;
558-
}
559-
name_len = p - *env;
560-
p++;
561-
len = strlen(p);
562-
if (len == 0) {
563-
ZVAL_EMPTY_STRING(&val);
564-
} else if (len == 1) {
565-
ZVAL_INTERNED_STR(&val, ZSTR_CHAR((zend_uchar)*p));
566-
} else {
567-
ZVAL_NEW_STR(&val, zend_string_init(p, len, 0));
568-
}
569-
if (ZEND_HANDLE_NUMERIC_STR(*env, name_len, idx)) {
570-
zend_hash_index_update(Z_ARRVAL_P(array_ptr), idx, &val);
571-
} else {
572-
php_register_variable_quick(*env, name_len, &val, Z_ARRVAL_P(array_ptr));
573-
}
585+
import_environment_variable(Z_ARRVAL_P(array_ptr), *env);
574586
}
587+
#else
588+
environment = GetEnvironmentStringsA();
589+
for (env = environment; env != NULL && *env; env += strlen(env) + 1) {
590+
import_environment_variable(Z_ARRVAL_P(array_ptr), env);
591+
}
592+
FreeEnvironmentStringsA(environment);
593+
#endif
575594
}
576595

577596
zend_bool php_std_auto_global_callback(char *name, uint32_t name_len)

0 commit comments

Comments
 (0)