Currently, when getting the LZWStatus::NoProgress from the underlying
weezl library, tiff checks that no input bytes were read and no
output bytes were written. Although this is according to what the
weezl library mentions in their doc-comment, it's not what the real
result always looks like.
Our fuzzer found input that triggered exactly this case, where the LZW
reader is able to write some output byte before hitting the NoProgress
status.
This change removes the assert, as the resulting action is anyways to return
an error that can be handled by the caller.
This allows us to recombine the reader and other file data in a Decoder
with any IFD, whether that of an image or an extension IFD as indicated
by an IFD pointer such as Exif and GPS.
This assumed that a `read` would succeed for the full length, thus
interpreting in a subsequent call some data bits as a header.
For instance, consider 77 bytes of literal were left and a buffer of
1024 bytes was provided. Then the `read` call might return 60 which was
ignored and assumed to be 77. Thus the next 17 bytes of literal data
were instead interpreted as a header due to setting `self.count` to 0.
- Switch to streaming decompression via `flate2`. Aside from performance improvements and lower RAM consumption, this fixes a bug where `max_uncompressed_length` was precalculated for a single tile but then used as a hard limit on the whole data, failing to decompress any tiled images.
- Deprecate `InflateError` - this was used for wrapping `miniz_oxide` raw status, but `flate2` already reports them as `io::Error` instead. This makes errors from both Lzw and Deflate modes more consistent - they're all now just `io::Error`.
- Add support for new `Deflate` tag in addition to `OldDeflate` - format-wise it's same Zlib, and on practice decodes successfully with the same underlying code.
- Slightly simplify partial reads from the `Reader` by using the `std::io::copy` helper instead of doing it manually.
Fixes#131.
When the required amount of data was just a tiny bit larger than full a
page size (one buffer increment), the decoder would stop since all
compressed data had been read. However, the lzw decoder contains a small
internal bit buffer for code decoding. That is, some remaining bytes had
been retained and were still left to be decoded.