1
+ /**
2
+ * This file provides the first phase of the `cpp/invalid-pointer-deref` query that identifies flow
3
+ * an allocation to a pointer-arithmetic instruction that constructs a pointer that's out of bounds.
4
+ */
5
+
1
6
private import cpp
2
7
private import semmle.code.cpp.ir.dataflow.internal.ProductFlow
3
8
private import semmle.code.cpp.ir.ValueNumbering
@@ -85,6 +90,10 @@ module Barrier2 {
85
90
)
86
91
}
87
92
93
+ /**
94
+ * Gets an instruction that is guarded by a guard condition which ensures that
95
+ * the value of the instruction is upper-bounded by size of some allocation.
96
+ */
88
97
Instruction getABarrierInstruction ( FlowState2 state ) {
89
98
exists ( IRGuardCondition g , ValueNumber value , Operand use , boolean edge |
90
99
use = value .getAUse ( ) and
@@ -95,16 +104,24 @@ module Barrier2 {
95
104
)
96
105
}
97
106
107
+ /**
108
+ * Gets a `DataFlow::Node` that is guarded by a guard condition which ensures that
109
+ * the value of the node is upper-bounded by size of some allocation.
110
+ */
98
111
DataFlow:: Node getABarrierNode ( FlowState2 state ) {
99
112
result .asOperand ( ) = getABarrierInstruction ( state ) .getAUse ( )
100
113
}
101
114
115
+ /**
116
+ * Gets the block of a node that is guarded (see `getABarrierInstruction` or
117
+ * `getABarrierNode` for the definition of what it means to be guarded).
118
+ */
102
119
IRBlock getABarrierBlock ( FlowState2 state ) {
103
120
result .getAnInstruction ( ) = getABarrierInstruction ( state )
104
121
}
105
122
}
106
123
107
- module InterestingPointerAddInstruction {
124
+ private module InterestingPointerAddInstruction {
108
125
private module PointerAddInstructionConfig implements DataFlow:: ConfigSig {
109
126
predicate isSource ( DataFlow:: Node source ) {
110
127
// The sources is the same as in the sources for the second
@@ -119,6 +136,12 @@ module InterestingPointerAddInstruction {
119
136
120
137
private import DataFlow:: Global< PointerAddInstructionConfig >
121
138
139
+ /**
140
+ * Holds if `pai` is a pointer-arithmetic instruction such that the
141
+ * result of an allocation flows to the left-hand side of `pai`.
142
+ *
143
+ * This predicate is used to reduce the set of tuples in `isSinkPair`.
144
+ */
122
145
predicate isInteresting ( PointerAddInstruction pai ) {
123
146
exists ( DataFlow:: Node n |
124
147
n .asInstruction ( ) = pai .getLeft ( ) and
@@ -210,12 +233,18 @@ private predicate pointerAddInstructionHasBounds0(
210
233
pai .getRight ( ) = right and
211
234
pai .getLeft ( ) = sink1 .asInstruction ( ) and
212
235
instr2 = sink2 .asInstruction ( ) and
236
+ // pai.getRight() <= sink2 + delta
213
237
bounded1 ( right , instr2 , delta ) and
214
238
not right = Barrier2:: getABarrierInstruction ( delta ) and
215
239
not instr2 = Barrier2:: getABarrierInstruction ( delta )
216
240
)
217
241
}
218
242
243
+ /**
244
+ * Holds if `allocation` flows to `sink1` and `sink1` represents the left-hand
245
+ * side of the pointer-arithmetic instruction `pai`, and the right-hand side of `pai`
246
+ * is non-strictly upper bounded by the size of `alllocation` + `delta`.
247
+ */
219
248
pragma [ nomagic]
220
249
predicate pointerAddInstructionHasBounds (
221
250
DataFlow:: Node allocation , PointerAddInstruction pai , DataFlow:: Node sink1 , int delta
0 commit comments