Require 'exact', 'prefix', or '' for match operation in property_contexts

The previous code would lazily check for 'exact' and accept any other
value as a prefix match.  This should be a tighter check allowing only
'exact', 'prefix', or an empty string for this option.

Test: build fails if an invalid string is used for the match operation
Test: build succeeds normally
Test: `getprop -Z` shows exact vs prefix is differentiated correctly
Change-Id: I21dcb193810d65f468f8960967eabfd261f71e21
This commit is contained in:
Tom Cherry 2019-12-11 07:56:51 -08:00
parent 1ccaf2b8ee
commit 4b077c51f2
5 changed files with 22 additions and 13 deletions

View file

@ -191,7 +191,7 @@ void HandlePropertyContexts(const std::string& filename,
}
auto errors = std::vector<std::string>{};
ParsePropertyInfoFile(file_contents, property_infos, &errors);
ParsePropertyInfoFile(file_contents, true, property_infos, &errors);
for (const auto& error : errors) {
LOG(ERROR) << "Could not read line from '" << filename << "': " << error;
}

View file

@ -925,7 +925,8 @@ bool LoadPropertyInfoFromFile(const std::string& filename,
}
auto errors = std::vector<std::string>{};
ParsePropertyInfoFile(file_contents, property_infos, &errors);
bool require_prefix_or_exact = SelinuxGetVendorAndroidVersion() >= __ANDROID_API_R__;
ParsePropertyInfoFile(file_contents, require_prefix_or_exact, property_infos, &errors);
// Individual parsing errors are reported but do not cause a failed boot, which is what
// returning false would do here.
for (const auto& error : errors) {

View file

@ -14,8 +14,7 @@
// limitations under the License.
//
#ifndef PROPERTY_INFO_SERIALIZER_H
#define PROPERTY_INFO_SERIALIZER_H
#pragma once
#include <string>
#include <vector>
@ -41,11 +40,9 @@ bool BuildTrie(const std::vector<PropertyInfoEntry>& property_info,
const std::string& default_context, const std::string& default_type,
std::string* serialized_trie, std::string* error);
void ParsePropertyInfoFile(const std::string& file_contents,
void ParsePropertyInfoFile(const std::string& file_contents, bool require_prefix_or_exact,
std::vector<PropertyInfoEntry>* property_infos,
std::vector<std::string>* errors);
} // namespace properties
} // namespace android
#endif

View file

@ -56,7 +56,8 @@ bool IsTypeValid(const std::vector<std::string>& type_strings) {
return false;
}
bool ParsePropertyInfoLine(const std::string& line, PropertyInfoEntry* out, std::string* error) {
bool ParsePropertyInfoLine(const std::string& line, bool require_prefix_or_exact,
PropertyInfoEntry* out, std::string* error) {
auto tokenizer = SpaceTokenizer(line);
auto property = tokenizer.GetNext();
@ -72,7 +73,7 @@ bool ParsePropertyInfoLine(const std::string& line, PropertyInfoEntry* out, std:
}
// It is not an error to not find exact_match or a type, as older files will not contain them.
auto exact_match = tokenizer.GetNext();
auto match_operation = tokenizer.GetNext();
// We reformat type to be space deliminated regardless of the input whitespace for easier storage
// and subsequent parsing.
auto type_strings = std::vector<std::string>{};
@ -82,18 +83,27 @@ bool ParsePropertyInfoLine(const std::string& line, PropertyInfoEntry* out, std:
type = tokenizer.GetNext();
}
bool exact_match = false;
if (match_operation == "exact") {
exact_match = true;
} else if (match_operation != "prefix" && match_operation != "" && require_prefix_or_exact) {
*error = "Match operation '" + match_operation +
"' is not valid: must be either 'prefix' or 'exact'";
return false;
}
if (!type_strings.empty() && !IsTypeValid(type_strings)) {
*error = "Type '" + Join(type_strings, " ") + "' is not valid";
return false;
}
*out = {property, context, Join(type_strings, " "), exact_match == "exact"};
*out = {property, context, Join(type_strings, " "), exact_match};
return true;
}
} // namespace
void ParsePropertyInfoFile(const std::string& file_contents,
void ParsePropertyInfoFile(const std::string& file_contents, bool require_prefix_or_exact,
std::vector<PropertyInfoEntry>* property_infos,
std::vector<std::string>* errors) {
// Do not clear property_infos to allow this function to be called on multiple files, with
@ -108,7 +118,8 @@ void ParsePropertyInfoFile(const std::string& file_contents,
auto property_info_entry = PropertyInfoEntry{};
auto parse_error = std::string{};
if (!ParsePropertyInfoLine(trimmed_line, &property_info_entry, &parse_error)) {
if (!ParsePropertyInfoLine(trimmed_line, require_prefix_or_exact, &property_info_entry,
&parse_error)) {
errors->emplace_back(parse_error);
continue;
}

View file

@ -153,7 +153,7 @@ int main(int argc, char** argv) {
}
auto errors = std::vector<std::string>{};
ParsePropertyInfoFile(file_contents, &property_info_entries, &errors);
ParsePropertyInfoFile(file_contents, true, &property_info_entries, &errors);
if (!errors.empty()) {
for (const auto& error : errors) {
std::cerr << "Could not read line from '" << filename << "': " << error << std::endl;