Skip to content

docs: correct the decompress and decrypt cancellation remarks - #15

Merged
matt-edmondson merged 1 commit into
mainfrom
fix/async-decompress-remarks
Aug 23, 2026
Merged

docs: correct the decompress and decrypt cancellation remarks#15
matt-edmondson merged 1 commit into
mainfrom
fix/async-decompress-remarks

Conversation

@matt-edmondson

Copy link
Copy Markdown
Contributor

Corrects five XML doc remarks that shipped in 2.2.0 and are already on NuGet. Callers reading the current docs are told the wrong reason to distrust a partial destination.

What was wrong

TryDecompressAsync (Gzip, Deflate, ZLib, Brotli) and TryDecryptAsync (AES) each claimed that cancellation "still flushes the trailer" or "still flushes the final block". On those paths nothing is flushed to the destination at all. The wrapping stream takes the source:

GZipStream gzipStream = new(compressedData, CompressionMode.Decompress, leaveOpen: true);
await using (gzipStream.ConfigureAwait(false))
{
    await gzipStream.CopyToAsync(destination, 81920, cancellationToken).ConfigureAwait(false);
}

Disposal tears down the decompressor over the source. The destination only ever sees CopyToAsync output.

What it says now

The conclusion was always right, so the guidance to treat the destination as invalid unless the method returns true is unchanged. Only the justification is replaced: decompressed bytes and recovered plaintext have no structure of their own, so a truncated destination can't be told apart from a complete one by inspecting it. Each remark also now notes that the stream wraps the source, which is what makes the trailer irrelevant here.

What is deliberately untouched

The compress and encrypt remarks in the same five files. Those are accurate, because there the stream really does wrap the destination and disposal really does write the trailer or the final cipher block. That asymmetry is the whole point, and it is why only one of each pair changed.

Risk

None. Documentation only, no behavior change. Confirmed no test asserted the wrong claim, so nothing needed rewriting alongside it. Full solution builds clean, 0 warnings and 0 errors under warnings-as-errors.

The remarks on `TryDecompressAsync` and `TryDecryptAsync` shipped in 2.2.0
claiming that cancellation "still flushes the trailer" or "still flushes the
final block". That is false on those paths. The decompressing and decrypting
streams wrap the source, not the destination, and are constructed with
`leaveOpen: true`, so disposing them writes nothing to the destination. The
destination only ever receives the output of `CopyToAsync`.

The advice to treat a partial destination as invalid was right, but the reason
given was wrong. State the real one: raw decompressed bytes and recovered
plaintext carry no structure of their own, so a truncated destination cannot be
told apart from a complete one by inspecting it.

The matching remarks on the compress and encrypt paths are correct and are left
alone. There, the stream does wrap the destination and disposal does write the
trailer or final cipher block.

Documentation only. No behavior change, and no test asserted the wrong claim.
@sonarqubecloud

Copy link
Copy Markdown

@matt-edmondson
matt-edmondson merged commit a1f83de into main Aug 23, 2026
10 checks passed
@matt-edmondson
matt-edmondson deleted the fix/async-decompress-remarks branch August 23, 2026 15:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant