Fix bug where verification could crash on unresolved types.
Bug: 27626708
Change-Id: I708ee18215dccadc00ff3daa1e01c2830475ccae
diff --git a/runtime/verifier/method_verifier.cc b/runtime/verifier/method_verifier.cc
index 4019656..537d9c9 100644
--- a/runtime/verifier/method_verifier.cc
+++ b/runtime/verifier/method_verifier.cc
@@ -3992,13 +3992,17 @@
// TODO Can we verify anything else.
if (class_idx == class_def_->class_idx_) {
Fail(VERIFY_ERROR_CLASS_CHANGE) << "Cannot invoke-super on self as interface";
+ return nullptr;
}
// TODO Revisit whether we want to allow invoke-super on direct interfaces only like the JLS
// does.
- mirror::Class* this_class = GetDeclaringClass().GetClass();
- if (!reference_class->IsAssignableFrom(this_class)) {
+ if (!GetDeclaringClass().HasClass()) {
+ Fail(VERIFY_ERROR_NO_CLASS) << "Unable to resolve the full class of 'this' used in an"
+ << "interface invoke-super";
+ return nullptr;
+ } else if (!reference_class->IsAssignableFrom(GetDeclaringClass().GetClass())) {
Fail(VERIFY_ERROR_CLASS_CHANGE)
- << "invoke-super in " << PrettyClass(this_class) << " in method "
+ << "invoke-super in " << PrettyClass(GetDeclaringClass().GetClass()) << " in method "
<< PrettyMethod(dex_method_idx_, *dex_file_) << " to method "
<< PrettyMethod(method_idx, *dex_file_) << " references "
<< "non-super-interface type " << PrettyClass(reference_class);
diff --git a/test/974-verify-interface-super/expected.txt b/test/974-verify-interface-super/expected.txt
new file mode 100644
index 0000000..7ba7491
--- /dev/null
+++ b/test/974-verify-interface-super/expected.txt
@@ -0,0 +1 @@
+OK. No exception before invoke!
diff --git a/test/974-verify-interface-super/info.txt b/test/974-verify-interface-super/info.txt
new file mode 100644
index 0000000..c5ff1f6
--- /dev/null
+++ b/test/974-verify-interface-super/info.txt
@@ -0,0 +1,3 @@
+Test that we do the right thing with invoke-super on interfaces when there are
+verifier errors.
+
diff --git a/test/974-verify-interface-super/smali/base.smali b/test/974-verify-interface-super/smali/base.smali
new file mode 100644
index 0000000..c7875de
--- /dev/null
+++ b/test/974-verify-interface-super/smali/base.smali
@@ -0,0 +1,31 @@
+# Copyright 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 LBase;
+
+.super La/klass/that/does/not/Exist;
+
+.method public static run()V
+ .locals 4
+ new-instance v0, LBase;
+ invoke-direct {v0}, LBase;-><init>()V
+ invoke-virtual {v0}, LBase;->SayHi()V
+ return-void
+.end method
+
+.method public SayHi()V
+.locals 2
+ invoke-super {p0}, LIface;->SayHi()V
+ return-void
+.end method
diff --git a/test/974-verify-interface-super/smali/iface.smali b/test/974-verify-interface-super/smali/iface.smali
new file mode 100644
index 0000000..89f9c0b
--- /dev/null
+++ b/test/974-verify-interface-super/smali/iface.smali
@@ -0,0 +1,22 @@
+# Copyright 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 abstract interface LIface;
+
+.super Ljava/lang/Object;
+
+.method public SayHi()V
+.locals 0
+ return-void
+.end method
diff --git a/test/974-verify-interface-super/smali/main.smali b/test/974-verify-interface-super/smali/main.smali
new file mode 100644
index 0000000..be4016c
--- /dev/null
+++ b/test/974-verify-interface-super/smali/main.smali
@@ -0,0 +1,40 @@
+# Copyright 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 LMain;
+
+.super Ljava/lang/Object;
+
+.method public static main([Ljava/lang/String;)V
+ .locals 4
+ const-string v0, "OK. No exception before invoke!"
+ sget-object v1, Ljava/lang/System;->out:Ljava/io/PrintStream;
+ invoke-virtual {v1, v0}, Ljava/io/PrintStream;->println(Ljava/lang/Object;)V
+ :try_start
+ invoke-static {}, LBase;->run()V
+ const-string v0, "FAIL: no exception!"
+ sget-object v1, Ljava/lang/System;->out:Ljava/io/PrintStream;
+ invoke-virtual {v1, v0}, Ljava/io/PrintStream;->println(Ljava/lang/Object;)V
+ goto :end
+ :try_end
+ .catch Ljava/lang/LinkageError; {:try_start .. :try_end} :end
+ .catch Ljava/lang/Throwable; {:try_start .. :try_end} :error
+ :error
+ move-exception v0
+ sget-object v1, Ljava/lang/System;->out:Ljava/io/PrintStream;
+ invoke-virtual {v1, v0}, Ljava/io/PrintStream;->println(Ljava/lang/Object;)V
+ invoke-virtual {v0}, Ljava/lang/Throwable;->printStackTrace()V
+ :end
+ return-void
+.end method