zip_archive: Allow crc_out to be nullptr in Inflate.
Only compute the crc32 if required. In addition : - Add unit tests for Inflate that cover this addition. - Fix an inconsistency in return codes that was revealed by this new test. Bug: 35246701 Test: zip_archive_tests Test: make; zipalign. Merged-In: I31d7554378f94fc8995f707471d57cb98311e2c2 Change-Id: I05111bfa665c610f93d1c1dee987a509bf87aa65
This commit is contained in:
parent
51ec0a1387
commit
2d1e23f5d6
3 changed files with 96 additions and 4 deletions
|
@ -265,6 +265,9 @@ class Reader {
|
|||
* Returns 0 on success and negative values on failure, for example if |reader|
|
||||
* cannot supply the right amount of data, or if the number of bytes written to
|
||||
* data does not match |uncompressed_length|.
|
||||
*
|
||||
* If |crc_out| is not nullptr, it is set to the crc32 checksum of the
|
||||
* uncompressed data.
|
||||
*/
|
||||
int32_t Inflate(const Reader& reader, const uint32_t compressed_length,
|
||||
const uint32_t uncompressed_length, Writer* writer, uint64_t* crc_out);
|
||||
|
|
|
@ -908,6 +908,7 @@ 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;
|
||||
uint32_t remaining_bytes = compressed_length;
|
||||
do {
|
||||
|
@ -939,9 +940,8 @@ int32_t Inflate(const Reader& reader, const uint32_t compressed_length,
|
|||
if (zstream.avail_out == 0 || (zerr == Z_STREAM_END && zstream.avail_out != kBufSize)) {
|
||||
const size_t write_size = zstream.next_out - &write_buf[0];
|
||||
if (!writer->Append(&write_buf[0], write_size)) {
|
||||
// The file might have declared a bogus length.
|
||||
return kInconsistentInformation;
|
||||
} else {
|
||||
return kIoError;
|
||||
} else if (compute_crc) {
|
||||
crc = crc32(crc, &write_buf[0], write_size);
|
||||
}
|
||||
|
||||
|
@ -958,7 +958,9 @@ int32_t Inflate(const Reader& reader, const uint32_t compressed_length,
|
|||
// it ourselves above because there are no additional gains to be made by
|
||||
// having zlib calculate it for us, since they do it by calling crc32 in
|
||||
// the same manner that we have above.
|
||||
*crc_out = crc;
|
||||
if (compute_crc) {
|
||||
*crc_out = crc;
|
||||
}
|
||||
|
||||
if (zstream.total_out != uncompressed_length || remaining_bytes != 0) {
|
||||
ALOGW("Zip: size mismatch on inflated file (%lu vs %" PRIu32 ")", zstream.total_out,
|
||||
|
|
|
@ -717,6 +717,93 @@ TEST(ziparchive, ErrorCodeString) {
|
|||
ASSERT_STREQ("I/O error", ErrorCodeString(kIoError));
|
||||
}
|
||||
|
||||
class VectorReader : public zip_archive::Reader {
|
||||
public:
|
||||
VectorReader(const std::vector<uint8_t>& input) : Reader(), input_(input) {}
|
||||
|
||||
bool ReadAtOffset(uint8_t* buf, size_t len, uint32_t offset) const {
|
||||
if ((offset + len) < input_.size()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
memcpy(buf, &input_[offset], len);
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
const std::vector<uint8_t>& input_;
|
||||
};
|
||||
|
||||
class VectorWriter : public zip_archive::Writer {
|
||||
public:
|
||||
VectorWriter() : Writer() {}
|
||||
|
||||
bool Append(uint8_t* buf, size_t size) {
|
||||
output_.insert(output_.end(), buf, buf + size);
|
||||
return true;
|
||||
}
|
||||
|
||||
std::vector<uint8_t>& GetOutput() { return output_; }
|
||||
|
||||
private:
|
||||
std::vector<uint8_t> output_;
|
||||
};
|
||||
|
||||
class BadReader : public zip_archive::Reader {
|
||||
public:
|
||||
BadReader() : Reader() {}
|
||||
|
||||
bool ReadAtOffset(uint8_t*, size_t, uint32_t) const { return false; }
|
||||
};
|
||||
|
||||
class BadWriter : public zip_archive::Writer {
|
||||
public:
|
||||
BadWriter() : Writer() {}
|
||||
|
||||
bool Append(uint8_t*, size_t) { return false; }
|
||||
};
|
||||
|
||||
TEST(ziparchive, Inflate) {
|
||||
const uint32_t compressed_length = kATxtContentsCompressed.size();
|
||||
const uint32_t uncompressed_length = kATxtContents.size();
|
||||
|
||||
const VectorReader reader(kATxtContentsCompressed);
|
||||
{
|
||||
VectorWriter writer;
|
||||
uint64_t crc_out = 0;
|
||||
|
||||
int32_t ret =
|
||||
zip_archive::Inflate(reader, compressed_length, uncompressed_length, &writer, &crc_out);
|
||||
ASSERT_EQ(0, ret);
|
||||
ASSERT_EQ(kATxtContents, writer.GetOutput());
|
||||
ASSERT_EQ(0x950821C5u, crc_out);
|
||||
}
|
||||
|
||||
{
|
||||
VectorWriter writer;
|
||||
int32_t ret =
|
||||
zip_archive::Inflate(reader, compressed_length, uncompressed_length, &writer, nullptr);
|
||||
ASSERT_EQ(0, ret);
|
||||
ASSERT_EQ(kATxtContents, writer.GetOutput());
|
||||
}
|
||||
|
||||
{
|
||||
BadWriter writer;
|
||||
int32_t ret =
|
||||
zip_archive::Inflate(reader, compressed_length, uncompressed_length, &writer, nullptr);
|
||||
ASSERT_EQ(kIoError, ret);
|
||||
}
|
||||
|
||||
{
|
||||
BadReader reader;
|
||||
VectorWriter writer;
|
||||
int32_t ret =
|
||||
zip_archive::Inflate(reader, compressed_length, uncompressed_length, &writer, nullptr);
|
||||
ASSERT_EQ(kIoError, ret);
|
||||
ASSERT_EQ(0u, writer.GetOutput().size());
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
::testing::InitGoogleTest(&argc, argv);
|
||||
|
||||
|
|
Loading…
Reference in a new issue