@@ -18,10 +18,32 @@ private predicate predictableInstruction(Instruction instr) {
1818 predictableInstruction ( instr .( UnaryInstruction ) .getUnary ( ) )
1919}
2020
21+ private predicate userInputInstruction ( Instruction instr ) {
22+ exists ( CallInstruction ci , WriteSideEffectInstruction wsei |
23+ userInputArgument ( ci .getConvertedResultExpression ( ) , wsei .getIndex ( ) ) and
24+ instr = wsei and
25+ wsei .getPrimaryInstruction ( ) = ci
26+ )
27+ or
28+ userInputReturned ( instr .getConvertedResultExpression ( ) )
29+ or
30+ instr .getConvertedResultExpression ( ) instanceof EnvironmentRead
31+ or
32+ instr
33+ .( LoadInstruction )
34+ .getSourceAddress ( )
35+ .( VariableAddressInstruction )
36+ .getASTVariable ( )
37+ .hasName ( "argv" ) and
38+ instr .getEnclosingFunction ( ) .hasGlobalName ( "main" )
39+ }
40+
2141private class DefaultTaintTrackingCfg extends DataFlow:: Configuration {
2242 DefaultTaintTrackingCfg ( ) { this = "DefaultTaintTrackingCfg" }
2343
24- override predicate isSource ( DataFlow:: Node source ) { isUserInput ( source .asExpr ( ) , _) }
44+ override predicate isSource ( DataFlow:: Node source ) {
45+ userInputInstruction ( source .asInstruction ( ) )
46+ }
2547
2648 override predicate isSink ( DataFlow:: Node sink ) { any ( ) }
2749
@@ -87,6 +109,10 @@ private predicate instructionTaintStep(Instruction i1, Instruction i2) {
87109 // This is part of the translation of `a[i]`, where we want taint to flow
88110 // from `a`.
89111 i2 .( PointerAddInstruction ) .getLeft ( ) = i1
112+ or
113+ i2 .( ChiInstruction ) .getPartial ( ) = i1
114+ or
115+ i2 .( ChiInstruction ) .getTotal ( ) = i1
90116 // TODO: Flow from argument to return of known functions: Port missing parts
91117 // of `returnArgument` to the `interfaces.Taint` and `interfaces.DataFlow`
92118 // libraries.
@@ -102,6 +128,8 @@ private predicate instructionTaintStep(Instruction i1, Instruction i2) {
102128predicate tainted ( Expr source , Element tainted ) {
103129 exists ( DefaultTaintTrackingCfg cfg , DataFlow:: Node sink |
104130 cfg .hasFlow ( DataFlow:: exprNode ( source ) , sink )
131+ or
132+ cfg .hasFlow ( DataFlow:: definitionByReferenceNode ( source ) , sink )
105133 |
106134 // TODO: is it more appropriate to use asConvertedExpr here and avoid
107135 // `getConversion*`? Or will that cause us to miss some cases where there's
@@ -128,6 +156,23 @@ predicate tainted(Expr source, Element tainted) {
128156 // For compatibility, send flow into a `NotExpr` even if it's part of a
129157 // short-circuiting condition and thus might get skipped.
130158 tainted .( NotExpr ) .getOperand ( ) = sink .asExpr ( )
159+ or
160+ // For compatibility, send flow from argument read side effects to their
161+ // corresponding argument expression
162+ exists ( IndirectReadSideEffectInstruction read |
163+ read .getAnOperand ( ) .( SideEffectOperand ) .getAnyDef ( ) = sink .asInstruction ( ) and
164+ read .getArgumentDef ( ) .getUnconvertedResultExpression ( ) = tainted
165+ )
166+ or
167+ exists ( BufferReadSideEffectInstruction read |
168+ read .getAnOperand ( ) .( SideEffectOperand ) .getAnyDef ( ) = sink .asInstruction ( ) and
169+ read .getArgumentDef ( ) .getUnconvertedResultExpression ( ) = tainted
170+ )
171+ or
172+ exists ( SizedBufferReadSideEffectInstruction read |
173+ read .getAnOperand ( ) .( SideEffectOperand ) .getAnyDef ( ) = sink .asInstruction ( ) and
174+ read .getArgumentDef ( ) .getUnconvertedResultExpression ( ) = tainted
175+ )
131176 )
132177}
133178
0 commit comments