]> granicus.if.org Git - php/commitdiff
Fix #79254: getenv() w/o arguments not showing changes
authorChristoph M. Becker <cmbecker69@gmx.de>
Tue, 11 Feb 2020 08:43:15 +0000 (09:43 +0100)
committerChristoph M. Becker <cmbecker69@gmx.de>
Tue, 11 Feb 2020 10:47:29 +0000 (11:47 +0100)
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.

NEWS
ext/standard/tests/general_functions/bug79254.phpt [new file with mode: 0644]
main/php_variables.c

diff --git a/NEWS b/NEWS
index 398f685bf356b28975c2f998f31e49e4475f318e..af20e3db3d8840639ad695927d00855dc281328d 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -13,6 +13,9 @@ PHP                                                                        NEWS
   . Fixed bug #79188 (Memory corruption in preg_replace/preg_replace_callback
     and unicode). (Nikita)
 
+- Standard:
+  . Fixed bug #79254 (getenv() w/o arguments not showing changes). (cmb)
+
 20 Feb 2020, PHP 7.3.15
 
 - Core:
diff --git a/ext/standard/tests/general_functions/bug79254.phpt b/ext/standard/tests/general_functions/bug79254.phpt
new file mode 100644 (file)
index 0000000..d2b86aa
--- /dev/null
@@ -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"
index 5ac61a4fa09a1291662a1cb7baf80eb956751c3d..d804a3860f4e078d736280addc749ed61a59fc01 100644 (file)
@@ -541,37 +541,56 @@ 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, *p;
+       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
+       char **env;
+#else
+       char *environment, *env;
+#endif
+
+#ifndef PHP_WIN32
        for (env = environ; env != NULL && *env != NULL; env++) {
-               p = strchr(*env, '=');
-               if (!p
-                || p == *env
-                || !valid_environment_name(*env, p)) {
-                       /* malformed entry? */
-                       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));
-               }
+               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)