Json.cs: Catastrophic regex backtracking in Regex_String causes extreme slowdown with JSON arrays
Ninguém assumiu esta issue ainda.
Avaliação
- Dificuldade
- 2/5
- Tempo estimado
- 1-3 horas
- Facilidade para iniciantes
- 74/100
Direção de pesquisa
Abra ColorCode.Core/Compilation/Languages/Json.cs e inspecione o padrão Regex_String e a regra de correspondência de chaves descrita na issue. Reproduza a lentidão com arrays JSON contendo valores de string, substitua a repetição que corresponde a uma string vazia pelo padrão unrolled-loop especificado e verifique se o exemplo é colorido prontamente sem alterar os JSON scopes esperados.
Escrita pelo modelo de indexação a partir do texto da issue.
Descrição
Description
The JSON language definition in the underlying ColorCode-Universal dependency (ColorCode.Core/Compilation/Languages/Json.cs) contains a catastrophic backtracking bug in its Regex_String pattern. This causes exponential processing time (O(2^n)) when colorizing JSON that contains arrays with string values, making the application appear completely frozen.
The pattern is:
"[^"\\]*(?:\\[^\r\n]|[^"\\]*)*"
The repeating group (?:\\[^\r\n]|[^"\\]*) has two alternatives:
\\[^\r\n]— backslash escape, always consumes 2 characters ✓[^"\\]*— can match an empty string ✗
The key-matching rule [,{]\s*("...")\s*: attempts to match JSON keys (string followed by :). For every , inside a JSON array, the engine tries this rule, matches the string value (e.g. "John Doe"), but fails when no : follows. On failure, the engine backtracks into the string subpattern and tries all possible ways to partition the n non-special characters between the outer [^"\\]* and the inner (?:[^"\\]*) repetition — resulting in O(2^n) backtracking states. For a 16-character string value this is ~65,000 states; for longer strings the number grows exponentially.
The fix is to replace the pattern with Friedl's Unrolled Loop:
"[^"\\]*(?:\\.[^"\\]*)*"
Each iteration of the group now must consume at least 2 characters via \\., eliminating the empty alternative and all backtracking.
Expected Behaviour
JSON arrays with string values are colorized in milliseconds, identical to simple JSON objects without arrays.
Actual Behaviour
Colorizing JSON containing arrays with string values causes extreme slowdown. Processing time grows exponentially with the length of string values inside arrays. Simple JSON objects (no arrays) are not affected.
Affected Version
3.0.1
Steps to Reproduce
- Set up a Markdig pipeline with
UseColorCode() - Call
Markdig.Markdown.ToHtml()on a Markdown document containing the following fenced code block:
```json
{
"Project": "My Project",
"Tags": [
"first long string value",
"another long string value"
]
}
```
- Observe that processing takes several seconds (or longer) instead of being near-instantaneous
- Note that removing the array (keeping only simple key-value pairs) restores normal performance
Workaround (until the underlying bug is fixed in ColorCode-Universal): pass a corrected JSON language definition via additionalLanguages:
var pipeline = new MarkdownPipelineBuilder()
.UseAdvancedExtensions()
.UseColorCode(additionalLanguages: new[] { new JsonLanguageFixed() })
.Build();
// Friedl's Unrolled Loop – no backtracking, correct escape handling
private sealed class JsonLanguageFixed : ILanguage
{
private const string RegexString = @"""[^""\\]*(?:\\.[^""\\]*)*""";
private const string RegexNumber = @"-?(?:0|[1-9][0-9]*)(?:\.[0-9]*)?(?:[eE][-+]?[0-9]+)?";
public string Id => LanguageId.Json;
public string Name => "JSON";
public string CssClassName => "json";
public string FirstLinePattern => null;
public IList<LanguageRule> Rules => new List<LanguageRule>
{
new LanguageRule($@"[,\{{]\s*({RegexString})\s*:", new Dictionary<int, string> { { 1, ScopeName.JsonKey } }),
new LanguageRule(RegexString, new Dictionary<int, string> { { 0, ScopeName.JsonString } }),
new LanguageRule(RegexNumber, new Dictionary<int, string> { { 0, ScopeName.JsonNumber } }),
new LanguageRule(@"\b(true|false|null)\b", new Dictionary<int, string> { { 1, ScopeName.JsonConst } }),
};
public bool HasAlias(string lang) => false;
}
Checklist
- I have read the contributing guidelines
- I have verified this does not duplicate an existing issue
- Linguagem predominante
- C#
- Estrelas
- 267
- Forks
- 58
- Métricas de merge de PRs
- Nenhum PR com merge em 30d
Guia de contribuição
Nenhum guia de contribuição indexado para este repositório
Primeiros passos
- Leia a issue inteira e depois o guia de contribuição do projeto.
- Comente na issue dizendo que vai assumir — evita que duas pessoas façam o mesmo trabalho.
- Faça um fork do repositório e trabalhe em uma branch.
- Abra um pull request que referencie o número da issue.
Mais de CommunityToolkit/ColorCode-Universal
-
Dificuldade 5/5 Mais de uma semana Facilidade para iniciantes 20/100
-
Dificuldade 3/5 1-2 dias Facilidade para iniciantes 30/100
-
Dificuldade 3/5 1-2 dias Facilidade para iniciantes 38/100
-
Dificuldade 3/5 1-2 dias Facilidade para iniciantes 38/100
-
Dificuldade 4/5 3-5 dias Facilidade para iniciantes 35/100
CommunityToolkit/ColorCode-Universal#36 · 6 comentários ·
Todas as issues de CommunityToolkit/ColorCode-Universal
Issues semelhantes
-
[Feat] 조합 영역 구분선 개선 Aberta
Dificuldade 2/5 1-3 horas Facilidade para iniciantes 68/100
-
type/automation type/tech-debt
Dificuldade 2/5 1-3 horas Facilidade para iniciantes 78/100
-
bug
Dificuldade 2/5 1-3 horas Facilidade para iniciantes 88/100
-
t/bug
Dificuldade 2/5 1-3 horas Facilidade para iniciantes 82/100
-
ci-failure-cause test-failure
Dificuldade 2/5 1-3 horas Facilidade para iniciantes 82/100