26
26
#include "php_globals.h"
27
27
#include "SAPI.h"
28
28
#include "main/php_network.h"
29
- #include "zend_smart_string .h"
29
+ #include "zend_smart_str .h"
30
30
31
31
#if HAVE_SYS_WAIT_H
32
32
#include <sys/wait.h>
@@ -485,62 +485,63 @@ static zend_string *get_valid_arg_string(zval *zv, int elem_num) {
485
485
}
486
486
487
487
#ifdef PHP_WIN32
488
- static void append_backslashes (smart_string * str , size_t num_bs )
488
+ static void append_backslashes (smart_str * str , size_t num_bs )
489
489
{
490
490
for (size_t i = 0 ; i < num_bs ; i ++ ) {
491
- smart_string_appendc (str , '\\' );
491
+ smart_str_appendc (str , '\\' );
492
492
}
493
493
}
494
494
495
495
/* See https://docs.microsoft.com/en-us/cpp/cpp/parsing-cpp-command-line-arguments */
496
- static void append_win_escaped_arg (smart_string * str , char * arg )
496
+ static void append_win_escaped_arg (smart_str * str , zend_string * arg )
497
497
{
498
- char c ;
499
498
size_t num_bs = 0 ;
500
- smart_string_appendc (str , '"' );
501
- while ((c = * arg )) {
499
+
500
+ smart_str_appendc (str , '"' );
501
+ for (size_t i = 0 ; i < ZSTR_LEN (arg ); ++ i ) {
502
+ char c = ZSTR_VAL (arg )[i ];
502
503
if (c == '\\' ) {
503
504
num_bs ++ ;
504
- } else {
505
- if (c == '"' ) {
506
- /* Backslashes before " need to be doubled. */
507
- num_bs = num_bs * 2 + 1 ;
508
- }
509
- append_backslashes (str , num_bs );
510
- smart_string_appendc (str , c );
511
- num_bs = 0 ;
505
+ continue ;
506
+ }
507
+
508
+ if (c == '"' ) {
509
+ /* Backslashes before " need to be doubled. */
510
+ num_bs = num_bs * 2 + 1 ;
512
511
}
513
- arg ++ ;
512
+ append_backslashes (str , num_bs );
513
+ smart_str_appendc (str , c );
514
+ num_bs = 0 ;
514
515
}
515
516
append_backslashes (str , num_bs * 2 );
516
- smart_string_appendc (str , '"' );
517
+ smart_str_appendc (str , '"' );
517
518
}
518
519
519
- static char * create_win_command_from_args (HashTable * args )
520
+ static zend_string * create_win_command_from_args (HashTable * args )
520
521
{
521
- smart_string str = {0 };
522
+ smart_str str = {0 };
522
523
zval * arg_zv ;
523
524
bool is_prog_name = 1 ;
524
525
int elem_num = 0 ;
525
526
526
527
ZEND_HASH_FOREACH_VAL (args , arg_zv ) {
527
528
zend_string * arg_str = get_valid_arg_string (arg_zv , ++ elem_num );
528
529
if (!arg_str ) {
529
- smart_string_free (& str );
530
+ smart_str_free (& str );
530
531
return NULL ;
531
532
}
532
533
533
534
if (!is_prog_name ) {
534
- smart_string_appendc (& str , ' ' );
535
+ smart_str_appendc (& str , ' ' );
535
536
}
536
537
537
- append_win_escaped_arg (& str , ZSTR_VAL ( arg_str ) );
538
+ append_win_escaped_arg (& str , arg_str );
538
539
539
540
is_prog_name = 0 ;
540
541
zend_string_release (arg_str );
541
542
} ZEND_HASH_FOREACH_END ();
542
- smart_string_0 (& str );
543
- return str .c ;
543
+ smart_str_0 (& str );
544
+ return str .s ;
544
545
}
545
546
546
547
/* Get a boolean option from the `other_options` array which can be passed to `proc_open`.
@@ -611,10 +612,10 @@ static int convert_command_to_use_shell(wchar_t **cmdw, size_t cmdw_len)
611
612
#endif
612
613
613
614
/* Convert command parameter array passed as first argument to `proc_open` into command string */
614
- static char * get_command_from_array (HashTable * array , char * * * argv , int num_elems )
615
+ static zend_string * get_command_from_array (HashTable * array , char * * * argv , int num_elems )
615
616
{
616
617
zval * arg_zv ;
617
- char * command = NULL ;
618
+ zend_string * command = NULL ;
618
619
int i = 0 ;
619
620
620
621
* argv = safe_emalloc (sizeof (char * ), num_elems + 1 , 0 );
@@ -625,13 +626,13 @@ static char* get_command_from_array(HashTable *array, char ***argv, int num_elem
625
626
/* Terminate with NULL so exit_fail code knows how many entries to free */
626
627
(* argv )[i ] = NULL ;
627
628
if (command != NULL ) {
628
- efree (command );
629
+ zend_string_release_ex (command , false );
629
630
}
630
631
return NULL ;
631
632
}
632
633
633
634
if (i == 0 ) {
634
- command = estrdup ( ZSTR_VAL ( arg_str ) );
635
+ command = zend_string_copy ( arg_str );
635
636
}
636
637
637
638
(* argv )[i ++ ] = estrdup (ZSTR_VAL (arg_str ));
@@ -1005,7 +1006,6 @@ PHP_FUNCTION(proc_open)
1005
1006
size_t cwd_len = 0 ; /* Optional argument */
1006
1007
zval * environment = NULL , * other_options = NULL ; /* Optional arguments */
1007
1008
1008
- char * command = NULL ;
1009
1009
php_process_env env ;
1010
1010
int ndesc = 0 ;
1011
1011
int i ;
@@ -1057,18 +1057,16 @@ PHP_FUNCTION(proc_open)
1057
1057
#ifdef PHP_WIN32
1058
1058
/* Automatically bypass shell if command is given as an array */
1059
1059
bypass_shell = 1 ;
1060
- command = create_win_command_from_args (command_ht );
1061
- if (!command ) {
1060
+ command_str = create_win_command_from_args (command_ht );
1061
+ if (!command_str ) {
1062
1062
RETURN_FALSE ;
1063
1063
}
1064
1064
#else
1065
- command = get_command_from_array (command_ht , & argv , num_elems );
1066
- if (command == NULL ) {
1065
+ command_str = get_command_from_array (command_ht , & argv , num_elems );
1066
+ if (! command_str ) {
1067
1067
goto exit_fail ;
1068
1068
}
1069
1069
#endif
1070
- } else {
1071
- command = estrdup (ZSTR_VAL (command_str ));
1072
1070
}
1073
1071
1074
1072
#ifdef PHP_WIN32
@@ -1155,7 +1153,7 @@ PHP_FUNCTION(proc_open)
1155
1153
}
1156
1154
}
1157
1155
1158
- cmdw = php_win32_cp_conv_any_to_w (command , strlen ( command ), & cmdw_len );
1156
+ cmdw = php_win32_cp_conv_any_to_w (ZSTR_VAL ( command_str ), ZSTR_LEN ( command_str ), & cmdw_len );
1159
1157
if (!cmdw ) {
1160
1158
php_error_docref (NULL , E_WARNING , "Command conversion failed" );
1161
1159
goto exit_fail ;
@@ -1206,12 +1204,12 @@ PHP_FUNCTION(proc_open)
1206
1204
if (env .envarray ) {
1207
1205
environ = env .envarray ;
1208
1206
}
1209
- execvp (command , argv );
1207
+ execvp (ZSTR_VAL ( command_str ) , argv );
1210
1208
} else {
1211
1209
if (env .envarray ) {
1212
- execle ("/bin/sh" , "sh" , "-c" , command , NULL , env .envarray );
1210
+ execle ("/bin/sh" , "sh" , "-c" , ZSTR_VAL ( command_str ) , NULL , env .envarray );
1213
1211
} else {
1214
- execl ("/bin/sh" , "sh" , "-c" , command , NULL );
1212
+ execl ("/bin/sh" , "sh" , "-c" , ZSTR_VAL ( command_str ) , NULL );
1215
1213
}
1216
1214
}
1217
1215
@@ -1237,7 +1235,7 @@ PHP_FUNCTION(proc_open)
1237
1235
}
1238
1236
1239
1237
proc = (php_process_handle * ) emalloc (sizeof (php_process_handle ));
1240
- proc -> command = command ;
1238
+ proc -> command = estrdup ( ZSTR_VAL ( command_str )) ;
1241
1239
proc -> pipes = emalloc (sizeof (zend_resource * ) * ndesc );
1242
1240
proc -> npipes = ndesc ;
1243
1241
proc -> child = child ;
@@ -1308,12 +1306,14 @@ PHP_FUNCTION(proc_open)
1308
1306
} else {
1309
1307
exit_fail :
1310
1308
_php_free_envp (env );
1311
- if (command ) {
1312
- efree (command );
1313
- }
1314
1309
RETVAL_FALSE ;
1315
1310
}
1316
1311
1312
+ /* the command_str needs to be freed if it was created by parsing an array */
1313
+ if (command_ht && command_str ) {
1314
+ zend_string_release_ex (command_str , false);
1315
+ }
1316
+
1317
1317
#ifdef PHP_WIN32
1318
1318
free (cwdw );
1319
1319
free (cmdw );
0 commit comments