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

Fix check of filename length #2321

Merged
merged 1 commit into from
Sep 19, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -246,7 +246,8 @@ if(BUILD_TESTING)
src/util_test.cc
)
if(WIN32)
target_sources(ninja_test PRIVATE src/includes_normalize_test.cc src/msvc_helper_test.cc)
target_sources(ninja_test PRIVATE src/includes_normalize_test.cc src/msvc_helper_test.cc
windows/ninja.manifest)
endif()
target_link_libraries(ninja_test PRIVATE libninja libninja-re2c)

Expand Down
23 changes: 22 additions & 1 deletion src/disk_interface.cc
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
#include <sstream>
#include <windows.h>
#include <direct.h> // _mkdir
#include <atlcore.h>
#else
#include <unistd.h>
#endif
Expand Down Expand Up @@ -157,13 +158,27 @@ bool DiskInterface::MakeDirs(const string& path) {
}

// RealDiskInterface -----------------------------------------------------------
RealDiskInterface::RealDiskInterface()
#ifdef _WIN32
: use_cache_(false), long_paths_enabled_(false) {
setlocale(LC_ALL, "");
brondani marked this conversation as resolved.
Show resolved Hide resolved
IFDYNAMICGETCACHEDFUNCTIONTYPEDEF(L"ntdll", BOOLEAN(WINAPI*)(),
"RtlAreLongPathsEnabled",
RtlAreLongPathsEnabled) {
long_paths_enabled_ = RtlAreLongPathsEnabled();
}
}
#else
{}
#endif

TimeStamp RealDiskInterface::Stat(const string& path, string* err) const {
METRIC_RECORD("node stat");
#ifdef _WIN32
// MSDN: "Naming Files, Paths, and Namespaces"
// http://msdn.microsoft.com/en-us/library/windows/desktop/aa365247(v=vs.85).aspx
if (!path.empty() && path[0] != '\\' && path.size() > MAX_PATH) {
if (!path.empty() && !AreLongPathsEnabled() && path[0] != '\\' &&
path.size() > MAX_PATH) {
ostringstream err_stream;
err_stream << "Stat(" << path << "): Filename longer than " << MAX_PATH
<< " characters";
Expand Down Expand Up @@ -333,3 +348,9 @@ void RealDiskInterface::AllowStatCache(bool allow) {
cache_.clear();
#endif
}

#ifdef _WIN32
bool RealDiskInterface::AreLongPathsEnabled(void) const {
return long_paths_enabled_;
}
#endif
14 changes: 9 additions & 5 deletions src/disk_interface.h
Original file line number Diff line number Diff line change
Expand Up @@ -69,11 +69,7 @@ struct DiskInterface: public FileReader {

/// Implementation of DiskInterface that actually hits the disk.
struct RealDiskInterface : public DiskInterface {
RealDiskInterface()
#ifdef _WIN32
: use_cache_(false)
#endif
{}
RealDiskInterface();
virtual ~RealDiskInterface() {}
virtual TimeStamp Stat(const std::string& path, std::string* err) const;
virtual bool MakeDir(const std::string& path);
Expand All @@ -85,11 +81,19 @@ struct RealDiskInterface : public DiskInterface {
/// Whether stat information can be cached. Only has an effect on Windows.
void AllowStatCache(bool allow);

#ifdef _WIN32
/// Whether long paths are enabled. Only has an effect on Windows.
bool AreLongPathsEnabled() const;
#endif

private:
#ifdef _WIN32
/// Whether stat information can be cached.
bool use_cache_;

/// Whether long paths are enabled.
bool long_paths_enabled_;

typedef std::map<std::string, TimeStamp> DirCache;
// TODO: Neither a map nor a hashmap seems ideal here. If the statcache
// works out, come up with a better data structure.
Expand Down
19 changes: 19 additions & 0 deletions src/disk_interface_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#ifdef _WIN32
#include <io.h>
#include <windows.h>
#include <direct.h>
#endif

#include "disk_interface.h"
Expand Down Expand Up @@ -96,6 +97,24 @@ TEST_F(DiskInterfaceTest, StatExistingFile) {
EXPECT_EQ("", err);
}

#ifdef _WIN32
TEST_F(DiskInterfaceTest, StatExistingFileWithLongPath) {
string err;
char currentdir[32767];
_getcwd(currentdir, sizeof(currentdir));
const string filename = string(currentdir) +
"\\filename_with_256_characters_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\
xxxxxxxxxxxxxxxxxxxxx";
const string prefixed = "\\\\?\\" + filename;
ASSERT_TRUE(Touch(prefixed.c_str()));
EXPECT_GT(disk_.Stat(disk_.AreLongPathsEnabled() ?
filename : prefixed, &err), 1);
EXPECT_EQ("", err);
}
#endif

TEST_F(DiskInterfaceTest, StatExistingDir) {
string err;
ASSERT_TRUE(disk_.MakeDir("subdir"));
Expand Down
Loading