Skip to content

[5.6] FileLock encounters a runtime error when the path of the locked file is long (#277) #278

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Jan 15, 2022

Conversation

abertelrud
Copy link
Contributor

This is cherry-picked from #277.

Explanation: FileLock constructs the name of the lock file based on the path of the file being locked. When this path is very long, the name of the constructed lock file exceeds NAME_MAX (or more specifically the directory entry name length limit of the file system on which the directory that contains it resides, but NAME_MAX is a decent approximation on modern file systems commonly in use).

Scope of Issue: This can affect any use of the file locking where the locked file is at a long path (i.e. deeply nested and/or with long path components). This issue was seen in SwiftPM.

Reason for Nominating to 5.6: This causes unit test failures in SwiftPM and can cause runtime failures in actual use (typically not crashes but errors such as build errors and other kinds of failures). Although this can be worked around by moving the packages to a shallower path, it's not at all obvious that this is the problem nor is it always possibly to affect the paths of for example CI systems.

Risk: Low — the problem is understood and the fix is straightforward. The main issue would be if there is something special about Unicode content of paths that hasn't been accounted for. Any failure to fix the problem should be evident from continued failure of unit tests such as in SwiftPM and its client IDEs.

Reviewed By: @tomerd, @neonichu

Automated Testing: An updated unit test checks for this condition.

Dependencies: None

Impact on CI: None

How to Verify: Create a package that uses this API and try to lock a path whose total length in UTF-8 bytes is greater than the value of NAME_MAX (this is also what the unit test does).

rdar://87471360

…is long

FileLock constructs the name of the lock file based on the path of the file being locked.  When this path is very long, the name of the constructed lock file exceeds `NAME_MAX` (or more specifically the directory entry name length limit of the file system on which the directory that contains it resides, but `NAME_MAX` is a decent approximation on modern file systems commonly in use).

This change truncates it to `NAME_MAX` UTF-8 bytes (starting from the end), rounding down to avoid splitting Unicode scalars (but making no effort to avoid splitting clusters, since they don't affect the validity of the filename).  Another possible refinement would be to also include a hash of the elided part of the filename — in the interest of avoiding complexity this implementation doesn't do that, and it's not clear that it's needed given that 255 (the common value of `NAME_MAX`) usually results in a unique enough name in any practical circumstances.

rdar://87471360
(cherry picked from commit 2a2ba2a)
@abertelrud
Copy link
Contributor Author

@swift-ci please test

@abertelrud
Copy link
Contributor Author

abertelrud commented Jan 13, 2022

Linux: No space left on device (being discussed in other fora, just mentioning it here as to why there's no successful build yet)

@abertelrud
Copy link
Contributor Author

@swift-ci please test linux

@abertelrud
Copy link
Contributor Author

Will need to resolve the Windows issue identified in #280 before merging. I really wish we had some kind of Windows PR testing to flag these issues.

compnerd and others added 2 commits January 13, 2022 15:48
This fixes multiple issues with the file locking implementation on
Windows.  `AbsolutePath.root` is meaningless on Windows - there is
no concept of a singular root on Windows, instead you have have 26
individual roots - A-Z.  Stripping the count of characters for the
root path leaves us with an invalid path string as the root drives
have been stripped.  The next character is an invalid character on
most file systems, and so we must replace `:`.  Instead of using a
`MAX_NAME` to compute a length of the ARC, enforce a limit for the
complete path (though an ARC would be limited to 255 codepoints on
NTFS).  This incidentally also corrects the emitted path, previous
path computation left us with the file in PWD.
@abertelrud
Copy link
Contributor Author

Pushed the additional fixes to include @compnerd's and my fixes from #282

@abertelrud
Copy link
Contributor Author

@swift-ci please test

@abertelrud abertelrud added swift 5.6 This PR targets the 5.6 branch ready Author believes the PR is ready to be merged & any feedback has been addressed labels Jan 14, 2022
@abertelrud abertelrud merged commit 107e570 into release/5.6 Jan 15, 2022
@abertelrud abertelrud deleted the eng/5.6-87471360-long-filelock-names branch January 15, 2022 01:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
ready Author believes the PR is ready to be merged & any feedback has been addressed swift 5.6 This PR targets the 5.6 branch
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants