diff options
author | Piotr Jastrzebski <haaawk@google.com> | 2014-08-11 16:35:11 +0100 |
---|---|---|
committer | Piotr Jastrzebski <haaawk@google.com> | 2014-08-15 12:39:45 +0100 |
commit | ecccc5ad9397264d3d05018647b4a2e39d7c774c (patch) | |
tree | 3df7aee455f71717f090ca986fc4e22cb89fc47f /libziparchive/zip_archive.cc | |
parent | e1ba39aa6644feb9c5f742f65db6d3363203951f (diff) | |
download | system_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.cc | 81 |
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) { |