parse_xml.cpp: Deserilization does not touch lastError()
The global mLastError fields for each converters can
potentially cause a segfault when a program with multiple
threads tries to deserialize a bad file at the same time.
- deserialization APIs that touches the mLastError field are
marked as non-const APIs
- const variants are provided (error is provided as an output
parameter)
- Functionalities are equivalent (tests ensure this).
Test: libvintf_test
Test: vintf_object_test
Fixes: 71874788
Change-Id: I416de909b32809a4ac377d9da998c48d7d409457
diff --git a/AssembleVintf.cpp b/AssembleVintf.cpp
index 96e8537..39bdd3a 100644
--- a/AssembleVintf.cpp
+++ b/AssembleVintf.cpp
@@ -337,9 +337,9 @@
if (mCheckFile != nullptr) {
CompatibilityMatrix checkMatrix;
- if (!gCompatibilityMatrixConverter(&checkMatrix, read(*mCheckFile))) {
- std::cerr << "Cannot parse check file as a compatibility matrix: "
- << gCompatibilityMatrixConverter.lastError() << std::endl;
+ if (!gCompatibilityMatrixConverter(&checkMatrix, read(*mCheckFile), &error)) {
+ std::cerr << "Cannot parse check file as a compatibility matrix: " << error
+ << std::endl;
return false;
}
if (!halManifest->checkCompatibility(checkMatrix, &error)) {
@@ -443,9 +443,9 @@
Level deviceLevel = Level::UNSPECIFIED;
if (mCheckFile != nullptr) {
checkManifest = std::make_unique<HalManifest>();
- if (!gHalManifestConverter(checkManifest.get(), read(*mCheckFile))) {
- std::cerr << "Cannot parse check file as a HAL manifest: "
- << gHalManifestConverter.lastError() << std::endl;
+ if (!gHalManifestConverter(checkManifest.get(), read(*mCheckFile), &error)) {
+ std::cerr << "Cannot parse check file as a HAL manifest: " << error
+ << std::endl;
return false;
}
deviceLevel = checkManifest->level();
@@ -525,10 +525,10 @@
enum AssembleStatus { SUCCESS, FAIL_AND_EXIT, TRY_NEXT };
template <typename Schema, typename AssembleFunc>
AssembleStatus tryAssemble(const XmlConverter<Schema>& converter, const std::string& schemaName,
- AssembleFunc assemble) {
+ AssembleFunc assemble, std::string* error) {
Schemas<Schema> schemas;
Schema schema;
- if (!converter(&schema, read(mInFiles.front().stream()))) {
+ if (!converter(&schema, read(mInFiles.front().stream()), error)) {
return TRY_NEXT;
}
auto firstType = schema.type();
@@ -537,10 +537,10 @@
for (auto it = mInFiles.begin() + 1; it != mInFiles.end(); ++it) {
Schema additionalSchema;
const std::string& fileName = it->name();
- if (!converter(&additionalSchema, read(it->stream()))) {
+ if (!converter(&additionalSchema, read(it->stream()), error)) {
std::cerr << "File \"" << fileName << "\" is not a valid " << firstType << " "
<< schemaName << " (but the first file is a valid " << firstType << " "
- << schemaName << "). Error: " << converter.lastError() << std::endl;
+ << schemaName << "). Error: " << *error << std::endl;
return FAIL_AND_EXIT;
}
if (additionalSchema.type() != firstType) {
@@ -562,23 +562,26 @@
return false;
}
+ std::string manifestError;
auto status = tryAssemble(gHalManifestConverter, "manifest",
- std::bind(&AssembleVintfImpl::assembleHalManifest, this, _1));
+ std::bind(&AssembleVintfImpl::assembleHalManifest, this, _1),
+ &manifestError);
if (status == SUCCESS) return true;
if (status == FAIL_AND_EXIT) return false;
resetInFiles();
+ std::string matrixError;
status = tryAssemble(gCompatibilityMatrixConverter, "compatibility matrix",
- std::bind(&AssembleVintfImpl::assembleCompatibilityMatrix, this, _1));
+ std::bind(&AssembleVintfImpl::assembleCompatibilityMatrix, this, _1),
+ &matrixError);
if (status == SUCCESS) return true;
if (status == FAIL_AND_EXIT) return false;
std::cerr << "Input file has unknown format." << std::endl
- << "Error when attempting to convert to manifest: "
- << gHalManifestConverter.lastError() << std::endl
- << "Error when attempting to convert to compatibility matrix: "
- << gCompatibilityMatrixConverter.lastError() << std::endl;
+ << "Error when attempting to convert to manifest: " << manifestError << std::endl
+ << "Error when attempting to convert to compatibility matrix: " << matrixError
+ << std::endl;
return false;
}