gh-84419: Fix the execute permissions in os.stat() on Windows (GH-155… · python/cpython@b7daede

GitHub

@@ -2021,6 +2021,14 @@ win32_wchdir(LPCWSTR path)

20212021#define HAVE_STRUCT_STAT_ST_FILE_ATTRIBUTES 1

20222022#define HAVE_STRUCT_STAT_ST_REPARSE_TAG 1

202320232024+/* The \\?\ prefix disables the path normalization, in particular

2025+ stripping of trailing dots and spaces. */

2026+static int

2027+is_extended_path(const wchar_t *path)

2028+{

2029+ return wcsncmp(path, L"\\\\?\\", 4) == 0;

2030+}

2031+20242032static void

20252033find_data_to_file_info(WIN32_FIND_DATAW *pFileData,

20262034 FILE_BASIC_INFO* basic_info,

@@ -2094,12 +2102,20 @@ update_st_mode_from_path(const wchar_t *path, DWORD attr,

20942102 GetSecurityInfo, OpenThreadToken/OpenProcessToken, and

20952103 AccessCheck to check for generic read, write, and execute

20962104 access. */

2097- const wchar_t *fileExtension = wcsrchr(path, '.');

2098- if (fileExtension) {

2099- if (_wcsicmp(fileExtension, L".exe") == 0 ||

2100- _wcsicmp(fileExtension, L".bat") == 0 ||

2101- _wcsicmp(fileExtension, L".cmd") == 0 ||

2102- _wcsicmp(fileExtension, L".com") == 0) {

2105+ size_t len = wcslen(path);

2106+ if (!is_extended_path(path)) {

2107+ /* Trailing dots and spaces are stripped from the last component

2108+ of the path. */

2109+ while (len > 0 && (path[len - 1] == L'.' || path[len - 1] == L' ')) {

2110+ len--;

2111+ }

2112+ }

2113+ if (len >= 4) {

2114+ const wchar_t *fileExtension = path + len - 4;

2115+ if (_wcsnicmp(fileExtension, L".exe", 4) == 0 ||

2116+ _wcsnicmp(fileExtension, L".bat", 4) == 0 ||

2117+ _wcsnicmp(fileExtension, L".cmd", 4) == 0 ||

2118+ _wcsnicmp(fileExtension, L".com", 4) == 0) {

21032119 result->st_mode |= 0111;

21042120 }

21052121 }

@@ -16718,12 +16734,6 @@ static PyType_Spec DirEntryType_spec = {

16718167341671916735#ifdef MS_WINDOWS

167201673616721-static int

16722-is_extended_path(const wchar_t *path)

16723-{

16724- return wcsncmp(path, L"\\\\?\\", 4) == 0;

16725-}

16726-1672716737static wchar_t *

1672816738join_path_filenameW(const wchar_t *path_wide, const wchar_t *filename,

1672916739 int normalize)