Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 976b564

Browse files
author
Dave Bartolomeo
committed
C++: Update AliasedSSA to use Allocation instead of IRVariable
This introduces a new type of `MemoryLocation`: `EntireAllocationMemoryLocation`, representing an entire contiguous allocation whose size is not known. This is used to model the memory accesses on `InitializeIndirection` and `ReturnIndirection`.
1 parent 165a45d commit 976b564

1 file changed

Lines changed: 143 additions & 62 deletions

File tree

  • cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/internal

cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/internal/AliasedSSA.qll

Lines changed: 143 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -6,56 +6,71 @@ private import semmle.code.cpp.ir.implementation.unaliased_ssa.IR
66
private import semmle.code.cpp.ir.internal.IntegerConstant as Ints
77
private import semmle.code.cpp.ir.internal.IntegerInterval as Interval
88
private import semmle.code.cpp.ir.implementation.internal.OperandTag
9+
private import AliasConfiguration
910

1011
private class IntValue = Ints::IntValue;
1112

13+
private predicate isIndirectOrBufferMemoryAccess(MemoryAccessKind kind) {
14+
kind instanceof IndirectMemoryAccess or
15+
kind instanceof BufferMemoryAccess
16+
}
17+
1218
private predicate hasResultMemoryAccess(
13-
Instruction instr, IRVariable var, IRType type, Language::LanguageType languageType,
19+
Instruction instr, Allocation var, IRType type, Language::LanguageType languageType,
1420
IntValue startBitOffset, IntValue endBitOffset, boolean isMayAccess
1521
) {
16-
resultPointsTo(instr.getResultAddress(), var, startBitOffset) and
17-
languageType = instr.getResultLanguageType() and
18-
type = languageType.getIRType() and
19-
(if instr.hasResultMayMemoryAccess() then isMayAccess = true else isMayAccess = false) and
20-
if exists(type.getByteSize())
21-
then endBitOffset = Ints::add(startBitOffset, Ints::mul(type.getByteSize(), 8))
22-
else endBitOffset = Ints::unknown()
22+
exists(AddressOperand addrOperand |
23+
addrOperand = instr.getResultAddressOperand() and
24+
addressOperandAllocationAndOffset(addrOperand, var, startBitOffset) and
25+
languageType = instr.getResultLanguageType() and
26+
type = languageType.getIRType() and
27+
isIndirectOrBufferMemoryAccess(instr.getResultMemoryAccess()) and
28+
(if instr.hasResultMayMemoryAccess() then isMayAccess = true else isMayAccess = false) and
29+
if exists(type.getByteSize())
30+
then endBitOffset = Ints::add(startBitOffset, Ints::mul(type.getByteSize(), 8))
31+
else endBitOffset = Ints::unknown()
32+
)
2333
}
2434

2535
private predicate hasOperandMemoryAccess(
26-
MemoryOperand operand, IRVariable var, IRType type, Language::LanguageType languageType,
36+
MemoryOperand operand, Allocation var, IRType type, Language::LanguageType languageType,
2737
IntValue startBitOffset, IntValue endBitOffset, boolean isMayAccess
2838
) {
29-
resultPointsTo(operand.getAddressOperand().getAnyDef(), var, startBitOffset) and
30-
languageType = operand.getLanguageType() and
31-
type = languageType.getIRType() and
32-
(if operand.hasMayReadMemoryAccess() then isMayAccess = true else isMayAccess = false) and
33-
if exists(type.getByteSize())
34-
then endBitOffset = Ints::add(startBitOffset, Ints::mul(type.getByteSize(), 8))
35-
else endBitOffset = Ints::unknown()
39+
exists(AddressOperand addrOperand |
40+
addrOperand = operand.getAddressOperand() and
41+
addressOperandAllocationAndOffset(addrOperand, var, startBitOffset) and
42+
languageType = operand.getLanguageType() and
43+
type = languageType.getIRType() and
44+
isIndirectOrBufferMemoryAccess(operand.getMemoryAccess()) and
45+
(if operand.hasMayReadMemoryAccess() then isMayAccess = true else isMayAccess = false) and
46+
if exists(type.getByteSize())
47+
then endBitOffset = Ints::add(startBitOffset, Ints::mul(type.getByteSize(), 8))
48+
else endBitOffset = Ints::unknown()
49+
)
3650
}
3751

