Compare commits

..

19 Commits

Author SHA1 Message Date
Angela P Wen
2daf50500c Merge pull request #15833 from github/release-prep/2.16.4
Release preparation for version 2.16.4
2024-03-06 13:00:06 -08:00
github-actions[bot]
2f058ffb4d Release preparation for version 2.16.4 2024-03-06 20:56:51 +00:00
Angela P Wen
711c474049 Merge pull request #15832 from github/revert-15814-release-prep/2.16.4
Revert "Release preparation for version 2.16.4"
2024-03-06 12:53:52 -08:00
Angela P Wen
ce31f8641a Revert "Release preparation for version 2.16.4" 2024-03-06 12:07:33 -08:00
Angela P Wen
727a38a409 Merge pull request #15814 from github/release-prep/2.16.4
Release preparation for version 2.16.4
2024-03-05 10:16:21 -08:00
github-actions[bot]
661e68dab5 Release preparation for version 2.16.4 2024-03-05 18:13:58 +00:00
Angela P Wen
7e2a775a2a Merge pull request #15813 from github/revert-15801-release-prep/2.16.4
Revert "Release preparation for version 2.16.4"
2024-03-05 09:20:42 -08:00
Angela P Wen
967963a653 Revert "Release preparation for version 2.16.4" 2024-03-05 08:53:33 -08:00
Michael B. Gale
eaef544a26 Merge pull request #15810 from github/mbg/go/fix-initialised-module-names 2024-03-05 15:34:07 +00:00
Michael B. Gale
40ff75db07 Go: Update list of expected files for single-go-mod-and-go-files-not-under-it test 2024-03-05 14:56:51 +00:00
Michael B. Gale
a8d240dd72 Go: Add integration test for mixed layout project 2024-03-05 14:08:16 +00:00
Michael B. Gale
ac394dc80c Go: Better check for path prefixes 2024-03-05 13:46:33 +00:00
Michael B. Gale
b1e0bc03ab Go: Fix check for whether it is safe to initialise a go.mod file in a given directory 2024-03-05 12:48:21 +00:00
Michael B. Gale
367ecf75d5 Go: Use import path for auto-generated Go module names 2024-03-05 12:48:21 +00:00
Michael B. Gale
2aa093c95c Go: Move getImportPath to shared util package 2024-03-05 12:48:19 +00:00
Angela P Wen
92e91f596f Merge pull request #15801 from github/release-prep/2.16.4
Release preparation for version 2.16.4
2024-03-04 10:57:55 -08:00
github-actions[bot]
a67218a027 Release preparation for version 2.16.4 2024-03-04 17:42:08 +00:00
Angela P Wen
19539ab6d8 Merge pull request #15800 from github/angelapwen/fix-ruby-changenotes
Fix Markdown formatting on Ruby changenotes
2024-03-04 08:52:13 -08:00
Angela P Wen
2b2ea597ce Fix formatting on changenotes 2024-03-04 16:42:38 +00:00
1027 changed files with 34173 additions and 172071 deletions

View File

@@ -88,46 +88,123 @@
"IR Instruction": [
"cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/Instruction.qll",
"cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/Instruction.qll",
"cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/Instruction.qll"
"cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/Instruction.qll",
"csharp/ql/src/experimental/ir/implementation/raw/Instruction.qll",
"csharp/ql/src/experimental/ir/implementation/unaliased_ssa/Instruction.qll"
],
"IR IRBlock": [
"cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/IRBlock.qll",
"cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/IRBlock.qll",
"cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/IRBlock.qll"
"cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/IRBlock.qll",
"csharp/ql/src/experimental/ir/implementation/raw/IRBlock.qll",
"csharp/ql/src/experimental/ir/implementation/unaliased_ssa/IRBlock.qll"
],
"IR IRVariable": [
"cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/IRVariable.qll",
"cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/IRVariable.qll",
"cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/IRVariable.qll"
"cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/IRVariable.qll",
"csharp/ql/src/experimental/ir/implementation/raw/IRVariable.qll",
"csharp/ql/src/experimental/ir/implementation/unaliased_ssa/IRVariable.qll"
],
"IR IRFunction": [
"cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/IRFunction.qll",
"cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/IRFunction.qll",
"cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/IRFunction.qll"
"cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/IRFunction.qll",
"csharp/ql/src/experimental/ir/implementation/raw/IRFunction.qll",
"csharp/ql/src/experimental/ir/implementation/unaliased_ssa/IRFunction.qll"
],
"IR Operand": [
"cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/Operand.qll",
"cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/Operand.qll",
"cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/Operand.qll"
"cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/Operand.qll",
"csharp/ql/src/experimental/ir/implementation/raw/Operand.qll",
"csharp/ql/src/experimental/ir/implementation/unaliased_ssa/Operand.qll"
],
"IR IRType": [
"cpp/ql/lib/semmle/code/cpp/ir/implementation/IRType.qll",
"csharp/ql/src/experimental/ir/implementation/IRType.qll"
],
"IR IRConfiguration": [
"cpp/ql/lib/semmle/code/cpp/ir/implementation/IRConfiguration.qll",
"csharp/ql/src/experimental/ir/implementation/IRConfiguration.qll"
],
"IR UseSoundEscapeAnalysis": [
"cpp/ql/lib/semmle/code/cpp/ir/implementation/UseSoundEscapeAnalysis.qll",
"csharp/ql/src/experimental/ir/implementation/UseSoundEscapeAnalysis.qll"
],
"IR IRFunctionBase": [
"cpp/ql/lib/semmle/code/cpp/ir/implementation/internal/IRFunctionBase.qll",
"csharp/ql/src/experimental/ir/implementation/internal/IRFunctionBase.qll"
],
"IR Operand Tag": [
"cpp/ql/lib/semmle/code/cpp/ir/implementation/internal/OperandTag.qll",
"csharp/ql/src/experimental/ir/implementation/internal/OperandTag.qll"
],
"IR TInstruction": [
"cpp/ql/lib/semmle/code/cpp/ir/implementation/internal/TInstruction.qll",
"csharp/ql/src/experimental/ir/implementation/internal/TInstruction.qll"
],
"IR TIRVariable": [
"cpp/ql/lib/semmle/code/cpp/ir/implementation/internal/TIRVariable.qll",
"csharp/ql/src/experimental/ir/implementation/internal/TIRVariable.qll"
],
"IR IR": [
"cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/IR.qll",
"cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/IR.qll",
"cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/IR.qll"
"cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/IR.qll",
"csharp/ql/src/experimental/ir/implementation/raw/IR.qll",
"csharp/ql/src/experimental/ir/implementation/unaliased_ssa/IR.qll"
],
"IR IRConsistency": [
"cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/IRConsistency.qll",
"cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/IRConsistency.qll",
"cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/IRConsistency.qll"
"cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/IRConsistency.qll",
"csharp/ql/src/experimental/ir/implementation/raw/IRConsistency.qll",
"csharp/ql/src/experimental/ir/implementation/unaliased_ssa/IRConsistency.qll"
],
"IR PrintIR": [
"cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/PrintIR.qll",
"cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/PrintIR.qll",
"cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/PrintIR.qll"
"cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/PrintIR.qll",
"csharp/ql/src/experimental/ir/implementation/raw/PrintIR.qll",
"csharp/ql/src/experimental/ir/implementation/unaliased_ssa/PrintIR.qll"
],
"IR IntegerConstant": [
"cpp/ql/lib/semmle/code/cpp/ir/internal/IntegerConstant.qll",
"csharp/ql/src/experimental/ir/internal/IntegerConstant.qll"
],
"IR IntegerInteval": [
"cpp/ql/lib/semmle/code/cpp/ir/internal/IntegerInterval.qll",
"csharp/ql/src/experimental/ir/internal/IntegerInterval.qll"
],
"IR IntegerPartial": [
"cpp/ql/lib/semmle/code/cpp/ir/internal/IntegerPartial.qll",
"csharp/ql/src/experimental/ir/internal/IntegerPartial.qll"
],
"IR Overlap": [
"cpp/ql/lib/semmle/code/cpp/ir/internal/Overlap.qll",
"csharp/ql/src/experimental/ir/internal/Overlap.qll"
],
"IR EdgeKind": [
"cpp/ql/lib/semmle/code/cpp/ir/implementation/EdgeKind.qll",
"csharp/ql/src/experimental/ir/implementation/EdgeKind.qll"
],
"IR MemoryAccessKind": [
"cpp/ql/lib/semmle/code/cpp/ir/implementation/MemoryAccessKind.qll",
"csharp/ql/src/experimental/ir/implementation/MemoryAccessKind.qll"
],
"IR TempVariableTag": [
"cpp/ql/lib/semmle/code/cpp/ir/implementation/TempVariableTag.qll",
"csharp/ql/src/experimental/ir/implementation/TempVariableTag.qll"
],
"IR Opcode": [
"cpp/ql/lib/semmle/code/cpp/ir/implementation/Opcode.qll",
"csharp/ql/src/experimental/ir/implementation/Opcode.qll"
],
"IR SSAConsistency": [
"cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/SSAConsistency.qll",
"cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/internal/SSAConsistency.qll"
"cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/internal/SSAConsistency.qll",
"csharp/ql/src/experimental/ir/implementation/unaliased_ssa/internal/SSAConsistency.qll"
],
"C++ IR InstructionImports": [
"cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/InstructionImports.qll",
@@ -175,7 +252,8 @@
],
"SSA AliasAnalysis": [
"cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/AliasAnalysis.qll",
"cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/internal/AliasAnalysis.qll"
"cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/internal/AliasAnalysis.qll",
"csharp/ql/src/experimental/ir/implementation/unaliased_ssa/internal/AliasAnalysis.qll"
],
"SSA PrintAliasAnalysis": [
"cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/PrintAliasAnalysis.qll",
@@ -190,28 +268,44 @@
"cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/gvn/internal/ValueNumberingImports.qll",
"cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/gvn/internal/ValueNumberingImports.qll"
],
"IR SSA SimpleSSA": [
"cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/SimpleSSA.qll",
"csharp/ql/src/experimental/ir/implementation/unaliased_ssa/internal/SimpleSSA.qll"
],
"IR AliasConfiguration (unaliased_ssa)": [
"cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/AliasConfiguration.qll",
"csharp/ql/src/experimental/ir/implementation/unaliased_ssa/internal/AliasConfiguration.qll"
],
"IR SSA SSAConstruction": [
"cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/SSAConstruction.qll",
"cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/internal/SSAConstruction.qll"
"cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/internal/SSAConstruction.qll",
"csharp/ql/src/experimental/ir/implementation/unaliased_ssa/internal/SSAConstruction.qll"
],
"IR SSA PrintSSA": [
"cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/PrintSSA.qll",
"cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/internal/PrintSSA.qll"
"cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/internal/PrintSSA.qll",
"csharp/ql/src/experimental/ir/implementation/unaliased_ssa/internal/PrintSSA.qll"
],
"IR ValueNumberInternal": [
"cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/gvn/internal/ValueNumberingInternal.qll",
"cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/gvn/internal/ValueNumberingInternal.qll",
"cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/gvn/internal/ValueNumberingInternal.qll"
"cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/gvn/internal/ValueNumberingInternal.qll",
"csharp/ql/src/experimental/ir/implementation/raw/gvn/internal/ValueNumberingInternal.qll",
"csharp/ql/src/experimental/ir/implementation/unaliased_ssa/gvn/internal/ValueNumberingInternal.qll"
],
"C++ IR ValueNumber": [
"cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/gvn/ValueNumbering.qll",
"cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/gvn/ValueNumbering.qll",
"cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/gvn/ValueNumbering.qll"
"cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/gvn/ValueNumbering.qll",
"csharp/ql/src/experimental/ir/implementation/raw/gvn/ValueNumbering.qll",
"csharp/ql/src/experimental/ir/implementation/unaliased_ssa/gvn/ValueNumbering.qll"
],
"C++ IR PrintValueNumbering": [
"cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/gvn/PrintValueNumbering.qll",
"cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/gvn/PrintValueNumbering.qll",
"cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/gvn/PrintValueNumbering.qll"
"cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/gvn/PrintValueNumbering.qll",
"csharp/ql/src/experimental/ir/implementation/raw/gvn/PrintValueNumbering.qll",
"csharp/ql/src/experimental/ir/implementation/unaliased_ssa/gvn/PrintValueNumbering.qll"
],
"C++ IR ConstantAnalysis": [
"cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/constant/ConstantAnalysis.qll",
@@ -239,6 +333,38 @@
"cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/reachability/PrintDominance.qll",
"cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/reachability/PrintDominance.qll"
],
"C# IR InstructionImports": [
"csharp/ql/src/experimental/ir/implementation/raw/internal/InstructionImports.qll",
"csharp/ql/src/experimental/ir/implementation/unaliased_ssa/internal/InstructionImports.qll"
],
"C# IR IRImports": [
"csharp/ql/src/experimental/ir/implementation/raw/internal/IRImports.qll",
"csharp/ql/src/experimental/ir/implementation/unaliased_ssa/internal/IRImports.qll"
],
"C# IR IRBlockImports": [
"csharp/ql/src/experimental/ir/implementation/raw/internal/IRBlockImports.qll",
"csharp/ql/src/experimental/ir/implementation/unaliased_ssa/internal/IRBlockImports.qll"
],
"C# IR IRFunctionImports": [
"csharp/ql/src/experimental/ir/implementation/raw/internal/IRFunctionImports.qll",
"csharp/ql/src/experimental/ir/implementation/unaliased_ssa/internal/IRFunctionImports.qll"
],
"C# IR IRVariableImports": [
"csharp/ql/src/experimental/ir/implementation/raw/internal/IRVariableImports.qll",
"csharp/ql/src/experimental/ir/implementation/unaliased_ssa/internal/IRVariableImports.qll"
],
"C# IR OperandImports": [
"csharp/ql/src/experimental/ir/implementation/raw/internal/OperandImports.qll",
"csharp/ql/src/experimental/ir/implementation/unaliased_ssa/internal/OperandImports.qll"
],
"C# IR PrintIRImports": [
"csharp/ql/src/experimental/ir/implementation/raw/internal/PrintIRImports.qll",
"csharp/ql/src/experimental/ir/implementation/unaliased_ssa/internal/PrintIRImports.qll"
],
"C# IR ValueNumberingImports": [
"csharp/ql/src/experimental/ir/implementation/raw/gvn/internal/ValueNumberingImports.qll",
"csharp/ql/src/experimental/ir/implementation/unaliased_ssa/gvn/internal/ValueNumberingImports.qll"
],
"C# ControlFlowReachability": [
"csharp/ql/lib/semmle/code/csharp/dataflow/internal/ControlFlowReachability.qll",
"csharp/ql/lib/semmle/code/csharp/dataflow/internal/rangeanalysis/ControlFlowReachability.qll"
@@ -372,4 +498,4 @@
"python/ql/test/experimental/dataflow/model-summaries/InlineTaintTest.ext.yml",
"python/ql/test/experimental/dataflow/model-summaries/NormalDataflowTest.ext.yml"
]
}
}

View File

@@ -1,3 +1,9 @@
## 0.12.7
### Minor Analysis Improvements
* Added destructors for named objects to the intermediate representation.
## 0.12.6
### New Features

View File

@@ -1,4 +1,5 @@
---
category: minorAnalysis
---
* Added destructors for named objects to the intermediate representation.
## 0.12.7
### Minor Analysis Improvements
* Added destructors for named objects to the intermediate representation.

View File

@@ -1,2 +1,2 @@
---
lastReleaseVersion: 0.12.6
lastReleaseVersion: 0.12.7

View File

@@ -1,5 +1,5 @@
name: codeql/cpp-all
version: 0.12.7-dev
version: 0.12.7
groups: cpp
dbscheme: semmlecode.cpp.dbscheme
extractor: cpp

View File

