diff options
| author | 2015-10-27 14:06:34 -0700 | |
|---|---|---|
| committer | 2015-10-28 17:09:06 -0700 | |
| commit | 0db36b3ec3feb34adabf5d211612226a66d8b063 (patch) | |
| tree | e5b064895cc093991f6bb6e3a1d97ac87b064903 | |
| parent | 3dca4c04170bb4c7b26609e55f3f4966d46b681a (diff) | |
Fix minor problems with interface verification and default methods.
Previously we would fail verification on some <clinit> methods when
default methods are enabled and they are not marked as public.
Previously we would also give verifier soft failures when using
interface statics.
Bug: 24618811
Change-Id: I735740b4058bfd71e67bc3fb99e6a8c0c4696b01
| -rw-r--r-- | runtime/verifier/method_verifier.cc | 37 | ||||
| -rw-r--r-- | test/962-iface-static/smali/Displayer.smali | 2 | ||||
| -rw-r--r-- | test/962-iface-static/smali/iface.smali | 2 | ||||
| -rwxr-xr-x | test/964-default-iface-init-generated/util-src/generate_smali.py | 2 |
4 files changed, 26 insertions, 17 deletions
diff --git a/runtime/verifier/method_verifier.cc b/runtime/verifier/method_verifier.cc index e1d4160aac..2db79ab229 100644 --- a/runtime/verifier/method_verifier.cc +++ b/runtime/verifier/method_verifier.cc @@ -665,20 +665,22 @@ bool MethodVerifier::Verify() { // Interfaces may always have static initializers for their fields. If we are running with // default methods enabled we also allow other public, static, non-final methods to have code. // Otherwise that is the only type of method allowed. - if (runtime->AreExperimentalFlagsEnabled(ExperimentalFlags::kDefaultMethods)) { - if (IsInstanceConstructor()) { - Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "interfaces may not have non-static constructor"; - return false; - } else if (method_access_flags_ & kAccFinal) { - Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "interfaces may not have final methods"; - return false; - } else if (!(method_access_flags_ & kAccPublic)) { - Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "interfaces may not have non-public members"; + if (!(IsConstructor() && IsStatic())) { + if (runtime->AreExperimentalFlagsEnabled(ExperimentalFlags::kDefaultMethods)) { + if (IsInstanceConstructor()) { + Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "interfaces may not have non-static constructor"; + return false; + } else if (method_access_flags_ & kAccFinal) { + Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "interfaces may not have final methods"; + return false; + } else if (!(method_access_flags_ & kAccPublic)) { + Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "interfaces may not have non-public members"; + return false; + } + } else { + Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "interface methods must be abstract"; return false; } - } else if (!IsConstructor() || !IsStatic()) { - Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "interface methods must be abstract"; - return false; } } @@ -3662,8 +3664,15 @@ ArtMethod* MethodVerifier::ResolveMethodAndCheckAccess( << PrettyMethod(res_method); return nullptr; } - // Check that interface methods match interface classes. - if (klass->IsInterface() && method_type != METHOD_INTERFACE) { + // Check that interface methods are static or match interface classes. + // We only allow statics if we don't have default methods enabled. + Runtime* runtime = Runtime::Current(); + const bool default_methods_supported = + runtime == nullptr || + runtime->AreExperimentalFlagsEnabled(ExperimentalFlags::kDefaultMethods); + if (klass->IsInterface() && + method_type != METHOD_INTERFACE && + (!default_methods_supported || method_type != METHOD_STATIC)) { Fail(VERIFY_ERROR_CLASS_CHANGE) << "non-interface method " << PrettyMethod(res_method) << " is in an interface class " << PrettyClass(klass); return nullptr; diff --git a/test/962-iface-static/smali/Displayer.smali b/test/962-iface-static/smali/Displayer.smali index 06bec16432..ed4c013d3b 100644 --- a/test/962-iface-static/smali/Displayer.smali +++ b/test/962-iface-static/smali/Displayer.smali @@ -27,7 +27,7 @@ .class public LDisplayer; .super Ljava/lang/Object; -.method public static <clinit>()V +.method static constructor <clinit>()V .locals 3 sget-object v1, Ljava/lang/System;->out:Ljava/io/PrintStream; const-string v0, "init" diff --git a/test/962-iface-static/smali/iface.smali b/test/962-iface-static/smali/iface.smali index 441aae669e..5b9c03ec46 100644 --- a/test/962-iface-static/smali/iface.smali +++ b/test/962-iface-static/smali/iface.smali @@ -27,7 +27,7 @@ .field public final static f:LDisplayer; -.method public static <clinit>()V +.method static constructor <clinit>()V .locals 3 new-instance v1, LDisplayer; invoke-direct {v1}, LDisplayer;-><init>()V diff --git a/test/964-default-iface-init-generated/util-src/generate_smali.py b/test/964-default-iface-init-generated/util-src/generate_smali.py index be2d3ba563..3c138abf26 100755 --- a/test/964-default-iface-init-generated/util-src/generate_smali.py +++ b/test/964-default-iface-init-generated/util-src/generate_smali.py @@ -334,7 +334,7 @@ class TestInterface(mixins.DumpMixin, mixins.Named, mixins.NameComparableMixin, # public static final Displayer field = new Displayer("{tree}"); .field public final static field:LDisplayer; -.method public static constructor <clinit>()V +.method static constructor <clinit>()V .locals 3 const-string v2, "{tree}" new-instance v1, LDisplayer; |