3852
private newtype TMemoryLocation =
3953
TVariableMemoryLocation(
40-
IRVariable var, IRType type, Language::LanguageType languageType, IntValue startBitOffset,
54+
Allocation var, IRType type, Language::LanguageType languageType, IntValue startBitOffset,
4155
IntValue endBitOffset, boolean isMayAccess
4256
) {
4357
(
4458
hasResultMemoryAccess(_, var, type, _, startBitOffset, endBitOffset, isMayAccess)
4559
or
4660
hasOperandMemoryAccess(_, var, type, _, startBitOffset, endBitOffset, isMayAccess)
4761
or
48-
exists(IRAutomaticVariable autoVar |
49-
// Always create a memory location for the entire variable.
50-
autoVar = var and
51-
type = autoVar.getIRType() and
52-
startBitOffset = 0 and
53-
endBitOffset = type.getByteSize() * 8 and
54-
isMayAccess = false
55-
)
62+
// For a stack variable, always create a memory location for the entire variable.
63+
var.isAlwaysAllocatedOnStack() and
64+
type = var.getIRType() and
65+
startBitOffset = 0 and
66+
endBitOffset = type.getByteSize() * 8 and
67+
isMayAccess = false
5668
) and
5769
languageType = type.getCanonicalLanguageType()
5870
} or
71+
TEntireAllocationMemoryLocation(IndirectParameterAllocation var, boolean isMayAccess) {
72+
isMayAccess = false or isMayAccess = true
73+
} or
5974
TUnknownMemoryLocation(IRFunction irFunc, boolean isMayAccess) {
6075
isMayAccess = false or isMayAccess = true
6176
} or
@@ -94,6 +109,8 @@ abstract class MemoryLocation extends TMemoryLocation {
94109

95110
abstract predicate isMayAccess();
96111

112+
Allocation getAllocation() { none() }
113+
97114
/**
98115
* Holds if the location cannot be overwritten except by definition of a `MemoryLocation` for
99116
* which `def.canDefineReadOnly()` holds.
@@ -114,26 +131,63 @@ abstract class MemoryLocation extends TMemoryLocation {
114131

115132
abstract class VirtualVariable extends MemoryLocation { }
116133

134+
abstract class AllocationMemoryLocation extends MemoryLocation {
135+
Allocation var;
136+
boolean isMayAccess;
137+
138+
AllocationMemoryLocation() {
139+
this instanceof TMemoryLocation and
140+
isMayAccess = false
141+
or
142+
isMayAccess = true // Just ensures that `isMayAccess` is bound.
143+
}
144+
145+
final override VirtualVariable getVirtualVariable() {
146+
if allocationEscapes(var)
147+
then result = TAllAliasedMemory(var.getEnclosingIRFunction(), false)
148+
else result.(AllocationMemoryLocation).getAllocation() = var
149+
}
150+
151+
final override IRFunction getIRFunction() { result = var.getEnclosingIRFunction() }
152+
153+
final override Location getLocation() { result = var.getLocation() }
154+
155+
final override Allocation getAllocation() { result = var }
156+
157+
final override predicate isMayAccess() { isMayAccess = true }
158+
159+
final override predicate isReadOnly() { var.isReadOnly() }
160+
}
161+
117162
/**
118163
* An access to memory within a single known `IRVariable`. The variable may be either an unescaped variable
119164
* (with its own `VirtualIRVariable`) or an escaped variable (assigned to `UnknownVirtualVariable`).
120165
*/
121-
class VariableMemoryLocation extends TVariableMemoryLocation, MemoryLocation {
122-
IRVariable var;
166+
class VariableMemoryLocation extends TVariableMemoryLocation, AllocationMemoryLocation {
123167
IRType type;
124168
Language::LanguageType languageType;
125169
IntValue startBitOffset;
126170
IntValue endBitOffset;
127-
boolean isMayAccess;
128171

129172
VariableMemoryLocation() {
130173
this = TVariableMemoryLocation(var, type, languageType, startBitOffset, endBitOffset,
131174
isMayAccess)
132175
}
133176

177+
private string getIntervalString() {
178+
if coversEntireVariable()
179+
then result = ""
180+
else result = Interval::getIntervalString(startBitOffset, endBitOffset)
181+
}
182+
183+
private string getTypeString() {
184+
if coversEntireVariable() and type = var.getIRType()
185+
then result = ""
186+
else result = "<" + languageType.toString() + ">"
187+
}
188+
134189
final override string toStringInternal() {
135-
result = var.toString() + Interval::getIntervalString(startBitOffset, endBitOffset) + "<" +
136-
type.toString() + ", " + languageType.toString() + ">"
190+
result = var.toString() + getIntervalString() + getTypeString()
137191
}
138192

139193
final override Language::LanguageType getType() {
@@ -151,34 +205,16 @@ class VariableMemoryLocation extends TVariableMemoryLocation, MemoryLocation {
151205
result = type.getCanonicalLanguageType()
152206
}
153207

154-
final override IRFunction getIRFunction() { result = var.getEnclosingIRFunction() }
155-
156-
final override Location getLocation() { result = var.getLocation() }
157-
158208
final IntValue getStartBitOffset() { result = startBitOffset }
159209

160210
final IntValue getEndBitOffset() { result = endBitOffset }
161211

162-
final IRVariable getVariable() { result = var }
163-
164212
final override string getUniqueId() {
165213
result = var.getUniqueId() + Interval::getIntervalString(startBitOffset, endBitOffset) + "<" +
166214
type.getIdentityString() + ">"
167215
}
168216

169-
final override VirtualVariable getVirtualVariable() {
170-
if variableAddressEscapes(var)
171-
then result = TAllAliasedMemory(var.getEnclosingIRFunction(), false)
172-
else
173-
result = TVariableMemoryLocation(var, var.getIRType(), _, 0,
174-
var.getIRType().getByteSize() * 8, false)
175-
}
176-
177-
final override predicate isMayAccess() { isMayAccess = true }
178-
179-
final override predicate isReadOnly() { var.isReadOnly() }
180-
181-
final override predicate isAlwaysAllocatedOnStack() { var instanceof IRAutomaticVariable }
217+
final override predicate isAlwaysAllocatedOnStack() { var.isAlwaysAllocatedOnStack() }
182218

183219
/**
184220
* Holds if this memory location covers the entire variable.
@@ -189,14 +225,34 @@ class VariableMemoryLocation extends TVariableMemoryLocation, MemoryLocation {
189225
}
190226
}
191227

228+
class EntireAllocationMemoryLocation extends TEntireAllocationMemoryLocation,
229+
AllocationMemoryLocation {
230+
EntireAllocationMemoryLocation() { this = TEntireAllocationMemoryLocation(var, isMayAccess) }
231+
232+
final override string toStringInternal() { result = var.toString() }
233+
234+
final override Language::LanguageType getType() {
235+
result = any(IRUnknownType unknownType).getCanonicalLanguageType()
236+
}
237+
238+
final override string getUniqueId() { result = var.getUniqueId() }
239+
}
240+
241+
class EntireAllocationVirtualVariable extends EntireAllocationMemoryLocation, VirtualVariable {
242+
EntireAllocationVirtualVariable() {
243+
not allocationEscapes(var) and
244+
not isMayAccess()
245+
}
246+
}
247+
192248
/**
193249
* Represents the `MemoryLocation` for an `IRVariable` that acts as its own `VirtualVariable`. Includes any
194250
* `VariableMemoryLocation` that exactly overlaps its entire `IRVariable`, and only if that `IRVariable` does not
195251
* escape.
196252
*/
197253
class VariableVirtualVariable extends VariableMemoryLocation, VirtualVariable {
198254
VariableVirtualVariable() {
199-
not variableAddressEscapes(var) and
255+
not allocationEscapes(var) and
200256
type = var.getIRType() and
201257
coversEntireVariable() and
202258
not isMayAccess()
@@ -354,13 +410,30 @@ private Overlap getExtentOverlap(MemoryLocation def, MemoryLocation use) {
354410
not use.isAlwaysAllocatedOnStack()
355411
)
356412
or
413+
def.getVirtualVariable() = use.getVirtualVariable() and
414+
def instanceof EntireAllocationMemoryLocation and
415+
(
416+
// EntireAllocationMemoryLocation exactly overlaps itself.
417+
use instanceof EntireAllocationMemoryLocation and
418+
result instanceof MustExactlyOverlap
419+
or
420+
// EntireAllocationMemoryLocation totally overlaps any location within the same virtual
421+
// variable.
422+
not use instanceof EntireAllocationMemoryLocation and
423+
result instanceof MustTotallyOverlap
424+
)
425+
or
357426
exists(VariableMemoryLocation defVariableLocation |
358427
defVariableLocation = def and
359428
(
360429
// A VariableMemoryLocation may partially overlap an unknown location within the same
361430
// virtual variable.
362431
def.getVirtualVariable() = use.getVirtualVariable() and
363-
(use instanceof UnknownMemoryLocation or use instanceof AllAliasedMemory) and
432+
(
433+
use instanceof UnknownMemoryLocation or
434+
use instanceof AllAliasedMemory or
435+
use instanceof EntireAllocationMemoryLocation
436+
) and
364437
result instanceof MayPartiallyOverlap
365438
or
366439
// A VariableMemoryLocation that is not a local variable may partially overlap an
@@ -421,19 +494,19 @@ private predicate isRelatableMemoryLocation(VariableMemoryLocation vml) {
421494
vml.getStartBitOffset() != Ints::unknown()
422495
}
423496

424-
private predicate isCoveredOffset(IRVariable var, int offsetRank, VariableMemoryLocation vml) {
497+
private predicate isCoveredOffset(Allocation var, int offsetRank, VariableMemoryLocation vml) {
425498
exists(int startRank, int endRank, VirtualVariable vvar |
426499
vml.getStartBitOffset() = rank[startRank](IntValue offset_ | isRelevantOffset(vvar, offset_)) and
427500
vml.getEndBitOffset() = rank[endRank](IntValue offset_ | isRelevantOffset(vvar, offset_)) and
428-
var = vml.getVariable() and
501+
var = vml.getAllocation() and
429502
vvar = vml.getVirtualVariable() and
430503
isRelatableMemoryLocation(vml) and
431504
offsetRank in [startRank .. endRank]
432505
)
433506
}
434507

435-
private predicate hasUnknownOffset(IRVariable var, VariableMemoryLocation vml) {
436-
vml.getVariable() = var and
508+
private predicate hasUnknownOffset(Allocation var, VariableMemoryLocation vml) {
509+
vml.getAllocation() = var and
437510
(
438511
vml.getStartBitOffset() = Ints::unknown() or
439512
vml.getEndBitOffset() = Ints::unknown()
@@ -443,14 +516,14 @@ private predicate hasUnknownOffset(IRVariable var, VariableMemoryLocation vml) {
443516
private predicate overlappingIRVariableMemoryLocations(
444517
VariableMemoryLocation def, VariableMemoryLocation use
445518
) {
446-
exists(IRVariable var, int offsetRank |
519+
exists(Allocation var, int offsetRank |
447520
isCoveredOffset(var, offsetRank, def) and
448521
isCoveredOffset(var, offsetRank, use)
449522
)
450523
or
451-
hasUnknownOffset(use.getVariable(), def)
524+
hasUnknownOffset(use.getAllocation(), def)
452525
or
453-
hasUnknownOffset(def.getVariable(), use)
526+
hasUnknownOffset(def.getAllocation(), use)
454527
}
455528

456529
private Overlap getVariableMemoryLocationOverlap(
@@ -467,16 +540,20 @@ MemoryLocation getResultMemoryLocation(Instruction instr) {
467540
(if instr.hasResultMayMemoryAccess() then isMayAccess = true else isMayAccess = false) and
468541
(
469542
(
470-
kind.usesAddressOperand() and
543+
isIndirectOrBufferMemoryAccess(kind) and
471544
if hasResultMemoryAccess(instr, _, _, _, _, _, _)
472545
then
473-
exists(IRVariable var, IRType type, IntValue startBitOffset, IntValue endBitOffset |
546+
exists(Allocation var, IRType type, IntValue startBitOffset, IntValue endBitOffset |
474547
hasResultMemoryAccess(instr, var, type, _, startBitOffset, endBitOffset, isMayAccess) and
475548
result = TVariableMemoryLocation(var, type, _, startBitOffset, endBitOffset, isMayAccess)
476549
)
477550
else result = TUnknownMemoryLocation(instr.getEnclosingIRFunction(), isMayAccess)
478551
)
479552
or
553+
kind instanceof EntireAllocationMemoryAccess and
554+
result = TEntireAllocationMemoryLocation(getAddressOperandAllocation(instr
555+
.getResultAddressOperand()), isMayAccess)
556+
or
480557
kind instanceof EscapedMemoryAccess and
481558
result = TAllAliasedMemory(instr.getEnclosingIRFunction(), isMayAccess)
482559
or
@@ -492,16 +569,20 @@ MemoryLocation getOperandMemoryLocation(MemoryOperand operand) {
492569
(if operand.hasMayReadMemoryAccess() then isMayAccess = true else isMayAccess = false) and
493570
(
494571
(
495-
kind.usesAddressOperand() and
572+
isIndirectOrBufferMemoryAccess(kind) and
496573
if hasOperandMemoryAccess(operand, _, _, _, _, _, _)
497574
then
498-
exists(IRVariable var, IRType type, IntValue startBitOffset, IntValue endBitOffset |
575+
exists(Allocation var, IRType type, IntValue startBitOffset, IntValue endBitOffset |
499576
hasOperandMemoryAccess(operand, var, type, _, startBitOffset, endBitOffset, isMayAccess) and
500577
result = TVariableMemoryLocation(var, type, _, startBitOffset, endBitOffset, isMayAccess)
501578
)
502579
else result = TUnknownMemoryLocation(operand.getEnclosingIRFunction(), isMayAccess)
503580
)
504581
or
582+
kind instanceof EntireAllocationMemoryAccess and
583+
result = TEntireAllocationMemoryLocation(getAddressOperandAllocation(operand
584+
.getAddressOperand()), isMayAccess)
585+
or
505586
kind instanceof EscapedMemoryAccess and
506587
result = TAllAliasedMemory(operand.getEnclosingIRFunction(), isMayAccess)
507588
or

0 commit comments

Comments
 (0)