From b3de7ff37111361e0d7201f5d5b3fb2bc53456e8 Mon Sep 17 00:00:00 2001 From: Tom Tromey Date: Wed, 30 Jan 2002 22:20:23 +0000 Subject: verify.cc (handle_ret_insn): Check for subroutine merge here... * verify.cc (handle_ret_insn): Check for subroutine merge here... (state::merge): ... not here. (subr_entry_info): New structure. (entry_points): New field. (~_Jv_BytecodeVerifier): Correctly free jsr_ptrs. Free entry_points. From-SVN: r49344 --- libjava/verify.cc | 81 ++++++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 72 insertions(+), 9 deletions(-) (limited to 'libjava/verify.cc') diff --git a/libjava/verify.cc b/libjava/verify.cc index 9100831..1035cda 100644 --- a/libjava/verify.cc +++ b/libjava/verify.cc @@ -56,6 +56,7 @@ private: struct state; struct type; struct subr_info; + struct subr_entry_info; struct linked_utf8; // The current PC. @@ -84,6 +85,11 @@ private: // of all calling `jsr's at at each jsr target. subr_info **jsr_ptrs; + // We keep a linked list of entries which map each `ret' instruction + // to its unique subroutine entry point. We expect that there won't + // be many `ret' instructions, so a linked list is ok. + subr_entry_info *entry_points; + // The current top of the stack, in terms of slots. int stacktop; // The current depth of the stack. This will be larger than @@ -273,6 +279,18 @@ private: subr_info *next; }; + // This is used to keep track of which subroutine entry point + // corresponds to which `ret' instruction. + struct subr_entry_info + { + // PC of the subroutine entry point. + int pc; + // PC of the `ret' instruction. + int ret_pc; + // Link. + subr_entry_info *next; + }; + // The `type' class is used to represent a single type in the // verifier. struct type @@ -886,9 +904,9 @@ private: if (this_type.isinitialized ()) this_type = state_old->this_type; - // Merge subroutine states. *THIS and *STATE_OLD must be in the - // same subroutine. Also, recursive subroutine calls must be - // avoided. + // Merge subroutine states. Here we just keep track of what + // subroutine we think we're in. We only check for a merge + // (which is invalid) when we see a `ret'. if (subroutine == state_old->subroutine) { // Nothing. @@ -898,11 +916,13 @@ private: subroutine = state_old->subroutine; changed = true; } - // If we're handling the result of an unmerged `ret', then we - // can't trust that it has the correct PC setting. So in this - // case we ignore what might otherwise look like a merge error. - else if (! state_old->is_unmerged_ret_state (max_locals)) - verifier->verify_fail ("subroutines merged"); + else + { + // If the subroutines differ, indicate that the state + // changed. This is needed to detect when subroutines have + // merged. + changed = true; + } // Merge stacks. if (state_old->stacktop != stacktop) @@ -1329,6 +1349,24 @@ private: if (csub == 0) verify_fail ("no subroutine"); + // Check to see if we've merged subroutines. + subr_entry_info *entry; + for (entry = entry_points; entry != NULL; entry = entry->next) + { + if (entry->ret_pc == start_PC) + break; + } + if (entry == NULL) + { + entry = (subr_entry_info *) _Jv_Malloc (sizeof (subr_entry_info)); + entry->pc = csub; + entry->ret_pc = start_PC; + entry->next = entry_points; + entry_points = entry; + } + else if (entry->pc != csub) + verify_fail ("subroutines merged"); + for (subr_info *subr = jsr_ptrs[csub]; subr != NULL; subr = subr->next) { // Temporarily modify the current state so it looks like we're @@ -2893,6 +2931,7 @@ public: flags = NULL; jsr_ptrs = NULL; utf8_list = NULL; + entry_points = NULL; } ~_Jv_BytecodeVerifier () @@ -2901,8 +2940,25 @@ public: _Jv_Free (states); if (flags) _Jv_Free (flags); + if (jsr_ptrs) - _Jv_Free (jsr_ptrs); + { + for (int i = 0; i < current_method->code_length; ++i) + { + if (jsr_ptrs[i] != NULL) + { + subr_info *info = jsr_ptrs[i]; + while (info != NULL) + { + subr_info *next = info->next; + _Jv_Free (info); + info = next; + } + } + } + _Jv_Free (jsr_ptrs); + } + while (utf8_list != NULL) { linked_utf8 *n = utf8_list->next; @@ -2910,6 +2966,13 @@ public: _Jv_Free (utf8_list); utf8_list = n; } + + while (entry_points != NULL) + { + subr_entry_info *next = entry_points->next; + _Jv_Free (entry_points); + entry_points = next; + } } }; -- cgit v1.1