Skip to content

Commit b37f2dd

Browse files
committed
Fix stored-block deflate truncating inputs over 64 KiB
1 parent e5cad3f commit b37f2dd

1 file changed

Lines changed: 17 additions & 14 deletions

File tree

src/lib/deflate-enc.inc.c

Lines changed: 17 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -272,17 +272,20 @@ int deflate(z_stream *strm, int flush) {
272272

273273
/* If no compression wanted or very small level, just store uncompressed */
274274
if (state->level == Z_NO_COMPRESSION) {
275-
if (strm->avail_in > 0) {
276-
/* Calculate block size - length fields + data */
277-
uint32_t block_size = 4 + strm->avail_in;
275+
/* Emit one stored block per DEFLATE 64KiB limit until avail_in is drained */
276+
while (strm->avail_in > 0) {
277+
uint32_t chunk = strm->avail_in > 0xFFFF? 0xFFFFu: strm->avail_in;
278+
uint32_t block_size = 4 + chunk;
278279

279-
/* Check if we have enough output space */
280+
/* Check if we have enough output space for this block's len/nlen + data */
280281
if (strm->avail_out < block_size) {
281282
return Z_BUF_ERROR;
282283
}
283284

284-
/* Write block header using bit buffer - final bit + type 00 (uncompressed) */
285-
int ret = write_bits (strm, state, state->is_last_block? 1: 0, 1); /* Final block bit */
285+
/* BFINAL only on the block that drains the last of the input under Z_FINISH */
286+
int is_final = (flush == Z_FINISH && chunk == strm->avail_in)? 1: 0;
287+
288+
int ret = write_bits (strm, state, is_final, 1); /* Final block bit */
286289
if (ret != Z_OK) {
287290
return ret;
288291
}
@@ -296,7 +299,7 @@ int deflate(z_stream *strm, int flush) {
296299
flush_bits (strm, state);
297300

298301
/* Write length and inverted length */
299-
uint16_t len = strm->avail_in > 0xFFFF? 0xFFFF: strm->avail_in;
302+
uint16_t len = (uint16_t)chunk;
300303
*strm->next_out++ = len & 0xFF;
301304
*strm->next_out++ = (len >> 8) & 0xFF;
302305
*strm->next_out++ = (~len) & 0xFF;
@@ -305,13 +308,13 @@ int deflate(z_stream *strm, int flush) {
305308
strm->total_out += 4;
306309

307310
/* Write data */
308-
memcpy (strm->next_out, strm->next_in, len);
309-
strm->next_in += len;
310-
strm->avail_in -= len;
311-
strm->total_in += len;
312-
strm->next_out += len;
313-
strm->avail_out -= len;
314-
strm->total_out += len;
311+
memcpy (strm->next_out, strm->next_in, chunk);
312+
strm->next_in += chunk;
313+
strm->avail_in -= chunk;
314+
strm->total_in += chunk;
315+
strm->next_out += chunk;
316+
strm->avail_out -= chunk;
317+
strm->total_out += chunk;
315318
}
316319
return flush == Z_FINISH? Z_STREAM_END: Z_OK;
317320
}

0 commit comments

Comments
 (0)