microsoft / microsoft/STL

`<filesystem>`: `weakly_canonical` doesn't make absolute path for relative path with only correct drive.

Open
#6,054 2 comments 2 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

bug filesystem
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

Additional context

In the standard, weakly_canonical is specified as:

Effects: Using status(p) or status(p, ec), respectively, to determine existence, return a path composed by operator/= from the result of calling canonical with a path argument composed of the leading elements of p that exist, if any, followed by the elements of p that 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

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. 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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.