`<filesystem>`: `directory_iterator` with `\\\\.\\pipe` can produce invalid paths
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
Attempting to use directory_iterator or recursive_directory_iterator with the path \\\\.\\pipe (to list named pipes) can produce invalid paths. It seems that although the documentation states that pipe names can't include backslashes, this isn't actually enforced. If a pipe under \\\\.\\pipe\\ does include a backslash in its name then _Dir_enum_impl::_Refresh only replaces the previous pipe name from the last backslash onwards, producing paths like "\\\\.\\pipe\\Winsock2\\Winsock2\\Winsock2\\Winsock2\\Winsock2\\Winsock2\\Winsock2\\def", where a previously found pipe was named "\\\\.\\pipe\\WinSock2\\abc".
Command-line test case
C:\DirectoryIteratorTest>type DirectoryIteratorTest.cpp
#include <filesystem>
#include <iostream>
#include <Windows.h>
int main()
{
// Random strings that shouldn't already exist in pipe names
const std::wstring strRand1{ L"5639357256" }, strRand2{ L"9423298489" }, strRand3{ L"3214769820" };
// The base path for pipes
const std::filesystem::path pathPipeBase{ "\\\\.\\pipe" };
// A pipe path with a backslash in its name
const std::filesystem::path pathPipeBad{ pathPipeBase / strRand1 / strRand2 };
// A pipe path without a backslash in its name
const std::filesystem::path pathPipeOk{ pathPipeBase / strRand3 };
HANDLE hPipeBad(CreateNamedPipeW(pathPipeBad.native().c_str(), PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT, 1, 1024, 1024, 0, nullptr));
HANDLE hPipeOk(CreateNamedPipeW(pathPipeOk.native().c_str(), PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT, 1, 1024, 1024, 0, nullptr));
if (!std::filesystem::exists(pathPipeBad) || !std::filesystem::exists(pathPipeOk))
{
std::cout << "CreateNamedPipe failed" << std::endl;
return 1;
}
for (const auto& entry : std::filesystem::directory_iterator{ pathPipeBase })
{
// Look for paths that contain the random string in the bad path before the backslash, but not the one after
if ((entry.path().native().find(strRand1) != std::wstring::npos) && (entry.path().native().find(strRand2) == std::wstring::npos))
std::cout << entry.path() << std::endl;
}
CloseHandle(hPipeOk);
CloseHandle(hPipeBad);
}
C:\DirectoryIteratorTest>cl /EHsc /W4 /WX /std:c++latest DirectoryIteratorTest.cpp
Microsoft (R) C/C++ Optimizing Compiler Version 19.40.33521 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.
DirectoryIteratorTest.cpp
Microsoft (R) Incremental Linker Version 14.40.33521.0
Copyright (C) Microsoft Corporation. All rights reserved.
/out:DirectoryIteratorTest.exe
DirectoryIteratorTest.obj
C:\DirectoryIteratorTest>.\DirectoryIteratorTest.exe
"\\\\.\\pipe\\Winsock2\\Winsock2\\Winsock2\\Winsock2\\Winsock2\\Winsock2\\Winsock2\\Winsock2\\PIPE_EVENTROOT\\LOCAL\\LOCAL\\LOCAL\\LOCAL\\LOCAL\\LOCAL\\LOCAL\\LOCAL\\LOCAL\\LOCAL\\LOCAL\\LOCAL\\LOCAL\\ProtectedPrefix\\LocalService\\LOCAL\\LOCAL\\LOCAL\\LOCAL\\LOCAL\\LOCAL\\LOCAL\\LOCAL\\LOCAL\\LOCAL\\LOCAL\\LOCAL\\LOCAL\\LOCAL\\LOCAL\\LOCAL\\uv\\uv\\uv\\uv\\uv\\uv\\uv\\uv\\uv\\uv\\uv\\uv\\uv\\uv\\uv\\uv\\uv\\uv\\uv\\uv\\uv\\uv\\uv\\uv\\uv\\uv\\LOCAL\\LOCAL\\LOCAL\\LOCAL\\LOCAL\\LOCAL\\LOCAL\\LOCAL\\LOCAL\\LOCAL\\LOCAL\\LOCAL\\LOCAL\\LOCAL\\LOCAL\\LOCAL\\LOCAL\\LOCAL\\LOCAL\\IdentityNexusIntegrationPipe\\LOCAL\\LOCAL\\LOCAL\\LOCAL\\LOCAL\\LOCAL\\LOCAL\\LOCAL\\LOCAL\\LOCAL\\LOCAL\\LOCAL\\LOCAL\\LOCAL\\LOCAL\\LOCAL\\LOCAL\\LOCAL\\LOCAL\\LOCAL\\5639357256\\3214769820"
Expected behavior
In the example above there should be no output, in general pipe names with backslashes should be handled correctly
STL version
Microsoft Visual Studio Professional 2022 (64-bit) - Preview
Version 17.10.0 Preview 1.0
Additional context
I have no idea whether supporting \\\\.\\pipe with std::filesystem is even intended, though it would be nice
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
Start with the directory_iterator and recursive_directory_iterator implementation, especially _Dir_enum_impl::_Refresh, and reproduce the behavior using the command-line test case with named pipes under \.\pipe. Trace how entries containing backslashes are converted into paths. Done means pipe names with backslashes are returned correctly without accumulating or duplicating path components.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- cpp
- Domain
- operating-systems
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100