@@ -18,6 +18,7 @@ import semmle.code.cpp.security.FlowSources
1818import semmle.code.cpp.ir.dataflow.TaintTracking
1919import semmle.code.cpp.rangeanalysis.RangeAnalysisUtils
2020import DataFlow:: PathGraph
21+ import semmle.code.cpp.security.Security
2122
2223predicate hasUpperBound ( VariableAccess offsetExpr ) {
2324 exists ( BasicBlock controlled , StackVariable offsetVar , SsaDefinition def |
@@ -55,6 +56,15 @@ predicate nodeIsBarrierEqualityCandidate(DataFlow::Node node, Operand access, Va
5556
5657predicate isFlowSource ( FlowSource source , string sourceType ) { sourceType = source .getSourceType ( ) }
5758
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+
5868class ImproperArrayIndexValidationConfig extends TaintTracking:: Configuration {
5969 ImproperArrayIndexValidationConfig ( ) { this = "ImproperArrayIndexValidationConfig" }
6070
@@ -63,6 +73,8 @@ class ImproperArrayIndexValidationConfig extends TaintTracking::Configuration {
6373 override predicate isSanitizer ( DataFlow:: Node node ) {
6474 hasUpperBound ( node .asExpr ( ) )
6575 or
76+ // These barriers are ported from `DefaultTaintTracking` because this query is quite noisy
77+ // otherwise.
6678 exists ( Variable checkedVar |
6779 readsVariable ( node .asInstruction ( ) , checkedVar ) and
6880 hasUpperBoundsCheck ( checkedVar )
@@ -72,6 +84,27 @@ class ImproperArrayIndexValidationConfig extends TaintTracking::Configuration {
7284 readsVariable ( access .getDef ( ) , checkedVar ) and
7385 nodeIsBarrierEqualityCandidate ( node , access , checkedVar )
7486 )
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+ )
75108 }
76109
77110 override predicate isSink ( DataFlow:: Node sink ) {
0 commit comments