1
1
private import AliasAnalysisInternal
2
- private import cpp
3
2
private import InputIR
4
- private import semmle.code.cpp.ir.internal.IntegerConstant as Ints
5
- private import semmle.code.cpp.ir.implementation.IRConfiguration
6
- private import semmle.code.cpp.models.interfaces.Alias
3
+ private import AliasAnalysisImports
7
4
8
5
private class IntValue = Ints:: IntValue ;
9
6
10
- /**
11
- * Gets the offset of field `field` in bits.
12
- */
13
- private IntValue getFieldBitOffset ( Field field ) {
14
- if field instanceof BitField
15
- then result = Ints:: add ( Ints:: mul ( field .getByteOffset ( ) , 8 ) , field .( BitField ) .getBitOffset ( ) )
16
- else result = Ints:: mul ( field .getByteOffset ( ) , 8 )
17
- }
18
-
19
7
/**
20
8
* Holds if the operand `tag` of instruction `instr` is used in a way that does
21
9
* not result in any address held in that operand from escaping beyond the
@@ -36,7 +24,7 @@ private predicate operandIsConsumedWithoutEscaping(Operand operand) {
36
24
instr instanceof PointerDiffInstruction
37
25
or
38
26
// Converting an address to a `bool` does not escape the address.
39
- instr .( ConvertInstruction ) .getResultType ( ) instanceof BoolType
27
+ instr .( ConvertInstruction ) .getResultIRType ( ) instanceof IRBooleanType
40
28
)
41
29
)
42
30
or
@@ -111,13 +99,10 @@ private predicate operandIsPropagated(Operand operand, IntValue bitOffset) {
111
99
bitOffset = Ints:: unknown ( )
112
100
or
113
101
// Conversion to another pointer type propagates the source address.
114
- exists ( ConvertInstruction convert , Type resultType |
102
+ exists ( ConvertInstruction convert , IRType resultType |
115
103
convert = instr and
116
- resultType = convert .getResultType ( ) and
117
- (
118
- resultType instanceof PointerType or
119
- resultType instanceof Class //REVIEW: Remove when all glvalues are pointers
120
- ) and
104
+ resultType = convert .getResultIRType ( ) and
105
+ resultType instanceof IRAddressType and
121
106
bitOffset = 0
122
107
)
123
108
or
@@ -131,7 +116,7 @@ private predicate operandIsPropagated(Operand operand, IntValue bitOffset) {
131
116
or
132
117
// Computing a field address from a pointer propagates the address plus the
133
118
// offset of the field.
134
- bitOffset = getFieldBitOffset ( instr .( FieldAddressInstruction ) .getField ( ) )
119
+ bitOffset = Language :: getFieldBitOffset ( instr .( FieldAddressInstruction ) .getField ( ) )
135
120
or
136
121
// A copy propagates the source value.
137
122
operand = instr .( CopyInstruction ) .getSourceValueOperand ( ) and bitOffset = 0
@@ -212,7 +197,7 @@ private predicate operandReturned(Operand operand, IntValue bitOffset) {
212
197
}
213
198
214
199
private predicate isArgumentForParameter ( CallInstruction ci , Operand operand , Instruction init ) {
215
- exists ( Function f |
200
+ exists ( Language :: Function f |
216
201
ci = operand .getUse ( ) and
217
202
f = ci .getStaticCallTarget ( ) and
218
203
(
@@ -223,27 +208,27 @@ private predicate isArgumentForParameter(CallInstruction ci, Operand operand, In
223
208
init .getEnclosingFunction ( ) = f and
224
209
operand instanceof ThisArgumentOperand
225
210
) and
226
- not f . isVirtual ( ) and
227
- not f instanceof AliasFunction
211
+ not Language :: isFunctionVirtual ( f ) and
212
+ not f instanceof AliasModels :: AliasFunction
228
213
)
229
214
}
230
215
231
216
private predicate isAlwaysReturnedArgument ( Operand operand ) {
232
- exists ( AliasFunction f |
217
+ exists ( AliasModels :: AliasFunction f |
233
218
f = operand .getUse ( ) .( CallInstruction ) .getStaticCallTarget ( ) and
234
219
f .parameterIsAlwaysReturned ( operand .( PositionalArgumentOperand ) .getIndex ( ) )
235
220
)
236
221
}
237
222
238
223
private predicate isOnlyEscapesViaReturnArgument ( Operand operand ) {
239
- exists ( AliasFunction f |
224
+ exists ( AliasModels :: AliasFunction f |
240
225
f = operand .getUse ( ) .( CallInstruction ) .getStaticCallTarget ( ) and
241
226
f .parameterEscapesOnlyViaReturn ( operand .( PositionalArgumentOperand ) .getIndex ( ) )
242
227
)
243
228
}
244
229
245
230
private predicate isNeverEscapesArgument ( Operand operand ) {
246
- exists ( AliasFunction f |
231
+ exists ( AliasModels :: AliasFunction f |
247
232
f = operand .getUse ( ) .( CallInstruction ) .getStaticCallTarget ( ) and
248
233
f .parameterNeverEscapes ( operand .( PositionalArgumentOperand ) .getIndex ( ) )
249
234
)
@@ -265,61 +250,86 @@ private predicate resultEscapesNonReturn(Instruction instr) {
265
250
}
266
251
267
252
/**
268
- * Holds if the address of the specified local variable or parameter escapes the
269
- * domain of the analysis.
253
+ * Holds if the address of `allocation` escapes outside the domain of the analysis. This can occur
254
+ * either because the allocation's address is taken within the function and escapes, or because the
255
+ * allocation is marked as always escaping via `alwaysEscapes()`.
270
256
*/
271
- private predicate automaticVariableAddressEscapes ( IRAutomaticVariable var ) {
272
- // The variable's address escapes if the result of any
273
- // VariableAddressInstruction that computes the variable's address escapes.
274
- exists ( VariableAddressInstruction instr |
275
- instr .getIRVariable ( ) = var and
276
- resultEscapesNonReturn ( instr )
257
+ predicate allocationEscapes ( Configuration:: Allocation allocation ) {
258
+ allocation .alwaysEscapes ( )
259
+ or
260
+ exists ( IREscapeAnalysisConfiguration config |
261
+ config .useSoundEscapeAnalysis ( ) and resultEscapesNonReturn ( allocation .getABaseInstruction ( ) )
277
262
)
278
263
}
279
264
280
265
/**
281
- * Holds if the address of the specified variable escapes the domain of the
282
- * analysis.
266
+ * Equivalent to `operandIsPropagated()`, but includes interprocedural propagation.
283
267
*/
284
- predicate variableAddressEscapes ( IRVariable var ) {
285
- exists ( IREscapeAnalysisConfiguration config |
286
- config .useSoundEscapeAnalysis ( ) and
287
- automaticVariableAddressEscapes ( var .( IRAutomaticVariable ) )
288
- )
268
+ private predicate operandIsPropagatedIncludingByCall ( Operand operand , IntValue bitOffset ) {
269
+ operandIsPropagated ( operand , bitOffset )
289
270
or
290
- // All variables with static storage duration have their address escape, even when escape analysis
291
- // is allowed to be unsound. Otherwise, we won't have a definition for any non-escaped global
292
- // variable. Normally, we rely on `AliasedDefinition` to handle that.
293
- not var instanceof IRAutomaticVariable
271
+ exists ( CallInstruction call , Instruction init |
272
+ isArgumentForParameter ( call , operand , init ) and
273
+ resultReturned ( init , bitOffset )
274
+ )
294
275
}
295
276
296
277
/**
297
- * Holds if the result of instruction `instr` points within variable `var`, at
298
- * bit offset `bitOffset` within the variable. If the result points within
299
- * `var`, but at an unknown or non-constant offset, then `bitOffset` is unknown.
278
+ * Holds if `addrOperand` is at offset `bitOffset` from the value of instruction `base`. The offset
279
+ * may be `unknown()`.
300
280
*/
301
- predicate resultPointsTo ( Instruction instr , IRVariable var , IntValue bitOffset ) {
302
- // The address of a variable points to that variable, at offset 0.
303
- instr .( VariableAddressInstruction ) .getIRVariable ( ) = var and
304
- bitOffset = 0
305
- or
306
- // A string literal is just a special read-only global variable.
307
- instr .( StringConstantInstruction ) .getIRVariable ( ) = var and
308
- bitOffset = 0
281
+ private predicate hasBaseAndOffset ( AddressOperand addrOperand , Instruction base , IntValue bitOffset ) {
282
+ base = addrOperand .getDef ( ) and bitOffset = 0 // Base case
309
283
or
310
- exists ( Operand operand , IntValue originalBitOffset , IntValue propagatedBitOffset |
311
- operand = instr .getAnOperand ( ) and
312
- // If an operand is propagated, then the result points to the same variable,
313
- // offset by the bit offset from the propagation.
314
- resultPointsTo ( operand .getAnyDef ( ) , var , originalBitOffset ) and
315
- (
316
- operandIsPropagated ( operand , propagatedBitOffset )
317
- or
318
- exists ( CallInstruction ci , Instruction init |
319
- isArgumentForParameter ( ci , operand , init ) and
320
- resultReturned ( init , propagatedBitOffset )
321
- )
322
- ) and
323
- bitOffset = Ints:: add ( originalBitOffset , propagatedBitOffset )
284
+ exists (
285
+ Instruction middle , int previousBitOffset , Operand middleOperand , IntValue additionalBitOffset
286
+ |
287
+ // We already have an offset from `middle`.
288
+ hasBaseAndOffset ( addrOperand , middle , previousBitOffset ) and
289
+ // `middle` is propagated from `base`.
290
+ middleOperand = middle .getAnOperand ( ) and
291
+ operandIsPropagatedIncludingByCall ( middleOperand , additionalBitOffset ) and
292
+ base = middleOperand .getDef ( ) and
293
+ bitOffset = Ints:: add ( previousBitOffset , additionalBitOffset )
294
+ )
295
+ }
296
+
297
+ /**
298
+ * Holds if `addrOperand` is at constant offset `bitOffset` from the value of instruction `base`.
299
+ * Only holds for the `base` with the longest chain of propagation to `addrOperand`.
300
+ */
301
+ predicate addressOperandBaseAndConstantOffset (
302
+ AddressOperand addrOperand , Instruction base , int bitOffset
303
+ ) {
304
+ hasBaseAndOffset ( addrOperand , base , bitOffset ) and
305
+ Ints:: hasValue ( bitOffset ) and
306
+ not exists ( Instruction previousBase , int previousBitOffset |
307
+ hasBaseAndOffset ( addrOperand , previousBase , previousBitOffset ) and
308
+ previousBase = base .getAnOperand ( ) .getDef ( ) and
309
+ Ints:: hasValue ( previousBitOffset )
310
+ )
311
+ }
312
+
313
+ /**
314
+ * Gets the allocation into which `addrOperand` points, if known.
315
+ */
316
+ Configuration:: Allocation getAddressOperandAllocation ( AddressOperand addrOperand ) {
317
+ addressOperandAllocationAndOffset ( addrOperand , result , _)
318
+ }
319
+
320
+ /**
321
+ * Holds if `addrOperand` is at offset `bitOffset` from a base instruction of `allocation`. The
322
+ * offset may be `unknown()`.
323
+ */
324
+ predicate addressOperandAllocationAndOffset (
325
+ AddressOperand addrOperand , Configuration:: Allocation allocation , IntValue bitOffset
326
+ ) {
327
+ exists ( Instruction base |
328
+ allocation .getABaseInstruction ( ) = base and
329
+ hasBaseAndOffset ( addrOperand , base , bitOffset ) and
330
+ not exists ( Instruction previousBase |
331
+ hasBaseAndOffset ( addrOperand , previousBase , _) and
332
+ previousBase = base .getAnOperand ( ) .getDef ( )
333
+ )
324
334
)
325
335
}
0 commit comments