[Eradicate] Fix issue where direct throw instructions were not handled like method calls that trow exceptions.

master
Cristiano Calcagno 10 years ago
parent 2365e6244d
commit a94fab55e8

@ -54,6 +54,8 @@ module Node = struct
let exn_handler_kind = Stmt_node "exception handler" let exn_handler_kind = Stmt_node "exception handler"
let exn_sink_kind = Stmt_node "exceptions sink" let exn_sink_kind = Stmt_node "exceptions sink"
let throw_kind = Stmt_node "throw"
type cfg = (** data type for the control flow graph *) type cfg = (** data type for the control flow graph *)
{ node_id : int ref; { node_id : int ref;

@ -145,6 +145,9 @@ module Node : sig
(** kind of Stmt_node for an exceptions sink. *) (** kind of Stmt_node for an exceptions sink. *)
val exn_sink_kind : nodekind val exn_sink_kind : nodekind
(** kind of Stmt_node for a throw instruction. *)
val throw_kind : nodekind
(** Append the instructions and temporaries to the list of instructions to execute *) (** Append the instructions and temporaries to the list of instructions to execute *)
val append_instrs_temps : t -> Sil.instr list -> Ident.t list -> unit val append_instrs_temps : t -> Sil.instr list -> Ident.t list -> unit

@ -938,13 +938,19 @@ let typecheck_node
let typestates_exn = ref [] in let typestates_exn = ref [] in
let handle_exceptions typestate instr = match instr with let handle_exceptions typestate instr = match instr with
| Sil.Call (_, Sil.Const (Sil.Cfun callee_pname), _, _, _) -> | Sil.Call (_, Sil.Const (Sil.Cfun callee_pname), _, _, _) ->
(* check if the call might throw an exception *)
let exceptions = let exceptions =
match get_proc_desc callee_pname with match get_proc_desc callee_pname with
| Some callee_pdesc -> | Some callee_pdesc ->
(Specs.proc_get_attributes callee_pname callee_pdesc).Sil.exceptions (Specs.proc_get_attributes callee_pname callee_pdesc).Sil.exceptions
| None -> [] in | None -> [] in
if exceptions <> [] then if exceptions <> [] then
typestates_exn := typestate :: !typestates_exn; typestates_exn := typestate :: !typestates_exn
| Sil.Set (Sil.Lvar pv, _, _, _) when
Sil.pvar_is_return pv &&
Cfg.Node.get_kind node = Cfg.Node.throw_kind ->
(* throw instruction *)
typestates_exn := typestate :: !typestates_exn
| _ -> () in | _ -> () in
let canonical_node = find_canonical_duplicate node in let canonical_node = find_canonical_duplicate node in

@ -936,11 +936,10 @@ let rec instruction context pc instr : translation =
else else
Prune (prune_node_true, prune_node_false) Prune (prune_node_true, prune_node_false)
| JBir.Throw expr -> | JBir.Throw expr ->
let node_kind = Cfg.Node.Stmt_node "throw" in
let (ids, instrs, sil_expr) = expression context pc expr in let (ids, instrs, sil_expr) = expression context pc expr in
let sil_exn = Sil.Const (Sil.Cexn sil_expr) in let sil_exn = Sil.Const (Sil.Cexn sil_expr) in
let sil_instr = Sil.Set (Sil.Lvar ret_var, ret_type, sil_exn, loc) in let sil_instr = Sil.Set (Sil.Lvar ret_var, ret_type, sil_exn, loc) in
let node = create_node node_kind ids (instrs @ [sil_instr]) in let node = create_node Cfg.Node.throw_kind ids (instrs @ [sil_instr]) in
JContext.add_goto_jump context pc JContext.Exit; JContext.add_goto_jump context pc JContext.Exit;
Instr node Instr node
| JBir.New (var, cn, constr_type_list, constr_arg_list) -> | JBir.New (var, cn, constr_type_list, constr_arg_list) ->

@ -88,4 +88,27 @@ public class ReturnNotNullable {
String testOptional(Optional<String> os) { String testOptional(Optional<String> os) {
return os.orNull(); return os.orNull();
} }
class E extends Exception {
}
String return_null_in_catch() {
try {
throw new E();
} catch (E e) {
return null;
}
}
String return_null_in_catch_after_throw() {
try {
try {
throw new E();
} catch (E e) {
throw e;
}
} catch (E e) {
return null;
}
}
} }

@ -49,13 +49,21 @@ public class ReturnNotNullableTest {
throws IOException, InterruptedException, InferException { throws IOException, InterruptedException, InferException {
String[] nullableMethods = {"returnNull", "returnNullable"}; String[] nullableMethods = {
"returnNull",
"returnNullable",
"return_null_in_catch",
"return_null_in_catch_after_throw",
};
List<ErrorPattern> errorPatterns = createPatterns( List<ErrorPattern> errorPatterns = createPatterns(
RETURN_NOT_NULLABLE, RETURN_NOT_NULLABLE,
SOURCE_FILE, SOURCE_FILE,
nullableMethods); nullableMethods);
String[] redundantMethods = {"redundantEq", "redundantNeq"}; String[] redundantMethods = {
"redundantEq",
"redundantNeq",
};
errorPatterns.addAll( errorPatterns.addAll(
createPatterns( createPatterns(
CONDITION_REDUNDANT_NONNULL, CONDITION_REDUNDANT_NONNULL,

Loading…
Cancel
Save