@@ -92,59 +92,57 @@ predicate hasSize(HeuristicAllocationExpr alloc, DataFlow::Node n, int state) {
9292 * ```
9393 * In this case, the sink pair identified by the product flow library (without any additional barriers)
9494 * would be `(p, n)` (where `n` is the `n` in `p[n]`), because there exists a pointer-arithmetic
95- * instruction `pai` such that:
96- * 1. The left-hand of `pai` flows from the allocation , and
97- * 2. The right-hand of `pai` is non-strictly upper bounded by ` n` ( where `n` is the `n` in `p[n]`)
95+ * instruction `pai = a + b ` such that:
96+ * 1. the allocation flows to `a` , and
97+ * 2. `b <= n` where `n` is the `n` in `p[n]`
9898 * but because there's a strict comparison that compares `n` against the size of the allocation this
9999 * snippet is fine.
100100 */
101- module Barrier2 {
102- private class FlowState2 = int ;
103-
104- private module BarrierConfig2 implements DataFlow:: ConfigSig {
101+ module SizeBarrier {
102+ private module SizeBarrierConfig implements DataFlow:: ConfigSig {
105103 predicate isSource ( DataFlow:: Node source ) {
106104 // The sources is the same as in the sources for the second
107105 // projection in the `AllocToInvalidPointerConfig` module.
108106 hasSize ( _, source , _)
109107 }
110108
111109 additional predicate isSink (
112- DataFlow:: Node left , DataFlow:: Node right , IRGuardCondition g , FlowState2 state ,
113- boolean testIsTrue
110+ DataFlow:: Node left , DataFlow:: Node right , IRGuardCondition g , int k , boolean testIsTrue
114111 ) {
115- // The sink is any "large" side of a relational comparison.
116- g .comparesLt ( left .asOperand ( ) , right .asOperand ( ) , state , true , testIsTrue )
112+ // The sink is any "large" side of a relational comparison. i.e., the `right` expression
113+ // in a guard such as `left < right + k`.
114+ g .comparesLt ( left .asOperand ( ) , right .asOperand ( ) , k , true , testIsTrue )
117115 }
118116
119117 predicate isSink ( DataFlow:: Node sink ) { isSink ( _, sink , _, _, _) }
120118 }
121119
122- private import DataFlow:: Global< BarrierConfig2 >
120+ private import DataFlow:: Global< SizeBarrierConfig >
123121
124- private FlowState2 getAFlowStateForNode ( DataFlow:: Node node ) {
122+ private int getAFlowStateForNode ( DataFlow:: Node node ) {
125123 exists ( DataFlow:: Node source |
126124 flow ( source , node ) and
127125 hasSize ( _, source , result )
128126 )
129127 }
130128
131129 private predicate operandGuardChecks (
132- IRGuardCondition g , Operand left , Operand right , FlowState2 state , boolean edge
130+ IRGuardCondition g , Operand left , Operand right , int state , boolean edge
133131 ) {
134- exists ( DataFlow:: Node nLeft , DataFlow:: Node nRight , FlowState2 state0 |
132+ exists ( DataFlow:: Node nLeft , DataFlow:: Node nRight , int k |
135133 nRight .asOperand ( ) = right and
136134 nLeft .asOperand ( ) = left and
137- BarrierConfig2 :: isSink ( nLeft , nRight , g , state0 , edge ) and
135+ SizeBarrierConfig :: isSink ( nLeft , nRight , g , k , edge ) and
138136 state = getAFlowStateForNode ( nRight ) and
139- state0 <= state
137+ k <= state
140138 )
141139 }
142140
143141 /**
144142 * Gets an instruction that is guarded by a guard condition which ensures that
145143 * the value of the instruction is upper-bounded by size of some allocation.
146144 */
147- Instruction getABarrierInstruction ( FlowState2 state ) {
145+ Instruction getABarrierInstruction ( int state ) {
148146 exists ( IRGuardCondition g , ValueNumber value , Operand use , boolean edge |
149147 use = value .getAUse ( ) and
150148 operandGuardChecks ( pragma [ only_bind_into ] ( g ) , pragma [ only_bind_into ] ( use ) , _,
@@ -158,17 +156,15 @@ module Barrier2 {
158156 * Gets a `DataFlow::Node` that is guarded by a guard condition which ensures that
159157 * the value of the node is upper-bounded by size of some allocation.
160158 */
161- DataFlow:: Node getABarrierNode ( FlowState2 state ) {
159+ DataFlow:: Node getABarrierNode ( int state ) {
162160 result .asOperand ( ) = getABarrierInstruction ( state ) .getAUse ( )
163161 }
164162
165163 /**
166164 * Gets the block of a node that is guarded (see `getABarrierInstruction` or
167165 * `getABarrierNode` for the definition of what it means to be guarded).
168166 */
169- IRBlock getABarrierBlock ( FlowState2 state ) {
170- result .getAnInstruction ( ) = getABarrierInstruction ( state )
171- }
167+ IRBlock getABarrierBlock ( int state ) { result .getAnInstruction ( ) = getABarrierInstruction ( state ) }
172168}
173169
174170private module InterestingPointerAddInstruction {
@@ -201,38 +197,38 @@ private module InterestingPointerAddInstruction {
201197}
202198
203199/**
204- * A product-flow configuration for flow from an `(allocation, size)` pair to a pointer-
205- * arithmetic instruction that is non-strictly upper-bounded by ` allocation + size`.
200+ * A product-flow configuration for flow from an `(allocation, size)` pair to a
201+ * pointer- arithmetic operation `pai` such that `pai <= allocation + size`.
206202 */
207203private module Config implements ProductFlow:: StateConfigSig {
208204 class FlowState1 = Unit ;
209205
210206 class FlowState2 = int ;
211207
212208 predicate isSourcePair (
213- DataFlow:: Node source1 , FlowState1 state1 , DataFlow:: Node source2 , FlowState2 state2
209+ DataFlow:: Node allocSource , FlowState1 unit , DataFlow:: Node sizeSource , FlowState2 sizeAddend
214210 ) {
215211 // In the case of an allocation like
216212 // ```cpp
217213 // malloc(size + 1);
218214 // ```
219215 // we use `state2` to remember that there was an offset (in this case an offset of `1`) added
220216 // to the size of the allocation. This state is then checked in `isSinkPair`.
221- exists ( state1 ) and
222- hasSize ( source1 .asConvertedExpr ( ) , source2 , state2 )
217+ exists ( unit ) and
218+ hasSize ( allocSource .asConvertedExpr ( ) , sizeSource , sizeAddend )
223219 }
224220
225221 predicate isSinkPair (
226- DataFlow:: Node sink1 , FlowState1 state1 , DataFlow:: Node sink2 , FlowState2 state2
222+ DataFlow:: Node allocSink , FlowState1 unit , DataFlow:: Node sizeSink , FlowState2 sizeAddend
227223 ) {
228- exists ( state1 ) and
224+ exists ( unit ) and
229225 // We check that the delta computed by the range analysis matches the
230226 // state value that we set in `isSourcePair`.
231- pointerAddInstructionHasBounds0 ( _, sink1 , sink2 , state2 )
227+ pointerAddInstructionHasBounds0 ( _, allocSink , sizeSink , sizeAddend )
232228 }
233229
234230 predicate isBarrier2 ( DataFlow:: Node node , FlowState2 state ) {
235- node = Barrier2 :: getABarrierNode ( state )
231+ node = SizeBarrier :: getABarrierNode ( state )
236232 }
237233
238234 predicate isBarrierIn1 ( DataFlow:: Node node ) { isSourcePair ( node , _, _, _) }
@@ -245,7 +241,7 @@ private module Config implements ProductFlow::StateConfigSig {
245241private module AllocToInvalidPointerFlow = ProductFlow:: GlobalWithState< Config > ;
246242
247243/**
248- * Holds if `pai` is non-strictly upper bounded by `sink2 + delta` and `sink1 ` is the
244+ * Holds if `pai` is non-strictly upper bounded by `sizeSink + delta` and `allocSink ` is the
249245 * left operand of the pointer-arithmetic operation.
250246 *
251247 * For example in,
@@ -254,37 +250,37 @@ private module AllocToInvalidPointerFlow = ProductFlow::GlobalWithState<Config>;
254250 * ```
255251 * We will have:
256252 * - `pai` is `p + (size + 1)`,
257- * - `sink1 ` is `p`
258- * - `sink2 ` is `size`
253+ * - `allocSink ` is `p`
254+ * - `sizeSink ` is `size`
259255 * - `delta` is `1`.
260256 */
261257pragma [ nomagic]
262258private predicate pointerAddInstructionHasBounds0 (
263- PointerAddInstruction pai , DataFlow:: Node sink1 , DataFlow:: Node sink2 , int delta
259+ PointerAddInstruction pai , DataFlow:: Node allocSink , DataFlow:: Node sizeSink , int delta
264260) {
265261 InterestingPointerAddInstruction:: isInteresting ( pragma [ only_bind_into ] ( pai ) ) and
266- exists ( Instruction right , Instruction instr2 |
262+ exists ( Instruction right , Instruction sizeInstr |
267263 pai .getRight ( ) = right and
268- pai .getLeft ( ) = sink1 .asInstruction ( ) and
269- instr2 = sink2 .asInstruction ( ) and
270- // pai.getRight() <= sink2 + delta
271- bounded1 ( right , instr2 , delta ) and
272- not right = Barrier2 :: getABarrierInstruction ( delta ) and
273- not instr2 = Barrier2 :: getABarrierInstruction ( delta )
264+ pai .getLeft ( ) = allocSink .asInstruction ( ) and
265+ sizeInstr = sizeSink .asInstruction ( ) and
266+ // pai.getRight() <= sizeSink + delta
267+ bounded1 ( right , sizeInstr , delta ) and
268+ not right = SizeBarrier :: getABarrierInstruction ( delta ) and
269+ not sizeInstr = SizeBarrier :: getABarrierInstruction ( delta )
274270 )
275271}
276272
277273/**
278- * Holds if `allocation` flows to `sink1 ` and `sink1 ` represents the left-hand
279- * side of the pointer-arithmetic instruction `pai`, and the right-hand side of `pai`
280- * is non-strictly upper bounded by the size of `alllocation` + ` delta`.
274+ * Holds if `allocation` flows to `allocSink ` and `allocSink ` represents the left operand
275+ * of the pointer-arithmetic instruction `pai = a + b` (i.e., `allocSink = a`), and
276+ * `b <= allocation + delta`.
281277 */
282278pragma [ nomagic]
283279predicate pointerAddInstructionHasBounds (
284- DataFlow:: Node allocation , PointerAddInstruction pai , DataFlow:: Node sink1 , int delta
280+ DataFlow:: Node allocation , PointerAddInstruction pai , DataFlow:: Node allocSink , int delta
285281) {
286- exists ( DataFlow:: Node sink2 |
287- AllocToInvalidPointerFlow:: flow ( allocation , _, sink1 , sink2 ) and
288- pointerAddInstructionHasBounds0 ( pai , sink1 , sink2 , delta )
282+ exists ( DataFlow:: Node sizeSink |
283+ AllocToInvalidPointerFlow:: flow ( allocation , _, allocSink , sizeSink ) and
284+ pointerAddInstructionHasBounds0 ( pai , allocSink , sizeSink , delta )
289285 )
290286}
0 commit comments