Ziparchive: Enable -Wconversion
Enable -Wconversion (but not -Wsign-conversion). Fix up code. Handle some actual error cases: * too many files * files too large Bug: 130039052 Test: atest ziparchive-tests Change-Id: I632af317b9e65dbc728851efefd0d11a2b5c29b9
This commit is contained in:
parent
3a6a01bdee
commit
964b95cf61
9 changed files with 122 additions and 57 deletions
|
@ -26,6 +26,8 @@ cc_defaults {
|
|||
// Incorrectly warns when C++11 empty brace {} initializer is used.
|
||||
// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=61489
|
||||
"-Wno-missing-field-initializers",
|
||||
"-Wconversion",
|
||||
"-Wno-sign-conversion",
|
||||
],
|
||||
|
||||
// Enable -Wold-style-cast only for non-Windows targets. _islower_l,
|
||||
|
|
|
@ -20,9 +20,15 @@
|
|||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <limits>
|
||||
|
||||
// Check if |length| bytes at |entry_name| constitute a valid entry name.
|
||||
// Entry names must be valid UTF-8 and must not contain '0'.
|
||||
// Entry names must be valid UTF-8 and must not contain '0'. They also must
|
||||
// fit into the central directory record.
|
||||
inline bool IsValidEntryName(const uint8_t* entry_name, const size_t length) {
|
||||
if (length > std::numeric_limits<uint16_t>::max()) {
|
||||
return false;
|
||||
}
|
||||
for (size_t i = 0; i < length; ++i) {
|
||||
const uint8_t byte = entry_name[i];
|
||||
if (byte == 0) {
|
||||
|
@ -35,7 +41,8 @@ inline bool IsValidEntryName(const uint8_t* entry_name, const size_t length) {
|
|||
return false;
|
||||
} else {
|
||||
// 2-5 byte sequences.
|
||||
for (uint8_t first = (byte & 0x7f) << 1; first & 0x80; first = (first & 0x7f) << 1) {
|
||||
for (uint8_t first = static_cast<uint8_t>((byte & 0x7f) << 1); first & 0x80;
|
||||
first = static_cast<uint8_t>((first & 0x7f) << 1)) {
|
||||
++i;
|
||||
|
||||
// Missing continuation byte..
|
||||
|
|
|
@ -76,7 +76,7 @@ class ZipWriter {
|
|||
uint32_t uncompressed_size;
|
||||
uint16_t last_mod_time;
|
||||
uint16_t last_mod_date;
|
||||
uint32_t padding_length;
|
||||
uint16_t padding_length;
|
||||
off64_t local_file_header_offset;
|
||||
};
|
||||
|
||||
|
@ -161,8 +161,8 @@ class ZipWriter {
|
|||
|
||||
int32_t HandleError(int32_t error_code);
|
||||
int32_t PrepareDeflate();
|
||||
int32_t StoreBytes(FileEntry* file, const void* data, size_t len);
|
||||
int32_t CompressBytes(FileEntry* file, const void* data, size_t len);
|
||||
int32_t StoreBytes(FileEntry* file, const void* data, uint32_t len);
|
||||
int32_t CompressBytes(FileEntry* file, const void* data, uint32_t len);
|
||||
int32_t FlushCompressedBytes(FileEntry* file);
|
||||
|
||||
enum class State {
|
||||
|
|
|
@ -72,7 +72,7 @@ static bool MakeDirectoryHierarchy(const std::string& path) {
|
|||
|
||||
static int CompressionRatio(int64_t uncompressed, int64_t compressed) {
|
||||
if (uncompressed == 0) return 0;
|
||||
return (100LL * (uncompressed - compressed)) / uncompressed;
|
||||
return static_cast<int>((100LL * (uncompressed - compressed)) / uncompressed);
|
||||
}
|
||||
|
||||
static void MaybeShowHeader() {
|
||||
|
|
|
@ -147,7 +147,7 @@ static int64_t EntryToIndex(const ZipStringOffset* hash_table, const uint32_t ha
|
|||
/*
|
||||
* Add a new entry to the hash table.
|
||||
*/
|
||||
static int32_t AddToHash(ZipStringOffset* hash_table, const uint64_t hash_table_size,
|
||||
static int32_t AddToHash(ZipStringOffset* hash_table, const uint32_t hash_table_size,
|
||||
const ZipString& name, const uint8_t* start) {
|
||||
const uint64_t hash = ComputeHash(name);
|
||||
uint32_t ent = hash & (hash_table_size - 1);
|
||||
|
@ -215,7 +215,7 @@ ZipArchive::~ZipArchive() {
|
|||
}
|
||||
|
||||
static int32_t MapCentralDirectory0(const char* debug_file_name, ZipArchive* archive,
|
||||
off64_t file_length, off64_t read_amount,
|
||||
off64_t file_length, uint32_t read_amount,
|
||||
uint8_t* scan_buffer) {
|
||||
const off64_t search_start = file_length - read_amount;
|
||||
|
||||
|
@ -231,7 +231,8 @@ static int32_t MapCentralDirectory0(const char* debug_file_name, ZipArchive* arc
|
|||
* doing an initial minimal read; if we don't find it, retry with a
|
||||
* second read as above.)
|
||||
*/
|
||||
int i = read_amount - sizeof(EocdRecord);
|
||||
CHECK_LE(read_amount, std::numeric_limits<int32_t>::max());
|
||||
int32_t i = read_amount - sizeof(EocdRecord);
|
||||
for (; i >= 0; i--) {
|
||||
if (scan_buffer[i] == 0x50) {
|
||||
uint32_t* sig_addr = reinterpret_cast<uint32_t*>(&scan_buffer[i]);
|
||||
|
@ -334,9 +335,9 @@ static int32_t MapCentralDirectory(const char* debug_file_name, ZipArchive* arch
|
|||
*
|
||||
* We start by pulling in the last part of the file.
|
||||
*/
|
||||
off64_t read_amount = kMaxEOCDSearch;
|
||||
uint32_t read_amount = kMaxEOCDSearch;
|
||||
if (file_length < read_amount) {
|
||||
read_amount = file_length;
|
||||
read_amount = static_cast<uint32_t>(file_length);
|
||||
}
|
||||
|
||||
std::vector<uint8_t> scan_buffer(read_amount);
|
||||
|
@ -533,7 +534,7 @@ static int32_t ValidateDataDescriptor(MappedZipFile& mapped_zip, ZipEntry* entry
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int32_t FindEntry(const ZipArchive* archive, const int ent, ZipEntry* data) {
|
||||
static int32_t FindEntry(const ZipArchive* archive, const int32_t ent, ZipEntry* data) {
|
||||
const uint16_t nameLen = archive->hash_table[ent].name_length;
|
||||
|
||||
// Recover the start of the central directory entry from the filename
|
||||
|
@ -752,9 +753,10 @@ int32_t FindEntry(const ZipArchiveHandle archive, const ZipString& entryName, Zi
|
|||
archive->central_directory.GetBasePtr());
|
||||
if (ent < 0) {
|
||||
ALOGV("Zip: Could not find entry %.*s", entryName.name_length, entryName.name);
|
||||
return ent;
|
||||
return static_cast<int32_t>(ent); // kEntryNotFound is safe to truncate.
|
||||
}
|
||||
return FindEntry(archive, ent, data);
|
||||
// We know there are at most hast_table_size entries, safe to truncate.
|
||||
return FindEntry(archive, static_cast<uint32_t>(ent), data);
|
||||
}
|
||||
|
||||
int32_t Next(void* cookie, ZipEntry* data, ZipString* name) {
|
||||
|
@ -837,7 +839,6 @@ class FileWriter : public zip_archive::Writer {
|
|||
return FileWriter{};
|
||||
}
|
||||
|
||||
int result = 0;
|
||||
#if defined(__linux__)
|
||||
if (declared_length > 0) {
|
||||
// Make sure we have enough space on the volume to extract the compressed
|
||||
|
@ -849,7 +850,7 @@ class FileWriter : public zip_archive::Writer {
|
|||
// EOPNOTSUPP error when issued in other filesystems.
|
||||
// Hence, check for the return error code before concluding that the
|
||||
// disk does not have enough space.
|
||||
result = TEMP_FAILURE_RETRY(fallocate(fd, 0, current_offset, declared_length));
|
||||
long result = TEMP_FAILURE_RETRY(fallocate(fd, 0, current_offset, declared_length));
|
||||
if (result == -1 && errno == ENOSPC) {
|
||||
ALOGW("Zip: unable to allocate %" PRId64 " bytes at offset %" PRId64 ": %s",
|
||||
static_cast<int64_t>(declared_length), static_cast<int64_t>(current_offset),
|
||||
|
@ -867,7 +868,7 @@ class FileWriter : public zip_archive::Writer {
|
|||
|
||||
// Block device doesn't support ftruncate(2).
|
||||
if (!S_ISBLK(sb.st_mode)) {
|
||||
result = TEMP_FAILURE_RETRY(ftruncate(fd, declared_length + current_offset));
|
||||
long result = TEMP_FAILURE_RETRY(ftruncate(fd, declared_length + current_offset));
|
||||
if (result == -1) {
|
||||
ALOGW("Zip: unable to truncate file to %" PRId64 ": %s",
|
||||
static_cast<int64_t>(declared_length + current_offset), strerror(errno));
|
||||
|
@ -986,16 +987,16 @@ int32_t Inflate(const Reader& reader, const uint32_t compressed_length,
|
|||
std::unique_ptr<z_stream, decltype(zstream_deleter)> zstream_guard(&zstream, zstream_deleter);
|
||||
|
||||
const bool compute_crc = (crc_out != nullptr);
|
||||
uint64_t crc = 0;
|
||||
uLong crc = 0;
|
||||
uint32_t remaining_bytes = compressed_length;
|
||||
do {
|
||||
/* read as much as we can */
|
||||
if (zstream.avail_in == 0) {
|
||||
const size_t read_size = (remaining_bytes > kBufSize) ? kBufSize : remaining_bytes;
|
||||
const uint32_t read_size = (remaining_bytes > kBufSize) ? kBufSize : remaining_bytes;
|
||||
const uint32_t offset = (compressed_length - remaining_bytes);
|
||||
// Make sure to read at offset to ensure concurrent access to the fd.
|
||||
if (!reader.ReadAtOffset(read_buf.data(), read_size, offset)) {
|
||||
ALOGW("Zip: inflate read failed, getSize = %zu: %s", read_size, strerror(errno));
|
||||
ALOGW("Zip: inflate read failed, getSize = %u: %s", read_size, strerror(errno));
|
||||
return kIoError;
|
||||
}
|
||||
|
||||
|
@ -1019,7 +1020,8 @@ int32_t Inflate(const Reader& reader, const uint32_t compressed_length,
|
|||
if (!writer->Append(&write_buf[0], write_size)) {
|
||||
return kIoError;
|
||||
} else if (compute_crc) {
|
||||
crc = crc32(crc, &write_buf[0], write_size);
|
||||
DCHECK_LE(write_size, kBufSize);
|
||||
crc = crc32(crc, &write_buf[0], static_cast<uint32_t>(write_size));
|
||||
}
|
||||
|
||||
zstream.next_out = &write_buf[0];
|
||||
|
@ -1064,17 +1066,17 @@ static int32_t CopyEntryToWriter(MappedZipFile& mapped_zip, const ZipEntry* entr
|
|||
|
||||
const uint32_t length = entry->uncompressed_length;
|
||||
uint32_t count = 0;
|
||||
uint64_t crc = 0;
|
||||
uLong crc = 0;
|
||||
while (count < length) {
|
||||
uint32_t remaining = length - count;
|
||||
off64_t offset = entry->offset + count;
|
||||
|
||||
// Safe conversion because kBufSize is narrow enough for a 32 bit signed value.
|
||||
const size_t block_size = (remaining > kBufSize) ? kBufSize : remaining;
|
||||
const uint32_t block_size = (remaining > kBufSize) ? kBufSize : remaining;
|
||||
|
||||
// Make sure to read at offset to ensure concurrent access to the fd.
|
||||
if (!mapped_zip.ReadAtOffset(buf.data(), block_size, offset)) {
|
||||
ALOGW("CopyFileToFile: copy read failed, block_size = %zu, offset = %" PRId64 ": %s",
|
||||
ALOGW("CopyFileToFile: copy read failed, block_size = %u, offset = %" PRId64 ": %s",
|
||||
block_size, static_cast<int64_t>(offset), strerror(errno));
|
||||
return kIoError;
|
||||
}
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
#include <vector>
|
||||
|
||||
#include <android-base/file.h>
|
||||
#include <android-base/logging.h>
|
||||
#include <log/log.h>
|
||||
|
||||
#include <ziparchive/zip_archive.h>
|
||||
|
@ -77,6 +78,12 @@ bool ZipArchiveStreamEntryUncompressed::Init(const ZipEntry& entry) {
|
|||
}
|
||||
|
||||
const std::vector<uint8_t>* ZipArchiveStreamEntryUncompressed::Read() {
|
||||
// Simple sanity check. The vector should *only* be handled by this code. A caller
|
||||
// should not const-cast and modify the capacity. This may invalidate next_out.
|
||||
//
|
||||
// Note: it would be better to store the results of data() across Read calls.
|
||||
CHECK_EQ(data_.capacity(), kBufSize);
|
||||
|
||||
if (length_ == 0) {
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -97,7 +104,8 @@ const std::vector<uint8_t>* ZipArchiveStreamEntryUncompressed::Read() {
|
|||
if (bytes < data_.size()) {
|
||||
data_.resize(bytes);
|
||||
}
|
||||
computed_crc32_ = crc32(computed_crc32_, data_.data(), data_.size());
|
||||
computed_crc32_ = static_cast<uint32_t>(
|
||||
crc32(computed_crc32_, data_.data(), static_cast<uint32_t>(data_.size())));
|
||||
length_ -= bytes;
|
||||
offset_ += bytes;
|
||||
return &data_;
|
||||
|
@ -192,9 +200,15 @@ bool ZipArchiveStreamEntryCompressed::Verify() {
|
|||
}
|
||||
|
||||
const std::vector<uint8_t>* ZipArchiveStreamEntryCompressed::Read() {
|
||||
// Simple sanity check. The vector should *only* be handled by this code. A caller
|
||||
// should not const-cast and modify the capacity. This may invalidate next_out.
|
||||
//
|
||||
// Note: it would be better to store the results of data() across Read calls.
|
||||
CHECK_EQ(out_.capacity(), kBufSize);
|
||||
|
||||
if (z_stream_.avail_out == 0) {
|
||||
z_stream_.next_out = out_.data();
|
||||
z_stream_.avail_out = out_.size();
|
||||
z_stream_.avail_out = static_cast<uint32_t>(out_.size());
|
||||
;
|
||||
}
|
||||
|
||||
|
@ -203,7 +217,9 @@ const std::vector<uint8_t>* ZipArchiveStreamEntryCompressed::Read() {
|
|||
if (compressed_length_ == 0) {
|
||||
return nullptr;
|
||||
}
|
||||
size_t bytes = (compressed_length_ > in_.size()) ? in_.size() : compressed_length_;
|
||||
DCHECK_LE(in_.size(), std::numeric_limits<uint32_t>::max()); // Should be buf size = 64k.
|
||||
uint32_t bytes = (compressed_length_ > in_.size()) ? static_cast<uint32_t>(in_.size())
|
||||
: compressed_length_;
|
||||
ZipArchive* archive = reinterpret_cast<ZipArchive*>(handle_);
|
||||
errno = 0;
|
||||
if (!archive->mapped_zip.ReadAtOffset(in_.data(), bytes, offset_)) {
|
||||
|
@ -230,14 +246,16 @@ const std::vector<uint8_t>* ZipArchiveStreamEntryCompressed::Read() {
|
|||
|
||||
if (z_stream_.avail_out == 0) {
|
||||
uncompressed_length_ -= out_.size();
|
||||
computed_crc32_ = crc32(computed_crc32_, out_.data(), out_.size());
|
||||
computed_crc32_ = static_cast<uint32_t>(
|
||||
crc32(computed_crc32_, out_.data(), static_cast<uint32_t>(out_.size())));
|
||||
return &out_;
|
||||
}
|
||||
if (zerr == Z_STREAM_END) {
|
||||
if (z_stream_.avail_out != 0) {
|
||||
// Resize the vector down to the actual size of the data.
|
||||
out_.resize(out_.size() - z_stream_.avail_out);
|
||||
computed_crc32_ = crc32(computed_crc32_, out_.data(), out_.size());
|
||||
computed_crc32_ = static_cast<uint32_t>(
|
||||
crc32(computed_crc32_, out_.data(), static_cast<uint32_t>(out_.size())));
|
||||
uncompressed_length_ -= out_.size();
|
||||
return &out_;
|
||||
}
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
#include <vector>
|
||||
|
||||
#include <android-base/file.h>
|
||||
#include <android-base/logging.h>
|
||||
#include <android-base/mapped_file.h>
|
||||
#include <android-base/unique_fd.h>
|
||||
#include <gtest/gtest.h>
|
||||
|
@ -65,7 +66,8 @@ static int32_t OpenArchiveWrapper(const std::string& name, ZipArchiveHandle* han
|
|||
|
||||
static void SetZipString(ZipString* zip_str, const std::string& str) {
|
||||
zip_str->name = reinterpret_cast<const uint8_t*>(str.c_str());
|
||||
zip_str->name_length = str.size();
|
||||
CHECK_LE(str.size(), std::numeric_limits<uint16_t>::max());
|
||||
zip_str->name_length = static_cast<uint16_t>(str.size());
|
||||
}
|
||||
|
||||
TEST(ziparchive, Open) {
|
||||
|
@ -332,7 +334,7 @@ TEST(ziparchive, EntryLargerThan32K) {
|
|||
|
||||
// Extract the entry to memory.
|
||||
std::vector<uint8_t> buffer(kAbUncompressedSize);
|
||||
ASSERT_EQ(0, ExtractToMemory(handle, &entry, &buffer[0], buffer.size()));
|
||||
ASSERT_EQ(0, ExtractToMemory(handle, &entry, &buffer[0], static_cast<uint32_t>(buffer.size())));
|
||||
|
||||
// Extract the entry to a file.
|
||||
TemporaryFile tmp_output_file;
|
||||
|
@ -415,7 +417,8 @@ TEST(ziparchive, OpenFromMemory) {
|
|||
ASSERT_EQ(0, fstat(fd, &sb));
|
||||
|
||||
// Memory map the file first and open the archive from the memory region.
|
||||
auto file_map{android::base::MappedFile::FromFd(fd, 0, sb.st_size, PROT_READ)};
|
||||
auto file_map{
|
||||
android::base::MappedFile::FromFd(fd, 0, static_cast<size_t>(sb.st_size), PROT_READ)};
|
||||
ZipArchiveHandle handle;
|
||||
ASSERT_EQ(0,
|
||||
OpenArchiveFromMemory(file_map->data(), file_map->size(), zip_path.c_str(), &handle));
|
||||
|
@ -488,7 +491,8 @@ static void ZipArchiveStreamTestUsingMemory(const std::string& zip_file,
|
|||
|
||||
std::vector<uint8_t> cmp_data(entry.uncompressed_length);
|
||||
ASSERT_EQ(entry.uncompressed_length, read_data.size());
|
||||
ASSERT_EQ(0, ExtractToMemory(handle, &entry, cmp_data.data(), cmp_data.size()));
|
||||
ASSERT_EQ(
|
||||
0, ExtractToMemory(handle, &entry, cmp_data.data(), static_cast<uint32_t>(cmp_data.size())));
|
||||
ASSERT_TRUE(memcmp(read_data.data(), cmp_data.data(), read_data.size()) == 0);
|
||||
|
||||
CloseArchive(handle);
|
||||
|
@ -737,8 +741,8 @@ class BadWriter : public zip_archive::Writer {
|
|||
};
|
||||
|
||||
TEST(ziparchive, Inflate) {
|
||||
const uint32_t compressed_length = kATxtContentsCompressed.size();
|
||||
const uint32_t uncompressed_length = kATxtContents.size();
|
||||
const uint32_t compressed_length = static_cast<uint32_t>(kATxtContentsCompressed.size());
|
||||
const uint32_t uncompressed_length = static_cast<uint32_t>(kATxtContents.size());
|
||||
|
||||
const VectorReader reader(kATxtContentsCompressed);
|
||||
{
|
||||
|
|
|
@ -169,8 +169,8 @@ static void ExtractTimeAndDate(time_t when, uint16_t* out_time, uint16_t* out_da
|
|||
year = 80;
|
||||
}
|
||||
|
||||
*out_date = (year - 80) << 9 | (ptm->tm_mon + 1) << 5 | ptm->tm_mday;
|
||||
*out_time = ptm->tm_hour << 11 | ptm->tm_min << 5 | ptm->tm_sec >> 1;
|
||||
*out_date = static_cast<uint16_t>((year - 80) << 9 | (ptm->tm_mon + 1) << 5 | ptm->tm_mday);
|
||||
*out_time = static_cast<uint16_t>(ptm->tm_hour << 11 | ptm->tm_min << 5 | ptm->tm_sec >> 1);
|
||||
}
|
||||
|
||||
static void CopyFromFileEntry(const ZipWriter::FileEntry& src, bool use_data_descriptor,
|
||||
|
@ -193,7 +193,8 @@ static void CopyFromFileEntry(const ZipWriter::FileEntry& src, bool use_data_des
|
|||
dst->compression_method = src.compression_method;
|
||||
dst->last_mod_time = src.last_mod_time;
|
||||
dst->last_mod_date = src.last_mod_date;
|
||||
dst->file_name_length = src.path.size();
|
||||
DCHECK_LE(src.path.size(), std::numeric_limits<uint16_t>::max());
|
||||
dst->file_name_length = static_cast<uint16_t>(src.path.size());
|
||||
dst->extra_field_length = src.padding_length;
|
||||
}
|
||||
|
||||
|
@ -203,6 +204,11 @@ int32_t ZipWriter::StartAlignedEntryWithTime(const char* path, size_t flags, tim
|
|||
return kInvalidState;
|
||||
}
|
||||
|
||||
// Can only have 16535 entries because of zip records.
|
||||
if (files_.size() == std::numeric_limits<uint16_t>::max()) {
|
||||
return HandleError(kIoError);
|
||||
}
|
||||
|
||||
if (flags & kAlign32) {
|
||||
return kInvalidAlign32Flag;
|
||||
}
|
||||
|
@ -210,10 +216,17 @@ int32_t ZipWriter::StartAlignedEntryWithTime(const char* path, size_t flags, tim
|
|||
if (powerof2(alignment) == 0) {
|
||||
return kInvalidAlignment;
|
||||
}
|
||||
if (alignment > std::numeric_limits<uint16_t>::max()) {
|
||||
return kInvalidAlignment;
|
||||
}
|
||||
|
||||
FileEntry file_entry = {};
|
||||
file_entry.local_file_header_offset = current_offset_;
|
||||
file_entry.path = path;
|
||||
// No support for larger than 4GB files.
|
||||
if (file_entry.local_file_header_offset > std::numeric_limits<uint32_t>::max()) {
|
||||
return HandleError(kIoError);
|
||||
}
|
||||
|
||||
if (!IsValidEntryName(reinterpret_cast<const uint8_t*>(file_entry.path.data()),
|
||||
file_entry.path.size())) {
|
||||
|
@ -237,7 +250,7 @@ int32_t ZipWriter::StartAlignedEntryWithTime(const char* path, size_t flags, tim
|
|||
std::vector<char> zero_padding;
|
||||
if (alignment != 0 && (offset & (alignment - 1))) {
|
||||
// Pad the extra field so the data will be aligned.
|
||||
uint16_t padding = alignment - (offset % alignment);
|
||||
uint16_t padding = static_cast<uint16_t>(alignment - (offset % alignment));
|
||||
file_entry.padding_length = padding;
|
||||
offset += padding;
|
||||
zero_padding.resize(padding, 0);
|
||||
|
@ -314,7 +327,8 @@ int32_t ZipWriter::PrepareDeflate() {
|
|||
}
|
||||
|
||||
z_stream_->next_out = buffer_.data();
|
||||
z_stream_->avail_out = buffer_.size();
|
||||
DCHECK_EQ(buffer_.size(), kBufSize);
|
||||
z_stream_->avail_out = static_cast<uint32_t>(buffer_.size());
|
||||
return kNoError;
|
||||
}
|
||||
|
||||
|
@ -322,25 +336,31 @@ int32_t ZipWriter::WriteBytes(const void* data, size_t len) {
|
|||
if (state_ != State::kWritingEntry) {
|
||||
return HandleError(kInvalidState);
|
||||
}
|
||||
// Need to be able to mark down data correctly.
|
||||
if (len + static_cast<uint64_t>(current_file_entry_.uncompressed_size) >
|
||||
std::numeric_limits<uint32_t>::max()) {
|
||||
return HandleError(kIoError);
|
||||
}
|
||||
uint32_t len32 = static_cast<uint32_t>(len);
|
||||
|
||||
int32_t result = kNoError;
|
||||
if (current_file_entry_.compression_method & kCompressDeflated) {
|
||||
result = CompressBytes(¤t_file_entry_, data, len);
|
||||
result = CompressBytes(¤t_file_entry_, data, len32);
|
||||
} else {
|
||||
result = StoreBytes(¤t_file_entry_, data, len);
|
||||
result = StoreBytes(¤t_file_entry_, data, len32);
|
||||
}
|
||||
|
||||
if (result != kNoError) {
|
||||
return result;
|
||||
}
|
||||
|
||||
current_file_entry_.crc32 =
|
||||
crc32(current_file_entry_.crc32, reinterpret_cast<const Bytef*>(data), len);
|
||||
current_file_entry_.uncompressed_size += len;
|
||||
current_file_entry_.crc32 = static_cast<uint32_t>(
|
||||
crc32(current_file_entry_.crc32, reinterpret_cast<const Bytef*>(data), len32));
|
||||
current_file_entry_.uncompressed_size += len32;
|
||||
return kNoError;
|
||||
}
|
||||
|
||||
int32_t ZipWriter::StoreBytes(FileEntry* file, const void* data, size_t len) {
|
||||
int32_t ZipWriter::StoreBytes(FileEntry* file, const void* data, uint32_t len) {
|
||||
CHECK(state_ == State::kWritingEntry);
|
||||
|
||||
if (fwrite(data, 1, len, file_) != len) {
|
||||
|
@ -351,7 +371,7 @@ int32_t ZipWriter::StoreBytes(FileEntry* file, const void* data, size_t len) {
|
|||
return kNoError;
|
||||
}
|
||||
|
||||
int32_t ZipWriter::CompressBytes(FileEntry* file, const void* data, size_t len) {
|
||||
int32_t ZipWriter::CompressBytes(FileEntry* file, const void* data, uint32_t len) {
|
||||
CHECK(state_ == State::kWritingEntry);
|
||||
CHECK(z_stream_);
|
||||
CHECK(z_stream_->next_out != nullptr);
|
||||
|
@ -379,7 +399,8 @@ int32_t ZipWriter::CompressBytes(FileEntry* file, const void* data, size_t len)
|
|||
|
||||
// Reset the output buffer for the next input.
|
||||
z_stream_->next_out = buffer_.data();
|
||||
z_stream_->avail_out = buffer_.size();
|
||||
DCHECK_EQ(buffer_.size(), kBufSize);
|
||||
z_stream_->avail_out = static_cast<uint32_t>(buffer_.size());
|
||||
}
|
||||
}
|
||||
return kNoError;
|
||||
|
@ -404,7 +425,8 @@ int32_t ZipWriter::FlushCompressedBytes(FileEntry* file) {
|
|||
current_offset_ += write_bytes;
|
||||
|
||||
z_stream_->next_out = buffer_.data();
|
||||
z_stream_->avail_out = buffer_.size();
|
||||
DCHECK_EQ(buffer_.size(), kBufSize);
|
||||
z_stream_->avail_out = static_cast<uint32_t>(buffer_.size());
|
||||
}
|
||||
if (zerr != Z_STREAM_END) {
|
||||
return HandleError(kZlibError);
|
||||
|
@ -491,7 +513,11 @@ int32_t ZipWriter::Finish() {
|
|||
cdr.crc32 = file.crc32;
|
||||
cdr.compressed_size = file.compressed_size;
|
||||
cdr.uncompressed_size = file.uncompressed_size;
|
||||
cdr.file_name_length = file.path.size();
|
||||
// Checked in IsValidEntryName.
|
||||
DCHECK_LE(file.path.size(), std::numeric_limits<uint16_t>::max());
|
||||
cdr.file_name_length = static_cast<uint16_t>(file.path.size());
|
||||
// Checked in StartAlignedEntryWithTime.
|
||||
DCHECK_LE(file.local_file_header_offset, std::numeric_limits<uint32_t>::max());
|
||||
cdr.local_file_header_offset = static_cast<uint32_t>(file.local_file_header_offset);
|
||||
if (fwrite(&cdr, sizeof(cdr), 1, file_) != 1) {
|
||||
return HandleError(kIoError);
|
||||
|
@ -508,10 +534,15 @@ int32_t ZipWriter::Finish() {
|
|||
er.eocd_signature = EocdRecord::kSignature;
|
||||
er.disk_num = 0;
|
||||
er.cd_start_disk = 0;
|
||||
er.num_records_on_disk = files_.size();
|
||||
er.num_records = files_.size();
|
||||
er.cd_size = current_offset_ - startOfCdr;
|
||||
er.cd_start_offset = startOfCdr;
|
||||
// Checked when adding entries.
|
||||
DCHECK_LE(files_.size(), std::numeric_limits<uint16_t>::max());
|
||||
er.num_records_on_disk = static_cast<uint16_t>(files_.size());
|
||||
er.num_records = static_cast<uint16_t>(files_.size());
|
||||
if (current_offset_ > std::numeric_limits<uint32_t>::max()) {
|
||||
return HandleError(kIoError);
|
||||
}
|
||||
er.cd_size = static_cast<uint32_t>(current_offset_ - startOfCdr);
|
||||
er.cd_start_offset = static_cast<uint32_t>(startOfCdr);
|
||||
|
||||
if (fwrite(&er, sizeof(er), 1, file_) != 1) {
|
||||
return HandleError(kIoError);
|
||||
|
|
|
@ -257,7 +257,7 @@ TEST_F(zipwriter, WriteCompressedZipFlushFull) {
|
|||
std::vector<uint8_t> buffer(kBufSize);
|
||||
size_t prev = 1;
|
||||
for (size_t i = 0; i < kBufSize; i++) {
|
||||
buffer[i] = i + prev;
|
||||
buffer[i] = static_cast<uint8_t>(i + prev);
|
||||
prev = i;
|
||||
}
|
||||
|
||||
|
@ -279,7 +279,8 @@ TEST_F(zipwriter, WriteCompressedZipFlushFull) {
|
|||
|
||||
std::vector<uint8_t> decompress(kBufSize);
|
||||
memset(decompress.data(), 0, kBufSize);
|
||||
ASSERT_EQ(0, ExtractToMemory(handle, &data, decompress.data(), decompress.size()));
|
||||
ASSERT_EQ(0, ExtractToMemory(handle, &data, decompress.data(),
|
||||
static_cast<uint32_t>(decompress.size())));
|
||||
EXPECT_EQ(0, memcmp(decompress.data(), buffer.data(), kBufSize))
|
||||
<< "Input buffer and output buffer are different.";
|
||||
|
||||
|
@ -391,7 +392,7 @@ static ::testing::AssertionResult AssertFileEntryContentsEq(const std::string& e
|
|||
actual.resize(expected.size());
|
||||
|
||||
uint8_t* buffer = reinterpret_cast<uint8_t*>(&*actual.begin());
|
||||
if (ExtractToMemory(handle, zip_entry, buffer, actual.size()) != 0) {
|
||||
if (ExtractToMemory(handle, zip_entry, buffer, static_cast<uint32_t>(actual.size())) != 0) {
|
||||
return ::testing::AssertionFailure() << "failed to extract entry";
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue