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

Skip to content

Commit a33b591

Browse files
Robert Marshdave-bartolomeo
authored andcommitted
C++: insert Chi nodes in the IR successor relation
This commit adds Chi nodes to the successor relation and accounts for them in the CFG, but does not add them to the SSA data graph. Chi nodes are inserted for partial writes to any VirtualVariable, regardless of whether the partial write reaches any uses.
1 parent 1fb36ff commit a33b591

19 files changed

Lines changed: 1443 additions & 1263 deletions

config/identical-files.json

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -43,10 +43,6 @@
4343
"cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/AliasAnalysis.qll",
4444
"cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/internal/AliasAnalysis.qll"
4545
],
46-
"C++ SSA SimpleSSA": [
47-
"cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/SimpleSSA.qll",
48-
"cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/internal/SimpleSSA.qll"
49-
],
5046
"C++ SSA SSAConstruction": [
5147
"cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/SSAConstruction.qll",
5248
"cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/internal/SSAConstruction.qll"

cpp/ql/src/semmle/code/cpp/ir/implementation/MemoryAccessKind.qll

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,9 @@ private newtype TMemoryAccessKind =
77
TBufferMayMemoryAccess() or
88
TEscapedMemoryAccess() or
99
TPhiMemoryAccess() or
10-
TUnmodeledMemoryAccess()
10+
TUnmodeledMemoryAccess() or
11+
TChiOldMemoryAccess() or
12+
TChiUpdateMemoryAccess()
1113

1214
/**
1315
* Describes the set of memory locations memory accessed by a memory operand or
@@ -78,6 +80,25 @@ class PhiMemoryAccess extends MemoryAccessKind, TPhiMemoryAccess {
7880
}
7981
}
8082

83+
/**
84+
* The operand is a ChiOld operand, which accesses the same memory as its
85+
* definition.
86+
*/
87+
class ChiOldMemoryAccess extends MemoryAccessKind, TChiOldMemoryAccess {
88+
override string toString() {
89+
result = "chi(old)"
90+
}
91+
}
92+
93+
/**
94+
* The operand is a ChiUpdate operand, which accesses the same memory as its
95+
* definition.
96+
*/
97+
class ChiUpdateMemoryAccess extends MemoryAccessKind, TChiUpdateMemoryAccess {
98+
override string toString() {
99+
result = "chi(updated)"
100+
}
101+
}
81102
/**
82103
* The operand accesses memory not modeled in SSA. Used only on the result of
83104
* `UnmodeledDefinition` and on the operands of `UnmodeledUse`.

cpp/ql/src/semmle/code/cpp/ir/implementation/Opcode.qll

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,8 @@ private newtype TOpcode =
6666
TIndirectMayWriteSideEffect() or
6767
TBufferReadSideEffect() or
6868
TBufferWriteSideEffect() or
69-
TBufferMayWriteSideEffect()
69+
TBufferMayWriteSideEffect() or
70+
TChi()
7071

7172
class Opcode extends TOpcode {
7273
string toString() {
@@ -192,4 +193,5 @@ module Opcode {
192193
class BufferReadSideEffect extends ReadSideEffectOpcode, BufferAccessOpcode, TBufferReadSideEffect { override final string toString() { result = "BufferReadSideEffect" } }
193194
class BufferWriteSideEffect extends WriteSideEffectOpcode, BufferAccessOpcode, TBufferWriteSideEffect { override final string toString() { result = "BufferWriteSideEffect" } }
194195
class BufferMayWriteSideEffect extends MayWriteSideEffectOpcode, BufferAccessOpcode, TBufferMayWriteSideEffect { override final string toString() { result = "BufferMayWriteSideEffect" } }
196+
class Chi extends Opcode, TChi {override final string toString() { result = "Chi" } }
195197
}

cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/Instruction.qll

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1340,6 +1340,16 @@ class PhiInstruction extends Instruction {
13401340
}
13411341
}
13421342

1343+
class ChiInstruction extends Instruction {
1344+
ChiInstruction() {
1345+
opcode instanceof Opcode::Chi
1346+
}
1347+
1348+
override final MemoryAccessKind getResultMemoryAccess() {
1349+
result instanceof ChiUpdateMemoryAccess
1350+
}
1351+
}
1352+
13431353
/**
13441354
* An instruction representing a built-in operation. This is used to represent
13451355
* operations such as access to variable argument lists.
Lines changed: 227 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,227 @@
1+
import cpp
2+
import AliasAnalysis
3+
private import semmle.code.cpp.ir.implementation.unaliased_ssa.IR
4+
private import semmle.code.cpp.ir.internal.OperandTag
5+
private import semmle.code.cpp.ir.internal.Overlap
6+
7+
import semmle.code.cpp.ir.internal.Overlap
8+
private import semmle.code.cpp.ir.internal.IntegerConstant as Ints
9+
10+
private class IntValue = Ints::IntValue;
11+
12+
private newtype TVirtualVariable =
13+
TVirtualIRVariable(IRVariable var) {
14+
not variableAddressEscapes(var)
15+
} or
16+
TUnknownVirtualVariable(FunctionIR f)
17+
18+
private VirtualIRVariable getVirtualVariable(IRVariable var) {
19+
result.getIRVariable() = var
20+
}
21+
22+
class VirtualVariable extends TVirtualVariable {
23+
string toString() {
24+
none()
25+
}
26+
27+
string getUniqueId() {
28+
none()
29+
}
30+
31+
Type getType() {
32+
none()
33+
}
34+
}
35+
36+
class VirtualIRVariable extends VirtualVariable, TVirtualIRVariable {
37+
IRVariable var;
38+
39+
VirtualIRVariable() {
40+
this = TVirtualIRVariable(var)
41+
}
42+
43+
override final string toString() {
44+
result = var.toString()
45+
}
46+
47+
final IRVariable getIRVariable() {
48+
result = var
49+
}
50+
51+
// REVIEW: This should just be on MemoryAccess
52+
override final Type getType() {
53+
result = var.getType()
54+
}
55+
56+
override final string getUniqueId() {
57+
result = var.getUniqueId()
58+
}
59+
}
60+
61+
class UnknownVirtualVariable extends VirtualVariable, TUnknownVirtualVariable {
62+
FunctionIR f;
63+
64+
UnknownVirtualVariable() {
65+
this = TUnknownVirtualVariable(f)
66+
}
67+
68+
override final string toString() {
69+
result = "UnknownVvar(" + f + ")"
70+
}
71+
72+
override final string getUniqueId() {
73+
result = "UnknownVvar(" + f + ")"
74+
}
75+
76+
override final Type getType() {
77+
result instanceof UnknownType
78+
}
79+
80+
final FunctionIR getFunctionIR() {
81+
result = f
82+
}
83+
}
84+
85+
private newtype TMemoryAccess =
86+
TVariableMemoryAccess(VirtualIRVariable vvar, IntValue offset, IntValue size) {
87+
exists(Instruction instr |
88+
instr.getResultMemoryAccess() instanceof IndirectMemoryAccess and
89+
resultPointsTo(instr.getAnOperand().(AddressOperand).getDefinitionInstruction(), vvar.getIRVariable(), offset) and
90+
instr.getResultSize() = size
91+
)
92+
}
93+
or
94+
TUnknownMemoryAccess(UnknownVirtualVariable uvv)
95+
96+
private VariableMemoryAccess getVariableMemoryAccess(IRVariable var, IntValue offset, IntValue size) {
97+
result.getVirtualVariable() = getVirtualVariable(var) and
98+
result.getOffset() = offset and
99+
result.getSize() = size
100+
}
101+
102+
class MemoryAccess extends TMemoryAccess {
103+
string toString() {
104+
none()
105+
}
106+
107+
VirtualVariable getVirtualVariable() {
108+
none()
109+
}
110+
111+
predicate isPartialMemoryAccess() {
112+
none()
113+
}
114+
}
115+
116+
class VariableMemoryAccess extends TVariableMemoryAccess, MemoryAccess {
117+
VirtualIRVariable vvar;
118+
IntValue offset;
119+
IntValue size;
120+
121+
VariableMemoryAccess() {
122+
this = TVariableMemoryAccess(vvar, offset, size)
123+
}
124+
125+
override final string toString() {
126+
result = vvar.toString()
127+
}
128+
129+
final override VirtualVariable getVirtualVariable() {
130+
result = vvar
131+
}
132+
133+
IntValue getOffset() {
134+
result = offset
135+
}
136+
137+
IntValue getSize() {
138+
result = size
139+
}
140+
141+
final override predicate isPartialMemoryAccess() {
142+
getOffset() != 0
143+
or
144+
getSize() != vvar.getType().getSize()
145+
}
146+
}
147+
148+
class UnknownMemoryAccess extends TUnknownMemoryAccess, MemoryAccess {
149+
UnknownVirtualVariable vvar;
150+
151+
final override string toString() {
152+
result = vvar.toString()
153+
}
154+
155+
final override VirtualVariable getVirtualVariable() {
156+
result = vvar
157+
}
158+
159+
final override predicate isPartialMemoryAccess() {
160+
any()
161+
}
162+
Type getType() {
163+
result instanceof UnknownType
164+
}
165+
}
166+
167+
Overlap getOverlap(MemoryAccess def, MemoryAccess use) {
168+
def instanceof VariableMemoryAccess and
169+
def = use and
170+
result instanceof MustExactlyOverlap
171+
or
172+
exists(VariableMemoryAccess defVMA, VariableMemoryAccess useVMA, int defOffset, int defEnd,
173+
int useOffset, int useEnd |
174+
defVMA = def and
175+
useVMA = use and
176+
defVMA.getVirtualVariable() = useVMA.getVirtualVariable() and
177+
defVMA != useVMA and
178+
defOffset = Ints::getValue(defVMA.getOffset()) and
179+
defEnd = Ints::getValue(Ints::add(defVMA.getOffset(), defVMA.getSize())) and
180+
useOffset = Ints::getValue(useVMA.getOffset()) and
181+
useEnd = Ints::getValue(Ints::add(useVMA.getOffset(), useVMA.getSize()))
182+
|
183+
defOffset <= useOffset and
184+
defEnd >= useEnd and
185+
result instanceof MustTotallyOverlap
186+
or
187+
defOffset > useOffset and
188+
defOffset < useEnd and
189+
result instanceof MayPartiallyOverlap
190+
or
191+
defOffset = useOffset and
192+
defEnd < useEnd and
193+
result instanceof MayPartiallyOverlap
194+
)
195+
or
196+
exists(UnknownVirtualVariable uvv |
197+
uvv = def.getVirtualVariable() and
198+
uvv = use.getVirtualVariable() and
199+
result instanceof MayPartiallyOverlap
200+
)
201+
}
202+
203+
MemoryAccess getResultMemoryAccess(Instruction instr) {
204+
instr.getResultMemoryAccess() instanceof IndirectMemoryAccess and
205+
if exists(IRVariable var, IntValue i |
206+
resultPointsTo(instr.getAnOperand().(AddressOperand).getDefinitionInstruction(), var, i)
207+
)
208+
then exists(IRVariable var, IntValue i |
209+
resultPointsTo(instr.getAnOperand().(AddressOperand).getDefinitionInstruction(), var, i) and
210+
result = getVariableMemoryAccess(var, i, instr.getResultSize())
211+
)
212+
else
213+
result = TUnknownMemoryAccess(TUnknownVirtualVariable(instr.getFunctionIR()))
214+
}
215+
216+
MemoryAccess getOperandMemoryAccess(Operand operand) {
217+
operand.getMemoryAccess() instanceof IndirectMemoryAccess and
218+
if exists(IRVariable var, IntValue i |
219+
resultPointsTo(operand.getAddressOperand().getDefinitionInstruction(), var, i)
220+
)
221+
then exists(IRVariable var, IntValue i |
222+
resultPointsTo(operand.getAddressOperand().getDefinitionInstruction(), var, i) and
223+
result = getVariableMemoryAccess(var, i, operand.getAddressOperand().getDefinitionInstruction().getResultSize())
224+
)
225+
else
226+
result = TUnknownMemoryAccess(TUnknownVirtualVariable(operand.getInstruction().getFunctionIR()))
227+
}

0 commit comments

Comments
 (0)