diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/CS73_StackAllocInitializers.cs b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/CS73_StackAllocInitializers.cs index d082d149a..e5ec81ba4 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/CS73_StackAllocInitializers.cs +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/CS73_StackAllocInitializers.cs @@ -257,6 +257,33 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty return UsePointer((byte*)ptr); } + // A buffer that is only partially written through a reinterpreting cast is not an + // initializer: the fourth int is never assigned, so it must stay a sequence of stores + // rather than be reconstructed as 'stackalloc int[4] { 1, v, 3 }' (too few elements). + public unsafe string PartialReinterpret(int v) + { +#if OPT + byte* num = stackalloc byte[16]; + *(int*)num = 1; + ((int*)num)[1] = v; + ((int*)num)[2] = 3; + long num2 = 0L; + return UseBytePointer(num, &num2); +#else + byte* ptr = stackalloc byte[16]; + *(int*)ptr = 1; + ((int*)ptr)[1] = v; + ((int*)ptr)[2] = 3; + long num = 0L; + return UseBytePointer(ptr, &num); +#endif + } + + public unsafe static string UseBytePointer(byte* ptr, long* length) + { + return ((int*)ptr)->ToString(); + } + public unsafe string NegativeOffsets(int a, int b, int c) { #if OPT diff --git a/ICSharpCode.Decompiler/IL/Transforms/TransformArrayInitializers.cs b/ICSharpCode.Decompiler/IL/Transforms/TransformArrayInitializers.cs index 6245920c1..9ae14ec99 100644 --- a/ICSharpCode.Decompiler/IL/Transforms/TransformArrayInitializers.cs +++ b/ICSharpCode.Decompiler/IL/Transforms/TransformArrayInitializers.cs @@ -515,8 +515,12 @@ namespace ICSharpCode.Decompiler.IL.Transforms elementCount++; } - if (values == null || store.Kind != VariableKind.StackSlot || store.StoreCount != 1 - || store.AddressCount != 0 || store.LoadCount > values.Length + 1) + // Every element must be written, either from the constant data blob or by an explicit + // store. A gap means the buffer is only partially initialized (e.g. a 'stackalloc + // byte[16]' reinterpreted and written through a few elements), which cannot be + // represented as an initializer and has to stay a sequence of individual stores. + if (values == null || Array.IndexOf(values, null) >= 0 || store.Kind != VariableKind.StackSlot + || store.StoreCount != 1 || store.AddressCount != 0 || store.LoadCount > values.Length + 1) return false; if (store.LoadInstructions.Last().Parent is StLoc finalStore)