This is the mail archive of the
java-patches@gcc.gnu.org
mailing list for the Java project.
Patch: FYI: verifier bug fixes
- From: Tom Tromey <tromey at redhat dot com>
- To: Java Patch List <java-patches at gcc dot gnu dot org>
- Date: 26 Nov 2002 22:45:04 -0700
- Subject: Patch: FYI: verifier bug fixes
- Reply-to: tromey at redhat dot com
I'm checking this in.
This fixes a verifier bug I read about on the main list last night.
The bug was that we could call <init> on a null object.
It also fixes another bug I noticed while fixing the first bug. This
bug is that we allowed various operations to be performed on
uninitialized references, in some situations.
Tests for both of these bugs are now in Mauve.
This passes the libgcj test suite without regressions.
Tom
Index: libjava/ChangeLog
from Tom Tromey <tromey@redhat.com>
* verify.cc (pop_init_ref): New method.
(verify_instructions_0) [op_iaload, op_laload, op_faload,
op_daload, op_aaload, op_baload, op_caload, op_saload, op_iastore,
op_lastore, op_fastore, op_dastore, op_aastore, op_bastore,
op_castore, op_sastore, op_areturn, op_arraylength, op_checkcast,
op_instanceof, op_monitorenter, op_monitorexit]: Use it.
(verify_instructions_0) [op_invokevirtual, op_invokespecial,
op_invokestatic, op_invokeinterface]: Use pop_init_ref. Don't
let `this' argument be uninitialized. Don't let `null' be passed
as `this' to construtor.
Index: libjava/verify.cc
===================================================================
RCS file: /cvs/gcc/gcc/libjava/verify.cc,v
retrieving revision 1.44
diff -u -r1.44 verify.cc
--- libjava/verify.cc 26 Nov 2002 07:15:53 -0000 1.44
+++ libjava/verify.cc 27 Nov 2002 05:37:40 -0000
@@ -458,7 +458,8 @@
if (key < reference_type || k.key < reference_type)
return key == k.key;
- // The `null' type is convertible to any reference type.
+ // The `null' type is convertible to any initialized reference
+ // type.
if (key == null_type || k.key == null_type)
return true;
@@ -1137,6 +1138,19 @@
return t;
}
+ // Pop a reference which is guaranteed to be initialized. MATCH
+ // doesn't have to be a reference type; in this case this acts like
+ // pop_type.
+ type pop_init_ref (type match)
+ {
+ type t = pop_raw ();
+ if (t.isreference () && ! t.isinitialized ())
+ verify_fail ("initialized reference required");
+ else if (! match.compatible (t, this))
+ verify_fail ("incompatible type on stack");
+ return t;
+ }
+
// Pop a reference type or a return address.
type pop_ref_or_return ()
{
@@ -2300,42 +2314,42 @@
break;
case op_iaload:
pop_type (int_type);
- push_type (require_array_type (pop_type (reference_type),
+ push_type (require_array_type (pop_init_ref (reference_type),
int_type));
break;
case op_laload:
pop_type (int_type);
- push_type (require_array_type (pop_type (reference_type),
+ push_type (require_array_type (pop_init_ref (reference_type),
long_type));
break;
case op_faload:
pop_type (int_type);
- push_type (require_array_type (pop_type (reference_type),
+ push_type (require_array_type (pop_init_ref (reference_type),
float_type));
break;
case op_daload:
pop_type (int_type);
- push_type (require_array_type (pop_type (reference_type),
+ push_type (require_array_type (pop_init_ref (reference_type),
double_type));
break;
case op_aaload:
pop_type (int_type);
- push_type (require_array_type (pop_type (reference_type),
+ push_type (require_array_type (pop_init_ref (reference_type),
reference_type));
break;
case op_baload:
pop_type (int_type);
- require_array_type (pop_type (reference_type), byte_type);
+ require_array_type (pop_init_ref (reference_type), byte_type);
push_type (int_type);
break;
case op_caload:
pop_type (int_type);
- require_array_type (pop_type (reference_type), char_type);
+ require_array_type (pop_init_ref (reference_type), char_type);
push_type (int_type);
break;
case op_saload:
pop_type (int_type);
- require_array_type (pop_type (reference_type), short_type);
+ require_array_type (pop_init_ref (reference_type), short_type);
push_type (int_type);
break;
case op_istore:
@@ -2386,42 +2400,42 @@
case op_iastore:
pop_type (int_type);
pop_type (int_type);
- require_array_type (pop_type (reference_type), int_type);
+ require_array_type (pop_init_ref (reference_type), int_type);
break;
case op_lastore:
pop_type (long_type);
pop_type (int_type);
- require_array_type (pop_type (reference_type), long_type);
+ require_array_type (pop_init_ref (reference_type), long_type);
break;
case op_fastore:
pop_type (float_type);
pop_type (int_type);
- require_array_type (pop_type (reference_type), float_type);
+ require_array_type (pop_init_ref (reference_type), float_type);
break;
case op_dastore:
pop_type (double_type);
pop_type (int_type);
- require_array_type (pop_type (reference_type), double_type);
+ require_array_type (pop_init_ref (reference_type), double_type);
break;
case op_aastore:
pop_type (reference_type);
pop_type (int_type);
- require_array_type (pop_type (reference_type), reference_type);
+ require_array_type (pop_init_ref (reference_type), reference_type);
break;
case op_bastore:
pop_type (int_type);
pop_type (int_type);
- require_array_type (pop_type (reference_type), byte_type);
+ require_array_type (pop_init_ref (reference_type), byte_type);
break;
case op_castore:
pop_type (int_type);
pop_type (int_type);
- require_array_type (pop_type (reference_type), char_type);
+ require_array_type (pop_init_ref (reference_type), char_type);
break;
case op_sastore:
pop_type (int_type);
pop_type (int_type);
- require_array_type (pop_type (reference_type), short_type);
+ require_array_type (pop_init_ref (reference_type), short_type);
break;
case op_pop:
pop32 ();
@@ -2759,7 +2773,7 @@
invalidate_pc ();
break;
case op_areturn:
- check_return_type (pop_type (reference_type));
+ check_return_type (pop_init_ref (reference_type));
invalidate_pc ();
break;
case op_return:
@@ -2841,7 +2855,7 @@
// This is only used for verifying the byte for
// invokeinterface.
nargs -= arg_types[i].depth ();
- pop_type (arg_types[i]);
+ pop_init_ref (arg_types[i]);
}
if (opcode == op_invokeinterface
@@ -2858,7 +2872,15 @@
}
type raw = pop_raw ();
bool ok = false;
- if (t.compatible (raw, this))
+ if (! is_init && ! raw.isinitialized ())
+ {
+ // This is a failure.
+ }
+ else if (is_init && raw.isnull ())
+ {
+ // Another failure.
+ }
+ else if (t.compatible (raw, this))
{
ok = true;
}
@@ -2914,7 +2936,7 @@
break;
case op_arraylength:
{
- type t = pop_type (reference_type);
+ type t = pop_init_ref (reference_type);
if (! t.isarray () && ! t.isnull ())
verify_fail ("array type expected");
push_type (int_type);
@@ -2925,19 +2947,19 @@
invalidate_pc ();
break;
case op_checkcast:
- pop_type (reference_type);
+ pop_init_ref (reference_type);
push_type (check_class_constant (get_ushort ()));
break;
case op_instanceof:
- pop_type (reference_type);
+ pop_init_ref (reference_type);
check_class_constant (get_ushort ());
push_type (int_type);
break;
case op_monitorenter:
- pop_type (reference_type);
+ pop_init_ref (reference_type);
break;
case op_monitorexit:
- pop_type (reference_type);
+ pop_init_ref (reference_type);
break;
case op_wide:
{
@@ -2971,7 +2993,7 @@
set_variable (get_ushort (), pop_type (double_type));
break;
case op_astore:
- set_variable (get_ushort (), pop_type (reference_type));
+ set_variable (get_ushort (), pop_init_ref (reference_type));
break;
case op_ret:
handle_ret_insn (get_short ());