Zipalign: Don't align directory entries
Directories are entries with uncompressed size zero and ending with character '/' or '\' are allowed in apks since b/204425803. These entries should not be considered for alignment since they are not mmap by the framework. Test: align_test.cpp Bug: 250872480 Change-Id: I964aad118a82839f9ed230acc4c2c76f51888c67
This commit is contained in:
@@ -70,6 +70,7 @@ cc_test_host {
|
||||
"libgmock",
|
||||
],
|
||||
data: [
|
||||
"tests/data/archiveWithOneDirectoryEntry.zip",
|
||||
"tests/data/diffOrders.zip",
|
||||
"tests/data/holes.zip",
|
||||
"tests/data/unaligned.zip",
|
||||
|
@@ -22,6 +22,19 @@
|
||||
|
||||
namespace android {
|
||||
|
||||
// An entry is considered a directory if it has a stored size of zero
|
||||
// and it ends with '/' or '\' character.
|
||||
static bool isDirectory(ZipEntry* entry) {
|
||||
if (entry->getUncompressedLen() != 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const char* name = entry->getFileName();
|
||||
size_t nameLength = strlen(name);
|
||||
char lastChar = name[nameLength-1];
|
||||
return lastChar == '/' || lastChar == '\\';
|
||||
}
|
||||
|
||||
static int getAlignment(bool pageAlignSharedLibs, int defaultAlignment,
|
||||
ZipEntry* pEntry) {
|
||||
|
||||
@@ -59,7 +72,7 @@ static int copyAndAlign(ZipFile* pZin, ZipFile* pZout, int alignment, bool zopfl
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (pEntry->isCompressed()) {
|
||||
if (pEntry->isCompressed() || isDirectory(pEntry)) {
|
||||
/* copy the entry without padding */
|
||||
//printf("--- %s: orig at %ld len=%ld (compressed)\n",
|
||||
// pEntry->getFileName(), (long) pEntry->getFileOffset(),
|
||||
@@ -160,7 +173,13 @@ int verify(const char* fileName, int alignment, bool verbose,
|
||||
printf("%8jd %s (OK - compressed)\n",
|
||||
(intmax_t) pEntry->getFileOffset(), pEntry->getFileName());
|
||||
}
|
||||
} else {
|
||||
} else if(isDirectory(pEntry)) {
|
||||
// Directory entries do not need to be aligned.
|
||||
if (verbose)
|
||||
printf("%8jd %s (OK - directory)\n",
|
||||
(intmax_t) pEntry->getFileOffset(), pEntry->getFileName());
|
||||
continue;
|
||||
} else {
|
||||
off_t offset = pEntry->getFileOffset();
|
||||
const int alignTo = getAlignment(pageAlignSharedLibs, alignment, pEntry);
|
||||
if ((offset % alignTo) != 0) {
|
||||
|
BIN
tools/zipalign/tests/data/archiveWithOneDirectoryEntry.zip
Normal file
BIN
tools/zipalign/tests/data/archiveWithOneDirectoryEntry.zip
Normal file
Binary file not shown.
@@ -12,6 +12,28 @@
|
||||
using namespace android;
|
||||
using namespace base;
|
||||
|
||||
// This load the whole file to memory so be careful!
|
||||
static bool sameContent(const std::string& path1, const std::string& path2) {
|
||||
std::string f1;
|
||||
if (!ReadFileToString(path1, &f1)) {
|
||||
printf("Unable to read '%s' content: %m\n", path1.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string f2;
|
||||
if (!ReadFileToString(path2, &f2)) {
|
||||
printf("Unable to read '%s' content %m\n", path1.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
if (f1.size() != f2.size()) {
|
||||
printf("File '%s' and '%s' are not the same\n", path1.c_str(), path2.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
return f1.compare(f2) == 0;
|
||||
}
|
||||
|
||||
static std::string GetTestPath(const std::string& filename) {
|
||||
static std::string test_data_dir = android::base::GetExecutableDirectory() + "/tests/data/";
|
||||
return test_data_dir + filename;
|
||||
@@ -87,3 +109,21 @@ TEST(Align, DifferenteOrders) {
|
||||
int verified = verify(dst.c_str(), 4, false, true);
|
||||
ASSERT_EQ(0, verified);
|
||||
}
|
||||
|
||||
TEST(Align, DirectoryEntryDoNotRequireAlignment) {
|
||||
const std::string src = GetTestPath("archiveWithOneDirectoryEntry.zip");
|
||||
int verified = verify(src.c_str(), 4, false, true);
|
||||
ASSERT_EQ(0, verified);
|
||||
}
|
||||
|
||||
TEST(Align, DirectoryEntry) {
|
||||
const std::string src = GetTestPath("archiveWithOneDirectoryEntry.zip");
|
||||
const std::string dst = GetTempPath("archiveWithOneDirectoryEntry_out.zip");
|
||||
|
||||
int processed = process(src.c_str(), dst.c_str(), 4, true, false, 4096);
|
||||
ASSERT_EQ(0, processed);
|
||||
ASSERT_EQ(true, sameContent(src, dst));
|
||||
|
||||
int verified = verify(dst.c_str(), 4, false, true);
|
||||
ASSERT_EQ(0, verified);
|
||||
}
|
||||
|
Reference in New Issue
Block a user