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

Attachment: bug2
Description: Binary data

_______________________________________________
Mono-devel-list mailing list
Mono-devel-list@lists.ximian.com
http://lists.ximian.com/mailman/listinfo/mono-devel-list

Reply via email to