48 lines
		
	
	
		
			1.4 KiB
		
	
	
	
		
			Smali
		
	
	
	
			
		
		
	
	
			48 lines
		
	
	
		
			1.4 KiB
		
	
	
	
		
			Smali
		
	
	
	
| # Test that the verifier does not stash methods incorrectly because they are being invoked with
 | |
| # the wrong opcode.
 | |
| #
 | |
| # When using invoke-interface on a method id that is not from an interface class, we should throw
 | |
| # an IncompatibleClassChangeError. FindInterfaceMethod assumes that the given type is an interface,
 | |
| # so we can construct a class hierarchy that would have a surprising result:
 | |
| #
 | |
| #   interface I {
 | |
| #     void a();
 | |
| #   }
 | |
| #
 | |
| #   class B implements I {
 | |
| #      // miranda method for a, or a implemented.
 | |
| #   }
 | |
| #
 | |
| #   class C extends B {
 | |
| #   }
 | |
| #
 | |
| # Then calling invoke-interface C.a() will go wrong if there is no explicit check: a can't be found
 | |
| # in C, but in the interface table, so we will find an interface method and pass ICCE checks.
 | |
| #
 | |
| # If we do this before a correct invoke-virtual C.a(), we poison the dex cache with an incorrect
 | |
| # method. In this test, this is done in A (A < B, so processed first). The "real" call is in B.
 | |
| 
 | |
| .class public LB21869691A;
 | |
| 
 | |
| .super Ljava/lang/Object;
 | |
| 
 | |
| .method public constructor <init>()V
 | |
|     .registers 1
 | |
|     invoke-direct {p0}, Ljava/lang/Object;-><init>()V
 | |
|     return-void
 | |
| .end method
 | |
| 
 | |
| .method public run()V
 | |
|   .registers 3
 | |
|   new-instance v0, LB21869691C;
 | |
|   invoke-direct {v0}, LB21869691C;-><init>()V
 | |
|   invoke-virtual {v2, v0}, LB21869691A;->callinf(LB21869691C;)V
 | |
|   return-void
 | |
| .end method
 | |
| 
 | |
| .method public callinf(LB21869691C;)V
 | |
|   .registers 2
 | |
|   invoke-interface {p1}, LB21869691C;->a()V
 | |
|   return-void
 | |
| .end method
 |