{"record":{"id":"3d3cb7b02c885245","repo":"dotnet/wpf","slug":"returned-string-is-too-long-for-the-buffer-provided","errorCode":null,"errorMessage":"Returned string is too long for the buffer provided.","messagePattern":"Returned string is too long for the buffer provided\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/Microsoft.DotNet.Wpf/src/PresentationFramework/MS/Internal/IO/Packaging/indexingfiltermarshaler.cs","lineNumber":98,"sourceCode":"                return null;\n        }\n\n        /// <summary>\n        /// StringToPtr\n        /// </summary>\n        /// <remarks>Converts a managed string into the format useful for IFilter.GetText</remarks>\n        /// <param name=\"s\">string to convert</param>\n        /// <param name=\"bufCharacterCount\">maximum number of characters to convert</param>\n        /// <param name=\"p\">pointer to write to</param>\n        internal static void MarshalStringToPtr(string s, ref uint bufCharacterCount, IntPtr p)\n        {\n            // bufCharacterCount is never supposed to be zero at this level.\n            Invariant.Assert(bufCharacterCount != 0);\n\n            // ensure the interface rules are followed\n            // string must also be null terminated so we restrict the length to buf size - 1\n            if ((uint)(s.Length) > bufCharacterCount - 1)\n                throw new InvalidOperationException(SR.FilterGetTextBufferOverflow);\n\n            // Return the number of characters written, including the terminating null.\n            bufCharacterCount = (UInt32)s.Length + 1;\n\n            // convert string to unmanaged string and write into provided buffer\n            Marshal.Copy(s.ToCharArray(), 0, p, s.Length);\n\n            // null terminate (16bit's of zero to replace one Unicode character)\n            Marshal.WriteInt16(p, s.Length * _int16Size, 0);\n        }\n\n        /// <summary>\n        /// Marshal Managed to Native PROPSPEC\n        /// </summary>\n        /// <param name=\"propSpec\"></param>\n        /// <param name=\"native\"></param>\n        internal static void MarshalPropSpec(ManagedPropSpec propSpec, ref PROPSPEC native)\n        {","sourceCodeStart":80,"sourceCodeEnd":116,"githubUrl":"https://github.com/dotnet/wpf/blob/81131a70a4c573cd62748a5c36908fc4d662daa9/src/Microsoft.DotNet.Wpf/src/PresentationFramework/MS/Internal/IO/Packaging/indexingfiltermarshaler.cs#L80-L116","documentation":"WPF's IndexingFilterMarshaler implements the COM IFilter interface so Windows Search can index XPS/package content. When a host calls IFilter::GetText, MarshalStringToPtr copies the filter's text into a caller-provided character buffer sized by bufCharacterCount. The contract requires room for the string plus a terminating null, so when s.Length > bufCharacterCount - 1 the marshaler throws InvalidOperationException because it can neither truncate the text nor overrun the buffer.","triggerScenarios":"A search/indexing host calls GetText with a buffer whose bufCharacterCount is less than or equal to the length of the current text chunk string; the check (uint)s.Length > bufCharacterCount - 1 in MarshalStringToPtr fires.","commonSituations":"Custom IFilter hosts or third-party indexing clients that allocate undersized text buffers when enumerating an XPS document via WPF's filter; hosts that pass bufCharacterCount in bytes instead of characters, halving the effective capacity; buffer-size renegotiation bugs after partial GetText calls.","solutions":["Allocate a buffer of at least (chunk text length + 1) characters before calling GetText and pass that count in bufCharacterCount","Catch the exception, grow the buffer, and retry the GetText call","If you control the filter's text source, split long strings so each fits the advertised buffer size","Verify the host counts characters (WCHARs), not bytes — a byte/char confusion makes buffers appear half-size"],"exampleFix":"// before: fixed 64-char buffer regardless of text\nchar[] buf = new char[64];\nuint count = 64;\nfilter.GetText(ref count, buf);\n\n// after: size the buffer for the chunk text plus terminating null\nstring text = chunk.Text;\nchar[] buf = new char[text.Length + 1];\nuint count = (uint)buf.Length;\nfilter.GetText(ref count, buf);","handlingStrategy":"try-catch","validationCode":"if (text != null && bufCharacterCount < (uint)text.Length + 1)\n{\n    // grow the buffer before calling GetText\n    bufCharacterCount = (uint)text.Length + 1;\n    buffer = new char[text.Length + 1];\n}","typeGuard":null,"tryCatchPattern":"try\n{\n    filter.GetText(ref bufCharacterCount, buffer);\n}\ncatch (InvalidOperationException ex)\n{\n    // string did not fit: enlarge buffer to text length + 1 and retry\n    GrowBufferAndRetry();\n}","preventionTips":["Size buffers in characters (WCHARs), never bytes","Always reserve one extra character for the terminating null","Use a grow-and-retry loop pattern around GetText instead of assuming a fixed buffer size"],"tags":["wpf","com-interop","ifilter","packaging","buffer-size"],"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"}