gh-79125: Update _dirnameW to accept long path names#9769
Conversation
Calling through PathCchRemoveFileSpec will allow _dirnameW to trim paths longer than MAX_PATH in length.
| break; | ||
| if (_PPathCchRemoveFileSpec) { | ||
| if (FAILED(_PPathCchRemoveFileSpec(path, length))) { | ||
| Py_FatalError("Error removing path element in _dirnameW"); |
There was a problem hiding this comment.
I'm not excited about adding a fatal error in the midst of a Python call, especially since we have an error code here that could be returned instead (inside getpathp.c is different, because we aren't initialized enough to raise an exception at that stage).
Setting an error here and returning non-zero should work fine. I believe all calls to this are already holding the GIL, but that would be the only issue.
There was a problem hiding this comment.
Thanks - I wasn't aware of the difference there. I'll update the diff.
* Revert _dirnameW back to returning 0 on success, -1 on failure. * Release the GIL before calling out to LoadLibraryW.
|
I've updated the diffs to address the concerns, though I'm a bit puzzled by the CI failures, since I'm not seeing any test failures locally. |
_joinW presumes a buffer length of MAX_PATH, so given that I've changed the return type of _dirnameW back to int, I'll revert my changes for now.
|
I think I see where things are going wrong - taking a look. |
|
Ok: |
Also, update _joinW to not fix buffer sizes to MAX_PATH.
|
Ok - I think I've addressed all the issues, and all tests are passing. |
|
Hi everyone - it's been a couple of weeks, so I just wanted to see if there was any feedback :) |
|
Thanks for taking a look! I'll be happy to - I just need to spin up a new Windows environment. |
|
@jopamer friendly ping :-) |
|
This PR is stale because it has been open for 30 days with no activity. |
|
Just going to close this. If someone wants to work on it, we can now assume that the function is available, so it'll be a much simpler change than this one. |
The fix for issue 32557 updated
os__getdiskusage_implto use_dirnameWfor obtaining the parent directory of a file. This would cause a regression if the path exceeded 260 characters, since_dirnameWcurrently returns -1 if given a path >=MAX_PATHin length.As suggested in the issue's comments,
_dirnameWshould be updated to usePathCchRemoveFileSpecwhen available (on Win8.1 or greater) to avoid throwing an unnecessary error on a long path.Note:
If
PathCchRemoveFileSpecisn't available, we can call throughPathRemoveFileSpecW, which is otherwise deprecated. What's interesting there is that while the docs say it expects a buffer of sizeMAX_PATH, analysis of the function shows that it doesn't make assumptions about the size of the path other than it's less than 32k characters in length. It calls throughPathCchRemoveFileSpecunder the hood on Win8 and greater, passing in 0x8000h as thecchargument.PathCchRemoveFileSpecthen scans through the path for '' viawcschr, stops when it hits the last one and inserts a NULL. (Analysis ofPathRemoveFileSpecWon a Win7 VM shows that it does basically the same thing, and is also resilient to paths greater thanMAX_PATHin length.)https://bugs.python.org/issue34944