Skip to content

Fix -o <app>.apk writing the input archive into classes.dex - #171

Open
monperrus wants to merge 1 commit into
CalebFenton:masterfrom
monperrus:fix/apk-output-classes-dex
Open

Fix -o <app>.apk writing the input archive into classes.dex#171
monperrus wants to merge 1 commit into
CalebFenton:masterfrom
monperrus:fix/apk-output-classes-dex

Conversation

@monperrus

Copy link
Copy Markdown

Running simplify some.apk -o out.apk produces an out.apk whose classes.dex entry is the input APK, not the simplified dex — the output is unusable.

Cause

The option parser sets the output file while iterating over the flags, i.e. SimplifyOptions.setOutFile() runs before setInFile() is called with the positional input path. setOutFile() picks outDexFile based on isZip():

void setOutFile(File outFile) {
    this.outFile = outFile;
    if (isZip()) {
        outDexFile = File.createTempFile("simplify", "dex"); // temp, grafted into the apk later
    } else {
        outDexFile = outFile;
    }
}

But at that point inputType is still null, so isZip() is false and outDexFile is set to outFile itself. For a zip input the Launcher then does:

dexBuilder.writeTo(outDexFile);                 // writes a real dex to out.apk
Files.copy(inFile, outFile, REPLACE_EXISTING);  // overwrites out.apk with the input apk
updateZip(outFile, outDexFile, "classes.dex");  // outDexFile == outFile

so it copies the input APK into the output archive's classes.dex entry.

Fix

Recompute the out dex file in setInFile() once the input type is known (only when an output file was already set), so a zip input gets a distinct temp dex again.

Verification

Before: unzip -p out.apk classes.dex | file -Zip archive data (the input APK).
After: unzip -p out.apk classes.dex | file -Dalvik dex file version 035.

…asses.dex

The argument parser calls setOutFile(-o value) while looping over options,
before setInFile() is called with the positional input path. So when -o is
given, setOutFile runs with inputType still null: isZip() is false and
outDexFile is set to outFile itself instead of a temp dex.

For a zip input the Launcher then does:
  dexBuilder.writeTo(outDexFile);              // writes a dex to out.apk
  Files.copy(inFile, outFile);                 // overwrites out.apk with input
  updateZip(outFile, outDexFile, classes.dex); // outDexFile == outFile now
so it copies the INPUT APK into the output's classes.dex entry, and the
result is unreadable as a dex.

Recompute the out dex file in setInFile once the input type is known (only
when an output file was already set). With this, 'simplify app.apk -o out.apk'
writes the simplified dex into classes.dex; verified the output classes.dex
is a real 'Dalvik dex file' instead of an APK.

Co-Authored-By: Martin Monperrus (AI-assisted) <martin.monperrus+ai@gnieh.org>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant