Apktool icon indicating copy to clipboard operation
Apktool copied to clipboard

[BUG] Chunk [amp] is not a valid entry

Open pashamcr opened this issue 4 years ago • 5 comments

Information

  1. Apktool Version (apktool -version) - 2.6.0
  2. Operating System (Mac, Linux, Windows) - win
  3. APK From? (Playstore, ROM, Other) - rom

Stacktrace/Logcat

I: Using Apktool 2.6.0 on Settings.apk
I: Loading resource table...
I: Decoding Shared Library (miui), pkgId: 16
I: Decoding Shared Library (android.miui), pkgId: 17
I: Decoding Shared Library (miui.system), pkgId: 18
Exception in thread "main" java.lang.IllegalArgumentException: Chunk [amp] is not a valid entry
        at com.google.common.base.Preconditions.checkArgument(Preconditions.java:219)
        at com.google.common.base.Splitter$MapSplitter.split(Splitter.java:526)
        at brut.androlib.res.decoder.StringBlock$Tag.toString(StringBlock.java:167)
        at java.base/java.lang.String.valueOf(String.java:2951)
        at java.base/java.lang.StringBuilder.append(StringBuilder.java:168)
        at brut.androlib.res.decoder.StringBlock.processStyledString(StringBlock.java:260)
        at brut.androlib.res.decoder.StringBlock.getHTML(StringBlock.java:288)
        at brut.androlib.res.decoder.ARSCDecoder.readValue(ARSCDecoder.java:366)
        at brut.androlib.res.decoder.ARSCDecoder.readEntryData(ARSCDecoder.java:285)
        at brut.androlib.res.decoder.ARSCDecoder.readTableType(ARSCDecoder.java:261)
        at brut.androlib.res.decoder.ARSCDecoder.readTableTypeSpec(ARSCDecoder.java:184)
        at brut.androlib.res.decoder.ARSCDecoder.readTablePackage(ARSCDecoder.java:135)
        at brut.androlib.res.decoder.ARSCDecoder.readTableHeader(ARSCDecoder.java:84)
        at brut.androlib.res.decoder.ARSCDecoder.decode(ARSCDecoder.java:50)
        at brut.androlib.res.AndrolibResources.getResPackagesFromApk(AndrolibResources.java:783)
        at brut.androlib.res.AndrolibResources.loadMainPkg(AndrolibResources.java:64)
        at brut.androlib.res.AndrolibResources.getResTable(AndrolibResources.java:56)
        at brut.androlib.Androlib.getResTable(Androlib.java:69)
        at brut.androlib.ApkDecoder.getResTable(ApkDecoder.java:247)
        at brut.androlib.ApkDecoder.decode(ApkDecoder.java:109)
        at brut.apktool.Main.cmdDecode(Main.java:175)
        at brut.apktool.Main.main(Main.java:78)

Steps to Reproduce

  1. java -jar apktool_2.6.0.jar d -p frameworks Settings.apk

APK & Frameworks

https://drive.google.com/file/d/1pHBX9k4_lAhchdXMTJSfeMYiDWklTH94/view?usp=sharing

Issue:

The commit https://github.com/iBotPeaches/Apktool/commit/087142d4cf9cc43f91c9034ee05c9cf020e6b368 messed up the Settings.apk decompilation from the MIUI ROM.

pashamcr avatar Oct 11 '21 09:10 pashamcr

Confirmed. Marking as bug.

iBotPeaches avatar Oct 11 '21 10:10 iBotPeaches

@iBotPeaches solution to the problem: ResXmlEncoders.java

public final class ResXmlEncoders {

    public static String escapeXmlChars(String str) {
        return StringUtils.replace(StringUtils.replace(str, "&", "&amp;"), "<", "&lt;");
    }
...
}

to

import org.apache.commons.text.StringEscapeUtils;

public final class ResXmlEncoders {

    public static String escapeXmlChars(String str) {
        str = StringEscapeUtils.unescapeXml(str);
        str = StringUtils.replace(str, "&", "&amp;");
        str = StringUtils.replace(str, "<", "&lt;");
        return str;
    }
...
}

... strings PT-rPT are still not correct, if you remove them, then recompilation occurs normally.

pashamcr avatar Oct 14 '21 16:10 pashamcr

@pashamcr I'm not following how unescaping XML in a function that is called escaping has anything to do with a proper fix here. Can you give some background on to why you believe this works?

Also, Pull Requests are always available :)

iBotPeaches avatar Oct 17 '21 15:10 iBotPeaches

@iBotPeaches, I changed the code even further:

