aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDan Willemsen <dwillemsen@google.com>2018-02-12 18:16:35 -0800
committerDan Willemsen <dwillemsen@google.com>2018-02-13 14:26:58 -0800
commit1e0159219d2172f6b68d8625d54f592d5b46bc04 (patch)
tree2a82ba6f5a3826685a7761082cbcf90673e472ba
parent054627c9ee92e6b0ef87e5ff3479b457d0c78bbe (diff)
downloadkati-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.cc24
-rw-r--r--find_test.cc17
2 files changed, 34 insertions, 7 deletions
diff --git a/find.cc b/find.cc
index 1bf0b9e..a31adce 100644
--- a/find.cc
+++ b/find.cc
@@ -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;
}