Skip to content

Commit 710d0cf

Browse files
committed
C++: Since we now no longer have flow from exact memory operands to LoadInstructions, we no longer have flow from PhiInstructions to LoadInstructions. We could allow flow in this particular case, but we might as well use the shared SSA library's phi edges.
1 parent 8caff41 commit 710d0cf

File tree

2 files changed

+72
-1
lines changed

2 files changed

+72
-1
lines changed

cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,8 @@ private module Cached {
2222
TVariableNode(Variable var) or
2323
TStoreNodeInstr(Instruction i) { Ssa::explicitWrite(_, _, i) } or
2424
TStoreNodeOperand(ArgumentOperand op) { Ssa::explicitWrite(_, _, op.getDef()) } or
25-
TReadNode(Instruction i) { needsPostReadNode(i) }
25+
TReadNode(Instruction i) { needsPostReadNode(i) } or
26+
TSsaPhiNode(Ssa::PhiNode phi)
2627

2728
cached
2829
predicate localFlowStepCached(Node nodeFrom, Node nodeTo) {
@@ -347,6 +348,44 @@ class ReadNode extends Node, TReadNode {
347348
}
348349
}
349350

351+
/**
352+
* INTERNAL: do not use.
353+
*
354+
* A phi node produced by the shared SSA library, viewed as a node in a data flow graph.
355+
*/
356+
class SsaPhiNode extends Node, TSsaPhiNode {
357+
Ssa::PhiNode phi;
358+
359+
SsaPhiNode() { this = TSsaPhiNode(phi) }
360+
361+
/* Get the phi node associated with this node. */
362+
Ssa::PhiNode getPhiNode() { result = phi }
363+
364+
override Declaration getEnclosingCallable() { result = this.getFunction() }
365+
366+
override Function getFunction() { result = phi.getBasicBlock().getEnclosingFunction() }
367+
368+
override IRType getType() { result instanceof IRVoidType }
369+
370+
override Location getLocation() { result = phi.getBasicBlock().getLocation() }
371+
372+
/** Holds if this phi node has input from the `rnk`'th write operation in block `block`. */
373+
final predicate hasInputAtRankInBlock(IRBlock block, int rnk) {
374+
hasInputAtRankInBlock(block, rnk, _)
375+
}
376+
377+
/**
378+
* Holds if this phi node has input from the definition `input` (which is the `rnk`'th write
379+
* operation in block `block`).
380+
*/
381+
cached
382+
final predicate hasInputAtRankInBlock(IRBlock block, int rnk, Ssa::Definition input) {
383+
Ssa::phiHasInputFromBlock(phi, input, _) and input.definesAt(_, block, rnk)
384+
}
385+
386+
override string toString() { result = "Phi" }
387+
}
388+
350389
/**
351390
* An expression, viewed as a node in a data flow graph.
352391
*/

cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/Ssa.qll

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -336,6 +336,34 @@ private module Cached {
336336
)
337337
}
338338

339+
private predicate fromPhiNode(SsaPhiNode nodeFrom, Node nodeTo) {
340+
exists(PhiNode phi, Use use, IRBlock block, int rnk |
341+
phi = nodeFrom.getPhiNode() and
342+
adjacentDefRead(phi, _, _, block, rnk) and
343+
use.hasRankInBlock(block, rnk) and
344+
flowOutOfAddressStep(use.getOperand(), nodeTo)
345+
)
346+
}
347+
348+
private predicate toPhiNode(Node nodeFrom, SsaPhiNode nodeTo) {
349+
// Flow to phi nodes
350+
exists(Def def, IRBlock block, int rnk |
351+
def.hasRankInBlock(block, rnk) and
352+
nodeTo.hasInputAtRankInBlock(block, rnk)
353+
|
354+
exists(StoreNode store |
355+
store = nodeFrom and
356+
store.isTerminal() and
357+
def.getInstruction() = store.getStoreInstruction()
358+
)
359+
or
360+
def.getInstruction() = nodeFrom.asInstruction()
361+
)
362+
or
363+
// Phi -> phi flow
364+
nodeTo.hasInputAtRankInBlock(_, _, nodeFrom.(SsaPhiNode).getPhiNode())
365+
}
366+
339367
/**
340368
* Holds if `nodeFrom` is a read or write, and `nTo` is the next subsequent read of the variable
341369
* written (or read) by `storeOrRead`.
@@ -350,6 +378,10 @@ private module Cached {
350378
or
351379
// Use-use flow from a `ReadNode` to an `OperandNode`
352380
fromReadNode(nodeFrom, nodeTo)
381+
or
382+
fromPhiNode(nodeFrom, nodeTo)
383+
or
384+
toPhiNode(nodeFrom, nodeTo)
353385
}
354386

355387
private predicate flowOutOfAddressStep(Operand operand, Node nTo) {

0 commit comments

Comments
 (0)