{"record":{"id":"e1ea386400a5cfb8","repo":"dotnet/wpf","slug":"sr-textstore-badimecharoffset","errorCode":null,"errorMessage":"SR.TextStore_BadIMECharOffset","messagePattern":"SR\\.TextStore_BadIMECharOffset","errorType":"validation","errorClass":"ArgumentException","httpStatus":null,"severity":"error","filePath":"src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Documents/TextStore.cs","lineNumber":3332,"sourceCode":"\n        // Asserts that this TextStore is sending TS_TEXTCHANGE structs\n        // in sync with the actual TextContainer.\n        private void VerifyTextStoreConsistency()\n        {\n            if (_netCharCount != this.TextContainer.IMECharCount)\n            {\n                Invariant.Assert(false, \"TextContainer/TextStore have inconsistent char counts!\");\n            }\n        }\n\n        // Validates the character offset supplied by cicero.\n        // See bug 1395082.  Sometimes cicero gives us offsets that are\n        // too large for the document.\n        private void ValidateCharOffset(int offset)\n        {\n            if (offset < 0 || offset > this.TextContainer.IMECharCount)\n            {\n                throw new ArgumentException(SR.Format(SR.TextStore_BadIMECharOffset, offset, this.TextContainer.IMECharCount));\n            }\n        }\n\n        /// Discards previous composition undo unit, to prevent\n        /// from merging it with the subsequent typing.\n        private void BreakTypingSequence(ITextPointer caretPosition)\n        {\n            CompositionParentUndoUnit unit = PeekCompositionParentUndoUnit();\n\n            // We also put the caret at the end of the composition after\n            // redoing a composition undo.  So update the end position now.\n            unit?.RecordRedoSelectionState(caretPosition, caretPosition);\n        }\n\n        // Repositions an ITextRange to comply with limitations on IME input.\n        // We cannot modify Table structure, or insert content\n        // before or after Tables or BlockUIContainers while maintaing our\n        // contract with the cicero interfaces (without major refactoring of","sourceCodeStart":3314,"sourceCodeEnd":3350,"githubUrl":"https://github.com/dotnet/wpf/blob/81131a70a4c573cd62748a5c36908fc4d662daa9/src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Documents/TextStore.cs#L3314-L3350","documentation":"ValidateCharOffset throws ArgumentException when a character offset supplied (typically by the TSF/cicero text service) is negative or greater than the text container's IMECharCount. Cicero sometimes sends offsets beyond the document extent (bug 1395082), and WPF rejects them rather than corrupting the text tree.","triggerScenarios":"TSF calls into TextStore with an offset (e.g. for composition start/adproperty queries) where offset < 0 || offset > TextContainer.IMECharCount.","commonSituations":"Third-party IMEs computing offsets against stale text; rapid edits shrinking the document while the IME still references old offsets; bug-triggering timing races noted in WPF bug 1395082.","solutions":["Clamp offsets to [0, TextContainer.IMECharCount] before passing to TSF interop if you drive the store yourself.","Catch ArgumentException and recompute offsets after text changed events.","Update the IME driver / WPF version; specific stale-offset IME bugs were addressed in servicing.","Synchronize edits with composition: avoid programmatic text changes while an IME composition is active."],"exampleFix":"// before\nint offset = GetImeOffset(); // may exceed document\nValidateCharOffset(offset);\n// after\nint offset = Math.Clamp(GetImeOffset(), 0, textContainer.IMECharCount);\nValidateCharOffset(offset);","handlingStrategy":"validation","validationCode":"bool offsetValid = offset >= 0 && offset <= textContainer.IMECharCount;","typeGuard":"bool IsValidCharOffset(int offset, ITextContainer c) => offset >= 0 && offset <= c.IMECharCount;","tryCatchPattern":"try { ValidateCharOffset(offset); }\ncatch (ArgumentException) { offset = Math.Clamp(offset, 0, textContainer.IMECharCount); }","preventionTips":["Clamp TSF offsets to document length","Avoid editing text during active composition","Test with third-party IMEs and rapid edits"],"tags":["wpf","ime","tsf","argument"],"backgroundTag":"value-out-of-range","analyzedSha":"81131a70a4c573cd62748a5c36908fc4d662daa9","analyzedAt":"2026-09-14T10:12:48.479Z","contentChangedAt":"2026-09-14T10:12:48.479Z","schemaVersion":2},"datasetVersion":"2026-09-21T21:30:21.729Z"}