ART: Fix verification of constructors.

Summary:

A constructor must call its superclass constructor. However, if one
replaces the invoke-direct superclass.<init>() instruction with a
variety of instructions, the verifier would NOT complain that the
superclass constructor hadn't been called.

Detailed explanation:

This was because if we are verifying the return-void insn of a
constructor, then we check that the register line doesn't contain a
register with an UninitializedThis type. With a method like follows:

Class.<init>()V:
  return-void

Then we hit the return-void, see the UninitializedThis, and fail the
method. However, with a method like follows:

Class.<init>()V:
  nop
  return-void

Any insn that continues or branches onto a return-void instruction will
mark all of the registers as Conflict. This meant that the check in
return-void for an UninitializedThis residing the register line would
_always_ pass if there were any insns before it - the entire line had
been set to Conflict.

The fix is to bring the check for an UninitializedThis forward to the
point just before we set all registers to Conflict, if we're about to
hit a return-void insn in a constructor. It still needs to be done
again in the verification of return-void itself, to avoid the solo
return-void case.

This patch also deals with the case where the only remaining
UninitializedThis reference is overwritten, to avoid a method like the
following from getting through verification:

Class.<init>()V:
  const/4 v0, 0
  return-void

Bug: 18800943

Change-Id: I2e317261844d3b6c78e35228669f3da173316570
Fuzzed-With: https://android-review.googlesource.com/#/c/119463/
8 files changed