Skip to content

Commit

Permalink
fix(res): avoid duplicated XML attributes (PR #2112)
Browse files Browse the repository at this point in the history
Co-authored-by: bagipro <bugi@bugi>
  • Loading branch information
bagipro and bagipro authored Feb 27, 2024
1 parent 881a716 commit 278e3c2
Show file tree
Hide file tree
Showing 3 changed files with 44 additions and 31 deletions.
54 changes: 27 additions & 27 deletions jadx-core/src/main/java/jadx/core/xmlgen/BinaryXMLParser.java
Original file line number Diff line number Diff line change
Expand Up @@ -286,43 +286,49 @@ private void parseElement() throws IOException {
}
}
}
Set<String> attrCache = new HashSet<>();
boolean attrNewLine = attributeCount != 1 && this.attrNewLine;
for (int i = 0; i < attributeCount; i++) {
parseAttribute(i, attrNewLine);
parseAttribute(i, attrNewLine, attrCache);
}
}

private void parseAttribute(int i, boolean newLine) throws IOException {
private void parseAttribute(int i, boolean newLine, Set<String> attrCache) throws IOException {
int attributeNS = is.readInt32();
int attributeName = is.readInt32();
int attributeRawValue = is.readInt32();
is.skip(3);
int attrValDataType = is.readInt8();
int attrValData = is.readInt32();

if (newLine) {
writer.startLine().addIndent();
} else {
writer.add(' ');
}
String shortNsName = null;
if (attributeNS != -1) {
shortNsName = getAttributeNS(attributeNS);
writer.add(shortNsName).add(':');
}
String attrName = getValidTagAttributeName(getAttributeName(attributeName));
writer.add(attrName).add("=\"");
String attrFullName = shortNsName != null ? shortNsName + ":" + attrName : attrName;
// do not dump duplicated values
if (XmlDeobf.isDuplicatedAttr(attrFullName, attrCache)) {
return;
}

if (newLine) {
writer.startLine().addIndent();
} else {
writer.add(' ');
}
writer.add(attrFullName).add("=\"");
String decodedAttr = ManifestAttributes.getInstance().decode(attrName, attrValData);
if (decodedAttr != null) {
memorizePackageName(attrName, decodedAttr);
if (isDeobfCandidateAttr(shortNsName, attrName)) {
if (isDeobfCandidateAttr(attrFullName)) {
decodedAttr = deobfClassName(decodedAttr);
}
attachClassNode(writer, attrName, decodedAttr);
writer.add(StringUtils.escapeXML(decodedAttr));
} else {
decodeAttribute(attributeNS, attrValDataType, attrValData,
shortNsName, attrName);
attrFullName);
}
if (shortNsName != null && shortNsName.equals("android")) {
if (attrName.equals("pathData")) {
Expand Down Expand Up @@ -402,7 +408,7 @@ private String getString(int strId) {
}

private void decodeAttribute(int attributeNS, int attrValDataType, int attrValData,
String shortNsName, String attrName) {
String attrFullName) {
if (attrValDataType == TYPE_REFERENCE) {
// reference custom processing
String resName = resNames.get(attrValData);
Expand All @@ -424,11 +430,11 @@ private void decodeAttribute(int attributeNS, int attrValDataType, int attrValDa
}
} else {
String str = valuesParser.decodeValue(attrValDataType, attrValData);
memorizePackageName(attrName, str);
if (isDeobfCandidateAttr(shortNsName, attrName)) {
memorizePackageName(attrFullName, str);
if (isDeobfCandidateAttr(attrFullName)) {
str = deobfClassName(str);
}
attachClassNode(writer, attrName, str);
attachClassNode(writer, attrFullName, str);
writer.add(str != null ? StringUtils.escapeXML(str) : "null");
}
}
Expand Down Expand Up @@ -487,11 +493,11 @@ private static String generateTagAttrName() {
return sb.toString();
}

private void attachClassNode(ICodeWriter writer, String attrName, String clsName) {
private void attachClassNode(ICodeWriter writer, String attrFullName, String clsName) {
if (!writer.isMetadataSupported()) {
return;
}
if (clsName == null || !attrName.equals("name")) {
if (clsName == null || !attrFullName.equals("android:name")) {
return;
}
String clsFullName;
Expand All @@ -517,18 +523,12 @@ private String deobfClassName(String className) {
return className;
}

private boolean isDeobfCandidateAttr(String shortNsName, String attrName) {
String fullName;
if (shortNsName != null) {
fullName = shortNsName + ':' + attrName;
} else {
return false;
}
return "android:name".equals(fullName);
private boolean isDeobfCandidateAttr(String attrFullName) {
return "android:name".equals(attrFullName);
}

private void memorizePackageName(String attrName, String attrValue) {
if ("manifest".equals(currentTag) && "package".equals(attrName)) {
private void memorizePackageName(String attrFullName, String attrValue) {
if ("manifest".equals(currentTag) && "package".equals(attrFullName)) {
appPackageName = attrValue;
}
}
Expand Down
15 changes: 11 additions & 4 deletions jadx-core/src/main/java/jadx/core/xmlgen/ProtoXMLParser.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,10 @@
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Random;
import java.util.Set;

import com.android.aapt.Resources.XmlAttribute;
import com.android.aapt.Resources.XmlElement;
Expand Down Expand Up @@ -58,9 +60,12 @@ private void decode(XmlElement e) throws IOException {
for (int i = 0; i < e.getNamespaceDeclarationCount(); i++) {
decode(e.getNamespaceDeclaration(i));
}

Set<String> attrCache = new HashSet<>();
for (int i = 0; i < e.getAttributeCount(); i++) {
decode(e.getAttribute(i));
decode(e.getAttribute(i), attrCache);
}

if (e.getChildCount() > 0) {
writer.add('>');
writer.incIndent();
Expand All @@ -76,11 +81,13 @@ private void decode(XmlElement e) throws IOException {
}
}

private void decode(XmlAttribute a) {
writer.add(' ');
private void decode(XmlAttribute a, Set<String> attrCache) {
String name = getAttributeFullName(a);
if (XmlDeobf.isDuplicatedAttr(name, attrCache)) {
return;
}
String value = deobfClassName(getAttributeValue(a));
writer.add(name).add("=\"").add(StringUtils.escapeXML(value)).add('\"');
writer.add(' ').add(name).add("=\"").add(StringUtils.escapeXML(value)).add('\"');
memorizePackageName(name, value);
}

Expand Down
6 changes: 6 additions & 0 deletions jadx-core/src/main/java/jadx/core/xmlgen/XmlDeobf.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package jadx.core.xmlgen;

import java.util.Set;

import org.jetbrains.annotations.Nullable;

import jadx.core.dex.info.ClassInfo;
Expand Down Expand Up @@ -30,4 +32,8 @@ public static String deobfClassName(RootNode root, String potentialClassName, St
}
return classInfo.getAliasFullName();
}

public static boolean isDuplicatedAttr(String attrFullName, Set<String> attrCache) {
return !attrCache.add(attrFullName);
}
}

0 comments on commit 278e3c2

Please sign in to comment.