gh-82367: Use FindFirstFile Win32 API in ntpath.realpath() (GH-110298)

* Use `FindFirstFile` Win32 API to fix a bug where `ntpath.realpath()`
breaks out of traversing a series of paths where a (handled)
`ERROR_ACCESS_DENIED` or `ERROR_SHARING_VIOLATION` occurs.
* Update docs to reflect that `ntpath.realpath()` eliminates MS-DOS
style names.
This commit is contained in:
박문식 2023-10-05 23:49:07 +09:00 committed by GitHub
parent 2cb62c6437
commit d33aa18f15
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 132 additions and 8 deletions

View file

@ -1848,6 +1848,40 @@ exit:
#if defined(MS_WINDOWS)
PyDoc_STRVAR(os__findfirstfile__doc__,
"_findfirstfile($module, path, /)\n"
"--\n"
"\n"
"A function to get the real file name without accessing the file in Windows.");
#define OS__FINDFIRSTFILE_METHODDEF \
{"_findfirstfile", (PyCFunction)os__findfirstfile, METH_O, os__findfirstfile__doc__},
static PyObject *
os__findfirstfile_impl(PyObject *module, path_t *path);
static PyObject *
os__findfirstfile(PyObject *module, PyObject *arg)
{
PyObject *return_value = NULL;
path_t path = PATH_T_INITIALIZE("_findfirstfile", "path", 0, 0);
if (!path_converter(arg, &path)) {
goto exit;
}
return_value = os__findfirstfile_impl(module, &path);
exit:
/* Cleanup for path */
path_cleanup(&path);
return return_value;
}
#endif /* defined(MS_WINDOWS) */
#if defined(MS_WINDOWS)
PyDoc_STRVAR(os__getvolumepathname__doc__,
"_getvolumepathname($module, /, path)\n"
"--\n"
@ -11451,6 +11485,10 @@ exit:
#define OS__GETFINALPATHNAME_METHODDEF
#endif /* !defined(OS__GETFINALPATHNAME_METHODDEF) */
#ifndef OS__FINDFIRSTFILE_METHODDEF
#define OS__FINDFIRSTFILE_METHODDEF
#endif /* !defined(OS__FINDFIRSTFILE_METHODDEF) */
#ifndef OS__GETVOLUMEPATHNAME_METHODDEF
#define OS__GETVOLUMEPATHNAME_METHODDEF
#endif /* !defined(OS__GETVOLUMEPATHNAME_METHODDEF) */
@ -11986,4 +12024,4 @@ exit:
#ifndef OS_WAITSTATUS_TO_EXITCODE_METHODDEF
#define OS_WAITSTATUS_TO_EXITCODE_METHODDEF
#endif /* !defined(OS_WAITSTATUS_TO_EXITCODE_METHODDEF) */
/*[clinic end generated code: output=8b60de6ddb925bc3 input=a9049054013a1b77]*/
/*[clinic end generated code: output=a36904281a8a7507 input=a9049054013a1b77]*/

View file

@ -4809,6 +4809,37 @@ cleanup:
return result;
}
/*[clinic input]
os._findfirstfile
path: path_t
/
A function to get the real file name without accessing the file in Windows.
[clinic start generated code]*/
static PyObject *
os__findfirstfile_impl(PyObject *module, path_t *path)
/*[clinic end generated code: output=106dd3f0779c83dd input=0734dff70f60e1a8]*/
{
PyObject *result;
HANDLE hFindFile;
WIN32_FIND_DATAW wFileData;
WCHAR *wRealFileName;
Py_BEGIN_ALLOW_THREADS
hFindFile = FindFirstFileW(path->wide, &wFileData);
Py_END_ALLOW_THREADS
if (hFindFile == INVALID_HANDLE_VALUE) {
path_error(path);
return NULL;
}
wRealFileName = wFileData.cFileName;
result = PyUnicode_FromWideChar(wRealFileName, wcslen(wRealFileName));
FindClose(hFindFile);
return result;
}
/*[clinic input]
os._getvolumepathname
@ -15961,6 +15992,7 @@ static PyMethodDef posix_methods[] = {
OS__GETFULLPATHNAME_METHODDEF
OS__GETDISKUSAGE_METHODDEF
OS__GETFINALPATHNAME_METHODDEF
OS__FINDFIRSTFILE_METHODDEF
OS__GETVOLUMEPATHNAME_METHODDEF
OS__PATH_SPLITROOT_METHODDEF
OS__PATH_NORMPATH_METHODDEF