Message-Id: <3.0.1.32.19970604114107.00941a70@june.cs.washington.edu>
Date: Wed, 04 Jun 1997 11:41:07 +0100
To: Marianne Mueller <mrm@Eng>, frantz@communities.com
From: Brian Bershad <bershad@cs.washington.edu>
Subject: Re: New(?) bytecode verification weakness
In-Reply-To: <199706032126.OAA22589@puffin.eng.sun.com>
I'm not sure I agree with Marianne's assessment about the danger of this
bug. If the field is final, then everyone (VM, other applets) can assume
that the the field does not change. This would allow all kinds of
optimizations to be performed either at the VM level or the programming
level, which, in the presence of a misbehaving program, might cause problems.
For example, suppose that the final field is some kind of access key. An
untrusting cooperating client can read the token, verify once on its own
that the key is legitimate and allows only the right resources to be
accessed, and then proceed, maintaining some local state that says 'key is
good.' Subsequent to this, a bad applet could change the key so that it
could trojan horse the unsuspecting applet to do something it had not
expected to do.
Final means final. Everyone gets to assume that it's final. If the bad
class had defined the field as non-final, then it would have to export a
different interface to clients, and they would be able to assume a
different sort of contract. But, if final doesn't mean final, then why
have the property at all.
The observation here is simple I think. There is a spec. It is intended to
ensure that progams have certain properties. If we allow code in that
deviates from the spec, then programs can have different (and unexpected)
properties. I can't see any reason why this would be a good thing.
Brian
At 02:26 PM 6/3/97 -0700, Marianne Mueller wrote:
>
>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
>
>