From ef3912cbde210dc0f943652d41c22f413fa46996 Mon Sep 17 00:00:00 2001 From: Sam Blackshear Date: Tue, 2 Feb 2016 16:55:47 -0800 Subject: [PATCH] Adding on-the-fly translation of types during pre-analysis Reviewed By: jeremydubreil Differential Revision: D2880106 fb-gh-sync-id: 0de5fe5 --- infer/src/backend/preanal.ml | 22 +++++++++++++++++++--- infer/src/backend/preanal.mli | 3 ++- infer/src/backend/symExec.ml | 10 ++++------ infer/src/java/jMain.ml | 11 +++++++---- 4 files changed, 32 insertions(+), 14 deletions(-) diff --git a/infer/src/backend/preanal.ml b/infer/src/backend/preanal.ml index d1f44884e..caeae9b13 100644 --- a/infer/src/backend/preanal.ml +++ b/infer/src/backend/preanal.ml @@ -374,7 +374,22 @@ let analyze_and_annotate_proc cfg tenv pname pdesc = Table.reset () (** 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 = (* TODO: handle dynamic dispatch for virtual calls as well *) 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 just pick one target *) 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 Sil.Call (ret_ids, call_exp, args, loc, call_flags')) | 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.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; Cfg.iter_proc_desc cfg (analyze_and_annotate_proc cfg tenv); 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; diff --git a/infer/src/backend/preanal.mli b/infer/src/backend/preanal.mli index bab8f75c0..6e8b845d5 100644 --- a/infer/src/backend/preanal.mli +++ b/infer/src/backend/preanal.mli @@ -11,4 +11,5 @@ (** Preanalysis for eliminating dead local variables *) (** 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 diff --git a/infer/src/backend/symExec.ml b/infer/src/backend/symExec.ml index 4f024d256..548b22b2a 100644 --- a/infer/src/backend/symExec.ml +++ b/infer/src/backend/symExec.ml @@ -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 | None -> pname in let receiver_types_equal pname actual_receiver_typ = - try - let formal_receiver_typ = - 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.typ_equal formal_receiver_typ actual_receiver_typ - with Cannot_convert_string_to_typ _ -> false in + let formal_receiver_typ = + 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.typ_equal formal_receiver_typ actual_receiver_typ in match actuals with | _ 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 *) diff --git a/infer/src/java/jMain.ml b/infer/src/java/jMain.ml index 8d86bcb04..2c25bfaac 100644 --- a/infer/src/java/jMain.ml +++ b/infer/src/java/jMain.ml @@ -59,13 +59,16 @@ let init_global_state source_file = 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 begin 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 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; Cg.store_to_file cg_file cg; Cfg.store_cfg_to_file cfg_file true cfg; @@ -90,7 +93,7 @@ let do_source_file JFrontend.compute_source_icfg never_null_matcher linereader classes program tenv 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 IList.fold_left (fun proc_file_map pdesc -> @@ -111,7 +114,7 @@ let capture_libs never_null_matcher linereader program tenv = let call_graph, cfg = JFrontend.compute_class_icfg 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; end in JBasics.ClassMap.iter (capture_class tenv) (JClasspath.get_classmap program)