diff options
author | vitek-karas <vitek.karas@microsoft.com> | 2020-08-27 14:48:27 +0300 |
---|---|---|
committer | Marek Safar <marek.safar@gmail.com> | 2020-09-07 22:04:06 +0300 |
commit | 75fc419764f239dcdd679657316e6eae31e04dc2 (patch) | |
tree | 3763e97908a4405eefffbcb636e3a3ce06bcd23f | |
parent | c2dec1423990005029279785905e8c54abb706d4 (diff) |
Fix crash with null local scoperelease/5.0
-rw-r--r-- | Mono.Cecil.Cil/MethodBody.cs | 27 | ||||
-rw-r--r-- | Test/Mono.Cecil.Tests/ILProcessorTests.cs | 14 |
2 files changed, 17 insertions, 24 deletions
diff --git a/Mono.Cecil.Cil/MethodBody.cs b/Mono.Cecil.Cil/MethodBody.cs index 4aa71a9..d970a01 100644 --- a/Mono.Cecil.Cil/MethodBody.cs +++ b/Mono.Cecil.Cil/MethodBody.cs @@ -340,32 +340,11 @@ namespace Mono.Cecil.Cil { UpdateLocalScope (debug_info.Scope, removedInstruction, existingInstruction, ref cache); } - static void UpdateLocalScope (ScopeDebugInformation scope, int startFromOffset, int offset, Instruction instructionRemoved) - { - // For both start and enf offsets on the scope: - // * If the offset is resolved (points to instruction by reference) only update it if the instruction it points to is being removed. - // For non-removed instructions it remains correct regardless of any updates to the instructions. - // * If the offset is not resolved (stores the instruction offset number itself) - // update the number accordingly to keep it pointing to the correct instruction (by offset). - - if ((!scope.Start.IsResolved && scope.Start.Offset >= startFromOffset) || - (instructionRemoved != null && scope.Start.ResolvedInstruction == instructionRemoved)) - scope.Start = new InstructionOffset (scope.Start.Offset + offset); - - // For end offset only update it if it's not the special sentinel value "EndOfMethod"; that should remain as-is. - if (!scope.End.IsEndOfMethod && - ((!scope.End.IsResolved && scope.End.Offset >= startFromOffset) || - (instructionRemoved != null && scope.End.ResolvedInstruction == instructionRemoved))) - scope.End = new InstructionOffset (scope.End.Offset + offset); - - if (scope.HasScopes) { - foreach (var subScope in scope.Scopes) - UpdateLocalScope (subScope, startFromOffset, offset, instructionRemoved); - } - } - void UpdateLocalScope (ScopeDebugInformation scope, Instruction removedInstruction, Instruction existingInstruction, ref InstructionOffsetCache cache) { + if (scope == null) + return; + if (!scope.Start.IsResolved) scope.Start = ResolveInstructionOffset (scope.Start, ref cache); diff --git a/Test/Mono.Cecil.Tests/ILProcessorTests.cs b/Test/Mono.Cecil.Tests/ILProcessorTests.cs index 446e8fc..8836615 100644 --- a/Test/Mono.Cecil.Tests/ILProcessorTests.cs +++ b/Test/Mono.Cecil.Tests/ILProcessorTests.cs @@ -194,6 +194,20 @@ namespace Mono.Cecil.Tests { methodBody.Method.Module.Dispose (); } + [Test] + public void EditWithDebugInfoButNoLocalScopes() + { + var methodBody = CreateTestMethod (OpCodes.Ret); + methodBody.Method.DebugInformation = new MethodDebugInformation (methodBody.Method); + + var il = methodBody.GetILProcessor (); + il.Replace (methodBody.Instructions [0], il.Create (OpCodes.Nop)); + + Assert.AreEqual (1, methodBody.Instructions.Count); + Assert.AreEqual (Code.Nop, methodBody.Instructions [0].OpCode.Code); + Assert.Null (methodBody.Method.DebugInformation.Scope); + } + static void AssertOpCodeSequence (OpCode [] expected, MethodBody body) { var opcodes = body.Instructions.Select (i => i.OpCode).ToArray (); |