Yes, I agree with Ondrej. Take a look at the example I have
attached to this message. There are four classes A,B,C and Test as
in your example,
I wrote a little Java program, compiled
it to class files, then produced Jimple using Soot, edited the Jimple to put
the private in class B and changed the signature of the virtualinvoke in
class Test (see below) and then used Soot to produce class files from
the Jimple.
I also decompiled the new class files (files in dava/src). This gives
you a source code look at what I have. Note that
the decompiled source will not recompile because of the private f in
class B.
However, you can run the class file Test.
Try, java -verify Test
and it will say that it is running the method in class A.
Here is the jimple for Test.java,
/*****************************************
public class Test extends java.lang.Object
{
public void <init>()
{
Test r0;
r0 := @this: Test;
specialinvoke r0.<java.lang.Object: void <init>()>();
return;
}
public static void main(java.lang.String[] )
{
java.lang.String[] r0;
C $r1, r2;
r0 := @parameter0: java.lang.String[];
$r1 = new C;
specialinvoke $r1.<C: void <init>()>();
r2 = $r1;
virtualinvoke r2.<A: void f()>(); <---------------
return;
}
}
*******************************************
Look at the statement marked by the arrow. This must use the
signature A in the call to f. If either B or C is used, then
the bytecode fails when run with the verifier (and it writes out
that it is running f in B if you turn the verifier off).
Cheers, Laurie
+-------------------------------------------------------------+
| Laurie Hendren, Professor, School of Computer Science |
| McGill University |
| 318 McConnell Engineering Building tel: (514) 398-7391 |
| 3480 University Street fax: (514) 398-3883 |
| Montreal, Quebec H3A 2A7 hendren@cs.mcgill.ca |
| CANADA http://www.sable.mcgill.ca/~hendren |
+-------------------------------------------------------------+
On Thu, 6 Mar 2003, Ondrej LHOTAK wrote:
The lookup code implemented in Soot follows the description given in the
Java Virtual Machine Specification, under invokevirtual:
http://java.sun.com/docs/books/vmspec/2nd-edition/html/Instructions2.doc6.html#invokevirtual
According to this description, for the example you gave, the A.f() that
Soot returns would indeed be the correct method to invoke. Contrary to
your claim, it is *not* true that C cannot access any f(), neither from
A nor B.
If you still think I have misunderstood the specification, please let me
know.
Ondrej
On Thu, Mar 06, 2003 at 11:17:21AM -0500, Weilei Zhang wrote:
The following is from the method resolveConcreteDispatch in Hierarchy.java.
public SootMethod resolveConcreteDispatch(SootClass concreteType, SootMethod m)
{
..........
while (it.hasNext())
{
SootClass c = (SootClass)it.next();
if (c.declaresMethod(methodSig)
&& isVisible( c, m )
) {
return c.getMethod(methodSig);
}
}
......
}
I think the loop should be terminated once we find a SootClass c s.t. (c.declaresMethod(methodSig)&& ! isVisible( c, m )).
The reason is as follows: think of a Class A ,which has public method f(), Class B which extends A and has a redefined private method f(), Class C extends B and doesn't redefine method f(). Then the instance of C can't access any f(), either in A() or in B(). But in your code, A.f() will be returned.
However, the case I mentioned can't appear in normally compiled java code because B can't override f() in A with weaker access privileges. But maybe it will appear in maliciously/purposefully made bytecode.
As a conclusion, there is no problem in general cases, but there is a mistake semantically, IMHO.
Regards
-Weilei