diff options
author | Mark Adler <madler@alumni.caltech.edu> | 2017-01-02 15:17:59 -0800 |
---|---|---|
committer | Mark Adler <madler@alumni.caltech.edu> | 2017-01-02 15:17:59 -0800 |
commit | bc5503b224b64e2dfafe1f6d6f2dace191eb219d (patch) | |
tree | c84927e64ad504c1b618ae23fbeda782617f29d2 | |
parent | 52aa5501ecfffed933d39647092852cab397ca39 (diff) | |
download | zlib-bc5503b224b64e2dfafe1f6d6f2dace191eb219d.tar.gz zlib-bc5503b224b64e2dfafe1f6d6f2dace191eb219d.tar.bz2 zlib-bc5503b224b64e2dfafe1f6d6f2dace191eb219d.zip |
Fix bug in deflate_stored() for zero-length input.
-rw-r--r-- | deflate.c | 37 |
1 files changed, 19 insertions, 18 deletions
@@ -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 | /* =========================================================================== |