fix: decoding references to private resources (#2650)

* fix: decoding references to private resources

* style: fix naming in constructor parameter

* test: add test to check build/decode private references
This commit is contained in:
Yaroslav 2021-10-17 19:01:54 +03:00 committed by GitHub
parent 9bdf385538
commit d29411117e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 38 additions and 7 deletions

View File

@ -18,6 +18,7 @@ package brut.androlib.res.data;
import brut.androlib.AndrolibException; import brut.androlib.AndrolibException;
import brut.androlib.err.UndefinedResObjectException; import brut.androlib.err.UndefinedResObjectException;
import brut.androlib.res.decoder.ARSCDecoder;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
@ -28,11 +29,13 @@ import java.util.Set;
public class ResResSpec { public class ResResSpec {
private final ResID mId; private final ResID mId;
private final String mName; private final String mName;
private final int mFlags;
private final ResPackage mPackage; private final ResPackage mPackage;
private final ResTypeSpec mType; private final ResTypeSpec mType;
private final Map<ResConfigFlags, ResResource> mResources = new LinkedHashMap<>(); private final Map<ResConfigFlags, ResResource> mResources = new LinkedHashMap<>();
public ResResSpec(ResID id, String name, ResPackage pkg, ResTypeSpec type) { public ResResSpec(ResID id, String name, int flags, ResPackage pkg, ResTypeSpec type) {
this.mFlags = flags;
this.mId = id; this.mId = id;
String cleanName; String cleanName;
@ -72,13 +75,19 @@ public class ResResSpec {
return mResources.containsKey(new ResConfigFlags()); return mResources.containsKey(new ResConfigFlags());
} }
public boolean isPublicResource() {
return (getFlags() & ARSCDecoder.ENTRY_FLAG_PUBLIC) != 0;
}
public String getFullName(ResPackage relativeToPackage, boolean excludeType) { public String getFullName(ResPackage relativeToPackage, boolean excludeType) {
return getFullName(getPackage().equals(relativeToPackage), excludeType); return getFullName(getPackage().equals(relativeToPackage), excludeType);
} }
public String getFullName(boolean excludePackage, boolean excludeType) { public String getFullName(boolean excludePackage, boolean excludeType) {
return (excludePackage ? "" : getPackage().getName() + ":") String privateSuffix = isPublicResource() ? "" : "*";
+ (excludeType ? "" : getType().getName() + "/") + getName(); String packageName = excludePackage ? "" : getPackage().getName() + ":";
return (packageName.isEmpty() ? "" : privateSuffix + packageName)
+ (excludeType ? "" : getType().getName() + "/") + getName();
} }
public ResID getId() { public ResID getId() {
@ -97,6 +106,10 @@ public class ResResSpec {
return mType; return mType;
} }
public int getFlags() {
return mFlags;
}
public boolean isDummyResSpec() { public boolean isDummyResSpec() {
return getName().startsWith("APKTOOL_DUMMY_"); return getName().startsWith("APKTOOL_DUMMY_");
} }

View File

@ -309,12 +309,12 @@ public class ARSCDecoder {
if (spec.isDummyResSpec()) { if (spec.isDummyResSpec()) {
removeResSpec(spec); removeResSpec(spec);
spec = new ResResSpec(resId, mSpecNames.getString(specNamesId), mPkg, mTypeSpec); spec = new ResResSpec(resId, mSpecNames.getString(specNamesId), entryData.mFlags, mPkg, mTypeSpec);
mPkg.addResSpec(spec); mPkg.addResSpec(spec);
mTypeSpec.addResSpec(spec); mTypeSpec.addResSpec(spec);
} }
} else { } else {
spec = new ResResSpec(resId, mSpecNames.getString(specNamesId), mPkg, mTypeSpec); spec = new ResResSpec(resId, mSpecNames.getString(specNamesId), entryData.mFlags, mPkg, mTypeSpec);
mPkg.addResSpec(spec); mPkg.addResSpec(spec);
mTypeSpec.addResSpec(spec); mTypeSpec.addResSpec(spec);
} }
@ -511,7 +511,7 @@ public class ARSCDecoder {
continue; continue;
} }
ResResSpec spec = new ResResSpec(new ResID(resId | i), "APKTOOL_DUMMY_" + Integer.toHexString(i), mPkg, mTypeSpec); ResResSpec spec = new ResResSpec(new ResID(resId | i), "APKTOOL_DUMMY_" + Integer.toHexString(i), ENTRY_FLAG_PUBLIC, mPkg, mTypeSpec);
// If we already have this resID dont add it again. // If we already have this resID dont add it again.
if (! mPkg.hasResSpec(new ResID(resId | i))) { if (! mPkg.hasResSpec(new ResID(resId | i))) {
@ -575,7 +575,7 @@ public class ARSCDecoder {
private final HashMap<Integer, ResTypeSpec> mResTypeSpecs = new HashMap<>(); private final HashMap<Integer, ResTypeSpec> mResTypeSpecs = new HashMap<>();
private final static short ENTRY_FLAG_COMPLEX = 0x0001; private final static short ENTRY_FLAG_COMPLEX = 0x0001;
private final static short ENTRY_FLAG_PUBLIC = 0x0002; public final static short ENTRY_FLAG_PUBLIC = 0x0002;
private final static short ENTRY_FLAG_WEAK = 0x0004; private final static short ENTRY_FLAG_WEAK = 0x0004;
public static class Header { public static class Header {

View File

@ -72,6 +72,16 @@ public class BuildAndDecodeTest extends BaseTest {
compareValuesFiles("values/strings.xml"); compareValuesFiles("values/strings.xml");
} }
@Test
public void valuesColorsTest() throws BrutException {
compareValuesFiles("values/colors.xml");
}
@Test
public void valuesBoolsTest() throws BrutException {
compareValuesFiles("values/bools.xml");
}
@Test @Test
public void valuesMaxLengthTest() throws BrutException { public void valuesMaxLengthTest() throws BrutException {
compareValuesFiles("values-es/strings.xml"); compareValuesFiles("values-es/strings.xml");

View File

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<item type="bool" name="bool_private_reference">@*android:bool/config_enableActivityRecognitionHardwareOverlay</item>
</resources>

View File

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="color_private_reference">@*android:color/Indigo_700</color>
</resources>