@@ -698,22 +698,77 @@ static void init_process_info(PROCESS_INFORMATION *pi)
698698 memset (& pi , 0 , sizeof (pi ));
699699}
700700
701+ /* on success, returns length of *comspec, which then needs to be efree'd by caller */
702+ static size_t find_comspec_nt (wchar_t * * comspec )
703+ {
704+ zend_string * path = NULL ;
705+ wchar_t * pathw = NULL ;
706+ wchar_t * bufp = NULL ;
707+ DWORD buflen = MAX_PATH , len = 0 ;
708+
709+ path = php_getenv ("PATH" , 4 );
710+ if (path == NULL ) {
711+ goto out ;
712+ }
713+ pathw = php_win32_cp_any_to_w (ZSTR_VAL (path ));
714+ if (pathw == NULL ) {
715+ goto out ;
716+ }
717+ bufp = emalloc (buflen * sizeof (wchar_t ));
718+ do {
719+ /* the first call to SearchPathW() fails if the buffer is too small,
720+ * what is unlikely but possible; to avoid an explicit second call to
721+ * SeachPathW() and the error handling, we're looping */
722+ len = SearchPathW (pathw , L"cmd.exe" , NULL , buflen , bufp , NULL );
723+ if (len == 0 ) {
724+ goto out ;
725+ }
726+ if (len < buflen ) {
727+ break ;
728+ }
729+ buflen = len ;
730+ bufp = erealloc (bufp , buflen * sizeof (wchar_t ));
731+ } while (1 );
732+ * comspec = bufp ;
733+
734+ out :
735+ if (path != NULL ) {
736+ zend_string_release (path );
737+ }
738+ if (pathw != NULL ) {
739+ free (pathw );
740+ }
741+ if (bufp != NULL && bufp != * comspec ) {
742+ efree (bufp );
743+ }
744+ return len ;
745+ }
746+
701747static zend_result convert_command_to_use_shell (wchar_t * * cmdw , size_t cmdw_len )
702748{
703- size_t len = sizeof (COMSPEC_NT ) + sizeof (" /s /c " ) + cmdw_len + 3 ;
749+ wchar_t * comspec ;
750+ size_t len = find_comspec_nt (& comspec );
751+ if (len == 0 ) {
752+ php_error_docref (NULL , E_WARNING , "Command conversion failed" );
753+ return FAILURE ;
754+ }
755+ len += sizeof (" /s /c " ) + cmdw_len + 3 ;
704756 wchar_t * cmdw_shell = (wchar_t * )malloc (len * sizeof (wchar_t ));
705757
706758 if (cmdw_shell == NULL ) {
759+ efree (comspec );
707760 php_error_docref (NULL , E_WARNING , "Command conversion failed" );
708761 return FAILURE ;
709762 }
710763
711- if (_snwprintf (cmdw_shell , len , L"%hs /s /c \"%s\"" , COMSPEC_NT , * cmdw ) == -1 ) {
764+ if (_snwprintf (cmdw_shell , len , L"%s /s /c \"%s\"" , comspec , * cmdw ) == -1 ) {
765+ efree (comspec );
712766 free (cmdw_shell );
713767 php_error_docref (NULL , E_WARNING , "Command conversion failed" );
714768 return FAILURE ;
715769 }
716770
771+ efree (comspec );
717772 free (* cmdw );
718773 * cmdw = cmdw_shell ;
719774
0 commit comments