skylot / jadx

Dex to Java decompiler
Apache License 2.0
41.81k stars 4.88k forks source link

Jadx can not parse resource type chunks with unordered entries #2343

Closed shifoc closed 3 days ago

shifoc commented 4 days ago

Issue details

https://www.apkmirror.com/apk/whatsapp-inc/whatsapp/whatsapp-2-24-24-14-release/whatsapp-messenger-2-24-24-14-android-apk-download/

Relevant log output or stacktrace

ERROR - Failed to parse 'resources.pb'/'.arsc' file
jadx.core.utils.exceptions.JadxException: Error decode: resources.arsc
    at jadx.api.ResourcesLoader.decodeStream(ResourcesLoader.java:118)
    at jadx.core.dex.nodes.RootNode.loadResources(RootNode.java:212)
    at jadx.api.JadxDecompiler.load(JadxDecompiler.java:128)
    at jadx.cli.JadxCLI.processAndSave(JadxCLI.java:59)
    at jadx.cli.JadxCLI.execute(JadxCLI.java:37)
    at jadx.cli.JadxCLI.main(JadxCLI.java:27)
Caused by: java.io.IOException: Expected start of entry 1, expected offset: 0x1f02f4, actual: 0x1f0304
    at jadx.core.xmlgen.ParserStream.checkPos(ParserStream.java:125)
    at jadx.core.xmlgen.ResTableBinaryParser.parseTypeChunk(ResTableBinaryParser.java:289)
    at jadx.core.xmlgen.ResTableBinaryParser.parsePackage(ResTableBinaryParser.java:164)
    at jadx.core.xmlgen.ResTableBinaryParser.decodeTableChunk(ResTableBinaryParser.java:111)
    at jadx.core.xmlgen.ResTableBinaryParser.decode(ResTableBinaryParser.java:84)
    at jadx.api.ResourcesLoader.decodeTable(ResourcesLoader.java:173)
    at jadx.core.dex.nodes.RootNode.lambda$loadResources$7(RootNode.java:212)
    at jadx.api.ResourcesLoader.decodeStream(ResourcesLoader.java:113)
    ... 5 common frames omitted
INFO  - processing ...
INFO  - done

Provide sample and class/method full name

No response

Jadx version

1.5.1

jpstotz commented 3 days ago

The expected offset: 0x1f02f4 is smaller than the actual offset 0x1f0304 - assuming that the index is correct that would mean we would have to jump backwards - which is currently not possible as we are using an InputStream that can only jump forward, not backward.

The only way to work around this problem would be always using a BufferedInputStream and if this happens reset() the stream to go back e.g. to the beginning of the chunk. That would allow us to go back if the chunk is not larger than the taget offset we want to reach.