diff options
author | Dan Willemsen <dwillemsen@google.com> | 2018-02-12 18:16:35 -0800 |
---|---|---|
committer | Dan Willemsen <dwillemsen@google.com> | 2018-02-13 14:26:58 -0800 |
commit | 1e0159219d2172f6b68d8625d54f592d5b46bc04 (patch) | |
tree | 2a82ba6f5a3826685a7761082cbcf90673e472ba | |
parent | 054627c9ee92e6b0ef87e5ff3479b457d0c78bbe (diff) | |
download | kati-1e0159219d2172f6b68d8625d54f592d5b46bc04.tar.gz |
Fail find parsing for \*
Android hit a few cases where we were searching for *.pyc or
verifiedboot*, and escaping the * as \*. In most cases the entire
argument was just quoted instead.
Kati understands and handles the quotes just fine, but it didn't realize
that \* was special, so it was searching for files that started with a
literal '\'.
We have no good way of freeing allocated memory in the find parser, so
just support stripping a leading \ (\*.pyc works, along with '\('), and
fall back to the system find if another \ is found in a token.
-rw-r--r-- | find.cc | 24 | ||||
-rw-r--r-- | find_test.cc | 17 |
2 files changed, 34 insertions, 7 deletions
@@ -449,6 +449,16 @@ class FindCommandParser { return false; *tok = tok->substr(1, tok->size() - 2); return true; + } else { + // Support stripping off a leading backslash + if (c == '\\') { + *tok = tok->substr(1); + } + // But if there are any others, we can't support it, as unescaping would + // require allocation + if (tok->find("\\") != string::npos) { + return false; + } } return true; @@ -473,18 +483,18 @@ class FindCommandParser { } FindCond* ParseFact(StringPiece tok) { - if (tok == "-not" || tok == "\\!") { + if (tok == "-not" || tok == "!") { if (!GetNextToken(&tok) || tok.empty()) return NULL; unique_ptr<FindCond> c(ParseFact(tok)); if (!c.get()) return NULL; return new NotCond(c.release()); - } else if (tok == "\\(") { + } else if (tok == "(") { if (!GetNextToken(&tok) || tok.empty()) return NULL; unique_ptr<FindCond> c(ParseExpr(tok)); - if (!GetNextToken(&tok) || tok != "\\)") { + if (!GetNextToken(&tok) || tok != ")") { return NULL; } return c.release(); @@ -530,7 +540,7 @@ class FindCommandParser { if (!GetNextToken(&tok) || tok.empty()) return NULL; } else { - if (tok != "-not" && tok != "\\!" && tok != "\\(" && tok != "-name" && + if (tok != "-not" && tok != "!" && tok != "(" && tok != "-name" && tok != "-type") { UngetToken(tok); return c.release(); @@ -567,8 +577,8 @@ class FindCommandParser { // <expr> ::= <term> {<or> <term>} // <term> ::= <fact> {[<and>] <fact>} - // <fact> ::= <not> <fact> | '\(' <expr> '\)' | <pred> - // <not> ::= '-not' | '\!' + // <fact> ::= <not> <fact> | '(' <expr> ')' | <pred> + // <not> ::= '-not' | '!' // <and> ::= '-and' | '-a' // <or> ::= '-or' | '-o' // <pred> ::= <name> | <type> | <maxdepth> @@ -609,7 +619,7 @@ class FindCommandParser { return false; } fc_->depth = d; - } else if (tok[0] == '-' || tok == "\\(") { + } else if (tok[0] == '-' || tok == "(" || tok == "!") { if (fc_->print_cond.get()) return false; FindCond* c = ParseFindCond(tok); diff --git a/find_test.cc b/find_test.cc index 10f865c..d7d44bd 100644 --- a/find_test.cc +++ b/find_test.cc @@ -107,6 +107,17 @@ void CompareFind(const string& cmd) { } } +void ExpectParseFailure(const string& cmd) { + Run(cmd); + + FindCommand fc; + if (fc.Parse(cmd)) { + fprintf(stderr, "Expected parse failure for `%s`\n", cmd.c_str()); + fprintf(stderr, "------------------------------------------\n"); + unit_test_failed = true; + } +} + int FindUnitTests() { Run("rm -rf out/find"); Run("mkdir -p out/find"); @@ -149,5 +160,11 @@ int FindUnitTests() { CompareFind("find .//top"); + CompareFind("find top -type f -name 'a*' -o -name \\*b"); + CompareFind("find top \\! -name 'a*'"); + CompareFind("find top \\( -name 'a*' \\)"); + + ExpectParseFailure("find top -name a\\*"); + return unit_test_failed ? 1 : 0; } |