SSA: Add BasicBlock.{getNode/1,length/0} to the input signature

This commit is contained in:
Tom Hvitved
2024-07-03 11:09:56 +02:00
parent 8e8100fd34
commit 4ae8720930
19 changed files with 117 additions and 33 deletions

View File

@@ -1809,7 +1809,7 @@ module IteratorFlow {
* Holds if `(bb, i)` contains a write to an iterator that may have been obtained
* by calling `begin` (or related functions) on the variable `v`.
*/
predicate variableWrite(IRBlock bb, int i, SourceVariable v, boolean certain) {
predicate variableWrite(BasicBlock bb, int i, SourceVariable v, boolean certain) {
certain = false and
exists(GetsIteratorCall beginCall, Instruction writeToDeref, IRBlock bbQual, int iQual |
isIteratorStoreInstruction(beginCall, writeToDeref) and
@@ -1820,7 +1820,7 @@ module IteratorFlow {
}
/** Holds if `(bb, i)` reads the container variable `v`. */
predicate variableRead(IRBlock bb, int i, SourceVariable v, boolean certain) {
predicate variableRead(BasicBlock bb, int i, SourceVariable v, boolean certain) {
Ssa::variableRead(bb, i, v, certain)
}
}

View File

@@ -981,7 +981,7 @@ private module SsaInput implements SsaImplCommon::InputSig<Location> {
* Holds if the `i`'th write in block `bb` writes to the variable `v`.
* `certain` is `true` if the write is guaranteed to overwrite the entire variable.
*/
predicate variableWrite(IRBlock bb, int i, SourceVariable v, boolean certain) {
predicate variableWrite(BasicBlock bb, int i, SourceVariable v, boolean certain) {
DataFlowImplCommon::forceCachingInSameStage() and
(
exists(DefImpl def | def.hasIndexInBlock(bb, i, v) |
@@ -999,7 +999,7 @@ private module SsaInput implements SsaImplCommon::InputSig<Location> {
* Holds if the `i`'th read in block `bb` reads to the variable `v`.
* `certain` is `true` if the read is guaranteed. For C++, this is always the case.
*/
predicate variableRead(IRBlock bb, int i, SourceVariable v, boolean certain) {
predicate variableRead(BasicBlock bb, int i, SourceVariable v, boolean certain) {
exists(UseImpl use | use.hasIndexInBlock(bb, i, v) |
if use.isCertain() then certain = true else certain = false
)

View File

@@ -757,13 +757,19 @@ import Cached
* between the SSA pruning stage, and the final SSA stage.
*/
module InputSigCommon {
class BasicBlock = IRBlock;
class BasicBlock extends IRBlock {
ControlFlowNode getNode(int i) { result = this.getInstruction(i) }
int length() { result = this.getInstructionCount() }
}
class ControlFlowNode = Instruction;
BasicBlock getImmediateBasicBlockDominator(BasicBlock bb) { result.immediatelyDominates(bb) }
BasicBlock getABasicBlockSuccessor(BasicBlock bb) { result = bb.getASuccessor() }
class ExitBasicBlock extends IRBlock {
class ExitBasicBlock extends BasicBlock {
ExitBasicBlock() { this.getLastInstruction() instanceof ExitFunctionInstruction }
}
}

View File

@@ -35,7 +35,7 @@ deprecated module Ssa {
}
/** Gets the location of this SSA definition. */
Location getLocation() { result = this.getVariableUpdate().getLocation() }
override Location getLocation() { result = this.getVariableUpdate().getLocation() }
}
/** A phi node. */

View File

@@ -1,14 +1,17 @@
private import cil
private import CIL
private import codeql.ssa.Ssa as SsaImplCommon
deprecated private module SsaInput implements SsaImplCommon::InputSig<CIL::Location> {
class BasicBlock = CIL::BasicBlock;
class ControlFlowNode = CIL::ControlFlowNode;
BasicBlock getImmediateBasicBlockDominator(BasicBlock bb) { result = bb.getImmediateDominator() }
BasicBlock getABasicBlockSuccessor(BasicBlock bb) { result = bb.getASuccessor() }
class ExitBasicBlock = CIL::ExitBasicBlock;
class ExitBasicBlock extends BasicBlock, CIL::ExitBasicBlock { }
class SourceVariable = CIL::StackVariable;

View File

@@ -80,7 +80,11 @@ module PreSsa {
}
module SsaInput implements SsaImplCommon::InputSig<Location> {
class BasicBlock = PreBasicBlocks::PreBasicBlock;
class BasicBlock extends PreBasicBlocks::PreBasicBlock {
ControlFlowNode getNode(int i) { result = this.getElement(i) }
}
class ControlFlowNode = ControlFlowElement;
BasicBlock getImmediateBasicBlockDominator(BasicBlock bb) { result.immediatelyDominates(bb) }
@@ -192,7 +196,7 @@ module PreSsa {
SsaImpl::ssaDefReachesEndOfBlock(bb, this, _)
}
Location getLocation() {
override Location getLocation() {
result = this.getDefinition().getLocation()
or
exists(Callable c, SsaInput::BasicBlock bb, SsaInput::SourceVariable v |

View File

@@ -427,7 +427,7 @@ module Ssa {
}
/** Gets the location of this SSA definition. */
Location getLocation() { none() }
override Location getLocation() { none() }
}
/**

View File

@@ -36,13 +36,15 @@ module BaseSsa {
class BasicBlock = ControlFlow::BasicBlock;
class ControlFlowNode = ControlFlow::Node;
BasicBlock getImmediateBasicBlockDominator(BasicBlock bb) {
result = bb.getImmediateDominator()
}
BasicBlock getABasicBlockSuccessor(BasicBlock bb) { result = bb.getASuccessor() }
class ExitBasicBlock = ControlFlow::BasicBlocks::ExitBlock;
class ExitBasicBlock extends BasicBlock, ControlFlow::BasicBlocks::ExitBlock { }
class SourceVariable = PreSsa::SimpleLocalScopeVariable;
@@ -93,7 +95,7 @@ module BaseSsa {
not result instanceof PhiNode
}
Location getLocation() {
override Location getLocation() {
result = this.getDefinition().getLocation()
or
exists(Callable c, SsaInput::BasicBlock bb, SsaInput::SourceVariable v |

View File

@@ -263,7 +263,7 @@ module VariableCapture {
private module CaptureInput implements Shared::InputSig<Location> {
private import csharp as Cs
private import semmle.code.csharp.controlflow.ControlFlowGraph
private import semmle.code.csharp.controlflow.ControlFlowGraph as Cfg
private import semmle.code.csharp.controlflow.BasicBlocks as BasicBlocks
private import TaintTrackingPrivate as TaintTrackingPrivate
@@ -271,6 +271,8 @@ module VariableCapture {
Callable getEnclosingCallable() { result = super.getCallable() }
}
class ControlFlowNode = Cfg::ControlFlow::Node;
BasicBlock getImmediateBasicBlockDominator(BasicBlock bb) {
result = bb.getImmediateDominator()
}

View File

@@ -10,11 +10,13 @@ private import semmle.code.csharp.controlflow.internal.PreSsa
private module SsaInput implements SsaImplCommon::InputSig<Location> {
class BasicBlock = ControlFlow::BasicBlock;
class ControlFlowNode = ControlFlow::Node;
BasicBlock getImmediateBasicBlockDominator(BasicBlock bb) { result = bb.getImmediateDominator() }
BasicBlock getABasicBlockSuccessor(BasicBlock bb) { result = bb.getASuccessor() }
class ExitBasicBlock = ControlFlow::BasicBlocks::ExitBlock;
class ExitBasicBlock extends BasicBlock, ControlFlow::BasicBlocks::ExitBlock { }
class SourceVariable = Ssa::SourceVariable;
@@ -24,7 +26,7 @@ private module SsaInput implements SsaImplCommon::InputSig<Location> {
*
* This includes implicit writes via calls.
*/
predicate variableWrite(ControlFlow::BasicBlock bb, int i, Ssa::SourceVariable v, boolean certain) {
predicate variableWrite(BasicBlock bb, int i, Ssa::SourceVariable v, boolean certain) {
variableWriteDirect(bb, i, v, certain)
or
variableWriteQualifier(bb, i, v, certain)
@@ -38,7 +40,7 @@ private module SsaInput implements SsaImplCommon::InputSig<Location> {
*
* This includes implicit reads via calls.
*/
predicate variableRead(ControlFlow::BasicBlock bb, int i, Ssa::SourceVariable v, boolean certain) {
predicate variableRead(BasicBlock bb, int i, Ssa::SourceVariable v, boolean certain) {
variableReadActual(bb, i, v) and
certain = true
or
@@ -1089,7 +1091,7 @@ class DefinitionExt extends Impl::DefinitionExt {
override string toString() { result = this.(Ssa::Definition).toString() }
/** Gets the location of this definition. */
Location getLocation() { result = this.(Ssa::Definition).getLocation() }
override Location getLocation() { result = this.(Ssa::Definition).getLocation() }
/** Gets the enclosing callable of this definition. */
Callable getEnclosingCallable() { result = this.(Ssa::Definition).getEnclosingCallable() }

View File

@@ -72,11 +72,17 @@ private module CaptureInput implements VariableCapture::InputSig<Location> {
class BasicBlock instanceof J::BasicBlock {
string toString() { result = super.toString() }
ControlFlowNode getNode(int i) { result = super.getNode(i) }
int length() { result = super.length() }
Callable getEnclosingCallable() { result = super.getEnclosingCallable() }
Location getLocation() { result = super.getLocation() }
}
class ControlFlowNode = J::ControlFlowNode;
BasicBlock getImmediateBasicBlockDominator(BasicBlock bb) { bbIDominates(result, bb) }
BasicBlock getABasicBlockSuccessor(BasicBlock bb) {

View File

@@ -24,6 +24,8 @@ private module CaptureInput implements Shared::InputSig<Location> {
}
class BasicBlock extends PY::BasicBlock {
int length() { result = count(int i | exists(this.getNode(i))) }
Callable getEnclosingCallable() { result = this.getScope() }
// Note `PY:BasicBlock` does not have a `getLocation`.
@@ -34,6 +36,8 @@ private module CaptureInput implements Shared::InputSig<Location> {
Location getLocation() { result = super.getNode(0).getLocation() }
}
class ControlFlowNode = PY::ControlFlowNode;
BasicBlock getImmediateBasicBlockDominator(BasicBlock bb) { result = bb.getImmediateDominator() }
BasicBlock getABasicBlockSuccessor(BasicBlock bb) { result = bb.getASuccessor() }

View File

@@ -176,9 +176,6 @@ module Ssa {
override string toString() { result = this.getControlFlowNode().toString() }
/** Gets the location of this SSA definition. */
Location getLocation() { result = this.getControlFlowNode().getLocation() }
/** Gets the scope of this SSA definition. */
CfgScope getScope() { result = this.getBasicBlock().getScope() }
}

View File

@@ -352,8 +352,7 @@ module VariableCapture {
}
private module CaptureInput implements Shared::InputSig<Location> {
private import ruby as R
private import codeql.ruby.controlflow.ControlFlowGraph
private import codeql.ruby.controlflow.ControlFlowGraph as Cfg
private import codeql.ruby.controlflow.BasicBlocks as BasicBlocks
private import TaintTrackingPrivate as TaintTrackingPrivate
@@ -361,6 +360,8 @@ module VariableCapture {
Callable getEnclosingCallable() { result = this.getScope() }
}
class ControlFlowNode = Cfg::CfgNode;
BasicBlock getImmediateBasicBlockDominator(BasicBlock bb) {
result = bb.getImmediateDominator()
}

View File

@@ -7,15 +7,18 @@ private import codeql.ruby.ast.Variable
private import Cfg::CfgNodes::ExprNodes
private module SsaInput implements SsaImplCommon::InputSig<Location> {
private import codeql.ruby.controlflow.ControlFlowGraph as Cfg
private import codeql.ruby.controlflow.BasicBlocks as BasicBlocks
class BasicBlock = BasicBlocks::BasicBlock;
class ControlFlowNode = Cfg::CfgNode;
BasicBlock getImmediateBasicBlockDominator(BasicBlock bb) { result = bb.getImmediateDominator() }
BasicBlock getABasicBlockSuccessor(BasicBlock bb) { result = bb.getASuccessor() }
class ExitBasicBlock = BasicBlocks::ExitBasicBlock;
class ExitBasicBlock extends BasicBlock, BasicBlocks::ExitBasicBlock { }
class SourceVariable = LocalVariable;
@@ -494,8 +497,7 @@ class DefinitionExt extends Impl::DefinitionExt {
override string toString() { result = this.(Ssa::Definition).toString() }
/** Gets the location of this definition. */
Location getLocation() { result = this.(Ssa::Definition).getLocation() }
override Location getLocation() { result = this.(Ssa::Definition).getLocation() }
}
/**
@@ -506,5 +508,5 @@ class DefinitionExt extends Impl::DefinitionExt {
class PhiReadNode extends DefinitionExt, Impl::PhiReadNode {
override string toString() { result = "SSA phi read(" + this.getSourceVariable() + ")" }
override Location getLocation() { result = this.getBasicBlock().getLocation() }
override Location getLocation() { result = Impl::PhiReadNode.super.getLocation() }
}

View File

@@ -17,6 +17,12 @@ signature module InputSig<LocationSig Location> {
/** Gets a textual representation of this basic block. */
string toString();
/** Gets the `i`th node in this basic block. */
ControlFlowNode getNode(int i);
/** Gets the length of this basic block. */
int length();
/** Gets the enclosing callable. */
Callable getEnclosingCallable();
@@ -24,6 +30,15 @@ signature module InputSig<LocationSig Location> {
Location getLocation();
}
/** A control flow node. */
class ControlFlowNode {
/** Gets a textual representation of this control flow node. */
string toString();
/** Gets the location of this control flow node. */
Location getLocation();
}
/**
* Gets the basic block that immediately dominates basic block `bb`, if any.
*
@@ -672,6 +687,8 @@ module Flow<LocationSig Location, InputSig<Location> Input> implements OutputSig
private module CaptureSsaInput implements Ssa::InputSig<Location> {
final class BasicBlock = Input::BasicBlock;
final class ControlFlowNode = Input::ControlFlowNode;
BasicBlock getImmediateBasicBlockDominator(BasicBlock bb) {
result = Input::getImmediateBasicBlockDominator(bb)
}
@@ -717,10 +734,10 @@ module Flow<LocationSig Location, InputSig<Location> Input> implements OutputSig
TSynthPhi(CaptureSsa::DefinitionExt phi) {
phi instanceof CaptureSsa::PhiNode or phi instanceof CaptureSsa::PhiReadNode
} or
TExprNode(Expr expr, boolean isPost) {
expr instanceof VariableRead and isPost = [false, true]
TExprNode(Expr expr, Boolean isPost) {
expr instanceof VariableRead
or
synthRead(_, _, _, _, expr) and isPost = [false, true]
synthRead(_, _, _, _, expr)
} or
TParamNode(CapturedParameter p) or
TThisParamNode(Callable c) { captureAccess(_, c) } or

View File

@@ -15,10 +15,25 @@ signature module InputSig<LocationSig Location> {
/** Gets a textual representation of this basic block. */
string toString();
/** Gets the `i`th node in this basic block. */
ControlFlowNode getNode(int i);
/** Gets the length of this basic block. */
int length();
/** Gets the location of this basic block. */
Location getLocation();
}
/** A control flow node. */
class ControlFlowNode {
/** Gets a textual representation of this control flow node. */
string toString();
/** Gets the location of this control flow node. */
Location getLocation();
}
/**
* Gets the basic block that immediately dominates basic block `bb`, if any.
*
@@ -905,6 +920,13 @@ module Make<LocationSig Location, InputSig<Location> Input> {
/** Gets a textual representation of this SSA definition. */
string toString() { result = "SSA def(" + this.getSourceVariable() + ")" }
/** Gets the location of this SSA definition. */
Location getLocation() {
exists(BasicBlock bb, int i | this.definesAt(_, bb, i) |
if i = -1 then result = bb.getLocation() else result = bb.getNode(i).getLocation()
)
}
}
/** An SSA definition that corresponds to a write. */
@@ -961,6 +983,13 @@ module Make<LocationSig Location, InputSig<Location> Input> {
/** Gets a textual representation of this SSA definition. */
string toString() { result = this.(Definition).toString() }
/** Gets the location of this SSA definition. */
Location getLocation() {
exists(BasicBlock bb, int i | this.definesAt(_, bb, i, _) |
if i = -1 then result = bb.getLocation() else result = bb.getNode(i).getLocation()
)
}
}
/**

View File

@@ -8,18 +8,20 @@ module Ssa {
private module SsaInput implements SsaImplCommon::InputSig<Location> {
private import internal.DataFlowPrivate
private import codeql.swift.controlflow.ControlFlowGraph
private import codeql.swift.controlflow.ControlFlowGraph as Cfg
private import codeql.swift.controlflow.CfgNodes
class BasicBlock = BasicBlocks::BasicBlock;
class ControlFlowNode = Cfg::ControlFlowNode;
BasicBlock getImmediateBasicBlockDominator(BasicBlock bb) {
result = bb.getImmediateDominator()
}
BasicBlock getABasicBlockSuccessor(BasicBlock bb) { result = bb.getASuccessor() }
class ExitBasicBlock = BasicBlocks::ExitBasicBlock;
class ExitBasicBlock extends BasicBlock, BasicBlocks::ExitBasicBlock { }
private newtype TSourceVariable =
TNormalSourceVariable(VarDecl v) or
@@ -138,7 +140,7 @@ module Ssa {
cached
class Definition extends SsaImpl::Definition {
cached
Location getLocation() { none() }
override Location getLocation() { none() }
cached
ControlFlowNode getARead() {

View File

@@ -886,16 +886,23 @@ private predicate closureFlowStep(CaptureInput::Expr e1, CaptureInput::Expr e2)
private module CaptureInput implements VariableCapture::InputSig<Location> {
private import swift as S
private import codeql.swift.controlflow.ControlFlowGraph as Cfg
private import codeql.swift.controlflow.BasicBlocks as B
class BasicBlock instanceof B::BasicBlock {
string toString() { result = super.toString() }
ControlFlowNode getNode(int i) { result = super.getNode(i) }
int length() { result = super.length() }
Callable getEnclosingCallable() { result = super.getScope() }
Location getLocation() { result = super.getLocation() }
}
class ControlFlowNode = Cfg::ControlFlowNode;
BasicBlock getImmediateBasicBlockDominator(BasicBlock bb) {
result.(B::BasicBlock).immediatelyDominates(bb)
}