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

Skip to content

Commit 1842fed

Browse files
committed
C++: Add shared SSA library and instantiate it with the IR.
1 parent 13ce256 commit 1842fed

3 files changed

Lines changed: 1004 additions & 0 deletions

File tree

Lines changed: 303 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,303 @@
1+
import SsaImplCommon
2+
import SsaImplSpecific
3+
private import cpp as Cpp
4+
private import semmle.code.cpp.ir.IR
5+
private import DataFlowUtil
6+
private import DataFlowPrivate
7+
private import semmle.code.cpp.models.interfaces.Allocation as Alloc
8+
private import semmle.code.cpp.models.interfaces.DataFlow as DataFlow
9+
10+
cached
11+
private newtype TDefOrUse =
12+
TExplicitDef(Instruction store) { explicitWrite(_, store, _) } or
13+
TInitializeParam(Instruction instr) {
14+
instr instanceof InitializeParameterInstruction
15+
or
16+
instr instanceof InitializeIndirectionInstruction
17+
} or
18+
TExplicitUse(Operand op) { isExplicitUse(op) } or
19+
TReturnParamIndirection(Operand op) { returnParameterIndirection(op, _) }
20+
21+
pragma[nomagic]
22+
private int getRank(DefOrUse defOrUse, IRBlock block) {
23+
defOrUse =
24+
rank[result](int i, DefOrUse cand |
25+
block.getInstruction(i) = toInstruction(cand)
26+
|
27+
cand order by i
28+
)
29+
}
30+
31+
private class DefOrUse extends TDefOrUse {
32+
/** Gets the instruction associated with this definition, if any. */
33+
Instruction asDef() { none() }
34+
35+
/** Gets the operand associated with this use, if any. */
36+
Operand asUse() { none() }
37+
38+
/** Gets a textual representation of this element. */
39+
abstract string toString();
40+
41+
/** Gets the block of this definition or use. */
42+
abstract IRBlock getBlock();
43+
44+
/** Holds if this definition or use has rank `rank` in block `block`. */
45+
cached
46+
final predicate hasRankInBlock(IRBlock block, int rnk) {
47+
block = getBlock() and
48+
rnk = getRank(this, block)
49+
}
50+
51+
/**
52+
* Holds if this element is at the specified location.
53+
* The location spans column `startcolumn` of line `startline` to
54+
* column `endcolumn` of line `endline` in file `filepath`.
55+
* For more information, see
56+
* [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/).
57+
*/
58+
abstract predicate hasLocationInfo(
59+
string filepath, int startline, int startcolumn, int endline, int endcolumn
60+
);
61+
}
62+
63+
private Instruction toInstruction(DefOrUse defOrUse) {
64+
result = defOrUse.asDef()
65+
or
66+
result = defOrUse.asUse().getUse()
67+
}
68+
69+
abstract class Def extends DefOrUse {
70+
Instruction store;
71+
72+
/** Gets the instruction of this definition. */
73+
Instruction getInstruction() { result = store }
74+
75+
/** Gets the variable that is defined by this definition. */
76+
abstract SourceVariable getVariable();
77+
78+
/** Holds if this definition is guaranteed to happen. */
79+
abstract predicate isCertain();
80+
81+
override Instruction asDef() { result = this.getInstruction() }
82+
83+
override string toString() { result = "Def" }
84+
85+
override IRBlock getBlock() { result = this.getInstruction().getBlock() }
86+
87+
override predicate hasLocationInfo(
88+
string filepath, int startline, int startcolumn, int endline, int endcolumn
89+
) {
90+
store.getLocation().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
91+
}
92+
}
93+
94+
private class ExplicitDef extends Def, TExplicitDef {
95+
ExplicitDef() { this = TExplicitDef(store) }
96+
97+
override SourceVariable getVariable() {
98+
exists(VariableInstruction var |
99+
explicitWrite(_, this.getInstruction(), var) and
100+
result.getVariable() = var.getIRVariable() and
101+
not result.isIndirection()
102+
)
103+
}
104+
105+
override predicate isCertain() { explicitWrite(true, this.getInstruction(), _) }
106+
}
107+
108+
private class ParameterDef extends Def, TInitializeParam {
109+
ParameterDef() { this = TInitializeParam(store) }
110+
111+
override SourceVariable getVariable() {
112+
result.getVariable() = store.(InitializeParameterInstruction).getIRVariable() and
113+
not result.isIndirection()
114+
or
115+
result.getVariable() = store.(InitializeIndirectionInstruction).getIRVariable() and
116+
result.isIndirection()
117+
}
118+
119+
override predicate isCertain() { any() }
120+
}
121+
122+
abstract class Use extends DefOrUse {
123+
Operand use;
124+
125+
override Operand asUse() { result = use }
126+
127+
/** Gets the underlying operand of this use. */
128+
Operand getOperand() { result = use }
129+
130+
override string toString() { result = "Use" }
131+
132+
/** Gets the variable that is used by this use. */
133+
abstract SourceVariable getVariable();
134+
135+
override IRBlock getBlock() { result = use.getUse().getBlock() }
136+
137+
override predicate hasLocationInfo(
138+
string filepath, int startline, int startcolumn, int endline, int endcolumn
139+
) {
140+
use.getLocation().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
141+
}
142+
}
143+
144+
private class ExplicitUse extends Use, TExplicitUse {
145+
ExplicitUse() { this = TExplicitUse(use) }
146+
147+
override SourceVariable getVariable() {
148+
exists(VariableInstruction var |
149+
use.getDef() = var and
150+
result.getVariable() = var.getIRVariable() and
151+
(
152+
if use.getUse() instanceof ReadSideEffectInstruction
153+
then result.isIndirection()
154+
else not result.isIndirection()
155+
)
156+
)
157+
}
158+
}
159+
160+
private class ReturnParameterIndirection extends Use, TReturnParamIndirection {
161+
ReturnParameterIndirection() { this = TReturnParamIndirection(use) }
162+
163+
override SourceVariable getVariable() {
164+
exists(ReturnIndirectionInstruction ret |
165+
returnParameterIndirection(use, ret) and
166+
result.getVariable() = ret.getIRVariable() and
167+
result.isIndirection()
168+
)
169+
}
170+
}
171+
172+
private predicate isExplicitUse(Operand op) {
173+
op.getDef() instanceof VariableAddressInstruction and
174+
not exists(LoadInstruction load |
175+
load.getSourceAddressOperand() = op and
176+
load.getAUse().getUse() instanceof InitializeIndirectionInstruction
177+
)
178+
}
179+
180+
private predicate returnParameterIndirection(Operand op, ReturnIndirectionInstruction ret) {
181+
ret.getSourceAddressOperand() = op
182+
}
183+
184+
/**
185+
* Holds if `iFrom` computes an address that is used by `iTo`.
186+
*/
187+
predicate addressFlow(Instruction iFrom, Instruction iTo) {
188+
iTo.(CopyValueInstruction).getSourceValue() = iFrom
189+
or
190+
iTo.(ConvertInstruction).getUnary() = iFrom
191+
or
192+
iTo.(CheckedConvertOrNullInstruction).getUnary() = iFrom
193+
or
194+
iTo.(InheritanceConversionInstruction).getUnary() = iFrom
195+
or
196+
iTo.(PointerArithmeticInstruction).getLeft() = iFrom
197+
or
198+
iTo.(FieldAddressInstruction).getObjectAddress() = iFrom
199+
or
200+
iTo.(LoadInstruction).getSourceAddress() = iFrom
201+
or
202+
exists(WriteSideEffectInstruction write |
203+
write.getPrimaryInstruction() = iTo and
204+
write.getDestinationAddress() = iFrom
205+
)
206+
}
207+
208+
/**
209+
* The reflexive, transitive closure of `addressFlow` that ends as the address of a
210+
* store or read operation.
211+
*/
212+
cached
213+
predicate addressFlowTC(Instruction iFrom, Instruction iTo) {
214+
iTo = [getDestinationAddress(_), getSourceAddress(_)] and
215+
addressFlow*(iFrom, iTo)
216+
}
217+
218+
/**
219+
* Gets the destination address of `instr` if it is a `StoreInstruction` or
220+
* a `WriteSideEffectInstruction`. The destination address of a `WriteSideEffectInstruction` is adjusted
221+
* in the case of calls to operator `new` to give the destination address of a subsequent store (if any).
222+
*/
223+
Instruction getDestinationAddress(Instruction instr) {
224+
result =
225+
[
226+
instr.(StoreInstruction).getDestinationAddress(),
227+
instr.(WriteSideEffectInstruction).getDestinationAddress()
228+
]
229+
}
230+
231+
class ReferenceToInstruction extends CopyValueInstruction {
232+
ReferenceToInstruction() {
233+
this.getResultType() instanceof Cpp::ReferenceType and
234+
not this.getUnary().getResultType() instanceof Cpp::ReferenceType
235+
}
236+
237+
Instruction getSourceAddress() { result = getSourceAddressOperand().getDef() }
238+
239+
Operand getSourceAddressOperand() { result = this.getUnaryOperand() }
240+
}
241+
242+
/** Gets the source address of `instr` if it is an instruction that behaves like a `LoadInstruction`. */
243+
Instruction getSourceAddress(Instruction instr) { result = getSourceAddressOperand(instr).getDef() }
244+
245+
/**
246+
* Gets the operand that represents the source address of `instr` if it is an
247+
* instruction that behaves like a `LoadInstruction`.
248+
*/
249+
Operand getSourceAddressOperand(Instruction instr) {
250+
result =
251+
[
252+
instr.(LoadInstruction).getSourceAddressOperand(),
253+
instr.(ReadSideEffectInstruction).getArgumentOperand(),
254+
instr.(ReferenceToInstruction).getSourceAddressOperand()
255+
]
256+
}
257+
258+
/**
259+
* Gets the source address of `node` if it's an instruction or operand that
260+
* behaves like a `LoadInstruction`.
261+
*/
262+
Instruction getSourceAddressFromNode(Node node) {
263+
result = getSourceAddress(node.asInstruction())
264+
or
265+
result = getSourceAddress(node.asOperand().(SideEffectOperand).getUse())
266+
}
267+
268+
/** Gets the source value of `instr` if it's an instruction that behaves like a `LoadInstruction`. */
269+
Instruction getSourceValue(Instruction instr) { result = getSourceValueOperand(instr).getDef() }
270+
271+
/**
272+
* Gets the operand that represents the source value of `instr` if it's an instruction
273+
* that behaves like a `LoadInstruction`.
274+
*/
275+
Operand getSourceValueOperand(Instruction instr) {
276+
result = instr.(LoadInstruction).getSourceValueOperand()
277+
or
278+
result = instr.(ReadSideEffectInstruction).getSideEffectOperand()
279+
or
280+
result = instr.(ReferenceToInstruction).getSourceValueOperand()
281+
}
282+
283+
/**
284+
* Holds if `instr` is a `StoreInstruction` or a `WriteSideEffectInstruction` that writes to an address.
285+
* The addresses is computed using `address`, and `certain` is `true` if the write is guaranteed to overwrite
286+
* the entire variable.
287+
*/
288+
cached
289+
predicate explicitWrite(boolean certain, Instruction instr, Instruction address) {
290+
exists(StoreInstruction store |
291+
store = instr and addressFlowTC(address, store.getDestinationAddress())
292+
|
293+
if
294+
addressFlowTC(any(Instruction i |
295+
i instanceof FieldAddressInstruction or i instanceof PointerArithmeticInstruction
296+
), store.getDestinationAddress())
297+
then certain = false
298+
else certain = true
299+
)
300+
or
301+
addressFlowTC(address, instr.(WriteSideEffectInstruction).getDestinationAddress()) and
302+
certain = false
303+
}

0 commit comments

Comments
 (0)