@@ -21,31 +21,19 @@ private predicate predictableInstruction(Instruction instr) {
2121 predictableInstruction ( instr .( UnaryInstruction ) .getUnary ( ) )
2222}
2323
24+ private DataFlow:: Node getNodeForSource ( Expr source ) {
25+ isUserInput ( source , _) and
26+ (
27+ result = DataFlow:: exprNode ( source )
28+ or
29+ result = DataFlow:: definitionByReferenceNode ( source )
30+ )
31+ }
32+
2433private class DefaultTaintTrackingCfg extends DataFlow:: Configuration {
2534 DefaultTaintTrackingCfg ( ) { this = "DefaultTaintTrackingCfg" }
2635
27- override predicate isSource ( DataFlow:: Node source ) {
28- exists ( CallInstruction ci , WriteSideEffectInstruction wsei |
29- userInputArgument ( ci .getConvertedResultExpression ( ) , wsei .getIndex ( ) ) and
30- source .asInstruction ( ) = wsei and
31- wsei .getPrimaryInstruction ( ) = ci
32- )
33- or
34- userInputReturned ( source .asExpr ( ) )
35- or
36- isUserInput ( source .asExpr ( ) , _)
37- or
38- source .asExpr ( ) instanceof EnvironmentRead
39- or
40- source
41- .asInstruction ( )
42- .( LoadInstruction )
43- .getSourceAddress ( )
44- .( VariableAddressInstruction )
45- .getASTVariable ( )
46- .hasName ( "argv" ) and
47- source .asInstruction ( ) .getEnclosingFunction ( ) .hasGlobalName ( "main" )
48- }
36+ override predicate isSource ( DataFlow:: Node source ) { source = getNodeForSource ( _) }
4937
5038 override predicate isSink ( DataFlow:: Node sink ) { any ( ) }
5139
@@ -59,7 +47,7 @@ private class DefaultTaintTrackingCfg extends DataFlow::Configuration {
5947private class ToGlobalVarTaintTrackingCfg extends DataFlow:: Configuration {
6048 ToGlobalVarTaintTrackingCfg ( ) { this = "GlobalVarTaintTrackingCfg" }
6149
62- override predicate isSource ( DataFlow:: Node source ) { isUserInput ( source . asExpr ( ) , _) }
50+ override predicate isSource ( DataFlow:: Node source ) { source = getNodeForSource ( _) }
6351
6452 override predicate isSink ( DataFlow:: Node sink ) {
6553 exists ( GlobalOrNamespaceVariable gv | writesVariable ( sink .asInstruction ( ) , gv ) )
@@ -163,6 +151,22 @@ private predicate instructionTaintStep(Instruction i1, Instruction i2) {
163151 // from `a`.
164152 i2 .( PointerAddInstruction ) .getLeft ( ) = i1
165153 or
154+ // Until we have from through indirections across calls, we'll take flow out
155+ // of the parameter and into its indirection.
156+ exists ( IRFunction f , Parameter parameter |
157+ i1 = getInitializeParameter ( f , parameter ) and
158+ i2 = getInitializeIndirection ( f , parameter )
159+ )
160+ or
161+ // Until we have flow through indirections across calls, we'll take flow out
162+ // of the indirection and into the argument.
163+ // When we get proper flow through indirections across calls, this code can be
164+ // moved to `adjusedSink` or possibly into the `DataFlow::ExprNode` class.
165+ exists ( ReadSideEffectInstruction read |
166+ read .getAnOperand ( ) .( SideEffectOperand ) .getAnyDef ( ) = i1 and
167+ read .getArgumentDef ( ) = i2
168+ )
169+ or
166170 // Flow from argument to return value
167171 i2 =
168172 any ( CallInstruction call |
@@ -188,6 +192,33 @@ private predicate instructionTaintStep(Instruction i1, Instruction i2) {
188192 )
189193}
190194
195+ pragma [ noinline]
196+ private InitializeIndirectionInstruction getInitializeIndirection ( IRFunction f , Parameter p ) {
197+ result .getParameter ( ) = p and
198+ result .getEnclosingIRFunction ( ) = f
199+ }
200+
201+ pragma [ noinline]
202+ private InitializeParameterInstruction getInitializeParameter ( IRFunction f , Parameter p ) {
203+ result .getParameter ( ) = p and
204+ result .getEnclosingIRFunction ( ) = f
205+ }
206+
207+ /**
208+ * Get an instruction that goes into argument `argumentIndex` of `call`. This
209+ * can be either directly or through one pointer indirection.
210+ */
211+ private Instruction getACallArgumentOrIndirection ( CallInstruction call , int argumentIndex ) {
212+ result = call .getPositionalArgument ( argumentIndex )
213+ or
214+ exists ( ReadSideEffectInstruction readSE |
215+ // TODO: why are read side effect operands imprecise?
216+ result = readSE .getSideEffectOperand ( ) .getAnyDef ( ) and
217+ readSE .getPrimaryInstruction ( ) = call and
218+ readSE .getIndex ( ) = argumentIndex
219+ )
220+ }
221+
191222private predicate modelTaintToParameter ( Function f , int parameterIn , int parameterOut ) {
192223 exists ( FunctionInput modelIn , FunctionOutput modelOut |
193224 (
@@ -270,31 +301,11 @@ private Element adjustedSink(DataFlow::Node sink) {
270301 // For compatibility, send flow into a `NotExpr` even if it's part of a
271302 // short-circuiting condition and thus might get skipped.
272303 result .( NotExpr ) .getOperand ( ) = sink .asExpr ( )
273- or
274- // For compatibility, send flow from argument read side effects to their
275- // corresponding argument expression
276- exists ( IndirectReadSideEffectInstruction read |
277- read .getAnOperand ( ) .( SideEffectOperand ) .getAnyDef ( ) = sink .asInstruction ( ) and
278- read .getArgumentDef ( ) .getUnconvertedResultExpression ( ) = result
279- )
280- or
281- exists ( BufferReadSideEffectInstruction read |
282- read .getAnOperand ( ) .( SideEffectOperand ) .getAnyDef ( ) = sink .asInstruction ( ) and
283- read .getArgumentDef ( ) .getUnconvertedResultExpression ( ) = result
284- )
285- or
286- exists ( SizedBufferReadSideEffectInstruction read |
287- read .getAnOperand ( ) .( SideEffectOperand ) .getAnyDef ( ) = sink .asInstruction ( ) and
288- read .getArgumentDef ( ) .getUnconvertedResultExpression ( ) = result
289- )
290304}
291305
292306predicate tainted ( Expr source , Element tainted ) {
293307 exists ( DefaultTaintTrackingCfg cfg , DataFlow:: Node sink |
294- cfg .hasFlow ( DataFlow:: exprNode ( source ) , sink )
295- or
296- cfg .hasFlow ( DataFlow:: definitionByReferenceNode ( source ) , sink )
297- |
308+ cfg .hasFlow ( getNodeForSource ( source ) , sink ) and
298309 tainted = adjustedSink ( sink )
299310 )
300311}
@@ -307,7 +318,7 @@ predicate taintedIncludingGlobalVars(Expr source, Element tainted, string global
307318 ToGlobalVarTaintTrackingCfg toCfg , FromGlobalVarTaintTrackingCfg fromCfg , DataFlow:: Node store ,
308319 GlobalOrNamespaceVariable global , DataFlow:: Node load , DataFlow:: Node sink
309320 |
310- toCfg .hasFlow ( DataFlow :: exprNode ( source ) , store ) and
321+ toCfg .hasFlow ( getNodeForSource ( source ) , store ) and
311322 store
312323 .asInstruction ( )
313324 .( StoreInstruction )
0 commit comments