From 898c2a3f9f2aca103d29bf57b14924622b83d80e Mon Sep 17 00:00:00 2001 From: ds5678 <49847914+ds5678@users.noreply.github.com> Date: Sat, 11 Jul 2026 13:54:32 -0700 Subject: [PATCH] Add Issue3877 test and handle negative dict capacity Added Issue3877 test to PrettyTestRunner and new test case source to verify dictionary initialization with negative capacity. Updated SwitchOnStringTransform to skip processing when a negative dictionary capacity is detected. --- .../PrettyTestRunner.cs | 6 ++ .../TestCases/Pretty/Issue3877.cs | 65 +++++++++++++++++++ .../IL/Transforms/SwitchOnStringTransform.cs | 2 + 3 files changed, 73 insertions(+) create mode 100644 ICSharpCode.Decompiler.Tests/TestCases/Pretty/Issue3877.cs diff --git a/ICSharpCode.Decompiler.Tests/PrettyTestRunner.cs b/ICSharpCode.Decompiler.Tests/PrettyTestRunner.cs index 707b1d1a6..e70b58e32 100644 --- a/ICSharpCode.Decompiler.Tests/PrettyTestRunner.cs +++ b/ICSharpCode.Decompiler.Tests/PrettyTestRunner.cs @@ -836,6 +836,12 @@ namespace ICSharpCode.Decompiler.Tests await RunForLibrary(cscOptions: cscOptions); } + [Test] + public async Task Issue3877([ValueSource(nameof(roslyn2OrNewerWithNet40Options))] CompilerOptions cscOptions) + { + await RunForLibrary(cscOptions: cscOptions); + } + [Test] public async Task AssemblyCustomAttributes([ValueSource(nameof(defaultOptions))] CompilerOptions cscOptions) { diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/Issue3877.cs b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/Issue3877.cs new file mode 100644 index 000000000..517de87cc --- /dev/null +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/Issue3877.cs @@ -0,0 +1,65 @@ +using System.Collections.Generic; +using System.Runtime.CompilerServices; + +namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty +{ + internal static class Issue3877 + { + [CompilerGenerated] + private static Dictionary backingField; + + public static void M(string s) + { + N(0); + if (s != null) + { + if (backingField == null) + { +#if OPT + backingField = new Dictionary(-87) { + { "string0", 0 }, + { "string1", 1 }, + { "string2", 2 }, + { "string3", 3 }, + { "string4", 4 } + }; +#else + Dictionary dictionary = new Dictionary(-87); + dictionary.Add("string0", 0); + dictionary.Add("string1", 1); + dictionary.Add("string2", 2); + dictionary.Add("string3", 3); + dictionary.Add("string4", 4); + backingField = dictionary; +#endif + } + if (backingField.TryGetValue(s, out var value)) + { + switch (value) + { + case 0: + N(10); + break; + case 1: + N(20); + break; + case 2: + N(30); + break; + case 3: + N(40); + break; + case 4: + N(50); + break; + } + } + } + N(60); + } + + public static void N(int i) + { + } + } +} diff --git a/ICSharpCode.Decompiler/IL/Transforms/SwitchOnStringTransform.cs b/ICSharpCode.Decompiler/IL/Transforms/SwitchOnStringTransform.cs index de0407eb3..df75cb5e4 100644 --- a/ICSharpCode.Decompiler/IL/Transforms/SwitchOnStringTransform.cs +++ b/ICSharpCode.Decompiler/IL/Transforms/SwitchOnStringTransform.cs @@ -818,6 +818,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms if (!newObj.Arguments[0].MatchLdcI4(out valuesLength)) return false; } + if (valuesLength < 0) + return false; values = new List<(string, int)>(valuesLength); int i = 0; while (MatchAddCall(dictionaryType, block.Instructions[i + 1], dictVar, out var index, out var value))