Fix bug in verifier: hard fail allowed following softfail
Rationale:
Dexfuzzing found a situation where a hard fail (not calling
super in constructor) did not immediately bail, allowing
a soft fail to follow, causing a FATAL message later on.
With crash-before/pass after test.
BUG=29070461
Change-Id: I46bd7a7457b9d408b254400aadac122539f2279c
diff --git a/runtime/verifier/method_verifier.cc b/runtime/verifier/method_verifier.cc
index b2be770..8ad79fb 100644
--- a/runtime/verifier/method_verifier.cc
+++ b/runtime/verifier/method_verifier.cc
@@ -4928,6 +4928,9 @@
// Initialize them as conflicts so they don't add to GC and deoptimization information.
const Instruction* ret_inst = Instruction::At(code_item_->insns_ + next_insn);
AdjustReturnLine(this, ret_inst, target_line);
+ if (have_pending_hard_failure_) {
+ return false;
+ }
}
} else {
RegisterLineArenaUniquePtr copy;
diff --git a/test/600-verifier-fails/expected.txt b/test/600-verifier-fails/expected.txt
index b0aad4d..e06fe1d 100644
--- a/test/600-verifier-fails/expected.txt
+++ b/test/600-verifier-fails/expected.txt
@@ -1 +1,2 @@
-passed
+passed A
+passed B
diff --git a/test/600-verifier-fails/info.txt b/test/600-verifier-fails/info.txt
index 478dd9b..781b922 100644
--- a/test/600-verifier-fails/info.txt
+++ b/test/600-verifier-fails/info.txt
@@ -1,4 +1,12 @@
-The situation in this test was discovered by running dexfuzz on
-another fuzzingly random generated Java test. The soft verification
-fail (on the final field modification) should not hide the hard
-verification fail (on the type mismatch) to avoid a crash later on.
+The situations in these tests were discovered by running the mutating
+dexfuzz on the DEX files of fuzzingly random generated Java test.
+
+(1) b/28908555:
+ soft verification fail (on the final field modification) should
+ not hide the hard verification fail (on the type mismatch) to
+ avoid compiler crash later on.
+(2) b/29070461:
+ hard failure (not calling super in constructor) should bail
+ immediately and not allow soft fails to pile up behind it to
+ avoid fatal message later on
+
diff --git a/test/600-verifier-fails/smali/construct.smali b/test/600-verifier-fails/smali/construct.smali
new file mode 100644
index 0000000..417ced9
--- /dev/null
+++ b/test/600-verifier-fails/smali/construct.smali
@@ -0,0 +1,25 @@
+#
+# Copyright (C) 2016 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+.class public LB;
+.super Ljava/lang/Object;
+
+.method public constructor <init>()V
+ .registers 1
+ if-eqz v0, :bail
+ invoke-direct {v0}, LB;->append(Ljava/lang/String;)V
+:bail
+ return-void
+.end method
diff --git a/test/600-verifier-fails/src/Main.java b/test/600-verifier-fails/src/Main.java
index ba4cc31..70873b2 100644
--- a/test/600-verifier-fails/src/Main.java
+++ b/test/600-verifier-fails/src/Main.java
@@ -14,8 +14,6 @@
* limitations under the License.
*/
-import java.lang.reflect.Method;
-
public class Main {
public static final String staticField = null;
@@ -24,7 +22,12 @@
try {
Class<?> a = Class.forName("A");
} catch (java.lang.VerifyError e) {
- System.out.println("passed");
+ System.out.println("passed A");
+ }
+ try {
+ Class<?> a = Class.forName("B");
+ } catch (java.lang.VerifyError e) {
+ System.out.println("passed B");
}
}
}