mirror of
https://github.com/revanced/Apktool.git
synced 2025-05-18 05:47:05 +02:00
Support malformed resource names/namespaces by falling back to resId (#2886)
* Correct falsely-referenced attribute into an entity which is an obfuscated name * style: correct syntax for custom attributes * fix: remove unused import Co-authored-by: MyAnoneNeko <MyAnoneNeko@users.noreply.github.com>
This commit is contained in:
parent
5d6c6c04d2
commit
3fff2f128e
@ -336,16 +336,26 @@ public class AXmlResourceParser implements XmlResourceParser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
String value = m_strings.getString(name);
|
String value = m_strings.getString(name);
|
||||||
|
String namespace = getAttributeNamespace(index);
|
||||||
|
|
||||||
// some attributes will return "", we must rely on the resource_id and refer to the frameworks
|
// If attribute name is lacking or a private namespace emerges,
|
||||||
// to match the resource id to the name. ex: 0x101021C = versionName
|
// retrieve the exact attribute name by its id.
|
||||||
if (value.length() == 0 || android_ns.equals(getAttributeNamespace(index))) {
|
if (value == null || value.length() == 0) {
|
||||||
try {
|
try {
|
||||||
int resourceId = getAttributeNameResource(index);
|
value = mAttrDecoder.decodeManifestAttr(getAttributeNameResource(index));
|
||||||
if (resourceId != 0) {
|
if (value == null) {
|
||||||
value = mAttrDecoder.decodeManifestAttr(getAttributeNameResource(index));
|
value = "";
|
||||||
}
|
}
|
||||||
} catch (AndrolibException | NullPointerException ignored) {}
|
} catch (AndrolibException e) {
|
||||||
|
value = "";
|
||||||
|
}
|
||||||
|
} else if (! namespace.equals(android_ns)) {
|
||||||
|
try {
|
||||||
|
String obfuscatedName = mAttrDecoder.decodeManifestAttr(getAttributeNameResource(index));
|
||||||
|
if (! (obfuscatedName == null || obfuscatedName.equals(value))) {
|
||||||
|
value = obfuscatedName;
|
||||||
|
}
|
||||||
|
} catch (AndrolibException ignored) {}
|
||||||
}
|
}
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
@ -381,11 +391,27 @@ public class AXmlResourceParser implements XmlResourceParser {
|
|||||||
|
|
||||||
if (mAttrDecoder != null) {
|
if (mAttrDecoder != null) {
|
||||||
try {
|
try {
|
||||||
|
String value = valueRaw == -1 ? null : ResXmlEncoders.escapeXmlChars(m_strings.getString(valueRaw));
|
||||||
|
String obfuscatedValue = mAttrDecoder.decodeManifestAttr(valueData);
|
||||||
|
|
||||||
|
if (! (value == null || obfuscatedValue == null)) {
|
||||||
|
int slashPos = value.lastIndexOf("/");
|
||||||
|
|
||||||
|
if (slashPos != -1) {
|
||||||
|
// Handle a value with a format of "@yyy/xxx"
|
||||||
|
String dir = value.substring(0, slashPos);
|
||||||
|
value = dir + "/"+ obfuscatedValue;
|
||||||
|
} else if (! value.equals(obfuscatedValue)) {
|
||||||
|
value = obfuscatedValue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return mAttrDecoder.decode(
|
return mAttrDecoder.decode(
|
||||||
valueType,
|
valueType,
|
||||||
valueData,
|
valueData,
|
||||||
valueRaw == -1 ? null : ResXmlEncoders.escapeXmlChars(m_strings.getString(valueRaw)),
|
value,
|
||||||
getAttributeNameResource(index));
|
getAttributeNameResource(index)
|
||||||
|
);
|
||||||
} catch (AndrolibException ex) {
|
} catch (AndrolibException ex) {
|
||||||
setFirstError(ex);
|
setFirstError(ex);
|
||||||
LOGGER.log(Level.WARNING, String.format("Could not decode attr value, using undecoded value "
|
LOGGER.log(Level.WARNING, String.format("Could not decode attr value, using undecoded value "
|
||||||
@ -807,9 +833,9 @@ public class AXmlResourceParser implements XmlResourceParser {
|
|||||||
if (m_strings == null) {
|
if (m_strings == null) {
|
||||||
m_reader.skipCheckInt(CHUNK_AXML_FILE, CHUNK_AXML_FILE_BROKEN);
|
m_reader.skipCheckInt(CHUNK_AXML_FILE, CHUNK_AXML_FILE_BROKEN);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* chunkSize
|
* chunkSize
|
||||||
*/
|
*/
|
||||||
m_reader.skipInt();
|
m_reader.skipInt();
|
||||||
m_strings = StringBlock.read(m_reader);
|
m_strings = StringBlock.read(m_reader);
|
||||||
m_namespaces.increaseDepth();
|
m_namespaces.increaseDepth();
|
||||||
@ -863,9 +889,9 @@ public class AXmlResourceParser implements XmlResourceParser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Common header.
|
// Common header.
|
||||||
/* chunkSize */m_reader.skipInt();
|
/* chunkSize */m_reader.skipInt();
|
||||||
int lineNumber = m_reader.readInt();
|
int lineNumber = m_reader.readInt();
|
||||||
/* 0xFFFFFFFF */m_reader.skipInt();
|
/* 0xFFFFFFFF */m_reader.skipInt();
|
||||||
|
|
||||||
if (chunkType == CHUNK_XML_START_NAMESPACE || chunkType == CHUNK_XML_END_NAMESPACE) {
|
if (chunkType == CHUNK_XML_START_NAMESPACE || chunkType == CHUNK_XML_END_NAMESPACE) {
|
||||||
if (chunkType == CHUNK_XML_START_NAMESPACE) {
|
if (chunkType == CHUNK_XML_START_NAMESPACE) {
|
||||||
@ -873,8 +899,8 @@ public class AXmlResourceParser implements XmlResourceParser {
|
|||||||
int uri = m_reader.readInt();
|
int uri = m_reader.readInt();
|
||||||
m_namespaces.push(prefix, uri);
|
m_namespaces.push(prefix, uri);
|
||||||
} else {
|
} else {
|
||||||
/* prefix */m_reader.skipInt();
|
/* prefix */m_reader.skipInt();
|
||||||
/* uri */m_reader.skipInt();
|
/* uri */m_reader.skipInt();
|
||||||
m_namespaces.pop();
|
m_namespaces.pop();
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
@ -885,7 +911,7 @@ public class AXmlResourceParser implements XmlResourceParser {
|
|||||||
if (chunkType == CHUNK_XML_START_TAG) {
|
if (chunkType == CHUNK_XML_START_TAG) {
|
||||||
m_namespaceUri = m_reader.readInt();
|
m_namespaceUri = m_reader.readInt();
|
||||||
m_name = m_reader.readInt();
|
m_name = m_reader.readInt();
|
||||||
/* flags? */m_reader.skipInt();
|
/* flags? */m_reader.skipInt();
|
||||||
int attributeCount = m_reader.readInt();
|
int attributeCount = m_reader.readInt();
|
||||||
m_idAttribute = (attributeCount >>> 16) - 1;
|
m_idAttribute = (attributeCount >>> 16) - 1;
|
||||||
attributeCount &= 0xFFFF;
|
attributeCount &= 0xFFFF;
|
||||||
@ -912,8 +938,8 @@ public class AXmlResourceParser implements XmlResourceParser {
|
|||||||
|
|
||||||
if (chunkType == CHUNK_XML_TEXT) {
|
if (chunkType == CHUNK_XML_TEXT) {
|
||||||
m_name = m_reader.readInt();
|
m_name = m_reader.readInt();
|
||||||
/* ? */m_reader.skipInt();
|
/* ? */m_reader.skipInt();
|
||||||
/* ? */m_reader.skipInt();
|
/* ? */m_reader.skipInt();
|
||||||
m_event = TEXT;
|
m_event = TEXT;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -927,10 +953,10 @@ public class AXmlResourceParser implements XmlResourceParser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ///////////////////////////////// data
|
// ///////////////////////////////// data
|
||||||
/*
|
/*
|
||||||
* All values are essentially indices, e.g. m_name is an index of name in
|
* All values are essentially indices, e.g. m_name is an index of name in
|
||||||
* m_strings.
|
* m_strings.
|
||||||
*/
|
*/
|
||||||
private ExtDataInput m_reader;
|
private ExtDataInput m_reader;
|
||||||
private ResAttrDecoder mAttrDecoder;
|
private ResAttrDecoder mAttrDecoder;
|
||||||
private AndrolibException mFirstError;
|
private AndrolibException mFirstError;
|
||||||
|
@ -18,6 +18,7 @@ package brut.androlib.res.decoder;
|
|||||||
|
|
||||||
import brut.androlib.AndrolibException;
|
import brut.androlib.AndrolibException;
|
||||||
import brut.androlib.err.UndefinedResObjectException;
|
import brut.androlib.err.UndefinedResObjectException;
|
||||||
|
import brut.androlib.res.data.ResID;
|
||||||
import brut.androlib.res.data.ResPackage;
|
import brut.androlib.res.data.ResPackage;
|
||||||
import brut.androlib.res.data.ResResSpec;
|
import brut.androlib.res.data.ResResSpec;
|
||||||
import brut.androlib.res.data.value.ResAttr;
|
import brut.androlib.res.data.value.ResAttr;
|
||||||
@ -48,10 +49,24 @@ public class ResAttrDecoder {
|
|||||||
throws AndrolibException {
|
throws AndrolibException {
|
||||||
|
|
||||||
if (attrResId != 0) {
|
if (attrResId != 0) {
|
||||||
ResResSpec resResSpec = getCurrentPackage().getResTable().getResSpec(attrResId);
|
int attrId = attrResId;
|
||||||
|
|
||||||
if (resResSpec != null) {
|
// See also: brut.androlib.res.data.ResTable.getResSpec
|
||||||
return resResSpec.getName();
|
if (attrId >> 24 == 0) {
|
||||||
|
ResPackage pkg = getCurrentPackage();
|
||||||
|
int packageId = pkg.getId();
|
||||||
|
int pkgId = (packageId == 0 ? 2 : packageId);
|
||||||
|
attrId = (0xFF000000 & (pkgId << 24)) | attrId;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Retrieve the ResSpec in a package by id
|
||||||
|
ResID resId = new ResID(attrId);
|
||||||
|
ResPackage pkg = getCurrentPackage();
|
||||||
|
if (pkg.hasResSpec(resId)) {
|
||||||
|
ResResSpec resResSpec = pkg.getResSpec(resId);
|
||||||
|
if (resResSpec != null) {
|
||||||
|
return resResSpec.getName();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user