Files
codeql/csharp/ql/test/library-tests/dataflow/defuse/useUseEquivalence.ql
2026-04-30 13:49:23 +02:00

65 lines
2.2 KiB
Plaintext

import csharp
private import semmle.code.csharp.dataflow.internal.BaseSSA
/** "Naive" use-use implementation. */
predicate useReaches(
LocalScopeVariableRead read, BaseSsa::SimpleLocalScopeVariable v, ControlFlowNode cfn
) {
read.getTarget() = v and cfn = read.getControlFlowNode().getASuccessor()
or
exists(ControlFlowNode mid | useReaches(read, v, mid) |
not mid =
any(AssignableDefinition ad | ad.getTarget() = v and ad.isCertain())
.getExpr()
.getControlFlowNode() and
cfn = mid.getASuccessor()
)
}
predicate useUsePair(LocalScopeVariableRead read1, LocalScopeVariableRead read2) {
exists(Assignable a |
useReaches(read1, a, read2.getControlFlowNode()) and
read2.getTarget() = a
)
}
private newtype TLocalScopeVariableReadOrSsaDef =
TLocalScopeVariableRead(LocalScopeVariableRead read) or
TSsaDefinition(SsaDefinition ssaDef)
private TLocalScopeVariableReadOrSsaDef getANextReadOrDef(TLocalScopeVariableReadOrSsaDef prev) {
exists(LocalScopeVariableRead read | prev = TLocalScopeVariableRead(read) |
result = TLocalScopeVariableRead(read.getANextRead())
or
not exists(read.getANextRead()) and
exists(SsaDefinition ssaDef, SsaPhiDefinition phi, BasicBlock bb |
ssaDef.getARead() = read and
phi.getAnInput() = ssaDef and
phi.definesAt(_, bb, _) and
read.getBasicBlock().getASuccessor+() = bb and
result = TSsaDefinition(phi)
)
)
or
exists(SsaDefinition ssaDef | prev = TSsaDefinition(ssaDef) |
result = TLocalScopeVariableRead(Ssa::ssaGetAFirstUse(ssaDef))
or
not exists(Ssa::ssaGetAFirstUse(ssaDef)) and
exists(SsaPhiDefinition phi |
phi.getAnInput() = ssaDef and
result = TSsaDefinition(phi)
)
)
}
private LocalScopeVariableRead getAReachableRead(LocalScopeVariableRead read) {
TLocalScopeVariableRead(result) = getANextReadOrDef+(TLocalScopeVariableRead(read))
}
from LocalScopeVariableRead read1, LocalScopeVariableRead read2, string s
where
read2 = getAReachableRead(read1) and not useUsePair(read1, read2) and s = "not a use/use pair"
or
useUsePair(read1, read2) and not read2 = getAReachableRead(read1) and s = "missing use/use pair"
select read1, read2, s