@@ -266,6 +266,41 @@ join(wchar_t *buffer, const wchar_t *stuff)
266266 }
267267}
268268
269+ static int _PathCchCanonicalizeEx_Initialized = 0 ;
270+ typedef HRESULT (__stdcall * PPathCchCanonicalizeEx ) (PWSTR pszPathOut , size_t cchPathOut ,
271+ PCWSTR pszPathIn , unsigned long dwFlags );
272+ static PPathCchCanonicalizeEx _PathCchCanonicalizeEx ;
273+
274+ static _PyInitError canonicalize (wchar_t * buffer , const wchar_t * path )
275+ {
276+ if (buffer == NULL ) {
277+ return _Py_INIT_NO_MEMORY ();
278+ }
279+
280+ if (_PathCchCanonicalizeEx_Initialized == 0 ) {
281+ HMODULE pathapi = LoadLibraryW (L"api-ms-win-core-path-l1-1-0.dll" );
282+ if (pathapi ) {
283+ _PathCchCanonicalizeEx = (PPathCchCanonicalizeEx )GetProcAddress (pathapi , "PathCchCanonicalizeEx" );
284+ }
285+ else {
286+ _PathCchCanonicalizeEx = NULL ;
287+ }
288+ _PathCchCanonicalizeEx_Initialized = 1 ;
289+ }
290+
291+ if (_PathCchCanonicalizeEx ) {
292+ if (FAILED (_PathCchCanonicalizeEx (buffer , MAXPATHLEN + 1 , path , 0 ))) {
293+ return _Py_INIT_ERR ("buffer overflow in getpathp.c's canonicalize()" );
294+ }
295+ }
296+ else {
297+ if (!PathCanonicalizeW (buffer , path )) {
298+ return _Py_INIT_ERR ("buffer overflow in getpathp.c's canonicalize()" );
299+ }
300+ }
301+ return _Py_INIT_OK ();
302+ }
303+
269304
270305/* gotlandmark only called by search_for_prefix, which ensures
271306 'prefix' is null terminated in bounds. join() ensures
@@ -504,63 +539,16 @@ get_program_full_path(const _PyCoreConfig *core_config,
504539 wchar_t program_full_path [MAXPATHLEN + 1 ];
505540 memset (program_full_path , 0 , sizeof (program_full_path ));
506541
507- if (GetModuleFileNameW (NULL , program_full_path , MAXPATHLEN )) {
508- goto done ;
509- }
510-
511- /* If there is no slash in the argv0 path, then we have to
512- * assume python is on the user's $PATH, since there's no
513- * other way to find a directory to start the search from. If
514- * $PATH isn't exported, you lose.
515- */
516- #ifdef ALTSEP
517- if (wcschr (core_config -> program_name , SEP ) ||
518- wcschr (core_config -> program_name , ALTSEP ))
519- #else
520- if (wcschr (core_config -> program_name , SEP ))
521- #endif
522- {
523- wcsncpy (program_full_path , core_config -> program_name , MAXPATHLEN );
542+ if (!GetModuleFileNameW (NULL , program_full_path , MAXPATHLEN )) {
543+ /* GetModuleFileName should never fail when passed NULL */
544+ return _Py_INIT_ERR ("Cannot determine program path" );
524545 }
525- else if (calculate -> path_env ) {
526- const wchar_t * path = calculate -> path_env ;
527- while (1 ) {
528- const wchar_t * delim = wcschr (path , DELIM );
529-
530- if (delim ) {
531- size_t len = delim - path ;
532- /* ensure we can't overwrite buffer */
533- len = min (MAXPATHLEN ,len );
534- wcsncpy (program_full_path , path , len );
535- program_full_path [len ] = '\0' ;
536- }
537- else {
538- wcsncpy (program_full_path , path , MAXPATHLEN );
539- }
540-
541- /* join() is safe for MAXPATHLEN+1 size buffer */
542- join (program_full_path , core_config -> program_name );
543- if (exists (program_full_path )) {
544- break ;
545- }
546546
547- if (!delim ) {
548- program_full_path [0 ] = '\0' ;
549- break ;
550- }
551- path = delim + 1 ;
552- }
553- }
554- else {
555- program_full_path [0 ] = '\0' ;
556- }
547+ config -> program_full_path = PyMem_RawMalloc (
548+ sizeof (wchar_t ) * (MAXPATHLEN + 1 ));
557549
558- done :
559- config -> program_full_path = _PyMem_RawWcsdup (program_full_path );
560- if (config -> program_full_path == NULL ) {
561- return _Py_INIT_NO_MEMORY ();
562- }
563- return _Py_INIT_OK ();
550+ return canonicalize (config -> program_full_path ,
551+ program_full_path );
564552}
565553
566554
0 commit comments