`<filesystem>`: `weakly_canonical` doesn't make absolute path for relative path with only correct drive.
Nobody has claimed this yet.
- Dominant language
- C++
- Stars
- 11.1k
- Forks
- 1.7k
- Avg merge
- 4d 15h
- Merged PRs (30d)
- 22
Description
Describe the bug
Say I have a directory Temp in C drive and my current directory is C:\Temp; Temp contains a subdirectory foo. There is no bar in Temp and foo.
And given the program below:
#include <filesystem>
namespace fs = std::filesystem;
int main()
{
fs::current_directory("C:\\Temp");
// Should be (and currently is) C:\Temp.
std::cout << fs::weakly_canonical("C:") << "\n";
// Should be (and currently is) C:\Temp\foo\bar, though bar doesn't exist.
std::cout << fs::weakly_canonical("C:foo\\bar") << "\n";
// Should be (**but currently is not**) C:\Temp\bar, though bar doesn't exist.
std::cout << fs::weakly_canonical("C:bar") << "\n";
}
Command-line test case
C:\Temp>type repro.cpp
#include <filesystem>
#include <iostream>
namespace fs = std::filesystem;
int main()
{
// Prepare reproduction environment.
fs::path tempDir{ "C:\\Temp" };
fs::create_directories(tempDir / "foo");
// Test
fs::current_path(tempDir);
std::cout << fs::weakly_canonical("C:") << "\n";
std::cout << fs::weakly_canonical("C:foo\\bar") << "\n";
std::cout << fs::weakly_canonical("C:bar") << "\n";
// Clean reproduction environment.
fs::remove_all(tempDir / "foo");
}
C:\Temp>cl /EHsc /W4 /WX /std:c++latest .\repro.cpp
Microsoft (R) C/C++ Optimizing Compiler Version 19.44.35214 for x64
Copyright (C) Microsoft Corporation. All rights reserved.
/std:c++latest is provided as a preview of language features from the latest C++
working draft, and we're eager to hear about bugs and suggestions for improvements.
However, note that these features are provided as-is without support, and subject
to changes or removal as the working draft evolves. See
https://go.microsoft.com/fwlink/?linkid=2045807 for details.
repro.cpp
Microsoft (R) Incremental Linker Version 14.44.35214.0
Copyright (C) Microsoft Corporation. All rights reserved.
/out:repro.exe
repro.obj
C:\Temp>.\repro.exe
"C:\\Temp"
"C:\\Temp\\foo\\bar"
"C:bar"
Expected behavior
The last output should be "C:\\Temp\\bar".
STL version
- Option 1: MSVC Compiler version: 19.44.35214
- Option 2:
_MSVC_STL_UPDATEvalue: 202503 - Option 3: git commit hash: this problem still exists in the [current latest commit] (https://github.com/microsoft/STL/blob/3f76681e18fa51e1441c9150099b8010c1d18e1c/stl/inc/filesystem).
Additional context
In the standard, weakly_canonical is specified as:
Effects: Using
status(p)orstatus(p, ec), respectively, to determine existence, return a path composed byoperator/=from the result of calling canonical with a path argument composed of the leading elements ofpthat exist, if any, followed by the elements ofpthat do not exist, if any.
And the elements of path are specifed as:
A path is a sequence of elements that identify the location of a file within a filesystem. The elements are the root-name, root-directory, and an optional sequence of filename ([fs.path.generic]).
So C: as the root-name is a legal leading element in the path and thus the last line in test case should be "C:\\Temp\\bar" instead.
The problem is that MS-STL skips initial value of the element for this case:
https://github.com/microsoft/STL/blob/3f76681e18fa51e1441c9150099b8010c1d18e1c/stl/inc/filesystem#L4132-L4159
Here in the loop, for C:bar, the first _Result to call _Canonical is C:bar instead of C:. I'd like to submit a PR if this is considered as a bug :-).
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Reproduce the Windows case from repro.cpp, then inspect the weakly_canonical implementation in stl/inc/filesystem around lines 4132-4159. Verify that the C: root-name is handled before the remaining elements; done means the final case prints "C:\Temp\bar" while the other outputs remain unchanged.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- cpp
- Domain
- operating-systems
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Stale
- Clarity
- Clearly specified
- Newbie friendliness
- 65/100