diff --git a/tests/unit/commands_test.cpp b/tests/unit/commands_test.cpp index bbc83b9a..cb2be917 100644 --- a/tests/unit/commands_test.cpp +++ b/tests/unit/commands_test.cpp @@ -310,3 +310,28 @@ TEST(CommandsTest, Parse_ZERO) { ASSERT_EQ(StashInfo(), command.stash()); ASSERT_EQ(PatchInfo(), command.patch()); } + +TEST(CommandsTest, Parse_InvalidNumberOfArgs) { + // Note that the case of having excess args in BSDIFF, IMGDIFF and MOVE is covered by + // ParseTargetInfoAndSourceInfo_InvalidInput. + std::vector inputs{ + "bsdiff", + "erase", + "erase 4,3,5,10,12 hash1", + "free", + "free id1 id2", + "imgdiff", + "move", + "new", + "new 4,3,5,10,12 hash1", + "stash", + "stash id1", + "stash id1 4,3,5,10,12 id2", + "zero", + "zero 4,3,5,10,12 hash2", + }; + for (const auto& input : inputs) { + std::string err; + ASSERT_FALSE(Command::Parse(input, 0, &err)); + } +} diff --git a/updater/commands.cpp b/updater/commands.cpp index 6d4b5310..fb19ebc9 100644 --- a/updater/commands.cpp +++ b/updater/commands.cpp @@ -54,7 +54,7 @@ bool Command::ParseTargetInfoAndSourceInfo(const std::vector& token const std::string& tgt_hash, TargetInfo* target, const std::string& src_hash, SourceInfo* source, std::string* err) { - // We expect the given tokens parameter in one of the following formats. + // We expect the given args (in 'tokens' vector) in one of the following formats. // // - <[stash_id:location] ...> // (loads data from stashes only) @@ -65,10 +65,9 @@ bool Command::ParseTargetInfoAndSourceInfo(const std::vector& token // <[stash_id:location] ...> // (loads data from both of source image and stashes) - // At least it needs to provide three parameters: , and - // "-"/. + // At least it needs to provide three args: , and "-"/. if (tokens.size() < 3) { - *err = "invalid number of parameters"; + *err = "invalid number of args"; return false; } @@ -170,6 +169,11 @@ Command Command::Parse(const std::string& line, size_t index, std::string* err) if (op == Type::ZERO || op == Type::NEW || op == Type::ERASE) { // zero/new/erase + if (pos + 1 != tokens.size()) { + *err = android::base::StringPrintf("invalid number of args: %zu (expected 1)", + tokens.size() - pos); + return {}; + } RangeSet tgt_ranges = RangeSet::Parse(tokens[pos++]); if (!tgt_ranges) { return {}; @@ -178,8 +182,9 @@ Command Command::Parse(const std::string& line, size_t index, std::string* err) target_info = TargetInfo(kUnknownHash, tgt_ranges); } else if (op == Type::STASH) { // stash - if (pos + 2 > tokens.size()) { - *err = "missing stash id and/or source ranges"; + if (pos + 2 != tokens.size()) { + *err = android::base::StringPrintf("invalid number of args: %zu (expected 2)", + tokens.size() - pos); return {}; } const std::string& id = tokens[pos++]; @@ -191,8 +196,9 @@ Command Command::Parse(const std::string& line, size_t index, std::string* err) stash_info = StashInfo(id, src_ranges); } else if (op == Type::FREE) { // free - if (pos + 1 > tokens.size()) { - *err = "missing stash id in free command"; + if (pos + 1 != tokens.size()) { + *err = android::base::StringPrintf("invalid number of args: %zu (expected 1)", + tokens.size() - pos); return {}; } stash_info = StashInfo(tokens[pos++], {}); @@ -211,7 +217,8 @@ Command Command::Parse(const std::string& line, size_t index, std::string* err) } else if (op == Type::BSDIFF || op == Type::IMGDIFF) { // if (pos + 4 > tokens.size()) { - *err = "invalid number of tokens"; + *err = android::base::StringPrintf("invalid number of args: %zu (expected 4+)", + tokens.size() - pos); return {}; } size_t offset;