dotnet/wpf · error · ArgumentOutOfRangeException
SR.CountOfBitsGreatThanRemainingBits
Error message
SR.CountOfBitsGreatThanRemainingBits
What it means
After validating the bit width, BitStream.ReadByte also checks that the requested countOfBits does not exceed the bits remaining in the buffer (_bufferLengthInBits); exceeding it throws ArgumentOutOfRangeException(SR.CountOfBitsGreatThanRemainingBits). It prevents partial reads past the end of the stream.
Solutions
- Check remaining bits before each call: only read min(requested, remaining) bits, or stop when fewer remain.
- Check BitStream.EndOfStream and track consumed bits to compute the remaining count before reading.
- Catch ArgumentOutOfRangeException around decode and treat the ISF stream as truncated.
- Align decode logic to byte boundaries so the last partial byte is handled explicitly.
Example fix
// before
byte v = bitStream.ReadByte(8); // may exceed remaining bits
// after
if (bitStream.EndOfStream || bitStream.RemainingBits < 8)
throw new InvalidDataException("Not enough bits remaining for an 8-bit read");
byte v = bitStream.ReadByte(8); Defensive patterns
Strategy: validation
Validate before calling
// only issue the read when enough bits remain
if (bitStream.EndOfStream)
throw new InvalidDataException("No bits remaining");
byte v = bitStream.ReadByte(Math.Min(requestedBits, 8)); Type guard
static bool HasBits(BitStream s, int n) => !s.EndOfStream && s.RemainingBits >= n;
Try / catch
try
{
byte v = bitStream.ReadByte(8);
}
catch (ArgumentOutOfRangeException)
{
// fewer bits remained than requested: handle partial/truncated tail
throw new InvalidDataException("Truncated ISF tail: not enough bits for field");
} Prevention
- Track remaining bits and reduce the final read's width accordingly.
- Handle sub-byte leftovers at the end of payloads explicitly.
- Never assume payloads are byte-aligned end to end.
- Fuzz-test decoders with truncated inputs.
When it happens
Trigger: Calling ReadByte(countOfBits) with 1-8 bits when fewer than countOfBits bits remain in the stream (e.g. 4 bits left, requesting 8). Triggered from GetDataFromReader, Uncompress, LoadPackets, and the indexer on truncated data.
Common situations: Reading fixed-width fields (e.g. always 8 bits) from an ISF payload whose final byte is partial; a decode loop that does not account for sub-byte leftovers.
Related errors
- SR.EndOfStreamReached
- args
- args
- ArgumentOutOfRangeException(authenticationType)
- ArgumentOutOfRangeException
AI-assisted analysis of dotnet/wpf@81131a70a4 (2026-09-14).
Data as JSON: /api/errors/72c59f7f2a303405.
Report an issue: GitHub.
Appendix: source
Thrown at src/Microsoft.DotNet.Wpf/src/Shared/MS/Internal/Ink/BitStream.cs:241
/// will be created with the least significant bits set to the 2 unpacked bits
/// from the stream</remarks>
internal byte ReadByte(int countOfBits)
{
// if the end of the stream has been reached, then throw an exception
if (EndOfStream)
{
throw new System.IO.EndOfStreamException(SR.EndOfStreamReached);
}
// we only support 1-8 bits currently, not multiple bytes, and not 0 bits
if (countOfBits > Native.BitsPerByte || countOfBits <= 0)
{
throw new ArgumentOutOfRangeException(nameof(countOfBits), countOfBits, SR.CountOfBitsOutOfRange);
}
if (countOfBits > _bufferLengthInBits)
{
throw new ArgumentOutOfRangeException(nameof(countOfBits), countOfBits, SR.CountOfBitsGreatThanRemainingBits);
}
_bufferLengthInBits -= (uint)countOfBits;
// initialize return byte to 0 before reading from the cache
byte returnByte = 0;
// if the partial bit cache contains more bits than requested, then read the
// cache only
if (_cbitsInPartialByte >= countOfBits)
{
// retrieve the requested count of most significant bits from the cache
// and store them in the least significant positions in the return byte
int rightShiftPartialByteBy = Native.BitsPerByte - countOfBits;
returnByte = (byte)(_partialByte >> rightShiftPartialByteBy);
// reposition any unused portion of the cache in the most significant part of the bit cache
unchecked // disable overflow checking since we are intentionally throwing awayView on GitHub (pinned to 81131a70a4)