@@ -10,12 +10,13 @@ private import semmle.code.cpp.models.interfaces.FunctionInputsAndOutputs as FIO
private import semmle.code.cpp.ir.internal.IRCppLanguage
private import semmle.code.cpp.ir.dataflow.internal.ModelUtil
private import DataFlowPrivate
private import ssa0.SsaInternals as SsaInternals0
import SsaInternalsCommon
private module SourceVariables {
cached
private newtype TSourceVariable =
TMkSourceVariable(BaseSourceVariable base, int ind) {
TMkSourceVariable(SsaInternals0::SourceVariable base, int ind) {
ind = [0 .. countIndirectionsForCppType(base.getLanguageType()) + 1]
}
@@ -29,7 +30,7 @@ private module SourceVariables {
}
class SourceVariable extends TSourceVariable {
BaseSourceVariable base;
SsaInternals0::SourceVariable base;
int ind;
SourceVariable() { this = TMkSourceVariable(base, ind) }
@@ -41,7 +42,7 @@ private module SourceVariables {
* Gets the base source variable (i.e., the variable without any
* indirections) of this source variable.
*/
BaseSourceVariable getBaseVariable() { result = base }
SsaInternals0::SourceVariable getBaseVariable() { result = base }
/** Gets a textual representation of this element. */
string toString() { result = repeatStars(this.getIndirection()) + base.toString() }
@@ -104,7 +105,16 @@ predicate hasRawIndirectInstruction(Instruction instr, int indirectionIndex) {
cached
private newtype TDefOrUseImpl =
TDefImpl(BaseSourceVariableInstruction base, Operand address, int indirectionIndex) {
isDef(_, _, address, base, _, indirectionIndex)
isDef(_, _, address, base, _, indirectionIndex) and
(
// We only include the definition if the SSA pruning stage
// concluded that the definition is live after the write.
any(SsaInternals0::Def def).getAddressOperand() = address
or
// Since the pruning stage doesn't know about global variables we can't use the above check to
// rule out dead assignments to globals.
base.(VariableAddressInstruction).getAstVariable() instanceof GlobalLikeVariable
)
} or
TUseImpl(BaseSourceVariableInstruction base, Operand operand, int indirectionIndex) {
isUse(_, operand, base, _, indirectionIndex) and
@@ -123,7 +133,8 @@ private newtype TDefOrUseImpl =
TIteratorDef(
Operand iteratorDerefAddress, BaseSourceVariableInstruction container, int indirectionIndex
) {
isIteratorDef(container, iteratorDerefAddress, _, _, indirectionIndex)
isIteratorDef(container, iteratorDerefAddress, _, _, indirectionIndex) and
any(SsaInternals0::Def def | def.isIteratorDef()).getAddressOperand() = iteratorDerefAddress
} or
TIteratorUse(
Operand iteratorAddress, BaseSourceVariableInstruction container, int indirectionIndex
@@ -973,6 +984,17 @@ predicate fromPhiNode(SsaPhiNode nodeFrom, Node nodeTo) {
)
}
/**
* Holds if there is a write at index `i` in basic block `bb` to variable `v` that's
* subsequently read (as determined by the SSA pruning stage).
*/
private predicate variableWriteCand(IRBlock bb, int i, SourceVariable v) {
exists(SsaInternals0::Def def, SsaInternals0::SourceVariable v0 |
def.asDefOrUse().hasIndexInBlock(bb, i, v0) and
v0 = v.getBaseVariable()
)
}
private predicate sourceVariableIsGlobal(
SourceVariable sv, GlobalLikeVariable global, IRFunction func, int indirectionIndex
) {
@@ -996,14 +1018,16 @@ private module SsaInput implements SsaImplCommon::InputSig<Location> {
predicate variableWrite(IRBlock bb, int i, SourceVariable v, boolean certain) {
DataFlowImplCommon::forceCachingInSameStage() and
(
exists(DefImpl def | def.hasIndexInBlock(bb, i, v) |
if def.isCertain() then certain = true else certain = false
)
or
exists(GlobalDefImpl global |
global.hasIndexInBlock(bb, i, v) and
certain = true
)
variableWriteCand(bb, i, v) or
sourceVariableIsGlobal(v, _, _, _)
) and
exists(DefImpl def | def.hasIndexInBlock(bb, i, v) |
if def.isCertain() then certain = true else certain = false
)
or
exists(GlobalDefImpl global |
global.hasIndexInBlock(bb, i, v) and
certain = true
)
}

View File

@@ -0,0 +1,347 @@
/**
* This module defines an initial SSA pruning stage that doesn't take
* indirections into account.
*/
private import codeql.ssa.Ssa as SsaImplCommon
private import semmle.code.cpp.ir.IR
private import semmle.code.cpp.ir.dataflow.internal.DataFlowImplCommon as DataFlowImplCommon
private import semmle.code.cpp.models.interfaces.Allocation as Alloc
private import semmle.code.cpp.models.interfaces.DataFlow as DataFlow
private import semmle.code.cpp.ir.implementation.raw.internal.SideEffects as SideEffects
private import semmle.code.cpp.ir.internal.IRCppLanguage
private import semmle.code.cpp.ir.dataflow.internal.DataFlowPrivate
private import semmle.code.cpp.ir.dataflow.internal.DataFlowUtil
private import semmle.code.cpp.ir.dataflow.internal.SsaInternalsCommon
private module SourceVariables {
class SourceVariable extends BaseSourceVariable {
/**
* Gets the base source variable of this `SourceVariable`.
*/
BaseSourceVariable getBaseVariable() { result = this }
}
}
import SourceVariables
private newtype TDefOrUseImpl =
TDefImpl(Operand address) { isDef(_, _, address, _, _, _) } or
TUseImpl(Operand operand) {
isUse(_, operand, _, _, _) and
not isDef(true, _, operand, _, _, _)
} or
TIteratorDef(BaseSourceVariableInstruction container, Operand iteratorAddress) {
isIteratorDef(container, iteratorAddress, _, _, _)
} or
TIteratorUse(BaseSourceVariableInstruction container, Operand iteratorAddress) {
isIteratorUse(container, iteratorAddress, _, _)
} or
TFinalParameterUse(Parameter p) {
any(Indirection indirection).getType() = p.getUnspecifiedType()
}
abstract private class DefOrUseImpl extends TDefOrUseImpl {
/** Gets a textual representation of this element. */
abstract string toString();
/** Gets the block of this definition or use. */
final IRBlock getBlock() { this.hasIndexInBlock(result, _) }
/** Holds if this definition or use has index `index` in block `block`. */
abstract predicate hasIndexInBlock(IRBlock block, int index);
final predicate hasIndexInBlock(IRBlock block, int index, SourceVariable sv) {
this.hasIndexInBlock(block, index) and
sv = this.getSourceVariable()
}
/** Gets the location of this element. */
abstract Cpp::Location getLocation();
abstract BaseSourceVariableInstruction getBase();
final BaseSourceVariable getBaseSourceVariable() {
result = this.getBase().getBaseSourceVariable()
}
/** Gets the variable that is defined or used. */
final SourceVariable getSourceVariable() {
result.getBaseVariable() = this.getBaseSourceVariable()
}
abstract predicate isCertain();
}
abstract class DefImpl extends DefOrUseImpl {
Operand address;
Operand getAddressOperand() { result = address }
abstract Node0Impl getValue();
override string toString() { result = address.toString() }
override Cpp::Location getLocation() { result = this.getAddressOperand().getLocation() }
final override predicate hasIndexInBlock(IRBlock block, int index) {
this.getAddressOperand().getUse() = block.getInstruction(index)
}
}
private class DirectDef extends DefImpl, TDefImpl {
DirectDef() { this = TDefImpl(address) }
override BaseSourceVariableInstruction getBase() { isDef(_, _, address, result, _, _) }
override Node0Impl getValue() { isDef(_, result, address, _, _, _) }
override predicate isCertain() { isDef(true, _, address, _, _, _) }
}
private class IteratorDef extends DefImpl, TIteratorDef {
BaseSourceVariableInstruction container;
IteratorDef() { this = TIteratorDef(container, address) }
override BaseSourceVariableInstruction getBase() { result = container }
override Node0Impl getValue() { isIteratorDef(_, address, result, _, _) }
override predicate isCertain() { none() }
}
abstract class UseImpl extends DefOrUseImpl { }
abstract private class OperandBasedUse extends UseImpl {
Operand operand;
override string toString() { result = operand.toString() }
final override predicate hasIndexInBlock(IRBlock block, int index) {
// Ideally, this would just be implemented as:
// ```
// operand.getUse() = block.getInstruction(index)
// ```
// but because the IR generated for a snippet such as
// ```
// int x = *p++;
// ```
// looks like
// ```
// r1(glval<int>) = VariableAddress[x] :
// r2(glval<int *>) = VariableAddress[p] :
// r3(int *) = Load[p] : &:r2, m1
// r4(int) = Constant[1] :
// r5(int *) = PointerAdd[4] : r3, r4
// m3(int *) = Store[p] : &:r2, r5
// r6(int *) = CopyValue : r3
// r7(int) = Load[?] : &:r6, ~m2
// m2(int) = Store[x] : &:r1, r7
// ```
// we need to ensure that the `r3` operand of the `CopyValue` instruction isn't seen as a fresh use
// of `p` that happens after the increment. So if the base instruction of this use comes from a
// post-fix crement operation we set the index of the SSA use that wraps the `r3` operand at the
// `CopyValue` instruction to be the same index as the `r3` operand at the `PointerAdd` instruction.
// This ensures that the SSA library doesn't create flow from the `PointerAdd` to `r6`.
exists(BaseSourceVariableInstruction base | base = this.getBase() |
if base.getAst() = any(Cpp::PostfixCrementOperation c).getOperand()
then
exists(Operand op |
op =
min(Operand cand, int i |
isUse(_, cand, base, _, _) and
block.getInstruction(i) = cand.getUse()
|
cand order by i
) and
block.getInstruction(index) = op.getUse()
)
else operand.getUse() = block.getInstruction(index)
)
}
final override Cpp::Location getLocation() { result = operand.getLocation() }
}
private class DirectUse extends OperandBasedUse, TUseImpl {
DirectUse() { this = TUseImpl(operand) }
override BaseSourceVariableInstruction getBase() { isUse(_, operand, result, _, _) }
override predicate isCertain() { isUse(true, operand, _, _, _) }
}
private class IteratorUse extends OperandBasedUse, TIteratorUse {
BaseSourceVariableInstruction container;
IteratorUse() { this = TIteratorUse(container, operand) }
override BaseSourceVariableInstruction getBase() { result = container }
override predicate isCertain() { none() }
}
private class FinalParameterUse extends UseImpl, TFinalParameterUse {
Parameter p;
FinalParameterUse() { this = TFinalParameterUse(p) }
override string toString() { result = p.toString() }
final override predicate hasIndexInBlock(IRBlock block, int index) {
// Ideally, this should always be a `ReturnInstruction`, but if
// someone forgets to write a `return` statement in a function
// with a non-void return type we generate an `UnreachedInstruction`.
// In this case we still want to generate flow out of such functions
// if they write to a parameter. So we pick the index of the
// `UnreachedInstruction` as the index of this use.
// Note that a function may have both a `ReturnInstruction` and an
// `UnreachedInstruction`. If that's the case this predicate will
// return multiple results. I don't think this is detrimental to
// performance, however.
exists(Instruction return |
return instanceof ReturnInstruction or
return instanceof UnreachedInstruction
|
block.getInstruction(index) = return and
return.getEnclosingFunction() = p.getFunction()
)
}
final override Cpp::Location getLocation() {
// Parameters can have multiple locations. When there's a unique location we use
// that one, but if multiple locations exist we default to an unknown location.
result = unique( | | p.getLocation())
or
not exists(unique( | | p.getLocation())) and
result instanceof UnknownDefaultLocation
}
override BaseSourceVariableInstruction getBase() {
exists(InitializeParameterInstruction init |
init.getParameter() = p and
// This is always a `VariableAddressInstruction`
result = init.getAnOperand().getDef()
)
}
override predicate isCertain() { any() }
}
private module SsaInput implements SsaImplCommon::InputSig<Location> {
import InputSigCommon
import SourceVariables
/**
* Holds if the `i`'th write in block `bb` writes to the variable `v`.
* `certain` is `true` if the write is guaranteed to overwrite the entire variable.
*/
predicate variableWrite(IRBlock bb, int i, SourceVariable v, boolean certain) {
DataFlowImplCommon::forceCachingInSameStage() and
exists(DefImpl def | def.hasIndexInBlock(bb, i, v) |
if def.isCertain() then certain = true else certain = false
)
}
/**
* Holds if the `i`'th read in block `bb` reads to the variable `v`.
* `certain` is `true` if the read is guaranteed.
*/
predicate variableRead(IRBlock bb, int i, SourceVariable v, boolean certain) {
exists(UseImpl use | use.hasIndexInBlock(bb, i, v) |
if use.isCertain() then certain = true else certain = false
)
}
}
private newtype TSsaDefOrUse =
TDefOrUse(DefOrUseImpl defOrUse) {
defOrUse instanceof UseImpl
or
// If `defOrUse` is a definition we only include it if the
// SSA library concludes that it's live after the write.
exists(DefinitionExt def, SourceVariable sv, IRBlock bb, int i |
def.definesAt(sv, bb, i, _) and
defOrUse.(DefImpl).hasIndexInBlock(bb, i, sv)
)
} or
TPhi(PhiNode phi)
abstract private class SsaDefOrUse extends TSsaDefOrUse {
string toString() { result = "SsaDefOrUse" }
DefOrUseImpl asDefOrUse() { none() }
PhiNode asPhi() { none() }
abstract Location getLocation();
}
class DefOrUse extends TDefOrUse, SsaDefOrUse {
DefOrUseImpl defOrUse;
DefOrUse() { this = TDefOrUse(defOrUse) }
final override DefOrUseImpl asDefOrUse() { result = defOrUse }
final override Location getLocation() { result = defOrUse.getLocation() }
final SourceVariable getSourceVariable() { result = defOrUse.getSourceVariable() }
}
class Phi extends TPhi, SsaDefOrUse {
PhiNode phi;
Phi() { this = TPhi(phi) }
final override PhiNode asPhi() { result = phi }
final override Location getLocation() { result = phi.getBasicBlock().getLocation() }
}
class UseOrPhi extends SsaDefOrUse {
UseOrPhi() {
this.asDefOrUse() instanceof UseImpl
or
this instanceof Phi
}
final override Location getLocation() {
result = this.asDefOrUse().getLocation() or result = this.(Phi).getLocation()
}
override string toString() {
result = this.asDefOrUse().toString()
or
this instanceof Phi and
result = "Phi"
}
}
class Def extends DefOrUse {
override DefImpl defOrUse;
Operand getAddressOperand() { result = defOrUse.getAddressOperand() }
Instruction getAddress() { result = this.getAddressOperand().getDef() }
Node0Impl getValue() { result = defOrUse.getValue() }
override string toString() { result = this.asDefOrUse().toString() }
BaseSourceVariableInstruction getBase() { result = defOrUse.getBase() }
predicate isIteratorDef() { defOrUse instanceof IteratorDef }
}
private module SsaImpl = SsaImplCommon::Make<Location, SsaInput>;
class PhiNode extends SsaImpl::DefinitionExt {
PhiNode() {
this instanceof SsaImpl::PhiNode or
this instanceof SsaImpl::PhiReadNode
}
}
class DefinitionExt = SsaImpl::DefinitionExt;

View File

@@ -96,9 +96,6 @@ private predicate ignoreExprAndDescendants(Expr expr) {
exists(BuiltInVarArgsStart vaStartExpr |
vaStartExpr.getLastNamedParameter().getFullyConverted() = expr
)
or
// suppress destructors of temporary variables until proper support is added for them.
exists(Expr parent | parent.getAnImplicitDestructorCall() = expr)
}
/**
@@ -747,13 +744,9 @@ newtype TTranslatedElement =
// The declaration/initialization part of a `ConditionDeclExpr`
TTranslatedConditionDecl(ConditionDeclExpr expr) { not ignoreExpr(expr) } or
// The side effects of a `Call`
TTranslatedCallSideEffects(CallOrAllocationExpr expr) {
not ignoreExpr(expr) and
not ignoreSideEffects(expr)
} or
TTranslatedCallSideEffects(CallOrAllocationExpr expr) { not ignoreSideEffects(expr) } or
// The non-argument-specific side effect of a `Call`
TTranslatedCallSideEffect(Expr expr, SideEffectOpcode opcode) {
not ignoreExpr(expr) and
not ignoreSideEffects(expr) and
opcode = getCallSideEffectOpcode(expr)
} or
@@ -771,7 +764,6 @@ newtype TTranslatedElement =
// Constructor calls lack a qualifier (`this`) expression, so we need to handle the side effects
// on `*this` without an `Expr`.
TTranslatedStructorQualifierSideEffect(Call call, SideEffectOpcode opcode) {
not ignoreExpr(call) and
not ignoreSideEffects(call) and
call instanceof ConstructorCall and
opcode = getASideEffectOpcode(call, -1)

View File

@@ -97,6 +97,19 @@ abstract class TranslatedExpr extends TranslatedElement {
)
}
final override predicate hasAnImplicitDestructorCall() {
exists(expr.getAnImplicitDestructorCall())
}
final override int getFirstDestructorCallIndex() {
not this.handlesDestructorsExplicitly() and
(
result = max(int childId | exists(this.getChildInternal(childId))) + 1
or
not exists(this.getChildInternal(_)) and result = 0
)
}
final override Locatable getAst() { result = expr }
final override Declaration getFunction() { result = getEnclosingDeclaration(expr) }

View File

@@ -1,3 +1,10 @@
## 0.9.6
### Minor Analysis Improvements
* The "non-constant format string" query (`cpp/non-constant-format`) has been converted to a `path-problem` query.
* The new C/C++ dataflow and taint-tracking libraries (`semmle.code.cpp.dataflow.new.DataFlow` and `semmle.code.cpp.dataflow.new.TaintTracking`) now implicitly assume that dataflow and taint modelled via `DataFlowFunction` and `TaintFunction` always fully overwrite their buffers and thus act as flow barriers. As a result, many dataflow and taint-tracking queries now produce fewer false positives. To remove this assumption and go back to the previous behavior for a given model, one can override the new `isPartialWrite` predicate.
## 0.9.5
### Minor Analysis Improvements

View File

@@ -1,4 +0,0 @@
---
category: minorAnalysis
---
* The "non-constant format string" query (`cpp/non-constant-format`) has been converted to a `path-problem` query.

View File

@@ -1,4 +1,6 @@
---
category: minorAnalysis
---
## 0.9.6
### Minor Analysis Improvements
* The "non-constant format string" query (`cpp/non-constant-format`) has been converted to a `path-problem` query.
* The new C/C++ dataflow and taint-tracking libraries (`semmle.code.cpp.dataflow.new.DataFlow` and `semmle.code.cpp.dataflow.new.TaintTracking`) now implicitly assume that dataflow and taint modelled via `DataFlowFunction` and `TaintFunction` always fully overwrite their buffers and thus act as flow barriers. As a result, many dataflow and taint-tracking queries now produce fewer false positives. To remove this assumption and go back to the previous behavior for a given model, one can override the new `isPartialWrite` predicate.

View File

@@ -1,2 +1,2 @@
---
lastReleaseVersion: 0.9.5
lastReleaseVersion: 0.9.6

View File

@@ -1,5 +1,5 @@
name: codeql/cpp-queries
version: 0.9.6-dev
version: 0.9.6
groups:
- cpp
- queries

View File

@@ -12779,7 +12779,7 @@ ir.cpp:
# 2215| r2215_1(glval<bool>) = VariableAddress[b] :
# 2215| r2215_2(bool) = Load[b] : &:r2215_1, ~m?
# 2215| v2215_3(void) = ConditionalBranch : r2215_2
#-----| False -> Block 4
#-----| False -> Block 5
#-----| True -> Block 3
# 2212| Block 1
@@ -12796,35 +12796,44 @@ ir.cpp:
# 2216| r2216_3(char *) = Convert : r2216_2
# 2216| mu2216_4(char *) = Store[#throw2216:7] : &:r2216_1, r2216_3
# 2216| v2216_5(void) = ThrowValue : &:r2216_1, ~m?
#-----| Exception -> Block 5
#-----| Exception -> Block 6
# 2218| Block 4
# 2218| r2218_1(glval<String>) = VariableAddress[s2] :
# 2218| mu2218_2(String) = Uninitialized[s2] : &:r2218_1
# 2218| r2218_3(glval<unknown>) = FunctionAddress[String] :
# 2218| v2218_4(void) = Call[String] : func:r2218_3, this:r2218_1
# 2218| mu2218_5(unknown) = ^CallSideEffect : ~m?
# 2218| mu2218_6(String) = ^IndirectMayWriteSideEffect[-1] : &:r2218_1
# 2219| r2219_1(glval<String>) = VariableAddress[s2] :
# 2219| Block 4
# 2219| r2219_1(glval<String>) = VariableAddress[s] :
# 2219| r2219_2(glval<unknown>) = FunctionAddress[~String] :
# 2219| v2219_3(void) = Call[~String] : func:r2219_2, this:r2219_1
# 2219| mu2219_4(unknown) = ^CallSideEffect : ~m?
# 2219| v2219_5(void) = ^IndirectReadSideEffect[-1] : &:r2219_1, ~m?
# 2219| mu2219_6(String) = ^IndirectMayWriteSideEffect[-1] : &:r2219_1
# 2219| r2219_7(glval<String>) = VariableAddress[s] :
# 2219| r2219_8(glval<unknown>) = FunctionAddress[~String] :
# 2219| v2219_9(void) = Call[~String] : func:r2219_8, this:r2219_7
# 2219| mu2219_10(unknown) = ^CallSideEffect : ~m?
# 2219| v2219_11(void) = ^IndirectReadSideEffect[-1] : &:r2219_7, ~m?
# 2219| mu2219_12(String) = ^IndirectMayWriteSideEffect[-1] : &:r2219_7
#-----| Goto -> Block 10
#-----| Goto -> Block 5
# 2220| Block 5
# 2220| v2220_1(void) = CatchByType[const char *] :
#-----| Exception -> Block 7
#-----| Goto -> Block 6
# 2218| Block 5
# 2218| r2218_1(glval<String>) = VariableAddress[s2] :
# 2218| mu2218_2(String) = Uninitialized[s2] : &:r2218_1
# 2218| r2218_3(glval<unknown>) = FunctionAddress[String] :
# 2218| v2218_4(void) = Call[String] : func:r2218_3, this:r2218_1
# 2218| mu2218_5(unknown) = ^CallSideEffect : ~m?
# 2218| mu2218_6(String) = ^IndirectMayWriteSideEffect[-1] : &:r2218_1
# 2219| r2219_7(glval<String>) = VariableAddress[s2] :
# 2219| r2219_8(glval<unknown>) = FunctionAddress[~String] :
# 2219| v2219_9(void) = Call[~String] : func:r2219_8, this:r2219_7
# 2219| mu2219_10(unknown) = ^CallSideEffect : ~m?
# 2219| v2219_11(void) = ^IndirectReadSideEffect[-1] : &:r2219_7, ~m?
# 2219| mu2219_12(String) = ^IndirectMayWriteSideEffect[-1] : &:r2219_7
# 2219| r2219_13(glval<String>) = VariableAddress[s] :
# 2219| r2219_14(glval<unknown>) = FunctionAddress[~String] :
# 2219| v2219_15(void) = Call[~String] : func:r2219_14, this:r2219_13
# 2219| mu2219_16(unknown) = ^CallSideEffect : ~m?
# 2219| v2219_17(void) = ^IndirectReadSideEffect[-1] : &:r2219_13, ~m?
# 2219| mu2219_18(String) = ^IndirectMayWriteSideEffect[-1] : &:r2219_13
#-----| Goto -> Block 11
# 2220| Block 6
# 2220| v2220_1(void) = CatchByType[const char *] :
#-----| Exception -> Block 8
#-----| Goto -> Block 7
# 2220| Block 7
# 2220| r2220_2(glval<char *>) = VariableAddress[s] :
# 2220| mu2220_3(char *) = InitializeParameter[s] : &:r2220_2
# 2220| r2220_4(char *) = Load[s] : &:r2220_2, ~m?
@@ -12841,25 +12850,25 @@ ir.cpp:
# 2221| v2221_10(void) = ThrowValue : &:r2221_1, ~m?
#-----| Exception -> Block 2
# 2223| Block 7
# 2223| v2223_1(void) = CatchByType[const String &] :
#-----| Exception -> Block 9
#-----| Goto -> Block 8
# 2223| Block 8
# 2223| v2223_1(void) = CatchByType[const String &] :
#-----| Exception -> Block 10
#-----| Goto -> Block 9
# 2223| Block 9
# 2223| r2223_2(glval<String &>) = VariableAddress[e] :
# 2223| mu2223_3(String &) = InitializeParameter[e] : &:r2223_2
# 2223| r2223_4(String &) = Load[e] : &:r2223_2, ~m?
# 2223| mu2223_5(unknown) = InitializeIndirection[e] : &:r2223_4
# 2223| v2223_6(void) = NoOp :
#-----| Goto -> Block 10
#-----| Goto -> Block 11
# 2225| Block 9
# 2225| Block 10
# 2225| v2225_1(void) = CatchAny :
# 2226| v2226_1(void) = ReThrow :
#-----| Exception -> Block 2
# 2228| Block 10
# 2228| Block 11
# 2228| v2228_1(void) = NoOp :
# 2212| v2212_9(void) = ReturnVoid :
#-----| Goto -> Block 1

View File

@@ -9,6 +9,7 @@ sideEffectWithoutPrimary
instructionWithoutSuccessor
| ms_try_mix.cpp:35:13:35:19 | ThrowValue: throw ... | Instruction 'ThrowValue: throw ...' has no successors in function '$@'. | ms_try_mix.cpp:29:6:29:19 | void ms_finally_mix(int) | void ms_finally_mix(int) |
| ms_try_mix.cpp:53:5:53:11 | ThrowValue: throw ... | Instruction 'ThrowValue: throw ...' has no successors in function '$@'. | ms_try_mix.cpp:49:6:49:28 | void ms_empty_finally_at_end() | void ms_empty_finally_at_end() |
| statements.cpp:25:5:25:9 | ReThrow: re-throw exception | Instruction 'ReThrow: re-throw exception ' has no successors in function '$@'. | statements.cpp:21:6:21:16 | void early_throw(int) | void early_throw(int) |
| stmt_expr.cpp:27:5:27:15 | Store: ... = ... | Instruction 'Store: ... = ...' has no successors in function '$@'. | stmt_expr.cpp:21:13:21:13 | void stmtexpr::g(int) | void stmtexpr::g(int) |
ambiguousSuccessors
unexplainedLoop

View File

@@ -10,6 +10,9 @@ sideEffectWithoutPrimary
instructionWithoutSuccessor
| ms_try_mix.cpp:35:13:35:19 | ThrowValue: throw ... | Instruction 'ThrowValue: throw ...' has no successors in function '$@'. | ms_try_mix.cpp:29:6:29:19 | void ms_finally_mix(int) | void ms_finally_mix(int) |
| ms_try_mix.cpp:53:5:53:11 | ThrowValue: throw ... | Instruction 'ThrowValue: throw ...' has no successors in function '$@'. | ms_try_mix.cpp:49:6:49:28 | void ms_empty_finally_at_end() | void ms_empty_finally_at_end() |
| statements.cpp:25:5:25:9 | ReThrow: re-throw exception | Instruction 'ReThrow: re-throw exception ' has no successors in function '$@'. | statements.cpp:21:6:21:16 | void early_throw(int) | void early_throw(int) |
| statements.cpp:26:3:26:3 | IndirectMayWriteSideEffect: inner | Instruction 'IndirectMayWriteSideEffect: inner' has no successors in function '$@'. | statements.cpp:21:6:21:16 | void early_throw(int) | void early_throw(int) |
| statements.cpp:28:1:28:1 | IndirectMayWriteSideEffect: before | Instruction 'IndirectMayWriteSideEffect: before' has no successors in function '$@'. | statements.cpp:21:6:21:16 | void early_throw(int) | void early_throw(int) |
| stmt_expr.cpp:27:5:27:15 | Store: ... = ... | Instruction 'Store: ... = ...' has no successors in function '$@'. | stmt_expr.cpp:21:13:21:13 | void stmtexpr::g(int) | void stmtexpr::g(int) |
| stmt_expr.cpp:29:11:32:11 | CopyValue: (statement expression) | Instruction 'CopyValue: (statement expression)' has no successors in function '$@'. | stmt_expr.cpp:21:13:21:13 | void stmtexpr::g(int) | void stmtexpr::g(int) |
| stmt_in_type.cpp:5:53:5:53 | Constant: 1 | Instruction 'Constant: 1' has no successors in function '$@'. | stmt_in_type.cpp:2:6:2:12 | void cpp_fun() | void cpp_fun() |

View File

@@ -9,6 +9,7 @@ sideEffectWithoutPrimary
instructionWithoutSuccessor
| ms_try_mix.cpp:35:13:35:19 | ThrowValue: throw ... | Instruction 'ThrowValue: throw ...' has no successors in function '$@'. | ms_try_mix.cpp:29:6:29:19 | void ms_finally_mix(int) | void ms_finally_mix(int) |
| ms_try_mix.cpp:53:5:53:11 | ThrowValue: throw ... | Instruction 'ThrowValue: throw ...' has no successors in function '$@'. | ms_try_mix.cpp:49:6:49:28 | void ms_empty_finally_at_end() | void ms_empty_finally_at_end() |
| statements.cpp:25:5:25:9 | ReThrow: re-throw exception | Instruction 'ReThrow: re-throw exception ' has no successors in function '$@'. | statements.cpp:21:6:21:16 | void early_throw(int) | void early_throw(int) |
| stmt_expr.cpp:27:5:27:15 | Store: ... = ... | Instruction 'Store: ... = ...' has no successors in function '$@'. | stmt_expr.cpp:21:13:21:13 | void stmtexpr::g(int) | void stmtexpr::g(int) |
ambiguousSuccessors
unexplainedLoop

View File

@@ -1,44 +1,44 @@
package,sink,source,summary,sink:code-injection,sink:encryption-decryptor,sink:encryption-encryptor,sink:encryption-keyprop,sink:encryption-symmetrickey,sink:file-content-store,sink:html-injection,sink:js-injection,sink:log-injection,sink:sql-injection,source:commandargs,source:environment,source:file,source:file-write,source:local,source:remote,summary:taint,summary:value
Amazon.Lambda.APIGatewayEvents,,6,,,,,,,,,,,,,,,,,6,,
Amazon.Lambda.Core,10,,,,,,,,,,,10,,,,,,,,,
Dapper,55,,,,,,,,,,,,55,,,,,,,,
ILCompiler,,,81,,,,,,,,,,,,,,,,,81,
ILLink.RoslynAnalyzer,,,63,,,,,,,,,,,,,,,,,63,
ILLink.Shared,,,32,,,,,,,,,,,,,,,,,29,3
ILLink.Tasks,,,5,,,,,,,,,,,,,,,,,5,
Internal.IL,,,69,,,,,,,,,,,,,,,,,67,2
Internal.Pgo,,,9,,,,,,,,,,,,,,,,,8,1
Internal.TypeSystem,,,367,,,,,,,,,,,,,,,,,331,36
JsonToItemsTaskFactory,,,7,,,,,,,,,,,,,,,,,7,
Microsoft.Android.Build,,,14,,,,,,,,,,,,,,,,,14,
Microsoft.Apple.Build,,,7,,,,,,,,,,,,,,,,,7,
Microsoft.ApplicationBlocks.Data,28,,,,,,,,,,,,28,,,,,,,,
Microsoft.CSharp,,,24,,,,,,,,,,,,,,,,,24,
Microsoft.Diagnostics.Tools.Pgo,,,13,,,,,,,,,,,,,,,,,13,
Microsoft.EntityFrameworkCore,6,,12,,,,,,,,,,6,,,,,,,,12
Microsoft.Extensions.Caching.Distributed,,,15,,,,,,,,,,,,,,,,,15,
Microsoft.Extensions.Caching.Memory,,,38,,,,,,,,,,,,,,,,,37,1
Microsoft.Extensions.Configuration,,2,89,,,,,,,,,,,,2,,,,,86,3
Microsoft.Extensions.DependencyInjection,,,120,,,,,,,,,,,,,,,,,120,
Microsoft.Extensions.DependencyModel,,,12,,,,,,,,,,,,,,,,,12,
Microsoft.Extensions.Diagnostics.Metrics,,,13,,,,,,,,,,,,,,,,,13,
Microsoft.Extensions.FileProviders,,,15,,,,,,,,,,,,,,,,,15,
Microsoft.Extensions.FileSystemGlobbing,,,16,,,,,,,,,,,,,,,,,14,2
Microsoft.Extensions.Hosting,,,23,,,,,,,,,,,,,,,,,22,1
Microsoft.Extensions.Http,,,10,,,,,,,,,,,,,,,,,10,
Microsoft.Extensions.Logging,,,60,,,,,,,,,,,,,,,,,59,1
Microsoft.Extensions.Options,,,8,,,,,,,,,,,,,,,,,8,
Microsoft.Extensions.Primitives,,,64,,,,,,,,,,,,,,,,,64,
Microsoft.Interop,,,78,,,,,,,,,,,,,,,,,78,
Microsoft.NET.Build.Tasks,,,1,,,,,,,,,,,,,,,,,1,
Microsoft.NET.WebAssembly.Webcil,,,7,,,,,,,,,,,,,,,,,7,
Microsoft.VisualBasic,,,10,,,,,,,,,,,,,,,,,5,5
Microsoft.WebAssembly.Build.Tasks,,,3,,,,,,,,,,,,,,,,,3,
Microsoft.Win32.SafeHandles,,,4,,,,,,,,,,,,,,,,,4,
Mono.Linker,,,163,,,,,,,,,,,,,,,,,163,
MySql.Data.MySqlClient,48,,,,,,,,,,,,48,,,,,,,,
Newtonsoft.Json,,,91,,,,,,,,,,,,,,,,,73,18
ServiceStack,194,,7,27,,,,,75,,,,92,,,,,,,7,
SourceGenerators,,,4,,,,,,,,,,,,,,,,,4,
System,67,30,11864,,8,8,9,,,4,5,,33,2,3,1,17,3,4,9898,1966
Windows.Security.Cryptography.Core,1,,,,,,,1,,,,,,,,,,,,,
package,sink,source,summary,sink:code-injection,sink:encryption-decryptor,sink:encryption-encryptor,sink:encryption-keyprop,sink:encryption-symmetrickey,sink:file-content-store,sink:html-injection,sink:js-injection,sink:log-injection,sink:sql-injection,source:file,source:file-write,source:local,source:remote,summary:taint,summary:value
Amazon.Lambda.APIGatewayEvents,,6,,,,,,,,,,,,,,,6,,
Amazon.Lambda.Core,10,,,,,,,,,,,10,,,,,,,
Dapper,55,,,,,,,,,,,,55,,,,,,
ILCompiler,,,81,,,,,,,,,,,,,,,81,
ILLink.RoslynAnalyzer,,,63,,,,,,,,,,,,,,,63,
ILLink.Shared,,,32,,,,,,,,,,,,,,,29,3
ILLink.Tasks,,,5,,,,,,,,,,,,,,,5,
Internal.IL,,,69,,,,,,,,,,,,,,,67,2
Internal.Pgo,,,9,,,,,,,,,,,,,,,8,1
Internal.TypeSystem,,,367,,,,,,,,,,,,,,,331,36
JsonToItemsTaskFactory,,,7,,,,,,,,,,,,,,,7,
Microsoft.Android.Build,,,14,,,,,,,,,,,,,,,14,
Microsoft.Apple.Build,,,7,,,,,,,,,,,,,,,7,
Microsoft.ApplicationBlocks.Data,28,,,,,,,,,,,,28,,,,,,
Microsoft.CSharp,,,24,,,,,,,,,,,,,,,24,
Microsoft.Diagnostics.Tools.Pgo,,,13,,,,,,,,,,,,,,,13,
Microsoft.EntityFrameworkCore,6,,12,,,,,,,,,,6,,,,,,12
Microsoft.Extensions.Caching.Distributed,,,15,,,,,,,,,,,,,,,15,
Microsoft.Extensions.Caching.Memory,,,38,,,,,,,,,,,,,,,37,1
Microsoft.Extensions.Configuration,,,83,,,,,,,,,,,,,,,80,3
Microsoft.Extensions.DependencyInjection,,,120,,,,,,,,,,,,,,,120,
Microsoft.Extensions.DependencyModel,,,12,,,,,,,,,,,,,,,12,
Microsoft.Extensions.Diagnostics.Metrics,,,13,,,,,,,,,,,,,,,13,
Microsoft.Extensions.FileProviders,,,15,,,,,,,,,,,,,,,15,
Microsoft.Extensions.FileSystemGlobbing,,,16,,,,,,,,,,,,,,,14,2
Microsoft.Extensions.Hosting,,,23,,,,,,,,,,,,,,,22,1
Microsoft.Extensions.Http,,,10,,,,,,,,,,,,,,,10,
Microsoft.Extensions.Logging,,,60,,,,,,,,,,,,,,,59,1
Microsoft.Extensions.Options,,,8,,,,,,,,,,,,,,,8,
Microsoft.Extensions.Primitives,,,64,,,,,,,,,,,,,,,64,
Microsoft.Interop,,,78,,,,,,,,,,,,,,,78,
Microsoft.NET.Build.Tasks,,,1,,,,,,,,,,,,,,,1,
Microsoft.NET.WebAssembly.Webcil,,,7,,,,,,,,,,,,,,,7,
Microsoft.VisualBasic,,,10,,,,,,,,,,,,,,,5,5
Microsoft.WebAssembly.Build.Tasks,,,3,,,,,,,,,,,,,,,3,
Microsoft.Win32.SafeHandles,,,4,,,,,,,,,,,,,,,4,
Mono.Linker,,,163,,,,,,,,,,,,,,,163,
MySql.Data.MySqlClient,48,,,,,,,,,,,,48,,,,,,
Newtonsoft.Json,,,91,,,,,,,,,,,,,,,73,18
ServiceStack,194,,7,27,,,,,75,,,,92,,,,,7,
SourceGenerators,,,4,,,,,,,,,,,,,,,4,
System,67,25,11862,,8,8,9,,,4,5,,33,1,17,3,4,9896,1966
Windows.Security.Cryptography.Core,1,,,,,,,1,,,,,,,,,,,
1 package sink source summary sink:code-injection sink:encryption-decryptor sink:encryption-encryptor sink:encryption-keyprop sink:encryption-symmetrickey sink:file-content-store sink:html-injection sink:js-injection sink:log-injection sink:sql-injection source:commandargs source:file source:environment source:file-write source:local source:remote summary:taint summary:value
2 Amazon.Lambda.APIGatewayEvents 6 6
3 Amazon.Lambda.Core 10 10
4 Dapper 55 55
5 ILCompiler 81 81
6 ILLink.RoslynAnalyzer 63 63
7 ILLink.Shared 32 29 3
8 ILLink.Tasks 5 5
9 Internal.IL 69 67 2
10 Internal.Pgo 9 8 1
11 Internal.TypeSystem 367 331 36
12 JsonToItemsTaskFactory 7 7
13 Microsoft.Android.Build 14 14
14 Microsoft.Apple.Build 7 7
15 Microsoft.ApplicationBlocks.Data 28 28
16 Microsoft.CSharp 24 24
17 Microsoft.Diagnostics.Tools.Pgo 13 13
18 Microsoft.EntityFrameworkCore 6 12 6 12
19 Microsoft.Extensions.Caching.Distributed 15 15
20 Microsoft.Extensions.Caching.Memory 38 37 1
21 Microsoft.Extensions.Configuration 2 89 83 2 86 80 3
22 Microsoft.Extensions.DependencyInjection 120 120
23 Microsoft.Extensions.DependencyModel 12 12
24 Microsoft.Extensions.Diagnostics.Metrics 13 13
25 Microsoft.Extensions.FileProviders 15 15
26 Microsoft.Extensions.FileSystemGlobbing 16 14 2
27 Microsoft.Extensions.Hosting 23 22 1
28 Microsoft.Extensions.Http 10 10
29 Microsoft.Extensions.Logging 60 59 1
30 Microsoft.Extensions.Options 8 8
31 Microsoft.Extensions.Primitives 64 64
32 Microsoft.Interop 78 78
33 Microsoft.NET.Build.Tasks 1 1
34 Microsoft.NET.WebAssembly.Webcil 7 7
35 Microsoft.VisualBasic 10 5 5
36 Microsoft.WebAssembly.Build.Tasks 3 3
37 Microsoft.Win32.SafeHandles 4 4
38 Mono.Linker 163 163
39 MySql.Data.MySqlClient 48 48
40 Newtonsoft.Json 91 73 18
41 ServiceStack 194 7 27 75 92 7
42 SourceGenerators 4 4
43 System 67 30 25 11864 11862 8 8 9 4 5 33 2 1 3 17 3 4 9898 9896 1966
44 Windows.Security.Cryptography.Core 1 1

View File

@@ -8,7 +8,7 @@ C# framework & library support
Framework / library,Package,Flow sources,Taint & value steps,Sinks (total),`CWE-079` :sub:`Cross-site scripting`
`ServiceStack <https://servicestack.net/>`_,"``ServiceStack.*``, ``ServiceStack``",,7,194,
System,"``System.*``, ``System``",30,11864,67,9
Others,"``Amazon.Lambda.APIGatewayEvents``, ``Amazon.Lambda.Core``, ``Dapper``, ``ILCompiler``, ``ILLink.RoslynAnalyzer``, ``ILLink.Shared``, ``ILLink.Tasks``, ``Internal.IL``, ``Internal.Pgo``, ``Internal.TypeSystem``, ``JsonToItemsTaskFactory``, ``Microsoft.Android.Build``, ``Microsoft.Apple.Build``, ``Microsoft.ApplicationBlocks.Data``, ``Microsoft.CSharp``, ``Microsoft.Diagnostics.Tools.Pgo``, ``Microsoft.EntityFrameworkCore``, ``Microsoft.Extensions.Caching.Distributed``, ``Microsoft.Extensions.Caching.Memory``, ``Microsoft.Extensions.Configuration``, ``Microsoft.Extensions.DependencyInjection``, ``Microsoft.Extensions.DependencyModel``, ``Microsoft.Extensions.Diagnostics.Metrics``, ``Microsoft.Extensions.FileProviders``, ``Microsoft.Extensions.FileSystemGlobbing``, ``Microsoft.Extensions.Hosting``, ``Microsoft.Extensions.Http``, ``Microsoft.Extensions.Logging``, ``Microsoft.Extensions.Options``, ``Microsoft.Extensions.Primitives``, ``Microsoft.Interop``, ``Microsoft.NET.Build.Tasks``, ``Microsoft.NET.WebAssembly.Webcil``, ``Microsoft.VisualBasic``, ``Microsoft.WebAssembly.Build.Tasks``, ``Microsoft.Win32.SafeHandles``, ``Mono.Linker``, ``MySql.Data.MySqlClient``, ``Newtonsoft.Json``, ``SourceGenerators``, ``Windows.Security.Cryptography.Core``",8,1547,148,
Totals,,38,13418,409,9
System,"``System.*``, ``System``",25,11862,67,9
Others,"``Amazon.Lambda.APIGatewayEvents``, ``Amazon.Lambda.Core``, ``Dapper``, ``ILCompiler``, ``ILLink.RoslynAnalyzer``, ``ILLink.Shared``, ``ILLink.Tasks``, ``Internal.IL``, ``Internal.Pgo``, ``Internal.TypeSystem``, ``JsonToItemsTaskFactory``, ``Microsoft.Android.Build``, ``Microsoft.Apple.Build``, ``Microsoft.ApplicationBlocks.Data``, ``Microsoft.CSharp``, ``Microsoft.Diagnostics.Tools.Pgo``, ``Microsoft.EntityFrameworkCore``, ``Microsoft.Extensions.Caching.Distributed``, ``Microsoft.Extensions.Caching.Memory``, ``Microsoft.Extensions.Configuration``, ``Microsoft.Extensions.DependencyInjection``, ``Microsoft.Extensions.DependencyModel``, ``Microsoft.Extensions.Diagnostics.Metrics``, ``Microsoft.Extensions.FileProviders``, ``Microsoft.Extensions.FileSystemGlobbing``, ``Microsoft.Extensions.Hosting``, ``Microsoft.Extensions.Http``, ``Microsoft.Extensions.Logging``, ``Microsoft.Extensions.Options``, ``Microsoft.Extensions.Primitives``, ``Microsoft.Interop``, ``Microsoft.NET.Build.Tasks``, ``Microsoft.NET.WebAssembly.Webcil``, ``Microsoft.VisualBasic``, ``Microsoft.WebAssembly.Build.Tasks``, ``Microsoft.Win32.SafeHandles``, ``Mono.Linker``, ``MySql.Data.MySqlClient``, ``Newtonsoft.Json``, ``SourceGenerators``, ``Windows.Security.Cryptography.Core``",6,1541,148,
Totals,,31,13410,409,9

View File

@@ -814,7 +814,6 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
private IEnumerable<string> RestoreSolutions(IEnumerable<string> solutions, out IEnumerable<string> assets)
{
var successCount = 0;
var nugetSourceFailures = 0;
var assetFiles = new List<string>();
var projects = solutions.SelectMany(solution =>
{
@@ -824,16 +823,11 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
{
successCount++;
}
if (res.HasNugetPackageSourceError)
{
nugetSourceFailures++;
}
assetFiles.AddRange(res.AssetsFilePaths);
return res.RestoredProjects;
}).ToList();
assets = assetFiles;
CompilationInfos.Add(("Successfully restored solution files", successCount.ToString()));
CompilationInfos.Add(("Failed solution restore with package source error", nugetSourceFailures.ToString()));
CompilationInfos.Add(("Restored projects through solution files", projects.Count.ToString()));
return projects;
}
@@ -847,7 +841,6 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
private void RestoreProjects(IEnumerable<string> projects, out IEnumerable<string> assets)
{
var successCount = 0;
var nugetSourceFailures = 0;
var assetFiles = new List<string>();
var sync = new object();
Parallel.ForEach(projects, new ParallelOptions { MaxDegreeOfParallelism = threads }, project =>
@@ -860,16 +853,11 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
{
successCount++;
}
if (res.HasNugetPackageSourceError)
{
nugetSourceFailures++;
}
assetFiles.AddRange(res.AssetsFilePaths);
}
});
assets = assetFiles;
CompilationInfos.Add(("Successfully restored project files", successCount.ToString()));
CompilationInfos.Add(("Failed project restore with package source error", nugetSourceFailures.ToString()));
}
[GeneratedRegex(@"^(.+)\.(\d+\.\d+\.\d+(-(.+))?)$", RegexOptions.IgnoreCase | RegexOptions.Compiled | RegexOptions.Singleline)]

View File

@@ -131,16 +131,11 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
try
{
var o = JObject.Parse(File.ReadAllText(path));
var v = (string?)o?["sdk"]?["version"];
if (v is not null)
{
versions.Add(v);
}
versions.Add((string)o?["sdk"]?["version"]!);
}
catch
{
// not a valid `global.json` file
logger.LogInfo($"Couldn't find .NET SDK version in '{path}'.");
continue;
}
}

View File

@@ -60,9 +60,10 @@ namespace Semmle.Extraction.CSharp.Standalone
{
try
{
FileUtils.TryDelete(output.FullName);
if (shouldCleanUpContainingFolder)
{
FileUtils.TryDelete(output.FullName);
output.Directory?.Delete(true);
}
}
catch
@@ -104,19 +105,12 @@ namespace Semmle.Extraction.CSharp.Standalone
public void Analysed(int item, int total, string source, string output, TimeSpan time, AnalysisAction action)
{
var extra = action switch
{
AnalysisAction.Extracted => time.ToString(),
AnalysisAction.Excluded => "excluded",
AnalysisAction.UpToDate => "up to date",
_ => "unknown action"
};
logger.LogInfo($"[{item}/{total}] {source} ({extra})");
}
public void Started(int item, int total, string source)
{
logger.LogInfo($"[{item}/{total}] {source} (processing started)");
logger.Log(Severity.Info, "[{0}/{1}] {2} ({3})", item, total, source,
action == AnalysisAction.Extracted
? time.ToString()
: action == AnalysisAction.Excluded
? "excluded"
: "up to date");
}
public void MissingType(string type)

View File

@@ -9,20 +9,19 @@ namespace Semmle.Extraction.CSharp.Entities
private readonly string assemblyPath;
private readonly IAssemblySymbol assembly;
private readonly bool isOutputAssembly;
private Assembly(Context cx, Microsoft.CodeAnalysis.Location? init)
: base(cx, init)
{
isOutputAssembly = init is null;
if (isOutputAssembly)
if (init is null)
{
// This is the output assembly
assemblyPath = cx.Extractor.OutputPath;
assembly = cx.Compilation.Assembly;
}
else
{
assembly = init!.MetadataModule!.ContainingAssembly;
assembly = init.MetadataModule!.ContainingAssembly;
var identity = assembly.Identity;
var idString = identity.Name + " " + identity.Version;
assemblyPath = cx.Extractor.GetAssemblyFile(idString);
@@ -33,13 +32,8 @@ namespace Semmle.Extraction.CSharp.Entities
{
if (assemblyPath is not null)
{
var isBuildlessOutputAssembly = isOutputAssembly && Context.Extractor.Mode.HasFlag(ExtractorMode.Standalone);
var identifier = isBuildlessOutputAssembly
? ""
: assembly.ToString() ?? "";
var name = isBuildlessOutputAssembly ? "" : assembly.Identity.Name;
var version = isBuildlessOutputAssembly ? "" : assembly.Identity.Version.ToString();
trapFile.assemblies(this, File.Create(Context, assemblyPath), identifier, name, version);
trapFile.assemblies(this, File.Create(Context, assemblyPath), assembly.ToString() ?? "",
assembly.Identity.Name, assembly.Identity.Version.ToString());
}
}
@@ -74,16 +68,8 @@ namespace Semmle.Extraction.CSharp.Entities
public override void WriteId(EscapingTextWriter trapFile)
{
if (isOutputAssembly && Context.Extractor.Mode.HasFlag(ExtractorMode.Standalone))
{
trapFile.Write("buildlessOutputAssembly");
}
else
{
trapFile.Write(assembly.ToString());
}
if (assemblyPath is not null)
trapFile.Write(assembly.ToString());
if (!(assemblyPath is null))
{
trapFile.Write("#file:///");
trapFile.Write(assemblyPath.Replace("\\", "/"));

View File

@@ -3,7 +3,6 @@ using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
@@ -24,6 +23,8 @@ namespace Semmle.Extraction.CSharp
private protected Entities.Compilation? compilationEntity;
private IDisposable? compilationTrapFile;
private readonly object progressMutex = new object();
// The bulk of the extraction work, potentially executed in parallel.
protected readonly List<Action> extractionTasks = new List<Action>();
private int taskCount = 0;
@@ -130,9 +131,6 @@ namespace Semmle.Extraction.CSharp
var skipExtraction = options.Cache && File.Exists(trapWriter.TrapFile);
var currentTaskId = IncrementTaskCount();
ReportProgressTaskStarted(currentTaskId, assemblyPath);
if (!skipExtraction)
{
/* Note on parallel builds:
@@ -169,7 +167,7 @@ namespace Semmle.Extraction.CSharp
}
}
ReportProgressTaskDone(currentTaskId, assemblyPath, trapWriter.TrapFile, stopwatch.Elapsed, skipExtraction ? AnalysisAction.UpToDate : AnalysisAction.Extracted);
ReportProgress(assemblyPath, trapWriter.TrapFile, stopwatch.Elapsed, skipExtraction ? AnalysisAction.UpToDate : AnalysisAction.Extracted);
}
catch (Exception ex) // lgtm[cs/catch-of-all-exceptions]
{
@@ -179,13 +177,11 @@ namespace Semmle.Extraction.CSharp
private void DoExtractCIL(PortableExecutableReference r)
{
var currentTaskId = IncrementTaskCount();
ReportProgressTaskStarted(currentTaskId, r.FilePath);
var stopwatch = new Stopwatch();
stopwatch.Start();
CIL.Analyser.ExtractCIL(r.FilePath!, Logger, options, out var trapFile, out var extracted);
stopwatch.Stop();
ReportProgressTaskDone(currentTaskId, r.FilePath, trapFile, stopwatch.Elapsed, extracted ? AnalysisAction.Extracted : AnalysisAction.UpToDate);
ReportProgress(r.FilePath, trapFile, stopwatch.Elapsed, extracted ? AnalysisAction.Extracted : AnalysisAction.UpToDate);
}
private void DoExtractTree(SyntaxTree tree)
@@ -205,9 +201,6 @@ namespace Semmle.Extraction.CSharp
upToDate = options.Fast && FileIsUpToDate(sourcePath, trapWriter.TrapFile);
var currentTaskId = IncrementTaskCount();
ReportProgressTaskStarted(currentTaskId, sourcePath);
if (!upToDate)
{
var cx = new Context(extractor, compilation.Clone(), trapWriter, new SourceScope(tree), addAssemblyTrapPrefix);
@@ -228,7 +221,7 @@ namespace Semmle.Extraction.CSharp
cx.PopulateAll();
}
ReportProgressTaskDone(currentTaskId, sourcePath, trapPath, stopwatch.Elapsed, upToDate ? AnalysisAction.UpToDate : AnalysisAction.Extracted);
ReportProgress(sourcePath, trapPath, stopwatch.Elapsed, upToDate ? AnalysisAction.UpToDate : AnalysisAction.Extracted);
}
catch (Exception ex) // lgtm[cs/catch-of-all-exceptions]
{
@@ -241,11 +234,6 @@ namespace Semmle.Extraction.CSharp
try
{
var assemblyPath = extractor.OutputPath;
var stopwatch = new Stopwatch();
stopwatch.Start();
var currentTaskId = IncrementTaskCount();
ReportProgressTaskStarted(currentTaskId, assemblyPath);
var transformedAssemblyPath = PathTransformer.Transform(assemblyPath);
var assembly = compilation.Assembly;
var trapWriter = transformedAssemblyPath.CreateTrapWriter(Logger, options.TrapCompression, discardDuplicates: false);
@@ -255,8 +243,6 @@ namespace Semmle.Extraction.CSharp
compilationEntity = Entities.Compilation.Create(cx);
extractor.CompilationInfos.ForEach(ci => trapWriter.Writer.compilation_info(compilationEntity, ci.key, ci.value));
ReportProgressTaskDone(currentTaskId, assemblyPath, trapWriter.TrapFile, stopwatch.Elapsed, AnalysisAction.Extracted);
}
catch (Exception ex) // lgtm[cs/catch-of-all-exceptions]
{
@@ -293,19 +279,10 @@ namespace Semmle.Extraction.CSharp
}
}
private int IncrementTaskCount()
private void ReportProgress(string src, string output, TimeSpan time, AnalysisAction action)
{
return Interlocked.Increment(ref taskCount);
}
private void ReportProgressTaskStarted(int currentCount, string src)
{
progressMonitor.Started(currentCount, extractionTasks.Count, src);
}
private void ReportProgressTaskDone(int currentCount, string src, string output, TimeSpan time, AnalysisAction action)
{
progressMonitor.Analysed(currentCount, extractionTasks.Count, src, output, time, action);
lock (progressMutex)
progressMonitor.Analysed(++taskCount, extractionTasks.Count, src, output, time, action);
}
/// <summary>

View File

@@ -47,8 +47,6 @@ namespace Semmle.Extraction.CSharp
}
}
public void Started(int item, int total, string source) { }
public void MissingNamespace(string @namespace) { }
public void MissingSummary(int types, int namespaces) { }

View File

@@ -19,11 +19,6 @@ namespace Semmle.Extraction.CSharp
/// <param name="action">What action was taken for the file.</param>
void Analysed(int item, int total, string source, string output, TimeSpan time, AnalysisAction action);
/// <summary>
/// Callback that processing of a particular item has been started.
/// </summary>
void Started(int item, int total, string source);
/// <summary>
/// A "using namespace" directive was seen but the given
/// namespace could not be found.

View File

@@ -1,3 +1,7 @@
## 1.7.10
No user-facing changes.
## 1.7.9
No user-facing changes.

View File

@@ -0,0 +1,3 @@
## 1.7.10
No user-facing changes.

View File

@@ -1,2 +1,2 @@
---
lastReleaseVersion: 1.7.9
lastReleaseVersion: 1.7.10

View File

@@ -1,5 +1,5 @@
name: codeql/csharp-solorigate-all
version: 1.7.10-dev
version: 1.7.10
groups:
- csharp
- solorigate

View File

@@ -1,3 +1,7 @@
## 1.7.10
No user-facing changes.
## 1.7.9
No user-facing changes.

View File

@@ -0,0 +1,3 @@
## 1.7.10
No user-facing changes.

View File

@@ -1,2 +1,2 @@
---
lastReleaseVersion: 1.7.9
lastReleaseVersion: 1.7.10

View File

@@ -1,5 +1,5 @@
name: codeql/csharp-solorigate-queries
version: 1.7.10-dev
version: 1.7.10
groups:
- csharp
- solorigate

View File

@@ -1,4 +1,5 @@
import csharp
import cil
private import semmle.code.csharp.controlflow.internal.ControlFlowGraphImpl as ControlFlowGraphImpl
private import semmle.code.csharp.dataflow.internal.DataFlowImplSpecific
private import semmle.code.csharp.dataflow.internal.TaintTrackingImplSpecific
@@ -30,6 +31,11 @@ private module Input implements InputSig<CsharpDataFlow> {
n instanceof FlowInsensitiveFieldNode
}
predicate missingLocationExclude(Node n) {
// Some CIL methods are missing locations
n.asParameter() instanceof CIL::Parameter
}
predicate postWithInFlowExclude(Node n) {
n instanceof FlowSummaryNode
or
@@ -42,6 +48,8 @@ private module Input implements InputSig<CsharpDataFlow> {
not exists(LocalFlow::getAPostUpdateNodeForArg(n.getControlFlowNode()))
or
n instanceof ParamsArgumentNode
or
n.asExpr() instanceof CIL::Expr
}
predicate postHasUniquePreExclude(PostUpdateNode n) {

View File

@@ -1,17 +0,0 @@
| Failed project restore with package source error | 1.0 |
| Failed solution restore with package source error | 0.0 |
| Fallback nuget restore | 1.0 |
| Project files on filesystem | 1.0 |
| Resolved assembly conflicts | 7.0 |
| Restored .NET framework variants | 0.0 |
| Restored projects through solution files | 0.0 |
| Solution files on filesystem | 1.0 |
| Source files generated | 0.0 |
| Source files on filesystem | 1.0 |
| Successfully ran fallback nuget restore | 1.0 |
| Successfully restored project files | 0.0 |
| Successfully restored solution files | 1.0 |
| Unresolved references | 0.0 |
| UseWPF set | 0.0 |
| UseWindowsForms set | 0.0 |
| WebView extraction enabled | 1.0 |

View File

@@ -1,14 +0,0 @@
import csharp
import semmle.code.csharp.commons.Diagnostics
query predicate compilationInfo(string key, float value) {
key != "Resolved references" and
exists(Compilation c, string infoKey, string infoValue | infoValue = c.getInfo(infoKey) |
key = infoKey and
value = infoValue.toFloat()
or
not exists(infoValue.toFloat()) and
key = infoKey + ": " + infoValue and
value = 1
)
}

View File

@@ -1,3 +1,17 @@
## 0.8.10
### Major Analysis Improvements
* Improved support for flow through captured variables that properly adheres to inter-procedural control flow.
* We no longer make use of CodeQL database stats, which may affect join-orders in custom queries. It is therefore recommended to test performance of custom queries after upgrading to this version.
### Minor Analysis Improvements
* C# 12: Add QL library support (`ExperimentalAttribute`) for the experimental attribute.
* C# 12: Add extractor and QL library support for `ref readonly` parameters.
* C#: The table `expr_compiler_generated` has been deleted and its content has been added to `compiler_generated`.
* Data flow via get only properties like `public object Obj { get; }` is now captured by the data flow library.
## 0.8.9
### Minor Analysis Improvements

View File

@@ -1,4 +0,0 @@
---
category: minorAnalysis
---
* Data flow via get only properties like `public object Obj { get; }` is now captured by the data flow library.

View File

@@ -1,4 +0,0 @@
---
category: majorAnalysis
---
* We no longer make use of CodeQL database stats, which may affect join-orders in custom queries. It is therefore recommended to test performance of custom queries after upgrading to this version.

View File

@@ -1,4 +0,0 @@
---
category: minorAnalysis
---
* C#: The table `expr_compiler_generated` has been deleted and its content has been added to `compiler_generated`.

View File

@@ -1,4 +0,0 @@
---
category: majorAnalysis
---
* Improved support for flow through captured variables that properly adheres to inter-procedural control flow.

View File

@@ -1,4 +0,0 @@
---
category: minorAnalysis
---
* C# 12: Add QL library support (`ExperimentalAttribute`) for the experimental attribute.

View File

@@ -1,4 +0,0 @@
---
category: minorAnalysis
---
* C# 12: Add extractor and QL library support for `ref readonly` parameters.

View File

@@ -1,4 +0,0 @@
---
category: breaking
---
* The QL library C# classes no longer extend their corresponding `DotNet` classes. Furthermore, CIL related data flow functionality has been deleted and all `DotNet` and `CIL` related classes have been deprecated. This effectively means that it no longer has any effect to enable CIL extraction.

View File

@@ -1,4 +0,0 @@
---
category: minorAnalysis
---
* The models for `System.IO.TextReader` have been modified to better model the flow of tainted text from a `TextReader`.

View File

@@ -1,5 +0,0 @@
---
category: minorAnalysis
---
* The .NET standard libraries APIs for accessing command line arguments and environment variables have been modeled using the `commandargs` and `environment` threat models.
* The `cs/assembly-path-injection` query has been modified so that it's sources rely on `ThreatModelFlowSource`. In order to restore results from command line arguments, you should enable the `commandargs` threat model.

View File

@@ -1,4 +0,0 @@
---
category: minorAnalysis
---
* The models for `System.Net.Http.HttpRequestMessage` have been modified to better model the flow of tainted URIs.

View File

@@ -0,0 +1,13 @@
## 0.8.10
### Major Analysis Improvements
* Improved support for flow through captured variables that properly adheres to inter-procedural control flow.
* We no longer make use of CodeQL database stats, which may affect join-orders in custom queries. It is therefore recommended to test performance of custom queries after upgrading to this version.
### Minor Analysis Improvements
* C# 12: Add QL library support (`ExperimentalAttribute`) for the experimental attribute.
* C# 12: Add extractor and QL library support for `ref readonly` parameters.
* C#: The table `expr_compiler_generated` has been deleted and its content has been added to `compiler_generated`.
* Data flow via get only properties like `public object Obj { get; }` is now captured by the data flow library.

View File

@@ -1,2 +1,2 @@
---
lastReleaseVersion: 0.8.9
lastReleaseVersion: 0.8.10

View File

@@ -2,4 +2,4 @@
* The default QL library for modeling .NET definitions for both C# and CIL code.
*/
deprecated import semmle.code.dotnet.DotNet as DotNet
import semmle.code.dotnet.DotNet as DotNet

View File

@@ -1,17 +0,0 @@
extensions:
- addsTo:
pack: codeql/csharp-all
extensible: sourceModel
data:
- ["Microsoft.Extensions.Configuration", "EnvironmentVariablesExtensions", False, "AddEnvironmentVariables", "", "", "Argument[0]", "environment", "manual"]
- ["Microsoft.Extensions.Configuration", "EnvironmentVariablesExtensions", False, "AddEnvironmentVariables", "", "", "ReturnValue", "environment", "manual"]
- addsTo:
pack: codeql/csharp-all
extensible: summaryModel
data:
- ["Microsoft.Extensions.Configuration", "IConfiguration", True, "get_Item", "(System.String)", "", "Argument[this]", "ReturnValue", "taint", "manual"]
- ["Microsoft.Extensions.Configuration", "IConfigurationBuilder", True, "Build", "()", "", "Argument[this]", "ReturnValue", "taint", "manual"]
- ["Microsoft.Extensions.Configuration", "CommandLineConfigurationExtensions", False, "AddCommandLine", "", "", "Argument[1]", "Argument[0]", "taint", "manual"]
- ["Microsoft.Extensions.Configuration", "CommandLineConfigurationExtensions", False, "AddCommandLine", "(Microsoft.Extensions.Configuration.IConfigurationBuilder,System.String[],System.Collections.Generic.IDictionary<System.String,System.String>)", "", "Argument[2]", "Argument[0]", "taint", "manual"]
- ["Microsoft.Extensions.Configuration", "CommandLineConfigurationExtensions", False, "AddCommandLine", "", "", "Argument[1]", "ReturnValue", "taint", "manual"]
- ["Microsoft.Extensions.Configuration", "CommandLineConfigurationExtensions", False, "AddCommandLine", "(Microsoft.Extensions.Configuration.IConfigurationBuilder,System.String[],System.Collections.Generic.IDictionary<System.String,System.String>)", "", "Argument[2]", "ReturnValue", "taint", "manual"]

View File

@@ -89,16 +89,14 @@ extensions:
- ["System.IO", "StreamReader", False, "StreamReader", "(System.String,System.Text.Encoding,System.Boolean,System.Int32)", "", "Argument[0]", "Argument[this]", "taint", "manual"]
- ["System.IO", "StringReader", False, "StringReader", "(System.String)", "", "Argument[0]", "Argument[this]", "taint", "manual"]
- ["System.IO", "TextReader", True, "Read", "()", "", "Argument[this]", "ReturnValue", "taint", "manual"]
- ["System.IO", "TextReader", True, "Read", "(System.Char[],System.Int32,System.Int32)", "", "Argument[this]", "Argument[0].Element", "taint", "manual"]
- ["System.IO", "TextReader", True, "Read", "(System.Span<System.Char>)", "", "Argument[this]", "Argument[0].Element", "taint", "manual"]
- ["System.IO", "TextReader", True, "ReadAsync", "(System.Char[],System.Int32,System.Int32)", "", "Argument[this]", "Argument[0].Element", "taint", "manual"]
# Post-update nodes for `Memory<T>` are currently unsupported. This model is provided for completeness
- ["System.IO", "TextReader", True, "ReadAsync", "(System.Memory<System.Char>,System.Threading.CancellationToken)", "", "Argument[this]", "Argument[0].Element", "taint", "manual"]
- ["System.IO", "TextReader", True, "ReadBlock", "(System.Char[],System.Int32,System.Int32)", "", "Argument[this]", "Argument[0].Element", "taint", "manual"]
- ["System.IO", "TextReader", True, "ReadBlock", "(System.Span<System.Char>)", "", "Argument[this]", "Argument[0].Element", "taint", "manual"]
- ["System.IO", "TextReader", True, "ReadBlockAsync", "(System.Char[],System.Int32,System.Int32)", "", "Argument[this]", "Argument[0].Element", "taint", "manual"]
# Post-update nodes for `Memory<T>` are currently unsupported. This model is provided for completeness
- ["System.IO", "TextReader", True, "ReadBlockAsync", "(System.Memory<System.Char>,System.Threading.CancellationToken)", "", "Argument[this]", "Argument[0].Element", "taint", "manual"]
- ["System.IO", "TextReader", True, "Read", "(System.Char[],System.Int32,System.Int32)", "", "Argument[this]", "ReturnValue", "taint", "manual"]
- ["System.IO", "TextReader", True, "Read", "(System.Span<System.Char>)", "", "Argument[this]", "ReturnValue", "taint", "manual"]
- ["System.IO", "TextReader", True, "ReadAsync", "(System.Char[],System.Int32,System.Int32)", "", "Argument[this]", "ReturnValue", "taint", "manual"]
- ["System.IO", "TextReader", True, "ReadAsync", "(System.Memory<System.Char>,System.Threading.CancellationToken)", "", "Argument[this]", "ReturnValue", "taint", "manual"]
- ["System.IO", "TextReader", True, "ReadBlock", "(System.Char[],System.Int32,System.Int32)", "", "Argument[this]", "ReturnValue", "taint", "manual"]
- ["System.IO", "TextReader", True, "ReadBlock", "(System.Span<System.Char>)", "", "Argument[this]", "ReturnValue", "taint", "manual"]
- ["System.IO", "TextReader", True, "ReadBlockAsync", "(System.Char[],System.Int32,System.Int32)", "", "Argument[this]", "ReturnValue", "taint", "manual"]
- ["System.IO", "TextReader", True, "ReadBlockAsync", "(System.Memory<System.Char>,System.Threading.CancellationToken)", "", "Argument[this]", "ReturnValue", "taint", "manual"]
- ["System.IO", "TextReader", True, "ReadLine", "()", "", "Argument[this]", "ReturnValue", "taint", "manual"]
- ["System.IO", "TextReader", True, "ReadLineAsync", "()", "", "Argument[this]", "ReturnValue", "taint", "manual"]
- ["System.IO", "TextReader", True, "ReadToEnd", "()", "", "Argument[this]", "ReturnValue", "taint", "manual"]

View File

@@ -8,8 +8,6 @@ extensions:
pack: codeql/csharp-all
extensible: summaryModel
data:
- ["System.Net.Http", "HttpRequestMessage", False, "HttpRequestMessage", "(System.Net.Http.HttpMethod,System.String)", "", "Argument[0]", "Argument[this]", "taint", "manual"]
- ["System.Net.Http", "HttpRequestMessage", False, "HttpRequestMessage", "(System.Net.Http.HttpMethod,System.String)", "", "Argument[1]", "Argument[this]", "taint", "manual"]
- ["System.Net.Http", "HttpRequestOptions", False, "Add", "(System.Collections.Generic.KeyValuePair<System.String,System.Object>)", "", "Argument[0].Property[System.Collections.Generic.KeyValuePair`2.Key]", "Argument[this].Element.Property[System.Collections.Generic.KeyValuePair`2.Key]", "value", "manual"]
- ["System.Net.Http", "HttpRequestOptions", False, "Add", "(System.Collections.Generic.KeyValuePair<System.String,System.Object>)", "", "Argument[0].Property[System.Collections.Generic.KeyValuePair`2.Value]", "Argument[this].Element.Property[System.Collections.Generic.KeyValuePair`2.Value]", "value", "manual"]
- ["System.Net.Http", "MultipartContent", False, "Add", "(System.Net.Http.HttpContent)", "", "Argument[0]", "Argument[this].Element", "value", "manual"]

View File

@@ -6,11 +6,6 @@ extensions:
- ["System", "Console", False, "Read", "", "", "ReturnValue", "local", "manual"]
- ["System", "Console", False, "ReadKey", "", "", "ReturnValue", "local", "manual"]
- ["System", "Console", False, "ReadLine", "", "", "ReturnValue", "local", "manual"]
- ["System", "Environment", False, "ExpandEnvironmentVariables", "(System.String)", "", "ReturnValue", "environment", "manual"]
- ["System", "Environment", False, "GetCommandLineArgs", "()", "", "ReturnValue", "commandargs", "manual"]
- ["System", "Environment", False, "get_CommandLine", "()", "", "ReturnValue", "commandargs", "manual"]
- ["System", "Environment", False, "GetEnvironmentVariable", "", "", "ReturnValue", "environment", "manual"]
- ["System", "Environment", False, "GetEnvironmentVariables", "", "", "ReturnValue", "environment", "manual"]
- addsTo:
pack: codeql/csharp-all
extensible: summaryModel

View File

@@ -1,5 +1,5 @@
name: codeql/csharp-all
version: 0.8.10-dev
version: 0.8.10
groups: csharp
dbscheme: semmlecode.csharp.dbscheme
extractor: csharp

View File

@@ -7,7 +7,7 @@
private import CIL
/** An instruction that accesses a variable. */
deprecated class Access extends Instruction, @cil_access {
class Access extends Instruction, @cil_access {
/** Gets the declaration referenced by this instruction. */
Variable getTarget() { cil_access(this, result) }
}
@@ -16,59 +16,59 @@ deprecated class Access extends Instruction, @cil_access {
* An instruction that accesses a variable.
* This class is provided for consistency with the C# data model.
*/
deprecated class VariableAccess extends Access, @cil_access { }
class VariableAccess extends Access, @cil_access { }
/** An instruction that reads a variable. */
deprecated class ReadAccess extends VariableAccess, Expr, @cil_read_access {
class ReadAccess extends VariableAccess, Expr, @cil_read_access {
override Type getType() { result = this.getTarget().getType() }
}
/** An instruction yielding an address. */
deprecated class ReadRef extends Expr, @cil_read_ref { }
class ReadRef extends Expr, @cil_read_ref { }
/** An instruction that reads the address of a variable. */
deprecated class ReadRefAccess extends ReadAccess, ReadRef { }
class ReadRefAccess extends ReadAccess, ReadRef { }
/** An instruction that writes a variable. */
deprecated class WriteAccess extends VariableAccess, @cil_write_access {
class WriteAccess extends VariableAccess, @cil_write_access {
/** Gets the expression whose value is used in this variable write. */
Expr getExpr() { none() }
}
/** An instruction that accesses a parameter. */
deprecated class ParameterAccess extends StackVariableAccess, @cil_arg_access {
class ParameterAccess extends StackVariableAccess, @cil_arg_access {
override MethodParameter getTarget() { result = StackVariableAccess.super.getTarget() }
}
/** An instruction that reads a parameter. */
deprecated class ParameterReadAccess extends ParameterAccess, ReadAccess {
class ParameterReadAccess extends ParameterAccess, ReadAccess {
override int getPopCount() { result = 0 }
}
/** An instruction that writes to a parameter. */
deprecated class ParameterWriteAccess extends ParameterAccess, WriteAccess {
class ParameterWriteAccess extends ParameterAccess, WriteAccess {
override int getPopCount() { result = 1 }
override Expr getExpr() { result = this.getOperand(0) }
}
/** An access to the `this` parameter. */
deprecated class ThisAccess extends ParameterReadAccess {
class ThisAccess extends ParameterReadAccess {
ThisAccess() { this.getTarget() instanceof ThisParameter }
}
/** An instruction that accesses a stack variable. */
deprecated class StackVariableAccess extends VariableAccess, @cil_stack_access {
class StackVariableAccess extends VariableAccess, @cil_stack_access {
override StackVariable getTarget() { result = VariableAccess.super.getTarget() }
}
/** An instruction that accesses a local variable. */
deprecated class LocalVariableAccess extends StackVariableAccess, @cil_local_access {
class LocalVariableAccess extends StackVariableAccess, @cil_local_access {
override LocalVariable getTarget() { result = StackVariableAccess.super.getTarget() }
}
/** An instruction that writes to a local variable. */
deprecated class LocalVariableWriteAccess extends LocalVariableAccess, WriteAccess {
class LocalVariableWriteAccess extends LocalVariableAccess, WriteAccess {
override int getPopCount() { result = 1 }
override Expr getExpr() { result = this.getOperand(0) }
@@ -77,12 +77,12 @@ deprecated class LocalVariableWriteAccess extends LocalVariableAccess, WriteAcce
}
/** An instruction that reads a local variable. */
deprecated class LocalVariableReadAccess extends LocalVariableAccess, ReadAccess {
class LocalVariableReadAccess extends LocalVariableAccess, ReadAccess {
override int getPopCount() { result = 0 }
}
/** An instruction that accesses a field. */
deprecated class FieldAccess extends VariableAccess, @cil_field_access {
class FieldAccess extends VariableAccess, @cil_field_access {
override Field getTarget() { result = VariableAccess.super.getTarget() }
override string getExtra() { result = this.getTarget().getName() }
@@ -92,7 +92,7 @@ deprecated class FieldAccess extends VariableAccess, @cil_field_access {
}
/** An instruction that reads a field. */
abstract deprecated class FieldReadAccess extends FieldAccess, ReadAccess { }
abstract class FieldReadAccess extends FieldAccess, ReadAccess { }
/** An instruction that writes a field. */
abstract deprecated class FieldWriteAccess extends FieldAccess, WriteAccess { }
abstract class FieldWriteAccess extends FieldAccess, WriteAccess { }

View File

@@ -4,7 +4,7 @@ private import CIL
private import semmle.code.csharp.Location as CS
/** An attribute to a declaration, such as a method, field, type or parameter. */
deprecated class Attribute extends Element, @cil_attribute {
class Attribute extends Element, @cil_attribute {
/** Gets the declaration this attribute is attached to. */
Declaration getDeclaration() { cil_attribute(this, result, _) }
@@ -29,7 +29,7 @@ deprecated class Attribute extends Element, @cil_attribute {
}
/** A generic attribute to a declaration. */
deprecated class GenericAttribute extends Attribute {
class GenericAttribute extends Attribute {
private ConstructedType type;
GenericAttribute() { type = this.getType() }

View File

@@ -8,7 +8,7 @@ private import CIL
* A basic block, that is, a maximal straight-line sequence of control flow nodes
* without branches or joins.
*/
deprecated class BasicBlock extends Cached::TBasicBlockStart {
class BasicBlock extends Cached::TBasicBlockStart {
/** Gets an immediate successor of this basic block, if any. */
BasicBlock getASuccessor() { result.getFirstNode() = this.getLastNode().getASuccessor() }
@@ -249,7 +249,7 @@ deprecated class BasicBlock extends Cached::TBasicBlockStart {
* Internal implementation details.
*/
cached
deprecated private module Cached {
private module Cached {
/** Internal representation of basic blocks. */
cached
newtype TBasicBlock = TBasicBlockStart(ControlFlowNode cfn) { startsBB(cfn) }
@@ -287,54 +287,49 @@ deprecated private module Cached {
* Holds if the first node of basic block `succ` is a control flow
* successor of the last node of basic block `pred`.
*/
deprecated private predicate succBB(BasicBlock pred, BasicBlock succ) {
succ = pred.getASuccessor()
}
private predicate succBB(BasicBlock pred, BasicBlock succ) { succ = pred.getASuccessor() }
/** Holds if `dom` is an immediate dominator of `bb`. */
deprecated predicate bbIDominates(BasicBlock dom, BasicBlock bb) =
idominance(entryBB/1, succBB/2)(_, dom, bb)
predicate bbIDominates(BasicBlock dom, BasicBlock bb) = idominance(entryBB/1, succBB/2)(_, dom, bb)
/** Holds if `pred` is a basic block predecessor of `succ`. */
deprecated private predicate predBB(BasicBlock succ, BasicBlock pred) { succBB(pred, succ) }
private predicate predBB(BasicBlock succ, BasicBlock pred) { succBB(pred, succ) }
/** Holds if `dom` is an immediate post-dominator of `bb`. */
deprecated predicate bbIPostDominates(BasicBlock dom, BasicBlock bb) =
predicate bbIPostDominates(BasicBlock dom, BasicBlock bb) =
idominance(exitBB/1, predBB/2)(_, dom, bb)
/**
* An entry basic block, that is, a basic block whose first node is
* the entry node of a callable.
*/
deprecated class EntryBasicBlock extends BasicBlock {
class EntryBasicBlock extends BasicBlock {
EntryBasicBlock() { entryBB(this) }
}
/** Holds if `bb` is an entry basic block. */
deprecated private predicate entryBB(BasicBlock bb) {
bb.getFirstNode() instanceof MethodImplementation
}
private predicate entryBB(BasicBlock bb) { bb.getFirstNode() instanceof MethodImplementation }
/**
* An exit basic block, that is, a basic block whose last node is
* an exit node.
*/
deprecated class ExitBasicBlock extends BasicBlock {
class ExitBasicBlock extends BasicBlock {
ExitBasicBlock() { exitBB(this) }
}
/** Holds if `bb` is an exit basic block. */
deprecated private predicate exitBB(BasicBlock bb) { not exists(bb.getLastNode().getASuccessor()) }
private predicate exitBB(BasicBlock bb) { not exists(bb.getLastNode().getASuccessor()) }
/**
* A basic block with more than one predecessor.
*/
deprecated class JoinBlock extends BasicBlock {
class JoinBlock extends BasicBlock {
JoinBlock() { this.getFirstNode().isJoin() }
}
/** A basic block that terminates in a condition, splitting the subsequent control flow. */
deprecated class ConditionBlock extends BasicBlock {
class ConditionBlock extends BasicBlock {
ConditionBlock() {
exists(BasicBlock succ |
succ = this.getATrueSuccessor()

View File

@@ -8,26 +8,22 @@ cached
private module Cached {
/** Holds if method `m` always returns null. */
cached
deprecated predicate alwaysNullMethod(Method m) {
forex(Expr e | m.canReturn(e) | alwaysNullExpr(e))
}
predicate alwaysNullMethod(Method m) { forex(Expr e | m.canReturn(e) | alwaysNullExpr(e)) }
/** Holds if method `m` always returns non-null. */
cached
deprecated predicate alwaysNotNullMethod(Method m) {
forex(Expr e | m.canReturn(e) | alwaysNotNullExpr(e))
}
predicate alwaysNotNullMethod(Method m) { forex(Expr e | m.canReturn(e) | alwaysNotNullExpr(e)) }
/** Holds if method `m` always throws an exception. */
cached
deprecated predicate alwaysThrowsMethod(Method m) {
predicate alwaysThrowsMethod(Method m) {
m.hasBody() and
not exists(m.getImplementation().getAnInstruction().(Return))
}
/** Holds if method `m` always throws an exception of type `t`. */
cached
deprecated predicate alwaysThrowsException(Method m, Type t) {
predicate alwaysThrowsException(Method m, Type t) {
alwaysThrowsMethod(m) and
forex(Throw ex | ex = m.getImplementation().getAnInstruction() | t = ex.getExceptionType())
}
@@ -36,12 +32,12 @@ private module Cached {
import Cached
pragma[noinline]
deprecated private predicate alwaysNullVariableUpdate(VariableUpdate vu) {
private predicate alwaysNullVariableUpdate(VariableUpdate vu) {
forex(Expr src | src = vu.getSource() | alwaysNullExpr(src))
}
/** Holds if expression `expr` always evaluates to `null`. */
deprecated private predicate alwaysNullExpr(Expr expr) {
private predicate alwaysNullExpr(Expr expr) {
expr instanceof NullLiteral
or
alwaysNullMethod(expr.(StaticCall).getTarget())
@@ -54,12 +50,12 @@ deprecated private predicate alwaysNullExpr(Expr expr) {
}
pragma[noinline]
deprecated private predicate alwaysNotNullVariableUpdate(VariableUpdate vu) {
private predicate alwaysNotNullVariableUpdate(VariableUpdate vu) {
forex(Expr src | src = vu.getSource() | alwaysNotNullExpr(src))
}
/** Holds if expression `expr` always evaluates to non-null. */
deprecated private predicate alwaysNotNullExpr(Expr expr) {
private predicate alwaysNotNullExpr(Expr expr) {
expr instanceof Opcodes::NewObj
or
expr instanceof Literal and not expr instanceof NullLiteral

View File

@@ -8,15 +8,15 @@ private import semmle.code.csharp.commons.QualifiedName
private newtype ConsistencyCheck =
MissingEntityCheck() or
deprecated TypeCheck(Type t) or
deprecated CfgCheck(ControlFlowNode n) or
deprecated DeclarationCheck(Declaration d) or
TypeCheck(Type t) or
CfgCheck(ControlFlowNode n) or
DeclarationCheck(Declaration d) or
MissingCSharpCheck(CS::Declaration d)
/**
* A consistency violation in the database or data model.
*/
abstract deprecated class ConsistencyViolation extends ConsistencyCheck {
abstract class ConsistencyViolation extends ConsistencyCheck {
abstract string toString();
abstract string getMessage();
@@ -25,14 +25,14 @@ abstract deprecated class ConsistencyViolation extends ConsistencyCheck {
/**
* A check that is deliberately disabled.
*/
abstract deprecated class DisabledCheck extends ConsistencyViolation {
abstract class DisabledCheck extends ConsistencyViolation {
DisabledCheck() { none() }
}
/**
* A consistency violation on a control flow node.
*/
abstract deprecated class CfgViolation extends ConsistencyViolation, CfgCheck {
abstract class CfgViolation extends ConsistencyViolation, CfgCheck {
ControlFlowNode node;
CfgViolation() { this = CfgCheck(node) }
@@ -43,7 +43,7 @@ abstract deprecated class CfgViolation extends ConsistencyViolation, CfgCheck {
/**
* A consistency violation in a specific instruction.
*/
abstract deprecated class InstructionViolation extends CfgViolation, CfgCheck {
abstract class InstructionViolation extends CfgViolation, CfgCheck {
Instruction instruction;
InstructionViolation() { this = CfgCheck(instruction) }
@@ -70,7 +70,7 @@ abstract deprecated class InstructionViolation extends CfgViolation, CfgCheck {
/**
* A literal that does not have exactly one `getValue()`.
*/
deprecated class MissingValue extends InstructionViolation {
class MissingValue extends InstructionViolation {
MissingValue() { exists(Literal l | l = instruction | count(l.getValue()) != 1) }
override string getMessage() { result = "Literal has invalid getValue()" }
@@ -79,7 +79,7 @@ deprecated class MissingValue extends InstructionViolation {
/**
* A call that does not have exactly one `getTarget()`.
*/
deprecated class MissingCallTarget extends InstructionViolation {
class MissingCallTarget extends InstructionViolation {
MissingCallTarget() {
exists(Call c | c = instruction |
count(c.getTarget()) != 1 and not c instanceof Opcodes::Calli
@@ -94,7 +94,7 @@ deprecated class MissingCallTarget extends InstructionViolation {
/**
* An instruction that has not been assigned a specific QL class.
*/
deprecated class MissingOpCode extends InstructionViolation {
class MissingOpCode extends InstructionViolation {
MissingOpCode() { not exists(instruction.getOpcodeName()) }
override string getMessage() {
@@ -114,7 +114,7 @@ deprecated class MissingOpCode extends InstructionViolation {
* It could also mean that the target of a call has failed and has not determined the
* correct number of arguments.
*/
deprecated class MissingOperand extends InstructionViolation {
class MissingOperand extends InstructionViolation {
MissingOperand() {
exists(int op | op in [0 .. instruction.getPopCount() - 1] |
not exists(instruction.getOperand(op)) and not instruction instanceof DeadInstruction
@@ -136,7 +136,7 @@ deprecated class MissingOperand extends InstructionViolation {
* These should not exist, however it turns out that the Mono compiler sometimes
* emits them.
*/
deprecated class DeadInstruction extends Instruction {
class DeadInstruction extends Instruction {
DeadInstruction() { not exists(EntryPoint e | e.getASuccessor+() = this) }
}
@@ -146,20 +146,20 @@ deprecated class DeadInstruction extends Instruction {
* If this fails, it means that the calculation of the call graph is incorrect.
* Disabled, because Mono compiler sometimes emits dead instructions.
*/
deprecated class DeadInstructionViolation extends InstructionViolation, DisabledCheck {
class DeadInstructionViolation extends InstructionViolation, DisabledCheck {
DeadInstructionViolation() { instruction instanceof DeadInstruction }
override string getMessage() { result = "This instruction is not reachable" }
}
deprecated class YesNoBranch extends ConditionalBranch {
class YesNoBranch extends ConditionalBranch {
YesNoBranch() { not this instanceof Opcodes::Switch }
}
/**
* A branch instruction that does not have exactly 2 successors.
*/
deprecated class InvalidBranchSuccessors extends InstructionViolation {
class InvalidBranchSuccessors extends InstructionViolation {
InvalidBranchSuccessors() {
// Mono compiler sometimes generates branches to the next instruction, which is just wrong.
// However it is valid CIL.
@@ -174,7 +174,7 @@ deprecated class InvalidBranchSuccessors extends InstructionViolation {
/**
* An instruction that has a true/false successor but is not a branch.
*/
deprecated class OnlyYesNoBranchHasTrueFalseSuccessors extends InstructionViolation {
class OnlyYesNoBranchHasTrueFalseSuccessors extends InstructionViolation {
OnlyYesNoBranchHasTrueFalseSuccessors() {
(exists(instruction.getTrueSuccessor()) or exists(instruction.getFalseSuccessor())) and
not instruction instanceof YesNoBranch
@@ -186,7 +186,7 @@ deprecated class OnlyYesNoBranchHasTrueFalseSuccessors extends InstructionViolat
/**
* An unconditional branch instruction that has more than one successor.
*/
deprecated class UnconditionalBranchSuccessors extends InstructionViolation {
class UnconditionalBranchSuccessors extends InstructionViolation {
UnconditionalBranchSuccessors() {
exists(UnconditionalBranch i | i = instruction | count(i.getASuccessor()) != 1)
}
@@ -199,7 +199,7 @@ deprecated class UnconditionalBranchSuccessors extends InstructionViolation {
/**
* A branch instruction that does not have a true successor.
*/
deprecated class NoTrueSuccessor extends InstructionViolation {
class NoTrueSuccessor extends InstructionViolation {
NoTrueSuccessor() { exists(YesNoBranch i | i = instruction | not exists(i.getTrueSuccessor())) }
override string getMessage() { result = "Missing a true successor" }
@@ -208,7 +208,7 @@ deprecated class NoTrueSuccessor extends InstructionViolation {
/**
* A branch instruction that does not have a false successor.
*/
deprecated class NoFalseSuccessor extends InstructionViolation {
class NoFalseSuccessor extends InstructionViolation {
NoFalseSuccessor() { exists(YesNoBranch i | i = instruction | not exists(i.getFalseSuccessor())) }
override string getMessage() { result = "Missing a false successor" }
@@ -217,7 +217,7 @@ deprecated class NoFalseSuccessor extends InstructionViolation {
/**
* An instruction whose true successor is not a successor.
*/
deprecated class TrueSuccessorIsSuccessor extends InstructionViolation {
class TrueSuccessorIsSuccessor extends InstructionViolation {
TrueSuccessorIsSuccessor() {
exists(instruction.getTrueSuccessor()) and
not instruction.getTrueSuccessor() = instruction.getASuccessor()
@@ -229,7 +229,7 @@ deprecated class TrueSuccessorIsSuccessor extends InstructionViolation {
/**
* An instruction whose false successor is not a successor.
*/
deprecated class FalseSuccessorIsSuccessor extends InstructionViolation {
class FalseSuccessorIsSuccessor extends InstructionViolation {
FalseSuccessorIsSuccessor() {
exists(instruction.getFalseSuccessor()) and
not instruction.getFalseSuccessor() = instruction.getASuccessor()
@@ -241,7 +241,7 @@ deprecated class FalseSuccessorIsSuccessor extends InstructionViolation {
/**
* An access that does not have exactly one target.
*/
deprecated class AccessMissingTarget extends InstructionViolation {
class AccessMissingTarget extends InstructionViolation {
AccessMissingTarget() { exists(Access i | i = instruction | count(i.getTarget()) != 1) }
override string getMessage() { result = "Access has invalid getTarget()" }
@@ -250,7 +250,7 @@ deprecated class AccessMissingTarget extends InstructionViolation {
/**
* A catch handler that doesn't have a caught exception type.
*/
deprecated class CatchHandlerMissingType extends CfgViolation {
class CatchHandlerMissingType extends CfgViolation {
CatchHandlerMissingType() { exists(CatchHandler h | h = node | not exists(h.getCaughtType())) }
override string getMessage() { result = "Catch handler missing caught type" }
@@ -259,7 +259,7 @@ deprecated class CatchHandlerMissingType extends CfgViolation {
/**
* A CFG node that does not have a stack size.
*/
deprecated class MissingStackSize extends CfgViolation {
class MissingStackSize extends CfgViolation {
MissingStackSize() {
(
not exists(node.getStackSizeAfter()) or
@@ -275,7 +275,7 @@ deprecated class MissingStackSize extends CfgViolation {
* A CFG node that does not have exactly one stack size.
* Disabled because inconsistent stack sizes have been observed.
*/
deprecated class InvalidStackSize extends CfgViolation, DisabledCheck {
class InvalidStackSize extends CfgViolation, DisabledCheck {
InvalidStackSize() {
(
count(node.getStackSizeAfter()) != 1 or
@@ -294,7 +294,7 @@ deprecated class InvalidStackSize extends CfgViolation, DisabledCheck {
/**
* A CFG node that does not have exactly 1 `getPopCount()`.
*/
deprecated class InconsistentPopCount extends CfgViolation {
class InconsistentPopCount extends CfgViolation {
InconsistentPopCount() { count(node.getPopCount()) != 1 }
override string getMessage() {
@@ -305,7 +305,7 @@ deprecated class InconsistentPopCount extends CfgViolation {
/**
* A CFG node that does not have exactly one `getPushCount()`.
*/
deprecated class InconsistentPushCount extends CfgViolation {
class InconsistentPushCount extends CfgViolation {
InconsistentPushCount() { count(node.getPushCount()) != 1 }
override string getMessage() {
@@ -316,7 +316,7 @@ deprecated class InconsistentPushCount extends CfgViolation {
/**
* A return instruction that does not have a stack size of 0 after it.
*/
deprecated class InvalidReturn extends InstructionViolation {
class InvalidReturn extends InstructionViolation {
InvalidReturn() { instruction instanceof Return and instruction.getStackSizeAfter() != 0 }
override string getMessage() { result = "Return has invalid stack size" }
@@ -325,7 +325,7 @@ deprecated class InvalidReturn extends InstructionViolation {
/**
* A throw instruction that does not have a stack size of 0 after it.
*/
deprecated class InvalidThrow extends InstructionViolation, DisabledCheck {
class InvalidThrow extends InstructionViolation, DisabledCheck {
InvalidThrow() { instruction instanceof Throw and instruction.getStackSizeAfter() != 0 }
override string getMessage() {
@@ -336,7 +336,7 @@ deprecated class InvalidThrow extends InstructionViolation, DisabledCheck {
/**
* A field access where the field is "static" but the instruction is "instance".
*/
deprecated class StaticFieldTarget extends InstructionViolation {
class StaticFieldTarget extends InstructionViolation {
StaticFieldTarget() {
exists(FieldAccess i | i = instruction |
(i instanceof Opcodes::Stfld or i instanceof Opcodes::Stfld) and
@@ -350,7 +350,7 @@ deprecated class StaticFieldTarget extends InstructionViolation {
/**
* A branch without a target.
*/
deprecated class BranchWithoutTarget extends InstructionViolation {
class BranchWithoutTarget extends InstructionViolation {
BranchWithoutTarget() {
instruction = any(Branch b | not exists(b.getTarget()) and not b instanceof Opcodes::Switch)
}
@@ -361,7 +361,7 @@ deprecated class BranchWithoutTarget extends InstructionViolation {
/**
* A consistency violation in a type.
*/
deprecated class TypeViolation extends ConsistencyViolation, TypeCheck {
class TypeViolation extends ConsistencyViolation, TypeCheck {
/** Gets the type containing the violation. */
Type getType() { this = TypeCheck(result) }
@@ -373,7 +373,7 @@ deprecated class TypeViolation extends ConsistencyViolation, TypeCheck {
/**
* A type that has both type arguments and type parameters.
*/
deprecated class TypeIsBothConstructedAndUnbound extends TypeViolation {
class TypeIsBothConstructedAndUnbound extends TypeViolation {
TypeIsBothConstructedAndUnbound() {
this.getType() instanceof ConstructedGeneric and this.getType() instanceof UnboundGeneric
}
@@ -385,7 +385,7 @@ deprecated class TypeIsBothConstructedAndUnbound extends TypeViolation {
* The location of a constructed generic type should be the same
* as the location of its unbound generic type.
*/
deprecated class InconsistentTypeLocation extends TypeViolation {
class InconsistentTypeLocation extends TypeViolation {
InconsistentTypeLocation() {
this.getType().getLocation() != this.getType().getUnboundDeclaration().getLocation()
}
@@ -396,7 +396,7 @@ deprecated class InconsistentTypeLocation extends TypeViolation {
/**
* A constructed type that does not match its unbound generic type.
*/
deprecated class TypeParameterMismatch extends TypeViolation {
class TypeParameterMismatch extends TypeViolation {
TypeParameterMismatch() {
this.getType().(ConstructedGeneric).getNumberOfTypeArguments() !=
this.getType().getUnboundType().(UnboundGeneric).getNumberOfTypeParameters()
@@ -415,7 +415,7 @@ deprecated class TypeParameterMismatch extends TypeViolation {
/**
* A consistency violation in a method.
*/
deprecated class MethodViolation extends ConsistencyViolation, DeclarationCheck {
class MethodViolation extends ConsistencyViolation, DeclarationCheck {
/** Gets the method containing the violation. */
Method getMethod() { this = DeclarationCheck(result) }
@@ -428,7 +428,7 @@ deprecated class MethodViolation extends ConsistencyViolation, DeclarationCheck
* The location of a constructed method should be equal to the
* location of its unbound generic.
*/
deprecated class InconsistentMethodLocation extends MethodViolation {
class InconsistentMethodLocation extends MethodViolation {
InconsistentMethodLocation() {
this.getMethod().getLocation() != this.getMethod().getUnboundDeclaration().getLocation()
}
@@ -439,7 +439,7 @@ deprecated class InconsistentMethodLocation extends MethodViolation {
/**
* A constructed method that does not match its unbound method.
*/
deprecated class ConstructedMethodTypeParams extends MethodViolation {
class ConstructedMethodTypeParams extends MethodViolation {
ConstructedMethodTypeParams() {
this.getMethod().(ConstructedGeneric).getNumberOfTypeArguments() !=
this.getMethod().getUnboundDeclaration().(UnboundGeneric).getNumberOfTypeParameters()
@@ -456,14 +456,14 @@ deprecated class ConstructedMethodTypeParams extends MethodViolation {
/**
* A violation marking an entity that should be present but is not.
*/
abstract deprecated class MissingEntityViolation extends ConsistencyViolation, MissingEntityCheck {
abstract class MissingEntityViolation extends ConsistencyViolation, MissingEntityCheck {
override string toString() { result = "Missing entity" }
}
/**
* The type `object` is missing from the database.
*/
deprecated class MissingObjectViolation extends MissingEntityViolation {
class MissingObjectViolation extends MissingEntityViolation {
MissingObjectViolation() {
exists(this) and
not exists(ObjectType o)
@@ -475,7 +475,7 @@ deprecated class MissingObjectViolation extends MissingEntityViolation {
/**
* An override that is invalid because the overridden method is not in a base class.
*/
deprecated class InvalidOverride extends MethodViolation {
class InvalidOverride extends MethodViolation {
private Method base;
InvalidOverride() {
@@ -497,7 +497,7 @@ deprecated class InvalidOverride extends MethodViolation {
/**
* A pointer type that does not have a pointee type.
*/
deprecated class InvalidPointerType extends TypeViolation {
class InvalidPointerType extends TypeViolation {
InvalidPointerType() {
exists(PointerType p | p = this.getType() | count(p.getReferentType()) != 1)
}
@@ -508,7 +508,7 @@ deprecated class InvalidPointerType extends TypeViolation {
/**
* An array with an invalid `getElementType`.
*/
deprecated class ArrayTypeMissingElement extends TypeViolation {
class ArrayTypeMissingElement extends TypeViolation {
ArrayTypeMissingElement() {
exists(ArrayType t | t = this.getType() | count(t.getElementType()) != 1)
}
@@ -519,7 +519,7 @@ deprecated class ArrayTypeMissingElement extends TypeViolation {
/**
* An array with an invalid `getRank`.
*/
deprecated class ArrayTypeInvalidRank extends TypeViolation {
class ArrayTypeInvalidRank extends TypeViolation {
ArrayTypeInvalidRank() { exists(ArrayType t | t = this.getType() | not t.getRank() > 0) }
override string getMessage() { result = "Invalid ArrayType.getRank()" }
@@ -529,7 +529,7 @@ deprecated class ArrayTypeInvalidRank extends TypeViolation {
* A type should have at most one kind, except for missing referenced types
* where the interface/class is unknown.
*/
deprecated class KindViolation extends TypeViolation {
class KindViolation extends TypeViolation {
KindViolation() {
count(typeKind(this.getType())) != 1 and
exists(this.getType().getLocation())
@@ -544,7 +544,7 @@ deprecated class KindViolation extends TypeViolation {
* The type of a kind must be consistent between a constructed generic and its
* unbound generic.
*/
deprecated class InconsistentKind extends TypeViolation {
class InconsistentKind extends TypeViolation {
InconsistentKind() {
typeKind(this.getType()) != typeKind(this.getType().getUnboundDeclaration())
}
@@ -552,7 +552,7 @@ deprecated class InconsistentKind extends TypeViolation {
override string getMessage() { result = "Inconsistent type kind of source declaration" }
}
deprecated private string typeKind(Type t) {
private string typeKind(Type t) {
t instanceof Interface and result = "interface"
or
t instanceof Class and result = "class"
@@ -567,7 +567,7 @@ deprecated private string typeKind(Type t) {
/**
* A violation in a `Member`.
*/
abstract deprecated class DeclarationViolation extends ConsistencyViolation, DeclarationCheck {
abstract class DeclarationViolation extends ConsistencyViolation, DeclarationCheck {
abstract override string getMessage();
/** Gets the member containing the potential violation. */
@@ -579,7 +579,7 @@ abstract deprecated class DeclarationViolation extends ConsistencyViolation, Dec
/**
* Properties that have no accessors.
*/
deprecated class PropertyWithNoAccessors extends DeclarationViolation {
class PropertyWithNoAccessors extends DeclarationViolation {
PropertyWithNoAccessors() {
exists(Property p | p = this.getDeclaration() | not exists(p.getAnAccessor()))
}
@@ -590,7 +590,7 @@ deprecated class PropertyWithNoAccessors extends DeclarationViolation {
/**
* An expression that have an unexpected push count.
*/
deprecated class ExprPushCount extends InstructionViolation {
class ExprPushCount extends InstructionViolation {
ExprPushCount() {
instruction instanceof Expr and
not instruction instanceof Opcodes::Dup and
@@ -608,7 +608,7 @@ deprecated class ExprPushCount extends InstructionViolation {
* An expression that does not have exactly one type.
* Note that calls with no return have type `System.Void`.
*/
deprecated class ExprMissingType extends InstructionViolation {
class ExprMissingType extends InstructionViolation {
ExprMissingType() {
// Don't have types for the following op codes:
not instruction instanceof Opcodes::Ldftn and
@@ -632,7 +632,7 @@ deprecated class ExprMissingType extends InstructionViolation {
/**
* An instruction that has a push count of 0, yet is still used as an operand
*/
deprecated class InvalidExpressionViolation extends InstructionViolation {
class InvalidExpressionViolation extends InstructionViolation {
InvalidExpressionViolation() {
instruction.getPushCount() = 0 and
exists(Instruction expr | instruction = expr.getAnOperand())
@@ -647,7 +647,7 @@ deprecated class InvalidExpressionViolation extends InstructionViolation {
* A type that has multiple entities with the same qualified name in `System`.
* .NET Core does sometimes duplicate types, so this check is disabled.
*/
deprecated class TypeMultiplyDefined extends TypeViolation, DisabledCheck {
class TypeMultiplyDefined extends TypeViolation, DisabledCheck {
TypeMultiplyDefined() {
this.getType().getParent().getName() = "System" and
not this.getType() instanceof ConstructedGeneric and
@@ -672,7 +672,7 @@ deprecated class TypeMultiplyDefined extends TypeViolation, DisabledCheck {
/**
* A C# declaration which is expected to have a corresponding CIL declaration, but for some reason does not.
*/
deprecated class MissingCilDeclaration extends ConsistencyViolation, MissingCSharpCheck {
class MissingCilDeclaration extends ConsistencyViolation, MissingCSharpCheck {
MissingCilDeclaration() {
exists(CS::Declaration decl | this = MissingCSharpCheck(decl) |
expectedCilDeclaration(decl) and
@@ -694,7 +694,7 @@ deprecated class MissingCilDeclaration extends ConsistencyViolation, MissingCSha
/**
* Holds if the C# declaration is expected to have a CIl declaration.
*/
deprecated private predicate expectedCilDeclaration(CS::Declaration decl) {
private predicate expectedCilDeclaration(CS::Declaration decl) {
decl = decl.getUnboundDeclaration() and
not decl instanceof CS::ArrayType and
decl.getALocation() instanceof CS::Assembly and
@@ -730,7 +730,7 @@ deprecated private predicate expectedCilDeclaration(CS::Declaration decl) {
}
/** A member with an invalid name. */
deprecated class MemberWithInvalidName extends DeclarationViolation {
class MemberWithInvalidName extends DeclarationViolation {
MemberWithInvalidName() {
exists(string name | name = this.getDeclaration().(Member).getName() |
exists(name.indexOf(".")) and
@@ -744,7 +744,7 @@ deprecated class MemberWithInvalidName extends DeclarationViolation {
}
}
deprecated class ConstructedSourceDeclarationMethod extends MethodViolation {
class ConstructedSourceDeclarationMethod extends MethodViolation {
Method method;
ConstructedSourceDeclarationMethod() {
@@ -762,7 +762,7 @@ deprecated class ConstructedSourceDeclarationMethod extends MethodViolation {
}
/** A declaration with multiple labels. */
deprecated class DeclarationWithMultipleLabels extends DeclarationViolation {
class DeclarationWithMultipleLabels extends DeclarationViolation {
DeclarationWithMultipleLabels() {
exists(Declaration d | this = DeclarationCheck(d) | strictcount(d.getLabel()) > 1)
}
@@ -773,7 +773,7 @@ deprecated class DeclarationWithMultipleLabels extends DeclarationViolation {
}
/** A declaration without a label. */
deprecated class DeclarationWithoutLabel extends DeclarationViolation {
class DeclarationWithoutLabel extends DeclarationViolation {
DeclarationWithoutLabel() {
exists(Declaration d | this = DeclarationCheck(d) |
d.isUnboundDeclaration() and

View File

@@ -5,7 +5,7 @@
private import CIL
/** A node in the control flow graph. */
deprecated class ControlFlowNode extends @cil_controlflow_node {
class ControlFlowNode extends @cil_controlflow_node {
/** Gets a textual representation of this control flow node. */
string toString() { none() }
@@ -149,31 +149,31 @@ deprecated class ControlFlowNode extends @cil_controlflow_node {
*
* Handlers are control flow nodes because they push the handled exception onto the stack.
*/
deprecated class EntryPoint extends ControlFlowNode, @cil_entry_point {
class EntryPoint extends ControlFlowNode, @cil_entry_point {
override int getStackSizeBefore() { result = 0 }
}
deprecated private newtype TFlowType =
private newtype TFlowType =
TNormalFlow() or
TTrueFlow() or
TFalseFlow()
/** A type of control flow. Either normal flow (`NormalFlow`), true flow (`TrueFlow`) or false flow (`FalseFlow`). */
abstract deprecated class FlowType extends TFlowType {
abstract class FlowType extends TFlowType {
abstract string toString();
}
/** Normal control flow. */
deprecated class NormalFlow extends FlowType, TNormalFlow {
class NormalFlow extends FlowType, TNormalFlow {
override string toString() { result = "" }
}
/** True control flow. */
deprecated class TrueFlow extends FlowType, TTrueFlow {
class TrueFlow extends FlowType, TTrueFlow {
override string toString() { result = "true" }
}
/** False control flow. */
deprecated class FalseFlow extends FlowType, TFalseFlow {
class FalseFlow extends FlowType, TFalseFlow {
override string toString() { result = "false" }
}

View File

@@ -12,7 +12,7 @@ private import dotnet
* - the type of parameters.
* A `CustomModifierReceiver` is therefore either a `Field`, `Property`, `Method`, or `Parameter`.
*/
deprecated class CustomModifierReceiver extends Declaration, @cil_custom_modifier_receiver {
class CustomModifierReceiver extends Declaration, @cil_custom_modifier_receiver {
/** Holds if this targeted type has `modifier` applied as `modreq`. */
predicate hasRequiredCustomModifier(Type modifier) { cil_custom_modifiers(this, modifier, 1) }

View File

@@ -9,7 +9,7 @@ private import CIL
*
* Either an instruction (`Instruction`), a method return (`Method`), or a variable (`Variable`).
*/
deprecated class DataFlowNode extends @cil_dataflow_node {
class DataFlowNode extends @cil_dataflow_node {
/** Gets a textual representation of this data flow node. */
abstract string toString();
@@ -24,7 +24,7 @@ deprecated class DataFlowNode extends @cil_dataflow_node {
}
/** A node that updates a variable. */
abstract deprecated class VariableUpdate extends DataFlowNode {
abstract class VariableUpdate extends DataFlowNode {
/** Gets the value assigned, if any. */
abstract DataFlowNode getSource();
@@ -35,7 +35,7 @@ abstract deprecated class VariableUpdate extends DataFlowNode {
abstract predicate updatesAt(BasicBlock bb, int i);
}
deprecated private class MethodParameterDef extends VariableUpdate, MethodParameter {
private class MethodParameterDef extends VariableUpdate, MethodParameter {
override MethodParameter getSource() { result = this }
override MethodParameter getVariable() { result = this }
@@ -46,7 +46,7 @@ deprecated private class MethodParameterDef extends VariableUpdate, MethodParame
}
}
deprecated private class VariableWrite extends VariableUpdate, WriteAccess {
private class VariableWrite extends VariableUpdate, WriteAccess {
override Expr getSource() { result = this.getExpr() }
override Variable getVariable() { result = this.getTarget() }
@@ -54,7 +54,7 @@ deprecated private class VariableWrite extends VariableUpdate, WriteAccess {
override predicate updatesAt(BasicBlock bb, int i) { this = bb.getNode(i) }
}
deprecated private class MethodOutOrRefTarget extends VariableUpdate, Call {
private class MethodOutOrRefTarget extends VariableUpdate, Call {
int parameterIndex;
MethodOutOrRefTarget() { this.getTarget().getRawParameter(parameterIndex).hasOutFlag() }

View File

@@ -10,7 +10,7 @@ private import semmle.code.csharp.commons.QualifiedName
/**
* A declaration. Either a member (`Member`) or a variable (`Variable`).
*/
deprecated class Declaration extends DotNet::Declaration, Element, @cil_declaration {
class Declaration extends DotNet::Declaration, Element, @cil_declaration {
/** Gets an attribute (for example `[Obsolete]`) of this declaration, if any. */
Attribute getAnAttribute() { result.getDeclaration() = this }
@@ -42,18 +42,14 @@ deprecated class Declaration extends DotNet::Declaration, Element, @cil_declarat
}
}
deprecated private CS::Declaration toCSharpNonTypeParameter(Declaration d) {
result.(DotNet::Declaration).matchesHandle(d)
}
private CS::Declaration toCSharpNonTypeParameter(Declaration d) { result.matchesHandle(d) }
deprecated private CS::TypeParameter toCSharpTypeParameter(TypeParameter tp) {
private CS::TypeParameter toCSharpTypeParameter(TypeParameter tp) {
toCSharpTypeParameterJoin(tp, result.getIndex(), result.getGeneric())
}
pragma[nomagic]
deprecated private predicate toCSharpTypeParameterJoin(
TypeParameter tp, int i, CS::UnboundGeneric ug
) {
private predicate toCSharpTypeParameterJoin(TypeParameter tp, int i, CS::UnboundGeneric ug) {
exists(TypeContainer tc |
tp.getIndex() = i and
tc = tp.getGeneric() and
@@ -64,7 +60,7 @@ deprecated private predicate toCSharpTypeParameterJoin(
/**
* A member of a type. Either a type (`Type`), a method (`Method`), a property (`Property`), or an event (`Event`).
*/
deprecated class Member extends DotNet::Member, Declaration, @cil_member {
class Member extends DotNet::Member, Declaration, @cil_member {
override predicate isPublic() { cil_public(this) }
override predicate isProtected() { cil_protected(this) }
@@ -86,7 +82,7 @@ deprecated class Member extends DotNet::Member, Declaration, @cil_member {
}
/** A property. */
deprecated class Property extends DotNet::Property, Member, CustomModifierReceiver, @cil_property {
class Property extends DotNet::Property, Member, CustomModifierReceiver, @cil_property {
override string getName() { cil_property(this, _, result, _) }
/** Gets the type of this property. */
@@ -113,7 +109,7 @@ deprecated class Property extends DotNet::Property, Member, CustomModifierReceiv
}
/** A property that is trivial (wraps a field). */
deprecated class TrivialProperty extends Property {
class TrivialProperty extends Property {
TrivialProperty() {
this.getGetter().(TrivialGetter).getField() = this.getSetter().(TrivialSetter).getField()
}
@@ -123,7 +119,7 @@ deprecated class TrivialProperty extends Property {
}
/** An event. */
deprecated class Event extends DotNet::Event, Member, @cil_event {
class Event extends DotNet::Event, Member, @cil_event {
override string getName() { cil_event(this, _, result, _) }
/** Gets the type of this event. */

View File

@@ -4,12 +4,12 @@ private import dotnet
import semmle.code.csharp.Location
/** An element. */
deprecated class Element extends DotNet::Element, @cil_element {
class Element extends DotNet::Element, @cil_element {
override Location getLocation() { result = bestLocation(this) }
}
cached
deprecated private Location bestLocation(Element e) {
private Location bestLocation(Element e) {
result = e.getALocation() and
(e.getALocation().getFile().isPdbSourceFile() implies result.getFile().isPdbSourceFile())
}

View File

@@ -7,7 +7,7 @@ private import dotnet
* A generic declaration. Either an unbound generic (`UnboundGeneric`) or a
* constructed generic (`ConstructedGeneric`).
*/
deprecated class Generic extends DotNet::Generic, Declaration, TypeContainer {
class Generic extends DotNet::Generic, Declaration, TypeContainer {
Generic() {
cil_type_parameter(this, _, _) or
cil_type_argument(this, _, _)
@@ -15,14 +15,14 @@ deprecated class Generic extends DotNet::Generic, Declaration, TypeContainer {
}
/** An unbound generic type or method. */
deprecated class UnboundGeneric extends Generic, DotNet::UnboundGeneric {
class UnboundGeneric extends Generic, DotNet::UnboundGeneric {
UnboundGeneric() { cil_type_parameter(this, _, _) }
final override TypeParameter getTypeParameter(int n) { cil_type_parameter(this, n, result) }
}
/** A constructed generic type or method. */
deprecated class ConstructedGeneric extends Generic, DotNet::ConstructedGeneric {
class ConstructedGeneric extends Generic, DotNet::ConstructedGeneric {
ConstructedGeneric() { cil_type_argument(this, _, _) }
final override Type getTypeArgument(int n) { cil_type_argument(this, n, result) }
@@ -30,18 +30,18 @@ deprecated class ConstructedGeneric extends Generic, DotNet::ConstructedGeneric
/** Gets the concatenation of the `getName()` of type arguments. */
language[monotonicAggregates]
deprecated private string getTypeArgumentsNames(ConstructedGeneric cg) {
private string getTypeArgumentsNames(ConstructedGeneric cg) {
result = strictconcat(Type t, int i | t = cg.getTypeArgument(i) | t.getName(), "," order by i)
}
/** An unbound generic type. */
deprecated class UnboundGenericType extends UnboundGeneric, Type { }
class UnboundGenericType extends UnboundGeneric, Type { }
/** An unbound generic method. */
deprecated class UnboundGenericMethod extends UnboundGeneric, Method { }
class UnboundGenericMethod extends UnboundGeneric, Method { }
/** A constructed generic type. */
deprecated class ConstructedType extends ConstructedGeneric, Type {
class ConstructedType extends ConstructedGeneric, Type {
final override UnboundGenericType getUnboundGeneric() { result = this.getUnboundType() }
override predicate isInterface() { this.getUnboundType().isInterface() }
@@ -54,6 +54,6 @@ deprecated class ConstructedType extends ConstructedGeneric, Type {
}
/** A constructed generic method. */
deprecated class ConstructedMethod extends ConstructedGeneric, Method {
class ConstructedMethod extends ConstructedGeneric, Method {
final override UnboundGenericMethod getUnboundGeneric() { result = this.getUnboundMethod() }
}

View File

@@ -19,7 +19,7 @@ private import CIL
* Either a finally handler (`FinallyHandler`), filter handler (`FilterHandler`),
* catch handler (`CatchHandler`), or a fault handler (`FaultHandler`).
*/
deprecated class Handler extends Element, EntryPoint, @cil_handler {
class Handler extends Element, EntryPoint, @cil_handler {
override MethodImplementation getImplementation() { cil_handler(this, result, _, _, _, _, _) }
/** Gets the 0-based index of this handler. Handlers are evaluated in this sequence. */
@@ -56,12 +56,12 @@ deprecated class Handler extends Element, EntryPoint, @cil_handler {
}
/** A handler corresponding to a `finally` block. */
deprecated class FinallyHandler extends Handler, @cil_finally_handler {
class FinallyHandler extends Handler, @cil_finally_handler {
override string toString() { result = "finally {...}" }
}
/** A handler corresponding to a `where()` clause. */
deprecated class FilterHandler extends Handler, @cil_filter_handler {
class FilterHandler extends Handler, @cil_filter_handler {
override string toString() { result = "where (...)" }
/** Gets the filter clause - the start of a sequence of instructions to evaluate the filter function. */
@@ -71,13 +71,13 @@ deprecated class FilterHandler extends Handler, @cil_filter_handler {
}
/** A handler corresponding to a `catch` clause. */
deprecated class CatchHandler extends Handler, @cil_catch_handler {
class CatchHandler extends Handler, @cil_catch_handler {
override string toString() { result = "catch(" + this.getCaughtType().getName() + ") {...}" }
override int getPushCount() { result = 1 }
}
/** A handler for memory faults. */
deprecated class FaultHandler extends Handler, @cil_fault_handler {
class FaultHandler extends Handler, @cil_fault_handler {
override string toString() { result = "fault {...}" }
}

View File

@@ -3,7 +3,7 @@
private import CIL
/** An instruction. */
deprecated class Instruction extends Element, ControlFlowNode, DataFlowNode, @cil_instruction {
class Instruction extends Element, ControlFlowNode, DataFlowNode, @cil_instruction {
override string toString() { result = this.getOpcodeName() }
/** Gets a more verbose textual representation of this instruction. */

View File

@@ -9,7 +9,7 @@ private import dotnet
/**
* An instruction that pushes a value onto the stack.
*/
deprecated class Expr extends DotNet::Expr, Instruction, @cil_expr {
class Expr extends DotNet::Expr, Instruction, @cil_expr {
override int getPushCount() { result = 1 }
override Type getType() { result = Instruction.super.getType() }
@@ -24,7 +24,7 @@ deprecated class Expr extends DotNet::Expr, Instruction, @cil_expr {
}
/** An instruction that changes control flow. */
deprecated class Branch extends Instruction, @cil_jump {
class Branch extends Instruction, @cil_jump {
/** Gets the instruction that is jumped to. */
Instruction getTarget() { cil_jump(this, result) }
@@ -32,7 +32,7 @@ deprecated class Branch extends Instruction, @cil_jump {
}
/** An instruction that unconditionally jumps to another instruction. */
deprecated class UnconditionalBranch extends Branch, @cil_unconditional_jump {
class UnconditionalBranch extends Branch, @cil_unconditional_jump {
override Instruction getASuccessorType(FlowType t) {
t instanceof NormalFlow and result = this.getTarget()
}
@@ -41,7 +41,7 @@ deprecated class UnconditionalBranch extends Branch, @cil_unconditional_jump {
}
/** An instruction that jumps to a target based on a condition. */
deprecated class ConditionalBranch extends Branch, @cil_conditional_jump {
class ConditionalBranch extends Branch, @cil_conditional_jump {
override Instruction getASuccessorType(FlowType t) {
t instanceof TrueFlow and result = this.getTarget()
or
@@ -52,12 +52,12 @@ deprecated class ConditionalBranch extends Branch, @cil_conditional_jump {
}
/** An expression with two operands. */
deprecated class BinaryExpr extends Expr, @cil_binary_expr {
class BinaryExpr extends Expr, @cil_binary_expr {
override int getPopCount() { result = 2 }
}
/** An expression with one operand. */
deprecated class UnaryExpr extends Expr, @cil_unary_expr {
class UnaryExpr extends Expr, @cil_unary_expr {
override int getPopCount() { result = 1 }
/** Gets the operand of this unary expression. */
@@ -65,12 +65,12 @@ deprecated class UnaryExpr extends Expr, @cil_unary_expr {
}
/** A binary expression that compares two values. */
deprecated class ComparisonOperation extends BinaryExpr, @cil_comparison_operation {
class ComparisonOperation extends BinaryExpr, @cil_comparison_operation {
override BoolType getType() { exists(result) }
}
/** A binary arithmetic expression. */
deprecated class BinaryArithmeticExpr extends BinaryExpr, @cil_binary_arithmetic_operation {
class BinaryArithmeticExpr extends BinaryExpr, @cil_binary_arithmetic_operation {
override Type getType() {
exists(Type t0, Type t1 |
t0 = this.getOperandType(0).getUnderlyingType() and
@@ -86,28 +86,28 @@ deprecated class BinaryArithmeticExpr extends BinaryExpr, @cil_binary_arithmetic
}
/** A binary bitwise expression. */
deprecated class BinaryBitwiseOperation extends BinaryExpr, @cil_binary_bitwise_operation {
class BinaryBitwiseOperation extends BinaryExpr, @cil_binary_bitwise_operation {
// This is wrong but efficient - should depend on the types of the operands.
override IntType getType() { exists(result) }
}
/** A unary bitwise expression. */
deprecated class UnaryBitwiseOperation extends UnaryExpr, @cil_unary_bitwise_operation {
class UnaryBitwiseOperation extends UnaryExpr, @cil_unary_bitwise_operation {
// This is wrong but efficient - should depend on the types of the operands.
override IntType getType() { exists(result) }
}
/** A unary expression that converts a value from one primitive type to another. */
deprecated class Conversion extends UnaryExpr, @cil_conversion_operation {
class Conversion extends UnaryExpr, @cil_conversion_operation {
/** Gets the expression being converted. */
Expr getExpr() { result = this.getOperand(0) }
}
/** A branch that leaves the scope of a `Handler`. */
deprecated class Leave extends UnconditionalBranch, @cil_leave_any { }
class Leave extends UnconditionalBranch, @cil_leave_any { }
/** An expression that pushes a literal value onto the stack. */
deprecated class Literal extends DotNet::Literal, Expr, @cil_literal {
class Literal extends DotNet::Literal, Expr, @cil_literal {
/** Gets the pushed value. */
override string getValue() { cil_value(this, result) }
@@ -115,37 +115,37 @@ deprecated class Literal extends DotNet::Literal, Expr, @cil_literal {
}
/** An integer literal. */
deprecated class IntLiteral extends Literal, @cil_ldc_i {
class IntLiteral extends Literal, @cil_ldc_i {
override string getExtra() { none() }
override IntType getType() { exists(result) }
}
/** An expression that pushes a `float`/`Single`. */
deprecated class FloatLiteral extends Literal, @cil_ldc_r { }
class FloatLiteral extends Literal, @cil_ldc_r { }
/** An expression that pushes a `null` value onto the stack. */
deprecated class NullLiteral extends Literal, @cil_ldnull { }
class NullLiteral extends Literal, @cil_ldnull { }
/** An expression that pushes a string onto the stack. */
deprecated class StringLiteral extends Literal, @cil_ldstr { }
class StringLiteral extends Literal, @cil_ldstr { }
/** A branch with one operand. */
deprecated class UnaryBranch extends ConditionalBranch, @cil_unary_jump {
class UnaryBranch extends ConditionalBranch, @cil_unary_jump {
override int getPopCount() { result = 1 }
override int getPushCount() { result = 0 }
}
/** A branch with two operands. */
deprecated class BinaryBranch extends ConditionalBranch, @cil_binary_jump {
class BinaryBranch extends ConditionalBranch, @cil_binary_jump {
override int getPopCount() { result = 2 }
override int getPushCount() { result = 0 }
}
/** A call. */
deprecated class Call extends Expr, DotNet::Call, @cil_call_any {
class Call extends Expr, DotNet::Call, @cil_call_any {
/** Gets the method that is called. */
override Method getTarget() { cil_access(this, result) }
@@ -198,24 +198,24 @@ deprecated class Call extends Expr, DotNet::Call, @cil_call_any {
}
/** A tail call. */
deprecated class TailCall extends Call {
class TailCall extends Call {
TailCall() { this.isTailCall() }
override predicate canFlowNext() { none() }
}
/** A call to a static target. */
deprecated class StaticCall extends Call {
class StaticCall extends Call {
StaticCall() { not this.isVirtual() }
}
/** A call to a virtual target. */
deprecated class VirtualCall extends Call {
class VirtualCall extends Call {
VirtualCall() { this.isVirtual() }
}
/** A read of an array element. */
deprecated class ReadArrayElement extends BinaryExpr, @cil_read_array {
class ReadArrayElement extends BinaryExpr, @cil_read_array {
/** Gets the array being read. */
Expr getArray() { result = this.getOperand(1) }
@@ -224,14 +224,14 @@ deprecated class ReadArrayElement extends BinaryExpr, @cil_read_array {
}
/** A write of an array element. */
deprecated class WriteArrayElement extends Instruction, @cil_write_array {
class WriteArrayElement extends Instruction, @cil_write_array {
override int getPushCount() { result = 0 }
override int getPopCount() { result = 3 }
}
/** A `return` statement. */
deprecated class Return extends Instruction, @cil_ret {
class Return extends Instruction, @cil_ret {
/** Gets the expression being returned, if any. */
Expr getExpr() { result = this.getOperand(0) }
@@ -239,7 +239,7 @@ deprecated class Return extends Instruction, @cil_ret {
}
/** A `throw` statement. */
deprecated class Throw extends Instruction, DotNet::Throw, @cil_throw_any {
class Throw extends Instruction, DotNet::Throw, @cil_throw_any {
override Expr getExpr() { result = this.getOperand(0) }
/** Gets the type of the exception being thrown. */
@@ -249,7 +249,7 @@ deprecated class Throw extends Instruction, DotNet::Throw, @cil_throw_any {
}
/** Stores a value at an address/location. */
deprecated class StoreIndirect extends Instruction, @cil_stind {
class StoreIndirect extends Instruction, @cil_stind {
override int getPopCount() { result = 2 }
/** Gets the location to store the value at. */
@@ -260,4 +260,4 @@ deprecated class StoreIndirect extends Instruction, @cil_stind {
}
/** Loads a value from an address/location. */
deprecated class LoadIndirect extends UnaryExpr, @cil_ldind { }
class LoadIndirect extends UnaryExpr, @cil_ldind { }

View File

@@ -8,7 +8,7 @@
private import CIL
private import semmle.code.dotnet.Variable as DotNet
deprecated module Opcodes {
module Opcodes {
/** An `ldc.i4.m1` instruction. */
class Ldc_i4_m1 extends IntLiteral, @cil_ldc_i4_m1 {
override string getOpcodeName() { result = "ldc.i4.m1" }

View File

@@ -12,7 +12,7 @@ private import dotnet
/**
* An implementation of a method in an assembly.
*/
deprecated class MethodImplementation extends EntryPoint, @cil_method_implementation {
class MethodImplementation extends EntryPoint, @cil_method_implementation {
/** Gets the method of this implementation. */
Method getMethod() { cil_method_implementation(this, result, _) }
@@ -66,7 +66,7 @@ deprecated class MethodImplementation extends EntryPoint, @cil_method_implementa
* A method, which corresponds to any callable in C#, including constructors,
* destructors, operators, accessors and so on.
*/
deprecated class Method extends DotNet::Callable, Element, Member, TypeContainer, DataFlowNode,
class Method extends DotNet::Callable, Element, Member, TypeContainer, DataFlowNode,
CustomModifierReceiver, Parameterizable, @cil_method
{
/**
@@ -191,27 +191,27 @@ deprecated class Method extends DotNet::Callable, Element, Member, TypeContainer
}
/** A destructor/finalizer. */
deprecated class Destructor extends Method, DotNet::Destructor {
class Destructor extends Method, DotNet::Destructor {
Destructor() { this.isFinalizer() }
}
/** A constructor. */
deprecated class Constructor extends Method, DotNet::Constructor {
class Constructor extends Method, DotNet::Constructor {
Constructor() { this.isConstructor() }
}
/** A static/class constructor. */
deprecated class StaticConstructor extends Constructor {
class StaticConstructor extends Constructor {
StaticConstructor() { this.isStaticConstructor() }
}
/** An instance constructor. */
deprecated class InstanceConstructor extends Constructor {
class InstanceConstructor extends Constructor {
InstanceConstructor() { this.isInstanceConstructor() }
}
/** A method that always returns the `this` parameter. */
deprecated class ChainingMethod extends Method {
class ChainingMethod extends Method {
ChainingMethod() {
forex(Return ret | ret = this.getImplementation().getAnInstruction() |
ret.getExpr() instanceof ThisAccess
@@ -220,13 +220,13 @@ deprecated class ChainingMethod extends Method {
}
/** An accessor. */
abstract deprecated class Accessor extends Method {
abstract class Accessor extends Method {
/** Gets the property declaring this accessor. */
abstract Property getProperty();
}
/** A getter. */
deprecated class Getter extends Accessor {
class Getter extends Accessor {
Getter() { cil_getter(_, this) }
override Property getProperty() { cil_getter(result, this) }
@@ -236,7 +236,7 @@ deprecated class Getter extends Accessor {
* A method that does nothing but retrieve a field.
* Note that this is not necessarily a property getter.
*/
deprecated class TrivialGetter extends Method {
class TrivialGetter extends Method {
TrivialGetter() {
exists(MethodImplementation impl | impl = this.getAnImplementation() |
impl.getInstruction(0) instanceof ThisAccess and
@@ -252,7 +252,7 @@ deprecated class TrivialGetter extends Method {
}
/** A setter. */
deprecated class Setter extends Accessor {
class Setter extends Accessor {
Setter() { cil_setter(_, this) }
override Property getProperty() { cil_setter(result, this) }
@@ -269,7 +269,7 @@ deprecated class Setter extends Accessor {
* A method that does nothing but set a field.
* This is not necessarily a property setter.
*/
deprecated class TrivialSetter extends Method {
class TrivialSetter extends Method {
TrivialSetter() {
exists(MethodImplementation impl | impl = this.getAnImplementation() |
impl.getInstruction(0) instanceof ThisAccess and
@@ -285,10 +285,10 @@ deprecated class TrivialSetter extends Method {
}
/** An alias for `Method` for compatibility with the C# data model. */
deprecated class Callable = Method;
class Callable = Method;
/** An operator. */
deprecated class Operator extends Method {
class Operator extends Method {
Operator() { this.isOperator() }
/** Gets the name of the implementing method (for compatibility with C# data model). */

View File

@@ -8,7 +8,7 @@ private import dotnet
/**
* A parameterizable entity, such as `FunctionPointerType` or `Method`.
*/
deprecated class Parameterizable extends DotNet::Parameterizable, Element, @cil_parameterizable {
class Parameterizable extends DotNet::Parameterizable, Element, @cil_parameterizable {
override Parameter getRawParameter(int n) { cil_parameter(result, this, n, _) }
override Parameter getParameter(int n) { cil_parameter(result, this, n, _) }

View File

@@ -7,7 +7,7 @@ private import CIL
/**
* Provides classes for working with static single assignment (SSA) form.
*/
deprecated module Ssa {
module Ssa {
private import internal.SsaImpl as SsaImpl
/** An SSA definition. */

View File

@@ -8,7 +8,7 @@ import CIL
* The average number of instructions per method,
* below which an assembly is probably a stub.
*/
deprecated private float stubInstructionThreshold() { result = 5.1 }
private float stubInstructionThreshold() { result = 5.1 }
cached
private module Cached {
@@ -18,7 +18,7 @@ private module Cached {
* Look at the average number of instructions per method.
*/
cached
deprecated predicate assemblyIsStubImpl(Assembly asm) {
predicate assemblyIsStubImpl(Assembly asm) {
exists(int totalInstructions, int totalImplementations |
totalInstructions = count(Instruction i | i.getImplementation().getLocation() = asm) and
totalImplementations =
@@ -28,7 +28,7 @@ private module Cached {
}
cached
deprecated predicate bestImplementation(MethodImplementation mi) {
predicate bestImplementation(MethodImplementation mi) {
exists(Assembly asm |
asm = mi.getLocation() and
(assemblyIsStubImpl(asm) implies asm.getFile().extractedQlTest()) and
@@ -45,13 +45,13 @@ private module Cached {
private import Cached
deprecated predicate assemblyIsStub = assemblyIsStubImpl/1;
predicate assemblyIsStub = assemblyIsStubImpl/1;
/**
* A method implementation that is the "best" one for a particular method,
* if there are several potential implementations to choose between, and
* excludes implementations that are probably from stub/reference assemblies.
*/
deprecated class BestImplementation extends MethodImplementation {
class BestImplementation extends MethodImplementation {
BestImplementation() { bestImplementation(this) }
}

View File

@@ -11,7 +11,7 @@ private import semmle.code.csharp.commons.QualifiedName
*
* Either a type (`Type`), a method(`Method`), or a namespace (`Namespace`).
*/
deprecated class TypeContainer extends DotNet::NamedElement, @cil_type_container {
class TypeContainer extends DotNet::NamedElement, @cil_type_container {
/** Gets the parent of this type container, if any. */
TypeContainer getParent() { none() }
@@ -19,7 +19,7 @@ deprecated class TypeContainer extends DotNet::NamedElement, @cil_type_container
}
/** A namespace. */
deprecated class Namespace extends DotNet::Namespace, TypeContainer, @namespace {
class Namespace extends DotNet::Namespace, TypeContainer, @namespace {
override string toString() { result = this.getFullName() }
override Namespace getParent() { result = this.getParentNamespace() }
@@ -32,7 +32,7 @@ deprecated class Namespace extends DotNet::Namespace, TypeContainer, @namespace
/**
* A type.
*/
deprecated class Type extends DotNet::Type, Declaration, TypeContainer, @cil_type {
class Type extends DotNet::Type, Declaration, TypeContainer, @cil_type {
override TypeContainer getParent() { cil_type(this, _, _, result, _) }
override string getName() { cil_type(this, result, _, _, _) }

View File

@@ -6,7 +6,7 @@ private import CIL
private import dotnet
/** A type parameter. */
deprecated class TypeParameter extends DotNet::TypeParameter, Type, @cil_typeparameter {
class TypeParameter extends DotNet::TypeParameter, Type, @cil_typeparameter {
override int getIndex() { cil_type_parameter(_, result, this) }
/** Gets the generic type/method declaring this type parameter. */
@@ -33,7 +33,7 @@ deprecated class TypeParameter extends DotNet::TypeParameter, Type, @cil_typepar
}
/** A value or reference type. */
deprecated class ValueOrRefType extends DotNet::ValueOrRefType, Type, @cil_valueorreftype {
class ValueOrRefType extends DotNet::ValueOrRefType, Type, @cil_valueorreftype {
override ValueOrRefType getDeclaringType() { result = this.getParent() }
override string getUndecoratedName() { cil_type(this, result, _, _, _) }
@@ -44,7 +44,7 @@ deprecated class ValueOrRefType extends DotNet::ValueOrRefType, Type, @cil_value
}
/** An `enum`. */
deprecated class Enum extends ValueOrRefType {
class Enum extends ValueOrRefType {
Enum() { this.isEnum() }
override IntegralType getUnderlyingType() {
@@ -56,17 +56,17 @@ deprecated class Enum extends ValueOrRefType {
}
/** A `class`. */
deprecated class Class extends ValueOrRefType {
class Class extends ValueOrRefType {
Class() { this.isClass() }
}
/** An `interface`. */
deprecated class Interface extends ValueOrRefType {
class Interface extends ValueOrRefType {
Interface() { this.isInterface() }
}
/** An array. */
deprecated class ArrayType extends DotNet::ArrayType, Type, @cil_array_type {
class ArrayType extends DotNet::ArrayType, Type, @cil_array_type {
override Type getElementType() { cil_array_type(this, result, _) }
/** Gets the rank of this array. */
@@ -80,7 +80,7 @@ deprecated class ArrayType extends DotNet::ArrayType, Type, @cil_array_type {
}
/** A pointer type. */
deprecated class PointerType extends DotNet::PointerType, PrimitiveType, @cil_pointer_type {
class PointerType extends DotNet::PointerType, PrimitiveType, @cil_pointer_type {
override Type getReferentType() { cil_pointer_type(this, result) }
override IntType getUnderlyingType() { any() }
@@ -95,31 +95,31 @@ deprecated class PointerType extends DotNet::PointerType, PrimitiveType, @cil_po
}
/** A primitive type, built into the runtime. */
abstract deprecated class PrimitiveType extends Type { }
abstract class PrimitiveType extends Type { }
/**
* A primitive numeric type.
* Either an integral type (`IntegralType`) or a floating point type (`FloatingPointType`).
*/
abstract deprecated class NumericType extends PrimitiveType, ValueOrRefType { }
abstract class NumericType extends PrimitiveType, ValueOrRefType { }
/** A floating point type. Either single precision (`FloatType`) or double precision (`DoubleType`). */
abstract deprecated class FloatingPointType extends NumericType { }
abstract class FloatingPointType extends NumericType { }
/**
* An integral numeric type. Either a signed integral type (`SignedIntegralType`)
* or an unsigned integral type (`UnsignedIntegralType`).
*/
abstract deprecated class IntegralType extends NumericType { }
abstract class IntegralType extends NumericType { }
/** A signed integral type. */
abstract deprecated class SignedIntegralType extends IntegralType { }
abstract class SignedIntegralType extends IntegralType { }
/** An unsigned integral type. */
abstract deprecated class UnsignedIntegralType extends IntegralType { }
abstract class UnsignedIntegralType extends IntegralType { }
/** The `void` type, `System.Void`. */
deprecated class VoidType extends PrimitiveType {
class VoidType extends PrimitiveType {
VoidType() { this.isSystemType("Void") }
override string toString() { result = "void" }
@@ -128,7 +128,7 @@ deprecated class VoidType extends PrimitiveType {
}
/** The type `System.Int32`. */
deprecated class IntType extends SignedIntegralType {
class IntType extends SignedIntegralType {
IntType() { this.isSystemType("Int32") }
override string toStringWithTypes() { result = "int" }
@@ -139,21 +139,21 @@ deprecated class IntType extends SignedIntegralType {
}
/** The type `System.IntPtr`. */
deprecated class IntPtrType extends PrimitiveType {
class IntPtrType extends PrimitiveType {
IntPtrType() { this.isSystemType("IntPtr") }
override IntType getUnderlyingType() { any() }
}
/** The type `System.UIntPtr`. */
deprecated class UIntPtrType extends PrimitiveType {
class UIntPtrType extends PrimitiveType {
UIntPtrType() { this.isSystemType("UIntPtr") }
override IntType getUnderlyingType() { any() }
}
/** The type `System.UInt32`. */
deprecated class UIntType extends UnsignedIntegralType {
class UIntType extends UnsignedIntegralType {
UIntType() { this.isSystemType("UInt32") }
override string toStringWithTypes() { result = "uint" }
@@ -164,7 +164,7 @@ deprecated class UIntType extends UnsignedIntegralType {
}
/** The type `System.SByte`. */
deprecated class SByteType extends SignedIntegralType {
class SByteType extends SignedIntegralType {
SByteType() { this.isSystemType("SByte") }
override string toStringWithTypes() { result = "sbyte" }
@@ -173,7 +173,7 @@ deprecated class SByteType extends SignedIntegralType {
}
/** The type `System.Byte`. */
deprecated class ByteType extends UnsignedIntegralType {
class ByteType extends UnsignedIntegralType {
ByteType() { this.isSystemType("Byte") }
override string toStringWithTypes() { result = "byte" }
@@ -184,7 +184,7 @@ deprecated class ByteType extends UnsignedIntegralType {
}
/** The type `System.Int16`. */
deprecated class ShortType extends SignedIntegralType {
class ShortType extends SignedIntegralType {
ShortType() { this.isSystemType("Int16") }
override string toStringWithTypes() { result = "short" }
@@ -193,7 +193,7 @@ deprecated class ShortType extends SignedIntegralType {
}
/** The type `System.UInt16`. */
deprecated class UShortType extends UnsignedIntegralType {
class UShortType extends UnsignedIntegralType {
UShortType() { this.isSystemType("UInt16") }
override string toStringWithTypes() { result = "ushort" }
@@ -204,7 +204,7 @@ deprecated class UShortType extends UnsignedIntegralType {
}
/** The type `System.Int64`. */
deprecated class LongType extends SignedIntegralType {
class LongType extends SignedIntegralType {
LongType() { this.isSystemType("Int64") }
override string toStringWithTypes() { result = "long" }
@@ -213,7 +213,7 @@ deprecated class LongType extends SignedIntegralType {
}
/** The type `System.UInt64`. */
deprecated class ULongType extends UnsignedIntegralType {
class ULongType extends UnsignedIntegralType {
ULongType() { this.isSystemType("UInt64") }
override string toStringWithTypes() { result = "ulong" }
@@ -224,7 +224,7 @@ deprecated class ULongType extends UnsignedIntegralType {
}
/** The type `System.Decimal`. */
deprecated class DecimalType extends SignedIntegralType {
class DecimalType extends SignedIntegralType {
DecimalType() { this.isSystemType("Decimal") }
override string toStringWithTypes() { result = "decimal" }
@@ -233,21 +233,21 @@ deprecated class DecimalType extends SignedIntegralType {
}
/** The type `System.String`. */
deprecated class StringType extends PrimitiveType, ValueOrRefType {
class StringType extends PrimitiveType, ValueOrRefType {
StringType() { this.isSystemType("String") }
override string toStringWithTypes() { result = "string" }
}
/** The type `System.Object`. */
deprecated class ObjectType extends ValueOrRefType {
class ObjectType extends ValueOrRefType {
ObjectType() { this.isSystemType("Object") }
override string toStringWithTypes() { result = "object" }
}
/** The type `System.Boolean`. */
deprecated class BoolType extends PrimitiveType, ValueOrRefType {
class BoolType extends PrimitiveType, ValueOrRefType {
BoolType() { this.isSystemType("Boolean") }
override string toStringWithTypes() { result = "bool" }
@@ -256,7 +256,7 @@ deprecated class BoolType extends PrimitiveType, ValueOrRefType {
}
/** The type `System.Double`. */
deprecated class DoubleType extends FloatingPointType {
class DoubleType extends FloatingPointType {
DoubleType() { this.isSystemType("Double") }
override string toStringWithTypes() { result = "double" }
@@ -265,7 +265,7 @@ deprecated class DoubleType extends FloatingPointType {
}
/** The type `System.Single`. */
deprecated class FloatType extends FloatingPointType {
class FloatType extends FloatingPointType {
FloatType() { this.isSystemType("Single") }
override string toStringWithTypes() { result = "float" }
@@ -274,7 +274,7 @@ deprecated class FloatType extends FloatingPointType {
}
/** The type `System.Char`. */
deprecated class CharType extends IntegralType {
class CharType extends IntegralType {
CharType() { this.isSystemType("Char") }
override string toStringWithTypes() { result = "char" }
@@ -285,7 +285,7 @@ deprecated class CharType extends IntegralType {
}
/** The type `System.Type`. */
deprecated class SystemType extends ValueOrRefType {
class SystemType extends ValueOrRefType {
SystemType() { this.isSystemType("Type") }
}
@@ -296,7 +296,7 @@ deprecated class SystemType extends ValueOrRefType {
* delegate*<int, void>
* ```
*/
deprecated class FunctionPointerType extends Type, CustomModifierReceiver, Parameterizable,
class FunctionPointerType extends Type, CustomModifierReceiver, Parameterizable,
@cil_function_pointer_type
{
/** Gets the return type of this function pointer. */

View File

@@ -6,7 +6,7 @@ private import CIL
private import dotnet
/** A variable. Either a stack variable (`StackVariable`) or a field (`Field`). */
deprecated class Variable extends DotNet::Variable, Declaration, DataFlowNode, @cil_variable {
class Variable extends DotNet::Variable, Declaration, DataFlowNode, @cil_variable {
/** Gets the type of this variable. */
override Type getType() { none() }
@@ -28,7 +28,7 @@ deprecated class Variable extends DotNet::Variable, Declaration, DataFlowNode, @
}
/** A stack variable. Either a local variable (`LocalVariable`) or a parameter (`Parameter`). */
deprecated class StackVariable extends Variable, @cil_stack_variable {
class StackVariable extends Variable, @cil_stack_variable {
deprecated override predicate hasQualifiedName(string qualifier, string name) { none() }
override predicate hasFullyQualifiedName(string qualifier, string name) { none() }
@@ -39,7 +39,7 @@ deprecated class StackVariable extends Variable, @cil_stack_variable {
*
* Each method in CIL has a number of typed local variables, in addition to the evaluation stack.
*/
deprecated class LocalVariable extends StackVariable, @cil_local_variable {
class LocalVariable extends StackVariable, @cil_local_variable {
override string toString() {
result =
"Local variable " + this.getIndex() + " of method " +
@@ -60,7 +60,7 @@ deprecated class LocalVariable extends StackVariable, @cil_local_variable {
}
/** A parameter of a `Method` or `FunctionPointerType`. */
deprecated class Parameter extends DotNet::Parameter, CustomModifierReceiver, @cil_parameter {
class Parameter extends DotNet::Parameter, CustomModifierReceiver, @cil_parameter {
override Parameterizable getDeclaringElement() { cil_parameter(this, result, _, _) }
/** Gets the index of this parameter. */
@@ -107,7 +107,7 @@ deprecated class Parameter extends DotNet::Parameter, CustomModifierReceiver, @c
}
/** A method parameter. */
deprecated class MethodParameter extends Parameter, StackVariable {
class MethodParameter extends Parameter, StackVariable {
/** Gets the method declaring this parameter. */
override Method getMethod() { this = result.getARawParameter() }
@@ -132,7 +132,7 @@ deprecated class MethodParameter extends Parameter, StackVariable {
}
/** A parameter corresponding to `this`. */
deprecated class ThisParameter extends MethodParameter {
class ThisParameter extends MethodParameter {
ThisParameter() {
not this.getMethod().isStatic() and
this.getIndex() = 0
@@ -140,7 +140,7 @@ deprecated class ThisParameter extends MethodParameter {
}
/** A field. */
deprecated class Field extends DotNet::Field, Variable, Member, CustomModifierReceiver, @cil_field {
class Field extends DotNet::Field, Variable, Member, CustomModifierReceiver, @cil_field {
override string toString() { result = this.getName() }
override string toStringWithTypes() {

View File

@@ -1,7 +1,7 @@
private import cil
private import codeql.ssa.Ssa as SsaImplCommon
deprecated private module SsaInput implements SsaImplCommon::InputSig<CIL::Location> {
private module SsaInput implements SsaImplCommon::InputSig<CIL::Location> {
class BasicBlock = CIL::BasicBlock;
BasicBlock getImmediateBasicBlockDominator(BasicBlock bb) { result = bb.getImmediateDominator() }
@@ -29,17 +29,17 @@ deprecated private module SsaInput implements SsaImplCommon::InputSig<CIL::Locat
}
}
deprecated import SsaImplCommon::Make<CIL::Location, SsaInput>
import SsaImplCommon::Make<CIL::Location, SsaInput>
cached
private module Cached {
private import CIL
cached
deprecated predicate forceCachingInSameStage() { any() }
predicate forceCachingInSameStage() { any() }
cached
deprecated ReadAccess getARead(Definition def) {
ReadAccess getARead(Definition def) {
exists(BasicBlock bb, int i |
ssaDefReachesRead(_, def, bb, i) and
result = bb.getNode(i)
@@ -47,7 +47,7 @@ private module Cached {
}
cached
deprecated ReadAccess getAFirstReadExt(DefinitionExt def) {
ReadAccess getAFirstReadExt(DefinitionExt def) {
exists(BasicBlock bb1, int i1, BasicBlock bb2, int i2 |
def.definesAt(_, bb1, i1, _) and
adjacentDefReadExt(def, _, bb1, i1, bb2, i2) and
@@ -56,7 +56,7 @@ private module Cached {
}
cached
deprecated predicate hasAdjacentReadsExt(DefinitionExt def, ReadAccess first, ReadAccess second) {
predicate hasAdjacentReadsExt(DefinitionExt def, ReadAccess first, ReadAccess second) {
exists(BasicBlock bb1, int i1, BasicBlock bb2, int i2 |
first = bb1.getNode(i1) and
adjacentDefReadExt(def, _, bb1, i1, bb2, i2) and
@@ -65,12 +65,10 @@ private module Cached {
}
cached
deprecated Definition getAPhiInput(PhiNode phi) { phiHasInputFromBlock(phi, result, _) }
Definition getAPhiInput(PhiNode phi) { phiHasInputFromBlock(phi, result, _) }
cached
deprecated predicate lastRefBeforeRedefExt(
DefinitionExt def, BasicBlock bb, int i, DefinitionExt next
) {
predicate lastRefBeforeRedefExt(DefinitionExt def, BasicBlock bb, int i, DefinitionExt next) {
lastRefRedefExt(def, _, bb, i, next)
}
}

View File

@@ -8,6 +8,7 @@ import Stmt
import Type
import exprs.Call
private import commons.QualifiedName
private import dotnet
private import semmle.code.csharp.ExprOrStmtParent
private import semmle.code.csharp.metrics.Complexity
private import TypeRef
@@ -20,73 +21,8 @@ private import TypeRef
* an anonymous function (`AnonymousFunctionExpr`), or a local function
* (`LocalFunction`).
*/
class Callable extends Parameterizable, ExprOrStmtParent, @callable {
pragma[noinline]
deprecated private string getDeclaringTypeLabel() { result = this.getDeclaringType().getLabel() }
pragma[noinline]
deprecated private string getParameterTypeLabelNonGeneric(int p) {
not this instanceof Generic and
result = this.getParameter(p).getType().getLabel()
}
language[monotonicAggregates]
pragma[nomagic]
deprecated private string getMethodParamListNonGeneric() {
result =
concat(int p |
p in [0 .. this.getNumberOfParameters() - 1]
|
this.getParameterTypeLabelNonGeneric(p), "," order by p
)
}
pragma[noinline]
deprecated private string getParameterTypeLabelGeneric(int p) {
this instanceof Generic and
result = this.getParameter(p).getType().getLabel()
}
language[monotonicAggregates]
pragma[nomagic]
deprecated private string getMethodParamListGeneric() {
result =
concat(int p |
p in [0 .. this.getNumberOfParameters() - 1]
|
this.getParameterTypeLabelGeneric(p), "," order by p
)
}
pragma[noinline]
deprecated private string getLabelNonGeneric() {
not this instanceof Generic and
result =
this.getReturnTypeLabel() + " " + this.getDeclaringTypeLabel() + "." +
this.getUndecoratedName() + "(" + this.getMethodParamListNonGeneric() + ")"
}
pragma[noinline]
deprecated private string getLabelGeneric() {
result =
this.getReturnTypeLabel() + " " + this.getDeclaringTypeLabel() + "." +
this.getUndecoratedName() + getGenericsLabel(this) + "(" + this.getMethodParamListGeneric() +
")"
}
deprecated final override string getLabel() {
result = this.getLabelNonGeneric() or
result = this.getLabelGeneric()
}
deprecated private string getReturnTypeLabel() {
result = this.getReturnType().getLabel()
or
not exists(this.getReturnType()) and result = "System.Void"
}
/** Gets the return type of this callable. */
Type getReturnType() { none() }
class Callable extends DotNet::Callable, Parameterizable, ExprOrStmtParent, @callable {
override Type getReturnType() { none() }
/** Gets the annotated return type of this callable. */
final AnnotatedType getAnnotatedReturnType() { result.appliesTo(this) }
@@ -129,8 +65,7 @@ class Callable extends Parameterizable, ExprOrStmtParent, @callable {
result = this.getExpressionBody()
}
/** Holds if this callable has a body or an implementation. */
predicate hasBody() { exists(this.getBody()) }
override predicate hasBody() { exists(this.getBody()) }
/**
* Holds if this callable has a non-empty body. That is, either it has
@@ -261,8 +196,7 @@ class Callable extends Parameterizable, ExprOrStmtParent, @callable {
)
}
/** Holds if this callable can return expression `e`. */
predicate canReturn(Expr e) {
override predicate canReturn(DotNet::Expr e) {
exists(ReturnStmt ret | ret.getEnclosingCallable() = this | e = ret.getExpr())
or
e = this.getExpressionBody() and
@@ -284,6 +218,8 @@ class Callable extends Parameterizable, ExprOrStmtParent, @callable {
/** Gets a `Call` that has this callable as a target. */
Call getACall() { this = result.getTarget() }
override Parameter getAParameter() { result = Parameterizable.super.getAParameter() }
}
/**
@@ -389,7 +325,7 @@ class ExtensionMethod extends Method {
* }
* ```
*/
class Constructor extends Callable, Member, Attributable, @constructor {
class Constructor extends DotNet::Constructor, Callable, Member, Attributable, @constructor {
override string getName() { constructors(this, result, _, _) }
override Type getReturnType() {
@@ -499,7 +435,7 @@ class PrimaryConstructor extends Constructor {
* }
* ```
*/
class Destructor extends Callable, Member, Attributable, @destructor {
class Destructor extends DotNet::Destructor, Callable, Member, Attributable, @destructor {
override string getName() { destructors(this, result, _, _) }
override Type getReturnType() {
@@ -561,33 +497,10 @@ class Operator extends Callable, Member, Attributable, Overridable, @operator {
override Parameter getRawParameter(int i) { result = this.getParameter(i) }
}
pragma[nomagic]
private ValueOrRefType getARecordBaseType(ValueOrRefType t) {
exists(Callable c |
c.hasName("<Clone>$") and
c.getNumberOfParameters() = 0 and
t = c.getDeclaringType() and
result = t
)
or
result = getARecordBaseType(t).getABaseType()
}
/** A clone method on a record. */
class RecordCloneMethod extends Method {
RecordCloneMethod() {
this.hasName("<Clone>$") and
this.getNumberOfParameters() = 0 and
this.getReturnType() = getARecordBaseType(this.getDeclaringType()) and
this.isPublic() and
not this.isStatic()
}
/** Gets the constructor that this clone method calls. */
Constructor getConstructor() {
result.getDeclaringType() = this.getDeclaringType() and
result.getNumberOfParameters() = 1 and
result.getParameter(0).getType() = this.getDeclaringType()
class RecordCloneMethod extends Method, DotNet::RecordCloneCallable {
override Constructor getConstructor() {
result = DotNet::RecordCloneCallable.super.getConstructor()
}
}

View File

@@ -4,6 +4,7 @@
import Location
private import semmle.code.csharp.ExprOrStmtParent
private import dotnet
private import commons.QualifiedName
/**
@@ -13,64 +14,18 @@ private import commons.QualifiedName
* (`NamespaceDeclaration`), a `using` directive (`UsingDirective`), or type
* parameter constraints (`TypeParameterConstraints`).
*/
class Element extends @element {
/** Gets a textual representation of this element. */
cached
string toString() { none() }
/** Gets the file containing this element. */
final File getFile() { result = this.getLocation().getFile() }
/** Holds if this element is from source code. */
predicate fromSource() { this.getFile().fromSource() }
/** Holds if this element is from an assembly. */
predicate fromLibrary() { this.getFile().fromLibrary() }
/**
* Gets the "language" of this program element, as defined by the extension of the filename.
* For example, C# has language "cs", and Visual Basic has language "vb".
*/
deprecated final string getLanguage() { result = this.getLocation().getFile().getExtension() }
/**
* Gets a comma-separated list of the names of the primary CodeQL classes to which this element belongs.
*
* If no primary class can be determined, the result is `"???"`.
*/
final string getPrimaryQlClasses() {
result = strictconcat(this.getAPrimaryQlClass(), ",")
or
not exists(this.getAPrimaryQlClass()) and
result = "???"
}
/**
* Gets the name of a primary CodeQL class to which this element belongs.
*
* For most elements, this is simply the most precise syntactic category to
* which they belong; for example, `AddExpr` is a primary class, but
* `BinaryOperation` is not.
*
* If no primary classes match, this predicate has no result. If multiple
* primary classes match, this predicate can have multiple results.
*
* See also `getPrimaryQlClasses`, which is better to use in most cases.
*/
string getAPrimaryQlClass() { none() }
/** Gets the full textual representation of this element, including type information. */
string toStringWithTypes() { result = this.toString() }
class Element extends DotNet::Element, @element {
override string toStringWithTypes() { result = this.toString() }
/**
* Gets the location of this element. Where an element has locations in
* source and assemblies, choose the source location. If there are multiple
* assembly locations, choose only one.
*/
final Location getLocation() { result = bestLocation(this) }
final override Location getLocation() { result = bestLocation(this) }
/** Gets a location of this element, including sources and assemblies. */
Location getALocation() { none() }
override Location getALocation() { none() }
/** Gets the parent of this element, if any. */
Element getParent() { result.getAChild() = this }
@@ -91,96 +46,3 @@ class Element extends @element {
*/
int getIndex() { exists(Element parent | parent.getChild(result) = this) }
}
/** An element that has a name. */
class NamedElement extends Element, @named_element {
/** Gets the name of this element. */
cached
string getName() { none() }
/** Holds if this element has name 'name'. */
final predicate hasName(string name) { name = this.getName() }
/**
* Gets the fully qualified name of this element, for example the
* fully qualified name of `M` on line 3 is `N.C.M` in
*
* ```csharp
* namespace N {
* class C {
* void M(int i, string s) { }
* }
* }
* ```
*/
cached
deprecated final string getQualifiedName() {
exists(string qualifier, string name | this.hasQualifiedName(qualifier, name) |
if qualifier = "" then result = name else result = qualifier + "." + name
)
}
/**
* Gets the fully qualified name of this element, for example the
* fully qualified name of `M` on line 3 is `N.C.M` in
*
* ```csharp
* namespace N {
* class C {
* void M(int i, string s) { }
* }
* }
* ```
*
* Unbound generic types, such as `IList<T>`, are represented as
* ``System.Collections.Generic.IList`1``.
*/
cached
final string getFullyQualifiedName() {
exists(string qualifier, string name | this.hasFullyQualifiedName(qualifier, name) |
if qualifier = "" then result = name else result = qualifier + "." + name
)
}
/**
* DEPRECATED: Use `hasFullyQualifiedName` instead.
*
* Holds if this element has the qualified name `qualifier`.`name`.
*/
cached
deprecated predicate hasQualifiedName(string qualifier, string name) {
qualifier = "" and name = this.getName()
}
/** Holds if this element has the fully qualified name `qualifier`.`name`. */
cached
predicate hasFullyQualifiedName(string qualifier, string name) {
qualifier = "" and name = this.getName()
}
/** Gets a unique string label for this element. */
cached
deprecated string getLabel() { none() }
/** Holds if `other` has the same metadata handle in the same assembly. */
deprecated predicate matchesHandle(NamedElement other) {
exists(Assembly asm, int handle |
metadata_handle(this, asm, handle) and
metadata_handle(other, asm, handle)
)
}
/**
* Holds if this element was compiled from source code that is also present in the
* database. That is, this element corresponds to another element from source.
*/
deprecated predicate compiledFromSource() {
not this.fromSource() and
exists(NamedElement other | other != this |
this.matchesHandle(other) and
other.fromSource()
)
}
override string toString() { result = this.getName() }
}

View File

@@ -16,13 +16,14 @@
import Location
import Namespace
private import commons.QualifiedName
private import dotnet
private import TypeRef
/**
* A generic declaration. Either an unbound generic (`UnboundGeneric`) or a
* constructed generic (`ConstructedGeneric`).
*/
class Generic extends Declaration, @generic {
class Generic extends DotNet::Generic, Declaration, @generic {
Generic() {
type_parameters(_, _, this, _) or
type_arguments(_, _, this) or
@@ -36,23 +37,16 @@ class Generic extends Declaration, @generic {
* Either an unbound generic type (`UnboundGenericType`) or an unbound generic method
* (`UnboundGenericMethod`).
*/
class UnboundGeneric extends Generic {
class UnboundGeneric extends DotNet::UnboundGeneric, Generic {
UnboundGeneric() { type_parameters(_, _, this, _) }
/** Gets the `i`th type parameter, if any. */
final TypeParameter getTypeParameter(int n) { type_parameters(result, n, this, _) }
final override TypeParameter getTypeParameter(int n) { type_parameters(result, n, this, _) }
/** Gets a type parameter. */
TypeParameter getATypeParameter() { result = this.getTypeParameter(_) }
override ConstructedGeneric getAConstructedGeneric() { result.getUnboundGeneric() = this }
/**
* Gets one of the constructed versions of this declaration,
* which has been bound to a specific set of types.
*/
ConstructedGeneric getAConstructedGeneric() { result.getUnboundGeneric() = this }
/** Gets the total number of type parameters. */
int getNumberOfTypeParameters() { result = count(int i | exists(this.getTypeParameter(i))) }
override TypeParameter getATypeParameter() {
result = DotNet::UnboundGeneric.super.getATypeParameter()
}
}
/** Gets the type parameters as a comma-separated string. */
@@ -73,61 +67,25 @@ private string getTypeParameterBacktick(UnboundGeneric ug) {
* Either a constructed generic type (`ConstructedType`) or a constructed
* generic method (`ConstructedMethod`).
*/
class ConstructedGeneric extends Generic {
class ConstructedGeneric extends DotNet::ConstructedGeneric, Generic {
ConstructedGeneric() {
type_arguments(_, _, this)
or
nullable_underlying_type(this, _)
}
/**
* Gets the unbound generic declaration from which this declaration was
* constructed.
*/
UnboundGeneric getUnboundGeneric() { constructed_generic(this, result) }
override UnboundGeneric getUnboundGeneric() { constructed_generic(this, result) }
override UnboundGeneric getUnboundDeclaration() {
result = this.getUnboundGeneric().getUnboundDeclaration()
}
/** Gets the `i`th type argument, if any. */
Type getTypeArgument(int i) { none() }
override Type getTypeArgument(int i) { none() }
/** Gets a type argument. */
Type getATypeArgument() { result = this.getTypeArgument(_) }
override Type getATypeArgument() { result = this.getTypeArgument(_) }
/** Gets the annotated type of type argument `i`. */
final AnnotatedType getAnnotatedTypeArgument(int i) { result.appliesToTypeArgument(this, i) }
/** Gets the total number of type arguments. */
final int getNumberOfTypeArguments() { result = count(int i | exists(this.getTypeArgument(i))) }
}
/**
* INTERNAL: Do not use.
*
* Constructs the label suffix for a generic method or type.
*/
deprecated string getGenericsLabel(Generic g) {
result = "`" + g.(UnboundGeneric).getNumberOfTypeParameters()
or
result = "<" + typeArgs(g) + ">"
}
pragma[noinline]
deprecated private string getTypeArgumentLabel(ConstructedGeneric generic, int p) {
result = generic.getTypeArgument(p).getLabel()
}
language[monotonicAggregates]
pragma[nomagic]
deprecated private string typeArgs(ConstructedGeneric generic) {
result =
concat(int p |
p in [0 .. generic.getNumberOfTypeArguments() - 1]
|
getTypeArgumentLabel(generic, p), ","
)
}
/** Gets the type arguments as a comma-separated string. */
@@ -202,10 +160,7 @@ class UnboundGenericType extends ValueOrRefType, UnboundGeneric {
/**
* A type parameter, for example `T` in `List<T>`.
*/
class TypeParameter extends Type, @type_parameter {
/** Gets the generic type or method declaring this type parameter. */
UnboundGeneric getDeclaringGeneric() { this = result.getATypeParameter() }
class TypeParameter extends DotNet::TypeParameter, Type, @type_parameter {
/** Gets the constraints on this type parameter, if any. */
TypeParameterConstraints getConstraints() { result.getTypeParameter() = this }
@@ -261,13 +216,8 @@ class TypeParameter extends Type, @type_parameter {
result = this.getASuppliedType().(TypeParameter).getAnUltimatelySuppliedType()
}
/** Gets the index of this type parameter. For example the index of `U` in `Func<T,U>` is 1. */
override int getIndex() { type_parameters(this, result, _, _) }
deprecated final override string getLabel() { result = "!" + this.getIndex() }
override string getUndecoratedName() { result = "!" + this.getIndex() }
/** Gets the generic that defines this type parameter. */
UnboundGeneric getGeneric() { type_parameters(this, _, result, _) }

View File

@@ -4,6 +4,7 @@ import Callable
import Element
import Modifier
import Variable
private import dotnet
private import Implements
private import TypeRef
private import commons.QualifiedName
@@ -25,46 +26,8 @@ private module FullyQualifiedNameInput implements QualifiedNameInputSig {
*
* Either a modifiable (`Modifiable`) or an assignable (`Assignable`).
*/
class Declaration extends NamedElement, @declaration {
/** Gets the name of this declaration, without additional decoration such as `<...>`. */
string getUndecoratedName() { none() }
/** Holds if this element has undecorated name 'name'. */
final predicate hasUndecoratedName(string name) { name = this.getUndecoratedName() }
/**
* Gets the unbound version of this declaration, that is, the declaration where
* all type arguments have been removed. For example, in
*
* ```csharp
* class C<T>
* {
* class Nested
* {
* }
*
* void Method<S>() { }
* }
* ```
*
* we have the following
*
* | Declaration | Unbound declaration |
* |-------------------------|---------------------|
* | `C<int>` | ``C`1`` |
* | ``C`1.Nested`` | ``C`1.Nested`` |
* | `C<int>.Nested` | ``C`1.Nested`` |
* | ``C`1.Method`1`` | ``C`1.Method`1`` |
* | ``C<int>.Method`1`` | ``C`1.Method`1`` |
* | `C<int>.Method<string>` | ``C`1.Method`1`` |
*/
Declaration getUnboundDeclaration() { result = this }
/** Holds if this declaration is unbound. */
final predicate isUnboundDeclaration() { this.getUnboundDeclaration() = this }
/** Gets the type containing this declaration, if any. */
ValueOrRefType getDeclaringType() { none() }
class Declaration extends DotNet::Declaration, Element, @declaration {
override ValueOrRefType getDeclaringType() { none() }
/** Holds if this declaration is unconstructed and in source code. */
final predicate isSourceDeclaration() { this.fromSource() and this.isUnboundDeclaration() }
@@ -259,27 +222,33 @@ class Modifiable extends Declaration, @modifiable {
}
/** A declaration that is a member of a type. */
class Member extends Modifiable, @member {
class Member extends DotNet::Member, Modifiable, @member {
/** Gets an access to this member. */
MemberAccess getAnAccess() { result.getTarget() = this }
/**
* DEPRECATED: Use `hasFullyQualifiedName` instead.
*
* Holds if this member has name `name` and is defined in type `type`
* with namespace `namespace`.
*/
cached
deprecated final predicate hasQualifiedName(string namespace, string type, string name) {
override predicate isPublic() { Modifiable.super.isPublic() }
override predicate isProtected() { Modifiable.super.isProtected() }
override predicate isPrivate() { Modifiable.super.isPrivate() }
override predicate isInternal() { Modifiable.super.isInternal() }
override predicate isSealed() { Modifiable.super.isSealed() }
override predicate isAbstract() { Modifiable.super.isAbstract() }
override predicate isStatic() { Modifiable.super.isStatic() }
override predicate isRequired() { Modifiable.super.isRequired() }
override predicate isFile() { Modifiable.super.isFile() }
deprecated final override predicate hasQualifiedName(string namespace, string type, string name) {
QualifiedName<QualifiedNameInput>::hasQualifiedName(this, namespace, type, name)
}
/**
* Holds if this member has name `name` and is defined in type `type`
* with namespace `namespace`.
*/
cached
final predicate hasFullyQualifiedName(string namespace, string type, string name) {
final override predicate hasFullyQualifiedName(string namespace, string type, string name) {
QualifiedName<FullyQualifiedNameInput>::hasQualifiedName(this, namespace, type, name)
}
}
@@ -508,24 +477,10 @@ class Virtualizable extends Overridable, Member, @virtualizable {
* A parameterizable declaration. Either a callable (`Callable`), a delegate
* type (`DelegateType`), or an indexer (`Indexer`).
*/
class Parameterizable extends Declaration, @parameterizable {
/** Gets raw parameter `i`, including the `this` parameter at index 0. */
Parameter getRawParameter(int i) { params(result, _, _, i, _, this, _) }
class Parameterizable extends DotNet::Parameterizable, Declaration, @parameterizable {
override Parameter getRawParameter(int i) { params(result, _, _, i, _, this, _) }
/** Gets the `i`th parameter, excluding the `this` parameter. */
Parameter getParameter(int i) { params(result, _, _, i, _, this, _) }
/** Gets the number of parameters of this callable. */
int getNumberOfParameters() { result = count(this.getAParameter()) }
/** Holds if this declaration has no parameters. */
predicate hasNoParameters() { not exists(this.getAParameter()) }
/** Gets a parameter, if any. */
Parameter getAParameter() { result = this.getParameter(_) }
/** Gets a raw parameter (including the qualifier), if any. */
final Parameter getARawParameter() { result = this.getRawParameter(_) }
override Parameter getParameter(int i) { params(result, _, _, i, _, this, _) }
/**
* Gets the type of the parameter, possibly prefixed

View File

@@ -1,8 +1,8 @@
/** Provides classes for namespaces. */
private import semmle.code.csharp.commons.QualifiedName
import Element
import Type
private import dotnet
/**
* A type container. Either a namespace (`Namespace`) or a type (`Type`).
@@ -18,44 +18,24 @@ class TypeContainer extends Declaration, @type_container { }
* }
* ```
*/
class Namespace extends TypeContainer, Declaration, @namespace {
class Namespace extends DotNet::Namespace, TypeContainer, Declaration, @namespace {
override Namespace getParent() { result = this.getParentNamespace() }
/**
* Gets the parent namespace, if any. For example the parent namespace of `System.IO`
* is `System`. The parent namespace of `System` is the global namespace.
*/
Namespace getParentNamespace() { parent_namespace(this, result) }
override Namespace getParentNamespace() { parent_namespace(this, result) }
/**
* Gets a child namespace, if any. For example `System.IO` is a child in
* the namespace `System`.
*/
Namespace getAChildNamespace() { parent_namespace(result, this) }
override Namespace getAChildNamespace() { parent_namespace(result, this) }
override TypeContainer getChild(int i) {
i = 0 and
parent_namespace(result, this)
}
/**
* Holds if this namespace has the qualified name `qualifier`.`name`.
*
* For example if the qualified name is `System.Collections.Generic`, then
* `qualifier`=`System.Collections` and `name`=`Generic`.
*/
deprecated override predicate hasQualifiedName(string qualifier, string name) {
namespaceHasQualifiedName(this, qualifier, name)
DotNet::Namespace.super.hasQualifiedName(qualifier, name)
}
/**
* Holds if this namespace has the qualified name `qualifier`.`name`.
*
* For example if the qualified name is `System.Collections.Generic`, then
* `qualifier`=`System.Collections` and `name`=`Generic`.
*/
override predicate hasFullyQualifiedName(string qualifier, string name) {
namespaceHasQualifiedName(this, qualifier, name)
DotNet::Namespace.super.hasFullyQualifiedName(qualifier, name)
}
/**
@@ -143,28 +123,7 @@ class Namespace extends TypeContainer, Declaration, @namespace {
override Location getALocation() { result = this.getADeclaration().getALocation() }
/** Gets a textual representation of this namespace. */
override string toString() { result = this.getFullName() }
/** Holds if this is the global namespace. */
final predicate isGlobalNamespace() { this.getName() = "" }
/** Gets the simple name of this namespace, for example `IO` in `System.IO`. */
final override string getName() { namespaces(this, result) }
final override string getUndecoratedName() { namespaces(this, result) }
override string getAPrimaryQlClass() { result = "Namespace" }
/**
* Get the fully qualified name of this namespace.
*/
string getFullName() {
exists(string namespace, string name |
namespaceHasQualifiedName(this, namespace, name) and
result = getQualifiedName(namespace, name)
)
}
override string toString() { result = DotNet::Namespace.super.toString() }
}
/**

View File

@@ -5,6 +5,8 @@
import Member
import Stmt
import Type
private import cil
private import dotnet
private import semmle.code.csharp.ExprOrStmtParent
private import TypeRef
@@ -111,7 +113,7 @@ class DeclarationWithGetSetAccessors extends DeclarationWithAccessors, TopLevelE
* }
* ```
*/
class Property extends DeclarationWithGetSetAccessors, @property {
class Property extends DotNet::Property, DeclarationWithGetSetAccessors, @property {
override string getName() { properties(this, result, _, _, _) }
override string getUndecoratedName() { properties(this, result, _, _, _) }
@@ -556,6 +558,8 @@ class TrivialProperty extends Property {
this.isAutoImplemented()
or
this.getGetter().trivialGetterField() = this.getSetter().trivialSetterField()
or
exists(CIL::TrivialProperty prop | this.matchesHandle(prop))
}
}

View File

@@ -7,6 +7,7 @@ import Location
import Namespace
import Property
private import Conversion
private import dotnet
private import semmle.code.csharp.metrics.Coupling
private import TypeRef
private import semmle.code.csharp.frameworks.System
@@ -19,10 +20,7 @@ private import semmle.code.csharp.frameworks.system.runtime.CompilerServices
* a pointer type (`PointerType`), the arglist type (`ArglistType`), an unknown
* type (`UnknownType`), or a type parameter (`TypeParameter`).
*/
class Type extends Member, TypeContainer, @type {
/** Gets the name of this type without additional syntax such as `[]` or `*`. */
override string getUndecoratedName() { none() }
class Type extends DotNet::Type, Member, TypeContainer, @type {
override string getName() { types(this, _, result) }
override Type getUnboundDeclaration() { result = this }
@@ -58,7 +56,7 @@ private predicate isObjectClass(Class c) { c instanceof ObjectType }
*
* Either a value type (`ValueType`) or a reference type (`RefType`).
*/
class ValueOrRefType extends Type, Attributable, @value_or_ref_type {
class ValueOrRefType extends DotNet::ValueOrRefType, Type, Attributable, @value_or_ref_type {
/** Gets the namespace containing this type. */
Namespace getNamespace() {
if exists(this.getDeclaringType())
@@ -66,8 +64,7 @@ class ValueOrRefType extends Type, Attributable, @value_or_ref_type {
else result.getATypeDeclaration() = this
}
/** Gets the namespace declaring this type, if any. */
Namespace getDeclaringNamespace() { this = result.getATypeDeclaration() }
override Namespace getDeclaringNamespace() { this = result.getATypeDeclaration() }
override ValueOrRefType getDeclaringType() { none() }
@@ -76,30 +73,6 @@ class ValueOrRefType extends Type, Attributable, @value_or_ref_type {
/** Gets a nested child type, if any. */
NestedType getAChildType() { nested_types(result, this, _) }
deprecated private string getPrefixWithTypes() {
result = this.getDeclaringType().getLabel() + "."
or
if this.getDeclaringNamespace().isGlobalNamespace()
then result = ""
else result = this.getDeclaringNamespace().getFullName() + "."
}
pragma[noinline]
deprecated private string getLabelNonGeneric() {
not this instanceof Generic and
result = this.getPrefixWithTypes() + this.getUndecoratedName()
}
pragma[noinline]
deprecated private string getLabelGeneric() {
result = this.getPrefixWithTypes() + this.getUndecoratedName() + getGenericsLabel(this)
}
deprecated override string getLabel() {
result = this.getLabelNonGeneric() or
result = this.getLabelGeneric()
}
/**
* Gets the source namespace declaration in which this type is declared, if any.
* This only holds for non-nested types.
@@ -147,7 +120,7 @@ class ValueOrRefType extends Type, Attributable, @value_or_ref_type {
}
/** Gets an immediate base type of this type, if any. */
ValueOrRefType getABaseType() {
override ValueOrRefType getABaseType() {
result = this.getBaseClass() or
result = this.getABaseInterface()
}
@@ -387,8 +360,7 @@ class ValueOrRefType extends Type, Attributable, @value_or_ref_type {
nested_types(this, _, result)
}
/** Holds if this type is a `record`. */
predicate isRecord() { this.hasModifier("record") }
override predicate isRecord() { this.hasModifier("record") }
override string toString() { result = Type.super.toString() }
}
@@ -997,7 +969,7 @@ class FunctionPointerType extends Type, Parameterizable, @function_pointer_type
override string getAPrimaryQlClass() { result = "FunctionPointerType" }
deprecated override string getLabel() { result = this.getName() }
override string getLabel() { result = this.getName() }
}
/**
@@ -1092,7 +1064,7 @@ class InlineArrayType extends ValueType, @inline_array_type {
/**
* An array type, for example `int[]`.
*/
class ArrayType extends RefType, @array_type {
class ArrayType extends DotNet::ArrayType, RefType, @array_type {
/**
* Gets the dimension of this array type. For example `int[][]` is of
* dimension 2, while `int[]` is of dimension 1.
@@ -1109,15 +1081,13 @@ class ArrayType extends RefType, @array_type {
predicate isMultiDimensional() { this.getRank() > 1 }
/** Gets the element type of this array, for example `int` in `int[]`. */
Type getElementType() {
override Type getElementType() {
array_element_type(this, _, _, result)
or
not array_element_type(this, _, _, any(Type t)) and
array_element_type(this, _, _, getTypeRef(result))
}
deprecated final override string getLabel() { result = this.getElementType().getLabel() + "[]" }
/** Holds if this array type has the same shape (dimension and rank) as `that` array type. */
predicate hasSameShapeAs(ArrayType that) {
this.getDimension() = that.getDimension() and
@@ -1158,36 +1128,33 @@ class ArrayType extends RefType, @array_type {
not type_location(this, _) and
result = this.getElementType().getALocation()
}
override string getAPrimaryQlClass() { result = "ArrayType" }
}
/**
* A pointer type, for example `char*`.
*/
class PointerType extends Type, @pointer_type {
/** Gets the type referred by this pointer type, for example `char` in `char*`. */
Type getReferentType() {
class PointerType extends DotNet::PointerType, Type, @pointer_type {
override Type getReferentType() {
pointer_referent_type(this, result)
or
not pointer_referent_type(this, any(Type t)) and
pointer_referent_type(this, getTypeRef(result))
}
override string toStringWithTypes() { result = this.getReferentType().toStringWithTypes() + "*" }
override string toStringWithTypes() { result = DotNet::PointerType.super.toStringWithTypes() }
override Type getChild(int n) { result = this.getReferentType() and n = 0 }
final override string getName() { types(this, _, result) }
deprecated final override string getLabel() { result = this.getReferentType().getLabel() + "*" }
final override string getUndecoratedName() {
result = this.getReferentType().getUndecoratedName()
}
override Location getALocation() { result = this.getReferentType().getALocation() }
override string toString() { result = DotNet::PointerType.super.toString() }
override string getAPrimaryQlClass() { result = "PointerType" }
}
@@ -1271,7 +1238,7 @@ class TupleType extends ValueType, @tuple_type {
")"
}
deprecated override string getLabel() { result = this.getUnderlyingType().getLabel() }
override string getLabel() { result = this.getUnderlyingType().getLabel() }
override Type getChild(int i) { result = this.getUnderlyingType().getChild(i) }

View File

@@ -7,18 +7,18 @@ import Assignable
import Callable
import Element
import Type
private import dotnet
private import semmle.code.csharp.ExprOrStmtParent
private import TypeRef
/**
* A variable. Either a variable with local scope (`LocalScopeVariable`) or a field (`Field`).
*/
class Variable extends Assignable, @variable {
class Variable extends Assignable, DotNet::Variable, @variable {
override Variable getUnboundDeclaration() { result = this }
override VariableAccess getAnAccess() { result.getTarget() = this }
/** Gets the type of this variable. */
override Type getType() { none() }
/** Gets the expression used to initialise this variable, if any. */
@@ -87,10 +87,9 @@ class LocalScopeVariable extends Variable, @local_scope_variable {
* }
* ```
*/
class Parameter extends LocalScopeVariable, Attributable, TopLevelExprParent, @parameter {
/** Gets the raw position of this parameter, including the `this` parameter at index 0. */
final int getRawPosition() { this = this.getDeclaringElement().getRawParameter(result) }
class Parameter extends DotNet::Parameter, LocalScopeVariable, Attributable, TopLevelExprParent,
@parameter
{
/**
* Gets the position of this parameter. For example, the position of `x` is
* 0 and the position of `y` is 1 in
@@ -101,7 +100,7 @@ class Parameter extends LocalScopeVariable, Attributable, TopLevelExprParent, @p
* }
* ```
*/
int getPosition() { params(this, _, _, result, _, _, _) }
override int getPosition() { params(this, _, _, result, _, _, _) }
override int getIndex() { result = this.getPosition() }
@@ -139,7 +138,7 @@ class Parameter extends LocalScopeVariable, Attributable, TopLevelExprParent, @p
* }
* ```
*/
predicate isOut() { params(this, _, _, _, 2, _, _) }
override predicate isOut() { params(this, _, _, _, 2, _, _) }
/**
* Holds if this parameter is a value type that is passed in by reference.
@@ -194,7 +193,7 @@ class Parameter extends LocalScopeVariable, Attributable, TopLevelExprParent, @p
predicate hasExtensionMethodModifier() { params(this, _, _, _, 4, _, _) }
/** Gets the declaring element of this parameter. */
Parameterizable getDeclaringElement() { params(this, _, _, _, _, result, _) }
override Parameterizable getDeclaringElement() { params(this, _, _, _, _, result, _) }
override Parameter getUnboundDeclaration() { params(this, _, _, _, _, _, result) }
@@ -397,7 +396,9 @@ class LocalConstant extends LocalVariable, @local_constant {
* }
* ```
*/
class Field extends Variable, AssignableMember, Attributable, TopLevelExprParent, @field {
class Field extends Variable, AssignableMember, Attributable, TopLevelExprParent, DotNet::Field,
@field
{
/**
* Gets the initial value of this field, if any. For example, the initial
* value of `F` on line 2 is `20` in

View File

@@ -3,13 +3,56 @@
*/
import csharp
private import cil
private import dotnet
private predicate isDisposeMethod(Callable method) {
private predicate isDisposeMethod(DotNet::Callable method) {
method.getName() = "Dispose" and
method.getNumberOfParameters() = 0
}
private predicate cilVariableReadFlowsToNode(CIL::Variable variable, DataFlow::Node n) {
n.asExpr() = variable.getARead()
or
exists(DataFlow::Node mid |
cilVariableReadFlowsToNode(variable, mid) and
DataFlow::localFlowStep(mid, n)
)
}
private predicate cilVariableReadFlowsTo(CIL::Variable variable, CIL::DataFlowNode n) {
cilVariableReadFlowsToNode(variable, DataFlow::exprNode(n))
}
private predicate disposedCilVariable(CIL::Variable variable) {
// `variable` is the `this` parameter on a dispose method.
isDisposeMethod(variable.(CIL::ThisParameter).getMethod())
or
// `variable` is passed to a method that disposes it.
exists(CIL::Call call, CIL::Parameter param |
cilVariableReadFlowsTo(variable, call.getArgumentForParameter(param)) and
disposedCilVariable(param)
)
or
// A parameter is disposed if its source declaration is disposed
disposedCilVariable(variable.(CIL::Parameter).getUnboundDeclaration())
or
// A variable is disposed if it's assigned to another variable
// that may be disposed.
exists(CIL::WriteAccess write |
cilVariableReadFlowsTo(variable, write.getExpr()) and
disposedCilVariable(write.getTarget())
)
}
private predicate disposedCSharpVariable(Variable variable) {
// A C# parameter is disposed if its corresponding CIL parameter is disposed
exists(CIL::Method m, CIL::Parameter p, int i |
disposedCilVariable(p) and p = m.getRawParameter(i)
|
variable = any(Callable c2 | c2.matchesHandle(m)).getRawParameter(i)
)
or
// Call to a method that disposes it
exists(Call call, int arg, VariableRead read |
read.getTarget() = variable and
@@ -40,4 +83,7 @@ private predicate disposedCSharpVariable(Variable variable) {
* Hold if `variable` might be disposed.
* This is a conservative overestimate.
*/
predicate mayBeDisposed(Variable variable) { disposedCSharpVariable(variable) }
predicate mayBeDisposed(DotNet::Variable variable) {
disposedCSharpVariable(variable) or
disposedCilVariable(variable)
}

View File

@@ -1,6 +1,7 @@
/** Provides predicates for working with fully qualified names. */
private import csharp
private import dotnet
/**
* Holds if namespace `n` has the qualified name `qualifier`.`name`.
@@ -8,8 +9,8 @@ private import csharp
* For example if the qualified name is `System.Collections.Generic`, then
* `qualifier`=`System.Collections` and `name`=`Generic`.
*/
predicate namespaceHasQualifiedName(Namespace n, string qualifier, string name) {
if n instanceof GlobalNamespace
predicate namespaceHasQualifiedName(DotNet::Namespace n, string qualifier, string name) {
if n instanceof DotNet::GlobalNamespace
then qualifier = "" and name = ""
else (
exists(string pqualifier, string pname |

View File

@@ -3,6 +3,8 @@
*/
import csharp
private import cil
private import dotnet
private import ControlFlow::SuccessorTypes
private import semmle.code.csharp.commons.Assertions
private import semmle.code.csharp.commons.ComparisonTest
@@ -842,6 +844,8 @@ class NullGuardedDataFlowNode extends GuardedDataFlowNode {
/** INTERNAL: Do not use. */
module Internal {
private import semmle.code.cil.CallableReturns
newtype TAbstractValue =
TBooleanValue(boolean b) { b = true or b = false } or
TIntegerValue(int i) { i = any(Expr e).getValue().toInt() } or
@@ -852,11 +856,20 @@ module Internal {
} or
TEmptyCollectionValue(boolean b) { b = true or b = false }
/** A callable that always returns a `null` value. */
private class NullCallable extends Callable {
NullCallable() {
exists(CIL::Method m | m.matchesHandle(this) | alwaysNullMethod(m) and not m.isVirtual())
}
}
/** Holds if expression `e` is a `null` value. */
predicate nullValue(Expr e) {
e instanceof NullLiteral
or
e instanceof DefaultValueExpr and e.getType().isRefType()
or
e.(Call).getTarget().getUnboundDeclaration() instanceof NullCallable
}
/** Holds if expression `e2` is a `null` value whenever `e1` is. */
@@ -877,7 +890,11 @@ module Internal {
/** A callable that always returns a non-`null` value. */
private class NonNullCallable extends Callable {
NonNullCallable() { this = any(SystemObjectClass c).getGetTypeMethod() }
NonNullCallable() {
exists(CIL::Method m | m.matchesHandle(this) | alwaysNotNullMethod(m) and not m.isVirtual())
or
this = any(SystemObjectClass c).getGetTypeMethod()
}
}
/** Holds if expression `e` is a non-`null` value. */

View File

@@ -6,6 +6,8 @@
*/
import csharp
private import cil
private import semmle.code.cil.CallableReturns
private import semmle.code.csharp.ExprOrStmtParent
private import semmle.code.csharp.commons.Assertions
private import semmle.code.csharp.frameworks.System
@@ -37,6 +39,15 @@ private class ThrowingCall extends NonReturningCall {
or
this.(FailingAssertion).getAssertionFailure().isException(c.getExceptionClass())
or
exists(Callable target, CIL::Method m, CIL::Type ex |
target = this.getTarget() and
not target.hasBody() and
target.matchesHandle(m) and
alwaysThrowsException(m, ex) and
c.getExceptionClass().matchesHandle(ex) and
not m.isVirtual()
)
or
this =
any(MethodCall mc |
mc.getTarget()

View File

@@ -3,7 +3,9 @@
*/
import csharp
private import cil
private import semmle.code.csharp.dataflow.Nullness
private import semmle.code.cil.CallableReturns as CR
private predicate finalCallable(Callable c) {
not c.(Virtualizable).isVirtual() and
@@ -13,11 +15,19 @@ private predicate finalCallable(Callable c) {
/** Holds if callable `c` always returns null. */
predicate alwaysNullCallable(Callable c) {
finalCallable(c) and
forex(Expr e | c.canReturn(e) | e instanceof AlwaysNullExpr)
(
exists(CIL::Method m | m.matchesHandle(c) | CR::alwaysNullMethod(m))
or
forex(Expr e | c.canReturn(e) | e instanceof AlwaysNullExpr)
)
}
/** Holds if callable `c` always returns a non-null value. */
predicate alwaysNotNullCallable(Callable c) {
finalCallable(c) and
forex(Expr e | c.canReturn(e) | e instanceof NonNullExpr)
(
exists(CIL::Method m | m.matchesHandle(c) | CR::alwaysNotNullMethod(m))
or
forex(Expr e | c.canReturn(e) | e instanceof NonNullExpr)
)
}

View File

@@ -1,4 +1,6 @@
private import csharp
private import cil
private import dotnet
private import DataFlowImplCommon as DataFlowImplCommon
private import DataFlowPublic
private import DataFlowPrivate
@@ -12,11 +14,30 @@ private import semmle.code.csharp.frameworks.system.collections.Generic
/**
* Gets a source declaration of callable `c` that has a body or has
* a flow summary.
*
* If the callable has both CIL and source code, return only the source
* code version.
*/
Callable getCallableForDataFlow(Callable c) {
result = c.getUnboundDeclaration() and
result.hasBody() and
result.getFile().fromSource()
DotNet::Callable getCallableForDataFlow(DotNet::Callable c) {
exists(DotNet::Callable unboundDecl | unboundDecl = c.getUnboundDeclaration() |
result.hasBody() and
if unboundDecl.getFile().fromSource()
then
// C# callable with C# implementation in the database
result = unboundDecl
else
if unboundDecl instanceof CIL::Callable
then
// CIL callable with C# implementation in the database
unboundDecl.matchesHandle(result.(Callable))
or
// CIL callable without C# implementation in the database
not unboundDecl.matchesHandle(any(Callable k | k.hasBody())) and
result = unboundDecl
else
// C# callable without C# implementation in the database
unboundDecl.matchesHandle(result.(CIL::Callable))
)
}
newtype TReturnKind =
@@ -46,7 +67,7 @@ private module Cached {
*/
cached
newtype TDataFlowCallable =
TCallable(Callable c) { c.isUnboundDeclaration() } or
TDotNetCallable(DotNet::Callable c) { c.isUnboundDeclaration() } or
TSummarizedCallable(DataFlowSummarizedCallable sc) or
TFieldOrPropertyCallable(FieldOrProperty f) or
TCapturedVariableCallable(LocalScopeVariable v) { v.isCaptured() }
@@ -60,6 +81,10 @@ private module Cached {
TExplicitDelegateLikeCall(ControlFlow::Nodes::ElementNode cfn, DelegateLikeCall dc) {
cfn.getAstNode() = dc
} or
TCilCall(CIL::Call call) {
// No need to include calls that are compiled from source
not call.getImplementation().getMethod().compiledFromSource()
} or
TSummaryCall(FlowSummary::SummarizedCallable c, FlowSummaryImpl::Private::SummaryNode receiver) {
FlowSummaryImpl::Private::summaryCallbackRange(c, receiver)
}
@@ -172,7 +197,7 @@ class RefReturnKind extends OutRefReturnKind, TRefReturnKind {
/** A callable used for data flow. */
class DataFlowCallable extends TDataFlowCallable {
/** Gets the underlying source code callable, if any. */
Callable asCallable() { this = TCallable(result) }
DotNet::Callable asCallable() { this = TDotNetCallable(result) }
/** Gets the underlying summarized callable, if any. */
FlowSummary::SummarizedCallable asSummarizedCallable() { this = TSummarizedCallable(result) }
@@ -183,7 +208,7 @@ class DataFlowCallable extends TDataFlowCallable {
LocalScopeVariable asCapturedVariable() { this = TCapturedVariableCallable(result) }
/** Gets the underlying callable. */
Callable getUnderlyingCallable() {
DotNet::Callable getUnderlyingCallable() {
result = this.asCallable() or result = this.asSummarizedCallable()
}
@@ -210,7 +235,8 @@ class DataFlowCallable extends TDataFlowCallable {
abstract class DataFlowCall extends TDataFlowCall {
/**
* Gets a run-time target of this call. A target is always a source
* declaration.
* declaration, and if the callable has both CIL and source code, only
* the source code version is returned.
*/
abstract DataFlowCallable getARuntimeTarget();
@@ -224,7 +250,7 @@ abstract class DataFlowCall extends TDataFlowCall {
abstract DataFlowCallable getEnclosingCallable();
/** Gets the underlying expression, if any. */
final Expr getExpr() { result = this.getNode().asExpr() }
final DotNet::Expr getExpr() { result = this.getNode().asExpr() }
/** Gets the argument at position `pos` of this call. */
final ArgumentNode getArgument(ArgumentPosition pos) { result.argumentOf(this, pos) }
@@ -322,6 +348,33 @@ class ExplicitDelegateLikeDataFlowCall extends DelegateDataFlowCall, TExplicitDe
override Location getLocation() { result = cfn.getLocation() }
}
/** A CIL call relevant for data flow. */
class CilDataFlowCall extends DataFlowCall, TCilCall {
private CIL::Call call;
CilDataFlowCall() { this = TCilCall(call) }
/** Gets the underlying CIL call. */
CIL::Call getCilCall() { result = call }
override DataFlowCallable getARuntimeTarget() {
// There is no dispatch library for CIL, so do not consider overrides for now
result.getUnderlyingCallable() = getCallableForDataFlow(call.getTarget())
}
override ControlFlow::Nodes::ElementNode getControlFlowNode() { none() }
override DataFlow::ExprNode getNode() { result.getExpr() = call }
override DataFlowCallable getEnclosingCallable() {
result.asCallable() = call.getEnclosingCallable()
}
override string toString() { result = call.toString() }
override Location getLocation() { result = call.getLocation() }
}
/**
* A synthesized call inside a callable with a flow summary.
*

View File

@@ -1,4 +1,6 @@
private import csharp
private import cil
private import dotnet
private import DataFlowPublic
private import DataFlowDispatch
private import DataFlowImplCommon
@@ -16,6 +18,8 @@ private import semmle.code.csharp.frameworks.NHibernate
private import semmle.code.csharp.frameworks.Razor
private import semmle.code.csharp.frameworks.system.Collections
private import semmle.code.csharp.frameworks.system.threading.Tasks
private import semmle.code.cil.Ssa::Ssa as CilSsa
private import semmle.code.cil.internal.SsaImpl as CilSsaImpl
private import codeql.util.Unit
private import codeql.util.Boolean
@@ -53,15 +57,15 @@ abstract class NodeImpl extends Node {
/** Do not call: use `getType()` instead. */
cached
abstract Type getTypeImpl();
abstract DotNet::Type getTypeImpl();
/** Gets the type of this node used for type pruning. */
DataFlowType getDataFlowType() {
forceCachingInSameStage() and
exists(Type t0 | result.asGvnType() = Gvn::getGlobalValueNumber(t0) |
t0 = this.getType()
t0 = getCSharpType(this.getType())
or
not exists(this.getType()) and
not exists(getCSharpType(this.getType())) and
t0 instanceof ObjectType
)
}
@@ -92,12 +96,16 @@ private DataFlowCallable getEnclosingStaticFieldOrProperty(Expr e) {
private class ExprNodeImpl extends ExprNode, NodeImpl {
override DataFlowCallable getEnclosingCallableImpl() {
result.asCallable() = this.getControlFlowNodeImpl().getEnclosingCallable()
result.asCallable() =
[
this.getExpr().(CIL::Expr).getEnclosingCallable().(DotNet::Callable),
this.getControlFlowNodeImpl().getEnclosingCallable()
]
or
result = getEnclosingStaticFieldOrProperty(this.asExpr())
}
override Type getTypeImpl() {
override DotNet::Type getTypeImpl() {
forceCachingInSameStage() and
result = this.getExpr().getType()
}
@@ -113,6 +121,11 @@ private class ExprNodeImpl extends ExprNode, NodeImpl {
override string toStringImpl() {
forceCachingInSameStage() and
result = this.getControlFlowNodeImpl().toString()
or
exists(CIL::Expr e |
this = TCilExprNode(e) and
result = e.toString()
)
}
}
@@ -135,7 +148,7 @@ abstract private class LocalFunctionCreationNode extends NodeImpl, TLocalFunctio
LocalFunction getFunction() { result = function }
ExprNode getAnAccess(boolean inSameCallable) {
isLocalFunctionCallReceiver(_, result.getExpr(), this.getFunction()) and
result.getExpr().(LocalFunctionAccess).getTarget() = this.getFunction() and
if result.getEnclosingCallable() = this.getEnclosingCallable()
then inSameCallable = true
else inSameCallable = false
@@ -247,6 +260,12 @@ predicate hasNodePath(ControlFlowReachabilityConfiguration conf, ExprNode n1, No
)
}
/** Gets the CIL data-flow node for `node`, if any. */
CIL::DataFlowNode asCilDataFlowNode(Node node) {
result = node.asParameter() or
result = node.asExpr()
}
/** Provides logic related to captured variables. */
module VariableCapture {
private import codeql.dataflow.VariableCapture as Shared
@@ -380,11 +399,7 @@ module VariableCapture {
predicate hasBody(Callable body) { body = c }
predicate hasAliasedAccess(Expr f) {
closureFlowStep+(this, f) and not closureFlowStep(f, _)
or
isLocalFunctionCallReceiver(_, f.getAstNode(), c)
}
predicate hasAliasedAccess(Expr f) { closureFlowStep+(this, f) and not closureFlowStep(f, _) }
}
class Callable extends Cs::Callable {
@@ -712,6 +727,79 @@ module LocalFlow {
)
}
private module CilFlow {
/**
* Holds if `nodeFrom` is a last node referencing SSA definition `def`, which
* can reach `next`.
*/
private predicate localFlowCilSsaInput(
Node nodeFrom, CilSsaImpl::DefinitionExt def, CilSsaImpl::DefinitionExt next
) {
exists(CIL::BasicBlock bb, int i | CilSsaImpl::lastRefBeforeRedefExt(def, bb, i, next) |
def.definesAt(_, bb, i, _) and
def = nodeFrom.(CilSsaDefinitionExtNode).getDefinition() and
def != next
or
nodeFrom = TCilExprNode(bb.getNode(i).(CIL::ReadAccess))
)
}
/**
* Holds if there is a local flow step from `nodeFrom` to `nodeTo` involving
* CIL SSA definition `def`.
*/
private predicate localCilSsaFlowStep(CilSsaImpl::DefinitionExt def, Node nodeFrom, Node nodeTo) {
// Flow into SSA definition
exists(CIL::VariableUpdate vu |
vu = def.(CilSsa::Definition).getVariableUpdate() and
vu.getSource() = asCilDataFlowNode(nodeFrom) and
def = nodeTo.(CilSsaDefinitionExtNode).getDefinition()
)
or
// Flow from SSA definition to first read
def = nodeFrom.(CilSsaDefinitionExtNode).getDefinition() and
nodeTo = TCilExprNode(CilSsaImpl::getAFirstReadExt(def))
or
// Flow from read to next read
exists(CIL::ReadAccess readFrom, CIL::ReadAccess readTo |
CilSsaImpl::hasAdjacentReadsExt(def, readFrom, readTo) and
nodeTo = TCilExprNode(readTo) and
nodeFrom = TCilExprNode(readFrom) and
nodeFrom != nodeTo
)
or
// Flow into phi (read) node
exists(CilSsaImpl::DefinitionExt phi |
localFlowCilSsaInput(nodeFrom, def, phi) and
phi = nodeTo.(CilSsaDefinitionExtNode).getDefinition()
|
phi instanceof CilSsa::PhiNode
or
phi instanceof CilSsaImpl::PhiReadNode
)
}
private predicate localExactStep(CIL::DataFlowNode src, CIL::DataFlowNode sink) {
src = sink.(CIL::Opcodes::Dup).getAnOperand()
or
src = sink.(CIL::Conversion).getExpr()
or
src = sink.(CIL::WriteAccess).getExpr()
or
src = sink.(CIL::Method).getAnImplementation().getAnInstruction().(CIL::Return)
or
src = sink.(CIL::Return).getExpr()
or
src = sink.(CIL::ConditionalBranch).getAnOperand()
}
predicate localFlowStepCil(Node nodeFrom, Node nodeTo) {
localExactStep(asCilDataFlowNode(nodeFrom), asCilDataFlowNode(nodeTo))
or
localCilSsaFlowStep(_, nodeFrom, nodeTo)
}
}
predicate localFlowStepCommon(Node nodeFrom, Node nodeTo) {
hasNodePath(any(LocalExprStepConfiguration x), nodeFrom, nodeTo)
or
@@ -720,6 +808,8 @@ module LocalFlow {
or
ThisFlow::adjacentThisRefs(nodeFrom.(PostUpdateNode).getPreUpdateNode(), nodeTo)
or
CilFlow::localFlowStepCil(nodeFrom, nodeTo)
or
exists(AssignableDefinition def, ControlFlow::Node cfn, Ssa::ExplicitDefinition ssaDef |
ssaDef.getADefinition() = def and
ssaDef.getControlFlowNode() = cfn and
@@ -791,7 +881,7 @@ module LocalFlow {
exists(SsaImpl::getAReadAtNode(def, node2.(ExprNode).getControlFlowNode()))
)
or
node2 = node1.(LocalFunctionCreationNode).getAnAccess(true)
delegateCreationStep(node1, node2)
or
node1 =
unique(FlowSummaryNode n1 |
@@ -1021,6 +1111,13 @@ private predicate arrayStore(Expr e, Expr src, Expr a, boolean postUpdate) {
*/
private predicate arrayRead(Expr e1, ArrayRead e2) { e1 = e2.getQualifier() }
private Type getCSharpType(DotNet::Type t) {
result = t
or
not t instanceof Type and
result.matchesHandle(t)
}
private class RelevantGvnType extends Gvn::GvnType {
RelevantGvnType() { this = any(NodeImpl n).getDataFlowType().asGvnType() }
}
@@ -1092,6 +1189,8 @@ private module Cached {
cached
newtype TNode =
TExprNode(ControlFlow::Nodes::ElementNode cfn) { cfn.getAstNode() instanceof Expr } or
TCilExprNode(CIL::Expr e) { e.getImplementation() instanceof CIL::BestImplementation } or
TCilSsaDefinitionExtNode(CilSsaImpl::DefinitionExt def) or
TSsaDefinitionExtNode(SsaImpl::DefinitionExt def) {
// Handled by `TExplicitParameterNode` below
not def.(Ssa::ExplicitDefinition).getADefinition() instanceof
@@ -1102,7 +1201,7 @@ private module Cached {
// Handled by `TExplicitParameterNode` below
not def instanceof AssignableDefinitions::ImplicitParameterDefinition
} or
TExplicitParameterNode(Parameter p) {
TExplicitParameterNode(DotNet::Parameter p) {
p = any(DataFlowCallable dfc).asCallable().getAParameter()
} or
TInstanceParameterNode(InstanceCallable c) or
@@ -1272,6 +1371,28 @@ predicate nodeIsHidden(Node n) {
n instanceof CaptureNode
}
/** A CIL SSA definition, viewed as a node in a data flow graph. */
class CilSsaDefinitionExtNode extends NodeImpl, TCilSsaDefinitionExtNode {
CilSsaImpl::DefinitionExt def;
CilSsaDefinitionExtNode() { this = TCilSsaDefinitionExtNode(def) }
/** Gets the underlying SSA definition. */
CilSsaImpl::DefinitionExt getDefinition() { result = def }
override DataFlowCallable getEnclosingCallableImpl() {
result.asCallable() = def.getBasicBlock().getFirstNode().getImplementation().getMethod()
}
override CIL::Type getTypeImpl() { result = def.getSourceVariable().getType() }
override ControlFlow::Node getControlFlowNodeImpl() { none() }
override Location getLocationImpl() { result = def.getBasicBlock().getLocation() }
override string toStringImpl() { result = def.toString() }
}
/** An SSA definition, viewed as a node in a data flow graph. */
class SsaDefinitionExtNode extends NodeImpl, TSsaDefinitionExtNode {
SsaImpl::DefinitionExt def;
@@ -1343,7 +1464,7 @@ private module ParameterNodes {
* flow graph.
*/
class ExplicitParameterNode extends ParameterNodeImpl, TExplicitParameterNode {
private Parameter parameter;
private DotNet::Parameter parameter;
ExplicitParameterNode() { this = TExplicitParameterNode(parameter) }
@@ -1361,7 +1482,7 @@ private module ParameterNodes {
result.asCallable() = parameter.getCallable()
}
override Type getTypeImpl() { result = parameter.getType() }
override DotNet::Type getTypeImpl() { result = parameter.getType() }
override ControlFlow::Node getControlFlowNodeImpl() { none() }
@@ -1418,7 +1539,7 @@ private module ParameterNodes {
override Location getLocationImpl() { result = callable.getLocation() }
override Type getTypeImpl() { none() }
override DotNet::Type getTypeImpl() { none() }
override DataFlowType getDataFlowType() { callable = result.asDelegate() }
@@ -1487,7 +1608,11 @@ private module ArgumentNodes {
/** A data-flow node that represents an explicit call argument. */
class ExplicitArgumentNode extends ArgumentNodeImpl {
ExplicitArgumentNode() { this.asExpr() instanceof Argument }
ExplicitArgumentNode() {
this.asExpr() instanceof Argument
or
this.asExpr() = any(CilDataFlowCall cc).getCilCall().getAnArgument()
}
override predicate argumentOf(DataFlowCall call, ArgumentPosition pos) {
exists(ArgumentConfiguration x, Expr c, Argument arg |
@@ -1496,6 +1621,12 @@ private module ArgumentNodes {
arg.isArgumentOf(c, pos) and
x.hasExprPath(_, this.getControlFlowNode(), _, call.getControlFlowNode())
)
or
exists(CIL::Call c, CIL::Expr arg |
arg = this.asExpr() and
c = call.getExpr() and
arg = c.getArgument(pos.getPosition())
)
}
}
@@ -1612,7 +1743,7 @@ private module ReturnNodes {
*/
class ExprReturnNode extends ReturnNode, ExprNode {
ExprReturnNode() {
exists(Callable c, Expr e | e = this.getExpr() |
exists(DotNet::Callable c, DotNet::Expr e | e = this.getExpr() |
c.canReturn(e) and not c.(Modifiable).isAsync()
)
}
@@ -1746,13 +1877,17 @@ private module OutNodes {
}
/**
* A data-flow node that reads a value returned directly by a callable.
* A data-flow node that reads a value returned directly by a callable,
* either via a C# call or a CIL call.
*/
class ExprOutNode extends OutNode, ExprNode {
private DataFlowCall call;
ExprOutNode() {
exists(Expr e | e = this.getExpr() | call = csharpCall(e, this.getControlFlowNode()))
exists(DotNet::Expr e | e = this.getExpr() |
call = csharpCall(e, this.getControlFlowNode()) or
call = TCilCall(e)
)
}
override DataFlowCall getCall(ReturnKind kind) {
@@ -1834,7 +1969,7 @@ class FlowSummaryNode extends NodeImpl, TFlowSummaryNode {
result = FlowSummaryImpl::Private::summaryNodeType(this.getSummaryNode())
}
override Type getTypeImpl() { none() }
override DotNet::Type getTypeImpl() { none() }
override ControlFlow::Node getControlFlowNodeImpl() { none() }
@@ -1995,6 +2130,8 @@ class FieldOrProperty extends Assignable, Modifiable {
or
p.isAutoImplementedReadOnly()
or
p.matchesHandle(any(CIL::TrivialProperty tp))
or
p.getDeclaringType() instanceof AnonymousClass
)
)
@@ -2412,10 +2549,9 @@ class DataFlowType extends TDataFlowType {
* creations associated with the same type.
*/
ControlFlowElement getADelegateCreation() {
exists(Callable callable | this = TDelegateDataFlowType(callable) |
lambdaCreationExpr(result, callable)
or
isLocalFunctionCallReceiver(_, result, callable)
exists(Callable callable |
lambdaCreationExpr(result, callable) and
this = TDelegateDataFlowType(callable)
)
}
@@ -2430,7 +2566,12 @@ class DataFlowType extends TDataFlowType {
DataFlowType getNodeType(Node n) {
result = n.(NodeImpl).getDataFlowType() and
not lambdaCreation(n, _, _) and
not isLocalFunctionCallReceiver(_, n.asExpr(), _)
not delegateCreationStep(_, n)
or
exists(Node arg |
delegateCreationStep(arg, n) and
result = getNodeType(arg)
)
or
[
n.asExpr().(ControlFlowElement),
@@ -2599,7 +2740,7 @@ module PostUpdateNodes {
result = getEnclosingStaticFieldOrProperty(oc)
}
override Type getTypeImpl() { result = oc.getType() }
override DotNet::Type getTypeImpl() { result = oc.getType() }
override ControlFlow::Nodes::ElementNode getControlFlowNodeImpl() { result = cfn }
@@ -2712,7 +2853,7 @@ class CastNode extends Node {
}
}
class DataFlowExpr = Expr;
class DataFlowExpr = DotNet::Expr;
/** Holds if `e` is an expression that always has the same Boolean value `val`. */
private predicate constantBooleanExpr(Expr e, boolean val) {
@@ -2755,7 +2896,7 @@ private predicate lambdaCreationExpr(ControlFlowElement creation, Callable c) {
c =
[
creation.(AnonymousFunctionExpr),
creation.(DelegateCreation).getArgument().(CallableAccess).getTarget().getUnboundDeclaration(),
creation.(CallableAccess).getTarget().getUnboundDeclaration(),
creation.(AddressOfExpr).getOperand().(CallableAccess).getTarget().getUnboundDeclaration(),
creation.(LocalFunctionStmt).getLocalFunction()
]
@@ -2769,13 +2910,6 @@ predicate lambdaCreation(Node creation, LambdaCallKind kind, DataFlowCallable c)
exists(kind)
}
private predicate isLocalFunctionCallReceiver(
LocalFunctionCall call, LocalFunctionAccess receiver, LocalFunction f
) {
receiver.getParent() = call and
f = receiver.getTarget().getUnboundDeclaration()
}
private class LambdaConfiguration extends ControlFlowReachabilityConfiguration {
LambdaConfiguration() { this = "LambdaConfiguration" }
@@ -2792,7 +2926,7 @@ private class LambdaConfiguration extends ControlFlowReachabilityConfiguration {
scope = e2 and
isSuccessor = true
or
isLocalFunctionCallReceiver(e2, e1, _) and
e1.(LocalFunctionAccess).getParent() = e2.(LocalFunctionCall) and
exactScope = false and
scope = e2 and
isSuccessor = true

View File

@@ -1,4 +1,6 @@
private import csharp
private import cil
private import dotnet
private import DataFlowDispatch
private import DataFlowPrivate
private import semmle.code.csharp.controlflow.Guards
@@ -10,7 +12,7 @@ private import semmle.code.csharp.Unification
*/
class Node extends TNode {
/** Gets the expression corresponding to this node, if any. */
Expr asExpr() { result = this.(ExprNode).getExpr() }
DotNet::Expr asExpr() { result = this.(ExprNode).getExpr() }
/**
* Gets the expression corresponding to this node, at control flow node `cfn`,
@@ -21,7 +23,7 @@ class Node extends TNode {
}
/** Gets the parameter corresponding to this node, if any. */
Parameter asParameter() { result = this.(ParameterNode).getParameter() }
DotNet::Parameter asParameter() { result = this.(ParameterNode).getParameter() }
/** Gets the definition corresponding to this node, if any. */
AssignableDefinition asDefinition() { result = this.asDefinitionAtNode(_) }
@@ -35,7 +37,7 @@ class Node extends TNode {
}
/** Gets the type of this node. */
final Type getType() { result = this.(NodeImpl).getTypeImpl() }
final DotNet::Type getType() { result = this.(NodeImpl).getTypeImpl() }
/** Gets the enclosing callable of this node. */
final Callable getEnclosingCallable() {
@@ -65,6 +67,8 @@ class Node extends TNode {
}
}
private class TExprNode_ = TExprNode or TCilExprNode;
/**
* An expression, viewed as a node in a data flow graph.
*
@@ -72,9 +76,13 @@ class Node extends TNode {
* to multiple `ExprNode`s, just like it may correspond to multiple
* `ControlFlow::Node`s.
*/
class ExprNode extends Node, TExprNode {
class ExprNode extends Node, TExprNode_ {
/** Gets the expression corresponding to this node. */
Expr getExpr() { result = this.getExprAtNode(_) }
DotNet::Expr getExpr() {
result = this.getExprAtNode(_)
or
this = TCilExprNode(result)
}
/**
* Gets the expression corresponding to this node, at control flow node `cfn`,
@@ -86,22 +94,16 @@ class ExprNode extends Node, TExprNode {
}
}
pragma[nomagic]
private predicate isParameterOf0(DataFlowCallable c, ParameterPosition ppos, Parameter p) {
p.getCallable() = c.asCallable() and
p.getPosition() = ppos.getPosition()
}
/**
* The value of a parameter at function entry, viewed as a node in a data
* flow graph.
*/
class ParameterNode extends Node instanceof ParameterNodeImpl {
/** Gets the parameter corresponding to this node, if any. */
Parameter getParameter() {
DotNet::Parameter getParameter() {
exists(DataFlowCallable c, ParameterPosition ppos |
super.isParameterOf(c, ppos) and
isParameterOf0(c, ppos, result)
result = c.asCallable().getParameter(ppos.getPosition())
)
}
}
@@ -118,12 +120,12 @@ class AssignableDefinitionNode extends Node instanceof AssignableDefinitionNodeI
}
/** Gets a node corresponding to expression `e`. */
ExprNode exprNode(Expr e) { result.getExpr() = e }
ExprNode exprNode(DotNet::Expr e) { result.getExpr() = e }
/**
* Gets the node corresponding to the value of parameter `p` at function entry.
*/
ParameterNode parameterNode(Parameter p) { result.getParameter() = p }
ParameterNode parameterNode(DotNet::Parameter p) { result.getParameter() = p }
/** Gets a node corresponding to the definition `def`. */
AssignableDefinitionNode assignableDefinitionNode(AssignableDefinition def) {
@@ -144,7 +146,7 @@ predicate localFlow(Node source, Node sink) { localFlowStep*(source, sink) }
* local (intra-procedural) steps.
*/
pragma[inline]
predicate localExprFlow(Expr e1, Expr e2) { localFlow(exprNode(e1), exprNode(e2)) }
predicate localExprFlow(DotNet::Expr e1, DotNet::Expr e2) { localFlow(exprNode(e1), exprNode(e2)) }
/**
* A data flow node that jumps between callables. This can be extended in

View File

@@ -7,6 +7,8 @@ private import semmle.code.csharp.dataflow.internal.DataFlowPrivate
private import semmle.code.csharp.dataflow.internal.ControlFlowReachability
private import semmle.code.csharp.dispatch.Dispatch
private import semmle.code.csharp.commons.ComparisonTest
private import cil
private import dotnet
// import `TaintedMember` definitions from other files to avoid potential reevaluation
private import semmle.code.csharp.frameworks.JsonNET
private import semmle.code.csharp.frameworks.WCF
@@ -31,6 +33,16 @@ predicate defaultTaintSanitizer(DataFlow::Node node) {
bindingset[node]
predicate defaultImplicitTaintRead(DataFlow::Node node, DataFlow::ContentSet c) { none() }
private predicate localCilTaintStep(CIL::DataFlowNode src, CIL::DataFlowNode sink) {
src = sink.(CIL::BinaryArithmeticExpr).getAnOperand() or
src = sink.(CIL::Opcodes::Neg).getOperand() or
src = sink.(CIL::UnaryBitwiseOperation).getOperand()
}
private predicate localTaintStepCil(DataFlow::Node nodeFrom, DataFlow::Node nodeTo) {
localCilTaintStep(asCilDataFlowNode(nodeFrom), asCilDataFlowNode(nodeTo))
}
private class LocalTaintExprStepConfiguration extends ControlFlowReachabilityConfiguration {
LocalTaintExprStepConfiguration() { this = "LocalTaintExprStepConfiguration" }
@@ -94,6 +106,8 @@ private class LocalTaintExprStepConfiguration extends ControlFlowReachabilityCon
private predicate localTaintStepCommon(DataFlow::Node nodeFrom, DataFlow::Node nodeTo) {
hasNodePath(any(LocalTaintExprStepConfiguration x), nodeFrom, nodeTo)
or
localTaintStepCil(nodeFrom, nodeTo)
}
cached

View File

@@ -5,12 +5,14 @@
*/
import csharp
private import cil
private import dotnet
/**
* A run-time callable. That is, a callable that is neither abstract
* nor defined in an interface.
*/
class RuntimeCallable extends Callable {
class RuntimeCallable extends DotNet::Callable {
RuntimeCallable() {
not this.(Modifiable).isAbstract() and
(
@@ -21,7 +23,15 @@ class RuntimeCallable extends Callable {
}
/** A run-time method. */
class RuntimeMethod extends RuntimeCallable, Method { }
class RuntimeMethod extends RuntimeCallable {
RuntimeMethod() {
this instanceof Method or
this instanceof CIL::Method
}
/** Holds if the method is `static`. */
predicate isStatic() { this.(Method).isStatic() or this.(CIL::Method).isStatic() }
}
/** A run-time instance method. */
class RuntimeInstanceMethod extends RuntimeMethod {

View File

@@ -8,6 +8,7 @@ import Expr
private import semmle.code.csharp.dataflow.internal.DataFlowDispatch
private import semmle.code.csharp.dataflow.internal.DataFlowImplCommon
private import semmle.code.csharp.dispatch.Dispatch
private import dotnet
/**
* A call. Either a method call (`MethodCall`), a constructor initializer call
@@ -15,7 +16,7 @@ private import semmle.code.csharp.dispatch.Dispatch
* a delegate call (`DelegateCall`), an accessor call (`AccessorCall`), a
* constructor call (`ObjectCreation`), or a local function call (`LocalFunctionCall`).
*/
class Call extends Expr, @call {
class Call extends DotNet::Call, Expr, @call {
/**
* Gets the static (compile-time) target of this call. For example, the
* static target of `x.M()` on line 9 is `A.M` in
@@ -37,19 +38,13 @@ class Call extends Expr, @call {
* Use `getARuntimeTarget()` instead to get a potential run-time target (will
* include `B.M` in the example above).
*/
Callable getTarget() { none() }
override Callable getTarget() { none() }
/** Gets the `i`th argument to this call, if any. */
Expr getArgument(int i) { result = this.getChild(i) and i >= 0 }
override Expr getArgument(int i) { result = this.getChild(i) and i >= 0 }
/**
* Gets the `i`th "raw" argument to this call, if any.
* For instance methods, argument 0 is the qualifier.
*/
Expr getRawArgument(int i) { result = this.getArgument(i) }
override Expr getRawArgument(int i) { result = this.getArgument(i) }
/** Gets an argument to this call. */
Expr getAnArgument() { result = this.getArgument(_) }
override Expr getAnArgument() { result = this.getArgument(_) }
/** Gets the number of arguments of this call. */
int getNumberOfArguments() { result = count(this.getAnArgument()) }
@@ -64,7 +59,7 @@ class Call extends Expr, @call {
* consider default arguments.
*/
cached
Expr getArgumentForParameter(Parameter p) {
override Expr getArgumentForParameter(DotNet::Parameter p) {
// Appears in the positional part of the call
result = this.getImplicitArgument(p)
or
@@ -74,7 +69,7 @@ class Call extends Expr, @call {
}
pragma[noinline]
private Expr getImplicitArgument(Parameter p) {
private Expr getImplicitArgument(DotNet::Parameter p) {
this.getTarget().getAParameter() = p and
not exists(result.getExplicitArgumentName()) and
(
@@ -149,7 +144,7 @@ class Call extends Expr, @call {
* - Line 16: There is no static target (delegate call) but the delegate `i => { }`
* (line 20) is a run-time target.
*/
Callable getARuntimeTarget() {
override Callable getARuntimeTarget() {
exists(DispatchCall dc | dc.getCall() = this | result = dc.getADynamicTarget())
}

View File

@@ -18,6 +18,7 @@ import semmle.code.csharp.controlflow.ControlFlowElement
import semmle.code.csharp.Location
import semmle.code.csharp.Stmt
import semmle.code.csharp.Type
private import dotnet
private import semmle.code.csharp.ExprOrStmtParent
private import semmle.code.csharp.frameworks.System
private import semmle.code.csharp.TypeRef
@@ -37,11 +38,11 @@ private import semmle.code.csharp.TypeRef
* interpolated string (`InterpolatedStringExpr`), a qualifiable expression
* (`QualifiableExpr`), or a literal (`Literal`).
*/
class Expr extends ControlFlowElement, @expr {
class Expr extends DotNet::Expr, ControlFlowElement, @expr {
override Location getALocation() { expr_location(this, result) }
/** Gets the type of this expression. */
Type getType() {
override Type getType() {
expressions(this, _, result)
or
not expressions(this, _, any(Type t)) and
@@ -52,10 +53,7 @@ class Expr extends ControlFlowElement, @expr {
final AnnotatedType getAnnotatedType() { result.appliesTo(this) }
/** Gets the value of this expression, if any */
string getValue() { expr_value(this, result) }
/** Holds if this expression has a value. */
final predicate hasValue() { exists(this.getValue()) }
override string getValue() { expr_value(this, result) }
/** Gets the enclosing statement of this expression, if any. */
final Stmt getEnclosingStmt() { enclosingStmt(this, result) }
@@ -90,10 +88,6 @@ class Expr extends ControlFlowElement, @expr {
*/
string getExplicitArgumentName() { expr_argument_name(this, result) }
/**
* Gets the parent of this expression. This is for example the element
* that uses the result of this expression.
*/
override Element getParent() { result = ControlFlowElement.super.getParent() }
/** Holds if the nullable flow state of this expression is not null. */
@@ -949,13 +943,13 @@ class InterpolatedStringExpr extends Expr, @interpolated_string_expr {
* A `throw` element. Either a `throw` expression (`ThrowExpr`)
* or a `throw` statement (`ThrowStmt`).
*/
class ThrowElement extends ControlFlowElement, @throw_element {
class ThrowElement extends ControlFlowElement, DotNet::Throw, @throw_element {
/**
* Gets the expression of the exception being thrown, if any.
*
* For example, `new Exception("Syntax error")` in `throw new Exception("Syntax error");`.
*/
Expr getExpr() { result = this.getChild(0) }
override Expr getExpr() { result = this.getChild(0) }
/** Gets the type of exception being thrown. */
Class getThrownExceptionType() {

Some files were not shown because too many files have changed in this diff Show More