Adding on-the-fly translation of types during pre-analysis

Reviewed By: jeremydubreil

Differential Revision: D2880106

fb-gh-sync-id: 0de5fe5
master
Sam Blackshear 9 years ago committed by facebook-github-bot-7
parent 5683fd8413
commit ef3912cbde

@ -374,7 +374,22 @@ let analyze_and_annotate_proc cfg tenv pname pdesc =
Table.reset () Table.reset ()
(** mutate the cfg/cg to add dynamic dispatch handling *) (** mutate the cfg/cg to add dynamic dispatch handling *)
let add_dispatch_calls cfg cg tenv = let add_dispatch_calls cfg cg tenv f_translate_typ_opt =
let pname_translate_types pname =
match f_translate_typ_opt with
| Some f_translate_typ ->
if Procname.is_java pname then
let param_type_strs =
IList.map Procname.java_type_to_string (Procname.java_get_parameters pname) in
let receiver_type_str = Procname.java_get_class pname in
let return_type_str = Procname.java_get_return_type pname in
IList.iter
(fun typ_str -> f_translate_typ tenv typ_str)
(return_type_str :: (receiver_type_str :: param_type_strs))
else
(* TODO: support this for C/CPP/Obj-C *)
()
| None -> () in
let node_add_dispatch_calls caller_pname node = let node_add_dispatch_calls caller_pname node =
(* TODO: handle dynamic dispatch for virtual calls as well *) (* TODO: handle dynamic dispatch for virtual calls as well *)
let call_flags_is_dispatch call_flags = call_flags.Sil.cf_interface in let call_flags_is_dispatch call_flags = call_flags.Sil.cf_interface in
@ -399,6 +414,7 @@ let add_dispatch_calls cfg cg tenv =
(* TODO: do this with all possible targets. for now, it is too slow to do this, so we (* TODO: do this with all possible targets. for now, it is too slow to do this, so we
just pick one target *) just pick one target *)
Cg.add_edge cg caller_pname target_pname; Cg.add_edge cg caller_pname target_pname;
pname_translate_types target_pname;
let call_flags' = { call_flags with Sil.cf_targets = [target_pname]; } in let call_flags' = { call_flags with Sil.cf_targets = [target_pname]; } in
Sil.Call (ret_ids, call_exp, args, loc, call_flags')) Sil.Call (ret_ids, call_exp, args, loc, call_flags'))
| instr -> instr in | instr -> instr in
@ -410,9 +426,9 @@ let add_dispatch_calls cfg cg tenv =
Cfg.Procdesc.iter_nodes (node_add_dispatch_calls pname) pdesc in Cfg.Procdesc.iter_nodes (node_add_dispatch_calls pname) pdesc in
Cfg.iter_proc_desc cfg proc_add_dispach_calls Cfg.iter_proc_desc cfg proc_add_dispach_calls
let doit cfg cg tenv = let doit ?(f_translate_typ=None) cfg cg tenv =
AllPreds.mk_table cfg; AllPreds.mk_table cfg;
Cfg.iter_proc_desc cfg (analyze_and_annotate_proc cfg tenv); Cfg.iter_proc_desc cfg (analyze_and_annotate_proc cfg tenv);
AllPreds.clear_table (); AllPreds.clear_table ();
if !Config.sound_dynamic_dispatch then add_dispatch_calls cfg cg tenv; if !Config.sound_dynamic_dispatch then add_dispatch_calls cfg cg tenv f_translate_typ;

@ -11,4 +11,5 @@
(** Preanalysis for eliminating dead local variables *) (** Preanalysis for eliminating dead local variables *)
(** Perform liveness analysis *) (** Perform liveness analysis *)
val doit : Cfg.cfg -> Cg.t -> Sil.tenv -> unit val doit : ?f_translate_typ:(Sil.tenv -> string -> unit) option -> Cfg.cfg -> Cg.t -> Sil.tenv
-> unit

