Skip to content

Commit f0c8579

Browse files
authored
bpo-38353: Rework ismodule() in getpath.c (GH-16574)
* ismodule() no longer modify the input string. * copy_absolute(), joinpath(): rename parameters and local variables.
1 parent 03a8a56 commit f0c8579

File tree

1 file changed

+80
-64
lines changed

1 file changed

+80
-64
lines changed

Modules/getpath.c

Lines changed: 80 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -183,25 +183,6 @@ isfile(const wchar_t *filename)
183183
}
184184

185185

186-
/* Is module -- check for .pyc too */
187-
static int
188-
ismodule(wchar_t *filename, size_t filename_len)
189-
{
190-
if (isfile(filename)) {
191-
return 1;
192-
}
193-
194-
/* Check for the compiled version of prefix. */
195-
if (wcslen(filename) + 2 <= filename_len) {
196-
wcscat(filename, L"c");
197-
if (isfile(filename)) {
198-
return 1;
199-
}
200-
}
201-
return 0;
202-
}
203-
204-
205186
/* Is executable file */
206187
static int
207188
isxfile(const wchar_t *filename)
@@ -222,7 +203,7 @@ isxfile(const wchar_t *filename)
222203

223204
/* Is directory */
224205
static int
225-
isdir(wchar_t *filename)
206+
isdir(const wchar_t *filename)
226207
{
227208
struct stat buf;
228209
if (_Py_wstat(filename, &buf) != 0) {
@@ -238,29 +219,29 @@ isdir(wchar_t *filename)
238219
/* Add a path component, by appending stuff to buffer.
239220
buflen: 'buffer' length in characters including trailing NUL. */
240221
static PyStatus
241-
joinpath(wchar_t *buffer, const wchar_t *stuff, size_t buflen)
222+
joinpath(wchar_t *path, const wchar_t *path2, size_t path_len)
242223
{
243-
size_t n, k;
244-
if (!_Py_isabs(stuff)) {
245-
n = wcslen(buffer);
246-
if (n >= buflen) {
224+
size_t n;
225+
if (!_Py_isabs(path2)) {
226+
n = wcslen(path);
227+
if (n >= path_len) {
247228
return PATHLEN_ERR();
248229
}
249230

250-
if (n > 0 && buffer[n-1] != SEP) {
251-
buffer[n++] = SEP;
231+
if (n > 0 && path[n-1] != SEP) {
232+
path[n++] = SEP;
252233
}
253234
}
254235
else {
255236
n = 0;
256237
}
257238

258-
k = wcslen(stuff);
259-
if (n + k >= buflen) {
239+
size_t k = wcslen(path2);
240+
if (n + k >= path_len) {
260241
return PATHLEN_ERR();
261242
}
262-
wcsncpy(buffer+n, stuff, k);
263-
buffer[n+k] = '\0';
243+
wcsncpy(path + n, path2, k);
244+
path[n + k] = '\0';
264245

265246
return _PyStatus_OK();
266247
}
@@ -280,27 +261,27 @@ safe_wcscpy(wchar_t *dst, const wchar_t *src, size_t n)
280261

281262

282263
/* copy_absolute requires that path be allocated at least
283-
'pathlen' characters (including trailing NUL). */
264+
'abs_path_len' characters (including trailing NUL). */
284265
static PyStatus
285-
copy_absolute(wchar_t *path, const wchar_t *p, size_t pathlen)
266+
copy_absolute(wchar_t *abs_path, const wchar_t *path, size_t abs_path_len)
286267
{
287-
if (_Py_isabs(p)) {
288-
if (safe_wcscpy(path, p, pathlen) < 0) {
268+
if (_Py_isabs(path)) {
269+
if (safe_wcscpy(abs_path, path, abs_path_len) < 0) {
289270
return PATHLEN_ERR();
290271
}
291272
}
292273
else {
293-
if (!_Py_wgetcwd(path, pathlen)) {
274+
if (!_Py_wgetcwd(abs_path, abs_path_len)) {
294275
/* unable to get the current directory */
295-
if (safe_wcscpy(path, p, pathlen) < 0) {
276+
if (safe_wcscpy(abs_path, path, abs_path_len) < 0) {
296277
return PATHLEN_ERR();
297278
}
298279
return _PyStatus_OK();
299280
}
300-
if (p[0] == '.' && p[1] == SEP) {
301-
p += 2;
281+
if (path[0] == '.' && path[1] == SEP) {
282+
path += 2;
302283
}
303-
PyStatus status = joinpath(path, p, pathlen);
284+
PyStatus status = joinpath(abs_path, path, abs_path_len);
304285
if (_PyStatus_EXCEPTION(status)) {
305286
return status;
306287
}
@@ -330,33 +311,67 @@ absolutize(wchar_t *path, size_t path_len)
330311
}
331312

332313

314+
/* Is module -- check for .pyc too */
315+
static PyStatus
316+
ismodule(const wchar_t *path, int *result)
317+
{
318+
wchar_t filename[MAXPATHLEN+1];
319+
size_t filename_len = Py_ARRAY_LENGTH(filename);
320+
321+
if (safe_wcscpy(filename, path, filename_len) < 0) {
322+
return PATHLEN_ERR();
323+
}
324+
325+
PyStatus status = joinpath(filename, LANDMARK, filename_len);
326+
if (_PyStatus_EXCEPTION(status)) {
327+
return status;
328+
}
329+
330+
if (isfile(filename)) {
331+
*result = 1;
332+
return _PyStatus_OK();
333+
}
334+
335+
/* Check for the compiled version of prefix. */
336+
if (wcslen(filename) + 2 <= filename_len) {
337+
wcscat(filename, L"c");
338+
if (isfile(filename)) {
339+
*result = 1;
340+
return _PyStatus_OK();
341+
}
342+
}
343+
344+
*result = 0;
345+
return _PyStatus_OK();
346+
}
347+
348+
333349
#if defined(__CYGWIN__) || defined(__MINGW32__)
334350
#ifndef EXE_SUFFIX
335351
#define EXE_SUFFIX L".exe"
336352
#endif
337353

338354
/* pathlen: 'path' length in characters including trailing NUL */
339355
static PyStatus
340-
add_exe_suffix(wchar_t *progpath, size_t progpathlen)
356+
add_exe_suffix(wchar_t *path, size_t pathlen)
341357
{
342358
/* Check for already have an executable suffix */
343-
size_t n = wcslen(progpath);
359+
size_t n = wcslen(path);
344360
size_t s = wcslen(EXE_SUFFIX);
345-
if (wcsncasecmp(EXE_SUFFIX, progpath + n - s, s) == 0) {
361+
if (wcsncasecmp(EXE_SUFFIX, path + n - s, s) == 0) {
346362
return _PyStatus_OK();
347363
}
348364

349-
if (n + s >= progpathlen) {
365+
if (n + s >= pathlen) {
350366
return PATHLEN_ERR();
351367
}
352-
wcsncpy(progpath + n, EXE_SUFFIX, s);
353-
progpath[n+s] = '\0';
368+
wcsncpy(path + n, EXE_SUFFIX, s);
369+
path[n + s] = '\0';
354370

355-
if (!isxfile(progpath)) {
371+
if (!isxfile(path)) {
356372
/* Path that added suffix is invalid: truncate (remove suffix) */
357-
progpath[n] = '\0';
373+
path[n] = '\0';
358374
}
359-
360375
return _PyStatus_OK();
361376
}
362377
#endif
@@ -422,14 +437,14 @@ search_for_prefix(PyCalculatePath *calculate, _PyPathConfig *pathconfig,
422437
if (_PyStatus_EXCEPTION(status)) {
423438
return status;
424439
}
425-
status = joinpath(prefix, LANDMARK, prefix_len);
440+
441+
int module;
442+
status = ismodule(prefix, &module);
426443
if (_PyStatus_EXCEPTION(status)) {
427444
return status;
428445
}
429-
430-
if (ismodule(prefix, prefix_len)) {
446+
if (module) {
431447
*found = -1;
432-
reduce(prefix);
433448
return _PyStatus_OK();
434449
}
435450
}
@@ -448,14 +463,14 @@ search_for_prefix(PyCalculatePath *calculate, _PyPathConfig *pathconfig,
448463
if (_PyStatus_EXCEPTION(status)) {
449464
return status;
450465
}
451-
status = joinpath(prefix, LANDMARK, prefix_len);
466+
467+
int module;
468+
status = ismodule(prefix, &module);
452469
if (_PyStatus_EXCEPTION(status)) {
453470
return status;
454471
}
455-
456-
if (ismodule(prefix, prefix_len)) {
472+
if (module) {
457473
*found = 1;
458-
reduce(prefix);
459474
return _PyStatus_OK();
460475
}
461476
prefix[n] = L'\0';
@@ -471,14 +486,14 @@ search_for_prefix(PyCalculatePath *calculate, _PyPathConfig *pathconfig,
471486
if (_PyStatus_EXCEPTION(status)) {
472487
return status;
473488
}
474-
status = joinpath(prefix, LANDMARK, prefix_len);
489+
490+
int module;
491+
status = ismodule(prefix, &module);
475492
if (_PyStatus_EXCEPTION(status)) {
476493
return status;
477494
}
478-
479-
if (ismodule(prefix, prefix_len)) {
495+
if (module) {
480496
*found = 1;
481-
reduce(prefix);
482497
return _PyStatus_OK();
483498
}
484499

@@ -1038,12 +1053,13 @@ calculate_argv0_path_framework(PyCalculatePath *calculate,
10381053
if (_PyStatus_EXCEPTION(status)) {
10391054
goto done;
10401055
}
1041-
status = joinpath(argv0_path, LANDMARK, argv0_path_len);
1056+
1057+
int module;
1058+
status = ismodule(argv0_path, &module);
10421059
if (_PyStatus_EXCEPTION(status)) {
10431060
goto done;
10441061
}
1045-
1046-
if (ismodule(argv0_path, Py_ARRAY_LENGTH(argv0_path))) {
1062+
if (module) {
10471063
/* Use the location of the library as argv0_path */
10481064
if (safe_wcscpy(argv0_path, wbuf, argv0_path_len) < 0) {
10491065
status = PATHLEN_ERR();

0 commit comments

Comments
 (0)