diff --git a/infer/src/java/jFrontend.ml b/infer/src/java/jFrontend.ml index 9f282fbf5..441316421 100644 --- a/infer/src/java/jFrontend.ml +++ b/infer/src/java/jFrontend.ml @@ -22,28 +22,35 @@ let add_edges let pc_nb = Array.length method_body_nodes in let last_pc = pc_nb - 1 in let is_last pc = Int.equal pc last_pc in - let rec get_body_nodes pc = + let rec get_body_nodes_ pc visited = let current_nodes = method_body_nodes.(pc) in match current_nodes with - | JTrans.Skip when (is_last pc) && not (JContext.is_goto_jump context pc) -> - exit_nodes - | JTrans.Skip -> direct_successors pc + | JTrans.Skip when (is_last pc) && not (JContext.is_goto_jump context pc) -> exit_nodes + | JTrans.Skip -> direct_successors pc (Int.Set.add visited pc) | JTrans.Instr node -> [node] | JTrans.Prune (node_true, node_false) -> [node_true; node_false] | JTrans.Loop (join_node, _, _) -> [join_node] - and direct_successors pc = + and direct_successors pc visited = if is_last pc && not (JContext.is_goto_jump context pc) then exit_nodes else match JContext.get_goto_jump context pc with - | JContext.Next -> get_body_nodes (pc + 1) + | JContext.Next -> + let next_pc = pc + 1 in + if Int.Set.mem visited next_pc + then [] + else get_body_nodes_ next_pc visited + | JContext.Jump goto_pc when Int.Set.mem visited goto_pc -> + [] (* loop in goto *) | JContext.Jump goto_pc -> - if Int.equal pc goto_pc then [] (* loop in goto *) - else get_body_nodes goto_pc - | JContext.Exit -> exit_nodes in + get_body_nodes_ goto_pc visited + | JContext.Exit -> + exit_nodes in + let get_body_nodes pc = + get_body_nodes_ pc Int.Set.empty in let get_succ_nodes node pc = match JContext.get_if_jump context node with - | None -> direct_successors pc + | None -> direct_successors pc Int.Set.empty | Some jump_pc -> get_body_nodes jump_pc in let get_exn_nodes = if super_call then (fun _ -> exit_nodes) @@ -64,7 +71,7 @@ let add_edges connect node_false pc in let first_nodes = (* deals with the case of an empty array *) - direct_successors (-1) in + direct_successors (-1) Int.Set.empty in (* the exceptions edges here are going directly to the exit node *) Procdesc.node_set_succs_exn context.procdesc start_node first_nodes exit_nodes;