dotnet/wpf · error · FileFormatException

SR.CorruptStream

Error message

SR.CorruptStream

What it means

CompoundFileDeflateTransform.Decompress throws FileFormatException with SR.CorruptStream when ReliableRead returns fewer bytes than the compressed block size declared in the block header. The compressed data is truncated relative to its own header, so the deflate payload cannot be trusted. This guards the zlib inflate step from reading garbage or uninitialized buffer regions.

Solutions

  1. Verify/repair the document source; re-download or restore from backup
  2. Catch FileFormatException and treat the document as corrupt, surfacing a user-friendly error
  3. Validate file integrity (size, checksum) before opening if the source is untrusted
  4. Open the file with the application's repair/recovery path if available

Example fix

// before
transform.Decompress(source, sink);
// after
try {
    transform.Decompress(source, sink);
} catch (FileFormatException) {
    // stream is truncated/corrupt — recover or reject the document
    throw new InvalidDataException("Compound file stream is corrupt or truncated.");
}
Defensive patterns

Strategy: try-catch

Validate before calling

if (source.CanSeek && source.Length - source.Position < compressedSize) throw new InvalidDataException("Truncated compressed block.");

Try / catch

try { transform.Decompress(source, sink); } catch (FileFormatException) { /* treat document as corrupt; salvage or reject */ }

Prevention

When it happens

Trigger: Reading a compound-file deflate-compressed stream whose block data is truncated — the file was cut short, partially written, or the header's compressedSize field doesn't match the actual bytes present.

Common situations: Opening damaged .docx/.xps OLE containers; files truncated by failed downloads or interrupted saves; hand-edited or corrupted container bytes.

Understand the failure class

Background: Checksum mismatch errors: "checksum verification failed", "digest mismatch", "expected vs actual checksum" — what they mean and how to fix them — this error's family across 41 libraries.

Related errors


AI-assisted analysis of dotnet/wpf@81131a70a4 (2026-09-14). Data as JSON: /api/errors/f9a50fabbb8c8aa6. Report an issue: GitHub.

Appendix: source

Thrown at src/Microsoft.DotNet.Wpf/src/WindowsBase/MS/Internal/IO/Packaging/CompoundFile/CompoundFileDeflateTransform.cs:92

                try
                {
                    // read all available data
                    // each block is preceded by a header that is 3 ulongs
                    int uncompressedSize, compressedSize;
                    long destStreamLength = 0;      // keep track of decompressed size
                    while (ReadBlockHeader(source, out uncompressedSize, out compressedSize))
                    {
                        // ensure we have space
                        AllocOrRealloc(compressedSize, ref sourceBuf, ref gcSourceBuf);
                        AllocOrRealloc(uncompressedSize, ref sinkBuf, ref gcSinkBuf);

                        // read the data into the sourceBuf
                        int bytesRead = PackagingUtilities.ReliableRead(source, sourceBuf, 0, compressedSize);
                        if (bytesRead > 0)
                        {
                            if (compressedSize != bytesRead)
                                throw new FileFormatException(SR.CorruptStream);

                            // prepare structure
                            // The buffer pointers must be reset for every call
                            // because ZLibNative.Inflate modifies them
                            zStream.NextIn = gcSourceBuf.AddrOfPinnedObject();
                            zStream.NextOut = gcSinkBuf.AddrOfPinnedObject();
                            zStream.AvailIn = (uint)bytesRead;     // this is number of bytes available for decompression at pInBuf and is updated by ums_deflate call
                            zStream.AvailOut = (uint)sinkBuf.Length;   // this is the number of bytes free in pOutBuf and is updated by ums_deflate call

                            // InvokeZLib does the actual interop.  It updates zStream, and sinkBuf (sourceBuf passed by ref to avoid copying)
                            // and leaves the decompressed data in sinkBuf.
                            //                        int decompressedSize = InvokeZLib(bytesRead, ref zStream, ref sourceBuf, ref sinkBuf, pSource, pSink, false);
                            retVal = zStream.Inflate(ZLibNative.FlushCode.SyncFlush);

                            ThrowIfZLibError(retVal);

                            checked
                            {

View on GitHub (pinned to 81131a70a4)