hsiafan/apk-parser

Bug: library generates invalid manifest XML for APK of Chrome ("com.android.chrome")

Opened this issue · 1 comments

v2.6.10

Given this APK from the emulator:

Chrome.zip

I get this manifest XML file, which is invalid:

chrome manifest.zip

From the first few lines you can see that it's invalid:

<?xml version="1.0" encoding="utf-8"?>
<manifest http://schemas.android.com/apk/res/android:versionCode="373018518" http://schemas.android.com/apk/res/android:versionName="74.0.3729.185" http://schemas.android.com/apk/res/android:compileSdkVersion="29" http://schemas.android.com/apk/res/android:compileSdkVersionCodename="10" package="com.android.chrome" platformBuildVersionCode="29" platformBuildVersionName="10">

For some reason I see "http://schemas.android.com/apk/res/" in many places as if they are attributes.

The parsing of the APK seems to work fine for some reason. Just the generating of the manifest XML file didn't. So I think it's a bug on XmlTranslator.

Attached here a sample project that I used to find about it.

apkParser.zip

Seems I've found where it happens, but I don't know why it is as such:

    private void onAttribute(Attribute attribute) {
        sb.append(" ");
        String namespace = this.namespaces.getPrefixViaUri(attribute.getNamespace());
        if (namespace == null) {
            namespace = attribute.getNamespace();
        }
        if (namespace != null && !namespace.isEmpty()) {
            sb.append(namespace).append(':');
        }

image

Looking where it got this namespace, I can see it's from here:

    private Attribute readAttribute() {
        int nsRef = buffer.getInt();
        int nameRef = buffer.getInt();
        Attribute attribute = new Attribute();
        if (nsRef > 0) {
            attribute.setNamespace(stringPool.get(nsRef));
        }

image

For now, I've fixed it using this workaround:

    private Attribute readAttribute() {
        int nsRef = buffer.getInt();
        int nameRef = buffer.getInt();
        Attribute attribute = new Attribute();
        if (nsRef > 0) {
            String namespace = stringPool.get(nsRef);
            if (!namespace.equals("http://schemas.android.com/apk/res/android"))
               attribute.setNamespace(namespace);
        }

Sample with this workaround:
https://github.com/AndroidDeveloperLB/apk-parser