Skip to content

Commit

Permalink
deflateCopy(): Fix allocation and copying of pending_buf in LIT_MEM mode
Browse files Browse the repository at this point in the history
This applies the fix from madler/zlib#900 and
adds a test.

Bug: 1513368
Change-Id: I38025c66e1ef2420c726406ddefe6c728bdb6458
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5139141
Commit-Queue: Adenilson Cavalcanti <[email protected]>
Auto-Submit: Hans Wennborg <[email protected]>
Reviewed-by: Adenilson Cavalcanti <[email protected]>
Cr-Commit-Position: refs/heads/main@{#1239920}
NOKEYCHECK=True
GitOrigin-RevId: 5672e5e75c159ba1742f8cfd784d294cff21c597
  • Loading branch information
zmodem authored and copybara-github committed Dec 21, 2023
1 parent 002f75d commit 40e35a7
Show file tree
Hide file tree
Showing 2 changed files with 63 additions and 0 deletions.
55 changes: 55 additions & 0 deletions contrib/tests/utils_unittest.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1025,6 +1025,61 @@ TEST(ZlibTest, DeflateZFixedCorruption) {
0);
}

TEST(ZlibTest, DeflateCopy) {
// Check that deflateCopy() works.

z_stream stream1;
stream1.zalloc = Z_NULL;
stream1.zfree = Z_NULL;
int ret =
deflateInit(&stream1, Z_DEFAULT_COMPRESSION);
ASSERT_EQ(ret, Z_OK);
std::vector<uint8_t> compressed(
deflateBound(&stream1, strlen(zFixedCorruptionData)));
stream1.next_out = compressed.data();
stream1.avail_out = compressed.size();

// Compress the first 1000 bytes.
stream1.next_in = (uint8_t*)zFixedCorruptionData;
stream1.avail_in = 1000;
ret = deflate(&stream1, Z_NO_FLUSH);
ASSERT_EQ(ret, Z_OK);

// Copy the stream state.
z_stream stream2;
ret = deflateCopy(&stream2, &stream1);
ASSERT_EQ(ret, Z_OK);
deflateEnd(&stream1);

// Compress the remaining bytes.
stream2.next_in = (uint8_t*)zFixedCorruptionData + (1000 - stream2.avail_in);
stream2.avail_in = strlen(zFixedCorruptionData) - (1000 - stream2.avail_in);
ret = deflate(&stream2, Z_FINISH);
ASSERT_EQ(ret, Z_STREAM_END);
size_t compressed_sz = compressed.size() - stream2.avail_out;
deflateEnd(&stream2);

// Check that decompression is successful.
std::vector<uint8_t> decompressed(strlen(zFixedCorruptionData));
z_stream stream;
stream.zalloc = Z_NULL;
stream.zfree = Z_NULL;
ret = inflateInit(&stream);
ASSERT_EQ(ret, Z_OK);
stream.next_in = compressed.data();
stream.avail_in = compressed_sz;
stream.next_out = decompressed.data();
stream.avail_out = decompressed.size();
ret = inflate(&stream, Z_FINISH);
ASSERT_EQ(ret, Z_STREAM_END);
inflateEnd(&stream);

EXPECT_EQ(decompressed.size(), strlen(zFixedCorruptionData));
EXPECT_EQ(
memcmp(zFixedCorruptionData, decompressed.data(), decompressed.size()),
0);
}

// TODO(gustavoa): make these tests run standalone.
#ifndef CMAKE_STANDALONE_UNITTESTS

Expand Down
8 changes: 8 additions & 0 deletions deflate.c
Original file line number Diff line number Diff line change
Expand Up @@ -1345,7 +1345,11 @@ int ZEXPORT deflateCopy(z_streamp dest, z_streamp source) {
ds->window = (Bytef *) ZALLOC(dest, ds->w_size, 2*sizeof(Byte));
ds->prev = (Posf *) ZALLOC(dest, ds->w_size, sizeof(Pos));
ds->head = (Posf *) ZALLOC(dest, ds->hash_size, sizeof(Pos));
#ifdef LIT_MEM
ds->pending_buf = (uchf *) ZALLOC(dest, ds->lit_bufsize, 5);
#else
ds->pending_buf = (uchf *) ZALLOC(dest, ds->lit_bufsize, 4);
#endif

if (ds->window == Z_NULL || ds->prev == Z_NULL || ds->head == Z_NULL ||
ds->pending_buf == Z_NULL) {
Expand All @@ -1356,7 +1360,11 @@ int ZEXPORT deflateCopy(z_streamp dest, z_streamp source) {
zmemcpy(ds->window, ss->window, ds->w_size * 2 * sizeof(Byte));
zmemcpy((voidpf)ds->prev, (voidpf)ss->prev, ds->w_size * sizeof(Pos));
zmemcpy((voidpf)ds->head, (voidpf)ss->head, ds->hash_size * sizeof(Pos));
#ifdef LIT_MEM
zmemcpy(ds->pending_buf, ss->pending_buf, (uInt)ds->lit_bufsize * 5);
#else
zmemcpy(ds->pending_buf, ss->pending_buf, (uInt)ds->pending_buf_size);
#endif

ds->pending_out = ds->pending_buf + (ss->pending_out - ss->pending_buf);
#ifdef LIT_MEM
Expand Down

0 comments on commit 40e35a7

Please sign in to comment.