Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 79848547 authored by Ryan Mitchell's avatar Ryan Mitchell
Browse files

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
parent 342df6dd
Loading
Loading
Loading
Loading
+8 −0
Original line number Diff line number Diff line
@@ -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);
};
+18 −10
Original line number Diff line number Diff line
@@ -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,31 +46,37 @@ struct IdCollector : public xml::Visitor {
      bool create = false;
      if (ResourceUtils::ParseReference(attr.value, &name, &create, nullptr)) {
        if (create && name.type == ResourceType::kId) {
          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(),
              out_symbols_->insert(iter, SourcedResourceName{name.ToResourceName(),
                                                             element->line_number});
            }
          }
        }
      }
    }

    xml::Visitor::Visit(element);
  }

 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
+10 −0
Original line number Diff line number Diff line
@@ -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