On Windows, there is a built-in maximum path limitation of 260 characters under most conditions. This can be extended to 32767 characters under either of the following two conditions:
- Adding the longPathAware attribute to the executable's manifest AND enabling the LongPathsEnabled system-wide registry key or group policy.
- Ensuring fully qualified paths passed to Win32 APIs are prefixed with \?\
Unfortunately, the former is not realistic for the Swift ecosystem, since it requires developers to have awareness of this specific Windows limitation, AND set longPathAware in their apps' manifest AND expect end users of those apps to change their system configuration.
Instead, this patch transparently prefixes all eligible paths in calls to Win32 APIs with the \?\ prefix to allow them to work with paths longer than 260 characters without requiring the caller of Foundation to manually prefix the paths.
See https://learn.microsoft.com/en-us/windows/win32/fileio/maximum-file-path-limitation for more info.
* (133687793) Prevent buffer over-reads with string file system representations that fail
Signed-off-by: Jeremy Schonfeld <jschonfeld@apple.com>
* Account for empty buffers
Signed-off-by: Jeremy Schonfeld <jschonfeld@apple.com>
* Move empty buffer check earlier
Signed-off-by: Jeremy Schonfeld <jschonfeld@apple.com>
---------
Signed-off-by: Jeremy Schonfeld <jschonfeld@apple.com>
When trying to get the file system representation of a string, we may
have previously used `appendingPathComponent(_:)` which will have used
the incorrect separator. Ensure that all the separators are properly
converted prior to returning the path.
In the case that the path is canonicalised, the `/` would be replaced
with `\`. The leading `\` would interfere with our ability to recognise
the absolute path representation and thus get the wrong response.
When creating a file system representation from the path, we need to
strip the leading `/` which is added for the RFC representation of the
Windows path. Without this, the C runtime will fail with an invalid
argument error. Unfortunately this regresses the test suite by causing a
hang.
We would previously conditionally call `GetFullPathNameW` and do string
manipulations for normalising the path. Instead, always call
`GetFullPathNameW` to normalise the path as per Windows' rules. This
more importantly will collapse runs of the arc separator, which is
crucial when using extended paths as the NT path form must always use
the normalised paths or the access will fail.
The returned value in the success case does not account for the
terminating nul character, resulting in the value being 1 less than the
allocation required. This was causing a spurious failure and thus unable
to compute the location of the process.
This helper allows us to convert paths to the NT path representation.
The NT Path representation is important for internal usage as it allows
us to bypass the `MAX_PATH` (261) limit for Win32 APIs. In order to do
this, we simply escape the string with the NT prefix (`\\?\`) which
requires that the path is normalised (uses `\` rather than `/`) and
generally should be an absolute path. Using the NT path allows us to use
the fully supported 32k character path length of the NT kernel.
Co-authored-by: Alexander Smarus <bender@readdle.com>
Co-authored-by: Jeremy Schonfeld <1004103+jmschonfeld@users.noreply.github.com>
* Use smaller buffer for file system representation
* Reword scalars -> code-units
Co-authored-by: Karl <5254025+karwa@users.noreply.github.com>
---------
Co-authored-by: Karl <5254025+karwa@users.noreply.github.com>