@ -671,12 +671,10 @@ let resolve_virtual_pname cfg tenv prop actuals pname call_flags : Procname.t =
| Some class_name -> resolve_method tenv class_name pname | Some class_name -> resolve_method tenv class_name pname
| None -> pname in | None -> pname in
let receiver_types_equal pname actual_receiver_typ = let receiver_types_equal pname actual_receiver_typ =
try let formal_receiver_typ =
let formal_receiver_typ = let receiver_typ_str = Procname.java_get_class pname in
let receiver_typ_str = Procname.java_get_class pname in Sil.Tptr (lookup_java_typ_from_string tenv receiver_typ_str, Sil.Pk_pointer) in
Sil.Tptr (lookup_java_typ_from_string tenv receiver_typ_str, Sil.Pk_pointer) in Sil.typ_equal formal_receiver_typ actual_receiver_typ in
Sil.typ_equal formal_receiver_typ actual_receiver_typ
with Cannot_convert_string_to_typ _ -> false in
match actuals with match actuals with
| _ when not (call_flags.Sil.cf_virtual || call_flags.Sil.cf_interface) -> | _ when not (call_flags.Sil.cf_virtual || call_flags.Sil.cf_interface) ->
(* if this is not a virtual or interface call, there's no need for resolution *) (* if this is not a virtual or interface call, there's no need for resolution *)

@ -59,13 +59,16 @@ let init_global_state source_file =
Config.nLOC := nLOC Config.nLOC := nLOC
let store_icfg tenv cg cfg source_file = let store_icfg tenv cg cfg source_file program =
let f_translate_typ tenv typ_str =
let cn = JBasics.make_cn typ_str in
ignore (JTransType.get_class_type program tenv cn) in
let source_dir = DB.source_dir_from_source_file !DB.current_source in let source_dir = DB.source_dir_from_source_file !DB.current_source in
begin begin
let cfg_file = DB.source_dir_get_internal_file source_dir ".cfg" in let cfg_file = DB.source_dir_get_internal_file source_dir ".cfg" in
let cg_file = DB.source_dir_get_internal_file source_dir ".cg" in let cg_file = DB.source_dir_get_internal_file source_dir ".cg" in
Cfg.add_removetemps_instructions cfg; Cfg.add_removetemps_instructions cfg;
Preanal.doit cfg cg tenv; Preanal.doit ~f_translate_typ:(Some f_translate_typ) cfg cg tenv;
Cfg.add_abstraction_instructions cfg; Cfg.add_abstraction_instructions cfg;
Cg.store_to_file cg_file cg; Cg.store_to_file cg_file cg;
Cfg.store_cfg_to_file cfg_file true cfg; Cfg.store_cfg_to_file cfg_file true cfg;
@ -90,7 +93,7 @@ let do_source_file
JFrontend.compute_source_icfg JFrontend.compute_source_icfg
never_null_matcher linereader classes program tenv never_null_matcher linereader classes program tenv
source_basename package_opt in source_basename package_opt in
store_icfg tenv call_graph cfg source_file; store_icfg tenv call_graph cfg source_file program;
if !JConfig.create_harness then if !JConfig.create_harness then
IList.fold_left IList.fold_left
(fun proc_file_map pdesc -> (fun proc_file_map pdesc ->
@ -111,7 +114,7 @@ let capture_libs never_null_matcher linereader program tenv =
let call_graph, cfg = let call_graph, cfg =
JFrontend.compute_class_icfg JFrontend.compute_class_icfg
never_null_matcher linereader program tenv node fake_source_file in never_null_matcher linereader program tenv node fake_source_file in
store_icfg tenv call_graph cfg fake_source_file; store_icfg tenv call_graph cfg fake_source_file program;
JFrontend.cache_classname cn; JFrontend.cache_classname cn;
end in end in
JBasics.ClassMap.iter (capture_class tenv) (JClasspath.get_classmap program) JBasics.ClassMap.iter (capture_class tenv) (JClasspath.get_classmap program)

Loading…
Cancel
Save