From fb4d09cadd27a3fb1a2e268417f0f511aa92e344 Mon Sep 17 00:00:00 2001 From: Ryan Mitchell Date: Mon, 7 Dec 2020 16:06:04 -0800 Subject: [PATCH] Read manifest values using resource id in idmap2 Idmap2 currently reads android:targetPackage and android:targetName from overlay manifests by looking for an attribute with the name of the attribute resource. This fixes the divergence from package parsing by finding the attributes using their resource ids. Bug: 175060836 Test: libidmap2_tests Change-Id: I09965e5880a1e6c48c3f8077db0c595484804ce7 --- cmds/idmap2/include/idmap2/XmlParser.h | 6 +- cmds/idmap2/libidmap2/ResourceUtils.cpp | 14 ++-- cmds/idmap2/libidmap2/XmlParser.cpp | 62 +++++++++++------- cmds/idmap2/tests/ResourceUtilsTests.cpp | 24 ++++++- .../data/overlay/AndroidManifestInvalid.xml | 34 ++++++++++ cmds/idmap2/tests/data/overlay/build | 7 ++ .../tests/data/overlay/overlay-invalid.apk | Bin 0 -> 4876 bytes 7 files changed, 119 insertions(+), 28 deletions(-) create mode 100644 cmds/idmap2/tests/data/overlay/AndroidManifestInvalid.xml create mode 100644 cmds/idmap2/tests/data/overlay/overlay-invalid.apk diff --git a/cmds/idmap2/include/idmap2/XmlParser.h b/cmds/idmap2/include/idmap2/XmlParser.h index 972a6d7e3427c..1c74ab3bb691b 100644 --- a/cmds/idmap2/include/idmap2/XmlParser.h +++ b/cmds/idmap2/include/idmap2/XmlParser.h @@ -22,6 +22,7 @@ #include #include +#include "ResourceUtils.h" #include "Result.h" #include "android-base/macros.h" #include "androidfw/ResourceTypes.h" @@ -39,8 +40,11 @@ class XmlParser { Event event() const; std::string name() const; - Result GetAttributeStringValue(const std::string& name) const; Result GetAttributeValue(const std::string& name) const; + Result GetAttributeValue(ResourceId attr, const std::string& label) const; + + Result GetAttributeStringValue(const std::string& name) const; + Result GetAttributeStringValue(ResourceId attr, const std::string& label) const; bool operator==(const Node& rhs) const; bool operator!=(const Node& rhs) const; diff --git a/cmds/idmap2/libidmap2/ResourceUtils.cpp b/cmds/idmap2/libidmap2/ResourceUtils.cpp index 52837418e7759..4e85e57513003 100644 --- a/cmds/idmap2/libidmap2/ResourceUtils.cpp +++ b/cmds/idmap2/libidmap2/ResourceUtils.cpp @@ -32,6 +32,12 @@ using android::idmap2::ZipFile; using android::util::Utf16ToUtf8; namespace android::idmap2::utils { +namespace { +constexpr ResourceId kAttrName = 0x01010003; +constexpr ResourceId kAttrResourcesMap = 0x01010609; +constexpr ResourceId kAttrTargetName = 0x0101044d; +constexpr ResourceId kAttrTargetPackage = 0x01010021; +} // namespace bool IsReference(uint8_t data_type) { return data_type == Res_value::TYPE_REFERENCE || data_type == Res_value::TYPE_DYNAMIC_REFERENCE; @@ -119,7 +125,7 @@ Result ExtractOverlayManifestInfo(const std::string& path, } OverlayManifestInfo info{}; - if (auto result_str = it.GetAttributeStringValue("name")) { + if (auto result_str = it.GetAttributeStringValue(kAttrName, "android:name")) { if (*result_str != name) { // A value for android:name was found, but either a the name does not match the requested // name, or an tag with no name was requested. @@ -132,18 +138,18 @@ Result ExtractOverlayManifestInfo(const std::string& path, continue; } - if (auto result_str = it.GetAttributeStringValue("targetPackage")) { + if (auto result_str = it.GetAttributeStringValue(kAttrTargetPackage, "android:targetPackage")) { info.target_package = *result_str; } else { return Error("android:targetPackage missing from of %s: %s", path.c_str(), result_str.GetErrorMessage().c_str()); } - if (auto result_str = it.GetAttributeStringValue("targetName")) { + if (auto result_str = it.GetAttributeStringValue(kAttrTargetName, "android:targetName")) { info.target_name = *result_str; } - if (auto result_value = it.GetAttributeValue("resourcesMap")) { + if (auto result_value = it.GetAttributeValue(kAttrResourcesMap, "android:resourcesMap")) { if (IsReference((*result_value).dataType)) { info.resource_mapping = (*result_value).data; } else { diff --git a/cmds/idmap2/libidmap2/XmlParser.cpp b/cmds/idmap2/libidmap2/XmlParser.cpp index 4030b83b3a41f..00baea46f9093 100644 --- a/cmds/idmap2/libidmap2/XmlParser.cpp +++ b/cmds/idmap2/libidmap2/XmlParser.cpp @@ -90,15 +90,27 @@ std::string XmlParser::Node::name() const { return String8(key16).c_str(); } -Result XmlParser::Node::GetAttributeStringValue(const std::string& name) const { - auto value = GetAttributeValue(name); - if (!value) { - return value.GetError(); +template +Result FindAttribute(const ResXMLParser& parser, const std::string& label, + Func&& predicate) { + for (size_t i = 0; i < parser.getAttributeCount(); i++) { + if (!predicate(i)) { + continue; + } + Res_value res_value{}; + if (parser.getAttributeValue(i, &res_value) == BAD_TYPE) { + return Error(R"(Bad value for attribute "%s")", label.c_str()); + } + return res_value; } + return Error(R"(Failed to find attribute "%s")", label.c_str()); +} - switch ((*value).dataType) { +Result GetStringValue(const ResXMLParser& parser, const Res_value& value, + const std::string& label) { + switch (value.dataType) { case Res_value::TYPE_STRING: { - if (auto str = parser_.getStrings().string8ObjectAt((*value).data); str.ok()) { + if (auto str = parser.getStrings().string8ObjectAt(value.data); str.ok()) { return std::string(str->string()); } break; @@ -106,31 +118,37 @@ Result XmlParser::Node::GetAttributeStringValue(const std::string& case Res_value::TYPE_INT_DEC: case Res_value::TYPE_INT_HEX: case Res_value::TYPE_INT_BOOLEAN: { - return std::to_string((*value).data); + return std::to_string(value.data); } } + return Error(R"(Failed to convert attribute "%s" value to a string)", label.c_str()); +} - return Error(R"(Failed to convert attribute "%s" value to a string)", name.c_str()); +Result XmlParser::Node::GetAttributeValue(ResourceId attr, + const std::string& label) const { + return FindAttribute(parser_, label, [&](size_t index) -> bool { + return parser_.getAttributeNameResID(index) == attr; + }); } Result XmlParser::Node::GetAttributeValue(const std::string& name) const { - size_t len; - for (size_t i = 0; i < parser_.getAttributeCount(); i++) { - const String16 key16(parser_.getAttributeName(i, &len)); + return FindAttribute(parser_, name, [&](size_t index) -> bool { + size_t len; + const String16 key16(parser_.getAttributeName(index, &len)); std::string key = String8(key16).c_str(); - if (key != name) { - continue; - } + return key == name; + }); +} - Res_value res_value{}; - if (parser_.getAttributeValue(i, &res_value) == BAD_TYPE) { - return Error(R"(Bad value for attribute "%s")", name.c_str()); - } +Result XmlParser::Node::GetAttributeStringValue(ResourceId attr, + const std::string& label) const { + auto value = GetAttributeValue(attr, label); + return value ? GetStringValue(parser_, *value, label) : value.GetError(); +} - return res_value; - } - - return Error(R"(Failed to find attribute "%s")", name.c_str()); +Result XmlParser::Node::GetAttributeStringValue(const std::string& name) const { + auto value = GetAttributeValue(name); + return value ? GetStringValue(parser_, *value, name) : value.GetError(); } Result> XmlParser::Create(const void* data, size_t size, diff --git a/cmds/idmap2/tests/ResourceUtilsTests.cpp b/cmds/idmap2/tests/ResourceUtilsTests.cpp index 9ed807ccd8f90..1f6bf49f5f0e1 100644 --- a/cmds/idmap2/tests/ResourceUtilsTests.cpp +++ b/cmds/idmap2/tests/ResourceUtilsTests.cpp @@ -59,4 +59,26 @@ TEST_F(ResourceUtilsTests, ResToTypeEntryNameNoSuchResourceId) { ASSERT_FALSE(name); } -} // namespace android::idmap2 +TEST_F(ResourceUtilsTests, InvalidValidOverlayNameInvalidAttributes) { + auto info = utils::ExtractOverlayManifestInfo(GetTestDataPath() + "/overlay/overlay-invalid.apk", + "InvalidName"); + ASSERT_FALSE(info); +} + +TEST_F(ResourceUtilsTests, ValidOverlayNameInvalidAttributes) { + auto info = utils::ExtractOverlayManifestInfo(GetTestDataPath() + "/overlay/overlay-invalid.apk", + "ValidName"); + ASSERT_FALSE(info); +} + +TEST_F(ResourceUtilsTests, ValidOverlayNameAndTargetPackageInvalidAttributes) { + auto info = utils::ExtractOverlayManifestInfo(GetTestDataPath() + "/overlay/overlay-invalid.apk", + "ValidNameAndTargetPackage"); + ASSERT_TRUE(info); + ASSERT_EQ("ValidNameAndTargetPackage", info->name); + ASSERT_EQ("Valid", info->target_package); + ASSERT_EQ("", info->target_name); // Attribute resource id could not be found + ASSERT_EQ(0, info->resource_mapping); // Attribute resource id could not be found +} + +}// namespace android::idmap2 diff --git a/cmds/idmap2/tests/data/overlay/AndroidManifestInvalid.xml b/cmds/idmap2/tests/data/overlay/AndroidManifestInvalid.xml new file mode 100644 index 0000000000000..d61c36cad60ce --- /dev/null +++ b/cmds/idmap2/tests/data/overlay/AndroidManifestInvalid.xml @@ -0,0 +1,34 @@ + + + + + + + + + + + diff --git a/cmds/idmap2/tests/data/overlay/build b/cmds/idmap2/tests/data/overlay/build index 1f1cedb052719..7b1a66f31e611 100755 --- a/cmds/idmap2/tests/data/overlay/build +++ b/cmds/idmap2/tests/data/overlay/build @@ -38,4 +38,11 @@ aapt2 link \ -o overlay-legacy.apk \ compiled.flata +aapt2 link \ + --no-resource-removal \ + -I "$FRAMEWORK_RES_APK" \ + --manifest AndroidManifestInvalid.xml \ + -o overlay-invalid.apk \ + compiled.flata + rm compiled.flata diff --git a/cmds/idmap2/tests/data/overlay/overlay-invalid.apk b/cmds/idmap2/tests/data/overlay/overlay-invalid.apk new file mode 100644 index 0000000000000000000000000000000000000000..888c871e41019567120088b2ab93a2f213aa500b GIT binary patch literal 4876 zcmd^Dc{r478-K=FCPrkbv8FmIg-A)+CRvI$StG_^Xe>jsC>2RUh(mQsQ94maSqk|m zx-1!WD%yl}G)JXHmX4&A?|z4ghVQz*zJI^xx_)yn&-32zb1%>G&PF@DD1t^nDC!ih zV))`s9T9|r#1WDQ?Mj9(GlcHDj>@3>(O7KV9l=3I4y|LzuT+S+U^l>eP?Tb#^VkVkRj=>ByIL zmCa2}g>9+ll@Dv4>DsBXrundGeR&zqji=s%3#qc{Q`(I;uUh2ppS`Y+Sb^$!3qMYc zjLwN>Gm}8tjj(xM^Z|qbF_VYfby+I(OgthT%C2DDRef zMauZi@>-k{JCH5cMQghJ#KpPQB(5?gAjKg4uM?7~`RTkR1Ku9VnVXIpnRQUxm$k?uT7y@Ui|gubCUR9W0YELS@awDU=yn*w`^vhs(P?hFY#;MkG@7oSEORrj8NGEex;pUSG&#*mj)h zD1W6|kdYslkkH<`V`=U-PE*Fw&^r(9`prF`4{bis9$i?;Y`Efr-}74=q3od@EB5Fk zRZnHl!qhIOzgPoOAMGk*0dUPk9%-yrpe+#Wu^_)X&4X z$c^iZ=Ez#}yt37}*>U=6RfPT1R*;UWaZBP-rM<|cP`!`e42smP&7w}noK__^Q8WB6 z_xEpqC-GynDmz`A^C3#{IE3a-5-o}^-OrE4q%qi(P^wQL)t|!hZQOF0}?-XmJK^%bi7RcOmLYm=Z6r~<82bpJqUWKnI2fOHFa%3fanEcaVLKBX`jzFaj8=c?&`-z z#w15N-~F=Zn^1WqTy`_B1xGW$VU@`orZa-*j8QMIO4jJ1iucmfb31rhJYHVe@-j)u zo(8d1T9#7!)1Rn*BMdt&O7os3QK;&oTkp{^r+O6atLdp=Mr4 zEHPe|+Gia#uV~QO+DvWtkj%%W7t_@)H~+aq_gQ(;fJFegs97dsMmei%^FZs;ulJgQ z-Ve9P7HlXn%)5W9H2+|40e3jEOX|mD<3AGfGr?~XY`kid`5qb)ME9Z7M%Ku~b?a-$ zBynEh@CzF;H`^(e9%amDkByI&aheZrx-_LETWz)L>zY+Nh#`M3uh?(=ZS}QSdgdCx z${?c0(hRMy$TstLP?Vch@*FQ9>1i+4-b)STI(pw$BxVvlypaEGP44Ar>aSD+@u0!uT}=^RhC5|` z%xk1ZH|`bWGYYmmrOEQj+D;ASuiMlOfi+~=x~G2qHt}K?)E7K|S_@onnWd$v11n%n{vR@L z4jsSqPtEb$j{2rrwkMujc|TZSFumY}d;flo`GF3>_jPLe+ML5v>q_dJKI}YFSv^RL zecAN7v)-#ve7KkOkg(|ew1I`yih3{T9WBLY%}aM4es6T2mG_Aq@z^~uSF9s1SHj5n z&gKnj#md|=iCV?jwrYZV(mUAlBx>bjo2yBsq(jC@bQ$rOy;H?|)3+I4$bCB0I#UoH zEGDOLS!PMw5C|hD4c!+_nKF9l=;)8*4UmGuWQP)(J6Bje`Rl!I3P3RZY2O<)`&sc{QHcniEi3o{k;K&jP?E#jJXov;Bx+nyN0nbE1h>F6Y z=l`Q&b%HhaD8+cJejI_~F=4dL7cfBO0J8xSh>jTi2>SCQhmbfwmQ23hA4cHO4ipR# z9kEG-g{=rYzrp)L1w2ql2frrufvyC&0(JsY0NDVnE}H;-00KNa51oI! z0nh`G0UH5cfKWgb;8#Ev;3A+3An*~J2l&We%9zg>GhW8#K3*0RlHrc^LqE1o$B)Ns zj+dth$=De*z8^b##>+$@S$b3+%?&>n*m%qjEVg+-F&@j&_}KFIb{bh3u|QwAM^FKkdZ#Y?