diff --git a/infer/src/quandary/Trace.ml b/infer/src/quandary/Trace.ml index b201eb855..a77f34629 100644 --- a/infer/src/quandary/Trace.ml +++ b/infer/src/quandary/Trace.ml @@ -159,15 +159,21 @@ module Make (Spec : Spec) = struct let sources = Sources.filter (fun source -> not (Source.is_footprint source)) callee_trace.sources |> Sources.union caller_trace.sources in - let sinks = Sinks.union caller_trace.sinks callee_trace.sinks in - let passthroughs = - let is_original_sink sink = - Procname.equal (CallSite.pname callee_site) (CallSite.pname (Sink.call_site sink)) in - (* add [callee_site] as a passthrough if it is not an "original" sink; that is, a procedure - that is itself a sink rather than a caller of a sink *) - if Sinks.exists is_original_sink callee_trace.sinks - then caller_trace.passthroughs - else Passthroughs.add (Passthrough.make callee_site) caller_trace.passthroughs in + let sinks, passthroughs = + if Sinks.for_all (fun sink -> Sinks.mem sink caller_trace.sinks) callee_trace.sinks + then + (* this callee didn't add any new sinks; it's just a passthrough *) + let passthroughs = + Passthroughs.add (Passthrough.make callee_site) caller_trace.passthroughs in + caller_trace.sinks, passthroughs + else + (* this callee added a new sink *) + let callee_sinks = + IList.map + (fun sink -> Sink.to_callee sink callee_site) + (Sinks.elements callee_trace.sinks) + |> Sinks.of_list in + Sinks.union caller_trace.sinks callee_sinks, caller_trace.passthroughs in { sources; sinks; passthroughs; } let initial = diff --git a/infer/src/unit/TraceTests.ml b/infer/src/unit/TraceTests.ml index 4236cf461..4f5f85965 100644 --- a/infer/src/unit/TraceTests.ml +++ b/infer/src/unit/TraceTests.ml @@ -52,7 +52,7 @@ module MockTraceElem = struct let pp_element = pp end) - let to_callee _ _ = assert false + let to_callee t _ = t end module MockSource = struct diff --git a/infer/tests/codetoanalyze/cpp/quandary/issues.exp b/infer/tests/codetoanalyze/cpp/quandary/issues.exp index 41dd8b305..2a5cd8681 100644 --- a/infer/tests/codetoanalyze/cpp/quandary/issues.exp +++ b/infer/tests/codetoanalyze/cpp/quandary/issues.exp @@ -1,7 +1,7 @@ basics.cpp:28: ERROR: QUANDARY_TAINT_ERROR Error: Other(__infer_taint_source at [line 27]) -> Other(__infer_taint_sink at [line 28]) via { } basics.cpp:33: ERROR: QUANDARY_TAINT_ERROR Error: Other(__infer_taint_source at [line 20]) -> Other(__infer_taint_sink at [line 33]) via { basics::returnSource at [line 32] } -basics.cpp:38: ERROR: QUANDARY_TAINT_ERROR Error: Other(__infer_taint_source at [line 37]) -> Other(__infer_taint_sink at [line 22]) via { basics::callSink at [line 38] } -basics.cpp:44: ERROR: QUANDARY_TAINT_ERROR Error: Other(__infer_taint_source at [line 42]) -> Other(__infer_taint_sink at [line 22]) via { basics::callSink at [line 44], basics::id at [line 43] } +basics.cpp:38: ERROR: QUANDARY_TAINT_ERROR Error: Other(__infer_taint_source at [line 37]) -> Other(basics::callSink at [line 38]) via { } +basics.cpp:44: ERROR: QUANDARY_TAINT_ERROR Error: Other(__infer_taint_source at [line 42]) -> Other(basics::callSink at [line 44]) via { basics::id at [line 43] } execs.cpp:52: ERROR: QUANDARY_TAINT_ERROR Error: EnvironmentVariable(getenv at [line 47]) -> ShellExec(execl at [line 52]) via { } execs.cpp:54: ERROR: QUANDARY_TAINT_ERROR Error: EnvironmentVariable(getenv at [line 47]) -> ShellExec(execl at [line 54]) via { } execs.cpp:57: ERROR: QUANDARY_TAINT_ERROR Error: EnvironmentVariable(getenv at [line 47]) -> ShellExec(execl at [line 57]) via { } diff --git a/infer/tests/codetoanalyze/java/quandary/issues.exp b/infer/tests/codetoanalyze/java/quandary/issues.exp index dc06f1263..2a289c281 100644 --- a/infer/tests/codetoanalyze/java/quandary/issues.exp +++ b/infer/tests/codetoanalyze/java/quandary/issues.exp @@ -27,22 +27,22 @@ Basics.java:209: ERROR: QUANDARY_TAINT_ERROR Error: Other(Object InferTaint.infe Basics.java:218: ERROR: QUANDARY_TAINT_ERROR Error: Other(Object InferTaint.inferSecretSource() at [line 214]) -> Other(void InferTaint.inferSensitiveSink(Object) at [line 218]) 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] } -DynamicDispatch.java:82: ERROR: QUANDARY_TAINT_ERROR Error: Other(Object InferTaint.inferSecretSource() at [line 81]) -> Other(void InferTaint.inferSensitiveSink(Object) at [line 47]) via { void DynamicDispatch$BadInterfaceImpl2.callSink(Object) at [line 82] } +DynamicDispatch.java:82: ERROR: QUANDARY_TAINT_ERROR Error: Other(Object InferTaint.inferSecretSource() at [line 81]) -> Other(void DynamicDispatch$BadInterfaceImpl1.callSink(Object) at [line 82]) via { } +DynamicDispatch.java:82: ERROR: QUANDARY_TAINT_ERROR Error: Other(Object InferTaint.inferSecretSource() at [line 81]) -> Other(void DynamicDispatch$BadInterfaceImpl2.callSink(Object) at [line 82]) via { } DynamicDispatch.java:88: ERROR: QUANDARY_TAINT_ERROR Error: Other(Object InferTaint.inferSecretSource() at [line 86]) -> Other(void InferTaint.inferSensitiveSink(Object) at [line 88]) via { Object DynamicDispatch$BadInterfaceImpl1.propagate(Object) at [line 87], Object DynamicDispatch$BadInterfaceImpl2.propagate(Object) at [line 87] } DynamicDispatch.java:135: ERROR: QUANDARY_TAINT_ERROR Error: Other(Object InferTaint.inferSecretSource() at [line 119]) -> Other(void InferTaint.inferSensitiveSink(Object) at [line 135]) via { Object DynamicDispatch$BadSubtype.returnSource() at [line 134] } -DynamicDispatch.java:140: ERROR: QUANDARY_TAINT_ERROR Error: Other(Object InferTaint.inferSecretSource() at [line 139]) -> Other(void InferTaint.inferSensitiveSink(Object) at [line 124]) via { void DynamicDispatch$BadSubtype.callSink(Object) at [line 140] } +DynamicDispatch.java:140: ERROR: QUANDARY_TAINT_ERROR Error: Other(Object InferTaint.inferSecretSource() at [line 139]) -> Other(void DynamicDispatch$BadSubtype.callSink(Object) at [line 140]) via { } DynamicDispatch.java:146: ERROR: QUANDARY_TAINT_ERROR Error: Other(Object InferTaint.inferSecretSource() at [line 144]) -> Other(void InferTaint.inferSensitiveSink(Object) at [line 146]) via { Object DynamicDispatch$BadSubtype.propagate(Object) at [line 145] } DynamicDispatch.java:154: ERROR: QUANDARY_TAINT_ERROR Error: Other(Object InferTaint.inferSecretSource() at [line 119]) -> Other(void InferTaint.inferSensitiveSink(Object) at [line 154]) via { Object DynamicDispatch$BadSubtype.returnSource() at [line 153] } -DynamicDispatch.java:157: ERROR: QUANDARY_TAINT_ERROR Error: Other(Object InferTaint.inferSecretSource() at [line 156]) -> Other(void InferTaint.inferSensitiveSink(Object) at [line 124]) via { void DynamicDispatch$BadSubtype.callSink(Object) at [line 157] } -DynamicDispatch.java:160: ERROR: QUANDARY_TAINT_ERROR Error: Other(Object InferTaint.inferSecretSource() at [line 156]) -> Other(void InferTaint.inferSensitiveSink(Object) at [line 160]) via { void DynamicDispatch$BadSubtype.callSink(Object) at [line 157], Object DynamicDispatch$BadSubtype.propagate(Object) at [line 159] } +DynamicDispatch.java:157: ERROR: QUANDARY_TAINT_ERROR Error: Other(Object InferTaint.inferSecretSource() at [line 156]) -> Other(void DynamicDispatch$BadSubtype.callSink(Object) at [line 157]) via { } +DynamicDispatch.java:160: ERROR: QUANDARY_TAINT_ERROR Error: Other(Object InferTaint.inferSecretSource() at [line 156]) -> Other(void InferTaint.inferSensitiveSink(Object) at [line 160]) via { Object DynamicDispatch$BadSubtype.propagate(Object) at [line 159] } Exceptions.java:23: ERROR: QUANDARY_TAINT_ERROR Error: Other(Object InferTaint.inferSecretSource() at [line 19]) -> Other(void InferTaint.inferSensitiveSink(Object) at [line 23]) via { } Exceptions.java:33: ERROR: QUANDARY_TAINT_ERROR Error: Other(Object InferTaint.inferSecretSource() at [line 30]) -> Other(void InferTaint.inferSensitiveSink(Object) at [line 33]) via { } Exceptions.java:44: ERROR: QUANDARY_TAINT_ERROR Error: Other(Object InferTaint.inferSecretSource() at [line 38]) -> Other(void InferTaint.inferSensitiveSink(Object) at [line 44]) via { } Exceptions.java:63: ERROR: QUANDARY_TAINT_ERROR Error: Other(Object InferTaint.inferSecretSource() at [line 59]) -> Other(void InferTaint.inferSensitiveSink(Object) at [line 63]) via { } Exceptions.java:73: ERROR: QUANDARY_TAINT_ERROR Error: Other(Object InferTaint.inferSecretSource() at [line 71]) -> Other(void InferTaint.inferSensitiveSink(Object) at [line 73]) via { } Exceptions.java:84: ERROR: QUANDARY_TAINT_ERROR Error: Other(Object InferTaint.inferSecretSource() at [line 82]) -> Other(void InferTaint.inferSensitiveSink(Object) at [line 84]) via { } -Exceptions.java:117: ERROR: QUANDARY_TAINT_ERROR Error: Other(Object InferTaint.inferSecretSource() at [line 117]) -> Other(void InferTaint.inferSensitiveSink(Object) at [line 112]) via { void Exceptions.callSinkThenThrow(Object) at [line 117] } +Exceptions.java:117: ERROR: QUANDARY_TAINT_ERROR Error: Other(Object InferTaint.inferSecretSource() at [line 117]) -> Other(void Exceptions.callSinkThenThrow(Object) at [line 117]) via { } Fields.java:28: ERROR: QUANDARY_TAINT_ERROR Error: Other(Object InferTaint.inferSecretSource() at [line 27]) -> Other(void InferTaint.inferSensitiveSink(Object) at [line 28]) via { } Fields.java:33: ERROR: QUANDARY_TAINT_ERROR Error: Other(Object InferTaint.inferSecretSource() at [line 32]) -> Other(void InferTaint.inferSensitiveSink(Object) at [line 33]) via { } Fields.java:38: ERROR: QUANDARY_TAINT_ERROR Error: Other(Object InferTaint.inferSecretSource() at [line 37]) -> Other(void InferTaint.inferSensitiveSink(Object) at [line 38]) via { } @@ -87,21 +87,21 @@ Interprocedural.java:58: ERROR: QUANDARY_TAINT_ERROR Error: Other(Object InferTa Interprocedural.java:67: ERROR: QUANDARY_TAINT_ERROR Error: Other(Object InferTaint.inferSecretSource() at [line 62]) -> Other(void InferTaint.inferSensitiveSink(Object) at [line 67]) via { void Interprocedural.returnSourceViaParameter1(Interprocedural$Obj) at [line 66] } Interprocedural.java:77: ERROR: QUANDARY_TAINT_ERROR Error: Other(Object InferTaint.inferSecretSource() at [line 75]) -> Other(void InferTaint.inferSensitiveSink(Object) at [line 77]) via { void Interprocedural.returnSourceViaParameter2(Interprocedural$Obj,Interprocedural$Obj) at [line 76] } Interprocedural.java:92: ERROR: QUANDARY_TAINT_ERROR Error: Other(Object InferTaint.inferSecretSource() at [line 87]) -> Other(void InferTaint.inferSensitiveSink(Object) at [line 92]) via { void Interprocedural.returnSourceViaGlobal() at [line 91] } -Interprocedural.java:108: ERROR: QUANDARY_TAINT_ERROR Error: Other(Object InferTaint.inferSecretSource() at [line 108]) -> Other(void InferTaint.inferSensitiveSink(Object) at [line 104]) via { void Interprocedural.callSinkParam1(Object,Object) at [line 108] } -Interprocedural.java:120: ERROR: QUANDARY_TAINT_ERROR Error: Other(Object InferTaint.inferSecretSource() at [line 120]) -> Other(void InferTaint.inferSensitiveSink(Object) at [line 116]) via { void Interprocedural.callSinkParam2(Object,Object) at [line 120] } -Interprocedural.java:133: ERROR: QUANDARY_TAINT_ERROR Error: Other(Object InferTaint.inferSecretSource() at [line 132]) -> Other(void InferTaint.inferSensitiveSink(Object) at [line 128]) via { void Interprocedural.callSinkOnFieldDirect() at [line 133] } -Interprocedural.java:143: ERROR: QUANDARY_TAINT_ERROR Error: Other(Object InferTaint.inferSecretSource() at [line 142]) -> Other(void InferTaint.inferSensitiveSink(Object) at [line 137]) via { void Interprocedural.callSinkOnFieldIndirect(Interprocedural$Obj) at [line 143] } -Interprocedural.java:157: ERROR: QUANDARY_TAINT_ERROR Error: Other(Object InferTaint.inferSecretSource() at [line 156]) -> Other(void InferTaint.inferSensitiveSink(Object) at [line 152]) via { void Interprocedural.callSinkOnLocal() at [line 157] } -Interprocedural.java:166: ERROR: QUANDARY_TAINT_ERROR Error: Other(Object InferTaint.inferSecretSource() at [line 165]) -> Other(void InferTaint.inferSensitiveSink(Object) at [line 161]) via { void Interprocedural.callSinkOnGlobal() at [line 166] } -Interprocedural.java:181: ERROR: QUANDARY_TAINT_ERROR Error: Other(Object InferTaint.inferSecretSource() at [line 180]) -> Other(void InferTaint.inferSensitiveSink(Object) at [line 161]) via { void Interprocedural.callSinkOnGlobal() at [line 181], void Interprocedural.setGlobal(Object) at [line 180] } -Interprocedural.java:195: ERROR: QUANDARY_TAINT_ERROR Error: Other(Object InferTaint.inferSecretSource() at [line 194]) -> Other(void InferTaint.inferSensitiveSink(Object) at [line 190]) via { void Interprocedural.getGlobalThenCallSink() at [line 195] } -Interprocedural.java:201: ERROR: QUANDARY_TAINT_ERROR Error: Other(Object InferTaint.inferSecretSource() at [line 200]) -> Other(void InferTaint.inferSensitiveSink(Object) at [line 104]) via { void Interprocedural.callSinkParam1(Object,Object) at [line 201] } -Interprocedural.java:202: ERROR: QUANDARY_TAINT_ERROR Error: Other(Object InferTaint.inferSecretSource() at [line 200]) -> Other(void InferTaint.inferSensitiveSink(Object) at [line 116]) via { void Interprocedural.callSinkParam1(Object,Object) at [line 201], void Interprocedural.callSinkParam2(Object,Object) at [line 202] } +Interprocedural.java:108: ERROR: QUANDARY_TAINT_ERROR Error: Other(Object InferTaint.inferSecretSource() at [line 108]) -> Other(void Interprocedural.callSinkParam1(Object,Object) at [line 108]) via { } +Interprocedural.java:120: ERROR: QUANDARY_TAINT_ERROR Error: Other(Object InferTaint.inferSecretSource() at [line 120]) -> Other(void Interprocedural.callSinkParam2(Object,Object) at [line 120]) via { } +Interprocedural.java:133: ERROR: QUANDARY_TAINT_ERROR Error: Other(Object InferTaint.inferSecretSource() at [line 132]) -> Other(void Interprocedural.callSinkOnFieldDirect() at [line 133]) via { } +Interprocedural.java:143: ERROR: QUANDARY_TAINT_ERROR Error: Other(Object InferTaint.inferSecretSource() at [line 142]) -> Other(void Interprocedural.callSinkOnFieldIndirect(Interprocedural$Obj) at [line 143]) via { } +Interprocedural.java:157: ERROR: QUANDARY_TAINT_ERROR Error: Other(Object InferTaint.inferSecretSource() at [line 156]) -> Other(void Interprocedural.callSinkOnLocal() at [line 157]) via { } +Interprocedural.java:166: ERROR: QUANDARY_TAINT_ERROR Error: Other(Object InferTaint.inferSecretSource() at [line 165]) -> Other(void Interprocedural.callSinkOnGlobal() at [line 166]) via { } +Interprocedural.java:181: ERROR: QUANDARY_TAINT_ERROR Error: Other(Object InferTaint.inferSecretSource() at [line 180]) -> Other(void Interprocedural.callSinkOnGlobal() at [line 181]) via { void Interprocedural.setGlobal(Object) at [line 180] } +Interprocedural.java:195: ERROR: QUANDARY_TAINT_ERROR Error: Other(Object InferTaint.inferSecretSource() at [line 194]) -> Other(void Interprocedural.getGlobalThenCallSink() at [line 195]) via { void Interprocedural.getGlobalThenCallSink() at [line 195] } +Interprocedural.java:201: ERROR: QUANDARY_TAINT_ERROR Error: Other(Object InferTaint.inferSecretSource() at [line 200]) -> Other(void Interprocedural.callSinkParam1(Object,Object) at [line 201]) via { } +Interprocedural.java:202: ERROR: QUANDARY_TAINT_ERROR Error: Other(Object InferTaint.inferSecretSource() at [line 200]) -> Other(void Interprocedural.callSinkParam2(Object,Object) at [line 202]) via { } Interprocedural.java:210: ERROR: QUANDARY_TAINT_ERROR Error: Other(Object InferTaint.inferSecretSource() at [line 208]) -> Other(void InferTaint.inferSensitiveSink(Object) at [line 210]) via { Object Interprocedural.id(Object) at [line 209] } Interprocedural.java:217: ERROR: QUANDARY_TAINT_ERROR Error: Other(Object InferTaint.inferSecretSource() at [line 214]) -> Other(void InferTaint.inferSensitiveSink(Object) at [line 217]) via { Object Interprocedural.id(Object) at [line 215], Object Interprocedural.id(Object) at [line 216] } Interprocedural.java:228: ERROR: QUANDARY_TAINT_ERROR Error: Other(Object InferTaint.inferSecretSource() at [line 223]) -> Other(void InferTaint.inferSensitiveSink(Object) at [line 228]) via { Object Interprocedural.returnSourceConditional(boolean) at [line 228] } Interprocedural.java:239: ERROR: QUANDARY_TAINT_ERROR Error: Other(Object InferTaint.inferSecretSource() at [line 237]) -> Other(void InferTaint.inferSensitiveSink(Object) at [line 239]) via { } -Interprocedural.java:251: ERROR: QUANDARY_TAINT_ERROR Error: Other(Object InferTaint.inferSecretSource() at [line 251]) -> Other(void InferTaint.inferSensitiveSink(Object) at [line 247]) via { void Interprocedural.callSinkVariadic(java.lang.Object[]) at [line 251] } +Interprocedural.java:251: ERROR: QUANDARY_TAINT_ERROR Error: Other(Object InferTaint.inferSecretSource() at [line 251]) -> Other(void Interprocedural.callSinkVariadic(java.lang.Object[]) at [line 251]) via { } Interprocedural.java:262: ERROR: QUANDARY_TAINT_ERROR Error: Other(Object InferTaint.inferSecretSource() at [line 260]) -> Other(void InferTaint.inferSensitiveSink(Object) at [line 262]) via { } LoggingPrivateData.java:57: ERROR: QUANDARY_TAINT_ERROR Error: PrivateData(String TelephonyManager.getDeviceId() at [line 40]) -> Logging(int Log.e(String,String) at [line 57]) via { String String.valueOf(double) at [line 25], String String.valueOf(double) at [line 31], String String.valueOf(double) at [line 34], String String.valueOf(float) at [line 28], String String.valueOf(float) at [line 37] } LoggingPrivateData.java:57: ERROR: QUANDARY_TAINT_ERROR Error: PrivateData(String TelephonyManager.getLine1Number() at [line 43]) -> Logging(int Log.e(String,String) at [line 57]) via { String String.valueOf(double) at [line 25], String String.valueOf(double) at [line 31], String String.valueOf(double) at [line 34], String String.valueOf(float) at [line 28], String String.valueOf(float) at [line 37] } @@ -143,8 +143,8 @@ LoggingPrivateData.java:60: ERROR: QUANDARY_TAINT_ERROR Error: PrivateData(doubl LoggingPrivateData.java:60: ERROR: QUANDARY_TAINT_ERROR Error: PrivateData(double Location.getLongitude() at [line 34]) -> Logging(int Log.wtf(String,String) at [line 60]) via { String String.valueOf(double) at [line 25], String String.valueOf(double) at [line 31], String String.valueOf(double) at [line 34], String String.valueOf(float) at [line 28], String String.valueOf(float) at [line 37] } LoggingPrivateData.java:60: ERROR: QUANDARY_TAINT_ERROR Error: PrivateData(float Location.getBearing() at [line 28]) -> Logging(int Log.wtf(String,String) at [line 60]) via { String String.valueOf(double) at [line 25], String String.valueOf(double) at [line 31], String String.valueOf(double) at [line 34], String String.valueOf(float) at [line 28], String String.valueOf(float) at [line 37] } LoggingPrivateData.java:60: ERROR: QUANDARY_TAINT_ERROR Error: PrivateData(float Location.getSpeed() at [line 37]) -> Logging(int Log.wtf(String,String) at [line 60]) via { String String.valueOf(double) at [line 25], String String.valueOf(double) at [line 31], String String.valueOf(double) at [line 34], String String.valueOf(float) at [line 28], String String.valueOf(float) at [line 37] } -Recursion.java:26: ERROR: QUANDARY_TAINT_ERROR Error: Other(Object InferTaint.inferSecretSource() at [line 26]) -> Other(void InferTaint.inferSensitiveSink(Object) at [line 21]) via { void Recursion.callSinkThenDiverge(Object) at [line 26] } -Recursion.java:36: ERROR: QUANDARY_TAINT_ERROR Error: Other(Object InferTaint.inferSecretSource() at [line 36]) -> Other(void InferTaint.inferSensitiveSink(Object) at [line 31]) via { void Recursion.safeRecursionCallSink(int,Object) at [line 36] } -Recursion.java:42: ERROR: QUANDARY_TAINT_ERROR Error: Other(Object InferTaint.inferSecretSource() at [line 42]) -> Other(void InferTaint.inferSensitiveSink(Object) at [line 41]) via { void Recursion.recursionBad(int,Object) at [line 42] } +Recursion.java:26: ERROR: QUANDARY_TAINT_ERROR Error: Other(Object InferTaint.inferSecretSource() at [line 26]) -> Other(void Recursion.callSinkThenDiverge(Object) at [line 26]) via { } +Recursion.java:36: ERROR: QUANDARY_TAINT_ERROR Error: Other(Object InferTaint.inferSecretSource() at [line 36]) -> Other(void Recursion.safeRecursionCallSink(int,Object) at [line 36]) via { } +Recursion.java:42: ERROR: QUANDARY_TAINT_ERROR Error: Other(Object InferTaint.inferSecretSource() at [line 42]) -> Other(void Recursion.recursionBad(int,Object) at [line 42]) via { } UnknownCode.java:25: ERROR: QUANDARY_TAINT_ERROR Error: Other(Object InferTaint.inferSecretSource() at [line 23]) -> Other(void InferTaint.inferSensitiveSink(Object) at [line 25]) via { Object UnknownCode.id(Object) at [line 24] } UnknownCode.java:32: ERROR: QUANDARY_TAINT_ERROR Error: Other(Object InferTaint.inferSecretSource() at [line 29]) -> Other(void InferTaint.inferSensitiveSink(Object) at [line 32]) via { String.(String) at [line 31] }