From c4b09e1e7e1d531a818601be33e0ec8ee18c3cde Mon Sep 17 00:00:00 2001 From: Daniel Weber Date: Tue, 23 Aug 2016 00:26:38 +0200 Subject: Allow more path components - 60 instead of 30 path components - 64 instead of 32 backslashes in a path (windows only) Issue: 1161 --- src/build.cc | 2 +- src/clparser.cc | 2 +- src/graph.cc | 4 ++-- src/includes_normalize-win32.cc | 2 +- src/manifest_parser.cc | 6 +++--- src/ninja.cc | 4 ++-- src/util.cc | 18 +++++++++--------- src/util.h | 4 ++-- src/util_test.cc | 38 +++++++++++++++++++++++--------------- 9 files changed, 44 insertions(+), 36 deletions(-) diff --git a/src/build.cc b/src/build.cc index b806fb5..5078251 100644 --- a/src/build.cc +++ b/src/build.cc @@ -918,7 +918,7 @@ bool Builder::ExtractDeps(CommandRunner::Result* result, deps_nodes->reserve(deps.ins_.size()); for (vector::iterator i = deps.ins_.begin(); i != deps.ins_.end(); ++i) { - unsigned int slash_bits; + uint64_t slash_bits; if (!CanonicalizePath(const_cast(i->str_), &i->len_, &slash_bits, err)) return false; diff --git a/src/clparser.cc b/src/clparser.cc index f73a8c1..c17150b 100644 --- a/src/clparser.cc +++ b/src/clparser.cc @@ -90,7 +90,7 @@ bool CLParser::Parse(const string& output, const string& deps_prefix, #else // TODO: should this make the path relative to cwd? normalized = include; - unsigned int slash_bits; + uint64_t slash_bits; if (!CanonicalizePath(&normalized, &slash_bits, err)) return false; #endif diff --git a/src/graph.cc b/src/graph.cc index f1d9ca2..a5bac1c 100644 --- a/src/graph.cc +++ b/src/graph.cc @@ -420,7 +420,7 @@ bool ImplicitDepLoader::LoadDepFile(Edge* edge, const string& path, return false; } - unsigned int unused; + uint64_t unused; if (!CanonicalizePath(const_cast(depfile.out_.str_), &depfile.out_.len_, &unused, err)) return false; @@ -442,7 +442,7 @@ bool ImplicitDepLoader::LoadDepFile(Edge* edge, const string& path, // Add all its in-edges. for (vector::iterator i = depfile.ins_.begin(); i != depfile.ins_.end(); ++i, ++implicit_dep) { - unsigned int slash_bits; + uint64_t slash_bits; if (!CanonicalizePath(const_cast(i->str_), &i->len_, &slash_bits, err)) return false; diff --git a/src/includes_normalize-win32.cc b/src/includes_normalize-win32.cc index ca35012..e8a3e0f 100644 --- a/src/includes_normalize-win32.cc +++ b/src/includes_normalize-win32.cc @@ -103,7 +103,7 @@ bool IncludesNormalize::Normalize(const string& input, const char* relative_to, return false; } strncpy(copy, input.c_str(), input.size() + 1); - unsigned int slash_bits; + uint64_t slash_bits; if (!CanonicalizePath(copy, &len, &slash_bits, err)) return false; StringPiece partially_fixed(copy, len); diff --git a/src/manifest_parser.cc b/src/manifest_parser.cc index d6dcf22..2164921 100644 --- a/src/manifest_parser.cc +++ b/src/manifest_parser.cc @@ -212,7 +212,7 @@ bool ManifestParser::ParseDefault(string* err) { do { string path = eval.Evaluate(env_); string path_err; - unsigned int slash_bits; // Unused because this only does lookup. + uint64_t slash_bits; // Unused because this only does lookup. if (!CanonicalizePath(&path, &slash_bits, &path_err)) return lexer_.Error(path_err, err); if (!state_->AddDefault(path, &path_err)) @@ -342,7 +342,7 @@ bool ManifestParser::ParseEdge(string* err) { for (size_t i = 0, e = outs.size(); i != e; ++i) { string path = outs[i].Evaluate(env); string path_err; - unsigned int slash_bits; + uint64_t slash_bits; if (!CanonicalizePath(&path, &slash_bits, &path_err)) return lexer_.Error(path_err, err); if (!state_->AddOut(edge, path, slash_bits)) { @@ -375,7 +375,7 @@ bool ManifestParser::ParseEdge(string* err) { for (vector::iterator i = ins.begin(); i != ins.end(); ++i) { string path = i->Evaluate(env); string path_err; - unsigned int slash_bits; + uint64_t slash_bits; if (!CanonicalizePath(&path, &slash_bits, &path_err)) return lexer_.Error(path_err, err); state_->AddIn(edge, path, slash_bits); diff --git a/src/ninja.cc b/src/ninja.cc index 25eafe8..4fb04ad 100644 --- a/src/ninja.cc +++ b/src/ninja.cc @@ -233,7 +233,7 @@ int GuessParallelism() { /// Returns true if the manifest was rebuilt. bool NinjaMain::RebuildManifest(const char* input_file, string* err) { string path = input_file; - unsigned int slash_bits; // Unused because this path is only used for lookup. + uint64_t slash_bits; // Unused because this path is only used for lookup. if (!CanonicalizePath(&path, &slash_bits, err)) return false; Node* node = state_.LookupNode(path); @@ -255,7 +255,7 @@ bool NinjaMain::RebuildManifest(const char* input_file, string* err) { Node* NinjaMain::CollectTarget(const char* cpath, string* err) { string path = cpath; - unsigned int slash_bits; + uint64_t slash_bits; if (!CanonicalizePath(&path, &slash_bits, err)) return NULL; diff --git a/src/util.cc b/src/util.cc index e31fd1f..fb57cec 100644 --- a/src/util.cc +++ b/src/util.cc @@ -90,7 +90,7 @@ void Error(const char* msg, ...) { fprintf(stderr, "\n"); } -bool CanonicalizePath(string* path, unsigned int* slash_bits, string* err) { +bool CanonicalizePath(string* path, uint64_t* slash_bits, string* err) { METRIC_RECORD("canonicalize str"); size_t len = path->size(); char* str = 0; @@ -103,19 +103,19 @@ bool CanonicalizePath(string* path, unsigned int* slash_bits, string* err) { } #ifdef _WIN32 -static unsigned int ShiftOverBit(int offset, unsigned int bits) { +static uint64_t ShiftOverBit(int offset, uint64_t bits) { // e.g. for |offset| == 2: // | ... 9 8 7 6 5 4 3 2 1 0 | // \_________________/ \_/ // above below // So we drop the bit at offset and move above "down" into its place. - unsigned int above = bits & ~((1 << (offset + 1)) - 1); - unsigned int below = bits & ((1 << offset) - 1); + uint64_t above = bits & ~((1 << (offset + 1)) - 1); + uint64_t below = bits & ((1 << offset) - 1); return (above >> 1) | below; } #endif -bool CanonicalizePath(char* path, size_t* len, unsigned int* slash_bits, +bool CanonicalizePath(char* path, size_t* len, uint64_t* slash_bits, string* err) { // WARNING: this function is performance-critical; please benchmark // any changes you make to it. @@ -125,7 +125,7 @@ bool CanonicalizePath(char* path, size_t* len, unsigned int* slash_bits, return false; } - const int kMaxPathComponents = 30; + const int kMaxPathComponents = 60; char* components[kMaxPathComponents]; int component_count = 0; @@ -135,8 +135,8 @@ bool CanonicalizePath(char* path, size_t* len, unsigned int* slash_bits, const char* end = start + *len; #ifdef _WIN32 - unsigned int bits = 0; - unsigned int bits_mask = 1; + uint64_t bits = 0; + uint64_t bits_mask = 1; int bits_offset = 0; // Convert \ to /, setting a bit in |bits| for each \ encountered. for (char* c = path; c < end; ++c) { @@ -150,7 +150,7 @@ bool CanonicalizePath(char* path, size_t* len, unsigned int* slash_bits, bits_offset++; } } - if (bits_offset > 32) { + if (bits_offset > 64) { *err = "too many path components"; return false; } diff --git a/src/util.h b/src/util.h index cbdc1a6..846cd93 100644 --- a/src/util.h +++ b/src/util.h @@ -43,8 +43,8 @@ void Error(const char* msg, ...); /// Canonicalize a path like "foo/../bar.h" into just "bar.h". /// |slash_bits| has bits set starting from lowest for a backslash that was /// normalized to a forward slash. (only used on Windows) -bool CanonicalizePath(string* path, unsigned int* slash_bits, string* err); -bool CanonicalizePath(char* path, size_t* len, unsigned int* slash_bits, +bool CanonicalizePath(string* path, uint64_t* slash_bits, string* err); +bool CanonicalizePath(char* path, size_t* len, uint64_t* slash_bits, string* err); /// Appends |input| to |*result|, escaping according to the whims of either diff --git a/src/util_test.cc b/src/util_test.cc index 33a4107..64c2bbf 100644 --- a/src/util_test.cc +++ b/src/util_test.cc @@ -19,7 +19,7 @@ namespace { bool CanonicalizePath(string* path, string* err) { - unsigned int unused; + uint64_t unused; return ::CanonicalizePath(path, &unused, err); } @@ -177,7 +177,7 @@ TEST(CanonicalizePath, PathSamplesWindows) { TEST(CanonicalizePath, SlashTracking) { string path; string err; - unsigned int slash_bits; + uint64_t slash_bits; path = "foo.h"; err = ""; EXPECT_TRUE(CanonicalizePath(&path, &slash_bits, &err)); @@ -263,7 +263,7 @@ TEST(CanonicalizePath, SlashTracking) { TEST(CanonicalizePath, CanonicalizeNotExceedingLen) { // Make sure searching \/ doesn't go past supplied len. char buf[] = "foo/bar\\baz.h\\"; // Last \ past end. - unsigned int slash_bits; + uint64_t slash_bits; string err; size_t size = 13; EXPECT_TRUE(::CanonicalizePath(buf, &size, &slash_bits, &err)); @@ -274,31 +274,39 @@ TEST(CanonicalizePath, CanonicalizeNotExceedingLen) { TEST(CanonicalizePath, TooManyComponents) { string path; string err; - unsigned int slash_bits; + uint64_t slash_bits; - // 32 is OK. - path = "a/./a/./a/./a/./a/./a/./a/./a/./a/./a/./a/./a/./a/./a/./a/./a/./x.h"; + // 64 is OK. + path = "a/./a/./a/./a/./a/./a/./a/./a/./a/./a/./a/./a/./a/./a/./a/./a/./" + "a/./a/./a/./a/./a/./a/./a/./a/./a/./a/./a/./a/./a/./a/./a/./a/./x.h"; EXPECT_TRUE(CanonicalizePath(&path, &slash_bits, &err)); + EXPECT_EQ(slash_bits, 0x0); // Backslashes version. path = - "a\\.\\a\\.\\a\\.\\a\\.\\a\\.\\a\\.\\a\\.\\a\\.\\a\\.\\a\\.\\a\\.\\a\\." - "\\a\\.\\a\\.\\a\\.\\a\\.\\x.h"; + "a\\.\\a\\.\\a\\.\\a\\.\\a\\.\\a\\.\\a\\.\\a\\.\\" + "a\\.\\a\\.\\a\\.\\a\\.\\a\\.\\a\\.\\a\\.\\a\\.\\" + "a\\.\\a\\.\\a\\.\\a\\.\\a\\.\\a\\.\\a\\.\\a\\.\\" + "a\\.\\a\\.\\a\\.\\a\\.\\a\\.\\a\\.\\a\\.\\a\\.\\x.h"; + EXPECT_TRUE(CanonicalizePath(&path, &slash_bits, &err)); - EXPECT_EQ(slash_bits, 0xffff); + printf("%x\n",slash_bits); + EXPECT_EQ(slash_bits, 0xffffffffLL); - // 33 is not. + // 65 is not. err = ""; - path = - "a/./a/./a/./a/./a/./a/./a/./a/./a/./a/./a/./a/./a/./a/./a/./a/./a/x.h"; + path = "a/./a/./a/./a/./a/./a/./a/./a/./a/./a/./a/./a/./a/./a/./a/./a/./" + "a/./a/./a/./a/./a/./a/./a/./a/./a/./a/./a/./a/./a/./a/./a/./a/./x/y.h"; EXPECT_FALSE(CanonicalizePath(&path, &slash_bits, &err)); EXPECT_EQ(err, "too many path components"); // Backslashes version. err = ""; path = - "a\\.\\a\\.\\a\\.\\a\\.\\a\\.\\a\\.\\a\\.\\a\\.\\a\\.\\a\\.\\a\\.\\a\\." - "\\a\\.\\a\\.\\a\\.\\a\\.\\a\\x.h"; + "a\\.\\a\\.\\a\\.\\a\\.\\a\\.\\a\\.\\a\\.\\a\\.\\" + "a\\.\\a\\.\\a\\.\\a\\.\\a\\.\\a\\.\\a\\.\\a\\.\\" + "a\\.\\a\\.\\a\\.\\a\\.\\a\\.\\a\\.\\a\\.\\a\\.\\" + "a\\.\\a\\.\\a\\.\\a\\.\\a\\.\\a\\.\\a\\.\\a\\.\\x\\y.h"; EXPECT_FALSE(CanonicalizePath(&path, &slash_bits, &err)); EXPECT_EQ(err, "too many path components"); } @@ -326,7 +334,7 @@ TEST(CanonicalizePath, NotNullTerminated) { string path; string err; size_t len; - unsigned int unused; + uint64_t unused; path = "foo/. bar/."; len = strlen("foo/."); // Canonicalize only the part before the space. -- cgit v0.12