diff --git a/infer/src/quandary/TaintAnalysis.ml b/infer/src/quandary/TaintAnalysis.ml index 518f925aa..b3cc7de65 100644 --- a/infer/src/quandary/TaintAnalysis.ml +++ b/infer/src/quandary/TaintAnalysis.ml @@ -162,11 +162,17 @@ module Make (TaintSpec : TaintSpec.S) = struct | Some (actual_trace, _) -> (* add callee_pname to actual trace as a sink *) let actual_trace' = TraceDomain.add_sink sink_param.sink actual_trace in - let pname = Cfg.Procdesc.get_proc_name proc_data.ProcData.pdesc in - IList.iter - (Reporting.log_error pname ~loc) - (TraceDomain.get_reportable_exns actual_trace'); - TaintDomain.add_trace actual_ap actual_trace' access_tree_acc + begin + match TraceDomain.get_reportable_exns actual_trace' with + | [] -> + TaintDomain.add_trace actual_ap actual_trace' access_tree_acc + | reportable_exns -> + (* got new source -> sink flow. report it, but don't update the trace. if we + update the trace, we will double-report later on. *) + let pname = Cfg.Procdesc.get_proc_name proc_data.ProcData.pdesc in + IList.iter (Reporting.log_error pname ~loc) reportable_exns; + access_tree_acc + end | None -> access_tree_acc end diff --git a/infer/tests/codetoanalyze/java/quandary/Basics.java b/infer/tests/codetoanalyze/java/quandary/Basics.java index 56e705332..e6e95d52e 100644 --- a/infer/tests/codetoanalyze/java/quandary/Basics.java +++ b/infer/tests/codetoanalyze/java/quandary/Basics.java @@ -153,6 +153,13 @@ public class Basics { InferTaint.inferSensitiveSink(src); } + // this should report only two alarms, not three + void noTripleReportBad() { + Object src = InferTaint.inferSecretSource(); + InferTaint.inferSensitiveSink(src); + InferTaint.inferSensitiveSink(src); + } + /** should not report on these tests */ void directOk1() { diff --git a/infer/tests/codetoanalyze/java/quandary/issues.exp b/infer/tests/codetoanalyze/java/quandary/issues.exp index b08ff761d..790511098 100644 --- a/infer/tests/codetoanalyze/java/quandary/issues.exp +++ b/infer/tests/codetoanalyze/java/quandary/issues.exp @@ -20,8 +20,10 @@ Basics.java:118: ERROR: QUANDARY_TAINT_ERROR Error: Other(Object InferTaint.infe Basics.java:132: ERROR: QUANDARY_TAINT_ERROR Error: Other(Object InferTaint.inferSecretSource() at [line 129]) -> Other(void InferTaint.inferSensitiveSink(Object) at [line 132]) via { } Basics.java:142: ERROR: QUANDARY_TAINT_ERROR Error: Other(Object InferTaint.inferSecretSource() at [line 140]) -> Other(void InferTaint.inferSensitiveSink(Object) at [line 142]) via { } Basics.java:153: ERROR: QUANDARY_TAINT_ERROR Error: Other(Object InferTaint.inferSecretSource() at [line 150]) -> Other(void InferTaint.inferSensitiveSink(Object) at [line 153]) via { } -Basics.java:196: ERROR: QUANDARY_TAINT_ERROR Error: Other(Object InferTaint.inferSecretSource() at [line 193]) -> Other(void InferTaint.inferSensitiveSink(Object) at [line 196]) via { } -Basics.java:205: ERROR: QUANDARY_TAINT_ERROR Error: Other(Object InferTaint.inferSecretSource() at [line 201]) -> Other(void InferTaint.inferSensitiveSink(Object) at [line 205]) via { } +Basics.java:159: ERROR: QUANDARY_TAINT_ERROR Error: Other(Object InferTaint.inferSecretSource() at [line 158]) -> Other(void InferTaint.inferSensitiveSink(Object) at [line 159]) via { } +Basics.java:160: ERROR: QUANDARY_TAINT_ERROR Error: Other(Object InferTaint.inferSecretSource() at [line 158]) -> Other(void InferTaint.inferSensitiveSink(Object) at [line 160]) via { } +Basics.java:203: ERROR: QUANDARY_TAINT_ERROR Error: Other(Object InferTaint.inferSecretSource() at [line 200]) -> Other(void InferTaint.inferSensitiveSink(Object) at [line 203]) via { } +Basics.java:212: ERROR: QUANDARY_TAINT_ERROR Error: Other(Object InferTaint.inferSecretSource() at [line 208]) -> Other(void InferTaint.inferSensitiveSink(Object) at [line 212]) via { } DynamicDispatch.java:77: ERROR: QUANDARY_TAINT_ERROR Error: Other(Object InferTaint.inferSecretSource() at [line 25]) -> Other(void InferTaint.inferSensitiveSink(Object) at [line 77]) via { Object DynamicDispatch$BadInterfaceImpl1.returnSource() at [line 76], Object DynamicDispatch$BadInterfaceImpl2.returnSource() at [line 76] } DynamicDispatch.java:77: ERROR: QUANDARY_TAINT_ERROR Error: Other(Object InferTaint.inferSecretSource() at [line 42]) -> Other(void InferTaint.inferSensitiveSink(Object) at [line 77]) via { Object DynamicDispatch$BadInterfaceImpl1.returnSource() at [line 76], Object DynamicDispatch$BadInterfaceImpl2.returnSource() at [line 76] } DynamicDispatch.java:82: ERROR: QUANDARY_TAINT_ERROR Error: Other(Object InferTaint.inferSecretSource() at [line 81]) -> Other(void InferTaint.inferSensitiveSink(Object) at [line 30]) via { void DynamicDispatch$BadInterfaceImpl1.callSink(Object) at [line 82] }