This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Java bytecode verifier patch


This patch fixes a couple of bugs in the Java bytecode verifier which
cause programs to be incorrectly rejected.

Andrew.


1999-06-21  Andrew Haley  <aph@cygnus.com>

        * except.c (find_handler_in_range): The upper limit for exception
        ranges is exclusive, not inclusive: (start <= pc < end).  
        (link_handler): find child pointer which points to outer by
        searching sibling list: previous code incorrectly assumed that
        outer->outer->first_child must point to outer.
        * verify.c (verify_jvm_instructions): FIXME added to code for
        `athrow'.
        (verify_jvm_instructions): Do not assume that the last block
        processed in a subroutine is a block which ends with a `ret'
        instruction.  With some control flows it is possible that the last
        block ends with an `athrow'.

Index: gcc/java/verify.c
===================================================================
RCS file: /cvs/egcs/egcs/gcc/java/verify.c,v
retrieving revision 1.18
diff -c -2 -p -r1.18 verify.c
*** gcc/java/verify.c	1999/05/19 11:30:21	1.18
--- gcc/java/verify.c	1999/06/21 16:14:46
*************** verify_jvm_instructions (jcf, byte_ops, 
*** 1000,1003 ****
--- 1000,1004 ----
  
  	case OPCODE_athrow:
+ 	  // FIXME: athrow also empties the stack.
  	  pop_type (throwable_type_node);
  	  INVALIDATE_PC;
*************** verify_jvm_instructions (jcf, byte_ops, 
*** 1198,1201 ****
--- 1199,1212 ----
  		}
  
+ 
+             }
+           break;
+         case OPCODE_jsr_w:        
+         case OPCODE_ret_w:
+         default:
+           error ("unknown opcode %d@pc=%d during verification", op_code, PC-1);
+           return 0;
+         }
+ 
  	      /* Check if there are any more pending blocks in this subroutine.
  		 Because we push pending blocks in a last-in-first-out order,
*************** verify_jvm_instructions (jcf, byte_ops, 
*** 1204,1216 ****
  		 then we are done if the top of the pending_blocks stack is
  		 not in a subroutine, or it is in our caller. */
  	      if (pending_blocks == NULL_TREE
  		  || ! LABEL_IN_SUBR (pending_blocks)
  		  || LABEL_SUBR_START (pending_blocks) == caller)
  		{
! 		  /* Since we are done with this subroutine (i.e. this is the
! 		     last ret from it), set up the (so far known) return
! 		     address as pending - with the merged type state. */
! 		  tmp = LABEL_RETURN_LABELS (current_subr);
! 		  current_subr = caller;
  		  for ( ; tmp != NULL_TREE;  tmp = TREE_CHAIN (tmp))
  		    {
--- 1215,1242 ----
  		 then we are done if the top of the pending_blocks stack is
  		 not in a subroutine, or it is in our caller. */
+       if (current_subr 
+ 	  && PC == INVALID_PC)
+ 	{
+ 	  tree caller = LABEL_SUBR_CONTEXT (current_subr);
+ 
  	      if (pending_blocks == NULL_TREE
  		  || ! LABEL_IN_SUBR (pending_blocks)
  		  || LABEL_SUBR_START (pending_blocks) == caller)
+ 		{
+ 	      int size = DECL_MAX_LOCALS(current_function_decl)+stack_pointer;
+ 	      tree ret_map = LABEL_RETURN_TYPE_STATE (current_subr);
+ 	      tmp = LABEL_RETURN_LABELS (current_subr);
+ 	      
+ 	      /* FIXME: If we exit a subroutine via a throw, we might
+ 		 have returned to an earlier caller.  Obviously a
+ 		 "ret" can only return one level, but a throw may
+ 		 return many levels.*/
+ 	      current_subr = caller;
+ 
+ 	      if (RETURN_MAP_ADJUSTED (ret_map))
  		{
! 		  /* Since we are done with this subroutine , set up
! 		     the (so far known) return address as pending -
! 		     with the merged type state. */
  		  for ( ; tmp != NULL_TREE;  tmp = TREE_CHAIN (tmp))
  		    {
*************** verify_jvm_instructions (jcf, byte_ops, 
*** 1242,1251 ****
  		}
  	    }
- 	  break;
- 	case OPCODE_jsr_w:	  
- 	case OPCODE_ret_w:
-         default:
- 	  error ("unknown opcode %d@pc=%d during verification", op_code, PC-1);
- 	  return 0;
  	}
  
--- 1268,1271 ----
Index: gcc/java/except.c
===================================================================
RCS file: /cvs/egcs/egcs/gcc/java/except.c,v
retrieving revision 1.10
diff -c -2 -p -r1.10 except.c
*** gcc/java/except.c	1999/06/02 11:00:43	1.10
--- gcc/java/except.c	1999/06/21 16:14:46
*************** find_handler_in_range (pc, range, child)
*** 73,77 ****
        if (pc < child->start_pc)
  	break;
!       if (pc <= child->end_pc)
  	return find_handler_in_range (pc, child, child->first_child);
      }
--- 73,77 ----
        if (pc < child->start_pc)
  	break;
!       if (pc < child->end_pc)
  	return find_handler_in_range (pc, child, child->first_child);
      }
*************** link_handler (range, outer)
*** 130,134 ****
        range->next_sibling = NULL;
        range->first_child = outer;
!       outer->outer->first_child = range;
        outer->outer = range;
        return;
--- 130,139 ----
        range->next_sibling = NULL;
        range->first_child = outer;
!       {
! 	struct eh_range **pr = &(outer->outer->first_child);
! 	while (*pr != outer)
! 	  pr = &(*pr)->next_sibling;
! 	*pr = range;
!       }
        outer->outer = range;
        return;


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]