@@ -19,10 +19,32 @@ private predicate predictableInstruction(Instruction instr) {
1919 predictableInstruction ( instr .( UnaryInstruction ) .getUnary ( ) )
2020}
2121
22+ private predicate userInputInstruction ( Instruction instr ) {
23+ exists ( CallInstruction ci , WriteSideEffectInstruction wsei |
24+ userInputArgument ( ci .getConvertedResultExpression ( ) , wsei .getIndex ( ) ) and
25+ instr = wsei and
26+ wsei .getPrimaryInstruction ( ) = ci
27+ )
28+ or
29+ userInputReturned ( instr .getConvertedResultExpression ( ) )
30+ or
31+ instr .getConvertedResultExpression ( ) instanceof EnvironmentRead
32+ or
33+ instr
34+ .( LoadInstruction )
35+ .getSourceAddress ( )
36+ .( VariableAddressInstruction )
37+ .getASTVariable ( )
38+ .hasName ( "argv" ) and
39+ instr .getEnclosingFunction ( ) .hasGlobalName ( "main" )
40+ }
41+
2242private class DefaultTaintTrackingCfg extends DataFlow:: Configuration {
2343 DefaultTaintTrackingCfg ( ) { this = "DefaultTaintTrackingCfg" }
2444
25- override predicate isSource ( DataFlow:: Node source ) { isUserInput ( source .asExpr ( ) , _) }
45+ override predicate isSource ( DataFlow:: Node source ) {
46+ userInputInstruction ( source .asInstruction ( ) )
47+ }
2648
2749 override predicate isSink ( DataFlow:: Node sink ) { any ( ) }
2850
@@ -135,6 +157,8 @@ private predicate instructionTaintStep(Instruction i1, Instruction i2) {
135157 // This is part of the translation of `a[i]`, where we want taint to flow
136158 // from `a`.
137159 i2 .( PointerAddInstruction ) .getLeft ( ) = i1
160+ // TODO: robust Chi handling
161+ //
138162 // TODO: Flow from argument to return of known functions: Port missing parts
139163 // of `returnArgument` to the `interfaces.Taint` and `interfaces.DataFlow`
140164 // libraries.
@@ -176,11 +200,30 @@ private Element adjustedSink(DataFlow::Node sink) {
176200 // For compatibility, send flow into a `NotExpr` even if it's part of a
177201 // short-circuiting condition and thus might get skipped.
178202 result .( NotExpr ) .getOperand ( ) = sink .asExpr ( )
203+ or
204+ // For compatibility, send flow from argument read side effects to their
205+ // corresponding argument expression
206+ exists ( IndirectReadSideEffectInstruction read |
207+ read .getAnOperand ( ) .( SideEffectOperand ) .getAnyDef ( ) = sink .asInstruction ( ) and
208+ read .getArgumentDef ( ) .getUnconvertedResultExpression ( ) = result
209+ )
210+ or
211+ exists ( BufferReadSideEffectInstruction read |
212+ read .getAnOperand ( ) .( SideEffectOperand ) .getAnyDef ( ) = sink .asInstruction ( ) and
213+ read .getArgumentDef ( ) .getUnconvertedResultExpression ( ) = result
214+ )
215+ or
216+ exists ( SizedBufferReadSideEffectInstruction read |
217+ read .getAnOperand ( ) .( SideEffectOperand ) .getAnyDef ( ) = sink .asInstruction ( ) and
218+ read .getArgumentDef ( ) .getUnconvertedResultExpression ( ) = result
219+ )
179220}
180221
181222predicate tainted ( Expr source , Element tainted ) {
182223 exists ( DefaultTaintTrackingCfg cfg , DataFlow:: Node sink |
183224 cfg .hasFlow ( DataFlow:: exprNode ( source ) , sink )
225+ or
226+ cfg .hasFlow ( DataFlow:: definitionByReferenceNode ( source ) , sink )
184227 |
185228 tainted = adjustedSink ( sink )
186229 )
0 commit comments