{"record":{"id":"72c59f7f2a303405","repo":"dotnet/wpf","slug":"sr-countofbitsgreatthanremainingbits","errorCode":null,"errorMessage":"SR.CountOfBitsGreatThanRemainingBits","messagePattern":"SR\\.CountOfBitsGreatThanRemainingBits","errorType":"exception","errorClass":"ArgumentOutOfRangeException","httpStatus":null,"severity":"error","filePath":"src/Microsoft.DotNet.Wpf/src/Shared/MS/Internal/Ink/BitStream.cs","lineNumber":241,"sourceCode":"        /// will be created with the least significant bits set to the 2 unpacked bits\n        /// from the stream</remarks>\n        internal byte ReadByte(int countOfBits)\n        {\n            // if the end of the stream has been reached, then throw an exception\n            if (EndOfStream)\n            {\n                throw new System.IO.EndOfStreamException(SR.EndOfStreamReached);\n            }\n\n            // we only support 1-8 bits currently, not multiple bytes, and not 0 bits\n            if (countOfBits > Native.BitsPerByte || countOfBits <= 0)\n            {\n                throw new ArgumentOutOfRangeException(nameof(countOfBits), countOfBits, SR.CountOfBitsOutOfRange);\n            }\n\n            if (countOfBits > _bufferLengthInBits)\n            {\n                throw new ArgumentOutOfRangeException(nameof(countOfBits), countOfBits, SR.CountOfBitsGreatThanRemainingBits);\n            }\n\n            _bufferLengthInBits -= (uint)countOfBits;\n\n            // initialize return byte to 0 before reading from the cache\n            byte returnByte = 0;\n\n            // if the partial bit cache contains more bits than requested, then read the\n            //      cache only\n            if (_cbitsInPartialByte >= countOfBits)\n            {\n                // retrieve the requested count of most significant bits from the cache\n                //      and store them in the least significant positions in the return byte\n                int rightShiftPartialByteBy = Native.BitsPerByte - countOfBits;\n                returnByte = (byte)(_partialByte >> rightShiftPartialByteBy);\n\n                // reposition any unused portion of the cache in the most significant part of the bit cache\n                unchecked // disable overflow checking since we are intentionally throwing away","sourceCodeStart":223,"sourceCodeEnd":259,"githubUrl":"https://github.com/dotnet/wpf/blob/81131a70a4c573cd62748a5c36908fc4d662daa9/src/Microsoft.DotNet.Wpf/src/Shared/MS/Internal/Ink/BitStream.cs#L223-L259","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nbyte v = bitStream.ReadByte(8); // may exceed remaining bits\n// after\nif (bitStream.EndOfStream || bitStream.RemainingBits < 8)\n    throw new InvalidDataException(\"Not enough bits remaining for an 8-bit read\");\nbyte v = bitStream.ReadByte(8);","handlingStrategy":"validation","validationCode":"// only issue the read when enough bits remain\nif (bitStream.EndOfStream)\n    throw new InvalidDataException(\"No bits remaining\");\nbyte v = bitStream.ReadByte(Math.Min(requestedBits, 8));","typeGuard":"static bool HasBits(BitStream s, int n) => !s.EndOfStream && s.RemainingBits >= n;","tryCatchPattern":"try\n{\n    byte v = bitStream.ReadByte(8);\n}\ncatch (ArgumentOutOfRangeException)\n{\n    // fewer bits remained than requested: handle partial/truncated tail\n    throw new InvalidDataException(\"Truncated ISF tail: not enough bits for field\");\n}","preventionTips":["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."],"tags":["argument-out-of-range","truncated-data","ink-parsing"],"backgroundTag":"argument-out-of-range","analyzedSha":"81131a70a4c573cd62748a5c36908fc4d662daa9","analyzedAt":"2026-09-14T10:12:48.479Z","contentChangedAt":"2026-09-14T10:12:48.479Z","schemaVersion":2},"datasetVersion":"2026-09-22T01:17:13.364Z"}