[Mono-dev] Cecil bug report and a question
Bjarke Hammersholt Roune
bjarke.roune at gmail.com
Thu Aug 24 12:53:31 EDT 2006
Jb Evain skrev:
> 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
int GetLength (Instruction start, Instruction end, Instruction last)
return (end == null ? last.Offset + last.OpCode.Size : end.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
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?
-------------- next part --------------
A non-text attachment was scrubbed...
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