import org.unbescape.xml.XmlEscape;
import org.unbescape.html.HtmlEscape;

public final class ResXmlEncoders {

    public static String escapeXmlChars(String str) {
        str = XmlEscape.unescapeXml(str);
        str = HtmlEscape.unescapeHtml(str);

        str = StringUtils.replace(str, "&", "&amp;");
        str = StringUtils.replace(str, "<", "&lt;");
        return str;
    }

I can say for sure that apktool is complaining about amp inside the http address:

aapt2 dump resources Settings.apk > res.txt

Normal string: (da) "<Data>For at kunne bruge basisfunktionerne af denne tjeneste, skal du acceptere, at Xiaomi indsamler, bearbejder, og bruger dine personlige data. Se vores fortrolighedspolitik for at finde ud af, hvordan vi indsamler og bearbejder personlige data. Hvis du vælger "Acceptér", betyder det, at du har læst og accepteret vores <a href="https://privacy.mi.com/all/%1$s_%2$s">Fortrolighedspolitik</a> og <a href="http://www.miui.com/res/doc/eula.html?region=%3$s&lang=%4$s">Brugeraftale</a>.​</Data>"

Wrong string: (de) "<Data>Um grundlegende Funktionen dieses Dienstes nutzen zu können, müssen Sie zustimmen, dass Xiaomi Ihre persönlichen Daten erhebt, verarbeitet und nutzt. In unserer Datenschutzerklärung erfahren Sie, wie wir personenbezogene Daten erheben und verarbeiten. "Zustimmen" wählen bedeutet, dass Sie unsere <a href="https://privacy.mi.com/all/%1$s_%2$s">Datenschutzerklärung</a> und <a href="http://www.miui.com/res/doc/eula.html?region=%3$s&amp;lang=%4$s">Nutzervereinbarung</a> gelesen und akzeptiert haben.</Data>"

In the first case in the address &, in the second &amp;

str = StringUtils.replace(str, "&", "&amp;"); changes in the line in the second case &amp; to &amp;amp;

Here's the line after apktool 2.5.1: <string name="privacy_authorize_dialog_message">&lt;Data>Um grundlegende Funktionen dieses Dienstes nutzen zu können, müssen Sie zustimmen, dass Xiaomi Ihre persönlichen Daten erhebt, verarbeitet und nutzt. In unserer Datenschutzerklärung erfahren Sie, wie wir personenbezogene Daten erheben und verarbeiten. \"Zustimmen\" wählen bedeutet, dass Sie unsere &lt;a href=\"https://privacy.mi.com/all/%1$s_%2$s\">Datenschutzerklärung&lt;/a> und &lt;a href=\"http://www.miui.com/res/doc/eula.html?region=%3$s&amp;amp;lang=%4$s\">Nutzervereinbarung&lt;/a> gelesen und akzeptiert haben.&lt;/Data></string>

str = XmlEscape.unescapeXml(str); will bring lines of this type back to normal (apktool 2.6.1 latest snapshot with addition):

<string name="privacy_authorize_dialog_message">&lt;Data>Um grundlegende Funktionen dieses Dienstes nutzen zu können, müssen Sie zustimmen, dass Xiaomi Ihre persönlichen Daten erhebt, verarbeitet und nutzt. In unserer Datenschutzerklärung erfahren Sie, wie wir personenbezogene Daten erheben und verarbeiten. \"Zustimmen\" wählen bedeutet, dass Sie unsere &lt;a href=\"https://privacy.mi.com/all/%1$s_%2$s\">Datenschutzerklärung&lt;/a> und &lt;a href=\"http://www.miui.com/res/doc/eula.html?region=%3$s&amp;lang=%4$s\">Nutzervereinbarung&lt;/a> gelesen und akzeptiert haben.&lt;/Data></string>

str = HtmlEscape.unescapeHtml(str) will make the lines readable:

Snap2

Snap3

Snap4 : After this change, apktool 2.6.1 latest snapshot began to decompile Settings.apk If you or anyone likes it, please create Pull Requests.

pashamcr avatar Oct 17 '21 21:10 pashamcr

thank @pashamcr for the detailed breakdown. It looks like the issue is somewhere prior where we are improperly encoding resources (or just picking a few) while we could probably just use a proper XML encoding process.

iBotPeaches avatar Feb 27 '22 13:02 iBotPeaches

Going to close this one for https://github.com/iBotPeaches/Apktool/issues/2890

I believe the path on this is wrong as the root issue is the new attribute splitter we introduced and not related to escaping/unescaping.

iBotPeaches avatar Sep 21 '22 10:09 iBotPeaches