in xar/XarParser.cpp [105:163]
std::optional<XarParserError> parseLine(
const std::string& line,
XarHeader* xarHeader,
std::set<std::string>* foundNames) {
// Split line into up to 2 parts
auto nameValue = tools::xar::split(/* delim */ '=', line, /* nsplits */ 1);
if (nameValue.size() != 2) {
return XarParserError(XarParserErrorType::MALFORMED_LINE, line);
}
const std::string name = std::move(nameValue[0]);
const std::string wrappedValue = std::move(nameValue[1]);
if (name.empty() || wrappedValue.size() < 2 || wrappedValue.front() != '"' ||
wrappedValue.back() != '"') {
return XarParserError(XarParserErrorType::MALFORMED_LINE, line);
}
// Skip quotes around value
const std::string value = wrappedValue.substr(1, wrappedValue.size() - 2);
// Check value does not contain '"'
if (value.find('"') != std::string::npos) {
return XarParserError(XarParserErrorType::MALFORMED_LINE, line);
}
if (foundNames->find(name) != foundNames->end()) {
// Variable already set. Though we might be able to ignore this, this is
// probably a bug.
return XarParserError(XarParserErrorType::DUPLICATE_PARAMETER, name);
}
foundNames->emplace(name);
// Set field in header that corresponds to name
if (name == kOffsetName) {
if (auto maybeErrorMsg = parseUll(value, &xarHeader->offset);
!maybeErrorMsg.empty()) {
return XarParserError(XarParserErrorType::INVALID_OFFSET, maybeErrorMsg);
}
// Verify offset is a strictly positive multiple of kHeaderSizeBase
if (xarHeader->offset % kHeaderSizeBase != 0 || xarHeader->offset == 0) {
return XarParserError(
XarParserErrorType::INVALID_OFFSET,
std::to_string(xarHeader->offset) +
" is not a positive multiple of " +
std::to_string(kHeaderSizeBase));
}
} else if (name == kVersion) {
xarHeader->version = value;
} else if (name == kUuidName) {
xarHeader->uuid = value;
} else if (name == kXarexecTarget) {
xarHeader->xarexecTarget = value;
} else if (name == kXarexecTrampolineNames) {
if (auto maybeError =
parseTrampolineNames(value, &xarHeader->xarexecTrampolineNames)) {
return maybeError;
}
} else {
// Unknown parameter or offset (which has already been parsed). Ignore.
}
return {};
}