[Mono-dev] Cecil bug report and a question

Bjarke Hammersholt Roune bjarke.roune at gmail.com
Thu Aug 24 12:53:31 EDT 2006


Hi,

Jb Evain skrev:
> Hi,
> 
> Bjarke Hammersholt Roune wrote:
>> I have found the following bug in Cecil. Here is how to trigger it: Make 
>> an assembly with a method where the last instruction in that method is 
>> also the last instruction in a handler block. Use Cecil to load the 
>> assembly and then save it. This will result in a NullReferenceException 
>> being thrown from Mono.Cecil.Cil.CodeWriter.IsRangeFat. I have attached 
>> an example assembly that contains such a method.
> 
> This seems to be already fixed. Please use the very fresh 0.4.3 release 
> or even better, an always up to date SVN checkout.
> 
Thank you for the prompt and informative reply! I thought I was using 
the newest version, but I did not think to check if a new version had 
been released. Sorry about that.

I have taken a look at 0.4.3, and you are correct that it can read and 
then write the bug-triggering assembly that I attached to my previous 
bug report without problems. The issue has not been entirely fixed, 
however. I have attached an assembly that makes Cecil output an invalid 
assembly. This is using Cecil 0.4.3 - I have not checked the version of 
Cecil in SVN. Specifically MS peverify gives the following complaint 
when I run it on the output:

[IL]: Error: [E:\net\o.exe : Bug::Main][offset 0x00000007] Handler 
starts in the middle of an instruction.

As far as I can tell the problem is rather the handler end than the 
start, but maybe I am wrong (I can't inspect it manually as ildasm does 
not display what the actual ranges are, probably because in this case 
the handler is invalid).

I believe I have tracked the problem down to the following method in 
CodeWriter.cs:

int GetLength (Instruction start, Instruction end, Instruction last)
{
	return (end == null ? last.Offset + last.OpCode.Size : end.Offset) - 
start.Offset;
}

As far as I have been able to figure out, OpCode.Size is only the size 
of the opcode itself - it does not include any parameters that follow 
the opcode. Thus the ending offset is miscalculated in case the last 
instruction in the method has any parameters, and that instruction is 
also the last instruction in an exception handler.

Adding a dummy return instruction at the end of the instruction stream 
also works as a temporary work around for this bug, as return 
instructions do not take parameters.

>> It would probably be a good idea to document how ranges are represented 
>> in Cecil in the FAQ, as there are several reasonable ways it could work, 
>>  and it is not possible to tell from the Cecil interface which one it is.
> 
> Good idea! Feel tree to add another entry to 
> http://www.mono-project.com/Cecil:FAQ
> 
The thing is, I am not sure how ranges are handled in Cecil. I think it 
works like this: all ranges of instructions are represented as half open 
intervals [start, end), where start and end are pointers to actual 
Instructions. start and end can be null if they are past the last 
instruction. Is this correct?

>> I also have a question: I have an example of an assembly output by the 
>> MS C# compiler that shrinks from 3.072 bytes to 2.048 bytes simply by 
>> loading and then saving it using Cecil. How does that happen?
> 
> Cecil does not preserve the .rsrc (aka Win32 resources) section or the 
> PE file for the moment. So it saves some place.
> 
What are the consequences of this other than smaller assemblies?

Regards
Bjarke Roune
-------------- next part --------------
A non-text attachment was scrubbed...
Name: bug2
Type: application/octet-stream
Size: 2048 bytes
Desc: not available
Url : http://lists.ximian.com/pipermail/mono-devel-list/attachments/20060824/da899d7a/attachment.obj 


More information about the Mono-devel-list mailing list