AAPT2: Fail on invalid id names in compiled xml

AAPT2 was not erroring on invalid resource ids created in layouts with
creation syntax. This change causes this to error suring compile.

Bug: 71394154
Test: aapt2_tests
Change-Id: Idf16fb4bd011ed2d65e8c48f7cba0429ead5a055
This commit is contained in:
Ryan Mitchell
2018-09-11 10:41:09 -07:00
parent 342df6ddd1
commit 7984854750
3 changed files with 36 additions and 10 deletions

View File

@@ -133,11 +133,19 @@ class SourcePathDiagnostics : public IDiagnostics {
void Log(Level level, DiagMessageActual& actual_msg) override {
actual_msg.source.path = source_.path;
diag_->Log(level, actual_msg);
if (level == Level::Error) {
error = true;
}
}
bool HadError() {
return error;
}
private:
Source source_;
IDiagnostics* diag_;
bool error = false;
DISALLOW_COPY_AND_ASSIGN(SourcePathDiagnostics);
};

View File

@@ -21,6 +21,7 @@
#include "ResourceUtils.h"
#include "ResourceValues.h"
#include "text/Unicode.h"
#include "xml/XmlDom.h"
namespace aapt {
@@ -35,8 +36,9 @@ struct IdCollector : public xml::Visitor {
public:
using xml::Visitor::Visit;
explicit IdCollector(std::vector<SourcedResourceName>* out_symbols)
: out_symbols_(out_symbols) {}
explicit IdCollector(std::vector<SourcedResourceName>* out_symbols,
SourcePathDiagnostics* source_diag) : out_symbols_(out_symbols),
source_diag_(source_diag) {}
void Visit(xml::Element* element) override {
for (xml::Attribute& attr : element->attributes) {
@@ -44,12 +46,16 @@ struct IdCollector : public xml::Visitor {
bool create = false;
if (ResourceUtils::ParseReference(attr.value, &name, &create, nullptr)) {
if (create && name.type == ResourceType::kId) {
auto iter = std::lower_bound(out_symbols_->begin(),
out_symbols_->end(), name, cmp_name);
if (iter == out_symbols_->end() || iter->name != name) {
out_symbols_->insert(iter,
SourcedResourceName{name.ToResourceName(),
element->line_number});
if (!text::IsValidResourceEntryName(name.entry)) {
source_diag_->Error(DiagMessage(element->line_number)
<< "id '" << name << "' has an invalid entry name");
} else {
auto iter = std::lower_bound(out_symbols_->begin(),
out_symbols_->end(), name, cmp_name);
if (iter == out_symbols_->end() || iter->name != name) {
out_symbols_->insert(iter, SourcedResourceName{name.ToResourceName(),
element->line_number});
}
}
}
}
@@ -60,15 +66,17 @@ struct IdCollector : public xml::Visitor {
private:
std::vector<SourcedResourceName>* out_symbols_;
SourcePathDiagnostics* source_diag_;
};
} // namespace
bool XmlIdCollector::Consume(IAaptContext* context, xml::XmlResource* xmlRes) {
xmlRes->file.exported_symbols.clear();
IdCollector collector(&xmlRes->file.exported_symbols);
SourcePathDiagnostics source_diag(xmlRes->file.source, context->GetDiagnostics());
IdCollector collector(&xmlRes->file.exported_symbols, &source_diag);
xmlRes->root->Accept(&collector);
return true;
return !source_diag.HadError();
}
} // namespace aapt

View File

@@ -64,4 +64,14 @@ TEST(XmlIdCollectorTest, DontCollectNonIds) {
EXPECT_TRUE(doc->file.exported_symbols.empty());
}
TEST(XmlIdCollectorTest, ErrorOnInvalidIds) {
std::unique_ptr<IAaptContext> context = test::ContextBuilder().Build();
std::unique_ptr<xml::XmlResource> doc =
test::BuildXmlDom("<View foo=\"@+id/foo$bar\"/>");
XmlIdCollector collector;
ASSERT_FALSE(collector.Consume(context.get(), doc.get()));
}
} // namespace aapt