From f2f62e295ad1254b7e3cdd5d78fa8afb0e86f1ce Mon Sep 17 00:00:00 2001 From: Brad King Date: Thu, 3 Jun 2021 17:16:20 -0400 Subject: [PATCH 1/2] Add explicit "empty path" errors before calling CanonicalizePath Update call sites that might have empty paths to explicitly check for them before calling CanonicalizePath. Note that the depfile parser ensures all parsed outs and deps are non-empty. --- src/clean.cc | 5 +++++ src/dyndep_parser.cc | 6 ++++++ src/manifest_parser.cc | 6 ++++++ src/ninja.cc | 8 ++++++++ 4 files changed, 25 insertions(+) diff --git a/src/clean.cc b/src/clean.cc index 3e57437..1e97182 100644 --- a/src/clean.cc +++ b/src/clean.cc @@ -189,6 +189,11 @@ int Cleaner::CleanTargets(int target_count, char* targets[]) { LoadDyndeps(); for (int i = 0; i < target_count; ++i) { string target_name = targets[i]; + if (target_name.empty()) { + Error("failed to canonicalize '': empty path"); + status_ = 1; + continue; + } uint64_t slash_bits; string err; if (!CanonicalizePath(&target_name, &slash_bits, &err)) { diff --git a/src/dyndep_parser.cc b/src/dyndep_parser.cc index 56da16f..45d1c31 100644 --- a/src/dyndep_parser.cc +++ b/src/dyndep_parser.cc @@ -115,6 +115,8 @@ bool DyndepParser::ParseEdge(string* err) { return lexer_.Error("expected path", err); string path = out0.Evaluate(&env_); + if (path.empty()) + return lexer_.Error("empty path", err); string path_err; uint64_t slash_bits; if (!CanonicalizePath(&path, &slash_bits, &path_err)) @@ -202,6 +204,8 @@ bool DyndepParser::ParseEdge(string* err) { dyndeps->implicit_inputs_.reserve(ins.size()); for (vector::iterator i = ins.begin(); i != ins.end(); ++i) { string path = i->Evaluate(&env_); + if (path.empty()) + return lexer_.Error("empty path", err); string path_err; uint64_t slash_bits; if (!CanonicalizePath(&path, &slash_bits, &path_err)) @@ -213,6 +217,8 @@ bool DyndepParser::ParseEdge(string* err) { dyndeps->implicit_outputs_.reserve(outs.size()); for (vector::iterator i = outs.begin(); i != outs.end(); ++i) { string path = i->Evaluate(&env_); + if (path.empty()) + return lexer_.Error("empty path", err); string path_err; uint64_t slash_bits; if (!CanonicalizePath(&path, &slash_bits, &path_err)) diff --git a/src/manifest_parser.cc b/src/manifest_parser.cc index f77109f..8f0528a 100644 --- a/src/manifest_parser.cc +++ b/src/manifest_parser.cc @@ -190,6 +190,8 @@ bool ManifestParser::ParseDefault(string* err) { do { string path = eval.Evaluate(env_); + if (path.empty()) + return lexer_.Error("empty path", err); string path_err; uint64_t slash_bits; // Unused because this only does lookup. if (!CanonicalizePath(&path, &slash_bits, &path_err)) @@ -317,6 +319,8 @@ bool ManifestParser::ParseEdge(string* err) { edge->outputs_.reserve(outs.size()); for (size_t i = 0, e = outs.size(); i != e; ++i) { string path = outs[i].Evaluate(env); + if (path.empty()) + return lexer_.Error("empty path", err); string path_err; uint64_t slash_bits; if (!CanonicalizePath(&path, &slash_bits, &path_err)) @@ -349,6 +353,8 @@ bool ManifestParser::ParseEdge(string* err) { edge->inputs_.reserve(ins.size()); for (vector::iterator i = ins.begin(); i != ins.end(); ++i) { string path = i->Evaluate(env); + if (path.empty()) + return lexer_.Error("empty path", err); string path_err; uint64_t slash_bits; if (!CanonicalizePath(&path, &slash_bits, &path_err)) diff --git a/src/ninja.cc b/src/ninja.cc index c7182df..d55290c 100644 --- a/src/ninja.cc +++ b/src/ninja.cc @@ -252,6 +252,10 @@ int GuessParallelism() { bool NinjaMain::RebuildManifest(const char* input_file, string* err, Status* status) { string path = input_file; + if (path.empty()) { + *err = "empty path"; + return false; + } uint64_t slash_bits; // Unused because this path is only used for lookup. if (!CanonicalizePath(&path, &slash_bits, err)) return false; @@ -284,6 +288,10 @@ bool NinjaMain::RebuildManifest(const char* input_file, string* err, Node* NinjaMain::CollectTarget(const char* cpath, string* err) { string path = cpath; + if (path.empty()) { + *err = "empty path"; + return NULL; + } uint64_t slash_bits; if (!CanonicalizePath(&path, &slash_bits, err)) return NULL; From 91706b323fcb2da9a87656d00ebbaf939ed8dad7 Mon Sep 17 00:00:00 2001 From: Brad King Date: Thu, 3 Jun 2021 17:19:05 -0400 Subject: [PATCH 2/2] util: Remove unnecessary CanonicalizePath error handling Since commit 86f606fe (Remove path component limit from input of CanonicalizePath in windows, 2017-08-30, v1.8.0^2~2^2), the only failure case in the `CanonicalizePath` implementation is the "empty path" error. All call sites have been updated to ensure `CanonicalizePath` is never called with an empty path. Remove error handling from the signature to simplify call sites. --- src/build.cc | 4 +- src/canon_perftest.cc | 3 +- src/clean.cc | 21 ++--- src/clparser.cc | 3 +- src/dyndep_parser.cc | 11 +-- src/graph.cc | 12 +-- src/includes_normalize-win32.cc | 3 +- src/manifest_parser.cc | 20 ++--- src/missing_deps.cc | 4 +- src/ninja.cc | 6 +- src/util.cc | 13 +-- src/util.h | 6 +- src/util_test.cc | 148 +++++++++++++++----------------- 13 files changed, 103 insertions(+), 151 deletions(-) diff --git a/src/build.cc b/src/build.cc index fb5890a..cf07846 100644 --- a/src/build.cc +++ b/src/build.cc @@ -878,9 +878,7 @@ bool Builder::ExtractDeps(CommandRunner::Result* result, for (vector::iterator i = deps.ins_.begin(); i != deps.ins_.end(); ++i) { uint64_t slash_bits; - if (!CanonicalizePath(const_cast(i->str_), &i->len_, &slash_bits, - err)) - return false; + CanonicalizePath(const_cast(i->str_), &i->len_, &slash_bits); deps_nodes->push_back(state_->GetNode(*i, slash_bits)); } diff --git a/src/canon_perftest.cc b/src/canon_perftest.cc index 088bd45..6b5e382 100644 --- a/src/canon_perftest.cc +++ b/src/canon_perftest.cc @@ -26,7 +26,6 @@ const char kPath[] = int main() { vector times; - string err; char buf[200]; size_t len = strlen(kPath); @@ -37,7 +36,7 @@ int main() { int64_t start = GetTimeMillis(); uint64_t slash_bits; for (int i = 0; i < kNumRepetitions; ++i) { - CanonicalizePath(buf, &len, &slash_bits, &err); + CanonicalizePath(buf, &len, &slash_bits); } int delta = (int)(GetTimeMillis() - start); times.push_back(delta); diff --git a/src/clean.cc b/src/clean.cc index 1e97182..72dee1f 100644 --- a/src/clean.cc +++ b/src/clean.cc @@ -195,20 +195,15 @@ int Cleaner::CleanTargets(int target_count, char* targets[]) { continue; } uint64_t slash_bits; - string err; - if (!CanonicalizePath(&target_name, &slash_bits, &err)) { - Error("failed to canonicalize '%s': %s", target_name.c_str(), err.c_str()); - status_ = 1; + CanonicalizePath(&target_name, &slash_bits); + Node* target = state_->LookupNode(target_name); + if (target) { + if (IsVerbose()) + printf("Target %s\n", target_name.c_str()); + DoCleanTarget(target); } else { - Node* target = state_->LookupNode(target_name); - if (target) { - if (IsVerbose()) - printf("Target %s\n", target_name.c_str()); - DoCleanTarget(target); - } else { - Error("unknown target '%s'", target_name.c_str()); - status_ = 1; - } + Error("unknown target '%s'", target_name.c_str()); + status_ = 1; } } PrintFooter(); diff --git a/src/clparser.cc b/src/clparser.cc index 275641e..40e9407 100644 --- a/src/clparser.cc +++ b/src/clparser.cc @@ -103,8 +103,7 @@ bool CLParser::Parse(const string& output, const string& deps_prefix, // TODO: should this make the path relative to cwd? normalized = include; uint64_t slash_bits; - if (!CanonicalizePath(&normalized, &slash_bits, err)) - return false; + CanonicalizePath(&normalized, &slash_bits); #endif if (!IsSystemInclude(normalized)) includes_.insert(normalized); diff --git a/src/dyndep_parser.cc b/src/dyndep_parser.cc index 45d1c31..1b4dddd 100644 --- a/src/dyndep_parser.cc +++ b/src/dyndep_parser.cc @@ -117,10 +117,8 @@ bool DyndepParser::ParseEdge(string* err) { string path = out0.Evaluate(&env_); if (path.empty()) return lexer_.Error("empty path", err); - string path_err; uint64_t slash_bits; - if (!CanonicalizePath(&path, &slash_bits, &path_err)) - return lexer_.Error(path_err, err); + CanonicalizePath(&path, &slash_bits); Node* node = state_->LookupNode(path); if (!node || !node->in_edge()) return lexer_.Error("no build statement exists for '" + path + "'", err); @@ -206,10 +204,8 @@ bool DyndepParser::ParseEdge(string* err) { string path = i->Evaluate(&env_); if (path.empty()) return lexer_.Error("empty path", err); - string path_err; uint64_t slash_bits; - if (!CanonicalizePath(&path, &slash_bits, &path_err)) - return lexer_.Error(path_err, err); + CanonicalizePath(&path, &slash_bits); Node* n = state_->GetNode(path, slash_bits); dyndeps->implicit_inputs_.push_back(n); } @@ -221,8 +217,7 @@ bool DyndepParser::ParseEdge(string* err) { return lexer_.Error("empty path", err); string path_err; uint64_t slash_bits; - if (!CanonicalizePath(&path, &slash_bits, &path_err)) - return lexer_.Error(path_err, err); + CanonicalizePath(&path, &slash_bits); Node* n = state_->GetNode(path, slash_bits); dyndeps->implicit_outputs_.push_back(n); } diff --git a/src/graph.cc b/src/graph.cc index 822b7c5..c142f0c 100644 --- a/src/graph.cc +++ b/src/graph.cc @@ -562,11 +562,8 @@ bool ImplicitDepLoader::LoadDepFile(Edge* edge, const string& path, uint64_t unused; std::vector::iterator primary_out = depfile.outs_.begin(); - if (!CanonicalizePath(const_cast(primary_out->str_), - &primary_out->len_, &unused, err)) { - *err = path + ": " + *err; - return false; - } + CanonicalizePath(const_cast(primary_out->str_), &primary_out->len_, + &unused); // Check that this depfile matches the edge's output, if not return false to // mark the edge as dirty. @@ -601,10 +598,7 @@ bool ImplicitDepLoader::ProcessDepfileDeps( for (std::vector::iterator i = depfile_ins->begin(); i != depfile_ins->end(); ++i, ++implicit_dep) { uint64_t slash_bits; - if (!CanonicalizePath(const_cast(i->str_), &i->len_, &slash_bits, - err)) - return false; - + CanonicalizePath(const_cast(i->str_), &i->len_, &slash_bits); Node* node = state_->GetNode(*i, slash_bits); *implicit_dep = node; node->AddOutEdge(edge); diff --git a/src/includes_normalize-win32.cc b/src/includes_normalize-win32.cc index 9f8dfc2..5d52943 100644 --- a/src/includes_normalize-win32.cc +++ b/src/includes_normalize-win32.cc @@ -191,8 +191,7 @@ bool IncludesNormalize::Normalize(const string& input, } strncpy(copy, input.c_str(), input.size() + 1); uint64_t slash_bits; - if (!CanonicalizePath(copy, &len, &slash_bits, err)) - return false; + CanonicalizePath(copy, &len, &slash_bits); StringPiece partially_fixed(copy, len); string abs_input = AbsPath(partially_fixed, err); if (!err->empty()) diff --git a/src/manifest_parser.cc b/src/manifest_parser.cc index 8f0528a..521edb4 100644 --- a/src/manifest_parser.cc +++ b/src/manifest_parser.cc @@ -192,12 +192,11 @@ bool ManifestParser::ParseDefault(string* err) { string path = eval.Evaluate(env_); if (path.empty()) return lexer_.Error("empty path", err); - string path_err; 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)) - return lexer_.Error(path_err, err); + CanonicalizePath(&path, &slash_bits); + std::string default_err; + if (!state_->AddDefault(path, &default_err)) + return lexer_.Error(default_err, err); eval.Clear(); if (!lexer_.ReadPath(&eval, err)) @@ -321,10 +320,8 @@ bool ManifestParser::ParseEdge(string* err) { string path = outs[i].Evaluate(env); if (path.empty()) return lexer_.Error("empty path", err); - string path_err; uint64_t slash_bits; - if (!CanonicalizePath(&path, &slash_bits, &path_err)) - return lexer_.Error(path_err, err); + CanonicalizePath(&path, &slash_bits); if (!state_->AddOut(edge, path, slash_bits)) { if (options_.dupe_edge_action_ == kDupeEdgeActionError) { lexer_.Error("multiple rules generate " + path, err); @@ -355,10 +352,8 @@ bool ManifestParser::ParseEdge(string* err) { string path = i->Evaluate(env); if (path.empty()) return lexer_.Error("empty path", err); - string path_err; uint64_t slash_bits; - if (!CanonicalizePath(&path, &slash_bits, &path_err)) - return lexer_.Error(path_err, err); + CanonicalizePath(&path, &slash_bits); state_->AddIn(edge, path, slash_bits); } edge->implicit_deps_ = implicit; @@ -389,8 +384,7 @@ bool ManifestParser::ParseEdge(string* err) { string dyndep = edge->GetUnescapedDyndep(); if (!dyndep.empty()) { uint64_t slash_bits; - if (!CanonicalizePath(&dyndep, &slash_bits, err)) - return false; + CanonicalizePath(&dyndep, &slash_bits); edge->dyndep_ = state_->GetNode(dyndep, slash_bits); edge->dyndep_->set_dyndep_pending(true); vector::iterator dgi = diff --git a/src/missing_deps.cc b/src/missing_deps.cc index eaa3f73..78feb49 100644 --- a/src/missing_deps.cc +++ b/src/missing_deps.cc @@ -52,9 +52,7 @@ bool NodeStoringImplicitDepLoader::ProcessDepfileDeps( for (std::vector::iterator i = depfile_ins->begin(); i != depfile_ins->end(); ++i) { uint64_t slash_bits; - if (!CanonicalizePath(const_cast(i->str_), &i->len_, &slash_bits, - err)) - return false; + CanonicalizePath(const_cast(i->str_), &i->len_, &slash_bits); Node* node = state_->GetNode(*i, slash_bits); dep_nodes_output_->push_back(node); } diff --git a/src/ninja.cc b/src/ninja.cc index d55290c..32cf00e 100644 --- a/src/ninja.cc +++ b/src/ninja.cc @@ -257,8 +257,7 @@ bool NinjaMain::RebuildManifest(const char* input_file, string* err, return false; } uint64_t slash_bits; // Unused because this path is only used for lookup. - if (!CanonicalizePath(&path, &slash_bits, err)) - return false; + CanonicalizePath(&path, &slash_bits); Node* node = state_.LookupNode(path); if (!node) return false; @@ -293,8 +292,7 @@ Node* NinjaMain::CollectTarget(const char* cpath, string* err) { return NULL; } uint64_t slash_bits; - if (!CanonicalizePath(&path, &slash_bits, err)) - return NULL; + CanonicalizePath(&path, &slash_bits); // Special syntax: "foo.cc^" means "the first output of foo.cc". bool first_dependent = false; diff --git a/src/util.cc b/src/util.cc index b40a636..46a948d 100644 --- a/src/util.cc +++ b/src/util.cc @@ -117,16 +117,14 @@ void Info(const char* msg, ...) { va_end(ap); } -bool CanonicalizePath(string* path, uint64_t* slash_bits, string* err) { +void CanonicalizePath(string* path, uint64_t* slash_bits) { METRIC_RECORD("canonicalize str"); size_t len = path->size(); char* str = 0; if (len > 0) str = &(*path)[0]; - if (!CanonicalizePath(str, &len, slash_bits, err)) - return false; + CanonicalizePath(str, &len, slash_bits); path->resize(len); - return true; } static bool IsPathSeparator(char c) { @@ -137,14 +135,12 @@ static bool IsPathSeparator(char c) { #endif } -bool CanonicalizePath(char* path, size_t* len, uint64_t* slash_bits, - string* err) { +void CanonicalizePath(char* path, size_t* len, uint64_t* slash_bits) { // WARNING: this function is performance-critical; please benchmark // any changes you make to it. METRIC_RECORD("canonicalize path"); if (*len == 0) { - *err = "empty path"; - return false; + return; } const int kMaxPathComponents = 60; @@ -234,7 +230,6 @@ bool CanonicalizePath(char* path, size_t* len, uint64_t* slash_bits, #else *slash_bits = 0; #endif - return true; } static inline bool IsKnownShellSafeCharacter(char ch) { diff --git a/src/util.h b/src/util.h index 15414e1..4a7fea2 100644 --- a/src/util.h +++ b/src/util.h @@ -64,10 +64,8 @@ void Info(const char* msg, va_list ap); /// 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(std::string* path, uint64_t* slash_bits, - std::string* err); -bool CanonicalizePath(char* path, size_t* len, uint64_t* slash_bits, - std::string* err); +void CanonicalizePath(std::string* path, uint64_t* slash_bits); +void CanonicalizePath(char* path, size_t* len, uint64_t* slash_bits); /// Appends |input| to |*result|, escaping according to the whims of either /// Bash, or Win32's CommandLineToArgvW(). diff --git a/src/util_test.cc b/src/util_test.cc index 1621c91..d58b170 100644 --- a/src/util_test.cc +++ b/src/util_test.cc @@ -20,70 +20,69 @@ using namespace std; namespace { -bool CanonicalizePath(string* path, string* err) { +void CanonicalizePath(string* path) { uint64_t unused; - return ::CanonicalizePath(path, &unused, err); + ::CanonicalizePath(path, &unused); } } // namespace TEST(CanonicalizePath, PathSamples) { string path; - string err; - EXPECT_FALSE(CanonicalizePath(&path, &err)); - EXPECT_EQ("empty path", err); + CanonicalizePath(&path); + EXPECT_EQ("", path); - path = "foo.h"; err = ""; - EXPECT_TRUE(CanonicalizePath(&path, &err)); + path = "foo.h"; + CanonicalizePath(&path); EXPECT_EQ("foo.h", path); path = "./foo.h"; - EXPECT_TRUE(CanonicalizePath(&path, &err)); + CanonicalizePath(&path); EXPECT_EQ("foo.h", path); path = "./foo/./bar.h"; - EXPECT_TRUE(CanonicalizePath(&path, &err)); + CanonicalizePath(&path); EXPECT_EQ("foo/bar.h", path); path = "./x/foo/../bar.h"; - EXPECT_TRUE(CanonicalizePath(&path, &err)); + CanonicalizePath(&path); EXPECT_EQ("x/bar.h", path); path = "./x/foo/../../bar.h"; - EXPECT_TRUE(CanonicalizePath(&path, &err)); + CanonicalizePath(&path); EXPECT_EQ("bar.h", path); path = "foo//bar"; - EXPECT_TRUE(CanonicalizePath(&path, &err)); + CanonicalizePath(&path); EXPECT_EQ("foo/bar", path); path = "foo//.//..///bar"; - EXPECT_TRUE(CanonicalizePath(&path, &err)); + CanonicalizePath(&path); EXPECT_EQ("bar", path); path = "./x/../foo/../../bar.h"; - EXPECT_TRUE(CanonicalizePath(&path, &err)); + CanonicalizePath(&path); EXPECT_EQ("../bar.h", path); path = "foo/./."; - EXPECT_TRUE(CanonicalizePath(&path, &err)); + CanonicalizePath(&path); EXPECT_EQ("foo", path); path = "foo/bar/.."; - EXPECT_TRUE(CanonicalizePath(&path, &err)); + CanonicalizePath(&path); EXPECT_EQ("foo", path); path = "foo/.hidden_bar"; - EXPECT_TRUE(CanonicalizePath(&path, &err)); + CanonicalizePath(&path); EXPECT_EQ("foo/.hidden_bar", path); path = "/foo"; - EXPECT_TRUE(CanonicalizePath(&path, &err)); + CanonicalizePath(&path); EXPECT_EQ("/foo", path); path = "//foo"; - EXPECT_TRUE(CanonicalizePath(&path, &err)); + CanonicalizePath(&path); #ifdef _WIN32 EXPECT_EQ("//foo", path); #else @@ -91,173 +90,171 @@ TEST(CanonicalizePath, PathSamples) { #endif path = "/"; - EXPECT_TRUE(CanonicalizePath(&path, &err)); + CanonicalizePath(&path); EXPECT_EQ("", path); path = "/foo/.."; - EXPECT_TRUE(CanonicalizePath(&path, &err)); + CanonicalizePath(&path); EXPECT_EQ("", path); path = "."; - EXPECT_TRUE(CanonicalizePath(&path, &err)); + CanonicalizePath(&path); EXPECT_EQ(".", path); path = "./."; - EXPECT_TRUE(CanonicalizePath(&path, &err)); + CanonicalizePath(&path); EXPECT_EQ(".", path); path = "foo/.."; - EXPECT_TRUE(CanonicalizePath(&path, &err)); + CanonicalizePath(&path); EXPECT_EQ(".", path); } #ifdef _WIN32 TEST(CanonicalizePath, PathSamplesWindows) { string path; - string err; - EXPECT_FALSE(CanonicalizePath(&path, &err)); - EXPECT_EQ("empty path", err); + CanonicalizePath(&path); + EXPECT_EQ("", path); - path = "foo.h"; err = ""; - EXPECT_TRUE(CanonicalizePath(&path, &err)); + path = "foo.h"; + CanonicalizePath(&path); EXPECT_EQ("foo.h", path); path = ".\\foo.h"; - EXPECT_TRUE(CanonicalizePath(&path, &err)); + CanonicalizePath(&path); EXPECT_EQ("foo.h", path); path = ".\\foo\\.\\bar.h"; - EXPECT_TRUE(CanonicalizePath(&path, &err)); + CanonicalizePath(&path); EXPECT_EQ("foo/bar.h", path); path = ".\\x\\foo\\..\\bar.h"; - EXPECT_TRUE(CanonicalizePath(&path, &err)); + CanonicalizePath(&path); EXPECT_EQ("x/bar.h", path); path = ".\\x\\foo\\..\\..\\bar.h"; - EXPECT_TRUE(CanonicalizePath(&path, &err)); + CanonicalizePath(&path); EXPECT_EQ("bar.h", path); path = "foo\\\\bar"; - EXPECT_TRUE(CanonicalizePath(&path, &err)); + CanonicalizePath(&path); EXPECT_EQ("foo/bar", path); path = "foo\\\\.\\\\..\\\\\\bar"; - EXPECT_TRUE(CanonicalizePath(&path, &err)); + CanonicalizePath(&path); EXPECT_EQ("bar", path); path = ".\\x\\..\\foo\\..\\..\\bar.h"; - EXPECT_TRUE(CanonicalizePath(&path, &err)); + CanonicalizePath(&path); EXPECT_EQ("../bar.h", path); path = "foo\\.\\."; - EXPECT_TRUE(CanonicalizePath(&path, &err)); + CanonicalizePath(&path); EXPECT_EQ("foo", path); path = "foo\\bar\\.."; - EXPECT_TRUE(CanonicalizePath(&path, &err)); + CanonicalizePath(&path); EXPECT_EQ("foo", path); path = "foo\\.hidden_bar"; - EXPECT_TRUE(CanonicalizePath(&path, &err)); + CanonicalizePath(&path); EXPECT_EQ("foo/.hidden_bar", path); path = "\\foo"; - EXPECT_TRUE(CanonicalizePath(&path, &err)); + CanonicalizePath(&path); EXPECT_EQ("/foo", path); path = "\\\\foo"; - EXPECT_TRUE(CanonicalizePath(&path, &err)); + CanonicalizePath(&path); EXPECT_EQ("//foo", path); path = "\\"; - EXPECT_TRUE(CanonicalizePath(&path, &err)); + CanonicalizePath(&path); EXPECT_EQ("", path); } TEST(CanonicalizePath, SlashTracking) { string path; - string err; uint64_t slash_bits; - path = "foo.h"; err = ""; - EXPECT_TRUE(CanonicalizePath(&path, &slash_bits, &err)); + path = "foo.h"; + CanonicalizePath(&path, &slash_bits); EXPECT_EQ("foo.h", path); EXPECT_EQ(0, slash_bits); path = "a\\foo.h"; - EXPECT_TRUE(CanonicalizePath(&path, &slash_bits, &err)); + CanonicalizePath(&path, &slash_bits); EXPECT_EQ("a/foo.h", path); EXPECT_EQ(1, slash_bits); path = "a/bcd/efh\\foo.h"; - EXPECT_TRUE(CanonicalizePath(&path, &slash_bits, &err)); + CanonicalizePath(&path, &slash_bits); EXPECT_EQ("a/bcd/efh/foo.h", path); EXPECT_EQ(4, slash_bits); path = "a\\bcd/efh\\foo.h"; - EXPECT_TRUE(CanonicalizePath(&path, &slash_bits, &err)); + CanonicalizePath(&path, &slash_bits); EXPECT_EQ("a/bcd/efh/foo.h", path); EXPECT_EQ(5, slash_bits); path = "a\\bcd\\efh\\foo.h"; - EXPECT_TRUE(CanonicalizePath(&path, &slash_bits, &err)); + CanonicalizePath(&path, &slash_bits); EXPECT_EQ("a/bcd/efh/foo.h", path); EXPECT_EQ(7, slash_bits); path = "a/bcd/efh/foo.h"; - EXPECT_TRUE(CanonicalizePath(&path, &slash_bits, &err)); + CanonicalizePath(&path, &slash_bits); EXPECT_EQ("a/bcd/efh/foo.h", path); EXPECT_EQ(0, slash_bits); path = "a\\./efh\\foo.h"; - EXPECT_TRUE(CanonicalizePath(&path, &slash_bits, &err)); + CanonicalizePath(&path, &slash_bits); EXPECT_EQ("a/efh/foo.h", path); EXPECT_EQ(3, slash_bits); path = "a\\../efh\\foo.h"; - EXPECT_TRUE(CanonicalizePath(&path, &slash_bits, &err)); + CanonicalizePath(&path, &slash_bits); EXPECT_EQ("efh/foo.h", path); EXPECT_EQ(1, slash_bits); path = "a\\b\\c\\d\\e\\f\\g\\foo.h"; - EXPECT_TRUE(CanonicalizePath(&path, &slash_bits, &err)); + CanonicalizePath(&path, &slash_bits); EXPECT_EQ("a/b/c/d/e/f/g/foo.h", path); EXPECT_EQ(127, slash_bits); path = "a\\b\\c\\..\\..\\..\\g\\foo.h"; - EXPECT_TRUE(CanonicalizePath(&path, &slash_bits, &err)); + CanonicalizePath(&path, &slash_bits); EXPECT_EQ("g/foo.h", path); EXPECT_EQ(1, slash_bits); path = "a\\b/c\\../../..\\g\\foo.h"; - EXPECT_TRUE(CanonicalizePath(&path, &slash_bits, &err)); + CanonicalizePath(&path, &slash_bits); EXPECT_EQ("g/foo.h", path); EXPECT_EQ(1, slash_bits); path = "a\\b/c\\./../..\\g\\foo.h"; - EXPECT_TRUE(CanonicalizePath(&path, &slash_bits, &err)); + CanonicalizePath(&path, &slash_bits); EXPECT_EQ("a/g/foo.h", path); EXPECT_EQ(3, slash_bits); path = "a\\b/c\\./../..\\g/foo.h"; - EXPECT_TRUE(CanonicalizePath(&path, &slash_bits, &err)); + CanonicalizePath(&path, &slash_bits); EXPECT_EQ("a/g/foo.h", path); EXPECT_EQ(1, slash_bits); path = "a\\\\\\foo.h"; - EXPECT_TRUE(CanonicalizePath(&path, &slash_bits, &err)); + CanonicalizePath(&path, &slash_bits); EXPECT_EQ("a/foo.h", path); EXPECT_EQ(1, slash_bits); path = "a/\\\\foo.h"; - EXPECT_TRUE(CanonicalizePath(&path, &slash_bits, &err)); + CanonicalizePath(&path, &slash_bits); EXPECT_EQ("a/foo.h", path); EXPECT_EQ(0, slash_bits); path = "a\\//foo.h"; - EXPECT_TRUE(CanonicalizePath(&path, &slash_bits, &err)); + CanonicalizePath(&path, &slash_bits); EXPECT_EQ("a/foo.h", path); EXPECT_EQ(1, slash_bits); } @@ -266,22 +263,20 @@ TEST(CanonicalizePath, CanonicalizeNotExceedingLen) { // Make sure searching \/ doesn't go past supplied len. char buf[] = "foo/bar\\baz.h\\"; // Last \ past end. uint64_t slash_bits; - string err; size_t size = 13; - EXPECT_TRUE(::CanonicalizePath(buf, &size, &slash_bits, &err)); + ::CanonicalizePath(buf, &size, &slash_bits); EXPECT_EQ(0, strncmp("foo/bar/baz.h", buf, size)); EXPECT_EQ(2, slash_bits); // Not including the trailing one. } TEST(CanonicalizePath, TooManyComponents) { string path; - string err; uint64_t slash_bits; // 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)); + CanonicalizePath(&path, &slash_bits); EXPECT_EQ(slash_bits, 0x0); // Backslashes version. @@ -291,44 +286,40 @@ TEST(CanonicalizePath, TooManyComponents) { "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)); + CanonicalizePath(&path, &slash_bits); EXPECT_EQ(slash_bits, 0xffffffff); // 65 is OK if #component is less than 60 after path canonicalization. - err = ""; 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_TRUE(CanonicalizePath(&path, &slash_bits, &err)); + CanonicalizePath(&path, &slash_bits); EXPECT_EQ(slash_bits, 0x0); // Backslashes version. - err = ""; 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_TRUE(CanonicalizePath(&path, &slash_bits, &err)); + CanonicalizePath(&path, &slash_bits); EXPECT_EQ(slash_bits, 0x1ffffffff); // 59 after canonicalization is OK. - err = ""; 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/" "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_EQ(58, std::count(path.begin(), path.end(), '/')); - EXPECT_TRUE(CanonicalizePath(&path, &slash_bits, &err)); + CanonicalizePath(&path, &slash_bits); EXPECT_EQ(slash_bits, 0x0); // Backslashes version. - err = ""; 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\\" "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_EQ(58, std::count(path.begin(), path.end(), '\\')); - EXPECT_TRUE(CanonicalizePath(&path, &slash_bits, &err)); + CanonicalizePath(&path, &slash_bits); EXPECT_EQ(slash_bits, 0x3ffffffffffffff); } #endif @@ -336,36 +327,35 @@ TEST(CanonicalizePath, TooManyComponents) { TEST(CanonicalizePath, UpDir) { string path, err; path = "../../foo/bar.h"; - EXPECT_TRUE(CanonicalizePath(&path, &err)); + CanonicalizePath(&path); EXPECT_EQ("../../foo/bar.h", path); path = "test/../../foo/bar.h"; - EXPECT_TRUE(CanonicalizePath(&path, &err)); + CanonicalizePath(&path); EXPECT_EQ("../foo/bar.h", path); } TEST(CanonicalizePath, AbsolutePath) { string path = "/usr/include/stdio.h"; string err; - EXPECT_TRUE(CanonicalizePath(&path, &err)); + CanonicalizePath(&path); EXPECT_EQ("/usr/include/stdio.h", path); } TEST(CanonicalizePath, NotNullTerminated) { string path; - string err; size_t len; uint64_t unused; path = "foo/. bar/."; len = strlen("foo/."); // Canonicalize only the part before the space. - EXPECT_TRUE(CanonicalizePath(&path[0], &len, &unused, &err)); + CanonicalizePath(&path[0], &len, &unused); EXPECT_EQ(strlen("foo"), len); EXPECT_EQ("foo/. bar/.", string(path)); path = "foo/../file bar/."; len = strlen("foo/../file"); - EXPECT_TRUE(CanonicalizePath(&path[0], &len, &unused, &err)); + CanonicalizePath(&path[0], &len, &unused); EXPECT_EQ(strlen("file"), len); EXPECT_EQ("file ./file bar/.", string(path)); }