Repository navigation
Conversation
Encoding to a non-seekable stream buffers the output in a ChunkedMemoryStream. Overwriting bytes after seeking back, as the TIFF, BMP and ANI encoders do to patch offsets, extended the stream length, so trailing uninitialized bytes were copied to the destination. Seeking past the end of the buffered data, as the ICO and CUR encoders do to leave room for the directory, threw an ArgumentOutOfRangeException on an empty buffer and wrote one byte early at a chunk boundary. The length now only grows when a write ends past the current end, and a position beyond the allocated chunks is resolved after the buffer expands.
4 tasks done
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Prerequisites
Description
When the destination stream cannot seek,
ImageEncoderencodes into aChunkedMemoryStreamand copies the result to the destination. Two defects inChunkedMemoryStreammade that output differ from a seekable save, or made the save fail.Overwriting data extended the stream.
Writealways added the bytes written to the length, also when it overwrote bytes after a seek back. The TIFF encoder seeks back to write each IFD offset (and BMP and ANI patch offsets the same way), so the buffered stream got longer by 4 bytes per patch. Those trailing bytes were uninitialized pooled memory, and they were copied to the destination. A TIFF save to a non-seekable stream, sync or async, therefore ended with stray bytes and did not match a seekable save.Now the length only grows when a write ends after the current end of the data.
Seeking past the end failed or wrote at the wrong place. The ICO and CUR encoders seek forward past the directory, write the images, then go back and write the directory. On an empty buffer,
SetPositionindexed chunk-1and threwArgumentOutOfRangeException, so saving ICO or CUR to a non-seekable stream always failed. With chunks allocated, a position at or after the end of the chunks was mapped to the last byte of the last chunk, so the next write started one byte early.Now such a position maps to the start of the next chunk to allocate.
Writefinds the chunk again after it expands the buffer, if the position was past the end of the allocated chunks.Tests
ChunkedMemoryStreamTests: an overwrite after a seek back keeps the length and data. A write after a seek past the end (empty stream, exactly at a chunk boundary, and across chunks) lands at the right position.ImageTests.Save.ToNonSeekableStream_SyncAndAsync_MatchSeekableStream: for every built-in encoder, sync and async saves to a non-seekable stream are byte-identical to a seekable save. Before this change, this test failed for TIFF, ANI, ICO and CUR.TiffEncoderTests.TiffEncoder_ToNonSeekableStream_MatchesSeekableStream: a two-frame TIFF, so that more than one IFD offset is patched.The Release build passes for net10.0. These test sets pass (3879 tests): Tiff, Ico, Cur, Ani and Bmp formats,
ImageTests,GeneralFormatTests,ImageDecoder, andChunkedMemoryStreamTests(which includes the non-seekable decode/encode integration tests over all test images).Fixes #3244