Date: Tue, 3 Jun 1997 14:26:00 -0700
Message-Id: <199706032126.OAA22589@puffin.eng.sun.com>
From: Marianne Mueller <mrm@Eng>
To: frantz@communities.com
Subject: Re: New(?) bytecode verification weakness
Hi Bill,
(Actually since you're about two blocks away, we should meet for
coffee at Starbuck's!)
Anyway, this is a known feature or a known bug, depending on many
interesting debates that people have about how the Java keyword
"final" is defined and enforced.
Your example shows that a class is able to assign to its own final
variable more than once. (at the bytecode level)
The compiler performs checks to make sure that a final field is
assigned to at most once, but, the VM doesn't perform such checks.
I don't feel this is a security hole, since if a malicious class can
launch an attack by assigning to one of its own final fields, what's
preventing the same class file from declaring the field as non-final
in the first place?
We do not allow a class to modify final fields in other classes.
This does lead to the interesting discussion that the Princeton people
have raised, about how best to define the distribution layer for Java.
Marianne
p.s. Here's my version of your test, and also the jasm version of the
bytecode. We have jasm and jdis, a couple interesting tools. jdis
takes as input a .class file and produces a .jasm file. jasm takes a
.jasm file and produces a .class file.
--import examples.FinalTest;
public class Test { public static void main(String[] args) {
System.out.println("foo = " + FinalTest.foo); FinalTest.putFoo(2); System.out.println("foo = " + FinalTest.foo); } }
package examples;
public super class FinalTest { // Compiled from FinalTest.java // Compiler version 3.45;
final public static Field foo:"I";
public static Method putFoo:"(I)V" stack 1 locals 1 { iload_0; putstatic Field foo:"I"; return; }
public Method <init>:"()V" stack 1 locals 1 { aload_0; invokespecial Method java/lang/Object.<init>:"()V"; return; }
static Method <clinit>:"()V" stack 1 locals 0 { iconst_1; putstatic Field foo:"I"; return; }
} // end Class FinalTest