0

I'm modifying an assembly using Mono.Cecil, and I want to check it for validity (whether the result will run at all). I'm trying to use PEVerify, but I'm having a problem.

It was designed for ensuring code is verifiable, so it just says ERROR whether the error means the IL is completely invalid and will not execute, or whether it's a verifiability issue that would be ignored in full trust. Here are some examples:

  1. Using pointers and the like.
  2. Not setting .locals init when the method has locals.
  3. Calling .ctor from a non-constructor method.

Issues that make the IL fail to run include:

  1. Member isn't accessible from the location it is used in.
  2. Member doesn't exist.

Is there a way to make it give me some indication of the severity of the issue? If not, is there another tool that can do this?

GregRos
  • 8,667
  • 3
  • 37
  • 63
  • That's just not what PEVerify does. It checks if the IL is valid, that's a Yes/No answer. Security and "glitches" are not considered at all. Using the wrong version of PEVerify was just a silly mistake. – Hans Passant Aug 09 '15 at 21:42
  • @HansPassant I think I may have been unclear or something, unless you're saying unverifiable IL cannot run. I updated the question. If I'm still misunderstanding something, could you please write an answer? I'd like to know. – GregRos Aug 09 '15 at 22:41
  • Using pointers always creates an unverifiable app. The rest are just bugs, the kind you need to fix when PEVerify tells you that you are doing it wrong. – Hans Passant Aug 09 '15 at 22:49
  • @HansPassant I just want to know which errors will make the IL be unable to run, and which won't. I appreciate the program's kind advice, and it is useful, but finding fatal errors is more important to me right now. – GregRos Aug 09 '15 at 22:52

1 Answers1

1

@HansPassant already tried to explain it, but just so that we all understand each other, here's what's going on.

PEVerify checks your assembly for constructs that are not okay. That said, PEVerify is not the JIT compiler. The JIT compiler itself doesn't check the IL assembly - it just grabs the method it's going to call, changes it into an SSA form, optimizes it, compiles it and then calls the resulting binary assembly.

Now, the compiler will evolve over time. Optimizations are changed and added, and the role of the compiler is not necessarily to check for error (if it finds one as a by-product, it'll probably report it, but no guarantees). Remember, the JIT compiler is relentlessly optimized for just one thing, and that is to produce pretty good assembler byte code (because it's a JIT'ted language, the time it takes to compile something is really important). So, two different tools.

This basically results in the following:

  • The compiler will compile and execute what it was given.
  • PEVerify will tell you if the result of the method / assembly is defined.

If you ignore an error of PEVerify, this basically means that the result will be undefined behavior - which can be anything from a working executable to a hard crash. There is no such thing as a 'warning'.

atlaste
  • 30,418
  • 3
  • 57
  • 87
  • :S I'm really confused. What you're saying goes against [the description of the tool itself](https://msdn.microsoft.com/en-us/library/62bwd2yd(v=vs.110).aspx), as well as my understanding of the ECMA335 specification. For example, I was under the impression that not specifying `.locals init` just didn't initialize the locals, not cause undefined behavior. – GregRos Aug 14 '15 at 18:45
  • @GreĝRos Well that depends on if the JIT expects it, right? Code that cannot be verified, cannot be verified - simple as that. http://stackoverflow.com/questions/17645487/how-to-understand-these-paragraphs-in-emca-335-regarding-locals-init . Fair enough, it's 'sometimes defined behavior'... (I'd just never go for that). – atlaste Aug 14 '15 at 19:06
  • I'm wondering why you would want that in the first place. If you initialize it to zero and then to something else, the 0 init will become victim to dead code elimination. In practically all cases I wouldn't expect you to gain anything from skipping the `.locals init`... – atlaste Aug 14 '15 at 19:10