{"record":{"id":"1eaa0f52eef3c14b","repo":"dotnet/wpf","slug":"sr-glyphsunicodestringistooshort","errorCode":null,"errorMessage":"SR.GlyphsUnicodeStringIsTooShort","messagePattern":"SR\\.GlyphsUnicodeStringIsTooShort","errorType":"validation","errorClass":"ArgumentException","httpStatus":null,"severity":"error","filePath":"src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Documents/Glyphs.cs","lineNumber":466,"sourceCode":"            return advance * EmMultiplier;\n        }\n\n        private ushort GetGlyphFromCharacter(GlyphTypeface glyphTypeface, char character)\n        {\n            ushort glyphIndex;\n            // TryGetValue will return zero glyph index for missing code points,\n            // which is the right thing to display per http://www.microsoft.com/typography/otspec/cmap.htm\n            glyphTypeface.CharacterToGlyphMap.TryGetValue(character, out glyphIndex);\n            return glyphIndex;\n        }\n\n        /// <summary>\n        /// Performs validation against cluster map size and throws a well defined exception.\n        /// </summary>\n        private static void SetClusterMapEntry(ushort[] clusterMap, int index, ushort value)\n        {\n            if (index < 0 || index >= clusterMap.Length)\n                throw new ArgumentException(SR.GlyphsUnicodeStringIsTooShort);\n            clusterMap[index] = value;\n        }\n\n        private class ParsedGlyphData\n        {\n            public ushort   glyphIndex;\n            public double   advanceWidth;\n            public double   offsetX;\n            public double   offsetY;\n        };\n\n        // -----------------------------------------------------------------------------\n        // Parses a semicolon-delimited list of glyph specifiers, each of which consists\n        // of up to 4 comma-delimited values:\n        //   - glyph index (ushort)\n        //   - glyph advance (double)\n        //   - glyph offset X (double)\n        //   - glyph offset Y (double)","sourceCodeStart":448,"sourceCodeEnd":484,"githubUrl":"https://github.com/dotnet/wpf/blob/81131a70a4c573cd62748a5c36908fc4d662daa9/src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Documents/Glyphs.cs#L448-L484","documentation":"Thrown by Glyphs.SetClusterMapEntry, the guarded writer for the clusterMap array built during Glyphs parsing. If the caller tries to write a cluster-map entry at an index at or beyond the array length, the UnicodeString is shorter than the glyph/cluster data implies. It is a validation guard meaning the Characters/UnicodeString supplied does not cover all parsed glyph indices.","triggerScenarios":"Calling ParseGlyphsProperty (via Glyphs.GlyphIndices/UnicodeString assignment) where the number of characters implied by glyph clusters exceeds Glyphs.UnicodeString.Length — i.e. more cluster-map entries than characters.","commonSituations":"GlyphIndices and UnicodeString edited out of sync in XAML; adding a glyph cluster without adding corresponding characters to UnicodeString.","solutions":["Extend Glyphs.UnicodeString so it has at least as many characters as the cluster map requires.","Reduce the number of glyph indices/clusters in GlyphIndices to match the UnicodeString length.","Compute/check that parsedCharacterCount stays < UnicodeString.Length before writing cluster-map entries."],"exampleFix":"// before\nglyphs.UnicodeString = \"AB\";      // 2 chars\nglyphs.GlyphIndices = \";(1:1);(2:1);(3:1)\"; // needs >= 4 chars\n// after\nglyphs.UnicodeString = \"ABCD\";\nglyphs.GlyphIndices = \";(1:1);(2:1);(3:1)\";","handlingStrategy":"validation","validationCode":"int impliedChars = CountClusterCharacters(glyphIndices); // sum characterClusterSize over cluster tokens\nif (glyphs.UnicodeString == null || glyphs.UnicodeString.Length < impliedChars)\n    throw new InvalidOperationException(\"UnicodeString shorter than glyph cluster data\");","typeGuard":"static bool UnicodeCoversClusters(string unicode, string indices) => unicode != null && unicode.Length >= indices.Split(';').Length;","tryCatchPattern":"try { ApplyGlyphs(glyphs, indices, unicode); }\ncatch (ArgumentException ex) { RegenerateIndicesFromUnicode(glyphs); }\n// recovery: rebuild GlyphIndices from the UnicodeString so lengths always agree","preventionTips":["Always generate GlyphIndices and UnicodeString together from one source of truth","After editing UnicodeString, regenerate Indices","Assert unicode.Length >= glyphEntryCount before assignment"],"tags":["wpf","glyphs","unicode","parsing","index-out-of-range"],"backgroundTag":"index-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"}