SUppose we have following definitions:
public class Test {
public static void main(String[] args) {
System.out.println("------MAIN METHOD------");
A a = new B();
a.a = 3;
System.out.println(a.a);
}
}
public class A {
int a;
public void g(){
System.out.println(a);
}
}
public class B extends A {}
Now, suppose we build the above and then modify B to be
public class B {}
and rebuild JUST B. When we turn the verifier off, the method prints 3! I understand that the verifier does not catch this, reslution checks in A that there s a field a, which is the case... But B does not have allocated space for integer field a! Where does it write it to then?
The java objects in memory are padded and aligned to be at least 16 bytes long, so in a class containing only an int field there is some unused space. If you add some more fields to A you would probably overwrite the storage space of other objects, but that might also not result in an immediate crash, especially in such a short application that immediately exits.
You could have some more fun by declaring the classes like this:
public class A {
int[] a = new int[1];
}
public class B {
int a = 0x01020304;
}
public class Test {
public static void main(String[] args) {
A a = new B();
a.a[0] = 3;
System.out.println(a.a[0]);
}
}
The result of executing this code via java -Xverify:none Test
should result in a JVM error like the following, but in principle it should let you write anywhere into the memory of the java process:
------MAIN METHOD------
#
# A fatal error has been detected by the Java Runtime Environment:
#
# SIGSEGV (0xb) at pc=0x00007f9147d69532, pid=14785, tid=140262017775360
#
# JRE version: 6.0_26-b03
# Java VM: Java HotSpot(TM) 64-Bit Server VM (20.1-b02 mixed mode linux-amd64 compressed oops)
# Problematic frame:
# j Test.main([Ljava/lang/String;)V+17