jbevain / cecil

Cecil is a library to inspect, modify and create .NET programs and libraries.
MIT License
2.77k stars 630 forks source link

System.IndexOutOfRangeException at Mono.Cecil.MetadataReader.ReadLocalConstant in certain pdb #773

Closed ashmind closed 3 years ago

ashmind commented 3 years ago

Thank you for your work on this project!

I have found an issue where Cecil crashes when trying to load a certain dll+pdb.

Here is a minimal example project to reproduce this, using Cecil 0.11.3: Bugs.Cecil.IndexOutOfRangeExceptionAtReadLocalConstant.zip

When I run it, I get a crash with

_.exe
  <Module>
  <Program>$
    <Main>$
Unhandled exception. System.IndexOutOfRangeException: Index was outside the bounds of the array.
   at Mono.Cecil.MetadataReader.ReadLocalConstant(UInt32 rid)
   at Mono.Cecil.MetadataReader.ReadLocalScope(Row`6 record)
   at Mono.Cecil.MetadataReader.ReadScope(MethodDefinition method)
   at Mono.Cecil.Cil.PortablePdbReader.ReadScope(MethodDebugInformation method_info)
   at Mono.Cecil.Cil.PortablePdbReader.Read(MethodDefinition method)
   at Mono.Cecil.Cil.CodeReader.ReadMethodBody()
   at Mono.Cecil.Cil.CodeReader.ReadMethodBody(MethodDefinition method)
   at Mono.Cecil.MetadataReader.ReadMethodBody(MethodDefinition method)
   at Mono.Cecil.MethodDefinition.<>c.<get_Body>b__41_0(MethodDefinition method, MetadataReader reader)
   at Mono.Cecil.ModuleDefinition.Read[TItem,TRet](TRet& variable, TItem item, Func`3 read)
   at Mono.Cecil.MethodDefinition.get_Body()
   at <Program>$.<Main>$(String[] args) in Bugs.Cecil.IndexOutOfRangeExceptionAtReadLocalConstant\Program.cs:line 28
jbevain commented 3 years ago

@ashmind thank you for filing this and providing a repro! I'll have a look!

jbevain commented 3 years ago

@ashmind out of curiosity, do you have the source for the TestAssembly? That doesn't look like regular C#, and the local constant record doesn't look like it's been properly generated, it says it's a string constant but it has no value. I can fix it to interpret this as a null string value, but the IL does a ldstr "", so I'm thinking the string constant is for this empty string. If that's the case, the local const entry should have an empty string in there

ashmind commented 3 years ago

Thanks! The source is

using System;

const string value = "";
int.TryParse(value, out var _);

when built with Roslyn directly (Microsoft.CodeAnalysis.CSharp 3.10.0).

E.g: https://sharplab.io/#v2:C4LgTgrgdgNAJiA1AHwAICYCMBYAUHgYwHsoBnYAAlUwAYKA3AQwBsIBTCgXgoCIeBuPAEsowAHQAVMAE8ACozCk2ACias2MCkQiUmYCgH0AlPyA

Unfortunately I can't quickly check if building same with MSBuild and command line compiler produces the same (might depend on the version of course).

jbevain commented 3 years ago

Oh it's ok, just a misunderstanding on my side of things, the entry is indeed valid. I've pushed an actual fix in #776.