@@ -592,48 +592,39 @@ static void append_win_escaped_arg(smart_str *str, zend_string *arg, bool is_cmd
592
592
smart_str_appendc (str , '"' );
593
593
}
594
594
595
- static inline int stricmp_end (const char * suffix , const char * str ) {
596
- size_t suffix_len = strlen (suffix );
597
- size_t str_len = strlen (str );
595
+ static bool is_executed_by_cmd (const char * prog_name , size_t prog_name_length )
596
+ {
597
+ size_t out_len ;
598
+ WCHAR long_name [MAX_PATH ];
599
+ WCHAR full_name [MAX_PATH ];
600
+ LPWSTR file_part = NULL ;
598
601
599
- if (suffix_len > str_len ) {
600
- return -1 ; /* Suffix is longer than string, cannot match. */
601
- }
602
+ wchar_t * prog_name_wide = php_win32_cp_conv_any_to_w (prog_name , prog_name_length , & out_len );
602
603
603
- /* Compare the end of the string with the suffix, ignoring case. */
604
- return _stricmp (str + (str_len - suffix_len ), suffix );
605
- }
604
+ if (GetLongPathNameW (prog_name_wide , long_name , MAX_PATH ) == 0 ) {
605
+ /* This can fail for example with ERROR_FILE_NOT_FOUND (short path resolution only works for existing files)
606
+ * in which case we'll pass the path verbatim to the FullPath transformation. */
607
+ lstrcpynW (long_name , prog_name_wide , MAX_PATH );
608
+ }
606
609
607
- static bool is_executed_by_cmd (const char * prog_name )
608
- {
609
- /* If program name is cmd.exe, then return true. */
610
- if (_stricmp ("cmd.exe" , prog_name ) == 0 || _stricmp ("cmd" , prog_name ) == 0
611
- || stricmp_end ("\\cmd.exe" , prog_name ) == 0 || stricmp_end ("\\cmd" , prog_name ) == 0 ) {
612
- return true;
613
- }
610
+ free (prog_name_wide );
611
+ prog_name_wide = NULL ;
614
612
615
- /* Find the last occurrence of the directory separator (backslash or forward slash). */
616
- char * last_separator = strrchr (prog_name , '\\' );
617
- char * last_separator_fwd = strrchr (prog_name , '/' );
618
- if (last_separator_fwd && (!last_separator || last_separator < last_separator_fwd )) {
619
- last_separator = last_separator_fwd ;
613
+ if (GetFullPathNameW (long_name , MAX_PATH , full_name , & file_part ) == 0 || file_part == NULL ) {
614
+ return false;
620
615
}
621
616
622
- /* Find the last dot in the filename after the last directory separator. */
623
- char * extension = NULL ;
624
- if (last_separator != NULL ) {
625
- extension = strrchr (last_separator , '.' );
617
+ bool uses_cmd = false;
618
+ if (_wcsicmp (file_part , L"cmd.exe" ) == 0 || _wcsicmp (file_part , L"cmd" ) == 0 ) {
619
+ uses_cmd = true;
626
620
} else {
627
- extension = strrchr (prog_name , '.' );
628
- }
629
-
630
- if (extension == NULL || extension == prog_name ) {
631
- /* No file extension found, it is not batch file. */
632
- return false;
621
+ const WCHAR * extension_dot = wcsrchr (file_part , L'.' );
622
+ if (extension_dot && (_wcsicmp (extension_dot , L".bat" ) == 0 || _wcsicmp (extension_dot , L".cmd" ) == 0 )) {
623
+ uses_cmd = true;
624
+ }
633
625
}
634
626
635
- /* Check if the file extension is ".bat" or ".cmd" which is always executed by cmd.exe. */
636
- return _stricmp (extension , ".bat" ) == 0 || _stricmp (extension , ".cmd" ) == 0 ;
627
+ return uses_cmd ;
637
628
}
638
629
639
630
static zend_string * create_win_command_from_args (HashTable * args )
@@ -652,7 +643,7 @@ static zend_string *create_win_command_from_args(HashTable *args)
652
643
}
653
644
654
645
if (is_prog_name ) {
655
- is_cmd_execution = is_executed_by_cmd (ZSTR_VAL (arg_str ));
646
+ is_cmd_execution = is_executed_by_cmd (ZSTR_VAL (arg_str ), ZSTR_LEN ( arg_str ) );
656
647
} else {
657
648
smart_str_appendc (& str , ' ' );
658
649
}
0 commit comments