8282#include "Python.h"
8383#include "pycore_initconfig.h" // PyStatus
8484#include "pycore_pathconfig.h" // _PyPathConfig
85+ #include "pycore_fileutils.h" // _Py_add_relfile()
8586#include "osdefs.h" // SEP, ALTSEP
8687#include <wchar.h>
8788
115116 * with a semicolon separated path prior to calling Py_Initialize.
116117 */
117118
118- #ifndef LANDMARK
119- # define LANDMARK L"lib\\os.py"
120- #endif
121-
122119#define INIT_ERR_BUFFER_OVERFLOW () _PyStatus_ERR("buffer overflow")
123120
124121
@@ -216,7 +213,7 @@ exists(const wchar_t *filename)
216213 Assumes 'filename' MAXPATHLEN+1 bytes long -
217214 may extend 'filename' by one character. */
218215static int
219- ismodule (wchar_t * filename , int update_filename )
216+ ismodule (wchar_t * filename )
220217{
221218 size_t n ;
222219
@@ -231,9 +228,8 @@ ismodule(wchar_t *filename, int update_filename)
231228 filename [n ] = L'c' ;
232229 filename [n + 1 ] = L'\0' ;
233230 exist = exists (filename );
234- if (!update_filename ) {
235- filename [n ] = L'\0' ;
236- }
231+ // Drop the 'c' we just added.
232+ filename [n ] = L'\0' ;
237233 return exist ;
238234 }
239235 return 0 ;
@@ -253,7 +249,7 @@ ismodule(wchar_t *filename, int update_filename)
253249static void
254250join (wchar_t * buffer , const wchar_t * stuff )
255251{
256- if (FAILED ( PathCchCombineEx ( buffer , MAXPATHLEN + 1 , buffer , stuff , 0 )) ) {
252+ if (_Py_add_relfile ( buffer , stuff , MAXPATHLEN + 1 ) < 0 ) {
257253 Py_FatalError ("buffer overflow in getpathp.c's join()" );
258254 }
259255}
@@ -273,30 +269,37 @@ canonicalize(wchar_t *buffer, const wchar_t *path)
273269 return _PyStatus_OK ();
274270}
275271
276-
277- /* gotlandmark only called by search_for_prefix, which ensures
278- 'prefix' is null terminated in bounds. join() ensures
279- 'landmark' can not overflow prefix if too long. */
280272static int
281- gotlandmark ( const wchar_t * prefix , const wchar_t * landmark )
273+ is_stdlibdir ( wchar_t * stdlibdir )
282274{
283- wchar_t filename [MAXPATHLEN + 1 ];
284- memset (filename , 0 , sizeof (filename ));
285- wcscpy_s (filename , Py_ARRAY_LENGTH (filename ), prefix );
286- join (filename , landmark );
287- return ismodule (filename , FALSE);
275+ wchar_t * filename = stdlibdir ;
276+ #ifndef LANDMARK
277+ # define LANDMARK L"os.py"
278+ #endif
279+ /* join() ensures 'landmark' can not overflow prefix if too long. */
280+ join (filename , LANDMARK );
281+ return ismodule (filename );
288282}
289283
290-
291284/* assumes argv0_path is MAXPATHLEN+1 bytes long, already \0 term'd.
292285 assumption provided by only caller, calculate_path() */
293286static int
294- search_for_prefix (wchar_t * prefix , const wchar_t * argv0_path , const wchar_t * landmark )
287+ search_for_prefix (wchar_t * prefix , const wchar_t * argv0_path )
295288{
296- /* Search from argv0_path, until landmark is found */
297- wcscpy_s (prefix , MAXPATHLEN + 1 , argv0_path );
289+ /* Search from argv0_path, until LANDMARK is found.
290+ We guarantee 'prefix' is null terminated in bounds. */
291+ wcscpy_s (prefix , MAXPATHLEN + 1 , argv0_path );
292+ wchar_t stdlibdir [MAXPATHLEN + 1 ];
293+ wcscpy_s (stdlibdir , Py_ARRAY_LENGTH (stdlibdir ), prefix );
294+ /* We initialize with the longest possible path, in case it doesn't fit.
295+ This also gives us an initial SEP at stdlibdir[wcslen(prefix)]. */
296+ join (stdlibdir , L"lib" );
298297 do {
299- if (gotlandmark (prefix , landmark )) {
298+ assert (stdlibdir [wcslen (prefix )] == SEP );
299+ /* Due to reduce() and our initial value, this result
300+ is guaranteed to fit. */
301+ wcscpy (& stdlibdir [wcslen (prefix ) + 1 ], L"lib" );
302+ if (is_stdlibdir (stdlibdir )) {
300303 return 1 ;
301304 }
302305 reduce (prefix );
@@ -758,7 +761,7 @@ calculate_home_prefix(PyCalculatePath *calculate,
758761 reduce (prefix );
759762 calculate -> home = prefix ;
760763 }
761- else if (search_for_prefix (prefix , argv0_path , LANDMARK )) {
764+ else if (search_for_prefix (prefix , argv0_path )) {
762765 calculate -> home = prefix ;
763766 }
764767 else {
@@ -936,7 +939,7 @@ calculate_module_search_path(PyCalculatePath *calculate,
936939 lookBuf [nchars ] = L'\0' ;
937940 /* Up one level to the parent */
938941 reduce (lookBuf );
939- if (search_for_prefix (prefix , lookBuf , LANDMARK )) {
942+ if (search_for_prefix (prefix , lookBuf )) {
940943 break ;
941944 }
942945 /* If we are out of paths to search - give up */
0 commit comments