mirror of
https://github.com/github/codeql.git
synced 2026-05-17 20:57:07 +02:00
Compare commits
84 Commits
rc/3.7
...
rdmarsh2/c
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9ddacf55a5 | ||
|
|
ba1005f875 | ||
|
|
99b21b3d79 | ||
|
|
5b51fcbd3d | ||
|
|
e13ae70eeb | ||
|
|
9f17bd0d89 | ||
|
|
86bb9c38ce | ||
|
|
dc105b404b | ||
|
|
fac28ccbe0 | ||
|
|
06afe9c0f4 | ||
|
|
2e2621adad | ||
|
|
ba1ad00d2a | ||
|
|
c7aa58252a | ||
|
|
12eab3d7f0 | ||
|
|
014dcd1454 | ||
|
|
5d9b25c75d | ||
|
|
1c0f2251e2 | ||
|
|
4cd90a15d0 | ||
|
|
28d95f4d99 | ||
|
|
f1799ae3d2 | ||
|
|
27fcc90a97 | ||
|
|
a50234adb0 | ||
|
|
5e3cb08ed2 | ||
|
|
1a7d3ee831 | ||
|
|
afadcd9b45 | ||
|
|
d96d6721ba | ||
|
|
de8384d904 | ||
|
|
305a23b952 | ||
|
|
f7846a598e | ||
|
|
7e0bd5bde4 | ||
|
|
df9a9f4a56 | ||
|
|
9b257bfa9e | ||
|
|
ca299b9dc1 | ||
|
|
31e15e27fc | ||
|
|
778879908e | ||
|
|
60908de089 | ||
|
|
20625ae60d | ||
|
|
b5458b2125 | ||
|
|
9cdd8cc8f5 | ||
|
|
9395f156de | ||
|
|
684a987abf | ||
|
|
54268f4424 | ||
|
|
8899c1be04 | ||
|
|
280b101caa | ||
|
|
034d197e01 | ||
|
|
2d0a4c3d83 | ||
|
|
5a0183f1e2 | ||
|
|
151529d08f | ||
|
|
b5f3cd7a55 | ||
|
|
49a3e208d7 | ||
|
|
52171d6733 | ||
|
|
ea11f744e1 | ||
|
|
064c9a6938 | ||
|
|
678e433013 | ||
|
|
ea2777fa3e | ||
|
|
55c8863e92 | ||
|
|
3553f3d9b8 | ||
|
|
39c1832995 | ||
|
|
cc41a83a8d | ||
|
|
b471a401cc | ||
|
|
698ccd8850 | ||
|
|
5a312cd0da | ||
|
|
b1c9843d15 | ||
|
|
594fbc678e | ||
|
|
e52fa9a469 | ||
|
|
049af68bc2 | ||
|
|
0aebc90b61 | ||
|
|
bcf4c57060 | ||
|
|
d052b1e3c9 | ||
|
|
26fcf6b25b | ||
|
|
de3e1c39e4 | ||
|
|
473bc92e2d | ||
|
|
af2c96f344 | ||
|
|
7c4d3800b6 | ||
|
|
5c11062d21 | ||
|
|
83af49c72f | ||
|
|
e0cfbb53dc | ||
|
|
844aabe3d6 | ||
|
|
c09c38c9a8 | ||
|
|
d324969d68 | ||
|
|
4ae218729a | ||
|
|
cc8e65f811 | ||
|
|
76b292da6a | ||
|
|
0b691dd46c |
@@ -1,21 +1,3 @@
|
||||
## 0.3.5
|
||||
|
||||
## 0.3.4
|
||||
|
||||
### Deprecated APIs
|
||||
|
||||
* Many classes/predicates/modules with upper-case acronyms in their name have been renamed to follow our style-guide.
|
||||
The old name still exists as a deprecated alias.
|
||||
|
||||
### New Features
|
||||
|
||||
* Added support for getting the link targets of global and namespace variables.
|
||||
* Added a `BlockAssignExpr` class, which models a `memcpy`-like operation used in compiler generated copy/move constructors and assignment operations.
|
||||
|
||||
### Minor Analysis Improvements
|
||||
|
||||
* All deprecated predicates/classes/modules that have been deprecated for over a year have been deleted.
|
||||
|
||||
## 0.3.3
|
||||
|
||||
### New Features
|
||||
|
||||
4
cpp/ql/lib/change-notes/2022-08-01-gvn-functions.md
Normal file
4
cpp/ql/lib/change-notes/2022-08-01-gvn-functions.md
Normal file
@@ -0,0 +1,4 @@
|
||||
---
|
||||
category: minorAnalysis
|
||||
---
|
||||
* Multiple function calls made in the same function may now receive the same global value number when the analysis can show they produce the same results.
|
||||
@@ -0,0 +1,4 @@
|
||||
---
|
||||
category: feature
|
||||
---
|
||||
* Added a `BlockAssignExpr` class, which models a `memcpy`-like operation used in compiler generated copy/move constructors and assignment operations.
|
||||
@@ -0,0 +1,6 @@
|
||||
---
|
||||
category: minorAnalysis
|
||||
---
|
||||
* All deprecated predicates/classes/modules that have been deprecated for over a year have been
|
||||
deleted.
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
---
|
||||
category: feature
|
||||
---
|
||||
* Added support for getting the link targets of global and namespace variables.
|
||||
5
cpp/ql/lib/change-notes/2022-08-22-xml-rename.md
Normal file
5
cpp/ql/lib/change-notes/2022-08-22-xml-rename.md
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
category: deprecated
|
||||
---
|
||||
* Many classes/predicates/modules with upper-case acronyms in their name have been renamed to follow our style-guide.
|
||||
The old name still exists as a deprecated alias.
|
||||
@@ -1,15 +0,0 @@
|
||||
## 0.3.4
|
||||
|
||||
### Deprecated APIs
|
||||
|
||||
* Many classes/predicates/modules with upper-case acronyms in their name have been renamed to follow our style-guide.
|
||||
The old name still exists as a deprecated alias.
|
||||
|
||||
### New Features
|
||||
|
||||
* Added support for getting the link targets of global and namespace variables.
|
||||
* Added a `BlockAssignExpr` class, which models a `memcpy`-like operation used in compiler generated copy/move constructors and assignment operations.
|
||||
|
||||
### Minor Analysis Improvements
|
||||
|
||||
* All deprecated predicates/classes/modules that have been deprecated for over a year have been deleted.
|
||||
@@ -1 +0,0 @@
|
||||
## 0.3.5
|
||||
@@ -1,2 +1,2 @@
|
||||
---
|
||||
lastReleaseVersion: 0.3.5
|
||||
lastReleaseVersion: 0.3.3
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
name: codeql/cpp-all
|
||||
version: 0.3.6-dev
|
||||
version: 0.3.4-dev
|
||||
groups: cpp
|
||||
dbscheme: semmlecode.cpp.dbscheme
|
||||
extractor: cpp
|
||||
|
||||
@@ -1712,6 +1712,11 @@ class SideEffectInstruction extends Instruction {
|
||||
*/
|
||||
class CallSideEffectInstruction extends SideEffectInstruction {
|
||||
CallSideEffectInstruction() { this.getOpcode() instanceof Opcode::CallSideEffect }
|
||||
|
||||
/** Gets the operand for the value that will be read by this instruction */
|
||||
final SideEffectOperand getSideEffectOperand() { result = this.getAnOperand() }
|
||||
|
||||
final Instruction getSideEffect() { result = this.getAnOperand().getDef() }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1723,6 +1728,11 @@ class CallSideEffectInstruction extends SideEffectInstruction {
|
||||
*/
|
||||
class CallReadSideEffectInstruction extends SideEffectInstruction {
|
||||
CallReadSideEffectInstruction() { this.getOpcode() instanceof Opcode::CallReadSideEffect }
|
||||
|
||||
/** Gets the operand for the value that will be read by this instruction */
|
||||
final SideEffectOperand getSideEffectOperand() { result = this.getAnOperand() }
|
||||
|
||||
final Instruction getSideEffect() { result = this.getAnOperand().getDef() }
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import semmle.code.cpp.ir.implementation.aliased_ssa.IR
|
||||
import semmle.code.cpp.ir.internal.Overlap
|
||||
import semmle.code.cpp.ir.internal.IRCppLanguage as Language
|
||||
import semmle.code.cpp.models.interfaces.SideEffect as SideEffect
|
||||
|
||||
@@ -41,8 +41,92 @@ newtype TValueNumber =
|
||||
) {
|
||||
loadTotalOverlapValueNumber(_, irFunc, type, memOperand, operand)
|
||||
} or
|
||||
TCallValueNumber(TCallPartialValueNumber vn) { callValueNumber(_, _, vn) } or
|
||||
TUniqueValueNumber(IRFunction irFunc, Instruction instr) { uniqueValueNumber(instr, irFunc) }
|
||||
|
||||
private class NumberableCallInstruction extends CallInstruction {
|
||||
NumberableCallInstruction() {
|
||||
not this.getResultIRType() instanceof IRVoidType and
|
||||
exists(SideEffect::SideEffectFunction sideEffectFunc |
|
||||
sideEffectFunc = this.getStaticCallTarget()
|
||||
|
|
||||
sideEffectFunc.hasOnlySpecificReadSideEffects() and
|
||||
sideEffectFunc.hasOnlySpecificWriteSideEffects()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private newtype TCallPartialValueNumber =
|
||||
TNilArgument() or
|
||||
TArgument(TCallPartialValueNumber head, TValueNumber arg) {
|
||||
exists(NumberableCallInstruction call, int index |
|
||||
callArgValueNumber(call, index, arg) and
|
||||
callPartialValueNumber(call, index, head)
|
||||
)
|
||||
}
|
||||
|
||||
private predicate callValueNumber(
|
||||
NumberableCallInstruction call, int index, TCallPartialValueNumber vn
|
||||
) {
|
||||
index = max(int n | callArgRank(call, n, _) | n) and
|
||||
exists(TCallPartialValueNumber head, TValueNumber arg |
|
||||
callPartialValueNumber(call, index, pragma[only_bind_out](head)) and
|
||||
callArgValueNumber(call, index, pragma[only_bind_into](arg)) and
|
||||
vn = TArgument(head, arg)
|
||||
)
|
||||
or
|
||||
not exists(int n | callArgRank(call, n, _)) and
|
||||
index = -1 and
|
||||
vn = TNilArgument()
|
||||
}
|
||||
|
||||
private predicate callPartialValueNumber(
|
||||
NumberableCallInstruction call, int index, TCallPartialValueNumber head
|
||||
) {
|
||||
exists(call) and
|
||||
index = 1 and
|
||||
head = TNilArgument()
|
||||
or
|
||||
exists(TCallPartialValueNumber prev, TValueNumber prevVN |
|
||||
callPartialValueNumber(call, index - 1, pragma[only_bind_out](prev)) and
|
||||
callArgValueNumber(call, index - 1, pragma[only_bind_into](prevVN)) and
|
||||
head = TArgument(prev, prevVN)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
private predicate callArgValueNumber(NumberableCallInstruction call, int index, TValueNumber arg) {
|
||||
exists(Instruction instr |
|
||||
callArgRank(call, index, instr) and
|
||||
arg = tvalueNumber(instr)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `arg` is the `index`th element in `call`'s extended argument list, including the `this`
|
||||
* argument and side-effect reads.
|
||||
*/
|
||||
private predicate callArgRank(NumberableCallInstruction call, int index, Instruction arg) {
|
||||
arg =
|
||||
rank[index](int argIndex, boolean isEffect, Instruction instr |
|
||||
// There is no need to include the call's read and write side effects on
|
||||
// all-aliased-memory as `NumberableCallInstruction`s do not read or write
|
||||
// to all-aliased-memory.
|
||||
instr = call.getArgument(argIndex) and
|
||||
isEffect = false
|
||||
or
|
||||
exists(ReadSideEffectInstruction read |
|
||||
read.getPrimaryInstruction() = call and
|
||||
read.getSideEffectOperand().getAnyDef() = instr and
|
||||
read.getIndex() = argIndex and
|
||||
isEffect = true
|
||||
)
|
||||
|
|
||||
instr order by argIndex, isEffect
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* A `CopyInstruction` whose source operand's value is congruent to the definition of that source
|
||||
* operand.
|
||||
@@ -93,6 +177,8 @@ private predicate numberableInstruction(Instruction instr) {
|
||||
instr instanceof CongruentCopyInstruction
|
||||
or
|
||||
instr instanceof LoadTotalOverlapInstruction
|
||||
or
|
||||
instr instanceof NumberableCallInstruction
|
||||
}
|
||||
|
||||
private predicate filteredNumberableInstruction(Instruction instr) {
|
||||
@@ -309,6 +395,11 @@ private TValueNumber nonUniqueValueNumber(Instruction instr) {
|
||||
or
|
||||
// The value number of a copy is just the value number of its source value.
|
||||
result = tvalueNumber(instr.(CongruentCopyInstruction).getSourceValue())
|
||||
or
|
||||
exists(TCallPartialValueNumber pvn |
|
||||
callValueNumber(instr, _, pvn) and
|
||||
result = TCallValueNumber(pvn)
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -8,11 +8,6 @@ private import Imports::RawIR as RawIR
|
||||
private import SsaInstructions
|
||||
private import SsaOperands
|
||||
private import NewIR
|
||||
|
||||
private class OldBlock = Reachability::ReachableBlock;
|
||||
|
||||
private class OldInstruction = Reachability::ReachableInstruction;
|
||||
|
||||
import Cached
|
||||
|
||||
cached
|
||||
@@ -58,7 +53,9 @@ private module Cached {
|
||||
|
||||
cached
|
||||
predicate hasInstruction(TStageInstruction instr) {
|
||||
instr instanceof TRawInstruction and instr instanceof OldInstruction
|
||||
instr instanceof TRawInstruction and
|
||||
instr instanceof OldInstruction and
|
||||
not removedInstruction(instr)
|
||||
or
|
||||
instr = phiInstruction(_, _)
|
||||
or
|
||||
@@ -382,7 +379,14 @@ private module Cached {
|
||||
(
|
||||
if Reachability::isInfeasibleInstructionSuccessor(oldInstruction, kind)
|
||||
then result = unreachedInstruction(instruction.getEnclosingIRFunction())
|
||||
else result = getNewInstruction(oldInstruction.getSuccessor(kind))
|
||||
else
|
||||
if removedInstruction(oldInstruction.getSuccessor(kind))
|
||||
then
|
||||
// the only removed nodes are side-effect writes, but those may have Chi nodes
|
||||
// skip to the following instruction in the old IR, which won't be removed
|
||||
// if we start skipping specific side effects, this may no longer hold
|
||||
result = getNewInstruction(oldInstruction.getSuccessor(kind).getSuccessor(kind))
|
||||
else result = getNewInstruction(oldInstruction.getSuccessor(kind))
|
||||
)
|
||||
)
|
||||
or
|
||||
|
||||
@@ -13,3 +13,15 @@ import semmle.code.cpp.ir.implementation.internal.TOperand::AliasedSsaOperands a
|
||||
|
||||
/** DEPRECATED: Alias for SsaOperands */
|
||||
deprecated module SSAOperands = SsaOperands;
|
||||
|
||||
private import SideEffectElimination as Elim
|
||||
|
||||
predicate removedInstruction(Reachability::ReachableInstruction instr) {
|
||||
Elim::removeableSideEffect(instr)
|
||||
}
|
||||
|
||||
class OldBlock = Reachability::ReachableBlock;
|
||||
|
||||
class OldInstruction extends Reachability::ReachableInstruction {
|
||||
OldInstruction() { not Elim::removeableSideEffect(this) }
|
||||
}
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
import cpp as CPP
|
||||
import semmle.code.cpp.ir.implementation.unaliased_ssa.IR as Unaliased
|
||||
import AliasAnalysis as Alias
|
||||
import AliasConfiguration as Conf
|
||||
import semmle.code.cpp.models.interfaces.SideEffect as SideEffect
|
||||
|
||||
private predicate noLocalSideEffectWrite(CPP::Function func) {
|
||||
forall(Unaliased::AddressOperand addr | addr.getUse().getEnclosingFunction() = func |
|
||||
not (
|
||||
Alias::getAddressOperandAllocation(addr) instanceof Conf::VariableAllocation and
|
||||
Alias::getAddressOperandAllocation(addr).(Conf::VariableAllocation).alwaysEscapes()
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
language[monotonicAggregates]
|
||||
private predicate noTransitiveSideEffectWrite(CPP::Function func) {
|
||||
exists(Unaliased::IRFunction irFunc | irFunc.getFunction() = func) and
|
||||
noLocalSideEffectWrite(func) and
|
||||
forall(Unaliased::CallInstruction call | call.getEnclosingFunction() = func |
|
||||
exists(call.getStaticCallTarget())
|
||||
) and
|
||||
forall(Unaliased::CallInstruction call, CPP::Function callee |
|
||||
call.getStaticCallTarget() = callee and
|
||||
call.getEnclosingFunction() = func
|
||||
|
|
||||
noTransitiveSideEffectWrite(callee)
|
||||
or
|
||||
callee.(SideEffect::SideEffectFunction).hasOnlySpecificWriteSideEffects()
|
||||
)
|
||||
}
|
||||
|
||||
predicate removeableSideEffect(Unaliased::SideEffectInstruction instr) {
|
||||
(
|
||||
instr instanceof Unaliased::CallSideEffectInstruction or
|
||||
instr instanceof Unaliased::CallReadSideEffectInstruction
|
||||
) and
|
||||
noTransitiveSideEffectWrite(instr
|
||||
.getPrimaryInstruction()
|
||||
.(Unaliased::CallInstruction)
|
||||
.getStaticCallTarget())
|
||||
}
|
||||
@@ -34,6 +34,7 @@ newtype TInstruction =
|
||||
AliasedSsa::SSA::hasPhiInstruction(blockStartInstr, memoryLocation)
|
||||
} or
|
||||
TAliasedSsaChiInstruction(TRawInstruction primaryInstruction) {
|
||||
not AliasedSsa::removedInstruction(primaryInstruction) and
|
||||
AliasedSsa::SSA::hasChiInstruction(primaryInstruction)
|
||||
} or
|
||||
TAliasedSsaUnreachedInstruction(IRFunctionBase irFunc) {
|
||||
|
||||
@@ -5,3 +5,5 @@ import semmle.code.cpp.ir.implementation.aliased_ssa.internal.SSAConstruction as
|
||||
|
||||
/** DEPRECATED: Alias for AliasedSsa */
|
||||
deprecated module AliasedSSA = AliasedSsa;
|
||||
|
||||
import semmle.code.cpp.ir.implementation.aliased_ssa.internal.SideEffectElimination as Elim
|
||||
|
||||
@@ -1712,6 +1712,11 @@ class SideEffectInstruction extends Instruction {
|
||||
*/
|
||||
class CallSideEffectInstruction extends SideEffectInstruction {
|
||||
CallSideEffectInstruction() { this.getOpcode() instanceof Opcode::CallSideEffect }
|
||||
|
||||
/** Gets the operand for the value that will be read by this instruction */
|
||||
final SideEffectOperand getSideEffectOperand() { result = this.getAnOperand() }
|
||||
|
||||
final Instruction getSideEffect() { result = this.getAnOperand().getDef() }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1723,6 +1728,11 @@ class CallSideEffectInstruction extends SideEffectInstruction {
|
||||
*/
|
||||
class CallReadSideEffectInstruction extends SideEffectInstruction {
|
||||
CallReadSideEffectInstruction() { this.getOpcode() instanceof Opcode::CallReadSideEffect }
|
||||
|
||||
/** Gets the operand for the value that will be read by this instruction */
|
||||
final SideEffectOperand getSideEffectOperand() { result = this.getAnOperand() }
|
||||
|
||||
final Instruction getSideEffect() { result = this.getAnOperand().getDef() }
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import semmle.code.cpp.ir.implementation.aliased_ssa.IR
|
||||
import semmle.code.cpp.ir.internal.Overlap
|
||||
import semmle.code.cpp.ir.internal.IRCppLanguage as Language
|
||||
import semmle.code.cpp.models.interfaces.SideEffect as SideEffect
|
||||
|
||||
@@ -41,8 +41,92 @@ newtype TValueNumber =
|
||||
) {
|
||||
loadTotalOverlapValueNumber(_, irFunc, type, memOperand, operand)
|
||||
} or
|
||||
TCallValueNumber(TCallPartialValueNumber vn) { callValueNumber(_, _, vn) } or
|
||||
TUniqueValueNumber(IRFunction irFunc, Instruction instr) { uniqueValueNumber(instr, irFunc) }
|
||||
|
||||
private class NumberableCallInstruction extends CallInstruction {
|
||||
NumberableCallInstruction() {
|
||||
not this.getResultIRType() instanceof IRVoidType and
|
||||
exists(SideEffect::SideEffectFunction sideEffectFunc |
|
||||
sideEffectFunc = this.getStaticCallTarget()
|
||||
|
|
||||
sideEffectFunc.hasOnlySpecificReadSideEffects() and
|
||||
sideEffectFunc.hasOnlySpecificWriteSideEffects()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private newtype TCallPartialValueNumber =
|
||||
TNilArgument() or
|
||||
TArgument(TCallPartialValueNumber head, TValueNumber arg) {
|
||||
exists(NumberableCallInstruction call, int index |
|
||||
callArgValueNumber(call, index, arg) and
|
||||
callPartialValueNumber(call, index, head)
|
||||
)
|
||||
}
|
||||
|
||||
private predicate callValueNumber(
|
||||
NumberableCallInstruction call, int index, TCallPartialValueNumber vn
|
||||
) {
|
||||
index = max(int n | callArgRank(call, n, _) | n) and
|
||||
exists(TCallPartialValueNumber head, TValueNumber arg |
|
||||
callPartialValueNumber(call, index, pragma[only_bind_out](head)) and
|
||||
callArgValueNumber(call, index, pragma[only_bind_into](arg)) and
|
||||
vn = TArgument(head, arg)
|
||||
)
|
||||
or
|
||||
not exists(int n | callArgRank(call, n, _)) and
|
||||
index = -1 and
|
||||
vn = TNilArgument()
|
||||
}
|
||||
|
||||
private predicate callPartialValueNumber(
|
||||
NumberableCallInstruction call, int index, TCallPartialValueNumber head
|
||||
) {
|
||||
exists(call) and
|
||||
index = 1 and
|
||||
head = TNilArgument()
|
||||
or
|
||||
exists(TCallPartialValueNumber prev, TValueNumber prevVN |
|
||||
callPartialValueNumber(call, index - 1, pragma[only_bind_out](prev)) and
|
||||
callArgValueNumber(call, index - 1, pragma[only_bind_into](prevVN)) and
|
||||
head = TArgument(prev, prevVN)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
private predicate callArgValueNumber(NumberableCallInstruction call, int index, TValueNumber arg) {
|
||||
exists(Instruction instr |
|
||||
callArgRank(call, index, instr) and
|
||||
arg = tvalueNumber(instr)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `arg` is the `index`th element in `call`'s extended argument list, including the `this`
|
||||
* argument and side-effect reads.
|
||||
*/
|
||||
private predicate callArgRank(NumberableCallInstruction call, int index, Instruction arg) {
|
||||
arg =
|
||||
rank[index](int argIndex, boolean isEffect, Instruction instr |
|
||||
// There is no need to include the call's read and write side effects on
|
||||
// all-aliased-memory as `NumberableCallInstruction`s do not read or write
|
||||
// to all-aliased-memory.
|
||||
instr = call.getArgument(argIndex) and
|
||||
isEffect = false
|
||||
or
|
||||
exists(ReadSideEffectInstruction read |
|
||||
read.getPrimaryInstruction() = call and
|
||||
read.getSideEffectOperand().getAnyDef() = instr and
|
||||
read.getIndex() = argIndex and
|
||||
isEffect = true
|
||||
)
|
||||
|
|
||||
instr order by argIndex, isEffect
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* A `CopyInstruction` whose source operand's value is congruent to the definition of that source
|
||||
* operand.
|
||||
@@ -93,6 +177,8 @@ private predicate numberableInstruction(Instruction instr) {
|
||||
instr instanceof CongruentCopyInstruction
|
||||
or
|
||||
instr instanceof LoadTotalOverlapInstruction
|
||||
or
|
||||
instr instanceof NumberableCallInstruction
|
||||
}
|
||||
|
||||
private predicate filteredNumberableInstruction(Instruction instr) {
|
||||
@@ -309,6 +395,11 @@ private TValueNumber nonUniqueValueNumber(Instruction instr) {
|
||||
or
|
||||
// The value number of a copy is just the value number of its source value.
|
||||
result = tvalueNumber(instr.(CongruentCopyInstruction).getSourceValue())
|
||||
or
|
||||
exists(TCallPartialValueNumber pvn |
|
||||
callValueNumber(instr, _, pvn) and
|
||||
result = TCallValueNumber(pvn)
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1712,6 +1712,11 @@ class SideEffectInstruction extends Instruction {
|
||||
*/
|
||||
class CallSideEffectInstruction extends SideEffectInstruction {
|
||||
CallSideEffectInstruction() { this.getOpcode() instanceof Opcode::CallSideEffect }
|
||||
|
||||
/** Gets the operand for the value that will be read by this instruction */
|
||||
final SideEffectOperand getSideEffectOperand() { result = this.getAnOperand() }
|
||||
|
||||
final Instruction getSideEffect() { result = this.getAnOperand().getDef() }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1723,6 +1728,11 @@ class CallSideEffectInstruction extends SideEffectInstruction {
|
||||
*/
|
||||
class CallReadSideEffectInstruction extends SideEffectInstruction {
|
||||
CallReadSideEffectInstruction() { this.getOpcode() instanceof Opcode::CallReadSideEffect }
|
||||
|
||||
/** Gets the operand for the value that will be read by this instruction */
|
||||
final SideEffectOperand getSideEffectOperand() { result = this.getAnOperand() }
|
||||
|
||||
final Instruction getSideEffect() { result = this.getAnOperand().getDef() }
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import semmle.code.cpp.ir.implementation.aliased_ssa.IR
|
||||
import semmle.code.cpp.ir.internal.Overlap
|
||||
import semmle.code.cpp.ir.internal.IRCppLanguage as Language
|
||||
import semmle.code.cpp.models.interfaces.SideEffect as SideEffect
|
||||
|
||||
@@ -41,8 +41,92 @@ newtype TValueNumber =
|
||||
) {
|
||||
loadTotalOverlapValueNumber(_, irFunc, type, memOperand, operand)
|
||||
} or
|
||||
TCallValueNumber(TCallPartialValueNumber vn) { callValueNumber(_, _, vn) } or
|
||||
TUniqueValueNumber(IRFunction irFunc, Instruction instr) { uniqueValueNumber(instr, irFunc) }
|
||||
|
||||
private class NumberableCallInstruction extends CallInstruction {
|
||||
NumberableCallInstruction() {
|
||||
not this.getResultIRType() instanceof IRVoidType and
|
||||
exists(SideEffect::SideEffectFunction sideEffectFunc |
|
||||
sideEffectFunc = this.getStaticCallTarget()
|
||||
|
|
||||
sideEffectFunc.hasOnlySpecificReadSideEffects() and
|
||||
sideEffectFunc.hasOnlySpecificWriteSideEffects()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private newtype TCallPartialValueNumber =
|
||||
TNilArgument() or
|
||||
TArgument(TCallPartialValueNumber head, TValueNumber arg) {
|
||||
exists(NumberableCallInstruction call, int index |
|
||||
callArgValueNumber(call, index, arg) and
|
||||
callPartialValueNumber(call, index, head)
|
||||
)
|
||||
}
|
||||
|
||||
private predicate callValueNumber(
|
||||
NumberableCallInstruction call, int index, TCallPartialValueNumber vn
|
||||
) {
|
||||
index = max(int n | callArgRank(call, n, _) | n) and
|
||||
exists(TCallPartialValueNumber head, TValueNumber arg |
|
||||
callPartialValueNumber(call, index, pragma[only_bind_out](head)) and
|
||||
callArgValueNumber(call, index, pragma[only_bind_into](arg)) and
|
||||
vn = TArgument(head, arg)
|
||||
)
|
||||
or
|
||||
not exists(int n | callArgRank(call, n, _)) and
|
||||
index = -1 and
|
||||
vn = TNilArgument()
|
||||
}
|
||||
|
||||
private predicate callPartialValueNumber(
|
||||
NumberableCallInstruction call, int index, TCallPartialValueNumber head
|
||||
) {
|
||||
exists(call) and
|
||||
index = 1 and
|
||||
head = TNilArgument()
|
||||
or
|
||||
exists(TCallPartialValueNumber prev, TValueNumber prevVN |
|
||||
callPartialValueNumber(call, index - 1, pragma[only_bind_out](prev)) and
|
||||
callArgValueNumber(call, index - 1, pragma[only_bind_into](prevVN)) and
|
||||
head = TArgument(prev, prevVN)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
private predicate callArgValueNumber(NumberableCallInstruction call, int index, TValueNumber arg) {
|
||||
exists(Instruction instr |
|
||||
callArgRank(call, index, instr) and
|
||||
arg = tvalueNumber(instr)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `arg` is the `index`th element in `call`'s extended argument list, including the `this`
|
||||
* argument and side-effect reads.
|
||||
*/
|
||||
private predicate callArgRank(NumberableCallInstruction call, int index, Instruction arg) {
|
||||
arg =
|
||||
rank[index](int argIndex, boolean isEffect, Instruction instr |
|
||||
// There is no need to include the call's read and write side effects on
|
||||
// all-aliased-memory as `NumberableCallInstruction`s do not read or write
|
||||
// to all-aliased-memory.
|
||||
instr = call.getArgument(argIndex) and
|
||||
isEffect = false
|
||||
or
|
||||
exists(ReadSideEffectInstruction read |
|
||||
read.getPrimaryInstruction() = call and
|
||||
read.getSideEffectOperand().getAnyDef() = instr and
|
||||
read.getIndex() = argIndex and
|
||||
isEffect = true
|
||||
)
|
||||
|
|
||||
instr order by argIndex, isEffect
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* A `CopyInstruction` whose source operand's value is congruent to the definition of that source
|
||||
* operand.
|
||||
@@ -93,6 +177,8 @@ private predicate numberableInstruction(Instruction instr) {
|
||||
instr instanceof CongruentCopyInstruction
|
||||
or
|
||||
instr instanceof LoadTotalOverlapInstruction
|
||||
or
|
||||
instr instanceof NumberableCallInstruction
|
||||
}
|
||||
|
||||
private predicate filteredNumberableInstruction(Instruction instr) {
|
||||
@@ -309,6 +395,11 @@ private TValueNumber nonUniqueValueNumber(Instruction instr) {
|
||||
or
|
||||
// The value number of a copy is just the value number of its source value.
|
||||
result = tvalueNumber(instr.(CongruentCopyInstruction).getSourceValue())
|
||||
or
|
||||
exists(TCallPartialValueNumber pvn |
|
||||
callValueNumber(instr, _, pvn) and
|
||||
result = TCallValueNumber(pvn)
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -8,11 +8,6 @@ private import Imports::RawIR as RawIR
|
||||
private import SsaInstructions
|
||||
private import SsaOperands
|
||||
private import NewIR
|
||||
|
||||
private class OldBlock = Reachability::ReachableBlock;
|
||||
|
||||
private class OldInstruction = Reachability::ReachableInstruction;
|
||||
|
||||
import Cached
|
||||
|
||||
cached
|
||||
@@ -58,7 +53,9 @@ private module Cached {
|
||||
|
||||
cached
|
||||
predicate hasInstruction(TStageInstruction instr) {
|
||||
instr instanceof TRawInstruction and instr instanceof OldInstruction
|
||||
instr instanceof TRawInstruction and
|
||||
instr instanceof OldInstruction and
|
||||
not removedInstruction(instr)
|
||||
or
|
||||
instr = phiInstruction(_, _)
|
||||
or
|
||||
@@ -382,7 +379,14 @@ private module Cached {
|
||||
(
|
||||
if Reachability::isInfeasibleInstructionSuccessor(oldInstruction, kind)
|
||||
then result = unreachedInstruction(instruction.getEnclosingIRFunction())
|
||||
else result = getNewInstruction(oldInstruction.getSuccessor(kind))
|
||||
else
|
||||
if removedInstruction(oldInstruction.getSuccessor(kind))
|
||||
then
|
||||
// the only removed nodes are side-effect writes, but those may have Chi nodes
|
||||
// skip to the following instruction in the old IR, which won't be removed
|
||||
// if we start skipping specific side effects, this may no longer hold
|
||||
result = getNewInstruction(oldInstruction.getSuccessor(kind).getSuccessor(kind))
|
||||
else result = getNewInstruction(oldInstruction.getSuccessor(kind))
|
||||
)
|
||||
)
|
||||
or
|
||||
|
||||
@@ -14,3 +14,9 @@ import semmle.code.cpp.ir.implementation.internal.TOperand::UnaliasedSsaOperands
|
||||
|
||||
/** DEPRECATED: Alias for SsaOperands */
|
||||
deprecated module SSAOperands = SsaOperands;
|
||||
|
||||
predicate removedInstruction(Reachability::ReachableInstruction instr) { none() }
|
||||
|
||||
class OldBlock = Reachability::ReachableBlock;
|
||||
|
||||
class OldInstruction = Reachability::ReachableInstruction;
|
||||
|
||||
@@ -29,7 +29,4 @@ where
|
||||
n = strictcount(ComplexStmt s | s = b.getAStmt()) and
|
||||
n > 3 and
|
||||
complexStmt = b.getAStmt()
|
||||
select b,
|
||||
"Block with too many statements (" + n.toString() +
|
||||
" complex statements in the block). Complex statements at: $@", complexStmt,
|
||||
complexStmt.toString()
|
||||
select b, "Block with too many statements (" + n.toString() + " complex statements in the block)."
|
||||
|
||||
@@ -110,4 +110,4 @@ where
|
||||
emptyBlock(s, eb) and
|
||||
not emptyBlockContainsNonchild(eb) and
|
||||
not lineComment(eb)
|
||||
select eb, "Empty block without comment"
|
||||
select eb, "Empty block without comment."
|
||||
|
||||
@@ -1,11 +1,3 @@
|
||||
## 0.3.4
|
||||
|
||||
## 0.3.3
|
||||
|
||||
### Minor Analysis Improvements
|
||||
|
||||
* The "Cleartext storage of sensitive information in buffer" (`cpp/cleartext-storage-buffer`) query has been improved to produce fewer false positives.
|
||||
|
||||
## 0.3.2
|
||||
|
||||
### Minor Analysis Improvements
|
||||
|
||||
@@ -12,4 +12,4 @@
|
||||
import CommentedOutCode
|
||||
|
||||
from CommentedOutCode comment
|
||||
select comment, "This comment appears to contain commented-out code"
|
||||
select comment, "This comment appears to contain commented-out code."
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
/**
|
||||
* @name Sign check of bitwise operation
|
||||
* @description Checking the sign of a bitwise operation often has surprising
|
||||
* edge cases.
|
||||
* @description Checking the sign of the result of a bitwise operation may yield unexpected results.
|
||||
* @kind problem
|
||||
* @problem.severity warning
|
||||
* @precision high
|
||||
@@ -26,4 +25,4 @@ where
|
||||
forall(int op | op = lhs.(BitwiseAndExpr).getAnOperand().getValue().toInt() | op < 0) and
|
||||
// exception for cases involving macros
|
||||
not e.isAffectedByMacro()
|
||||
select e, "Potential unsafe sign check of a bitwise operation."
|
||||
select e, "Potentially unsafe sign check of a bitwise operation."
|
||||
|
||||
@@ -21,4 +21,4 @@ where
|
||||
FloatingPointType and
|
||||
not ro.getAnOperand().isConstant() and // comparisons to constants generate too many false positives
|
||||
not left.(VariableAccess).getTarget() = right.(VariableAccess).getTarget() // skip self comparison
|
||||
select ro, "Equality test on floating point values may not behave as expected."
|
||||
select ro, "Equality checks on floating point values can yield unexpected results."
|
||||
|
||||
@@ -13,10 +13,11 @@
|
||||
|
||||
import cpp
|
||||
|
||||
from EnumSwitch es, float missing, float total
|
||||
from EnumSwitch es, float missing, float total, EnumConstant case
|
||||
where
|
||||
not es.hasDefaultCase() and
|
||||
missing = count(es.getAMissingCase()) and
|
||||
total = missing + count(es.getASwitchCase()) and
|
||||
missing / total < 0.3
|
||||
select es, "Switch statement is missing case for " + es.getAMissingCase().getName()
|
||||
missing / total < 0.3 and
|
||||
case = es.getAMissingCase()
|
||||
select es, "Switch statement does not have a case for $@.", case, case.getName()
|
||||
|
||||
@@ -163,46 +163,19 @@ TGlobalAddress globalAddress(Instruction instr) {
|
||||
result = globalAddress(instr.(PointerOffsetInstruction).getLeft())
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a first `StoreInstruction` that writes to address `globalAddress` reachable
|
||||
* from `block`.
|
||||
*/
|
||||
StoreInstruction getFirstStore(IRBlock block, TGlobalAddress globalAddress) {
|
||||
1 = getStoreRank(result, block, globalAddress)
|
||||
or
|
||||
not exists(getStoreRank(_, block, globalAddress)) and
|
||||
result = getFirstStore(block.getASuccessor(), globalAddress)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the rank of `store` in block `block` (i.e., a rank of `1` means that it is the
|
||||
* first `store` to write to `globalAddress`, a rank of `2` means it's the second, etc.)
|
||||
*/
|
||||
int getStoreRank(StoreInstruction store, IRBlock block, TGlobalAddress globalAddress) {
|
||||
blockStoresToAddress(block, _, store, globalAddress) and
|
||||
store =
|
||||
rank[result](StoreInstruction anotherStore, int i |
|
||||
blockStoresToAddress(_, i, anotherStore, globalAddress)
|
||||
|
|
||||
anotherStore order by i
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a next subsequent `StoreInstruction` to write to `globalAddress`
|
||||
* after `store` has done so.
|
||||
*/
|
||||
StoreInstruction getANextStoreTo(StoreInstruction store, TGlobalAddress globalAddress) {
|
||||
exists(IRBlock block, int rnk |
|
||||
rnk = getStoreRank(store, block, globalAddress) and
|
||||
rnk + 1 = getStoreRank(result, block, globalAddress)
|
||||
/** Gets a `StoreInstruction` that may be executed after executing `store`. */
|
||||
pragma[inline]
|
||||
StoreInstruction getAStoreStrictlyAfter(StoreInstruction store) {
|
||||
exists(IRBlock block, int index1, int index2 |
|
||||
block.getInstruction(index1) = store and
|
||||
block.getInstruction(index2) = result and
|
||||
index2 > index1
|
||||
)
|
||||
or
|
||||
exists(IRBlock block, int rnk, IRBlock succ |
|
||||
rnk = getStoreRank(store, block, globalAddress) and
|
||||
not rnk + 1 = getStoreRank(_, block, globalAddress) and
|
||||
succ = block.getASuccessor() and
|
||||
result = getFirstStore(succ, globalAddress)
|
||||
exists(IRBlock block1, IRBlock block2 |
|
||||
store.getBlock() = block1 and
|
||||
result.getBlock() = block2 and
|
||||
block1.getASuccessor+() = block2
|
||||
)
|
||||
}
|
||||
|
||||
@@ -219,7 +192,7 @@ predicate stackAddressEscapes(
|
||||
stackPointerFlowsToUse(store.getSourceValue(), vai)
|
||||
) and
|
||||
// Ensure there's no subsequent store that overrides the global address.
|
||||
not exists(getANextStoreTo(store, globalAddress))
|
||||
not globalAddress = globalAddress(getAStoreStrictlyAfter(store).getDestinationAddress())
|
||||
}
|
||||
|
||||
predicate blockStoresToAddress(
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
## 0.3.3
|
||||
|
||||
### Minor Analysis Improvements
|
||||
|
||||
---
|
||||
category: minorAnalysis
|
||||
---
|
||||
* The "Cleartext storage of sensitive information in buffer" (`cpp/cleartext-storage-buffer`) query has been improved to produce fewer false positives.
|
||||
4
cpp/ql/src/change-notes/2022-08-23-alert-messages.md
Normal file
4
cpp/ql/src/change-notes/2022-08-23-alert-messages.md
Normal file
@@ -0,0 +1,4 @@
|
||||
---
|
||||
category: minorAnalysis
|
||||
---
|
||||
* The alert message of many queries have been changed to make the message consistent with other languages.
|
||||
@@ -1 +0,0 @@
|
||||
## 0.3.4
|
||||
@@ -1,2 +1,2 @@
|
||||
---
|
||||
lastReleaseVersion: 0.3.4
|
||||
lastReleaseVersion: 0.3.2
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
name: codeql/cpp-queries
|
||||
version: 0.3.5-dev
|
||||
version: 0.3.3-dev
|
||||
groups:
|
||||
- cpp
|
||||
- queries
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1050,46 +1050,36 @@ ssa.cpp:
|
||||
# 240| r240_3(glval<unknown>) = FunctionAddress[Constructible] :
|
||||
# 240| r240_4(int) = Constant[1] :
|
||||
# 240| v240_5(void) = Call[Constructible] : func:r240_3, this:r240_1, 0:r240_4
|
||||
# 240| m240_6(unknown) = ^CallSideEffect : ~m239_4
|
||||
# 240| m240_7(unknown) = Chi : total:m239_4, partial:m240_6
|
||||
# 240| m240_8(Constructible) = ^IndirectMayWriteSideEffect[-1] : &:r240_1
|
||||
# 240| m240_9(Constructible) = Chi : total:m240_2, partial:m240_8
|
||||
# 240| m240_6(Constructible) = ^IndirectMayWriteSideEffect[-1] : &:r240_1
|
||||
# 240| m240_7(Constructible) = Chi : total:m240_2, partial:m240_6
|
||||
# 241| r241_1(glval<Constructible>) = VariableAddress[c] :
|
||||
# 241| r241_2(glval<unknown>) = FunctionAddress[g] :
|
||||
# 241| v241_3(void) = Call[g] : func:r241_2, this:r241_1
|
||||
# 241| m241_4(unknown) = ^CallSideEffect : ~m240_7
|
||||
# 241| m241_5(unknown) = Chi : total:m240_7, partial:m241_4
|
||||
# 241| v241_6(void) = ^IndirectReadSideEffect[-1] : &:r241_1, m240_9
|
||||
# 241| m241_7(Constructible) = ^IndirectMayWriteSideEffect[-1] : &:r241_1
|
||||
# 241| m241_8(Constructible) = Chi : total:m240_9, partial:m241_7
|
||||
# 241| v241_4(void) = ^IndirectReadSideEffect[-1] : &:r241_1, m240_7
|
||||
# 241| m241_5(Constructible) = ^IndirectMayWriteSideEffect[-1] : &:r241_1
|
||||
# 241| m241_6(Constructible) = Chi : total:m240_7, partial:m241_5
|
||||
# 242| r242_1(glval<Constructible>) = VariableAddress[c] :
|
||||
# 242| r242_2(glval<unknown>) = FunctionAddress[g] :
|
||||
# 242| v242_3(void) = Call[g] : func:r242_2, this:r242_1
|
||||
# 242| m242_4(unknown) = ^CallSideEffect : ~m241_5
|
||||
# 242| m242_5(unknown) = Chi : total:m241_5, partial:m242_4
|
||||
# 242| v242_6(void) = ^IndirectReadSideEffect[-1] : &:r242_1, m241_8
|
||||
# 242| m242_7(Constructible) = ^IndirectMayWriteSideEffect[-1] : &:r242_1
|
||||
# 242| m242_8(Constructible) = Chi : total:m241_8, partial:m242_7
|
||||
# 242| v242_4(void) = ^IndirectReadSideEffect[-1] : &:r242_1, m241_6
|
||||
# 242| m242_5(Constructible) = ^IndirectMayWriteSideEffect[-1] : &:r242_1
|
||||
# 242| m242_6(Constructible) = Chi : total:m241_6, partial:m242_5
|
||||
# 243| r243_1(glval<Constructible>) = VariableAddress[c2] :
|
||||
# 243| m243_2(Constructible) = Uninitialized[c2] : &:r243_1
|
||||
# 243| r243_3(glval<unknown>) = FunctionAddress[Constructible] :
|
||||
# 243| r243_4(int) = Constant[2] :
|
||||
# 243| v243_5(void) = Call[Constructible] : func:r243_3, this:r243_1, 0:r243_4
|
||||
# 243| m243_6(unknown) = ^CallSideEffect : ~m242_5
|
||||
# 243| m243_7(unknown) = Chi : total:m242_5, partial:m243_6
|
||||
# 243| m243_8(Constructible) = ^IndirectMayWriteSideEffect[-1] : &:r243_1
|
||||
# 243| m243_9(Constructible) = Chi : total:m243_2, partial:m243_8
|
||||
# 243| m243_6(Constructible) = ^IndirectMayWriteSideEffect[-1] : &:r243_1
|
||||
# 243| m243_7(Constructible) = Chi : total:m243_2, partial:m243_6
|
||||
# 244| r244_1(glval<Constructible>) = VariableAddress[c2] :
|
||||
# 244| r244_2(glval<unknown>) = FunctionAddress[g] :
|
||||
# 244| v244_3(void) = Call[g] : func:r244_2, this:r244_1
|
||||
# 244| m244_4(unknown) = ^CallSideEffect : ~m243_7
|
||||
# 244| m244_5(unknown) = Chi : total:m243_7, partial:m244_4
|
||||
# 244| v244_6(void) = ^IndirectReadSideEffect[-1] : &:r244_1, m243_9
|
||||
# 244| m244_7(Constructible) = ^IndirectMayWriteSideEffect[-1] : &:r244_1
|
||||
# 244| m244_8(Constructible) = Chi : total:m243_9, partial:m244_7
|
||||
# 244| v244_4(void) = ^IndirectReadSideEffect[-1] : &:r244_1, m243_7
|
||||
# 244| m244_5(Constructible) = ^IndirectMayWriteSideEffect[-1] : &:r244_1
|
||||
# 244| m244_6(Constructible) = Chi : total:m243_7, partial:m244_5
|
||||
# 245| v245_1(void) = NoOp :
|
||||
# 239| v239_5(void) = ReturnVoid :
|
||||
# 239| v239_6(void) = AliasedUse : ~m244_5
|
||||
# 239| v239_6(void) = AliasedUse : m239_3
|
||||
# 239| v239_7(void) = ExitFunction :
|
||||
|
||||
# 247| char* VoidStarIndirectParameters(char*, int)
|
||||
@@ -1391,43 +1381,37 @@ ssa.cpp:
|
||||
# 294| r294_18(glval<int>) = VariableAddress[x] :
|
||||
# 294| r294_19(int) = Load[x] : &:r294_18, m291_6
|
||||
# 294| v294_20(void) = Call[A] : func:r294_17, this:r294_16, 0:r294_19
|
||||
# 294| m294_21(unknown) = ^CallSideEffect : ~m294_14
|
||||
# 294| m294_22(unknown) = Chi : total:m294_14, partial:m294_21
|
||||
# 294| m294_23(A) = ^IndirectMayWriteSideEffect[-1] : &:r294_16
|
||||
# 294| m294_24(unknown) = Chi : total:m294_15, partial:m294_23
|
||||
# 294| v294_25(void) = Call[A] : func:r294_9, this:r294_8, 0:r294_16
|
||||
# 294| m294_26(unknown) = ^CallSideEffect : ~m294_22
|
||||
# 294| m294_27(unknown) = Chi : total:m294_22, partial:m294_26
|
||||
# 294| v294_28(void) = ^BufferReadSideEffect[0] : &:r294_16, ~m294_24
|
||||
# 294| m294_29(A) = ^IndirectMayWriteSideEffect[-1] : &:r294_8
|
||||
# 294| m294_30(unknown) = Chi : total:m294_7, partial:m294_29
|
||||
# 294| m294_31(unknown) = ^BufferMayWriteSideEffect[0] : &:r294_16
|
||||
# 294| m294_32(unknown) = Chi : total:m294_24, partial:m294_31
|
||||
# 294| r294_33(glval<int>) = FieldAddress[i] : r294_8
|
||||
# 294| r294_34(int) = Load[?] : &:r294_33, ~m294_30
|
||||
# 294| m294_35(int) = Store[j] : &:r294_1, r294_34
|
||||
# 294| m294_21(A) = ^IndirectMayWriteSideEffect[-1] : &:r294_16
|
||||
# 294| m294_22(unknown) = Chi : total:m294_15, partial:m294_21
|
||||
# 294| v294_23(void) = Call[A] : func:r294_9, this:r294_8, 0:r294_16
|
||||
# 294| v294_24(void) = ^BufferReadSideEffect[0] : &:r294_16, ~m294_22
|
||||
# 294| m294_25(A) = ^IndirectMayWriteSideEffect[-1] : &:r294_8
|
||||
# 294| m294_26(unknown) = Chi : total:m294_7, partial:m294_25
|
||||
# 294| m294_27(unknown) = ^BufferMayWriteSideEffect[0] : &:r294_16
|
||||
# 294| m294_28(unknown) = Chi : total:m294_22, partial:m294_27
|
||||
# 294| r294_29(glval<int>) = FieldAddress[i] : r294_8
|
||||
# 294| r294_30(int) = Load[?] : &:r294_29, ~m294_26
|
||||
# 294| m294_31(int) = Store[j] : &:r294_1, r294_30
|
||||
# 295| r295_1(glval<A *>) = VariableAddress[a] :
|
||||
# 295| r295_2(glval<unknown>) = FunctionAddress[operator new] :
|
||||
# 295| r295_3(unsigned long) = Constant[4] :
|
||||
# 295| r295_4(void *) = Call[operator new] : func:r295_2, 0:r295_3
|
||||
# 295| m295_5(unknown) = ^CallSideEffect : ~m294_27
|
||||
# 295| m295_6(unknown) = Chi : total:m294_27, partial:m295_5
|
||||
# 295| m295_5(unknown) = ^CallSideEffect : ~m294_14
|
||||
# 295| m295_6(unknown) = Chi : total:m294_14, partial:m295_5
|
||||
# 295| m295_7(unknown) = ^InitializeDynamicAllocation : &:r295_4
|
||||
# 295| r295_8(A *) = Convert : r295_4
|
||||
# 295| r295_9(glval<unknown>) = FunctionAddress[A] :
|
||||
# 295| v295_10(void) = Call[A] : func:r295_9, this:r295_8
|
||||
# 295| m295_11(unknown) = ^CallSideEffect : ~m295_6
|
||||
# 295| m295_12(unknown) = Chi : total:m295_6, partial:m295_11
|
||||
# 295| m295_13(A) = ^IndirectMayWriteSideEffect[-1] : &:r295_8
|
||||
# 295| m295_14(unknown) = Chi : total:m295_7, partial:m295_13
|
||||
# 295| m295_15(A *) = Store[a] : &:r295_1, r295_8
|
||||
# 295| m295_11(A) = ^IndirectMayWriteSideEffect[-1] : &:r295_8
|
||||
# 295| m295_12(unknown) = Chi : total:m295_7, partial:m295_11
|
||||
# 295| m295_13(A *) = Store[a] : &:r295_1, r295_8
|
||||
# 296| r296_1(glval<Point *>) = VariableAddress[#return] :
|
||||
# 296| r296_2(glval<Point *>) = VariableAddress[p] :
|
||||
# 296| r296_3(Point *) = Load[p] : &:r296_2, m292_9
|
||||
# 296| m296_4(Point *) = Store[#return] : &:r296_1, r296_3
|
||||
# 291| r291_7(glval<Point *>) = VariableAddress[#return] :
|
||||
# 291| v291_8(void) = ReturnValue : &:r291_7, m296_4
|
||||
# 291| v291_9(void) = AliasedUse : ~m295_12
|
||||
# 291| v291_9(void) = AliasedUse : ~m295_6
|
||||
# 291| v291_10(void) = ExitFunction :
|
||||
|
||||
# 301| int main(int, char**)
|
||||
|
||||
@@ -1045,46 +1045,36 @@ ssa.cpp:
|
||||
# 240| r240_3(glval<unknown>) = FunctionAddress[Constructible] :
|
||||
# 240| r240_4(int) = Constant[1] :
|
||||
# 240| v240_5(void) = Call[Constructible] : func:r240_3, this:r240_1, 0:r240_4
|
||||
# 240| m240_6(unknown) = ^CallSideEffect : ~m239_4
|
||||
# 240| m240_7(unknown) = Chi : total:m239_4, partial:m240_6
|
||||
# 240| m240_8(Constructible) = ^IndirectMayWriteSideEffect[-1] : &:r240_1
|
||||
# 240| m240_9(Constructible) = Chi : total:m240_2, partial:m240_8
|
||||
# 240| m240_6(Constructible) = ^IndirectMayWriteSideEffect[-1] : &:r240_1
|
||||
# 240| m240_7(Constructible) = Chi : total:m240_2, partial:m240_6
|
||||
# 241| r241_1(glval<Constructible>) = VariableAddress[c] :
|
||||
# 241| r241_2(glval<unknown>) = FunctionAddress[g] :
|
||||
# 241| v241_3(void) = Call[g] : func:r241_2, this:r241_1
|
||||
# 241| m241_4(unknown) = ^CallSideEffect : ~m240_7
|
||||
# 241| m241_5(unknown) = Chi : total:m240_7, partial:m241_4
|
||||
# 241| v241_6(void) = ^IndirectReadSideEffect[-1] : &:r241_1, m240_9
|
||||
# 241| m241_7(Constructible) = ^IndirectMayWriteSideEffect[-1] : &:r241_1
|
||||
# 241| m241_8(Constructible) = Chi : total:m240_9, partial:m241_7
|
||||
# 241| v241_4(void) = ^IndirectReadSideEffect[-1] : &:r241_1, m240_7
|
||||
# 241| m241_5(Constructible) = ^IndirectMayWriteSideEffect[-1] : &:r241_1
|
||||
# 241| m241_6(Constructible) = Chi : total:m240_7, partial:m241_5
|
||||
# 242| r242_1(glval<Constructible>) = VariableAddress[c] :
|
||||
# 242| r242_2(glval<unknown>) = FunctionAddress[g] :
|
||||
# 242| v242_3(void) = Call[g] : func:r242_2, this:r242_1
|
||||
# 242| m242_4(unknown) = ^CallSideEffect : ~m241_5
|
||||
# 242| m242_5(unknown) = Chi : total:m241_5, partial:m242_4
|
||||
# 242| v242_6(void) = ^IndirectReadSideEffect[-1] : &:r242_1, m241_8
|
||||
# 242| m242_7(Constructible) = ^IndirectMayWriteSideEffect[-1] : &:r242_1
|
||||
# 242| m242_8(Constructible) = Chi : total:m241_8, partial:m242_7
|
||||
# 242| v242_4(void) = ^IndirectReadSideEffect[-1] : &:r242_1, m241_6
|
||||
# 242| m242_5(Constructible) = ^IndirectMayWriteSideEffect[-1] : &:r242_1
|
||||
# 242| m242_6(Constructible) = Chi : total:m241_6, partial:m242_5
|
||||
# 243| r243_1(glval<Constructible>) = VariableAddress[c2] :
|
||||
# 243| m243_2(Constructible) = Uninitialized[c2] : &:r243_1
|
||||
# 243| r243_3(glval<unknown>) = FunctionAddress[Constructible] :
|
||||
# 243| r243_4(int) = Constant[2] :
|
||||
# 243| v243_5(void) = Call[Constructible] : func:r243_3, this:r243_1, 0:r243_4
|
||||
# 243| m243_6(unknown) = ^CallSideEffect : ~m242_5
|
||||
# 243| m243_7(unknown) = Chi : total:m242_5, partial:m243_6
|
||||
# 243| m243_8(Constructible) = ^IndirectMayWriteSideEffect[-1] : &:r243_1
|
||||
# 243| m243_9(Constructible) = Chi : total:m243_2, partial:m243_8
|
||||
# 243| m243_6(Constructible) = ^IndirectMayWriteSideEffect[-1] : &:r243_1
|
||||
# 243| m243_7(Constructible) = Chi : total:m243_2, partial:m243_6
|
||||
# 244| r244_1(glval<Constructible>) = VariableAddress[c2] :
|
||||
# 244| r244_2(glval<unknown>) = FunctionAddress[g] :
|
||||
# 244| v244_3(void) = Call[g] : func:r244_2, this:r244_1
|
||||
# 244| m244_4(unknown) = ^CallSideEffect : ~m243_7
|
||||
# 244| m244_5(unknown) = Chi : total:m243_7, partial:m244_4
|
||||
# 244| v244_6(void) = ^IndirectReadSideEffect[-1] : &:r244_1, m243_9
|
||||
# 244| m244_7(Constructible) = ^IndirectMayWriteSideEffect[-1] : &:r244_1
|
||||
# 244| m244_8(Constructible) = Chi : total:m243_9, partial:m244_7
|
||||
# 244| v244_4(void) = ^IndirectReadSideEffect[-1] : &:r244_1, m243_7
|
||||
# 244| m244_5(Constructible) = ^IndirectMayWriteSideEffect[-1] : &:r244_1
|
||||
# 244| m244_6(Constructible) = Chi : total:m243_7, partial:m244_5
|
||||
# 245| v245_1(void) = NoOp :
|
||||
# 239| v239_5(void) = ReturnVoid :
|
||||
# 239| v239_6(void) = AliasedUse : ~m244_5
|
||||
# 239| v239_6(void) = AliasedUse : m239_3
|
||||
# 239| v239_7(void) = ExitFunction :
|
||||
|
||||
# 247| char* VoidStarIndirectParameters(char*, int)
|
||||
@@ -1385,43 +1375,37 @@ ssa.cpp:
|
||||
# 294| r294_18(glval<int>) = VariableAddress[x] :
|
||||
# 294| r294_19(int) = Load[x] : &:r294_18, m291_6
|
||||
# 294| v294_20(void) = Call[A] : func:r294_17, this:r294_16, 0:r294_19
|
||||
# 294| m294_21(unknown) = ^CallSideEffect : ~m294_14
|
||||
# 294| m294_22(unknown) = Chi : total:m294_14, partial:m294_21
|
||||
# 294| m294_23(A) = ^IndirectMayWriteSideEffect[-1] : &:r294_16
|
||||
# 294| m294_24(unknown) = Chi : total:m294_15, partial:m294_23
|
||||
# 294| v294_25(void) = Call[A] : func:r294_9, this:r294_8, 0:r294_16
|
||||
# 294| m294_26(unknown) = ^CallSideEffect : ~m294_22
|
||||
# 294| m294_27(unknown) = Chi : total:m294_22, partial:m294_26
|
||||
# 294| v294_28(void) = ^BufferReadSideEffect[0] : &:r294_16, ~m294_24
|
||||
# 294| m294_29(A) = ^IndirectMayWriteSideEffect[-1] : &:r294_8
|
||||
# 294| m294_30(unknown) = Chi : total:m294_7, partial:m294_29
|
||||
# 294| m294_31(unknown) = ^BufferMayWriteSideEffect[0] : &:r294_16
|
||||
# 294| m294_32(unknown) = Chi : total:m294_24, partial:m294_31
|
||||
# 294| r294_33(glval<int>) = FieldAddress[i] : r294_8
|
||||
# 294| r294_34(int) = Load[?] : &:r294_33, ~m294_30
|
||||
# 294| m294_35(int) = Store[j] : &:r294_1, r294_34
|
||||
# 294| m294_21(A) = ^IndirectMayWriteSideEffect[-1] : &:r294_16
|
||||
# 294| m294_22(unknown) = Chi : total:m294_15, partial:m294_21
|
||||
# 294| v294_23(void) = Call[A] : func:r294_9, this:r294_8, 0:r294_16
|
||||
# 294| v294_24(void) = ^BufferReadSideEffect[0] : &:r294_16, ~m294_22
|
||||
# 294| m294_25(A) = ^IndirectMayWriteSideEffect[-1] : &:r294_8
|
||||
# 294| m294_26(unknown) = Chi : total:m294_7, partial:m294_25
|
||||
# 294| m294_27(unknown) = ^BufferMayWriteSideEffect[0] : &:r294_16
|
||||
# 294| m294_28(unknown) = Chi : total:m294_22, partial:m294_27
|
||||
# 294| r294_29(glval<int>) = FieldAddress[i] : r294_8
|
||||
# 294| r294_30(int) = Load[?] : &:r294_29, ~m294_26
|
||||
# 294| m294_31(int) = Store[j] : &:r294_1, r294_30
|
||||
# 295| r295_1(glval<A *>) = VariableAddress[a] :
|
||||
# 295| r295_2(glval<unknown>) = FunctionAddress[operator new] :
|
||||
# 295| r295_3(unsigned long) = Constant[4] :
|
||||
# 295| r295_4(void *) = Call[operator new] : func:r295_2, 0:r295_3
|
||||
# 295| m295_5(unknown) = ^CallSideEffect : ~m294_27
|
||||
# 295| m295_6(unknown) = Chi : total:m294_27, partial:m295_5
|
||||
# 295| m295_5(unknown) = ^CallSideEffect : ~m294_14
|
||||
# 295| m295_6(unknown) = Chi : total:m294_14, partial:m295_5
|
||||
# 295| m295_7(unknown) = ^InitializeDynamicAllocation : &:r295_4
|
||||
# 295| r295_8(A *) = Convert : r295_4
|
||||
# 295| r295_9(glval<unknown>) = FunctionAddress[A] :
|
||||
# 295| v295_10(void) = Call[A] : func:r295_9, this:r295_8
|
||||
# 295| m295_11(unknown) = ^CallSideEffect : ~m295_6
|
||||
# 295| m295_12(unknown) = Chi : total:m295_6, partial:m295_11
|
||||
# 295| m295_13(A) = ^IndirectMayWriteSideEffect[-1] : &:r295_8
|
||||
# 295| m295_14(unknown) = Chi : total:m295_7, partial:m295_13
|
||||
# 295| m295_15(A *) = Store[a] : &:r295_1, r295_8
|
||||
# 295| m295_11(A) = ^IndirectMayWriteSideEffect[-1] : &:r295_8
|
||||
# 295| m295_12(unknown) = Chi : total:m295_7, partial:m295_11
|
||||
# 295| m295_13(A *) = Store[a] : &:r295_1, r295_8
|
||||
# 296| r296_1(glval<Point *>) = VariableAddress[#return] :
|
||||
# 296| r296_2(glval<Point *>) = VariableAddress[p] :
|
||||
# 296| r296_3(Point *) = Load[p] : &:r296_2, m292_9
|
||||
# 296| m296_4(Point *) = Store[#return] : &:r296_1, r296_3
|
||||
# 291| r291_7(glval<Point *>) = VariableAddress[#return] :
|
||||
# 291| v291_8(void) = ReturnValue : &:r291_7, m296_4
|
||||
# 291| v291_9(void) = AliasedUse : ~m295_12
|
||||
# 291| v291_9(void) = AliasedUse : ~m295_6
|
||||
# 291| v291_10(void) = ExitFunction :
|
||||
|
||||
# 301| int main(int, char**)
|
||||
|
||||
@@ -149,9 +149,6 @@ uniqueNodeLocation
|
||||
| conditional_destructors.cpp:29:6:29:7 | EnterFunction | Node should have one location but has 2. |
|
||||
| conditional_destructors.cpp:29:6:29:7 | ExitFunction | Node should have one location but has 2. |
|
||||
| conditional_destructors.cpp:29:6:29:7 | InitializeNonLocal | Node should have one location but has 2. |
|
||||
| conditional_destructors.cpp:29:6:29:7 | Phi | Node should have one location but has 2. |
|
||||
| conditional_destructors.cpp:29:6:29:7 | Phi | Node should have one location but has 2. |
|
||||
| conditional_destructors.cpp:29:6:29:7 | Phi | Node should have one location but has 2. |
|
||||
| conditional_destructors.cpp:29:6:29:7 | ReturnVoid | Node should have one location but has 2. |
|
||||
| conditional_destructors.cpp:29:6:29:7 | SideEffect | Node should have one location but has 2. |
|
||||
| conditional_destructors.cpp:38:6:38:7 | AliasedDefinition | Node should have one location but has 2. |
|
||||
@@ -162,9 +159,6 @@ uniqueNodeLocation
|
||||
| conditional_destructors.cpp:38:6:38:7 | EnterFunction | Node should have one location but has 2. |
|
||||
| conditional_destructors.cpp:38:6:38:7 | ExitFunction | Node should have one location but has 2. |
|
||||
| conditional_destructors.cpp:38:6:38:7 | InitializeNonLocal | Node should have one location but has 2. |
|
||||
| conditional_destructors.cpp:38:6:38:7 | Phi | Node should have one location but has 2. |
|
||||
| conditional_destructors.cpp:38:6:38:7 | Phi | Node should have one location but has 2. |
|
||||
| conditional_destructors.cpp:38:6:38:7 | Phi | Node should have one location but has 2. |
|
||||
| conditional_destructors.cpp:38:6:38:7 | ReturnVoid | Node should have one location but has 2. |
|
||||
| conditional_destructors.cpp:38:6:38:7 | SideEffect | Node should have one location but has 2. |
|
||||
| conditional_destructors.cpp:38:6:38:7 | Unreached | Node should have one location but has 2. |
|
||||
@@ -561,9 +555,6 @@ uniqueNodeLocation
|
||||
| forstmt.cpp:1:6:1:7 | EnterFunction | Node should have one location but has 2. |
|
||||
| forstmt.cpp:1:6:1:7 | ExitFunction | Node should have one location but has 2. |
|
||||
| forstmt.cpp:1:6:1:7 | InitializeNonLocal | Node should have one location but has 2. |
|
||||
| forstmt.cpp:1:6:1:7 | Phi | Node should have one location but has 2. |
|
||||
| forstmt.cpp:1:6:1:7 | Phi | Node should have one location but has 2. |
|
||||
| forstmt.cpp:1:6:1:7 | Phi | Node should have one location but has 2. |
|
||||
| forstmt.cpp:1:6:1:7 | ReturnVoid | Node should have one location but has 2. |
|
||||
| forstmt.cpp:1:6:1:7 | SideEffect | Node should have one location but has 2. |
|
||||
| forstmt.cpp:8:6:8:7 | AliasedDefinition | Node should have one location but has 2. |
|
||||
@@ -574,9 +565,6 @@ uniqueNodeLocation
|
||||
| forstmt.cpp:8:6:8:7 | EnterFunction | Node should have one location but has 2. |
|
||||
| forstmt.cpp:8:6:8:7 | ExitFunction | Node should have one location but has 2. |
|
||||
| forstmt.cpp:8:6:8:7 | InitializeNonLocal | Node should have one location but has 2. |
|
||||
| forstmt.cpp:8:6:8:7 | Phi | Node should have one location but has 2. |
|
||||
| forstmt.cpp:8:6:8:7 | Phi | Node should have one location but has 2. |
|
||||
| forstmt.cpp:8:6:8:7 | Phi | Node should have one location but has 2. |
|
||||
| forstmt.cpp:8:6:8:7 | ReturnVoid | Node should have one location but has 2. |
|
||||
| forstmt.cpp:8:6:8:7 | SideEffect | Node should have one location but has 2. |
|
||||
| forstmt.cpp:8:6:8:7 | Unreached | Node should have one location but has 2. |
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
| test.cpp:5:7:5:8 | p0 | 5:c7-c8 6:c7-c8 |
|
||||
| test.cpp:5:7:5:13 | ... + ... | 5:c7-c13 6:c7-c13 7:c7-c7 |
|
||||
| test.cpp:5:12:5:13 | p1 | 5:c12-c13 6:c12-c13 |
|
||||
| test.cpp:10:16:10:16 | 1 | 10:c16-c16 176:c7-c7 178:c7-c7 |
|
||||
| test.cpp:16:3:16:3 | x | 16:c3-c3 17:c3-c3 |
|
||||
| test.cpp:16:7:16:8 | p0 | 16:c7-c8 17:c7-c8 |
|
||||
| test.cpp:16:7:16:13 | ... + ... | 16:c7-c13 17:c7-c13 |
|
||||
@@ -38,3 +39,9 @@
|
||||
| test.cpp:145:15:145:15 | y | 145:c15-c15 147:c7-c7 |
|
||||
| test.cpp:153:11:153:18 | global_a | 153:c11-c18 154:c11-c18 156:c3-c10 |
|
||||
| test.cpp:153:21:153:21 | x | 153:c21-c21 154:c21-c21 |
|
||||
| test.cpp:166:18:166:20 | (const char *)... | 166:c18-c20 167:c18-c20 173:c18-c20 |
|
||||
| test.cpp:166:18:166:20 | dst | 166:c18-c20 167:c18-c20 171:c10-c12 173:c18-c20 |
|
||||
| test.cpp:168:18:168:20 | (const char *)... | 168:c18-c20 169:c18-c20 171:c15-c17 174:c18-c20 |
|
||||
| test.cpp:168:18:168:20 | src | 168:c18-c20 169:c18-c20 171:c15-c17 174:c18-c20 |
|
||||
| test.cpp:176:10:176:10 | 2 | 176:c10-c10 178:c10-c10 21:c16-c16 |
|
||||
| test.cpp:177:7:177:7 | 3 | 177:c7-c7 35:c16-c16 |
|
||||
|
||||
@@ -44,3 +44,11 @@
|
||||
| test.cpp:144:15:144:15 | GVN | 144:c15-c15 149:c15-c15 |
|
||||
| test.cpp:153:11:153:18 | GVN | 153:c11-c18 154:c11-c18 156:c3-c10 |
|
||||
| test.cpp:153:21:153:21 | GVN | 153:c21-c21 154:c21-c21 |
|
||||
| test.cpp:166:11:166:16 | GVN | 166:c11-c16 167:c11-c16 |
|
||||
| test.cpp:166:18:166:20 | GVN | 166:c18-c20 167:c18-c20 171:c10-c12 173:c18-c20 |
|
||||
| test.cpp:166:18:166:20 | GVN | 166:c18-c20 167:c18-c20 173:c18-c20 |
|
||||
| test.cpp:168:11:168:16 | GVN | 168:c11-c16 169:c11-c16 174:c11-c16 |
|
||||
| test.cpp:168:18:168:20 | GVN | 168:c18-c20 169:c18-c20 171:c15-c17 174:c18-c20 |
|
||||
| test.cpp:168:18:168:20 | GVN | 168:c18-c20 169:c18-c20 171:c15-c17 174:c18-c20 |
|
||||
| test.cpp:176:7:176:7 | GVN | 176:c7-c7 178:c7-c7 |
|
||||
| test.cpp:176:10:176:10 | GVN | 176:c10-c10 178:c10-c10 |
|
||||
|
||||
@@ -1,15 +1,20 @@
|
||||
| test.cpp:5:3:5:13 | ... = ... | test.cpp:5:3:5:13 | ... = ... | AST only |
|
||||
| test.cpp:6:3:6:13 | ... = ... | test.cpp:6:3:6:13 | ... = ... | AST only |
|
||||
| test.cpp:7:3:7:7 | ... = ... | test.cpp:7:3:7:7 | ... = ... | AST only |
|
||||
| test.cpp:10:16:10:16 | 1 | test.cpp:176:7:176:7 | 1 | AST only |
|
||||
| test.cpp:10:16:10:16 | 1 | test.cpp:178:7:178:7 | 1 | AST only |
|
||||
| test.cpp:16:3:16:24 | ... = ... | test.cpp:16:3:16:24 | ... = ... | AST only |
|
||||
| test.cpp:17:3:17:24 | ... = ... | test.cpp:17:3:17:24 | ... = ... | AST only |
|
||||
| test.cpp:18:3:18:7 | ... = ... | test.cpp:18:3:18:7 | ... = ... | AST only |
|
||||
| test.cpp:21:16:21:16 | 2 | test.cpp:176:10:176:10 | 2 | AST only |
|
||||
| test.cpp:21:16:21:16 | 2 | test.cpp:178:10:178:10 | 2 | AST only |
|
||||
| test.cpp:29:3:29:3 | x | test.cpp:31:3:31:3 | x | IR only |
|
||||
| test.cpp:29:3:29:24 | ... = ... | test.cpp:29:3:29:24 | ... = ... | AST only |
|
||||
| test.cpp:30:3:30:17 | call to change_global02 | test.cpp:30:3:30:17 | call to change_global02 | AST only |
|
||||
| test.cpp:31:3:31:3 | x | test.cpp:29:3:29:3 | x | IR only |
|
||||
| test.cpp:31:3:31:24 | ... = ... | test.cpp:31:3:31:24 | ... = ... | AST only |
|
||||
| test.cpp:32:3:32:7 | ... = ... | test.cpp:32:3:32:7 | ... = ... | AST only |
|
||||
| test.cpp:35:16:35:16 | 3 | test.cpp:177:7:177:7 | 3 | AST only |
|
||||
| test.cpp:43:3:43:3 | x | test.cpp:45:3:45:3 | x | IR only |
|
||||
| test.cpp:43:3:43:24 | ... = ... | test.cpp:43:3:43:24 | ... = ... | AST only |
|
||||
| test.cpp:43:7:43:24 | ... + ... | test.cpp:45:7:45:24 | ... + ... | IR only |
|
||||
@@ -127,3 +132,41 @@
|
||||
| test.cpp:147:7:147:7 | y | test.cpp:145:15:145:15 | y | AST only |
|
||||
| test.cpp:149:15:149:15 | x | test.cpp:144:15:144:15 | x | IR only |
|
||||
| test.cpp:156:3:156:17 | ... = ... | test.cpp:156:3:156:17 | ... = ... | AST only |
|
||||
| test.cpp:166:11:166:16 | call to strlen | test.cpp:167:11:167:16 | call to strlen | IR only |
|
||||
| test.cpp:166:18:166:20 | (const char *)... | test.cpp:166:18:166:20 | (const char *)... | AST only |
|
||||
| test.cpp:166:18:166:20 | (const char *)... | test.cpp:167:18:167:20 | (const char *)... | AST only |
|
||||
| test.cpp:166:18:166:20 | (const char *)... | test.cpp:173:18:173:20 | (const char *)... | AST only |
|
||||
| test.cpp:167:11:167:16 | call to strlen | test.cpp:166:11:166:16 | call to strlen | IR only |
|
||||
| test.cpp:167:18:167:20 | (const char *)... | test.cpp:166:18:166:20 | (const char *)... | AST only |
|
||||
| test.cpp:167:18:167:20 | (const char *)... | test.cpp:167:18:167:20 | (const char *)... | AST only |
|
||||
| test.cpp:167:18:167:20 | (const char *)... | test.cpp:173:18:173:20 | (const char *)... | AST only |
|
||||
| test.cpp:168:11:168:16 | call to strlen | test.cpp:169:11:169:16 | call to strlen | IR only |
|
||||
| test.cpp:168:11:168:16 | call to strlen | test.cpp:174:11:174:16 | call to strlen | IR only |
|
||||
| test.cpp:168:18:168:20 | (const char *)... | test.cpp:168:18:168:20 | (const char *)... | AST only |
|
||||
| test.cpp:168:18:168:20 | (const char *)... | test.cpp:169:18:169:20 | (const char *)... | AST only |
|
||||
| test.cpp:168:18:168:20 | (const char *)... | test.cpp:171:15:171:17 | (const char *)... | AST only |
|
||||
| test.cpp:168:18:168:20 | (const char *)... | test.cpp:174:18:174:20 | (const char *)... | AST only |
|
||||
| test.cpp:169:11:169:16 | call to strlen | test.cpp:168:11:168:16 | call to strlen | IR only |
|
||||
| test.cpp:169:11:169:16 | call to strlen | test.cpp:174:11:174:16 | call to strlen | IR only |
|
||||
| test.cpp:169:18:169:20 | (const char *)... | test.cpp:168:18:168:20 | (const char *)... | AST only |
|
||||
| test.cpp:169:18:169:20 | (const char *)... | test.cpp:169:18:169:20 | (const char *)... | AST only |
|
||||
| test.cpp:169:18:169:20 | (const char *)... | test.cpp:171:15:171:17 | (const char *)... | AST only |
|
||||
| test.cpp:169:18:169:20 | (const char *)... | test.cpp:174:18:174:20 | (const char *)... | AST only |
|
||||
| test.cpp:171:15:171:17 | (const char *)... | test.cpp:168:18:168:20 | (const char *)... | AST only |
|
||||
| test.cpp:171:15:171:17 | (const char *)... | test.cpp:169:18:169:20 | (const char *)... | AST only |
|
||||
| test.cpp:171:15:171:17 | (const char *)... | test.cpp:171:15:171:17 | (const char *)... | AST only |
|
||||
| test.cpp:171:15:171:17 | (const char *)... | test.cpp:174:18:174:20 | (const char *)... | AST only |
|
||||
| test.cpp:173:18:173:20 | (const char *)... | test.cpp:166:18:166:20 | (const char *)... | AST only |
|
||||
| test.cpp:173:18:173:20 | (const char *)... | test.cpp:167:18:167:20 | (const char *)... | AST only |
|
||||
| test.cpp:173:18:173:20 | (const char *)... | test.cpp:173:18:173:20 | (const char *)... | AST only |
|
||||
| test.cpp:174:11:174:16 | call to strlen | test.cpp:168:11:168:16 | call to strlen | IR only |
|
||||
| test.cpp:174:11:174:16 | call to strlen | test.cpp:169:11:169:16 | call to strlen | IR only |
|
||||
| test.cpp:174:18:174:20 | (const char *)... | test.cpp:168:18:168:20 | (const char *)... | AST only |
|
||||
| test.cpp:174:18:174:20 | (const char *)... | test.cpp:169:18:169:20 | (const char *)... | AST only |
|
||||
| test.cpp:174:18:174:20 | (const char *)... | test.cpp:171:15:171:17 | (const char *)... | AST only |
|
||||
| test.cpp:174:18:174:20 | (const char *)... | test.cpp:174:18:174:20 | (const char *)... | AST only |
|
||||
| test.cpp:176:7:176:7 | 1 | test.cpp:10:16:10:16 | 1 | AST only |
|
||||
| test.cpp:176:10:176:10 | 2 | test.cpp:21:16:21:16 | 2 | AST only |
|
||||
| test.cpp:177:7:177:7 | 3 | test.cpp:35:16:35:16 | 3 | AST only |
|
||||
| test.cpp:178:7:178:7 | 1 | test.cpp:10:16:10:16 | 1 | AST only |
|
||||
| test.cpp:178:10:178:10 | 2 | test.cpp:21:16:21:16 | 2 | AST only |
|
||||
|
||||
@@ -1145,3 +1145,206 @@ test.cpp:
|
||||
# 152| v152_7(void) = ReturnVoid :
|
||||
# 152| v152_8(void) = AliasedUse : ~m156_7
|
||||
# 152| v152_9(void) = ExitFunction :
|
||||
|
||||
# 163| int add(int, int)
|
||||
# 163| Block 0
|
||||
# 163| v163_1(void) = EnterFunction :
|
||||
# 163| m163_2(unknown) = AliasedDefinition :
|
||||
# 163| valnum = unique
|
||||
# 163| m163_3(unknown) = InitializeNonLocal :
|
||||
# 163| valnum = unique
|
||||
# 163| m163_4(unknown) = Chi : total:m163_2, partial:m163_3
|
||||
# 163| valnum = unique
|
||||
# 163| r163_5(glval<int>) = VariableAddress[a] :
|
||||
# 163| valnum = r163_10, r163_5
|
||||
# 163| m163_6(int) = InitializeParameter[a] : &:r163_5
|
||||
# 163| valnum = m163_6, r163_11
|
||||
# 163| r163_7(glval<int>) = VariableAddress[b] :
|
||||
# 163| valnum = r163_12, r163_7
|
||||
# 163| m163_8(int) = InitializeParameter[b] : &:r163_7
|
||||
# 163| valnum = m163_8, r163_13
|
||||
# 163| r163_9(glval<int>) = VariableAddress[#return] :
|
||||
# 163| valnum = r163_16, r163_9
|
||||
# 163| r163_10(glval<int>) = VariableAddress[a] :
|
||||
# 163| valnum = r163_10, r163_5
|
||||
# 163| r163_11(int) = Load[a] : &:r163_10, m163_6
|
||||
# 163| valnum = m163_6, r163_11
|
||||
# 163| r163_12(glval<int>) = VariableAddress[b] :
|
||||
# 163| valnum = r163_12, r163_7
|
||||
# 163| r163_13(int) = Load[b] : &:r163_12, m163_8
|
||||
# 163| valnum = m163_8, r163_13
|
||||
# 163| r163_14(int) = Add : r163_11, r163_13
|
||||
# 163| valnum = m163_15, r163_14
|
||||
# 163| m163_15(int) = Store[#return] : &:r163_9, r163_14
|
||||
# 163| valnum = m163_15, r163_14
|
||||
# 163| r163_16(glval<int>) = VariableAddress[#return] :
|
||||
# 163| valnum = r163_16, r163_9
|
||||
# 163| v163_17(void) = ReturnValue : &:r163_16, m163_15
|
||||
# 163| v163_18(void) = AliasedUse : m163_3
|
||||
# 163| v163_19(void) = ExitFunction :
|
||||
|
||||
# 165| void test_func_value_numbering(char*, char*)
|
||||
# 165| Block 0
|
||||
# 165| v165_1(void) = EnterFunction :
|
||||
# 165| m165_2(unknown) = AliasedDefinition :
|
||||
# 165| valnum = unique
|
||||
# 165| m165_3(unknown) = InitializeNonLocal :
|
||||
# 165| valnum = unique
|
||||
# 165| m165_4(unknown) = Chi : total:m165_2, partial:m165_3
|
||||
# 165| valnum = unique
|
||||
# 165| r165_5(glval<char *>) = VariableAddress[dst] :
|
||||
# 165| valnum = r165_5, r166_3, r167_3, r171_2, r173_3
|
||||
# 165| m165_6(char *) = InitializeParameter[dst] : &:r165_5
|
||||
# 165| valnum = m165_6, r165_7, r166_4, r167_4, r171_3, r173_4
|
||||
# 165| r165_7(char *) = Load[dst] : &:r165_5, m165_6
|
||||
# 165| valnum = m165_6, r165_7, r166_4, r167_4, r171_3, r173_4
|
||||
# 165| m165_8(unknown) = InitializeIndirection[dst] : &:r165_7
|
||||
# 165| valnum = unique
|
||||
# 165| r165_9(glval<char *>) = VariableAddress[src] :
|
||||
# 165| valnum = r165_9, r168_3, r169_3, r171_4, r174_3
|
||||
# 165| m165_10(char *) = InitializeParameter[src] : &:r165_9
|
||||
# 165| valnum = m165_10, r165_11, r168_4, r169_4, r171_5, r174_4
|
||||
# 165| r165_11(char *) = Load[src] : &:r165_9, m165_10
|
||||
# 165| valnum = m165_10, r165_11, r168_4, r169_4, r171_5, r174_4
|
||||
# 165| m165_12(unknown) = InitializeIndirection[src] : &:r165_11
|
||||
# 165| valnum = unique
|
||||
# 166| r166_1(glval<int>) = VariableAddress[a] :
|
||||
# 166| valnum = unique
|
||||
# 166| r166_2(glval<unknown>) = FunctionAddress[strlen] :
|
||||
# 166| valnum = unique
|
||||
# 166| r166_3(glval<char *>) = VariableAddress[dst] :
|
||||
# 166| valnum = r165_5, r166_3, r167_3, r171_2, r173_3
|
||||
# 166| r166_4(char *) = Load[dst] : &:r166_3, m165_6
|
||||
# 166| valnum = m165_6, r165_7, r166_4, r167_4, r171_3, r173_4
|
||||
# 166| r166_5(char *) = Convert : r166_4
|
||||
# 166| valnum = r166_5, r167_5, r173_5
|
||||
# 166| r166_6(int) = Call[strlen] : func:r166_2, 0:r166_5
|
||||
# 166| valnum = m166_8, m167_8, r166_6, r167_6
|
||||
# 166| v166_7(void) = ^BufferReadSideEffect[0] : &:r166_5, ~m165_8
|
||||
# 166| m166_8(int) = Store[a] : &:r166_1, r166_6
|
||||
# 166| valnum = m166_8, m167_8, r166_6, r167_6
|
||||
# 167| r167_1(glval<int>) = VariableAddress[b] :
|
||||
# 167| valnum = unique
|
||||
# 167| r167_2(glval<unknown>) = FunctionAddress[strlen] :
|
||||
# 167| valnum = unique
|
||||
# 167| r167_3(glval<char *>) = VariableAddress[dst] :
|
||||
# 167| valnum = r165_5, r166_3, r167_3, r171_2, r173_3
|
||||
# 167| r167_4(char *) = Load[dst] : &:r167_3, m165_6
|
||||
# 167| valnum = m165_6, r165_7, r166_4, r167_4, r171_3, r173_4
|
||||
# 167| r167_5(char *) = Convert : r167_4
|
||||
# 167| valnum = r166_5, r167_5, r173_5
|
||||
# 167| r167_6(int) = Call[strlen] : func:r167_2, 0:r167_5
|
||||
# 167| valnum = m166_8, m167_8, r166_6, r167_6
|
||||
# 167| v167_7(void) = ^BufferReadSideEffect[0] : &:r167_5, ~m165_8
|
||||
# 167| m167_8(int) = Store[b] : &:r167_1, r167_6
|
||||
# 167| valnum = m166_8, m167_8, r166_6, r167_6
|
||||
# 168| r168_1(glval<int>) = VariableAddress[c] :
|
||||
# 168| valnum = unique
|
||||
# 168| r168_2(glval<unknown>) = FunctionAddress[strlen] :
|
||||
# 168| valnum = unique
|
||||
# 168| r168_3(glval<char *>) = VariableAddress[src] :
|
||||
# 168| valnum = r165_9, r168_3, r169_3, r171_4, r174_3
|
||||
# 168| r168_4(char *) = Load[src] : &:r168_3, m165_10
|
||||
# 168| valnum = m165_10, r165_11, r168_4, r169_4, r171_5, r174_4
|
||||
# 168| r168_5(char *) = Convert : r168_4
|
||||
# 168| valnum = r168_5, r169_5, r171_6, r174_5
|
||||
# 168| r168_6(int) = Call[strlen] : func:r168_2, 0:r168_5
|
||||
# 168| valnum = m168_8, m169_8, m174_8, r168_6, r169_6, r174_6
|
||||
# 168| v168_7(void) = ^BufferReadSideEffect[0] : &:r168_5, ~m165_12
|
||||
# 168| m168_8(int) = Store[c] : &:r168_1, r168_6
|
||||
# 168| valnum = m168_8, m169_8, m174_8, r168_6, r169_6, r174_6
|
||||
# 169| r169_1(glval<int>) = VariableAddress[d] :
|
||||
# 169| valnum = unique
|
||||
# 169| r169_2(glval<unknown>) = FunctionAddress[strlen] :
|
||||
# 169| valnum = unique
|
||||
# 169| r169_3(glval<char *>) = VariableAddress[src] :
|
||||
# 169| valnum = r165_9, r168_3, r169_3, r171_4, r174_3
|
||||
# 169| r169_4(char *) = Load[src] : &:r169_3, m165_10
|
||||
# 169| valnum = m165_10, r165_11, r168_4, r169_4, r171_5, r174_4
|
||||
# 169| r169_5(char *) = Convert : r169_4
|
||||
# 169| valnum = r168_5, r169_5, r171_6, r174_5
|
||||
# 169| r169_6(int) = Call[strlen] : func:r169_2, 0:r169_5
|
||||
# 169| valnum = m168_8, m169_8, m174_8, r168_6, r169_6, r174_6
|
||||
# 169| v169_7(void) = ^BufferReadSideEffect[0] : &:r169_5, ~m165_12
|
||||
# 169| m169_8(int) = Store[d] : &:r169_1, r169_6
|
||||
# 169| valnum = m168_8, m169_8, m174_8, r168_6, r169_6, r174_6
|
||||
# 171| r171_1(glval<unknown>) = FunctionAddress[strcat] :
|
||||
# 171| valnum = unique
|
||||
# 171| r171_2(glval<char *>) = VariableAddress[dst] :
|
||||
# 171| valnum = r165_5, r166_3, r167_3, r171_2, r173_3
|
||||
# 171| r171_3(char *) = Load[dst] : &:r171_2, m165_6
|
||||
# 171| valnum = m165_6, r165_7, r166_4, r167_4, r171_3, r173_4
|
||||
# 171| r171_4(glval<char *>) = VariableAddress[src] :
|
||||
# 171| valnum = r165_9, r168_3, r169_3, r171_4, r174_3
|
||||
# 171| r171_5(char *) = Load[src] : &:r171_4, m165_10
|
||||
# 171| valnum = m165_10, r165_11, r168_4, r169_4, r171_5, r174_4
|
||||
# 171| r171_6(char *) = Convert : r171_5
|
||||
# 171| valnum = r168_5, r169_5, r171_6, r174_5
|
||||
# 171| r171_7(char *) = Call[strcat] : func:r171_1, 0:r171_3, 1:r171_6
|
||||
# 171| valnum = unique
|
||||
# 171| v171_8(void) = ^BufferReadSideEffect[0] : &:r171_3, ~m165_8
|
||||
# 171| v171_9(void) = ^BufferReadSideEffect[1] : &:r171_6, ~m165_12
|
||||
# 171| m171_10(unknown) = ^BufferMayWriteSideEffect[0] : &:r171_3
|
||||
# 171| valnum = unique
|
||||
# 171| m171_11(unknown) = Chi : total:m165_8, partial:m171_10
|
||||
# 171| valnum = unique
|
||||
# 173| r173_1(glval<int>) = VariableAddress[e] :
|
||||
# 173| valnum = unique
|
||||
# 173| r173_2(glval<unknown>) = FunctionAddress[strlen] :
|
||||
# 173| valnum = unique
|
||||
# 173| r173_3(glval<char *>) = VariableAddress[dst] :
|
||||
# 173| valnum = r165_5, r166_3, r167_3, r171_2, r173_3
|
||||
# 173| r173_4(char *) = Load[dst] : &:r173_3, m165_6
|
||||
# 173| valnum = m165_6, r165_7, r166_4, r167_4, r171_3, r173_4
|
||||
# 173| r173_5(char *) = Convert : r173_4
|
||||
# 173| valnum = r166_5, r167_5, r173_5
|
||||
# 173| r173_6(int) = Call[strlen] : func:r173_2, 0:r173_5
|
||||
# 173| valnum = m173_8, r173_6
|
||||
# 173| v173_7(void) = ^BufferReadSideEffect[0] : &:r173_5, ~m171_11
|
||||
# 173| m173_8(int) = Store[e] : &:r173_1, r173_6
|
||||
# 173| valnum = m173_8, r173_6
|
||||
# 174| r174_1(glval<int>) = VariableAddress[f] :
|
||||
# 174| valnum = unique
|
||||
# 174| r174_2(glval<unknown>) = FunctionAddress[strlen] :
|
||||
# 174| valnum = unique
|
||||
# 174| r174_3(glval<char *>) = VariableAddress[src] :
|
||||
# 174| valnum = r165_9, r168_3, r169_3, r171_4, r174_3
|
||||
# 174| r174_4(char *) = Load[src] : &:r174_3, m165_10
|
||||
# 174| valnum = m165_10, r165_11, r168_4, r169_4, r171_5, r174_4
|
||||
# 174| r174_5(char *) = Convert : r174_4
|
||||
# 174| valnum = r168_5, r169_5, r171_6, r174_5
|
||||
# 174| r174_6(int) = Call[strlen] : func:r174_2, 0:r174_5
|
||||
# 174| valnum = m168_8, m169_8, m174_8, r168_6, r169_6, r174_6
|
||||
# 174| v174_7(void) = ^BufferReadSideEffect[0] : &:r174_5, ~m165_12
|
||||
# 174| m174_8(int) = Store[f] : &:r174_1, r174_6
|
||||
# 174| valnum = m168_8, m169_8, m174_8, r168_6, r169_6, r174_6
|
||||
# 176| r176_1(glval<unknown>) = FunctionAddress[add] :
|
||||
# 176| valnum = unique
|
||||
# 176| r176_2(int) = Constant[1] :
|
||||
# 176| valnum = r176_2, r178_2
|
||||
# 176| r176_3(int) = Constant[2] :
|
||||
# 176| valnum = r176_3, r178_3
|
||||
# 176| r176_4(int) = Call[add] : func:r176_1, 0:r176_2, 1:r176_3
|
||||
# 176| valnum = unique
|
||||
# 177| r177_1(glval<unknown>) = FunctionAddress[add] :
|
||||
# 177| valnum = unique
|
||||
# 177| r177_2(int) = Constant[3] :
|
||||
# 177| valnum = unique
|
||||
# 177| r177_3(int) = Constant[4] :
|
||||
# 177| valnum = unique
|
||||
# 177| r177_4(int) = Call[add] : func:r177_1, 0:r177_2, 1:r177_3
|
||||
# 177| valnum = unique
|
||||
# 178| r178_1(glval<unknown>) = FunctionAddress[add] :
|
||||
# 178| valnum = unique
|
||||
# 178| r178_2(int) = Constant[1] :
|
||||
# 178| valnum = r176_2, r178_2
|
||||
# 178| r178_3(int) = Constant[2] :
|
||||
# 178| valnum = r176_3, r178_3
|
||||
# 178| r178_4(int) = Call[add] : func:r178_1, 0:r178_2, 1:r178_3
|
||||
# 178| valnum = unique
|
||||
# 179| v179_1(void) = NoOp :
|
||||
# 165| v165_13(void) = ReturnIndirection[dst] : &:r165_7, m171_11
|
||||
# 165| v165_14(void) = ReturnIndirection[src] : &:r165_11, m165_12
|
||||
# 165| v165_15(void) = ReturnVoid :
|
||||
# 165| v165_16(void) = AliasedUse : m165_3
|
||||
# 165| v165_17(void) = ExitFunction :
|
||||
|
||||
@@ -156,4 +156,24 @@ void test_read_global_different(int n) {
|
||||
global_a->y = n;
|
||||
|
||||
int d = global_a->x;
|
||||
}
|
||||
|
||||
int strlen(const char *str);
|
||||
char *strcat(char *dst, const char *src);
|
||||
int add(int a, int b) { return a+b; }
|
||||
|
||||
void test_func_value_numbering(char *dst, char *src) {
|
||||
int a = strlen(dst);
|
||||
int b = strlen(dst); // same as previous line
|
||||
int c = strlen(src);
|
||||
int d = strlen(src); // same as previous line
|
||||
|
||||
strcat(dst, src);
|
||||
|
||||
int e = strlen(dst); // different from a and b
|
||||
int f = strlen(src); // same as c and d
|
||||
|
||||
add(1, 2);
|
||||
add(3, 4);
|
||||
add(1, 2); // same as two lines earlier
|
||||
}
|
||||
@@ -1,3 +1,3 @@
|
||||
| empty_block.cpp:9:10:9:11 | { ... } | Empty block without comment |
|
||||
| empty_block.cpp:12:10:13:3 | { ... } | Empty block without comment |
|
||||
| empty_block.cpp:20:10:21:3 | { ... } | Empty block without comment |
|
||||
| empty_block.cpp:9:10:9:11 | { ... } | Empty block without comment. |
|
||||
| empty_block.cpp:12:10:13:3 | { ... } | Empty block without comment. |
|
||||
| empty_block.cpp:20:10:21:3 | { ... } | Empty block without comment. |
|
||||
|
||||
@@ -1,20 +1,20 @@
|
||||
| test2.cpp:37:1:37:39 | // int myFunction() { return myValue; } | This comment appears to contain commented-out code |
|
||||
| test2.cpp:39:1:39:45 | // int myFunction() const { return myValue; } | This comment appears to contain commented-out code |
|
||||
| test2.cpp:41:1:41:54 | // int myFunction() const noexcept { return myValue; } | This comment appears to contain commented-out code |
|
||||
| test2.cpp:43:1:43:18 | // #define MYMACRO | This comment appears to contain commented-out code |
|
||||
| test2.cpp:45:1:45:23 | // #include "include.h" | This comment appears to contain commented-out code |
|
||||
| test2.cpp:47:1:51:2 | /*\n#ifdef\nvoid myFunction();\n#endif\n*/ | This comment appears to contain commented-out code |
|
||||
| test2.cpp:59:1:59:24 | // #if(defined(MYMACRO)) | This comment appears to contain commented-out code |
|
||||
| test2.cpp:63:1:63:15 | // #pragma once | This comment appears to contain commented-out code |
|
||||
| test2.cpp:65:1:65:17 | // # pragma once | This comment appears to contain commented-out code |
|
||||
| test2.cpp:67:1:67:19 | /*#error"myerror"*/ | This comment appears to contain commented-out code |
|
||||
| test2.cpp:91:1:95:2 | /*\n#ifdef MYMACRO\n\t// ...\n#endif // #ifdef MYMACRO\n*/ | This comment appears to contain commented-out code |
|
||||
| test2.cpp:107:21:107:43 | // #include "config2.h" | This comment appears to contain commented-out code |
|
||||
| test2.cpp:115:16:115:35 | /* #ifdef MYMACRO */ | This comment appears to contain commented-out code |
|
||||
| test2.cpp:117:1:117:24 | // commented_out_code(); | This comment appears to contain commented-out code |
|
||||
| test2.cpp:120:2:120:25 | // commented_out_code(); | This comment appears to contain commented-out code |
|
||||
| test.c:2:1:2:22 | // commented out code; | This comment appears to contain commented-out code |
|
||||
| test.c:4:1:7:8 | // some; | This comment appears to contain commented-out code |
|
||||
| test.c:9:1:13:8 | // also; | This comment appears to contain commented-out code |
|
||||
| test.c:21:1:26:2 | /*\n some;\n commented;\n out;\n code;\n*/ | This comment appears to contain commented-out code |
|
||||
| test.c:28:1:34:2 | /*\n also;\n this\n is;\n commented-out\n code;\n*/ | This comment appears to contain commented-out code |
|
||||
| test2.cpp:37:1:37:39 | // int myFunction() { return myValue; } | This comment appears to contain commented-out code. |
|
||||
| test2.cpp:39:1:39:45 | // int myFunction() const { return myValue; } | This comment appears to contain commented-out code. |
|
||||
| test2.cpp:41:1:41:54 | // int myFunction() const noexcept { return myValue; } | This comment appears to contain commented-out code. |
|
||||
| test2.cpp:43:1:43:18 | // #define MYMACRO | This comment appears to contain commented-out code. |
|
||||
| test2.cpp:45:1:45:23 | // #include "include.h" | This comment appears to contain commented-out code. |
|
||||
| test2.cpp:47:1:51:2 | /*\n#ifdef\nvoid myFunction();\n#endif\n*/ | This comment appears to contain commented-out code. |
|
||||
| test2.cpp:59:1:59:24 | // #if(defined(MYMACRO)) | This comment appears to contain commented-out code. |
|
||||
| test2.cpp:63:1:63:15 | // #pragma once | This comment appears to contain commented-out code. |
|
||||
| test2.cpp:65:1:65:17 | // # pragma once | This comment appears to contain commented-out code. |
|
||||
| test2.cpp:67:1:67:19 | /*#error"myerror"*/ | This comment appears to contain commented-out code. |
|
||||
| test2.cpp:91:1:95:2 | /*\n#ifdef MYMACRO\n\t// ...\n#endif // #ifdef MYMACRO\n*/ | This comment appears to contain commented-out code. |
|
||||
| test2.cpp:107:21:107:43 | // #include "config2.h" | This comment appears to contain commented-out code. |
|
||||
| test2.cpp:115:16:115:35 | /* #ifdef MYMACRO */ | This comment appears to contain commented-out code. |
|
||||
| test2.cpp:117:1:117:24 | // commented_out_code(); | This comment appears to contain commented-out code. |
|
||||
| test2.cpp:120:2:120:25 | // commented_out_code(); | This comment appears to contain commented-out code. |
|
||||
| test.c:2:1:2:22 | // commented out code; | This comment appears to contain commented-out code. |
|
||||
| test.c:4:1:7:8 | // some; | This comment appears to contain commented-out code. |
|
||||
| test.c:9:1:13:8 | // also; | This comment appears to contain commented-out code. |
|
||||
| test.c:21:1:26:2 | /*\n some;\n commented;\n out;\n code;\n*/ | This comment appears to contain commented-out code. |
|
||||
| test.c:28:1:34:2 | /*\n also;\n this\n is;\n commented-out\n code;\n*/ | This comment appears to contain commented-out code. |
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
| bsc.cpp:2:10:2:32 | ... > ... | Potential unsafe sign check of a bitwise operation. |
|
||||
| bsc.cpp:6:10:6:32 | ... > ... | Potential unsafe sign check of a bitwise operation. |
|
||||
| bsc.cpp:18:10:18:28 | ... > ... | Potential unsafe sign check of a bitwise operation. |
|
||||
| bsc.cpp:22:10:22:28 | ... < ... | Potential unsafe sign check of a bitwise operation. |
|
||||
| bsc.cpp:2:10:2:32 | ... > ... | Potentially unsafe sign check of a bitwise operation. |
|
||||
| bsc.cpp:6:10:6:32 | ... > ... | Potentially unsafe sign check of a bitwise operation. |
|
||||
| bsc.cpp:18:10:18:28 | ... > ... | Potentially unsafe sign check of a bitwise operation. |
|
||||
| bsc.cpp:22:10:22:28 | ... < ... | Potentially unsafe sign check of a bitwise operation. |
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
| c.c:10:5:10:10 | ... == ... | Equality test on floating point values may not behave as expected. |
|
||||
| c.c:14:5:14:14 | ... == ... | Equality test on floating point values may not behave as expected. |
|
||||
| c.c:16:5:16:12 | ... == ... | Equality test on floating point values may not behave as expected. |
|
||||
| c.c:17:5:17:12 | ... == ... | Equality test on floating point values may not behave as expected. |
|
||||
| c.c:10:5:10:10 | ... == ... | Equality checks on floating point values can yield unexpected results. |
|
||||
| c.c:14:5:14:14 | ... == ... | Equality checks on floating point values can yield unexpected results. |
|
||||
| c.c:16:5:16:12 | ... == ... | Equality checks on floating point values can yield unexpected results. |
|
||||
| c.c:17:5:17:12 | ... == ... | Equality checks on floating point values can yield unexpected results. |
|
||||
|
||||
@@ -64,10 +64,6 @@ edges
|
||||
| test.cpp:201:5:201:17 | EnterFunction: maybe_deref_p | test.cpp:201:5:201:17 | VariableAddress: maybe_deref_p |
|
||||
| test.cpp:210:3:210:9 | Call: call to escape1 | test.cpp:201:5:201:17 | EnterFunction: maybe_deref_p |
|
||||
| test.cpp:210:3:210:9 | Call: call to escape1 | test.cpp:201:5:201:17 | VariableAddress: maybe_deref_p |
|
||||
| test.cpp:234:3:234:13 | Store: ... = ... | test.cpp:238:3:238:9 | Call: call to escape2 |
|
||||
| test.cpp:238:3:238:9 | Call: call to escape2 | test.cpp:239:17:239:17 | Load: p |
|
||||
| test.cpp:263:3:263:13 | Store: ... = ... | test.cpp:267:3:267:9 | Call: call to escape3 |
|
||||
| test.cpp:267:3:267:9 | Call: call to escape3 | test.cpp:268:17:268:17 | Load: p |
|
||||
#select
|
||||
| test.cpp:15:16:15:16 | Load: p | test.cpp:10:3:10:13 | Store: ... = ... | test.cpp:15:16:15:16 | Load: p | Stack variable $@ escapes $@ and is used after it has expired. | test.cpp:9:7:9:7 | x | x | test.cpp:10:3:10:13 | Store: ... = ... | here |
|
||||
| test.cpp:24:16:24:16 | Load: p | test.cpp:10:3:10:13 | Store: ... = ... | test.cpp:24:16:24:16 | Load: p | Stack variable $@ escapes $@ and is used after it has expired. | test.cpp:9:7:9:7 | x | x | test.cpp:10:3:10:13 | Store: ... = ... | here |
|
||||
@@ -94,5 +90,3 @@ edges
|
||||
| test.cpp:180:14:180:19 | Load: * ... | test.cpp:154:3:154:22 | Store: ... = ... | test.cpp:180:14:180:19 | Load: * ... | Stack variable $@ escapes $@ and is used after it has expired. | test.cpp:133:7:133:8 | b2 | b2 | test.cpp:154:3:154:22 | Store: ... = ... | here |
|
||||
| test.cpp:181:13:181:20 | Load: access to array | test.cpp:155:3:155:21 | Store: ... = ... | test.cpp:181:13:181:20 | Load: access to array | Stack variable $@ escapes $@ and is used after it has expired. | test.cpp:134:7:134:8 | b3 | b3 | test.cpp:155:3:155:21 | Store: ... = ... | here |
|
||||
| test.cpp:182:14:182:19 | Load: * ... | test.cpp:156:3:156:25 | Store: ... = ... | test.cpp:182:14:182:19 | Load: * ... | Stack variable $@ escapes $@ and is used after it has expired. | test.cpp:134:7:134:8 | b3 | b3 | test.cpp:156:3:156:25 | Store: ... = ... | here |
|
||||
| test.cpp:239:17:239:17 | Load: p | test.cpp:234:3:234:13 | Store: ... = ... | test.cpp:239:17:239:17 | Load: p | Stack variable $@ escapes $@ and is used after it has expired. | test.cpp:232:7:232:7 | x | x | test.cpp:234:3:234:13 | Store: ... = ... | here |
|
||||
| test.cpp:268:17:268:17 | Load: p | test.cpp:263:3:263:13 | Store: ... = ... | test.cpp:268:17:268:17 | Load: p | Stack variable $@ escapes $@ and is used after it has expired. | test.cpp:260:7:260:7 | x | x | test.cpp:263:3:263:13 | Store: ... = ... | here |
|
||||
|
||||
@@ -209,61 +209,4 @@ int maybe_deref_p(bool b) {
|
||||
int field_indirect_maybe_bad(bool b) {
|
||||
escape1();
|
||||
return maybe_deref_p(b);
|
||||
}
|
||||
|
||||
// These next tests cover subsequent stores to the same address in the same basic block.
|
||||
|
||||
static struct S100 s102;
|
||||
|
||||
void not_escape1() {
|
||||
int x;
|
||||
s102.p = &x;
|
||||
s102.p = nullptr;
|
||||
}
|
||||
|
||||
void calls_not_escape1() {
|
||||
not_escape1();
|
||||
int x = *s102.p; // GOOD
|
||||
}
|
||||
|
||||
static struct S100 s103;
|
||||
|
||||
void escape2() {
|
||||
int x;
|
||||
s103.p = nullptr;
|
||||
s103.p = &x;
|
||||
}
|
||||
|
||||
void calls_escape2() {
|
||||
escape2();
|
||||
int x = *s103.p; // BAD
|
||||
}
|
||||
|
||||
bool unknown();
|
||||
static struct S100 s104;
|
||||
|
||||
void not_escape2() {
|
||||
int x;
|
||||
s104.p = &x;
|
||||
if(unknown()) { }
|
||||
s104.p = nullptr;
|
||||
}
|
||||
|
||||
void calls_not_escape2() {
|
||||
not_escape2();
|
||||
int x = *s104.p; // GOOD
|
||||
}
|
||||
|
||||
static struct S100 s105;
|
||||
|
||||
void escape3() {
|
||||
int x;
|
||||
s105.p = nullptr;
|
||||
if(unknown()) { }
|
||||
s105.p = &x;
|
||||
}
|
||||
|
||||
void calls_escape3() {
|
||||
escape3();
|
||||
int x = *s105.p; // BAD
|
||||
}
|
||||
@@ -1,7 +1,3 @@
|
||||
## 1.2.5
|
||||
|
||||
## 1.2.4
|
||||
|
||||
## 1.2.3
|
||||
|
||||
## 1.2.2
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
## 1.2.4
|
||||
@@ -1 +0,0 @@
|
||||
## 1.2.5
|
||||
@@ -1,2 +1,2 @@
|
||||
---
|
||||
lastReleaseVersion: 1.2.5
|
||||
lastReleaseVersion: 1.2.3
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
name: codeql/csharp-solorigate-all
|
||||
version: 1.2.6-dev
|
||||
version: 1.2.4-dev
|
||||
groups:
|
||||
- csharp
|
||||
- solorigate
|
||||
|
||||
@@ -1,7 +1,3 @@
|
||||
## 1.2.5
|
||||
|
||||
## 1.2.4
|
||||
|
||||
## 1.2.3
|
||||
|
||||
## 1.2.2
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
## 1.2.4
|
||||
@@ -1 +0,0 @@
|
||||
## 1.2.5
|
||||
@@ -1,2 +1,2 @@
|
||||
---
|
||||
lastReleaseVersion: 1.2.5
|
||||
lastReleaseVersion: 1.2.3
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
name: codeql/csharp-solorigate-queries
|
||||
version: 1.2.6-dev
|
||||
version: 1.2.4-dev
|
||||
groups:
|
||||
- csharp
|
||||
- solorigate
|
||||
|
||||
@@ -1,16 +1,3 @@
|
||||
## 0.3.5
|
||||
|
||||
## 0.3.4
|
||||
|
||||
### Deprecated APIs
|
||||
|
||||
* Many classes/predicates/modules with upper-case acronyms in their name have been renamed to follow our style-guide.
|
||||
The old name still exists as a deprecated alias.
|
||||
|
||||
### Minor Analysis Improvements
|
||||
|
||||
* All deprecated predicates/classes/modules that have been deprecated for over a year have been deleted.
|
||||
|
||||
## 0.3.3
|
||||
|
||||
## 0.3.2
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
---
|
||||
category: minorAnalysis
|
||||
---
|
||||
* All deprecated predicates/classes/modules that have been deprecated for over a year have been
|
||||
deleted.
|
||||
|
||||
5
csharp/ql/lib/change-notes/2022-08-22-xml-rename.md
Normal file
5
csharp/ql/lib/change-notes/2022-08-22-xml-rename.md
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
category: deprecated
|
||||
---
|
||||
* Many classes/predicates/modules with upper-case acronyms in their name have been renamed to follow our style-guide.
|
||||
The old name still exists as a deprecated alias.
|
||||
@@ -1,10 +0,0 @@
|
||||
## 0.3.4
|
||||
|
||||
### Deprecated APIs
|
||||
|
||||
* Many classes/predicates/modules with upper-case acronyms in their name have been renamed to follow our style-guide.
|
||||
The old name still exists as a deprecated alias.
|
||||
|
||||
### Minor Analysis Improvements
|
||||
|
||||
* All deprecated predicates/classes/modules that have been deprecated for over a year have been deleted.
|
||||
@@ -1 +0,0 @@
|
||||
## 0.3.5
|
||||
@@ -1,2 +1,2 @@
|
||||
---
|
||||
lastReleaseVersion: 0.3.5
|
||||
lastReleaseVersion: 0.3.3
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
name: codeql/csharp-all
|
||||
version: 0.3.6-dev
|
||||
version: 0.3.4-dev
|
||||
groups: csharp
|
||||
dbscheme: semmlecode.csharp.dbscheme
|
||||
extractor: csharp
|
||||
|
||||
@@ -14,4 +14,4 @@ import csharp
|
||||
|
||||
from CommentLine c
|
||||
where c.getText().regexpMatch("(?s).*FIXME.*|.*TODO.*|.*(?<!=)\\s*XXX.*")
|
||||
select c, "TODO comment."
|
||||
select c, "TODO comments should be addressed."
|
||||
|
||||
@@ -72,5 +72,5 @@ where
|
||||
) and
|
||||
m1.fromSource()
|
||||
select m1,
|
||||
"confusing to have methods " + m1.getName() + " in " + m1.getDeclaringType().getName() + " and " +
|
||||
m2.getName() + " in " + m2.getDeclaringType().getName() + "."
|
||||
"It is confusing to have methods " + m1.getName() + " in " + m1.getDeclaringType().getName() +
|
||||
" and " + m2.getName() + " in " + m2.getDeclaringType().getName() + "."
|
||||
|
||||
@@ -1,14 +1,3 @@
|
||||
## 0.3.4
|
||||
|
||||
## 0.3.3
|
||||
|
||||
### Minor Analysis Improvements
|
||||
|
||||
* Parameters of delegates passed to routing endpoint calls like `MapGet` in ASP.NET Core are now considered remote flow sources.
|
||||
* The query `cs/unsafe-deserialization-untrusted-input` is not reporting on all calls of `JsonConvert.DeserializeObject` any longer, it only covers cases that explicitly use unsafe serialization settings.
|
||||
* Added better support for the SQLite framework in the SQL injection query.
|
||||
* File streams are now considered stored flow sources. For example, reading query elements from a file can lead to a Second Order SQL injection alert.
|
||||
|
||||
## 0.3.2
|
||||
|
||||
## 0.3.1
|
||||
|
||||
@@ -64,6 +64,5 @@ where
|
||||
validGuard.controls(array, index) and
|
||||
validGuard.guards(indexAccess, _)
|
||||
)
|
||||
select incorrectGuard,
|
||||
"Off-by-one index comparison against length leads to possible out of bounds $@.", ea,
|
||||
ea.toString()
|
||||
select incorrectGuard, "Off-by-one index comparison against length may lead to out-of-bounds $@.",
|
||||
ea, ea.toString()
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
/**
|
||||
* @name Equality check on floating point values
|
||||
* @description Equality checks on floating point values can yield unexpected results.
|
||||
* @description Comparing results of floating-point computations with '==' or
|
||||
* '!=' is likely to yield surprising results since floating-point
|
||||
* computation does not follow the standard rules of algebra.
|
||||
* @kind problem
|
||||
* @problem.severity warning
|
||||
* @precision medium
|
||||
|
||||
@@ -42,4 +42,4 @@ where
|
||||
(loopStmtWithEmptyBlock(s) or conditionalWithEmptyBlock(s)) and
|
||||
not exists(CommentBlock c | c.getParent() = s) and
|
||||
not exists(ForStmt fs | fs.getBody() = s and exists(fs.getAnUpdate()))
|
||||
select s, "Empty block."
|
||||
select s, "Empty block without comment."
|
||||
|
||||
@@ -35,4 +35,4 @@ where
|
||||
access = cast.getAChild() and
|
||||
access.getTarget().getDeclaringElement() = access.getEnclosingCallable() and
|
||||
nodeBeforeParameterAccess(access.getAControlFlowNode())
|
||||
select cast, "Missing type-check before casting parameter to 'Equals'."
|
||||
select cast, "Equals() method does not check argument type."
|
||||
|
||||
@@ -23,5 +23,5 @@ where
|
||||
c.hasFlowPath(source, sink) and
|
||||
// No global timeout set
|
||||
not exists(RegexGlobalTimeout r)
|
||||
select sink.getNode(), source, sink, "$@ flows to the construction of a regular expression.",
|
||||
source.getNode(), "User-provided value"
|
||||
select sink.getNode(), source, sink, "This regular expression is constructed from a $@.",
|
||||
source.getNode(), "user-provided value"
|
||||
|
||||
@@ -18,4 +18,4 @@ from MethodCall mc
|
||||
where
|
||||
mc instanceof ImplicitToStringExpr and
|
||||
mc.getTarget() instanceof ToStringMethod
|
||||
select mc, "Redundant call to 'ToString'."
|
||||
select mc, "Redundant call to 'ToString' on a String object."
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
category: minorAnalysis
|
||||
---
|
||||
* Added better support for the SQLite framework in the SQL injection query.
|
||||
* File streams are now considered stored flow sources. Eg. reading query elements from a file can lead to a Second Order SQL injection alert.
|
||||
@@ -0,0 +1,4 @@
|
||||
---
|
||||
category: minorAnalysis
|
||||
---
|
||||
* The query `cs/unsafe-deserialization-untrusted-input` is not reporting on all calls of `JsonConvert.DeserializeObject` any longer, it only covers cases that explicitly use unsafe serialization settings.
|
||||
@@ -0,0 +1,4 @@
|
||||
---
|
||||
category: minorAnalysis
|
||||
---
|
||||
* Parameters of delegates passed to routing endpoint calls like `MapGet` in ASP.NET Core are now considered remote flow sources.
|
||||
4
csharp/ql/src/change-notes/2022-08-23-alert-messages.md
Normal file
4
csharp/ql/src/change-notes/2022-08-23-alert-messages.md
Normal file
@@ -0,0 +1,4 @@
|
||||
---
|
||||
category: minorAnalysis
|
||||
---
|
||||
* The alert message of many queries have been changed to make the message consistent with other languages.
|
||||
@@ -1,8 +0,0 @@
|
||||
## 0.3.3
|
||||
|
||||
### Minor Analysis Improvements
|
||||
|
||||
* Parameters of delegates passed to routing endpoint calls like `MapGet` in ASP.NET Core are now considered remote flow sources.
|
||||
* The query `cs/unsafe-deserialization-untrusted-input` is not reporting on all calls of `JsonConvert.DeserializeObject` any longer, it only covers cases that explicitly use unsafe serialization settings.
|
||||
* Added better support for the SQLite framework in the SQL injection query.
|
||||
* File streams are now considered stored flow sources. For example, reading query elements from a file can lead to a Second Order SQL injection alert.
|
||||
@@ -1 +0,0 @@
|
||||
## 0.3.4
|
||||
@@ -1,2 +1,2 @@
|
||||
---
|
||||
lastReleaseVersion: 0.3.4
|
||||
lastReleaseVersion: 0.3.2
|
||||
|
||||
@@ -17,3 +17,5 @@ module SSA {
|
||||
|
||||
predicate hasUnreachedInstruction(IRFunctionBase irFunc) { none() }
|
||||
}
|
||||
|
||||
predicate removedInstruction(TRawInstruction instr) { none() }
|
||||
|
||||
@@ -34,6 +34,7 @@ newtype TInstruction =
|
||||
AliasedSsa::SSA::hasPhiInstruction(blockStartInstr, memoryLocation)
|
||||
} or
|
||||
TAliasedSsaChiInstruction(TRawInstruction primaryInstruction) {
|
||||
not AliasedSsa::removedInstruction(primaryInstruction) and
|
||||
AliasedSsa::SSA::hasChiInstruction(primaryInstruction)
|
||||
} or
|
||||
TAliasedSsaUnreachedInstruction(IRFunctionBase irFunc) {
|
||||
|
||||
@@ -1712,6 +1712,11 @@ class SideEffectInstruction extends Instruction {
|
||||
*/
|
||||
class CallSideEffectInstruction extends SideEffectInstruction {
|
||||
CallSideEffectInstruction() { this.getOpcode() instanceof Opcode::CallSideEffect }
|
||||
|
||||
/** Gets the operand for the value that will be read by this instruction */
|
||||
final SideEffectOperand getSideEffectOperand() { result = this.getAnOperand() }
|
||||
|
||||
final Instruction getSideEffect() { result = this.getAnOperand().getDef() }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1723,6 +1728,11 @@ class CallSideEffectInstruction extends SideEffectInstruction {
|
||||
*/
|
||||
class CallReadSideEffectInstruction extends SideEffectInstruction {
|
||||
CallReadSideEffectInstruction() { this.getOpcode() instanceof Opcode::CallReadSideEffect }
|
||||
|
||||
/** Gets the operand for the value that will be read by this instruction */
|
||||
final SideEffectOperand getSideEffectOperand() { result = this.getAnOperand() }
|
||||
|
||||
final Instruction getSideEffect() { result = this.getAnOperand().getDef() }
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import experimental.ir.internal.Overlap
|
||||
import experimental.ir.internal.IRCSharpLanguage as Language
|
||||
import experimental.ir.implementation.unaliased_ssa.IR
|
||||
import experimental.ir.interfaces.SideEffect as SideEffect
|
||||
|
||||
@@ -41,8 +41,92 @@ newtype TValueNumber =
|
||||
) {
|
||||
loadTotalOverlapValueNumber(_, irFunc, type, memOperand, operand)
|
||||
} or
|
||||
TCallValueNumber(TCallPartialValueNumber vn) { callValueNumber(_, _, vn) } or
|
||||
TUniqueValueNumber(IRFunction irFunc, Instruction instr) { uniqueValueNumber(instr, irFunc) }
|
||||
|
||||
private class NumberableCallInstruction extends CallInstruction {
|
||||
NumberableCallInstruction() {
|
||||
not this.getResultIRType() instanceof IRVoidType and
|
||||
exists(SideEffect::SideEffectFunction sideEffectFunc |
|
||||
sideEffectFunc = this.getStaticCallTarget()
|
||||
|
|
||||
sideEffectFunc.hasOnlySpecificReadSideEffects() and
|
||||
sideEffectFunc.hasOnlySpecificWriteSideEffects()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private newtype TCallPartialValueNumber =
|
||||
TNilArgument() or
|
||||
TArgument(TCallPartialValueNumber head, TValueNumber arg) {
|
||||
exists(NumberableCallInstruction call, int index |
|
||||
callArgValueNumber(call, index, arg) and
|
||||
callPartialValueNumber(call, index, head)
|
||||
)
|
||||
}
|
||||
|
||||
private predicate callValueNumber(
|
||||
NumberableCallInstruction call, int index, TCallPartialValueNumber vn
|
||||
) {
|
||||
index = max(int n | callArgRank(call, n, _) | n) and
|
||||
exists(TCallPartialValueNumber head, TValueNumber arg |
|
||||
callPartialValueNumber(call, index, pragma[only_bind_out](head)) and
|
||||
callArgValueNumber(call, index, pragma[only_bind_into](arg)) and
|
||||
vn = TArgument(head, arg)
|
||||
)
|
||||
or
|
||||
not exists(int n | callArgRank(call, n, _)) and
|
||||
index = -1 and
|
||||
vn = TNilArgument()
|
||||
}
|
||||
|
||||
private predicate callPartialValueNumber(
|
||||
NumberableCallInstruction call, int index, TCallPartialValueNumber head
|
||||
) {
|
||||
exists(call) and
|
||||
index = 1 and
|
||||
head = TNilArgument()
|
||||
or
|
||||
exists(TCallPartialValueNumber prev, TValueNumber prevVN |
|
||||
callPartialValueNumber(call, index - 1, pragma[only_bind_out](prev)) and
|
||||
callArgValueNumber(call, index - 1, pragma[only_bind_into](prevVN)) and
|
||||
head = TArgument(prev, prevVN)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
private predicate callArgValueNumber(NumberableCallInstruction call, int index, TValueNumber arg) {
|
||||
exists(Instruction instr |
|
||||
callArgRank(call, index, instr) and
|
||||
arg = tvalueNumber(instr)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `arg` is the `index`th element in `call`'s extended argument list, including the `this`
|
||||
* argument and side-effect reads.
|
||||
*/
|
||||
private predicate callArgRank(NumberableCallInstruction call, int index, Instruction arg) {
|
||||
arg =
|
||||
rank[index](int argIndex, boolean isEffect, Instruction instr |
|
||||
// There is no need to include the call's read and write side effects on
|
||||
// all-aliased-memory as `NumberableCallInstruction`s do not read or write
|
||||
// to all-aliased-memory.
|
||||
instr = call.getArgument(argIndex) and
|
||||
isEffect = false
|
||||
or
|
||||
exists(ReadSideEffectInstruction read |
|
||||
read.getPrimaryInstruction() = call and
|
||||
read.getSideEffectOperand().getAnyDef() = instr and
|
||||
read.getIndex() = argIndex and
|
||||
isEffect = true
|
||||
)
|
||||
|
|
||||
instr order by argIndex, isEffect
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* A `CopyInstruction` whose source operand's value is congruent to the definition of that source
|
||||
* operand.
|
||||
@@ -93,6 +177,8 @@ private predicate numberableInstruction(Instruction instr) {
|
||||
instr instanceof CongruentCopyInstruction
|
||||
or
|
||||
instr instanceof LoadTotalOverlapInstruction
|
||||
or
|
||||
instr instanceof NumberableCallInstruction
|
||||
}
|
||||
|
||||
private predicate filteredNumberableInstruction(Instruction instr) {
|
||||
@@ -309,6 +395,11 @@ private TValueNumber nonUniqueValueNumber(Instruction instr) {
|
||||
or
|
||||
// The value number of a copy is just the value number of its source value.
|
||||
result = tvalueNumber(instr.(CongruentCopyInstruction).getSourceValue())
|
||||
or
|
||||
exists(TCallPartialValueNumber pvn |
|
||||
callValueNumber(instr, _, pvn) and
|
||||
result = TCallValueNumber(pvn)
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1712,6 +1712,11 @@ class SideEffectInstruction extends Instruction {
|
||||
*/
|
||||
class CallSideEffectInstruction extends SideEffectInstruction {
|
||||
CallSideEffectInstruction() { this.getOpcode() instanceof Opcode::CallSideEffect }
|
||||
|
||||
/** Gets the operand for the value that will be read by this instruction */
|
||||
final SideEffectOperand getSideEffectOperand() { result = this.getAnOperand() }
|
||||
|
||||
final Instruction getSideEffect() { result = this.getAnOperand().getDef() }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1723,6 +1728,11 @@ class CallSideEffectInstruction extends SideEffectInstruction {
|
||||
*/
|
||||
class CallReadSideEffectInstruction extends SideEffectInstruction {
|
||||
CallReadSideEffectInstruction() { this.getOpcode() instanceof Opcode::CallReadSideEffect }
|
||||
|
||||
/** Gets the operand for the value that will be read by this instruction */
|
||||
final SideEffectOperand getSideEffectOperand() { result = this.getAnOperand() }
|
||||
|
||||
final Instruction getSideEffect() { result = this.getAnOperand().getDef() }
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import experimental.ir.internal.Overlap
|
||||
import experimental.ir.internal.IRCSharpLanguage as Language
|
||||
import experimental.ir.implementation.unaliased_ssa.IR
|
||||
import experimental.ir.interfaces.SideEffect as SideEffect
|
||||
|
||||
@@ -41,8 +41,92 @@ newtype TValueNumber =
|
||||
) {
|
||||
loadTotalOverlapValueNumber(_, irFunc, type, memOperand, operand)
|
||||
} or
|
||||
TCallValueNumber(TCallPartialValueNumber vn) { callValueNumber(_, _, vn) } or
|
||||
TUniqueValueNumber(IRFunction irFunc, Instruction instr) { uniqueValueNumber(instr, irFunc) }
|
||||
|
||||
private class NumberableCallInstruction extends CallInstruction {
|
||||
NumberableCallInstruction() {
|
||||
not this.getResultIRType() instanceof IRVoidType and
|
||||
exists(SideEffect::SideEffectFunction sideEffectFunc |
|
||||
sideEffectFunc = this.getStaticCallTarget()
|
||||
|
|
||||
sideEffectFunc.hasOnlySpecificReadSideEffects() and
|
||||
sideEffectFunc.hasOnlySpecificWriteSideEffects()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private newtype TCallPartialValueNumber =
|
||||
TNilArgument() or
|
||||
TArgument(TCallPartialValueNumber head, TValueNumber arg) {
|
||||
exists(NumberableCallInstruction call, int index |
|
||||
callArgValueNumber(call, index, arg) and
|
||||
callPartialValueNumber(call, index, head)
|
||||
)
|
||||
}
|
||||
|
||||
private predicate callValueNumber(
|
||||
NumberableCallInstruction call, int index, TCallPartialValueNumber vn
|
||||
) {
|
||||
index = max(int n | callArgRank(call, n, _) | n) and
|
||||
exists(TCallPartialValueNumber head, TValueNumber arg |
|
||||
callPartialValueNumber(call, index, pragma[only_bind_out](head)) and
|
||||
callArgValueNumber(call, index, pragma[only_bind_into](arg)) and
|
||||
vn = TArgument(head, arg)
|
||||
)
|
||||
or
|
||||
not exists(int n | callArgRank(call, n, _)) and
|
||||
index = -1 and
|
||||
vn = TNilArgument()
|
||||
}
|
||||
|
||||
private predicate callPartialValueNumber(
|
||||
NumberableCallInstruction call, int index, TCallPartialValueNumber head
|
||||
) {
|
||||
exists(call) and
|
||||
index = 1 and
|
||||
head = TNilArgument()
|
||||
or
|
||||
exists(TCallPartialValueNumber prev, TValueNumber prevVN |
|
||||
callPartialValueNumber(call, index - 1, pragma[only_bind_out](prev)) and
|
||||
callArgValueNumber(call, index - 1, pragma[only_bind_into](prevVN)) and
|
||||
head = TArgument(prev, prevVN)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
private predicate callArgValueNumber(NumberableCallInstruction call, int index, TValueNumber arg) {
|
||||
exists(Instruction instr |
|
||||
callArgRank(call, index, instr) and
|
||||
arg = tvalueNumber(instr)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `arg` is the `index`th element in `call`'s extended argument list, including the `this`
|
||||
* argument and side-effect reads.
|
||||
*/
|
||||
private predicate callArgRank(NumberableCallInstruction call, int index, Instruction arg) {
|
||||
arg =
|
||||
rank[index](int argIndex, boolean isEffect, Instruction instr |
|
||||
// There is no need to include the call's read and write side effects on
|
||||
// all-aliased-memory as `NumberableCallInstruction`s do not read or write
|
||||
// to all-aliased-memory.
|
||||
instr = call.getArgument(argIndex) and
|
||||
isEffect = false
|
||||
or
|
||||
exists(ReadSideEffectInstruction read |
|
||||
read.getPrimaryInstruction() = call and
|
||||
read.getSideEffectOperand().getAnyDef() = instr and
|
||||
read.getIndex() = argIndex and
|
||||
isEffect = true
|
||||
)
|
||||
|
|
||||
instr order by argIndex, isEffect
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* A `CopyInstruction` whose source operand's value is congruent to the definition of that source
|
||||
* operand.
|
||||
@@ -93,6 +177,8 @@ private predicate numberableInstruction(Instruction instr) {
|
||||
instr instanceof CongruentCopyInstruction
|
||||
or
|
||||
instr instanceof LoadTotalOverlapInstruction
|
||||
or
|
||||
instr instanceof NumberableCallInstruction
|
||||
}
|
||||
|
||||
private predicate filteredNumberableInstruction(Instruction instr) {
|
||||
@@ -309,6 +395,11 @@ private TValueNumber nonUniqueValueNumber(Instruction instr) {
|
||||
or
|
||||
// The value number of a copy is just the value number of its source value.
|
||||
result = tvalueNumber(instr.(CongruentCopyInstruction).getSourceValue())
|
||||
or
|
||||
exists(TCallPartialValueNumber pvn |
|
||||
callValueNumber(instr, _, pvn) and
|
||||
result = TCallValueNumber(pvn)
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -8,11 +8,6 @@ private import Imports::RawIR as RawIR
|
||||
private import SsaInstructions
|
||||
private import SsaOperands
|
||||
private import NewIR
|
||||
|
||||
private class OldBlock = Reachability::ReachableBlock;
|
||||
|
||||
private class OldInstruction = Reachability::ReachableInstruction;
|
||||
|
||||
import Cached
|
||||
|
||||
cached
|
||||
@@ -58,7 +53,9 @@ private module Cached {
|
||||
|
||||
cached
|
||||
predicate hasInstruction(TStageInstruction instr) {
|
||||
instr instanceof TRawInstruction and instr instanceof OldInstruction
|
||||
instr instanceof TRawInstruction and
|
||||
instr instanceof OldInstruction and
|
||||
not removedInstruction(instr)
|
||||
or
|
||||
instr = phiInstruction(_, _)
|
||||
or
|
||||
@@ -382,7 +379,14 @@ private module Cached {
|
||||
(
|
||||
if Reachability::isInfeasibleInstructionSuccessor(oldInstruction, kind)
|
||||
then result = unreachedInstruction(instruction.getEnclosingIRFunction())
|
||||
else result = getNewInstruction(oldInstruction.getSuccessor(kind))
|
||||
else
|
||||
if removedInstruction(oldInstruction.getSuccessor(kind))
|
||||
then
|
||||
// the only removed nodes are side-effect writes, but those may have Chi nodes
|
||||
// skip to the following instruction in the old IR, which won't be removed
|
||||
// if we start skipping specific side effects, this may no longer hold
|
||||
result = getNewInstruction(oldInstruction.getSuccessor(kind).getSuccessor(kind))
|
||||
else result = getNewInstruction(oldInstruction.getSuccessor(kind))
|
||||
)
|
||||
)
|
||||
or
|
||||
|
||||
@@ -14,3 +14,9 @@ import experimental.ir.implementation.internal.TOperand::UnaliasedSsaOperands as
|
||||
|
||||
/** DEPRECATED: Alias for SsaOperands */
|
||||
deprecated module SSAOperands = SsaOperands;
|
||||
|
||||
predicate removedInstruction(Reachability::ReachableInstruction instr) { none() }
|
||||
|
||||
class OldBlock = Reachability::ReachableBlock;
|
||||
|
||||
class OldInstruction = Reachability::ReachableInstruction;
|
||||
|
||||
24
csharp/ql/src/experimental/ir/interfaces/SideEffect.qll
Normal file
24
csharp/ql/src/experimental/ir/interfaces/SideEffect.qll
Normal file
@@ -0,0 +1,24 @@
|
||||
private import csharp as CSharp
|
||||
|
||||
/**
|
||||
* A class that models the side effects of a library function.
|
||||
*/
|
||||
abstract class SideEffectFunction extends CSharp::Callable {
|
||||
/**
|
||||
* Holds if the function never reads from memory that was defined before entry to the function.
|
||||
* This memory could be from global variables, or from other memory that was reachable from a
|
||||
* pointer that was passed into the function. Input side-effects, and reads from memory that
|
||||
* cannot be visible to the caller (for example a buffer inside an I/O library) are not modeled
|
||||
* here.
|
||||
*/
|
||||
abstract predicate hasOnlySpecificReadSideEffects();
|
||||
|
||||
/**
|
||||
* Holds if the function never writes to memory that remains allocated after the function
|
||||
* returns. This memory could be from global variables, or from other memory that was reachable
|
||||
* from a pointer that was passed into the function. Output side-effects, and writes to memory
|
||||
* that cannot be visible to the caller (for example a buffer inside an I/O library) are not
|
||||
* modeled here.
|
||||
*/
|
||||
abstract predicate hasOnlySpecificWriteSideEffects();
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
name: codeql/csharp-queries
|
||||
version: 0.3.5-dev
|
||||
version: 0.3.3-dev
|
||||
groups:
|
||||
- csharp
|
||||
- queries
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
| TodoComments.cs:4:5:4:26 | // ... | TODO comment. |
|
||||
| TodoComments.cs:5:5:5:27 | // ... | TODO comment. |
|
||||
| TodoCommentsBad.cs:7:9:7:41 | // ... | TODO comment. |
|
||||
| TodoComments.cs:4:5:4:26 | // ... | TODO comments should be addressed. |
|
||||
| TodoComments.cs:5:5:5:27 | // ... | TODO comments should be addressed. |
|
||||
| TodoCommentsBad.cs:7:9:7:41 | // ... | TODO comments should be addressed. |
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user