From fc66129b478d49f493b8262f81f8813a5f41459e Mon Sep 17 00:00:00 2001 From: David Brazdil Date: Wed, 14 Mar 2018 13:57:27 +0000 Subject: Warn on overriding of hidden methods We could prevent apps from overriding hidden methods in the same manner they cannot override a package-private method - by creating a separate vtable entry for the child method. For now, start by printing a warning when a hidden method is being overridden but do not change the semantics. Bug: 64382372 Test: art/test.py -r -t 674-hiddenapi Change-Id: I9d5bfa6b833a4c0f5aaffa5f82dbe9b1e1f03f1f --- test/674-hiddenapi/src-ex/ChildClass.java | 34 +++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) (limited to 'test/674-hiddenapi/src-ex/ChildClass.java') diff --git a/test/674-hiddenapi/src-ex/ChildClass.java b/test/674-hiddenapi/src-ex/ChildClass.java index 582e907ca3..8cd237ab6f 100644 --- a/test/674-hiddenapi/src-ex/ChildClass.java +++ b/test/674-hiddenapi/src-ex/ChildClass.java @@ -123,6 +123,9 @@ public class ChildClass { // Check whether one can use an interface default method. String name = "method" + visibility.name() + "Default" + hiddenness.name(); checkMethod(ParentInterface.class, name, /*isStatic*/ false, visibility, expected); + + // Check whether one can override this method. + checkOverriding(suffix, isStatic, visibility, expected); } // Test whether static linking succeeds. @@ -403,6 +406,37 @@ public class ChildClass { } } + private static void checkOverriding(String suffix, + boolean isStatic, + Visibility visibility, + Behaviour behaviour) throws Exception { + if (isStatic || visibility == Visibility.Private) { + // Does not make sense to override a static or private method. + return; + } + + // The classes are in the same package, but will be able to access each + // other only if loaded with the same class loader, here the boot class loader. + boolean canAccess = (visibility != Visibility.Package) || (isParentInBoot && isChildInBoot); + boolean setsWarning = false; // warnings may be set during vtable linking + + String methodName = "callMethod" + visibility.name() + suffix; + + // Force the test class to link its vtable, which may cause warnings, before + // the actual test. + new OverrideClass().methodPublicWhitelist(); + + clearWarning(); + if (Linking.canOverride(methodName) != canAccess) { + throw new RuntimeException("Expected to " + (canAccess ? "" : "not ") + + "be able to override " + methodName + "." + + "isParentInBoot = " + isParentInBoot + ", " + "isChildInBoot = " + isChildInBoot); + } + if (canAccess && hasPendingWarning() != setsWarning) { + throwWarningException(ParentClass.class, methodName, false, "static linking", setsWarning); + } + } + private static void throwDiscoveryException(Class klass, String name, boolean isField, String fn, boolean canAccess) { throw new RuntimeException("Expected " + (isField ? "field " : "method ") + klass.getName() + -- cgit v1.2.3-59-g8ed1b