-
Notifications
You must be signed in to change notification settings - Fork 49
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
ZipAlign creates corrupted APK for already aligned APK #27
Comments
I am also reiterating the need for #6. Adding tests would greatly reduce issues like this. I feel that most issues I opened here could've been resolved if there were adequate tests. |
I haven't encountered this myself, but my guess is that it occurs because this line assumes all compressed entries have a data descriptor, which may not always be the case. |
Well, I need to look into this. But the Here's the source code: https://github.com/MuntashirAkon/zipalign-android/blob/master/zipalign/src/main/cpp/zipalign/ZipAlign.cpp#L124-L168 Seems quite easy to implement. I can implement that if you want. |
Well, I've tried about a dozen APK files, each of them has this issue. So, I believe that most of them do not have a data descriptor. But is there a way to actually detect this using the ZipFile API? I don't see any option to do that. And how it is that it only affects signed APK files, and not unsigned ones? |
ZipAlign is borrowed class and I am not full understood it. But my guess is that at line 149 Now I am focusing on new archive management lib archive2 which also solves such issue, until then hopefully someone will find a solution. |
I dont think there is, since the Java Zip library does not expose flags. Pull request #21 uses a different zip implementation, so its possible its not affected by the issue. I havent tested the static methods on ZipAlign much, but if you do test it only to find that its broken, please let me know |
Oh @Axelen123 is right, the problem was "flag" is calculated based on assumption that all non-STORED entries have Until archive2 ready , here is my ugly commit |
It didn't work. It still fails with the following error:
|
Anyways if you are interested, archive2 is ready now for early experiment |
No, hidden API enforcement policies are bypassed. It's something to do with calculating the offsets, I think. |
Getting NPE for some APKs: java.lang.NullPointerException: Attempt to invoke virtual method 'long com.reandroid.archive2.block.CentralEntryHeader.getCrc()' on a null object reference Let me know if you need a sample. |
Another similar NPE:
|
The new API works great except the aforementioned cases. BTW, here's the class I use for verification (it was converted from the ZipAlign library for Android): ZipAlignVerifier.javapublic class ZipAlignVerifier {
public static final String TAG = ZipAlignVerifier.class.getSimpleName();
public static final int kPageAlignment = 4096;
public static boolean verify(File file, int alignment, boolean pageAlignSharedLibs) {
Archive zipFile;
boolean foundBad = false;
Log.d(TAG, String.format(Locale.ROOT, "Verifying alignment of %s (%d)...\n", file, alignment));
try {
zipFile = new Archive(file);
} catch (IOException e) {
Log.e(TAG, String.format(Locale.ROOT, "Unable to open '%s' for verification\n", file), e);
return false;
}
List<ArchiveEntry> entries = zipFile.getEntryList();
long lastFileOffset;
for (ArchiveEntry pEntry : entries) {
String name = pEntry.getName();
lastFileOffset = pEntry.getFileOffset();
if (pEntry.getMethod() == ZipEntry.DEFLATED) {
Log.d(TAG, String.format(Locale.ROOT, "%8d %s (OK - compressed)\n", lastFileOffset, name));
} else if (pEntry.isDirectory()) {
// Directory entries do not need to be aligned.
Log.d(TAG, String.format(Locale.ROOT, "%8d %s (OK - directory)\n", lastFileOffset, name));
} else {
int alignTo = getAlignment(pageAlignSharedLibs, alignment, pEntry);
if ((lastFileOffset % alignTo) != 0) {
Log.w(TAG, String.format(Locale.ROOT, "%8d %s (BAD - %d)\n", lastFileOffset, name, (lastFileOffset % alignTo)));
foundBad = true;
break;
} else {
Log.d(TAG, String.format(Locale.ROOT, "%8d %s (OK)\n", lastFileOffset, name));
}
}
}
Log.d(TAG, String.format(Locale.ROOT, "Verification %s\n", foundBad ? "FAILED" : "successful"));
return !foundBad;
}
private static int getAlignment(boolean pageAlignSharedLibs, int defaultAlignment, ZipEntry pEntry) {
if (!pageAlignSharedLibs) {
return defaultAlignment;
}
if (pEntry.getName().endsWith(".so")) {
return kPageAlignment;
}
return defaultAlignment;
}
} |
Thanks I was hopping someone to test it on android os, how is the performance relative to old API ? |
Yes please |
(Just remove the zip extension) |
Is this compressed by archive2 ? |
No, this is just an example APK file which archive2 fails to open. |
All working fine with |
Here's the method I used for aligning an APK file: public static void align(File input, File output) throws IOException {
File dir = output.getParentFile();
if (dir != null && !dir.exists()) {
dir.mkdirs();
}
Archive archive = new Archive(input);
try (ApkWriter apkWriter = new ApkWriter(output, archive.mapEntrySource().values())) {
apkWriter.write();
}
if (!ZipAlignVerifier.verify(output, 4, true)) {
throw new IOException("Could not verify aligned APK file.");
}
} Before aligning the file, the verifier outputs the following error:
After aligning the file, I still get a failure:
Conclusion |
Thanks for your excellent testing report! You can control each file alignment as: public static void align(File input, File output) throws IOException {
File dir = output.getParentFile();
if (dir != null && !dir.exists()) {
dir.mkdirs();
}
Archive archive = new Archive(input);
ApkWriter apkWriter = new ApkWriter(output, archive.mapEntrySource().values());
ZipAligner zipAligner = new ZipAligner();
zipAligner.setDefaultAlignment(4);
zipAligner.clearFileAlignment();
// see ZipAligner.apkAligner();
apkWriter.write();
if (!ZipAlignVerifier.verify(output, 4, true)) {
throw new IOException("Could not verify aligned APK file.");
}
} NB: Updated with this commit |
The aligner for archive2 should work properly in #31. |
Getting this error:
|
Did you checked this commit |
Thanks. All known issues seem to have been fixed. |
Title says it all. In case you're wondering why it's necessary, we don't know if an APK is aligned or not in first place. So, we need to do that for both aligned and unaligned APKs.
The text was updated successfully, but these errors were encountered: