From b1039f51f8d92e6a22aafcf0b3d4bb367db02e18 Mon Sep 17 00:00:00 2001 From: Sam Blackshear Date: Thu, 22 Sep 2016 11:15:58 -0700 Subject: [PATCH] [quandary] add summaries for footprint traces associated with locals Differential Revision: D3883275 fbshipit-source-id: 651116e --- infer/src/quandary/TaintAnalysis.ml | 91 ++++++++----------- .../java/quandary/Interprocedural.java | 14 +++ .../codetoanalyze/java/quandary/issues.exp | 9 +- 3 files changed, 59 insertions(+), 55 deletions(-) diff --git a/infer/src/quandary/TaintAnalysis.ml b/infer/src/quandary/TaintAnalysis.ml index 7def0f929..a80348b90 100644 --- a/infer/src/quandary/TaintAnalysis.ml +++ b/infer/src/quandary/TaintAnalysis.ml @@ -351,64 +351,53 @@ module Make (TraceDomain : QuandarySummary.Trace) = struct (** grab footprint traces in [access_tree] and make them into inputs for the summary. for each trace Footprint(T_out, a.b.c) associated with access path x.z.y, we will produce a summary of the form (x.z.y, T_in) => (T_in + T_out, a.b.c) *) - let make_summary formal_map access_tree pdesc = - let add_summary_for_output summary_acc output trace = - let make_in_out_summary summary_input summary_output trace = - let _ = match summary_input with - | QuandarySummary.In_formal (_, _) -> () - | _ -> () in - QuandarySummary.make_in_out_summary - summary_input summary_output (TraceDomain.to_summary_trace trace) in - - let extract_input source acc = + let make_summary formal_map access_tree = + let is_return (var, _) = match var with + | Var.ProgramVar pvar -> Pvar.is_return pvar + | Var.LogicalVar _ -> false in + let add_summaries_for_trace summary_acc access_path trace = + let summary_trace = TraceDomain.to_summary_trace trace in + let output_opt = + let base = fst (AccessPath.extract access_path) in + match AccessPath.BaseMap.find base formal_map with + | index -> + Some (QuandarySummary.make_formal_output index access_path) + | exception Not_found -> + if is_return base + then Some (QuandarySummary.make_return_output access_path) + else None in + + let add_summary_for_source source acc = match TraceDomain.Source.get_footprint_access_path source with | Some footprint_ap -> - let input = - let footprint_ap_base = fst (AccessPath.extract footprint_ap) in + let footprint_ap_base = fst (AccessPath.extract footprint_ap) in + let formal_index = match AccessPath.BaseMap.find footprint_ap_base formal_map with - | index -> - QuandarySummary.make_formal_input index footprint_ap + | index -> index | exception Not_found -> failwithf "Couldn't find formal number for %a@." AccessPath.pp_base footprint_ap_base in - let summary = make_in_out_summary input output trace in + let input = QuandarySummary.make_formal_input formal_index footprint_ap in + let output = + match output_opt with + | Some output -> output + | None -> QuandarySummary.make_formal_output formal_index footprint_ap in + let summary = QuandarySummary.make_in_out_summary input output summary_trace in summary :: acc | None -> - let summary = make_in_out_summary QuandarySummary.empty_input output trace in - summary :: acc in - TraceDomain.Source.Set.fold extract_input (TraceDomain.sources trace) summary_acc in - - let add_summaries_for_base - ~(f_make_output : AccessPath.t -> QuandarySummary.output) base summary_acc = - let add_summary_for_access_path summary_acc access_path trace = - add_summary_for_output summary_acc (f_make_output access_path) trace in - - let raw_base_ap = base, [] in - match TaintDomain.BaseMap.find base access_tree with - | trace, TaintDomain.Star -> - add_summary_for_access_path summary_acc (AccessPath.Abstracted raw_base_ap) trace - | trace, TaintDomain.Subtree subtree -> - let access_path = AccessPath.Exact raw_base_ap in - add_summary_for_output summary_acc (f_make_output access_path) trace - |> TaintDomain.access_map_fold add_summary_for_access_path base subtree - | exception Not_found -> - summary_acc in - - let add_formal_summaries formal formal_index summary_acc = - let f_make_output = QuandarySummary.make_formal_output formal_index in - add_summaries_for_base ~f_make_output formal summary_acc in - - let add_return_summaries summary_acc = match Cfg.Procdesc.get_ret_type pdesc with - | Typ.Tvoid -> - summary_acc - | ret_typ -> - let return_var_base = AccessPath.base_of_pvar (Cfg.Procdesc.get_ret_var pdesc) ret_typ in - add_summaries_for_base - ~f_make_output:QuandarySummary.make_return_output return_var_base summary_acc in - - (* add summaries for each formal and the return value *) - AccessPath.BaseMap.fold add_formal_summaries formal_map [] - |> add_return_summaries + begin + match output_opt with + | Some output -> + let summary = + QuandarySummary.make_in_out_summary + QuandarySummary.empty_input output summary_trace in + summary :: acc + | None -> + acc + end in + + TraceDomain.Source.Set.fold add_summary_for_source (TraceDomain.sources trace) summary_acc in + TaintDomain.fold add_summaries_for_trace access_tree [] let dummy_cg = Cg.create None @@ -431,7 +420,7 @@ module Make (TraceDomain : QuandarySummary.Trace) = struct let proc_data = ProcData.make pdesc tenv formals in match Analyzer.compute_post proc_data with | Some { access_tree; } -> - let summary = make_summary formals access_tree pdesc in + let summary = make_summary formals access_tree in Summary.write_summary (Cfg.Procdesc.get_proc_name pdesc) summary; | None -> failwith "Couldn't compute post" in diff --git a/infer/tests/codetoanalyze/java/quandary/Interprocedural.java b/infer/tests/codetoanalyze/java/quandary/Interprocedural.java index e9181f553..f1c552f01 100644 --- a/infer/tests/codetoanalyze/java/quandary/Interprocedural.java +++ b/infer/tests/codetoanalyze/java/quandary/Interprocedural.java @@ -101,6 +101,20 @@ class Interprocedural { callSinkOnFieldIndirect(obj); } + public Object getF() { + return f; + } + + void callSinkOnLocal() { + Object local = this.getF(); + InferTaint.inferSensitiveSink(local); + } + + void callSinkOnLocalBad() { + this.f = InferTaint.inferSecretSource(); + callSinkOnLocal(); + } + /** passthrough tests */ public static void singlePassthroughBad() { diff --git a/infer/tests/codetoanalyze/java/quandary/issues.exp b/infer/tests/codetoanalyze/java/quandary/issues.exp index ef1e0b110..18a087b87 100644 --- a/infer/tests/codetoanalyze/java/quandary/issues.exp +++ b/infer/tests/codetoanalyze/java/quandary/issues.exp @@ -37,10 +37,11 @@ Interprocedural.java:66: ERROR: QUANDARY_TAINT_ERROR Error: Other(Object InferTa Interprocedural.java:78: ERROR: QUANDARY_TAINT_ERROR Error: Other(Object InferTaint.inferSecretSource() at [line 78]) -> Other(void InferTaint.inferSensitiveSink(Object) at [line 74]) via { void Interprocedural.callSinkParam2(Object,Object) at [line 78] } Interprocedural.java:91: ERROR: QUANDARY_TAINT_ERROR Error: Other(Object InferTaint.inferSecretSource() at [line 90]) -> Other(void InferTaint.inferSensitiveSink(Object) at [line 86]) via { void Interprocedural.callSinkOnFieldDirect() at [line 91] } Interprocedural.java:101: ERROR: QUANDARY_TAINT_ERROR Error: Other(Object InferTaint.inferSecretSource() at [line 100]) -> Other(void InferTaint.inferSensitiveSink(Object) at [line 95]) via { void Interprocedural.callSinkOnFieldIndirect(Interprocedural$Obj) at [line 101] } -Interprocedural.java:109: ERROR: QUANDARY_TAINT_ERROR Error: Other(Object InferTaint.inferSecretSource() at [line 107]) -> Other(void InferTaint.inferSensitiveSink(Object) at [line 109]) via { Object Interprocedural.id(Object) at [line 108] } -Interprocedural.java:116: ERROR: QUANDARY_TAINT_ERROR Error: Other(Object InferTaint.inferSecretSource() at [line 113]) -> Other(void InferTaint.inferSensitiveSink(Object) at [line 116]) via { Object Interprocedural.id(Object) at [line 114], Object Interprocedural.id(Object) at [line 115] } -Interprocedural.java:127: ERROR: QUANDARY_TAINT_ERROR Error: Other(Object InferTaint.inferSecretSource() at [line 122]) -> Other(void InferTaint.inferSensitiveSink(Object) at [line 127]) via { Object Interprocedural.returnSourceConditional(boolean) at [line 127] } -Interprocedural.java:138: ERROR: QUANDARY_TAINT_ERROR Error: Other(Object InferTaint.inferSecretSource() at [line 136]) -> Other(void InferTaint.inferSensitiveSink(Object) at [line 138]) via { } +Interprocedural.java:115: ERROR: QUANDARY_TAINT_ERROR Error: Other(Object InferTaint.inferSecretSource() at [line 114]) -> Other(void InferTaint.inferSensitiveSink(Object) at [line 110]) via { void Interprocedural.callSinkOnLocal() at [line 115], Object Interprocedural.getF() at [line 109] } +Interprocedural.java:123: ERROR: QUANDARY_TAINT_ERROR Error: Other(Object InferTaint.inferSecretSource() at [line 121]) -> Other(void InferTaint.inferSensitiveSink(Object) at [line 123]) via { Object Interprocedural.id(Object) at [line 122] } +Interprocedural.java:130: ERROR: QUANDARY_TAINT_ERROR Error: Other(Object InferTaint.inferSecretSource() at [line 127]) -> Other(void InferTaint.inferSensitiveSink(Object) at [line 130]) via { Object Interprocedural.id(Object) at [line 128], Object Interprocedural.id(Object) at [line 129] } +Interprocedural.java:141: ERROR: QUANDARY_TAINT_ERROR Error: Other(Object InferTaint.inferSecretSource() at [line 136]) -> Other(void InferTaint.inferSensitiveSink(Object) at [line 141]) via { Object Interprocedural.returnSourceConditional(boolean) at [line 141] } +Interprocedural.java:152: ERROR: QUANDARY_TAINT_ERROR Error: Other(Object InferTaint.inferSecretSource() at [line 150]) -> Other(void InferTaint.inferSensitiveSink(Object) at [line 152]) via { } LoggingPrivateData.java:18: ERROR: QUANDARY_TAINT_ERROR Error: SharedPreferences(String SharedPreferences.getString(String,String) at [line 18]) -> Logging(int Log.d(String,String) at [line 18]) via { } LoggingPrivateData.java:22: ERROR: QUANDARY_TAINT_ERROR Error: SharedPreferences(String SharedPreferences.getString(String,String) at [line 22]) -> Logging(int Log.d(String,String) at [line 22]) via { } LoggingPrivateData.java:37: ERROR: QUANDARY_TAINT_ERROR Error: SharedPreferences(String SharedPreferences.getString(String,String) at [line 36]) -> Logging(int Log.w(String,Throwable) at [line 37]) via { }