@@ -4,6 +4,8 @@ private import semmle.code.cpp.ir.dataflow.DataFlow
44private import semmle.code.cpp.ir.dataflow.DataFlow2
55private import semmle.code.cpp.ir.IR
66private import semmle.code.cpp.ir.dataflow.internal.DataFlowDispatch as Dispatch
7+ private import semmle.code.cpp.models.interfaces.Taint
8+ private import semmle.code.cpp.models.interfaces.DataFlow
79
810/**
911 * A predictable instruction is one where an external user can predict
@@ -159,18 +161,64 @@ private predicate instructionTaintStep(Instruction i1, Instruction i2) {
159161 // This is part of the translation of `a[i]`, where we want taint to flow
160162 // from `a`.
161163 i2 .( PointerAddInstruction ) .getLeft ( ) = i1
162- // TODO: robust Chi handling
163- //
164- // TODO: Flow from argument to return of known functions: Port missing parts
165- // of `returnArgument` to the `interfaces.Taint` and `interfaces.DataFlow`
166- // libraries.
167- //
168- // TODO: Flow from input argument to output argument of known functions: Port
169- // missing parts of `copyValueBetweenArguments` to the `interfaces.Taint` and
170- // `interfaces.DataFlow` libraries and implement call side-effect nodes. This
171- // will help with the test for `ExecTainted.ql`. The test for
172- // `TaintedPath.ql` is more tricky because the output arg is a pointer
173- // addition expression.
164+ or
165+ // Flow from argument to return value
166+ i2 = any ( CallInstruction call |
167+ exists ( int indexIn |
168+ modelTaintToReturnValue ( call .getStaticCallTarget ( ) , indexIn ) and
169+ i1 = call .getPositionalArgument ( indexIn )
170+ )
171+ )
172+ or
173+ // Flow from input argument to output argument
174+ // TODO: This won't work in practice as long as all aliased memory is tracked
175+ // together in a single virtual variable.
176+ // TODO: Will this work on the test for `TaintedPath.ql`, where the output arg
177+ // is a pointer addition expression?
178+ i2 = any ( WriteSideEffectInstruction outNode |
179+ exists ( CallInstruction call , int indexIn , int indexOut |
180+ modelTaintToParameter ( call .getStaticCallTarget ( ) , indexIn , indexOut ) and
181+ i1 = call .getPositionalArgument ( indexIn ) and
182+ outNode .getIndex ( ) = indexOut and
183+ outNode .getPrimaryInstruction ( ) = call
184+ )
185+ )
186+ }
187+
188+ private predicate modelTaintToParameter ( Function f , int parameterIn , int parameterOut ) {
189+ exists ( FunctionInput modelIn , FunctionOutput modelOut |
190+ f .( TaintFunction ) .hasTaintFlow ( modelIn , modelOut ) and
191+ ( modelIn .isParameter ( parameterIn ) or modelIn .isParameterDeref ( parameterIn ) ) and
192+ modelOut .isParameterDeref ( parameterOut )
193+ )
194+ }
195+
196+ private predicate modelTaintToReturnValue ( Function f , int parameterIn ) {
197+ // Taint flow from parameter to return value
198+ exists ( FunctionInput modelIn , FunctionOutput modelOut |
199+ f .( TaintFunction ) .hasTaintFlow ( modelIn , modelOut ) and
200+ ( modelIn .isParameter ( parameterIn ) or modelIn .isParameterDeref ( parameterIn ) ) and
201+ ( modelOut .isReturnValue ( ) or modelOut .isReturnValueDeref ( ) )
202+ )
203+ or
204+ // Data flow (not taint flow) to where the return value points. For the time
205+ // being we will conflate pointers and objects in taint tracking.
206+ exists ( FunctionInput modelIn , FunctionOutput modelOut |
207+ f .( DataFlowFunction ) .hasDataFlow ( modelIn , modelOut ) and
208+ ( modelIn .isParameter ( parameterIn ) or modelIn .isParameterDeref ( parameterIn ) ) and
209+ modelOut .isReturnValueDeref ( )
210+ )
211+ or
212+ // Taint flow from one argument to another and data flow from an argument to a
213+ // return value. This happens in functions like `strcat` and `memcpy`. We
214+ // could model this flow in two separate steps, but that would add reverse
215+ // flow from the write side-effect to the call instruction, which may not be
216+ // desirable.
217+ exists ( int parameterMid , InParameter modelMid , OutReturnValue returnOut |
218+ modelTaintToParameter ( f , parameterIn , parameterMid ) and
219+ modelMid .isParameter ( parameterMid ) and
220+ f .( DataFlowFunction ) .hasDataFlow ( modelMid , returnOut )
221+ )
174222}
175223
176224private Element adjustedSink ( DataFlow:: Node sink ) {
0 commit comments