@@ -21,53 +21,69 @@ predicate localTaintStep(DataFlow::Node nodeFrom, DataFlow::Node nodeTo) {
2121 */
2222cached
2323predicate localAdditionalTaintStep ( DataFlow:: Node nodeFrom , DataFlow:: Node nodeTo ) {
24- localInstructionTaintStep ( nodeFrom .asInstruction ( ) , nodeTo .asInstruction ( ) )
24+ operandToInstructionTaintStep ( nodeFrom .asOperand ( ) , nodeTo .asInstruction ( ) )
2525 or
26- modeledTaintStep ( nodeFrom , nodeTo )
26+ instructionToOperandTaintStep ( nodeFrom .asInstruction ( ) , nodeTo .asOperand ( ) )
27+ }
28+
29+ private predicate instructionToOperandTaintStep ( Instruction fromInstr , Operand toOperand ) {
30+ // Propagate flow from the definition of an operand to the operand, even when the overlap is inexact.
31+ // We only do this in certain cases:
32+ // 1. The instruction's result must not be conflated, and
33+ // 2. The instruction's result type is one the types where we expect element-to-object flow. Currently
34+ // this is array types and union types. This matches the other two cases of element-to-object flow in
35+ // `DefaultTaintTracking`.
36+ toOperand .getAnyDef ( ) = fromInstr and
37+ not fromInstr .isResultConflated ( ) and
38+ (
39+ fromInstr .getResultType ( ) instanceof ArrayType or
40+ fromInstr .getResultType ( ) instanceof Union
41+ )
42+ or
43+ exists ( ReadSideEffectInstruction readInstr |
44+ fromInstr = readInstr .getArgumentDef ( ) and
45+ toOperand = readInstr .getSideEffectOperand ( )
46+ )
47+ or
48+ toOperand .( LoadOperand ) .getAnyDef ( ) = fromInstr
2749}
2850
2951/**
3052 * Holds if taint propagates from `nodeFrom` to `nodeTo` in exactly one local
3153 * (intra-procedural) step.
3254 */
33- private predicate localInstructionTaintStep ( Instruction nodeFrom , Instruction nodeTo ) {
55+ private predicate operandToInstructionTaintStep ( Operand opFrom , Instruction instrTo ) {
3456 // Taint can flow through expressions that alter the value but preserve
3557 // more than one bit of it _or_ expressions that follow data through
3658 // pointer indirections.
37- nodeTo .getAnOperand ( ) . getAnyDef ( ) = nodeFrom and
59+ instrTo .getAnOperand ( ) = opFrom and
3860 (
39- nodeTo instanceof ArithmeticInstruction
61+ instrTo instanceof ArithmeticInstruction
4062 or
41- nodeTo instanceof BitwiseInstruction
63+ instrTo instanceof BitwiseInstruction
4264 or
43- nodeTo instanceof PointerArithmeticInstruction
65+ instrTo instanceof PointerArithmeticInstruction
4466 or
45- nodeTo instanceof FieldAddressInstruction
67+ instrTo instanceof FieldAddressInstruction
4668 or
4769 // The `CopyInstruction` case is also present in non-taint data flow, but
4870 // that uses `getDef` rather than `getAnyDef`. For taint, we want flow
4971 // from a definition of `myStruct` to a `myStruct.myField` expression.
50- nodeTo instanceof CopyInstruction
72+ instrTo instanceof CopyInstruction
5173 )
5274 or
53- nodeTo .( LoadInstruction ) .getSourceAddress ( ) = nodeFrom
54- or
55- // Flow through partial reads of arrays and unions
56- nodeTo .( LoadInstruction ) .getSourceValueOperand ( ) .getAnyDef ( ) = nodeFrom and
57- not nodeFrom .isResultConflated ( ) and
58- (
59- nodeFrom .getResultType ( ) instanceof ArrayType or
60- nodeFrom .getResultType ( ) instanceof Union
61- )
75+ instrTo .( LoadInstruction ) .getSourceAddressOperand ( ) = opFrom
6276 or
6377 // Flow from an element to an array or union that contains it.
64- nodeTo .( ChiInstruction ) .getPartial ( ) = nodeFrom and
65- not nodeTo .isResultConflated ( ) and
66- exists ( Type t | nodeTo .getResultLanguageType ( ) .hasType ( t , false ) |
78+ instrTo .( ChiInstruction ) .getPartialOperand ( ) = opFrom and
79+ not instrTo .isResultConflated ( ) and
80+ exists ( Type t | instrTo .getResultLanguageType ( ) .hasType ( t , false ) |
6781 t instanceof Union
6882 or
6983 t instanceof ArrayType
7084 )
85+ or
86+ modeledTaintStep ( opFrom , instrTo )
7187}
7288
7389/**
@@ -110,17 +126,19 @@ predicate defaultTaintSanitizer(DataFlow::Node node) { none() }
110126 * Holds if taint can flow from `instrIn` to `instrOut` through a call to a
111127 * modeled function.
112128 */
113- predicate modeledTaintStep ( DataFlow :: Node nodeIn , DataFlow :: Node nodeOut ) {
129+ predicate modeledTaintStep ( Operand nodeIn , Instruction nodeOut ) {
114130 exists ( CallInstruction call , TaintFunction func , FunctionInput modelIn , FunctionOutput modelOut |
115131 (
116132 nodeIn = callInput ( call , modelIn )
117133 or
118134 exists ( int n |
119- modelIn .isParameterDeref ( n ) and
120- nodeIn = callInput ( call , any ( InParameter inParam | inParam .getIndex ( ) = n ) )
135+ modelIn .isParameterDerefOrQualifierObject ( n ) and
136+ if n = - 1
137+ then nodeIn = callInput ( call , any ( InQualifierObject inQualifier ) )
138+ else nodeIn = callInput ( call , any ( InParameter inParam | inParam .getIndex ( ) = n ) )
121139 )
122140 ) and
123- nodeOut . asInstruction ( ) = callOutput ( call , modelOut ) and
141+ nodeOut = callOutput ( call , modelOut ) and
124142 call .getStaticCallTarget ( ) = func and
125143 func .hasTaintFlow ( modelIn , modelOut )
126144 )
@@ -135,7 +153,7 @@ predicate modeledTaintStep(DataFlow::Node nodeIn, DataFlow::Node nodeOut) {
135153 int indexMid , InParameter modelMidIn , OutReturnValue modelOut
136154 |
137155 nodeIn = callInput ( call , modelIn ) and
138- nodeOut . asInstruction ( ) = callOutput ( call , modelOut ) and
156+ nodeOut = callOutput ( call , modelOut ) and
139157 call .getStaticCallTarget ( ) = func and
140158 func .( TaintFunction ) .hasTaintFlow ( modelIn , modelMidOut ) and
141159 func .( DataFlowFunction ) .hasDataFlow ( modelMidIn , modelOut ) and
@@ -149,15 +167,15 @@ predicate modeledTaintStep(DataFlow::Node nodeIn, DataFlow::Node nodeOut) {
149167 CallInstruction call , ReadSideEffectInstruction read , Function func , FunctionInput modelIn ,
150168 FunctionOutput modelOut
151169 |
152- read .getSideEffectOperand ( ) = callInput ( call , modelIn ) . asOperand ( ) and
153- read .getArgumentDef ( ) = nodeIn .asInstruction ( ) and
170+ read .getSideEffectOperand ( ) = callInput ( call , modelIn ) and
171+ read .getArgumentDef ( ) = nodeIn .getDef ( ) and
154172 not read .getSideEffect ( ) .isResultModeled ( ) and
155173 call .getStaticCallTarget ( ) = func and
156174 (
157175 func .( DataFlowFunction ) .hasDataFlow ( modelIn , modelOut )
158176 or
159177 func .( TaintFunction ) .hasTaintFlow ( modelIn , modelOut )
160178 ) and
161- nodeOut . asInstruction ( ) = callOutput ( call , modelOut )
179+ nodeOut = callOutput ( call , modelOut )
162180 )
163181}
0 commit comments