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

Commit bbf42979 authored by Adam Lesinski's avatar Adam Lesinski
Browse files

AAPT2: Fix issue with deserializing binary XML

We assumed that a raw text value set for an attribute meant there
were no compiled values set either.

This would only really happen for attributes that did not belong to any
namespace (no prefix:), since we always kept their raw string values
in case some code relied on it.

Bug: 72700446
Test: make aapt2_tests
Change-Id: Icba40a1d4b181bfe7cad73131c4dbe5ba7f8b085
parent da9eba30
Loading
Loading
Loading
Loading
+8 −0
Original line number Diff line number Diff line
@@ -450,7 +450,15 @@ class XmlPrinter : public xml::ConstVisitor {
      if (attr.compiled_value != nullptr) {
        attr.compiled_value->PrettyPrint(printer_);
      } else {
        printer_->Print("\"");
        printer_->Print(attr.value);
        printer_->Print("\"");
      }

      if (!attr.value.empty()) {
        printer_->Print(" (Raw: \"");
        printer_->Print(attr.value);
        printer_->Print("\")");
      }
      printer_->Println();
    }
+1 −0
Original line number Diff line number Diff line
@@ -139,6 +139,7 @@ class BinaryApkSerializer : public IApkSerializer {
    BigBuffer buffer(4096);
    XmlFlattenerOptions options = {};
    options.use_utf16 = utf16;
    options.keep_raw_values = true;
    XmlFlattener flattener(&buffer, options);
    if (!flattener.Consume(context_, xml)) {
      return false;
+6 −6
Original line number Diff line number Diff line
@@ -23,6 +23,7 @@ using ::aapt::test::ValueEq;
using ::testing::Eq;
using ::testing::IsNull;
using ::testing::NotNull;
using ::testing::Pointee;
using ::testing::SizeIs;

namespace aapt {
@@ -287,13 +288,13 @@ TEST_F(XmlCompatVersionerTest, DegradeRuleOverridesExistingAttribute) {
  ASSERT_THAT(attr, NotNull());
  ASSERT_THAT(attr->compiled_value, NotNull());
  ASSERT_TRUE(attr->compiled_attribute);
  ASSERT_THAT(*attr->compiled_value, ValueEq(padding_horizontal_value));
  ASSERT_THAT(attr->compiled_value, Pointee(ValueEq(padding_horizontal_value)));

  attr = el->FindAttribute(xml::kSchemaAndroid, "paddingRight");
  ASSERT_THAT(attr, NotNull());
  ASSERT_THAT(attr->compiled_value, NotNull());
  ASSERT_TRUE(attr->compiled_attribute);
  ASSERT_THAT(*attr->compiled_value, ValueEq(padding_horizontal_value));
  ASSERT_THAT(attr->compiled_value, Pointee(ValueEq(padding_horizontal_value)));

  EXPECT_THAT(versioned_docs[1]->file.config.sdkVersion, Eq(SDK_LOLLIPOP_MR1));
  el = versioned_docs[1]->root.get();
@@ -302,21 +303,20 @@ TEST_F(XmlCompatVersionerTest, DegradeRuleOverridesExistingAttribute) {

  attr = el->FindAttribute(xml::kSchemaAndroid, "paddingHorizontal");
  ASSERT_THAT(attr, NotNull());
  ASSERT_THAT(attr->compiled_value, NotNull());
  ASSERT_TRUE(attr->compiled_attribute);
  ASSERT_THAT(*attr->compiled_value, ValueEq(padding_horizontal_value));
  ASSERT_THAT(attr->compiled_value, Pointee(ValueEq(padding_horizontal_value)));

  attr = el->FindAttribute(xml::kSchemaAndroid, "paddingLeft");
  ASSERT_THAT(attr, NotNull());
  ASSERT_THAT(attr->compiled_value, NotNull());
  ASSERT_TRUE(attr->compiled_attribute);
  ASSERT_THAT(*attr->compiled_value, ValueEq(padding_horizontal_value));
  ASSERT_THAT(attr->compiled_value, Pointee(ValueEq(padding_horizontal_value)));

  attr = el->FindAttribute(xml::kSchemaAndroid, "paddingRight");
  ASSERT_THAT(attr, NotNull());
  ASSERT_THAT(attr->compiled_value, NotNull());
  ASSERT_TRUE(attr->compiled_attribute);
  ASSERT_THAT(*attr->compiled_value, ValueEq(padding_horizontal_value));
  ASSERT_THAT(attr->compiled_value, Pointee(ValueEq(padding_horizontal_value)));
}

}  // namespace aapt
+44 −71
Original line number Diff line number Diff line
@@ -146,34 +146,10 @@ MATCHER_P(StrEq, a,
  return android::StringPiece16(arg) == a;
}

class ValueEq {
 public:
  template <typename arg_type>
  class BaseImpl : public ::testing::MatcherInterface<arg_type> {
    BaseImpl(const BaseImpl&) = default;

    void DescribeTo(::std::ostream* os) const override {
      *os << "is equal to " << *expected_;
    }

    void DescribeNegationTo(::std::ostream* os) const override {
      *os << "is not equal to " << *expected_;
    }

   protected:
    BaseImpl(const Value* expected) : expected_(expected) {
    }

    const Value* expected_;
  };

  template <typename T, bool>
  class Impl {};

template <typename T>
  class Impl<T, false> : public ::testing::MatcherInterface<T> {
class ValueEqImpl : public ::testing::MatcherInterface<T> {
 public:
    explicit Impl(const Value* expected) : expected_(expected) {
  explicit ValueEqImpl(const Value* expected) : expected_(expected) {
  }

  bool MatchAndExplain(T x, ::testing::MatchResultListener* listener) const override {
@@ -189,54 +165,51 @@ class ValueEq {
  }

 private:
    DISALLOW_COPY_AND_ASSIGN(Impl);
  DISALLOW_COPY_AND_ASSIGN(ValueEqImpl);

  const Value* expected_;
};

  template <typename T>
  class Impl<T, true> : public ::testing::MatcherInterface<T> {
template <typename TValue>
class ValueEqMatcher {
 public:
    explicit Impl(const Value* expected) : expected_(expected) {
    }

    bool MatchAndExplain(T x, ::testing::MatchResultListener* listener) const override {
      return expected_->Equals(x);
  ValueEqMatcher(TValue expected) : expected_(std::move(expected)) {
  }

    void DescribeTo(::std::ostream* os) const override {
      *os << "is equal to " << *expected_;
    }

    void DescribeNegationTo(::std::ostream* os) const override {
      *os << "is not equal to " << *expected_;
  template <typename T>
  operator ::testing::Matcher<T>() const {
    return ::testing::Matcher<T>(new ValueEqImpl<T>(&expected_));
  }

 private:
    DISALLOW_COPY_AND_ASSIGN(Impl);

    const Value* expected_;
  TValue expected_;
};

  ValueEq(const Value& expected) : expected_(&expected) {
  }
  ValueEq(const Value* expected) : expected_(expected) {
template <typename TValue>
class ValueEqPointerMatcher {
 public:
  ValueEqPointerMatcher(const TValue* expected) : expected_(expected) {
  }
  ValueEq(const ValueEq&) = default;

  template <typename T>
  operator ::testing::Matcher<T>() const {
    return ::testing::Matcher<T>(new Impl<T, std::is_pointer<T>::value>(expected_));
    return ::testing::Matcher<T>(new ValueEqImpl<T>(expected_));
  }

 private:
  const Value* expected_;
  const TValue* expected_;
};

// MATCHER_P(ValueEq, a,
//          std::string(negation ? "isn't" : "is") + " equal to " + ::testing::PrintToString(a)) {
//  return arg.Equals(&a);
//}
template <typename TValue,
          typename = typename std::enable_if<!std::is_pointer<TValue>::value, void>::type>
inline ValueEqMatcher<TValue> ValueEq(TValue value) {
  return ValueEqMatcher<TValue>(std::move(value));
}

template <typename TValue>
inline ValueEqPointerMatcher<TValue> ValueEq(const TValue* value) {
  return ValueEqPointerMatcher<TValue>(value);
}

MATCHER_P(StrValueEq, a,
          std::string(negation ? "isn't" : "is") + " equal to " + ::testing::PrintToString(a)) {
+5 −6
Original line number Diff line number Diff line
@@ -244,14 +244,13 @@ static void CopyAttributes(Element* el, android::ResXMLParser* parser, StringPoo
      str16 = parser->getAttributeStringValue(i, &len);
      if (str16) {
        attr.value = util::Utf16ToUtf8(StringPiece16(str16, len));
      } else {
      }

      android::Res_value res_value;
      if (parser->getAttributeValue(i, &res_value) > 0) {
        attr.compiled_value = ResourceUtils::ParseBinaryResValue(
            ResourceType::kAnim, {}, parser->getStrings(), res_value, out_pool);
      }
      }


      el->attributes.push_back(std::move(attr));
    }
Loading