Skip to content

gh-79125: Update _dirnameW to accept long path names#9769

Closed
jopamer wants to merge 8 commits into
python:mainfrom
jopamer:bpo-34944
Closed

gh-79125: Update _dirnameW to accept long path names#9769
jopamer wants to merge 8 commits into
python:mainfrom
jopamer:bpo-34944

Conversation

@jopamer

@jopamer jopamer commented Oct 9, 2018

Copy link
Copy Markdown
Contributor

The fix for issue 32557 updated os__getdiskusage_impl to use _dirnameW for obtaining the parent directory of a file. This would cause a regression if the path exceeded 260 characters, since _dirnameW currently returns -1 if given a path >= MAX_PATH in length.

As suggested in the issue's comments, _dirnameW should be updated to use PathCchRemoveFileSpec when available (on Win8.1 or greater) to avoid throwing an unnecessary error on a long path.

Note:
If PathCchRemoveFileSpec isn't available, we can call through PathRemoveFileSpecW, which is otherwise deprecated. What's interesting there is that while the docs say it expects a buffer of size MAX_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 through PathCchRemoveFileSpec under the hood on Win8 and greater, passing in 0x8000h as the cch argument. PathCchRemoveFileSpec then scans through the path for '' via wcschr, stops when it hits the last one and inserts a NULL. (Analysis of PathRemoveFileSpecW on a Win7 VM shows that it does basically the same thing, and is also resilient to paths greater than MAX_PATH in length.)

https://bugs.python.org/issue34944

Calling through PathCchRemoveFileSpec will allow _dirnameW to trim paths longer than MAX_PATH in length.
Comment thread Modules/posixmodule.c Outdated
break;
if (_PPathCchRemoveFileSpec) {
if (FAILED(_PPathCchRemoveFileSpec(path, length))) {
Py_FatalError("Error removing path element in _dirnameW");

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks - I wasn't aware of the difference there. I'll update the diff.

Comment thread Modules/posixmodule.c
* Revert _dirnameW back to returning 0 on success, -1 on failure.
* Release the GIL before calling out to LoadLibraryW.
@jopamer

jopamer commented Oct 9, 2018

Copy link
Copy Markdown
Contributor Author

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.
@jopamer

jopamer commented Oct 9, 2018

Copy link
Copy Markdown
Contributor Author

I think I see where things are going wrong - taking a look.

@jopamer

jopamer commented Oct 9, 2018

Copy link
Copy Markdown
Contributor Author

Ok: os.symlink doesn't seem to have the GIL, hence the crash in some of the CI tests when they hit Py_BEGIN_ALLOW_THREADS in _dirnameW.

jopamer and others added 2 commits October 9, 2018 21:31
@jopamer

jopamer commented Oct 10, 2018

Copy link
Copy Markdown
Contributor Author

Ok - I think I've addressed all the issues, and all tests are passing.

@jopamer

jopamer commented Oct 22, 2018

Copy link
Copy Markdown
Contributor Author

Hi everyone - it's been a couple of weeks, so I just wanted to see if there was any feedback :)

@zware

zware commented Sep 11, 2019

Copy link
Copy Markdown
Member

Hi @jopamer. Unfortunately this has wound up with a conflict since the last time @zooba reviewed it; would you mind to rebase it?

@jopamer

jopamer commented Sep 12, 2019

Copy link
Copy Markdown
Contributor Author

Thanks for taking a look! I'll be happy to - I just need to spin up a new Windows environment.

@csabella

Copy link
Copy Markdown
Contributor

@jopamer friendly ping :-)

@arhadthedev arhadthedev changed the title bpo-34944: Update _dirnameW to accept long path names gh-79125: Update _dirnameW to accept long path names May 5, 2023
@github-actions

Copy link
Copy Markdown

This PR is stale because it has been open for 30 days with no activity.

@github-actions github-actions Bot added the stale Stale PR or inactive for long period of time. label Apr 13, 2025
@zooba

zooba commented Apr 14, 2025

Copy link
Copy Markdown
Member

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.

@zooba zooba closed this Apr 14, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

awaiting review stale Stale PR or inactive for long period of time.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants