diff options
author | Tianjie Xu <xunchang@google.com> | 2016-10-10 12:11:30 -0700 |
---|---|---|
committer | Jiyong Park <jiyong@google.com> | 2017-06-30 17:19:28 +0900 |
commit | 9e020e2d117ac389387743c22a30f049c39970c7 (patch) | |
tree | efcefa16d4b8c73e8b2d06d3741beff9d0dc7e25 | |
parent | fba1a36fd912963a838bcf992f898bc5e9370b63 (diff) | |
download | core-9e020e2d117ac389387743c22a30f049c39970c7.tar.gz core-9e020e2d117ac389387743c22a30f049c39970c7.tar.bz2 core-9e020e2d117ac389387743c22a30f049c39970c7.zip |
Check filename memory bound when parsing ziparchive
Add a check to ensure the filename boundary doesn't exceed the mapped
memory region. Also add the corresponding unit test.
Bug: 28802225
Test: New unit test passes.
Merged-In: Ibf543a7da3d7898952e9eb332c84cdfc67cf5aa4
Change-Id: Ibf543a7da3d7898952e9eb332c84cdfc67cf5aa4
(cherry picked from commit bcc4431f240d1ee5bc89c6ab41542e096e07c48c)
-rw-r--r-- | libziparchive/testdata/bad_filename.zip | bin | 0 -> 4119 bytes | |||
-rw-r--r-- | libziparchive/zip_archive.cc | 10 | ||||
-rw-r--r-- | libziparchive/zip_archive_test.cc | 3 |
3 files changed, 13 insertions, 0 deletions
diff --git a/libziparchive/testdata/bad_filename.zip b/libziparchive/testdata/bad_filename.zip Binary files differnew file mode 100644 index 000000000..294eaf562 --- /dev/null +++ b/libziparchive/testdata/bad_filename.zip diff --git a/libziparchive/zip_archive.cc b/libziparchive/zip_archive.cc index efe10966e..0e8536df7 100644 --- a/libziparchive/zip_archive.cc +++ b/libziparchive/zip_archive.cc @@ -316,6 +316,11 @@ static int32_t ParseZipArchive(ZipArchive* archive) { archive->hash_table_size = RoundUpPower2(1 + (num_entries * 4) / 3); archive->hash_table = reinterpret_cast<ZipString*>(calloc(archive->hash_table_size, sizeof(ZipString))); + if (archive->hash_table == nullptr) { + ALOGW("Zip: unable to allocate the %u-entry hash_table, entry size: %zu", + archive->hash_table_size, sizeof(ZipString)); + return -1; + } /* * Walk through the central directory, adding entries to the hash @@ -348,6 +353,11 @@ static int32_t ParseZipArchive(ZipArchive* archive) { const uint16_t comment_length = cdr->comment_length; const uint8_t* file_name = ptr + sizeof(CentralDirectoryRecord); + if (file_name + file_name_length > cd_end) { + ALOGW("Zip: file name boundary exceeds the central directory range, file_name_length: " + "%" PRIx16 ", cd_length: %zu", file_name_length, cd_length); + return -1; + } /* check that file name is valid UTF-8 and doesn't contain NUL (U+0000) characters */ if (!IsValidEntryName(file_name, file_name_length)) { return -1; diff --git a/libziparchive/zip_archive_test.cc b/libziparchive/zip_archive_test.cc index 7653872fa..47f4bbd57 100644 --- a/libziparchive/zip_archive_test.cc +++ b/libziparchive/zip_archive_test.cc @@ -41,6 +41,7 @@ static const std::string kValidZip = "valid.zip"; static const std::string kLargeZip = "large.zip"; static const std::string kBadCrcZip = "bad_crc.zip"; static const std::string kCrashApk = "crash.apk"; +static const std::string kBadFilenameZip = "bad_filename.zip"; static const std::string kUpdateZip = "dummy-update.zip"; static const std::vector<uint8_t> kATxtContents { @@ -86,7 +87,9 @@ static void SetZipString(ZipString* zip_str, const std::string& str) { TEST(ziparchive, Open) { ZipArchiveHandle handle; ASSERT_EQ(0, OpenArchiveWrapper(kValidZip, &handle)); + CloseArchive(handle); + ASSERT_EQ(-1, OpenArchiveWrapper(kBadFilenameZip, &handle)); CloseArchive(handle); } |