@@ -82,11 +82,14 @@ private import RangeAnalysisUtil
8282
8383private module InvalidPointerToDerefBarrier {
8484 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 ) )
8889 }
8990
91+ predicate isSource ( DataFlow:: Node source ) { isSource ( source , _) }
92+
9093 additional predicate isSink (
9194 DataFlow:: Node left , DataFlow:: Node right , IRGuardCondition g , int k , boolean testIsTrue
9295 ) {
@@ -99,59 +102,80 @@ private module InvalidPointerToDerefBarrier {
99102
100103 private module BarrierFlow = DataFlow:: Global< BarrierConfig > ;
101104
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+ */
109111 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
111113 ) {
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 )
118119 )
119120 }
120121
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 |
123127 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
128135 )
129136 }
130137
131- DataFlow:: Node getABarrierNode ( ) { result .asOperand ( ) = getABarrierInstruction ( _) .getAUse ( ) }
138+ DataFlow:: Node getABarrierNode ( PointerArithmeticInstruction pai ) {
139+ result .asOperand ( ) = getABarrierInstruction ( pai ) .getAUse ( )
140+ }
132141
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+ }
135149}
136150
137151/**
138152 * A configuration to track flow from a pointer-arithmetic operation found
139153 * by `AllocToInvalidPointerConfig` to a dereference of the pointer.
140154 */
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+ }
143163
144164 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 ( ) }
146168
147169 predicate isBarrier ( DataFlow:: Node node ) {
148170 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 )
151175 }
152176}
153177
154- private import DataFlow:: Global < InvalidPointerToDerefConfig >
178+ private import DataFlow:: GlobalWithState < InvalidPointerToDerefConfig >
155179
156180/**
157181 * Holds if `allocSource` is dataflow node that represents an allocation that flows to the
@@ -165,19 +189,14 @@ private predicate invalidPointerToDerefSource(
165189 DataFlow:: Node allocSource , PointerArithmeticInstruction pai , DataFlow:: Node derefSource ,
166190 int deltaDerefSourceAndPai
167191) {
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
181200}
182201
183202/**
@@ -187,15 +206,14 @@ private predicate invalidPointerToDerefSource(
187206 */
188207pragma [ inline]
189208private 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
191211) {
192- exists ( AddressOperand addr , Instruction s , IRBlock b |
212+ exists ( Instruction s |
193213 s = sink .asInstruction ( ) and
194214 bounded ( addr .getDef ( ) , s , deltaDerefSinkAndDerefAddress ) and
195215 deltaDerefSinkAndDerefAddress >= 0 and
196- i .getAnOperand ( ) = addr and
197- b = i .getBlock ( ) and
198- not b = InvalidPointerToDerefBarrier:: getABarrierBlock ( deltaDerefSinkAndDerefAddress )
216+ i .getAnOperand ( ) = addr
199217 |
200218 i instanceof StoreInstruction and
201219 operation = "write"
@@ -221,9 +239,11 @@ private Instruction getASuccessor(Instruction instr) {
221239 instr .getBlock ( ) .getASuccessor + ( ) = result .getBlock ( )
222240}
223241
224- private predicate paiForDereferenceSink ( PointerArithmeticInstruction pai , DataFlow:: Node derefSink ) {
242+ private predicate paiForDereferenceSink (
243+ PointerArithmeticInstruction pai , DataFlow:: Node derefSink , int deltaDerefSourceAndPai
244+ ) {
225245 exists ( DataFlow:: Node derefSource |
226- invalidPointerToDerefSource ( _, pai , derefSource , _ ) and
246+ invalidPointerToDerefSource ( _, pai , derefSource , deltaDerefSourceAndPai ) and
227247 flow ( derefSource , derefSink )
228248 )
229249}
@@ -235,13 +255,15 @@ private predicate paiForDereferenceSink(PointerArithmeticInstruction pai, DataFl
235255 */
236256private predicate derefSinkToOperation (
237257 DataFlow:: Node derefSink , PointerArithmeticInstruction pai , DataFlow:: Node operation ,
238- string description , int deltaDerefSinkAndDerefAddress
258+ string description , int deltaDerefSourceAndPai , int deltaDerefSinkAndDerefAddress
239259) {
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
243264 operationInstr = getASuccessor ( derefSink .asInstruction ( ) ) and
244- operation .asInstruction ( ) = operationInstr
265+ operation .asInstruction ( ) = operationInstr and
266+ not addr = InvalidPointerToDerefBarrier:: getABarrierAddressOperand ( pai )
245267 )
246268}
247269
@@ -260,7 +282,8 @@ predicate operationIsOffBy(
260282 exists ( int deltaDerefSourceAndPai , int deltaDerefSinkAndDerefAddress |
261283 invalidPointerToDerefSource ( allocation , pai , derefSource , deltaDerefSourceAndPai ) and
262284 flow ( derefSource , derefSink ) and
263- derefSinkToOperation ( derefSink , pai , operation , description , deltaDerefSinkAndDerefAddress ) and
285+ derefSinkToOperation ( derefSink , pai , operation , description , deltaDerefSourceAndPai ,
286+ deltaDerefSinkAndDerefAddress ) and
264287 delta = deltaDerefSourceAndPai + deltaDerefSinkAndDerefAddress
265288 )
266289}
0 commit comments