Skip to content
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

directory_iterator fails on UNC paths with Windows Server 2016 or Windows Server 2012 R2 #245

Closed
dlaugt opened this issue Aug 3, 2022 · 8 comments

Comments

@dlaugt
Copy link

dlaugt commented Aug 3, 2022

I've upgraded boost from 1.67.0 to 1.79.0. I compile the following example with Visual Studio 2017. When I run the program, it fails with Windows Server 2016 or Windows Server 2012 R2:

#include <boost/filesystem/operations.hpp>`
#include <iostream>

int main ()
{
  try
  {
    boost::filesystem::directory_iterator it ("\\\\host\\dir");
  }
  catch (std::exception& ex)
  {
    std::cout << "Exception: " << ex.what () << std::endl;
  }

  return 0;
}

Here is the output:
Exception: boost::filesystem::directory_iterator::construct: The parameter is incorrect [system:87]: "\\host\dir"

It's a valid UNC path (eg the directory exists). The same program works with Windows Server 2019 or Windows 10.

It doesn't work with Boost 1.79.0 and the latest code in develop branch. It works fine with Boost 1.67.0.

In dir_itr_create(), it iterates to the following paths without any success (error code = ERROR_INVALID_PARAMETER):

  • get_file_information_by_handle_ex with file_id_extd_directory_restart_info_class
  • get_file_information_by_handle_ex with file_full_directory_restart_info_class
  • get_file_information_by_handle_ex with file_id_both_directory_restart_info_class

Any idea of what could be wrong?

Lastique added a commit that referenced this issue Aug 3, 2022
Apparently, Windows Server 2016 does not support any directory iteration
requests using GetFileInformationByHandleEx for UNC paths. Fallback to
NtQueryDirectoryFile in this case.

Fixes #245.
@Lastique
Copy link
Member

Lastique commented Aug 3, 2022

The problem is apparently Windows Server not supporting its own damn APIs for UNC paths. Could you test if the code from feature/fix_win_server_2016_unc_paths branch works?

Lastique added a commit that referenced this issue Aug 3, 2022
Apparently, Windows Server 2016 does not support any directory iteration
requests using GetFileInformationByHandleEx for UNC paths. Fallback to
NtQueryDirectoryFile in this case.

Fixes #245.
Lastique added a commit that referenced this issue Aug 3, 2022
Apparently, Windows Server 2016 does not support any directory iteration
requests using GetFileInformationByHandleEx for UNC paths. Fallback to
NtQueryDirectoryFile in this case.

Fixes #245.
Lastique added a commit that referenced this issue Aug 3, 2022
Apparently, Windows Server 2016 does not support any directory iteration
requests using GetFileInformationByHandleEx for UNC paths. Fallback to
NtQueryDirectoryFile in this case.

Fixes #245.
@dlaugt
Copy link
Author

dlaugt commented Aug 3, 2022

Unfortunately, it doesn't help. It goes to nt_query_directory_file () with file_directory_information_class but fails with the same error code:
Exception: boost::filesystem::directory_iterator::construct: The parameter is incorrect [system:87]: "\\host\dir"

@Lastique
Copy link
Member

Lastique commented Aug 3, 2022

In that case, I'm sorry, but your use case won't be supported. I'm not aware of any other way to iterate over a directory that involves a handle and FindFirstFileW/FindNextFileW is incompatible with handles. Using a handle is necessary for the remove_all implementation.

@Lastique Lastique closed this as completed Aug 3, 2022
@dlaugt
Copy link
Author

dlaugt commented Aug 3, 2022

Ok but this is a regression, it was supported before... I've tried to map the UNC path into a drive (eg Z:\dir) but I have the same error.

If I activate the C++17 mode and compile the program with std::filesystem (Microsoft implementation), it works fine on Windows Server 2016 and Windows Server 2012 R2.

However, I would like to stay on the default C++ standard (e.g. C++14) and still use boost...

@dlaugt
Copy link
Author

dlaugt commented Aug 3, 2022

Microsoft is using FindFirstFileW/FindNextFileW certainly for a good reason:
https://github.com/microsoft/STL/blob/main/stl/src/filesystem.cpp

@Lastique
Copy link
Member

Lastique commented Aug 3, 2022

We used to use FindFirstFileW/FindNextFileW, and the implementation is still there for Win CE, but that implementation does not allow remove_all to be protected against CVE-2022-21658. (And yes, Microsoft's implementation is vulnerable.)

I could probably merge FindFirstFileW/FindNextFileW implementation with GetFileInformationByHandleEx/NtQueryDirectoryFile based one, but that further complicates both the directory iterator and remove_all implementations. I suppose, I'll leave this open and try and see how ugly this will get.

@Lastique Lastique reopened this Aug 3, 2022
@Lastique
Copy link
Member

Lastique commented Aug 8, 2022

@dlaugt Could you test if #246 helps in your case?

@dlaugt
Copy link
Author

dlaugt commented Aug 25, 2022

The change in #246 resolves my issue. Excellent, thanks a lot.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants