@@ -18,6 +18,7 @@ import semmle.code.cpp.security.FlowSources
18
18
import semmle.code.cpp.ir.dataflow.TaintTracking
19
19
import semmle.code.cpp.rangeanalysis.RangeAnalysisUtils
20
20
import DataFlow:: PathGraph
21
+ import semmle.code.cpp.security.Security
21
22
22
23
predicate hasUpperBound ( VariableAccess offsetExpr ) {
23
24
exists ( BasicBlock controlled , StackVariable offsetVar , SsaDefinition def |
@@ -55,6 +56,15 @@ predicate nodeIsBarrierEqualityCandidate(DataFlow::Node node, Operand access, Va
55
56
56
57
predicate isFlowSource ( FlowSource source , string sourceType ) { sourceType = source .getSourceType ( ) }
57
58
59
+ predicate predictableInstruction ( Instruction instr ) {
60
+ instr instanceof ConstantInstruction
61
+ or
62
+ instr instanceof StringConstantInstruction
63
+ or
64
+ // This could be a conversion on a string literal
65
+ predictableInstruction ( instr .( UnaryInstruction ) .getUnary ( ) )
66
+ }
67
+
58
68
class ImproperArrayIndexValidationConfig extends TaintTracking:: Configuration {
59
69
ImproperArrayIndexValidationConfig ( ) { this = "ImproperArrayIndexValidationConfig" }
60
70
@@ -63,6 +73,8 @@ class ImproperArrayIndexValidationConfig extends TaintTracking::Configuration {
63
73
override predicate isSanitizer ( DataFlow:: Node node ) {
64
74
hasUpperBound ( node .asExpr ( ) )
65
75
or
76
+ // These barriers are ported from `DefaultTaintTracking` because this query is quite noisy
77
+ // otherwise.
66
78
exists ( Variable checkedVar |
67
79
readsVariable ( node .asInstruction ( ) , checkedVar ) and
68
80
hasUpperBoundsCheck ( checkedVar )
@@ -72,6 +84,27 @@ class ImproperArrayIndexValidationConfig extends TaintTracking::Configuration {
72
84
readsVariable ( access .getDef ( ) , checkedVar ) and
73
85
nodeIsBarrierEqualityCandidate ( node , access , checkedVar )
74
86
)
87
+ or
88
+ // Don't use dataflow into binary instructions if both operands are unpredictable
89
+ exists ( BinaryInstruction iTo |
90
+ iTo = node .asInstruction ( ) and
91
+ not predictableInstruction ( iTo .getLeft ( ) ) and
92
+ not predictableInstruction ( iTo .getRight ( ) ) and
93
+ // propagate taint from either the pointer or the offset, regardless of predictability
94
+ not iTo instanceof PointerArithmeticInstruction
95
+ )
96
+ or
97
+ // don't use dataflow through calls to pure functions if two or more operands
98
+ // are unpredictable
99
+ exists ( Instruction iFrom1 , Instruction iFrom2 , CallInstruction iTo |
100
+ iTo = node .asInstruction ( ) and
101
+ isPureFunction ( iTo .getStaticCallTarget ( ) .getName ( ) ) and
102
+ iFrom1 = iTo .getAnArgument ( ) and
103
+ iFrom2 = iTo .getAnArgument ( ) and
104
+ not predictableInstruction ( iFrom1 ) and
105
+ not predictableInstruction ( iFrom2 ) and
106
+ iFrom1 != iFrom2
107
+ )
75
108
}
76
109
77
110
override predicate isSink ( DataFlow:: Node sink ) {
0 commit comments