]> granicus.if.org Git - php/commitdiff
proc_open(): separate environment values that aren't strings
authorTjerk Meesters <datibbaw@php.net>
Thu, 10 Oct 2013 12:21:14 +0000 (20:21 +0800)
committerTjerk Meesters <datibbaw@php.net>
Sun, 2 Mar 2014 21:49:52 +0000 (05:49 +0800)
Added a test case

ext/standard/proc_open.c
ext/standard/tests/streams/bug60602.phpt [new file with mode: 0644]

index b22877c7ab50419255428574c98f548d22fd3d78..7ffba0e24d61871095a190d84c32e6de24d4b364 100644 (file)
@@ -112,8 +112,17 @@ static php_process_env_t _php_array_to_envp(zval *environment, int is_persistent
                        zend_hash_get_current_data_ex(target_hash, (void **) &element, &pos) == SUCCESS;
                        zend_hash_move_forward_ex(target_hash, &pos)) {
 
-               convert_to_string_ex(element);
-               el_len = Z_STRLEN_PP(element);
+               if (Z_TYPE_PP(element) != IS_STRING) {
+                       zval tmp;
+
+                       MAKE_COPY_ZVAL(element, &tmp);
+                       convert_to_string(&tmp);
+                       el_len = Z_STRLEN(tmp);
+
+                       zval_dtor(&tmp);
+               } else {
+                       el_len = Z_STRLEN_PP(element);
+               }
                if (el_len == 0) {
                        continue;
                }
@@ -125,7 +134,7 @@ static php_process_env_t _php_array_to_envp(zval *environment, int is_persistent
                                if (string_length == 0) {
                                        continue;
                                }
-                               sizeenv += string_length+1;
+                               sizeenv += string_length;
                                break;
                }
        }
@@ -138,19 +147,26 @@ static php_process_env_t _php_array_to_envp(zval *environment, int is_persistent
        for (zend_hash_internal_pointer_reset_ex(target_hash, &pos);
                        zend_hash_get_current_data_ex(target_hash, (void **) &element, &pos) == SUCCESS;
                        zend_hash_move_forward_ex(target_hash, &pos)) {
+               zval tmp;
 
-               convert_to_string_ex(element);
-               el_len = Z_STRLEN_PP(element);
+               if (Z_TYPE_PP(element) != IS_STRING) {
+                       MAKE_COPY_ZVAL(element, &tmp);
+                       convert_to_string(&tmp);
+               } else {
+                       tmp = **element;
+               }
+
+               el_len = Z_STRLEN(tmp);
 
                if (el_len == 0) {
-                       continue;
+                       goto next_element;
                }
 
-               data = Z_STRVAL_PP(element);
+               data = Z_STRVAL(tmp);
                switch (zend_hash_get_current_key_ex(target_hash, &string_key, &string_length, &num_key, 0, &pos)) {
                        case HASH_KEY_IS_STRING:
                                if (string_length == 0) {
-                                       continue;
+                                       goto next_element;
                                }
 
                                l = string_length + el_len + 1;
@@ -175,6 +191,11 @@ static php_process_env_t _php_array_to_envp(zval *environment, int is_persistent
                        case HASH_KEY_NON_EXISTANT:
                                break;
                }
+
+next_element:
+               if (Z_TYPE_PP(element) != IS_STRING) {
+                       zval_dtor(&tmp);
+               }
        }
 
        assert((uint)(p - env.envp) <= sizeenv);
diff --git a/ext/standard/tests/streams/bug60602.phpt b/ext/standard/tests/streams/bug60602.phpt
new file mode 100644 (file)
index 0000000..2c08ce8
--- /dev/null
@@ -0,0 +1,57 @@
+--TEST--
+Bug #60602 proc_open() modifies environment if it contains arrays
+--FILE--
+<?php
+
+$descs = array(
+       0 => array('pipe', 'r'), // stdin
+       1 => array('pipe', 'w'), // stdout
+       2 => array('pipe', 'w'), // strerr
+);
+
+$environment = array('test' => array(1, 2, 3));
+
+$cmd = (substr(PHP_OS, 0, 3) == 'WIN') ? 'dir' : 'ls';
+$p = proc_open($cmd, $descs, $pipes, '.', $environment);
+
+if (is_resource($p)) {
+       $data = '';
+
+       while (1) {     
+               $w = $e = NULL;
+               $n = stream_select($pipes, $w, $e, 300);
+
+               if ($n === false) {
+                       echo "no streams \n";
+                       break;
+               } else if ($n === 0) {
+                       echo "process timed out\n";
+                       proc_terminate($p, 9);
+                       break;
+               } else if ($n > 0) {
+                       $line = fread($pipes[1], 8192);
+                       if (strlen($line) == 0) {
+                               /* EOF */
+                               break;
+                       }
+                       $data .= $line;
+               }
+       }
+       var_dump(strlen($data));
+
+       $ret = proc_close($p);
+       var_dump($ret);
+       var_dump(is_array($environment['test']));
+} else {
+       echo "no process\n";
+}
+?>
+==DONE==
+--EXPECTF--
+Notice: Array to string conversion in %s on line %d
+
+Notice: Array to string conversion in %s on line %d
+int(%d)
+int(0)
+bool(true)
+==DONE==