11import cpp
22import semmle.code.cpp.security.Security
33private import semmle.code.cpp.ir.dataflow.DataFlow
4+ private import semmle.code.cpp.ir.dataflow.DataFlow2
45private import semmle.code.cpp.ir.IR
56private import semmle.code.cpp.ir.dataflow.internal.DataFlowDispatch as Dispatch
67
@@ -30,10 +31,7 @@ private class DefaultTaintTrackingCfg extends DataFlow::Configuration {
3031 }
3132
3233 override predicate isBarrier ( DataFlow:: Node node ) {
33- exists ( Variable checkedVar |
34- accessesVariable ( node .asInstruction ( ) , checkedVar ) and
35- hasUpperBoundsCheck ( checkedVar )
36- )
34+ nodeIsBarrier ( node )
3735 }
3836}
3937
@@ -44,37 +42,34 @@ private class ToGlobalVarTaintTrackingCfg extends DataFlow::Configuration {
4442
4543 override predicate isSink ( DataFlow:: Node sink ) {
4644 exists ( GlobalOrNamespaceVariable gv |
47- accessesVariable ( sink .asInstruction ( ) , gv ) and
48- sink .asInstruction ( ) instanceof StoreInstruction
45+ writesVariable ( sink .asInstruction ( ) , gv )
4946 )
5047 }
5148
5249 override predicate isAdditionalFlowStep ( DataFlow:: Node n1 , DataFlow:: Node n2 ) {
5350 instructionTaintStep ( n1 .asInstruction ( ) , n2 .asInstruction ( ) )
5451 or
5552 exists ( StoreInstruction i1 , LoadInstruction i2 , GlobalOrNamespaceVariable gv |
56- accessesVariable ( i1 , gv ) and
57- accessesVariable ( i2 , gv ) and
53+ writesVariable ( i1 , gv ) and
54+ readsVariable ( i2 , gv ) and
5855 i1 = n1 .asInstruction ( ) and
5956 i2 = n2 .asInstruction ( )
6057 )
6158 }
6259
6360 override predicate isBarrier ( DataFlow:: Node node ) {
64- exists ( Variable checkedVar |
65- accessesVariable ( node .asInstruction ( ) , checkedVar ) and
66- hasUpperBoundsCheck ( checkedVar )
67- )
61+ nodeIsBarrier ( node )
6862 }
6963}
7064
71- private class FromGlobalVarTaintTrackingCfg extends DataFlow :: Configuration {
65+ private class FromGlobalVarTaintTrackingCfg extends DataFlow2 :: Configuration {
7266 FromGlobalVarTaintTrackingCfg ( ) { this = "FromGlobalVarTaintTrackingCfg" }
7367
7468 override predicate isSource ( DataFlow:: Node source ) {
75- exists ( GlobalOrNamespaceVariable gv |
76- accessesVariable ( source .asInstruction ( ) , gv ) and
77- source .asInstruction ( ) instanceof LoadInstruction
69+ exists ( ToGlobalVarTaintTrackingCfg other , DataFlow:: Node prevSink , GlobalOrNamespaceVariable gv |
70+ other .hasFlowTo ( prevSink ) and
71+ writesVariable ( prevSink .asInstruction ( ) , gv ) and
72+ readsVariable ( source .asInstruction ( ) , gv )
7873 )
7974 }
8075
@@ -85,19 +80,16 @@ private class FromGlobalVarTaintTrackingCfg extends DataFlow::Configuration {
8580 }
8681
8782 override predicate isBarrier ( DataFlow:: Node node ) {
88- exists ( Variable checkedVar |
89- accessesVariable ( node .asInstruction ( ) , checkedVar ) and
90- hasUpperBoundsCheck ( checkedVar )
91- )
83+ nodeIsBarrier ( node )
9284 }
9385}
9486
95- private predicate accessesVariable ( CopyInstruction copy , Variable var ) {
96- exists ( VariableAddressInstruction va | va .getASTVariable ( ) = var |
97- copy . ( StoreInstruction ) . getDestinationAddress ( ) = va
98- or
99- copy . ( LoadInstruction ) . getSourceAddress ( ) = va
100- )
87+ private predicate readsVariable ( LoadInstruction load , Variable var ) {
88+ load . getSourceAddress ( ) . ( VariableAddressInstruction ) .getASTVariable ( ) = var
89+ }
90+
91+ private predicate writesVariable ( StoreInstruction store , Variable var ) {
92+ store . getDestinationAddress ( ) . ( VariableAddressInstruction ) . getASTVariable ( ) = var
10193}
10294
10395/**
@@ -117,6 +109,13 @@ private predicate hasUpperBoundsCheck(Variable var) {
117109 )
118110}
119111
112+ private predicate nodeIsBarrier ( DataFlow:: Node node ) {
113+ exists ( Variable checkedVar |
114+ readsVariable ( node .asInstruction ( ) , checkedVar ) and
115+ hasUpperBoundsCheck ( checkedVar )
116+ )
117+ }
118+
120119private predicate instructionTaintStep ( Instruction i1 , Instruction i2 ) {
121120 // Expressions computed from tainted data are also tainted
122121 i2 = any ( CallInstruction call |
@@ -173,7 +172,10 @@ private Element adjustedSink(DataFlow::Node sink) {
173172 // Load or Store of that variable.
174173 exists ( CopyInstruction copy |
175174 copy .getSourceValue ( ) = sink .asInstruction ( ) and
176- accessesVariable ( copy , result ) and
175+ (
176+ readsVariable ( copy , result ) or
177+ writesVariable ( copy , result )
178+ ) and
177179 not hasUpperBoundsCheck ( result )
178180 )
179181 or
@@ -192,28 +194,23 @@ predicate tainted(Expr source, Element tainted) {
192194
193195predicate taintedIncludingGlobalVars ( Expr source , Element tainted , string globalVar ) {
194196 tainted ( source , tainted ) and
195- // TODO: Find a way to emulate how `security.TaintTracking` reports the last
196- // global variable that taint has passed through. Also make sure we emulate
197- // its behavior for interprocedural flow through globals.
198197 globalVar = ""
199198 or
200199 exists (
201200 ToGlobalVarTaintTrackingCfg toCfg , FromGlobalVarTaintTrackingCfg fromCfg , DataFlow:: Node store ,
202201 GlobalOrNamespaceVariable global , DataFlow:: Node load , DataFlow:: Node sink
203202 |
204203 toCfg .hasFlow ( DataFlow:: exprNode ( source ) , store ) and
205- accessesVariable ( store .asInstruction ( ) , global ) and
206- accessesVariable ( load .asInstruction ( ) , global ) and
204+ store .asInstruction ( ) . ( StoreInstruction ) . getDestinationAddress ( ) . ( VariableAddressInstruction ) . getASTVariable ( ) = global and
205+ load .asInstruction ( ) . ( LoadInstruction ) . getSourceAddress ( ) . ( VariableAddressInstruction ) . getASTVariable ( ) = global and
207206 fromCfg .hasFlow ( load , sink ) and
208207 tainted = adjustedSink ( sink ) and
209208 global = globalVarFromId ( globalVar )
210209 )
211210}
212211
213212GlobalOrNamespaceVariable globalVarFromId ( string id ) {
214- if result instanceof NamespaceVariable
215- then id = result .getNamespace ( ) + "::" + result .getName ( )
216- else id = result .getName ( )
213+ id = result .getQualifiedName ( )
217214}
218215
219216Function resolveCall ( Call call ) {
0 commit comments