@@ -546,48 +546,39 @@ static void append_win_escaped_arg(smart_str *str, zend_string *arg, bool is_cmd
546
546
smart_str_appendc (str , '"' );
547
547
}
548
548
549
- static inline int stricmp_end (const char * suffix , const char * str ) {
550
- size_t suffix_len = strlen (suffix );
551
- size_t str_len = strlen (str );
549
+ static bool is_executed_by_cmd (const char * prog_name , size_t prog_name_length )
550
+ {
551
+ size_t out_len ;
552
+ WCHAR long_name [MAX_PATH ];
553
+ WCHAR full_name [MAX_PATH ];
554
+ LPWSTR file_part = NULL ;
552
555
553
- if (suffix_len > str_len ) {
554
- return -1 ; /* Suffix is longer than string, cannot match. */
555
- }
556
+ wchar_t * prog_name_wide = php_win32_cp_conv_any_to_w (prog_name , prog_name_length , & out_len );
556
557
557
- /* Compare the end of the string with the suffix, ignoring case. */
558
- return _stricmp (str + (str_len - suffix_len ), suffix );
559
- }
558
+ if (GetLongPathNameW (prog_name_wide , long_name , MAX_PATH ) == 0 ) {
559
+ /* This can fail for example with ERROR_FILE_NOT_FOUND (short path resolution only works for existing files)
560
+ * in which case we'll pass the path verbatim to the FullPath transformation. */
561
+ lstrcpynW (long_name , prog_name_wide , MAX_PATH );
562
+ }
560
563
561
- static bool is_executed_by_cmd (const char * prog_name )
562
- {
563
- /* If program name is cmd.exe, then return true. */
564
- if (_stricmp ("cmd.exe" , prog_name ) == 0 || _stricmp ("cmd" , prog_name ) == 0
565
- || stricmp_end ("\\cmd.exe" , prog_name ) == 0 || stricmp_end ("\\cmd" , prog_name ) == 0 ) {
566
- return true;
567
- }
564
+ free (prog_name_wide );
565
+ prog_name_wide = NULL ;
568
566
569
- /* Find the last occurrence of the directory separator (backslash or forward slash). */
570
- char * last_separator = strrchr (prog_name , '\\' );
571
- char * last_separator_fwd = strrchr (prog_name , '/' );
572
- if (last_separator_fwd && (!last_separator || last_separator < last_separator_fwd )) {
573
- last_separator = last_separator_fwd ;
567
+ if (GetFullPathNameW (long_name , MAX_PATH , full_name , & file_part ) == 0 || file_part == NULL ) {
568
+ return false;
574
569
}
575
570
576
- /* Find the last dot in the filename after the last directory separator. */
577
- char * extension = NULL ;
578
- if (last_separator != NULL ) {
579
- extension = strrchr (last_separator , '.' );
571
+ bool uses_cmd = false;
572
+ if (_wcsicmp (file_part , L"cmd.exe" ) == 0 || _wcsicmp (file_part , L"cmd" ) == 0 ) {
573
+ uses_cmd = true;
580
574
} else {
581
- extension = strrchr (prog_name , '.' );
582
- }
583
-
584
- if (extension == NULL || extension == prog_name ) {
585
- /* No file extension found, it is not batch file. */
586
- return false;
575
+ const WCHAR * extension_dot = wcsrchr (file_part , L'.' );
576
+ if (extension_dot && (_wcsicmp (extension_dot , L".bat" ) == 0 || _wcsicmp (extension_dot , L".cmd" ) == 0 )) {
577
+ uses_cmd = true;
578
+ }
587
579
}
588
580
589
- /* Check if the file extension is ".bat" or ".cmd" which is always executed by cmd.exe. */
590
- return _stricmp (extension , ".bat" ) == 0 || _stricmp (extension , ".cmd" ) == 0 ;
581
+ return uses_cmd ;
591
582
}
592
583
593
584
static zend_string * create_win_command_from_args (HashTable * args )
@@ -606,7 +597,7 @@ static zend_string *create_win_command_from_args(HashTable *args)
606
597
}
607
598
608
599
if (is_prog_name ) {
609
- is_cmd_execution = is_executed_by_cmd (ZSTR_VAL (arg_str ));
600
+ is_cmd_execution = is_executed_by_cmd (ZSTR_VAL (arg_str ), ZSTR_LEN ( arg_str ) );
610
601
} else {
611
602
smart_str_appendc (& str , ' ' );
612
603
}
0 commit comments