summaryrefslogtreecommitdiffstats
path: root/libziparchive/zip_archive.cc
diff options
context:
space:
mode:
authorPiotr Jastrzebski <haaawk@google.com>2014-08-11 16:35:11 +0100
committerPiotr Jastrzebski <haaawk@google.com>2014-08-15 12:39:45 +0100
commitecccc5ad9397264d3d05018647b4a2e39d7c774c (patch)
tree3df7aee455f71717f090ca986fc4e22cb89fc47f /libziparchive/zip_archive.cc
parente1ba39aa6644feb9c5f742f65db6d3363203951f (diff)
downloadsystem_core-ecccc5ad9397264d3d05018647b4a2e39d7c774c.zip
system_core-ecccc5ad9397264d3d05018647b4a2e39d7c774c.tar.gz
system_core-ecccc5ad9397264d3d05018647b4a2e39d7c774c.tar.bz2
Replace char* with ZipEntryName in ziparchive API.
It's important because entry names can be encoded in UTF-8 and can have \0 character in the middle. Use vector instead of char* for prefix in IterationHandle. Bug: 16162465 Change-Id: Ie34c8d7c6231cc258530c22bdde5542895213649
Diffstat (limited to 'libziparchive/zip_archive.cc')
-rw-r--r--libziparchive/zip_archive.cc81
1 files changed, 39 insertions, 42 deletions
diff --git a/libziparchive/zip_archive.cc b/libziparchive/zip_archive.cc
index a29eb79..cbe1b14 100644
--- a/libziparchive/zip_archive.cc
+++ b/libziparchive/zip_archive.cc
@@ -29,6 +29,7 @@
#include <unistd.h>
#include <utils/Compat.h>
#include <utils/FileMap.h>
+#include <vector>
#include <zlib.h>
#include <JNIHelp.h> // TEMP_FAILURE_RETRY may or may not be in unistd
@@ -385,8 +386,10 @@ static uint32_t RoundUpPower2(uint32_t val) {
return val;
}
-static uint32_t ComputeHash(const char* str, uint16_t len) {
+static uint32_t ComputeHash(const ZipEntryName& name) {
uint32_t hash = 0;
+ uint16_t len = name.name_length;
+ const uint8_t* str = name.name;
while (len--) {
hash = hash * 31 + *str++;
@@ -401,21 +404,21 @@ static uint32_t ComputeHash(const char* str, uint16_t len) {
*/
static int64_t EntryToIndex(const ZipEntryName* hash_table,
const uint32_t hash_table_size,
- const char* name, uint16_t length) {
- const uint32_t hash = ComputeHash(name, length);
+ const ZipEntryName& name) {
+ const uint32_t hash = ComputeHash(name);
// NOTE: (hash_table_size - 1) is guaranteed to be non-negative.
uint32_t ent = hash & (hash_table_size - 1);
while (hash_table[ent].name != NULL) {
- if (hash_table[ent].name_length == length &&
- memcmp(hash_table[ent].name, name, length) == 0) {
+ if (hash_table[ent].name_length == name.name_length &&
+ memcmp(hash_table[ent].name, name.name, name.name_length) == 0) {
return ent;
}
ent = (ent + 1) & (hash_table_size - 1);
}
- ALOGV("Zip: Unable to find entry %.*s", length, name);
+ ALOGV("Zip: Unable to find entry %.*s", name.name_length, name.name);
return kEntryNotFound;
}
@@ -423,8 +426,8 @@ static int64_t EntryToIndex(const ZipEntryName* hash_table,
* Add a new entry to the hash table.
*/
static int32_t AddToHash(ZipEntryName *hash_table, const uint64_t hash_table_size,
- const char* name, uint16_t length) {
- const uint64_t hash = ComputeHash(name, length);
+ const ZipEntryName& name) {
+ const uint64_t hash = ComputeHash(name);
uint32_t ent = hash & (hash_table_size - 1);
/*
@@ -432,17 +435,17 @@ static int32_t AddToHash(ZipEntryName *hash_table, const uint64_t hash_table_siz
* Further, we guarantee that the hashtable size is not 0.
*/
while (hash_table[ent].name != NULL) {
- if (hash_table[ent].name_length == length &&
- memcmp(hash_table[ent].name, name, length) == 0) {
+ if (hash_table[ent].name_length == name.name_length &&
+ memcmp(hash_table[ent].name, name.name, name.name_length) == 0) {
// We've found a duplicate entry. We don't accept it
- ALOGW("Zip: Found duplicate entry %.*s", length, name);
+ ALOGW("Zip: Found duplicate entry %.*s", name.name_length, name.name);
return kDuplicateEntry;
}
ent = (ent + 1) & (hash_table_size - 1);
}
- hash_table[ent].name = name;
- hash_table[ent].name_length = length;
+ hash_table[ent].name = name.name;
+ hash_table[ent].name_length = name.name_length;
return 0;
}
@@ -640,9 +643,12 @@ static int32_t ParseZipArchive(ZipArchive* archive) {
const uint16_t comment_length = cdr->comment_length;
/* add the CDE filename to the hash table */
- const char* file_name = reinterpret_cast<const char *>(ptr + sizeof(CentralDirectoryRecord));
+ const uint8_t* file_name = ptr + sizeof(CentralDirectoryRecord);
+ ZipEntryName entry_name;
+ entry_name.name = file_name;
+ entry_name.name_length = file_name_length;
const int add_result = AddToHash(archive->hash_table,
- archive->hash_table_size, file_name, file_name_length);
+ archive->hash_table_size, entry_name);
if (add_result) {
ALOGW("Zip: Error adding entry to hash table %d", add_result);
result = add_result;
@@ -751,12 +757,11 @@ static inline ssize_t ReadAtOffset(int fd, uint8_t* buf, size_t len,
static int32_t FindEntry(const ZipArchive* archive, const int ent,
ZipEntry* data) {
const uint16_t nameLen = archive->hash_table[ent].name_length;
- const char* name = archive->hash_table[ent].name;
// Recover the start of the central directory entry from the filename
// pointer. The filename is the first entry past the fixed-size data,
// so we can just subtract back from that.
- const uint8_t* ptr = reinterpret_cast<const uint8_t*>(name);
+ const uint8_t* ptr = archive->hash_table[ent].name;
ptr -= sizeof(CentralDirectoryRecord);
// This is the base of our mmapped region, we have to sanity check that
@@ -847,7 +852,7 @@ static int32_t FindEntry(const ZipArchive* archive, const int ent,
return kIoError;
}
- if (memcmp(name, name_buf, nameLen)) {
+ if (memcmp(archive->hash_table[ent].name, name_buf, nameLen)) {
free(name_buf);
return kInconsistentInformation;
}
@@ -884,12 +889,12 @@ static int32_t FindEntry(const ZipArchive* archive, const int ent,
struct IterationHandle {
uint32_t position;
- const char* prefix;
- uint16_t prefix_len;
+ std::vector<uint8_t> prefix;
ZipArchive* archive;
};
-int32_t StartIteration(ZipArchiveHandle handle, void** cookie_ptr, const char* prefix) {
+int32_t StartIteration(ZipArchiveHandle handle, void** cookie_ptr,
+ const ZipEntryName* optional_prefix) {
ZipArchive* archive = (ZipArchive *) handle;
if (archive == NULL || archive->hash_table == NULL) {
@@ -897,14 +902,13 @@ int32_t StartIteration(ZipArchiveHandle handle, void** cookie_ptr, const char* p
return kInvalidHandle;
}
- IterationHandle* cookie = (IterationHandle*) malloc(sizeof(IterationHandle));
+ IterationHandle* cookie = new IterationHandle();
cookie->position = 0;
cookie->archive = archive;
- if (prefix != NULL) {
- cookie->prefix = strdup(prefix);
- cookie->prefix_len = strlen(prefix);
- } else {
- cookie->prefix = NULL;
+ if (optional_prefix != NULL) {
+ cookie->prefix.insert(cookie->prefix.begin(),
+ optional_prefix->name,
+ optional_prefix->name + optional_prefix->name_length);
}
*cookie_ptr = cookie ;
@@ -912,29 +916,22 @@ int32_t StartIteration(ZipArchiveHandle handle, void** cookie_ptr, const char* p
}
void EndIteration(void* cookie) {
- if (cookie != NULL) {
- IterationHandle* handle = reinterpret_cast<IterationHandle*>(cookie);
- if (handle->prefix != NULL) {
- free(const_cast<char*>(handle->prefix));
- }
- free(cookie);
- }
+ delete reinterpret_cast<IterationHandle*>(cookie);
}
-int32_t FindEntry(const ZipArchiveHandle handle, const char* entryName,
+int32_t FindEntry(const ZipArchiveHandle handle, const ZipEntryName& entryName,
ZipEntry* data) {
const ZipArchive* archive = (ZipArchive*) handle;
- const int nameLen = strlen(entryName);
- if (nameLen == 0 || nameLen > 65535) {
- ALOGW("Zip: Invalid filename %s", entryName);
+ if (entryName.name_length == 0) {
+ ALOGW("Zip: Invalid filename %.*s", entryName.name_length, entryName.name);
return kInvalidEntryName;
}
const int64_t ent = EntryToIndex(archive->hash_table,
- archive->hash_table_size, entryName, nameLen);
+ archive->hash_table_size, entryName);
if (ent < 0) {
- ALOGV("Zip: Could not find entry %.*s", nameLen, entryName);
+ ALOGV("Zip: Could not find entry %.*s", entryName.name_length, entryName.name);
return ent;
}
@@ -959,8 +956,8 @@ int32_t Next(void* cookie, ZipEntry* data, ZipEntryName* name) {
for (uint32_t i = currentOffset; i < hash_table_length; ++i) {
if (hash_table[i].name != NULL &&
- (handle->prefix == NULL ||
- (memcmp(handle->prefix, hash_table[i].name, handle->prefix_len) == 0))) {
+ (handle->prefix.empty() ||
+ (memcmp(&(handle->prefix[0]), hash_table[i].name, handle->prefix.size()) == 0))) {
handle->position = (i + 1);
const int error = FindEntry(archive, i, data);
if (!error) {