@@ -82,11 +82,14 @@ private import RangeAnalysisUtil
82
82
83
83
private module InvalidPointerToDerefBarrier {
84
84
private module BarrierConfig implements DataFlow:: ConfigSig {
85
- predicate isSource ( DataFlow:: Node source ) {
86
- // The sources is the same as in the sources for `InvalidPointerToDerefConfig`.
87
- invalidPointerToDerefSource ( _, _, source , _)
85
+ additional predicate isSource ( DataFlow:: Node source , PointerArithmeticInstruction pai ) {
86
+ invalidPointerToDerefSource ( _, pai , _, _) and
87
+ // source <= pai
88
+ bounded2 ( source .asInstruction ( ) , pai , any ( int d | d <= 0 ) )
88
89
}
89
90
91
+ predicate isSource ( DataFlow:: Node source ) { isSource ( source , _) }
92
+
90
93
additional predicate isSink (
91
94
DataFlow:: Node left , DataFlow:: Node right , IRGuardCondition g , int k , boolean testIsTrue
92
95
) {
@@ -99,59 +102,80 @@ private module InvalidPointerToDerefBarrier {
99
102
100
103
private module BarrierFlow = DataFlow:: Global< BarrierConfig > ;
101
104
102
- private int getInvalidPointerToDerefSourceDelta ( DataFlow:: Node node ) {
103
- exists ( DataFlow:: Node source |
104
- BarrierFlow:: flow ( source , node ) and
105
- invalidPointerToDerefSource ( _, _, source , result )
106
- )
107
- }
108
-
105
+ /**
106
+ * Holds if `g` ensures that `small < big + k` if `g` evaluates to `edge`.
107
+ *
108
+ * Additionally, it also holds that `big <= pai`. Thus, when `g` evaluates to `edge`
109
+ * it holds that `small < pai + k`.
110
+ */
109
111
private predicate operandGuardChecks (
110
- IRGuardCondition g , Operand left , Operand right , int state , boolean edge
112
+ PointerArithmeticInstruction pai , IRGuardCondition g , Operand small , int k , boolean edge
111
113
) {
112
- exists ( DataFlow:: Node nLeft , DataFlow:: Node nRight , int k |
113
- nRight .asOperand ( ) = right and
114
- nLeft .asOperand ( ) = left and
115
- BarrierConfig:: isSink ( nLeft , nRight , g , k , edge ) and
116
- state = getInvalidPointerToDerefSourceDelta ( nRight ) and
117
- k <= state
114
+ exists ( DataFlow:: Node source , DataFlow:: Node nSmall , DataFlow:: Node nBig |
115
+ nSmall .asOperand ( ) = small and
116
+ BarrierConfig:: isSource ( source , pai ) and
117
+ BarrierFlow:: flow ( source , nBig ) and
118
+ BarrierConfig:: isSink ( nSmall , nBig , g , k , edge )
118
119
)
119
120
}
120
121
121
- Instruction getABarrierInstruction ( int state ) {
122
- exists ( IRGuardCondition g , ValueNumber value , Operand use , boolean edge |
122
+ /**
123
+ * Gets an instruction `instr` such that `instr < pai`.
124
+ */
125
+ Instruction getABarrierInstruction ( PointerArithmeticInstruction pai ) {
126
+ exists ( IRGuardCondition g , ValueNumber value , Operand use , boolean edge , int delta , int k |
123
127
use = value .getAUse ( ) and
124
- operandGuardChecks ( pragma [ only_bind_into ] ( g ) , pragma [ only_bind_into ] ( use ) , _, state ,
125
- pragma [ only_bind_into ] ( edge ) ) and
126
- result = value .getAnInstruction ( ) and
127
- g .controls ( result .getBlock ( ) , edge )
128
+ operandGuardChecks ( pai , pragma [ only_bind_into ] ( g ) , pragma [ only_bind_into ] ( use ) ,
129
+ pragma [ only_bind_into ] ( k ) , pragma [ only_bind_into ] ( edge ) ) and
130
+ // result <= value + delta
131
+ bounded ( result , value .getAnInstruction ( ) , delta ) and
132
+ g .controls ( result .getBlock ( ) , edge ) and
133
+ delta + k <= 0
134
+ // combining the above we have: result < pai + k + delta <= pai
128
135
)
129
136
}
130
137
131
- DataFlow:: Node getABarrierNode ( ) { result .asOperand ( ) = getABarrierInstruction ( _) .getAUse ( ) }
138
+ DataFlow:: Node getABarrierNode ( PointerArithmeticInstruction pai ) {
139
+ result .asOperand ( ) = getABarrierInstruction ( pai ) .getAUse ( )
140
+ }
132
141
133
- pragma [ nomagic]
134
- IRBlock getABarrierBlock ( int state ) { result .getAnInstruction ( ) = getABarrierInstruction ( state ) }
142
+ /**
143
+ * Gets an instruction `instr` such that `instr < derefSource - deltaDerefSinkAndDerefAddress`
144
+ * for some `derefSource`.
145
+ */
146
+ AddressOperand getABarrierAddressOperand ( PointerArithmeticInstruction pai ) {
147
+ result .getDef ( ) = getABarrierInstruction ( pai )
148
+ }
135
149
}
136
150
137
151
/**
138
152
* A configuration to track flow from a pointer-arithmetic operation found
139
153
* by `AllocToInvalidPointerConfig` to a dereference of the pointer.
140
154
*/
141
- private module InvalidPointerToDerefConfig implements DataFlow:: ConfigSig {
142
- predicate isSource ( DataFlow:: Node source ) { invalidPointerToDerefSource ( _, _, source , _) }
155
+ private module InvalidPointerToDerefConfig implements DataFlow:: StateConfigSig {
156
+ class FlowState extends PointerArithmeticInstruction {
157
+ FlowState ( ) { invalidPointerToDerefSource ( _, this , _, _) }
158
+ }
159
+
160
+ predicate isSource ( DataFlow:: Node source , FlowState pai ) {
161
+ invalidPointerToDerefSource ( _, pai , source , _)
162
+ }
143
163
144
164
pragma [ inline]
145
- predicate isSink ( DataFlow:: Node sink ) { isInvalidPointerDerefSink ( sink , _, _, _) }
165
+ predicate isSink ( DataFlow:: Node sink ) { isInvalidPointerDerefSink ( sink , _, _, _, _) }
166
+
167
+ predicate isSink ( DataFlow:: Node sink , FlowState pai ) { none ( ) }
146
168
147
169
predicate isBarrier ( DataFlow:: Node node ) {
148
170
node = any ( DataFlow:: SsaPhiNode phi | not phi .isPhiRead ( ) ) .getAnInput ( true )
149
- or
150
- node = InvalidPointerToDerefBarrier:: getABarrierNode ( )
171
+ }
172
+
173
+ predicate isBarrier ( DataFlow:: Node node , FlowState pai ) {
174
+ node = InvalidPointerToDerefBarrier:: getABarrierNode ( pai )
151
175
}
152
176
}
153
177
154
- private import DataFlow:: Global < InvalidPointerToDerefConfig >
178
+ private import DataFlow:: GlobalWithState < InvalidPointerToDerefConfig >
155
179
156
180
/**
157
181
* Holds if `allocSource` is dataflow node that represents an allocation that flows to the
@@ -165,19 +189,14 @@ private predicate invalidPointerToDerefSource(
165
189
DataFlow:: Node allocSource , PointerArithmeticInstruction pai , DataFlow:: Node derefSource ,
166
190
int deltaDerefSourceAndPai
167
191
) {
168
- exists ( int rhsSizeDelta |
169
- // Note that `deltaDerefSourceAndPai` is not necessarily equal to `rhsSizeDelta`:
170
- // `rhsSizeDelta` is the constant offset added to the size of the allocation, and
171
- // `deltaDerefSourceAndPai` is the constant difference between the pointer-arithmetic instruction
172
- // and the instruction computing the address for which we will search for a dereference.
173
- AllocToInvalidPointer:: pointerAddInstructionHasBounds ( allocSource , pai , _, rhsSizeDelta ) and
174
- bounded2 ( derefSource .asInstruction ( ) , pai , deltaDerefSourceAndPai ) and
175
- deltaDerefSourceAndPai >= 0 and
176
- // TODO: This condition will go away once #13725 is merged, and then we can make `SizeBarrier`
177
- // private to `AllocationToInvalidPointer.qll`.
178
- not derefSource .getBasicBlock ( ) =
179
- AllocToInvalidPointer:: SizeBarrier:: getABarrierBlock ( rhsSizeDelta )
180
- )
192
+ // Note that `deltaDerefSourceAndPai` is not necessarily equal to `rhsSizeDelta`:
193
+ // `rhsSizeDelta` is the constant offset added to the size of the allocation, and
194
+ // `deltaDerefSourceAndPai` is the constant difference between the pointer-arithmetic instruction
195
+ // and the instruction computing the address for which we will search for a dereference.
196
+ AllocToInvalidPointer:: pointerAddInstructionHasBounds ( allocSource , pai , _, _) and
197
+ // derefSource <= pai + deltaDerefSourceAndPai
198
+ bounded2 ( derefSource .asInstruction ( ) , pai , deltaDerefSourceAndPai ) and
199
+ deltaDerefSourceAndPai >= 0
181
200
}
182
201
183
202
/**
@@ -187,15 +206,14 @@ private predicate invalidPointerToDerefSource(
187
206
*/
188
207
pragma [ inline]
189
208
private predicate isInvalidPointerDerefSink (
190
- DataFlow:: Node sink , Instruction i , string operation , int deltaDerefSinkAndDerefAddress
209
+ DataFlow:: Node sink , AddressOperand addr , Instruction i , string operation ,
210
+ int deltaDerefSinkAndDerefAddress
191
211
) {
192
- exists ( AddressOperand addr , Instruction s , IRBlock b |
212
+ exists ( Instruction s |
193
213
s = sink .asInstruction ( ) and
194
214
bounded ( addr .getDef ( ) , s , deltaDerefSinkAndDerefAddress ) and
195
215
deltaDerefSinkAndDerefAddress >= 0 and
196
- i .getAnOperand ( ) = addr and
197
- b = i .getBlock ( ) and
198
- not b = InvalidPointerToDerefBarrier:: getABarrierBlock ( deltaDerefSinkAndDerefAddress )
216
+ i .getAnOperand ( ) = addr
199
217
|
200
218
i instanceof StoreInstruction and
201
219
operation = "write"
@@ -221,9 +239,11 @@ private Instruction getASuccessor(Instruction instr) {
221
239
instr .getBlock ( ) .getASuccessor + ( ) = result .getBlock ( )
222
240
}
223
241
224
- private predicate paiForDereferenceSink ( PointerArithmeticInstruction pai , DataFlow:: Node derefSink ) {
242
+ private predicate paiForDereferenceSink (
243
+ PointerArithmeticInstruction pai , DataFlow:: Node derefSink , int deltaDerefSourceAndPai
244
+ ) {
225
245
exists ( DataFlow:: Node derefSource |
226
- invalidPointerToDerefSource ( _, pai , derefSource , _ ) and
246
+ invalidPointerToDerefSource ( _, pai , derefSource , deltaDerefSourceAndPai ) and
227
247
flow ( derefSource , derefSink )
228
248
)
229
249
}
@@ -235,13 +255,15 @@ private predicate paiForDereferenceSink(PointerArithmeticInstruction pai, DataFl
235
255
*/
236
256
private predicate derefSinkToOperation (
237
257
DataFlow:: Node derefSink , PointerArithmeticInstruction pai , DataFlow:: Node operation ,
238
- string description , int deltaDerefSinkAndDerefAddress
258
+ string description , int deltaDerefSourceAndPai , int deltaDerefSinkAndDerefAddress
239
259
) {
240
- exists ( Instruction operationInstr |
241
- paiForDereferenceSink ( pai , pragma [ only_bind_into ] ( derefSink ) ) and
242
- isInvalidPointerDerefSink ( derefSink , operationInstr , description , deltaDerefSinkAndDerefAddress ) and
260
+ exists ( Instruction operationInstr , AddressOperand addr |
261
+ paiForDereferenceSink ( pai , pragma [ only_bind_into ] ( derefSink ) , deltaDerefSourceAndPai ) and
262
+ isInvalidPointerDerefSink ( derefSink , addr , operationInstr , description ,
263
+ deltaDerefSinkAndDerefAddress ) and
243
264
operationInstr = getASuccessor ( derefSink .asInstruction ( ) ) and
244
- operation .asInstruction ( ) = operationInstr
265
+ operation .asInstruction ( ) = operationInstr and
266
+ not addr = InvalidPointerToDerefBarrier:: getABarrierAddressOperand ( pai )
245
267
)
246
268
}
247
269
@@ -260,7 +282,8 @@ predicate operationIsOffBy(
260
282
exists ( int deltaDerefSourceAndPai , int deltaDerefSinkAndDerefAddress |
261
283
invalidPointerToDerefSource ( allocation , pai , derefSource , deltaDerefSourceAndPai ) and
262
284
flow ( derefSource , derefSink ) and
263
- derefSinkToOperation ( derefSink , pai , operation , description , deltaDerefSinkAndDerefAddress ) and
285
+ derefSinkToOperation ( derefSink , pai , operation , description , deltaDerefSourceAndPai ,
286
+ deltaDerefSinkAndDerefAddress ) and
264
287
delta = deltaDerefSourceAndPai + deltaDerefSinkAndDerefAddress
265
288
)
266
289
}
0 commit comments