aboutsummaryrefslogtreecommitdiff
path: root/deflate.c
diff options
context:
space:
mode:
authorMark Adler <madler@alumni.caltech.edu>2017-01-02 15:17:59 -0800
committerMark Adler <madler@alumni.caltech.edu>2017-01-02 15:17:59 -0800
commitbc5503b224b64e2dfafe1f6d6f2dace191eb219d (patch)
treec84927e64ad504c1b618ae23fbeda782617f29d2 /deflate.c
parent52aa5501ecfffed933d39647092852cab397ca39 (diff)
downloadzlib-bc5503b224b64e2dfafe1f6d6f2dace191eb219d.tar.gz
zlib-bc5503b224b64e2dfafe1f6d6f2dace191eb219d.tar.bz2
zlib-bc5503b224b64e2dfafe1f6d6f2dace191eb219d.zip
Fix bug in deflate_stored() for zero-length input.
Diffstat (limited to 'deflate.c')
-rw-r--r--deflate.c37
1 files changed, 19 insertions, 18 deletions
diff --git a/deflate.c b/deflate.c
index f13af8f..7817530 100644
--- a/deflate.c
+++ b/deflate.c
@@ -1040,7 +1040,6 @@ int ZEXPORT deflate (strm, flush)
1040 } 1040 }
1041 } 1041 }
1042 } 1042 }
1043 Assert(strm->avail_out > 0, "bug2");
1044 1043
1045 if (flush != Z_FINISH) return Z_OK; 1044 if (flush != Z_FINISH) return Z_OK;
1046 if (s->wrap <= 0) return Z_STREAM_END; 1045 if (s->wrap <= 0) return Z_STREAM_END;
@@ -1653,17 +1652,19 @@ local block_state deflate_stored(s, flush)
1653 * possible. If flushing, copy the remaining available input to next_out as 1652 * possible. If flushing, copy the remaining available input to next_out as
1654 * stored blocks, if there is enough space. 1653 * stored blocks, if there is enough space.
1655 */ 1654 */
1656 unsigned len, left, have, last; 1655 unsigned len, left, have, last = 0;
1657 unsigned used = s->strm->avail_in; 1656 unsigned used = s->strm->avail_in;
1658 for (;;) { 1657 do {
1659 /* Set len to the maximum size block that we can copy directly with the 1658 /* Set len to the maximum size block that we can copy directly with the
1660 * available input data and output space. Set left to how much of that 1659 * available input data and output space. Set left to how much of that
1661 * would be copied from what's left in the window. 1660 * would be copied from what's left in the window.
1662 */ 1661 */
1663 len = MAX_STORED; /* maximum deflate stored block length */ 1662 len = MAX_STORED; /* maximum deflate stored block length */
1664 have = (s->bi_valid + 42) >> 3; /* number of header bytes */ 1663 have = (s->bi_valid + 42) >> 3; /* number of header bytes */
1664 if (s->strm->avail_out < have) /* need room for header */
1665 break;
1665 /* maximum stored block length that will fit in avail_out: */ 1666 /* maximum stored block length that will fit in avail_out: */
1666 have = s->strm->avail_out > have ? s->strm->avail_out - have : 0; 1667 have = s->strm->avail_out - have;
1667 left = s->strstart - s->block_start; /* bytes left in window */ 1668 left = s->strstart - s->block_start; /* bytes left in window */
1668 if (len > (ulg)left + s->strm->avail_in) 1669 if (len > (ulg)left + s->strm->avail_in)
1669 len = left + s->strm->avail_in; /* limit len to the input */ 1670 len = left + s->strm->avail_in; /* limit len to the input */
@@ -1677,7 +1678,8 @@ local block_state deflate_stored(s, flush)
1677 * copying to the window and the pending buffer instead. Also don't 1678 * copying to the window and the pending buffer instead. Also don't
1678 * write an empty block when flushing -- deflate() does that. 1679 * write an empty block when flushing -- deflate() does that.
1679 */ 1680 */
1680 if (len < min_block && (len == 0 || flush == Z_NO_FLUSH || 1681 if (len < min_block && ((len == 0 && flush != Z_FINISH) ||
1682 flush == Z_NO_FLUSH ||
1681 len - left != s->strm->avail_in)) 1683 len - left != s->strm->avail_in))
1682 break; 1684 break;
1683 1685
@@ -1721,7 +1723,7 @@ local block_state deflate_stored(s, flush)
1721 s->strm->avail_out -= len; 1723 s->strm->avail_out -= len;
1722 s->strm->total_out += len; 1724 s->strm->total_out += len;
1723 } 1725 }
1724 } 1726 } while (last == 0);
1725 1727
1726 /* Update the sliding window with the last s->w_size bytes of the copied 1728 /* Update the sliding window with the last s->w_size bytes of the copied
1727 * data, or append all of the copied data to the existing window if less 1729 * data, or append all of the copied data to the existing window if less
@@ -1754,13 +1756,14 @@ local block_state deflate_stored(s, flush)
1754 s->insert += MIN(used, s->w_size - s->insert); 1756 s->insert += MIN(used, s->w_size - s->insert);
1755 } 1757 }
1756 1758
1757 /* If flushing or finishing and all input has been consumed, then done. If 1759 /* If the last block was written to next_out, then done. */
1758 * the code above couldn't write a complete block to next_out, then the 1760 if (last)
1759 * code following this won't be able to either. 1761 return finish_done;
1760 */ 1762
1761 if (flush != Z_NO_FLUSH && s->strm->avail_in == 0 && 1763 /* If flushing and all input has been consumed, then done. */
1762 (long)s->strstart == s->block_start) 1764 if (flush != Z_NO_FLUSH && flush != Z_FINISH &&
1763 return flush == Z_FINISH ? finish_done : block_done; 1765 s->strm->avail_in == 0 && (long)s->strstart == s->block_start)
1766 return block_done;
1764 1767
1765 /* Fill the window with any remaining input. */ 1768 /* Fill the window with any remaining input. */
1766 have = s->window_size - s->strstart - 1; 1769 have = s->window_size - s->strstart - 1;
@@ -1791,20 +1794,18 @@ local block_state deflate_stored(s, flush)
1791 min_block = MIN(have, s->w_size); 1794 min_block = MIN(have, s->w_size);
1792 left = s->strstart - s->block_start; 1795 left = s->strstart - s->block_start;
1793 if (left >= min_block || 1796 if (left >= min_block ||
1794 (left && flush != Z_NO_FLUSH && s->strm->avail_in == 0 && 1797 ((left || flush == Z_FINISH) && flush != Z_NO_FLUSH &&
1795 left <= have)) { 1798 s->strm->avail_in == 0 && left <= have)) {
1796 len = MIN(left, have); 1799 len = MIN(left, have);
1797 last = flush == Z_FINISH && s->strm->avail_in == 0 && 1800 last = flush == Z_FINISH && s->strm->avail_in == 0 &&
1798 len == left ? 1 : 0; 1801 len == left ? 1 : 0;
1799 _tr_stored_block(s, (charf *)s->window + s->block_start, len, last); 1802 _tr_stored_block(s, (charf *)s->window + s->block_start, len, last);
1800 s->block_start += len; 1803 s->block_start += len;
1801 flush_pending(s->strm); 1804 flush_pending(s->strm);
1802 if (last)
1803 return finish_started;
1804 } 1805 }
1805 1806
1806 /* We've done all we can with the available input and output. */ 1807 /* We've done all we can with the available input and output. */
1807 return need_more; 1808 return last ? finish_started : need_more;
1808} 1809}
1809 1810
1810/* =========================================================================== 1811/* ===========================================================================