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

Commit 71965e89 authored by Adam Lesinski's avatar Adam Lesinski
Browse files

AAPT2: Fix fully qualified java class verification

Proguard rules would be ignored for components defined
in AndroidManifest.xml for android:name attributes if
they didn't start with '.'.

Change-Id: I029b5a2f224f4daf155b73a2a4dcd940dd43372e
parent ec6f6c86
Loading
Loading
Loading
Loading
+11 −12
Original line number Diff line number Diff line
@@ -20,6 +20,8 @@
#include "xml/XmlActionExecutor.h"
#include "xml/XmlDom.h"

#include <unordered_set>

namespace aapt {

/**
@@ -27,21 +29,14 @@ namespace aapt {
 */
static bool nameIsJavaClassName(xml::Element* el, xml::Attribute* attr,
                                SourcePathDiagnostics* diag) {
    std::u16string className = attr->value;
    if (className.find(u'.') == std::u16string::npos) {
        // There is no '.', so add one to the beginning.
        className = u".";
        className += attr->value;
    }

    // We allow unqualified class names (ie: .HelloActivity)
    // Since we don't know the package name, we can just make a fake one here and
    // the test will be identical as long as the real package name is valid too.
    Maybe<std::u16string> fullyQualifiedClassName =
            util::getFullyQualifiedClassName(u"a", className);
            util::getFullyQualifiedClassName(u"a", attr->value);

    StringPiece16 qualifiedClassName = fullyQualifiedClassName
            ? fullyQualifiedClassName.value() : className;
            ? fullyQualifiedClassName.value() : attr->value;
    if (!util::isJavaClassName(qualifiedClassName)) {
        diag->error(DiagMessage(el->lineNumber)
                    << "attribute 'android:name' in <"
@@ -230,11 +225,14 @@ public:

    void visit(xml::Element* el) override {
        for (xml::Attribute& attr : el->attributes) {
            if (attr.namespaceUri == xml::kSchemaAndroid
                    && mClassAttributes.find(attr.name) != mClassAttributes.end()) {
                if (Maybe<std::u16string> newValue =
                        util::getFullyQualifiedClassName(mPackage, attr.value)) {
                    attr.value = std::move(newValue.value());
                }
            }
        }

        // Super implementation to iterate over the children.
        xml::Visitor::visit(el);
@@ -242,6 +240,7 @@ public:

private:
    StringPiece16 mPackage;
    std::unordered_set<StringPiece16> mClassAttributes = { u"name" };
};

static bool renameManifestPackage(const StringPiece16& packageOverride, xml::Element* manifestEl) {
+2 −2
Original line number Diff line number Diff line
@@ -175,11 +175,11 @@ Maybe<std::u16string> getFullyQualifiedClassName(const StringPiece16& package,
        return {};
    }

    std::u16string result(package.data(), package.size());
    if (className.data()[0] != u'.') {
        return {};
        result += u'.';
    }

    std::u16string result(package.data(), package.size());
    result.append(className.data(), className.size());
    if (!isJavaClassName(result)) {
        return {};
+5 −4
Original line number Diff line number Diff line
@@ -143,10 +143,7 @@ TEST(UtilTest, IsJavaPackageName) {
}

TEST(UtilTest, FullyQualifiedClassName) {
    Maybe<std::u16string> res = util::getFullyQualifiedClassName(u"android", u"asdf");
    AAPT_ASSERT_FALSE(res);

    res = util::getFullyQualifiedClassName(u"android", u".asdf");
    Maybe<std::u16string> res = util::getFullyQualifiedClassName(u"android", u".asdf");
    AAPT_ASSERT_TRUE(res);
    EXPECT_EQ(res.value(), u"android.asdf");

@@ -162,6 +159,10 @@ TEST(UtilTest, FullyQualifiedClassName) {
    AAPT_ASSERT_TRUE(res);
    EXPECT_EQ(res.value(), u"a.b");

    res = util::getFullyQualifiedClassName(u"android", u"Class");
    AAPT_ASSERT_TRUE(res);
    EXPECT_EQ(res.value(), u"android.Class");

    res = util::getFullyQualifiedClassName(u"", u"");
    AAPT_ASSERT_FALSE(res);