From 52ed8868864d6a239b1fe8d24345b83d6311c212 Mon Sep 17 00:00:00 2001 From: Sam Blackshear Date: Tue, 9 May 2017 10:17:37 -0700 Subject: [PATCH] [quandary] log error to summary instead of pdesc Summary: Stops Quandary errors from getting dropped on the floor when it runs alongside the other checkers. Reviewed By: jeremydubreil Differential Revision: D5010801 fbshipit-source-id: 2847f61 --- infer/src/backend/specs.ml | 9 +++++++++ infer/src/backend/specs.mli | 3 +++ infer/src/quandary/TaintAnalysis.ml | 31 +++++++++++++++-------------- infer/src/unit/TaintTests.ml | 2 +- 4 files changed, 29 insertions(+), 16 deletions(-) diff --git a/infer/src/backend/specs.ml b/infer/src/backend/specs.ml index 0050b61a3..8f628811e 100644 --- a/infer/src/backend/specs.ml +++ b/infer/src/backend/specs.ml @@ -712,6 +712,15 @@ let init_summary Typ.Procname.Hash.replace spec_tbl proc_attributes.ProcAttributes.proc_name summary; summary +let dummy = + init_summary ( + [], + ProcAttributes.proc_flags_empty (), + [], + ProcAttributes.default Typ.Procname.empty_block Config.Java, + None + ) + (** Reset a summary rebuilding the dependents and preserving the proc attributes if present. *) let reset_summary proc_name attributes_opt proc_desc_option = let proc_attributes = match attributes_opt with diff --git a/infer/src/backend/specs.mli b/infer/src/backend/specs.mli index 45a4edbed..faf8b6e30 100644 --- a/infer/src/backend/specs.mli +++ b/infer/src/backend/specs.mli @@ -154,6 +154,9 @@ type summary = { proc_desc_option : Procdesc.t option; } +(** dummy summary for testing *) +val dummy : summary + (** Add the summary to the table for the given function *) val add_summary : Typ.Procname.t -> summary -> unit diff --git a/infer/src/quandary/TaintAnalysis.ml b/infer/src/quandary/TaintAnalysis.ml index 800a7a785..aa97e6188 100644 --- a/infer/src/quandary/TaintAnalysis.ml +++ b/infer/src/quandary/TaintAnalysis.ml @@ -50,14 +50,15 @@ module Make (TaintSpecification : TaintSpec.S) = struct let _, base_typ = fst (AccessPath.extract access_path) in AccessPath.with_base (make_footprint_var formal_index, base_typ) access_path + type extras = { formal_map : FormalMap.t; summary : Specs.summary; } + module TransferFunctions (CFG : ProcCfg.S) = struct module CFG = CFG module Domain = Domain - - type extras = FormalMap.t + type nonrec extras = extras (* get the node associated with [access_path] in [access_tree] *) - let access_path_get_node access_path access_tree (proc_data : FormalMap.t ProcData.t) = + let access_path_get_node access_path access_tree (proc_data : extras ProcData.t) = match TaintDomain.get_node access_path access_tree with | Some _ as node_opt -> node_opt @@ -68,7 +69,7 @@ module Make (TaintSpecification : TaintSpec.S) = struct (TraceDomain.Source.make_footprint footprint_ap proc_data.pdesc) in Some (TaintDomain.make_normal_leaf trace) in let root, _ = AccessPath.extract access_path in - match FormalMap.get_formal_index root proc_data.extras with + match FormalMap.get_formal_index root proc_data.extras.formal_map with | Some formal_index -> make_footprint_trace (make_footprint_access_path formal_index access_path) | None -> @@ -110,7 +111,7 @@ module Make (TaintSpecification : TaintSpec.S) = struct false (** log any new reportable source-sink flows in [trace] *) - let report_trace trace cur_site (proc_data : FormalMap.t ProcData.t) = + let report_trace trace cur_site (proc_data : extras ProcData.t) = let trace_of_pname pname = if Typ.Procname.equal pname (Procdesc.get_proc_name proc_data.pdesc) then @@ -137,12 +138,12 @@ module Make (TaintSpecification : TaintSpec.S) = struct (if is_endpoint original_source then ". Note: source is an endpoint." else "") in let report_error path = - let caller_pname = Procdesc.get_proc_name proc_data.pdesc in let msg = Localise.to_issue_id Localise.quandary_taint_error in let trace_str = F.asprintf "%a" pp_path_short path in let ltr = TraceDomain.to_loc_trace path in let exn = Exceptions.Checkers (msg, Localise.verbatim_desc trace_str) in - Reporting.log_error caller_pname ~loc:(CallSite.loc cur_site) ~ltr exn in + Reporting.log_error_from_summary + proc_data.extras.summary ~loc:(CallSite.loc cur_site) ~ltr exn in List.iter ~f:report_error (TraceDomain.get_reportable_paths ~cur_site trace ~trace_of_pname) @@ -184,7 +185,7 @@ module Make (TaintSpecification : TaintSpec.S) = struct (actuals : HilExp.t list) summary caller_access_tree - (proc_data : FormalMap.t ProcData.t) + (proc_data : extras ProcData.t) callee_site = let get_caller_ap formal_ap = @@ -263,15 +264,13 @@ module Make (TaintSpecification : TaintSpec.S) = struct (TaintSpecification.of_summary_access_tree summary) caller_access_tree - let exec_instr - (astate : Domain.astate) (proc_data : FormalMap.t ProcData.t) _ (instr : HilInstr.t) = + let exec_instr (astate : Domain.astate) (proc_data : extras ProcData.t) _ (instr : HilInstr.t) = let exec_write lhs_access_path rhs_exp astate= let rhs_node = Option.value (hil_exp_get_node rhs_exp astate proc_data) ~default:TaintDomain.empty_node in TaintDomain.add_node (AccessPath.Exact lhs_access_path) rhs_node astate in - match instr with | Write (((Var.ProgramVar pvar, _), []), HilExp.Exception _, _) when Pvar.is_return pvar -> (* the Java frontend translates `throw Exception` as `return Exception`, which is a bit @@ -502,7 +501,7 @@ module Make (TaintSpecification : TaintSpec.S) = struct module Interprocedural = AbstractInterpreter.Interprocedural(Summary) - let checker ({ Callbacks.tenv; } as callback) : Specs.summary = + let checker ({ Callbacks.tenv; summary; } as callback) : Specs.summary = (* bind parameters to a trace with a tainted source (if applicable) *) let make_initial pdesc = @@ -519,7 +518,7 @@ module Make (TaintSpecification : TaintSpec.S) = struct (TraceDomain.Source.get_tainted_formals pdesc tenv) in access_tree, IdAccessPathMapDomain.empty in - let compute_post (proc_data : FormalMap.t ProcData.t) = + let compute_post (proc_data : extras ProcData.t) = if not (Procdesc.did_preanalysis proc_data.pdesc) then begin @@ -529,11 +528,13 @@ module Make (TaintSpecification : TaintSpec.S) = struct let initial = make_initial proc_data.pdesc in match Analyzer.compute_post proc_data ~initial with | Some (access_tree, _) -> - Some (make_summary proc_data.extras access_tree) + Some (make_summary proc_data.extras.formal_map access_tree) | None -> if Procdesc.Node.get_succs (Procdesc.get_start_node proc_data.pdesc) <> [] then failwith "Couldn't compute post" else None in - let make_extras = FormalMap.make in + let make_extras pdesc = + let formal_map = FormalMap.make pdesc in + { formal_map; summary; } in Interprocedural.compute_and_store_post ~compute_post ~make_extras callback end diff --git a/infer/src/unit/TaintTests.ml b/infer/src/unit/TaintTests.ml index 61590fd76..a39377fc2 100644 --- a/infer/src/unit/TaintTests.ml +++ b/infer/src/unit/TaintTests.ml @@ -225,6 +225,6 @@ let tests = ] |> TestInterpreter.create_tests ~pp_opt:pp_sparse - FormalMap.empty + { formal_map=FormalMap.empty; summary=Specs.dummy; } ~initial:(MockTaintAnalysis.Domain.empty, IdAccessPathMapDomain.empty) in "taint_test_suite">:::test_list