1 # Test that the verifier does not stash methods incorrectly because they are being invoked with 2 # the wrong opcode. 3 # 4 # When using invoke-interface on a method id that is not from an interface class, we should throw 5 # an IncompatibleClassChangeError. FindInterfaceMethod assumes that the given type is an interface, 6 # so we can construct a class hierarchy that would have a surprising result: 7 # 8 # interface I { 9 # void a(); 10 # } 11 # 12 # class B implements I { 13 # // miranda method for a, or a implemented. 14 # } 15 # 16 # class C extends B { 17 # } 18 # 19 # Then calling invoke-interface C.a() will go wrong if there is no explicit check: a can't be found 20 # in C, but in the interface table, so we will find an interface method and pass ICCE checks. 21 # 22 # If we do this before a correct invoke-virtual C.a(), we poison the dex cache with an incorrect 23 # method. In this test, this is done in A (A < B, so processed first). The "real" call is in B. 24 25 .class public LB21869691A; 26 27 .super Ljava/lang/Object; 28 29 .method public constructor <init>()V 30 .registers 1 31 invoke-direct {p0}, Ljava/lang/Object;-><init>()V 32 return-void 33 .end method 34 35 .method public run()V 36 .registers 3 37 new-instance v0, LB21869691C; 38 invoke-direct {v0}, LB21869691C;-><init>()V 39 invoke-virtual {v2, v0}, LB21869691A;->callinf(LB21869691C;)V 40 return-void 41 .end method 42 43 .method public callinf(LB21869691C;)V 44 .registers 2 45 invoke-interface {p1}, LB21869691C;->a()V 46 return-void 47 .end method 48