Avoid abort in malformed dex code.

Don't allow a perceived double monitor-enter on a register
to abort libartd.
Allow expected verifier errors in the smali tests.
Tidy includes in the method verifier.
Bug: 17978759

Change-Id: Ic44924c788cd2334f91a047fb41b459b89a1843b
diff --git a/test/800-smali/expected.txt b/test/800-smali/expected.txt
index 3e3955b..f766b0a 100644
--- a/test/800-smali/expected.txt
+++ b/test/800-smali/expected.txt
@@ -1,4 +1,5 @@
 b/17790197
+b/17978759
 FloatBadArgReg
 negLong
 Done!
diff --git a/test/800-smali/smali/b_17978759.smali b/test/800-smali/smali/b_17978759.smali
new file mode 100644
index 0000000..07bcae5
--- /dev/null
+++ b/test/800-smali/smali/b_17978759.smali
@@ -0,0 +1,28 @@
+.class public LB17978759;
+.super Ljava/lang/Object;
+
+  .method public constructor <init>()V
+    .registers 1
+    invoke-direct {p0}, Ljava/lang/Object;-><init>()V
+    return-void
+  .end method
+
+  .method public test()V
+    .registers 2
+
+    move-object   v0, p0
+    # v0 and p0 alias
+    monitor-enter p0
+    # monitor-enter on p0
+    monitor-exit  v0
+    # monitor-exit on v0, however, verifier doesn't track this and so this is
+    # a warning. Verifier will still think p0 is locked.
+
+    move-object   v0, p0
+    # v0 will now appear locked.
+    monitor-enter v0
+    # Attempt to lock v0 twice is a verifier failure.
+    monitor-exit  v0
+
+    return-void
+  .end method
diff --git a/test/800-smali/src/Main.java b/test/800-smali/src/Main.java
index 87549d9..014edc0 100644
--- a/test/800-smali/src/Main.java
+++ b/test/800-smali/src/Main.java
@@ -15,6 +15,7 @@
  */
 
 import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
 import java.util.LinkedList;
 import java.util.List;
 
@@ -49,6 +50,7 @@
         testCases = new LinkedList<TestCase>();
 
         testCases.add(new TestCase("b/17790197", "B17790197", "getInt", null, null, 100));
+        testCases.add(new TestCase("b/17978759", "B17978759", "test", null, new VerifyError(), null));
         testCases.add(new TestCase("FloatBadArgReg", "FloatBadArgReg", "getInt",
             new Object[]{100}, null, 100));
         testCases.add(new TestCase("negLong", "negLong", "negLong", null, null, 122142L));
@@ -66,47 +68,59 @@
     }
 
     private void runTest(TestCase tc) throws Exception {
-        Class<?> c = Class.forName(tc.testClass);
-
-        Method[] methods = c.getDeclaredMethods();
-
-        // For simplicity we assume that test methods are not overloaded. So searching by name
-        // will give us the method we need to run.
-        Method method = null;
-        for (Method m : methods) {
-            if (m.getName().equals(tc.testMethodName)) {
-                method = m;
-                break;
-            }
-        }
-
-        if (method == null) {
-            throw new IllegalArgumentException("Could not find test method " + tc.testMethodName +
-                    " in class " + tc.testClass + " for test " + tc.testName);
-        }
-
         Exception errorReturn = null;
         try {
-            Object retValue = method.invoke(null, tc.values);
-            if (tc.expectedException != null) {
-                errorReturn = new IllegalStateException("Expected an exception in test " +
-                                                        tc.testName);
+            Class<?> c = Class.forName(tc.testClass);
+
+            Method[] methods = c.getDeclaredMethods();
+
+            // For simplicity we assume that test methods are not overloaded. So searching by name
+            // will give us the method we need to run.
+            Method method = null;
+            for (Method m : methods) {
+                if (m.getName().equals(tc.testMethodName)) {
+                    method = m;
+                    break;
+                }
             }
-            if (tc.expectedReturn == null && retValue != null) {
-                errorReturn = new IllegalStateException("Expected a null result in test " +
-                                                        tc.testName);
-            } else if (tc.expectedReturn != null &&
-                       (retValue == null || !tc.expectedReturn.equals(retValue))) {
-                errorReturn = new IllegalStateException("Expected return " + tc.expectedReturn +
-                                                        ", but got " + retValue);
+
+            if (method == null) {
+                errorReturn = new IllegalArgumentException("Could not find test method " +
+                                                           tc.testMethodName + " in class " +
+                                                           tc.testClass + " for test " +
+                                                           tc.testName);
+            } else {
+                Object retValue;
+                if (Modifier.isStatic(method.getModifiers())) {
+                    retValue = method.invoke(null, tc.values);
+                } else {
+                    retValue = method.invoke(method.getDeclaringClass().newInstance(), tc.values);
+                }
+                if (tc.expectedException != null) {
+                    errorReturn = new IllegalStateException("Expected an exception in test " +
+                                                            tc.testName);
+                }
+                if (tc.expectedReturn == null && retValue != null) {
+                    errorReturn = new IllegalStateException("Expected a null result in test " +
+                                                            tc.testName);
+                } else if (tc.expectedReturn != null &&
+                           (retValue == null || !tc.expectedReturn.equals(retValue))) {
+                    errorReturn = new IllegalStateException("Expected return " +
+                                                            tc.expectedReturn +
+                                                            ", but got " + retValue);
+                } else {
+                    // Expected result, do nothing.
+                }
             }
-        } catch (Exception exc) {
+        } catch (Throwable exc) {
             if (tc.expectedException == null) {
                 errorReturn = new IllegalStateException("Did not expect exception", exc);
             } else if (!tc.expectedException.getClass().equals(exc.getClass())) {
                 errorReturn = new IllegalStateException("Expected " +
-                                                tc.expectedException.getClass().getName() +
-                                                ", but got " + exc.getClass(), exc);
+                                                        tc.expectedException.getClass().getName() +
+                                                        ", but got " + exc.getClass(), exc);
+            } else {
+              // Expected exception, do nothing.
             }
         } finally {
             if (errorReturn != null) {