Skip to content

fix: never assume Stream.Read fills the buffer - #34

Open
skippdot wants to merge 1 commit into
OpenOrbis:masterfrom
skippdot:pr/stream-read-full
Open

skippdot wants to merge 1 commit into
OpenOrbis:masterfrom
skippdot:pr/stream-read-full

Conversation

@skippdot

@skippdot skippdot commented Oct 6, 2026

Copy link
Copy Markdown

Several places assumed Stream.Read fills the buffer. That is not guaranteed: it holds for MemoryStream/local FileStream in practice, but not for network or wrapping streams.

The important ones read data:

  • PFS block signing and XTS encryption in PfsBuilder.WriteImage(Stream);
  • Util.StreamReader (used to read packages from streams).

Adds StreamExtensions.ReadFull, which reads exactly count bytes or throws EndOfStreamException, and uses it for every data/header read.

PfsBuilder.WriteImage(Stream) now also sizes the stream to the full image first, as the memory-mapped path does. Previously a standalone image (pfs_buildouter) hit end-of-stream at the last block, and the reused sector buffer encrypted stale bytes into the final sector.

Tests: PartialReadTests build a signed+encrypted image and a full PKG through a stream that returns at most 1000 bytes per Read, and require byte-identical output. Both fail on master.

Adds StreamExtensions.ReadFull and uses it for every data read (PFS signing and XTS in PfsBuilder.WriteImage(Stream), StreamReader, ReaderBase, PkgReader, header readers). PfsBuilder.WriteImage(Stream) now sizes the stream to the full image first, as the memory-mapped path does: standalone images (pfs_buildouter) previously encrypted stale bytes into the final sector. Test builds through a stream that returns <=1000 bytes per Read and requires byte-identical output.
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