Compare commits

..

3 Commits

Author SHA1 Message Date
Jean Helie
fe190a60e9 rename yml to include .model so it's correctly picked-up 2023-06-28 10:39:11 +02:00
Jean Helie
b2b445f1e9 use generated modles following tiny prompt fix 2023-06-27 16:12:57 +02:00
Jean Helie
3fbbdae9f6 add LLM generated sinks for spring-framework 2023-06-20 15:19:50 +02:00
1511 changed files with 26520 additions and 47379 deletions

View File

@@ -1,9 +1,3 @@
common --enable_platform_specific_config
build --repo_env=CC=clang --repo_env=CXX=clang++
build:linux --cxxopt=-std=c++20
build:macos --cxxopt=-std=c++20 --cpu=darwin_x86_64
build:windows --cxxopt=/std:c++20 --cxxopt=/Zc:preprocessor
build --repo_env=CC=clang --repo_env=CXX=clang++ --cxxopt="-std=c++17"
try-import %workspace%/local.bazelrc

View File

@@ -10,7 +10,6 @@ on:
- "*/ql/src/**/*.qll"
- "*/ql/lib/**/*.ql"
- "*/ql/lib/**/*.qll"
- "*/ql/lib/ext/**/*.yml"
- "misc/scripts/library-coverage/*.py"
# input data files
- "*/documentation/library-coverage/cwe-sink.csv"

View File

@@ -523,10 +523,6 @@
"python/ql/lib/semmle/python/dataflow/new/internal/TypeTracker.qll",
"ruby/ql/lib/codeql/ruby/typetracking/TypeTracker.qll"
],
"SummaryTypeTracker": [
"python/ql/lib/semmle/python/dataflow/new/internal/SummaryTypeTracker.qll",
"ruby/ql/lib/codeql/ruby/typetracking/internal/SummaryTypeTracker.qll"
],
"AccessPathSyntax": [
"csharp/ql/lib/semmle/code/csharp/dataflow/internal/AccessPathSyntax.qll",
"go/ql/lib/semmle/go/dataflow/internal/AccessPathSyntax.qll",

View File

@@ -1,11 +1,3 @@
## 0.7.3
### Minor Analysis Improvements
* Deleted the deprecated `hasCopyConstructor` predicate from the `Class` class in `Class.qll`.
* Deleted many deprecated predicates and classes with uppercase `AST`, `SSA`, `CFG`, `API`, etc. in their names. Use the PascalCased versions instead.
* Deleted the deprecated `CodeDuplication.qll` file.
## 0.7.2
### New Features

View File

@@ -1,4 +0,0 @@
---
category: minorAnalysis
---
* Deleted the deprecated `getURL` predicate from the `Container`, `Folder`, and `File` classes. Use the `getLocation` predicate instead.

View File

@@ -1,7 +0,0 @@
## 0.7.3
### Minor Analysis Improvements
* Deleted the deprecated `hasCopyConstructor` predicate from the `Class` class in `Class.qll`.
* Deleted many deprecated predicates and classes with uppercase `AST`, `SSA`, `CFG`, `API`, etc. in their names. Use the PascalCased versions instead.
* Deleted the deprecated `CodeDuplication.qll` file.

View File

@@ -1,2 +1,2 @@
---
lastReleaseVersion: 0.7.3
lastReleaseVersion: 0.7.2

View File

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

View File

@@ -176,6 +176,20 @@ class Class extends UserType {
/** Holds if this class, struct or union has a constructor. */
predicate hasConstructor() { exists(this.getAConstructor()) }
/**
* Holds if this class has a copy constructor that is either explicitly
* declared (though possibly `= delete`) or is auto-generated, non-trivial
* and called from somewhere.
*
* DEPRECATED: There is more than one reasonable definition of what it means
* to have a copy constructor, and we do not want to promote one particular
* definition by naming it with this predicate. Having a copy constructor
* could mean that such a member is declared or defined in the source or that
* it is callable by a particular caller. For C++11, there's also a question
* of whether to include members that are defaulted or deleted.
*/
deprecated predicate hasCopyConstructor() { this.getAMemberFunction() instanceof CopyConstructor }
/**
* Like accessOfBaseMember but returns multiple results if there are multiple
* paths to `base` through the inheritance graph.

View File

@@ -34,6 +34,14 @@ class Container extends Locatable, @container {
*/
string getAbsolutePath() { none() } // overridden by subclasses
/**
* DEPRECATED: Use `getLocation` instead.
* Gets a URL representing the location of this container.
*
* For more information see [Providing URLs](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/#providing-urls).
*/
deprecated string getURL() { none() } // overridden by subclasses
/**
* Gets the relative path of this file or folder from the root folder of the
* analyzed source location. The relative path of the root folder itself is
@@ -175,6 +183,12 @@ class Folder extends Container, @folder {
}
override string getAPrimaryQlClass() { result = "Folder" }
/**
* DEPRECATED: Use `getLocation` instead.
* Gets the URL of this folder.
*/
deprecated override string getURL() { result = "file://" + this.getAbsolutePath() + ":0:0:0:0" }
}
/**
@@ -199,6 +213,12 @@ class File extends Container, @file {
result.hasLocationInfo(_, 0, 0, 0, 0)
}
/**
* DEPRECATED: Use `getLocation` instead.
* Gets the URL of this file.
*/
deprecated override string getURL() { result = "file://" + this.getAbsolutePath() + ":0:0:0:0" }
/** Holds if this file was compiled as C (at any point). */
predicate compiledAsC() { fileannotations(underlyingElement(this), 1, "compiled as c", "1") }

View File

@@ -27,6 +27,9 @@ class PrintAstConfiguration extends TPrintAstConfiguration {
predicate shouldPrintFunction(Function func) { any() }
}
/** DEPRECATED: Alias for PrintAstConfiguration */
deprecated class PrintASTConfiguration = PrintAstConfiguration;
private predicate shouldPrintFunction(Function func) {
exists(PrintAstConfiguration config | config.shouldPrintFunction(func))
}
@@ -236,6 +239,9 @@ class PrintAstNode extends TPrintAstNode {
}
}
/** DEPRECATED: Alias for PrintAstNode */
deprecated class PrintASTNode = PrintAstNode;
/**
* Class that restricts the elements that we compute `qlClass` for.
*/
@@ -280,6 +286,9 @@ abstract class BaseAstNode extends PrintAstNode {
deprecated Locatable getAST() { result = this.getAst() }
}
/** DEPRECATED: Alias for BaseAstNode */
deprecated class BaseASTNode = BaseAstNode;
/**
* A node representing an AST node other than a `DeclarationEntry`.
*/
@@ -287,6 +296,9 @@ abstract class AstNode extends BaseAstNode, TAstNode {
AstNode() { this = TAstNode(ast) }
}
/** DEPRECATED: Alias for AstNode */
deprecated class ASTNode = AstNode;
/**
* A node representing an `Expr`.
*/

View File

@@ -14,6 +14,9 @@ library class StandardSsa extends SsaHelper {
StandardSsa() { this = 0 }
}
/** DEPRECATED: Alias for StandardSsa */
deprecated class StandardSSA = StandardSsa;
/**
* A definition of one or more SSA variables, including phi node definitions.
* An _SSA variable_, as defined in the literature, is effectively the pair of

View File

@@ -312,3 +312,6 @@ library class SsaHelper extends int {
ssa_use(v, result, _, _)
}
}
/** DEPRECATED: Alias for SsaHelper */
deprecated class SSAHelper = SsaHelper;

View File

@@ -1385,6 +1385,9 @@ private module Cached {
conditionalSuccessor(n1, _, n2)
}
/** DEPRECATED: Alias for qlCfgSuccessor */
deprecated predicate qlCFGSuccessor = qlCfgSuccessor/2;
/**
* Holds if `n2` is a control-flow node such that the control-flow
* edge `(n1, n2)` may be taken when `n1` is an expression that is true.
@@ -1395,6 +1398,9 @@ private module Cached {
not conditionalSuccessor(n1, false, n2)
}
/** DEPRECATED: Alias for qlCfgTrueSuccessor */
deprecated predicate qlCFGTrueSuccessor = qlCfgTrueSuccessor/2;
/**
* Holds if `n2` is a control-flow node such that the control-flow
* edge `(n1, n2)` may be taken when `n1` is an expression that is false.
@@ -1404,4 +1410,7 @@ private module Cached {
conditionalSuccessor(n1, false, n2) and
not conditionalSuccessor(n1, true, n2)
}
/** DEPRECATED: Alias for qlCfgFalseSuccessor */
deprecated predicate qlCFGFalseSuccessor = qlCfgFalseSuccessor/2;
}

View File

@@ -1135,8 +1135,8 @@ module Impl<FullStateConfigSig Config> {
DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow
);
bindingset[node, state, t0, ap]
predicate filter(NodeEx node, FlowState state, Typ t0, Ap ap, Typ t);
bindingset[node, state, t, ap]
predicate filter(NodeEx node, FlowState state, Typ t, Ap ap);
bindingset[typ, contentType]
predicate typecheckStore(Typ typ, DataFlowType contentType);
@@ -1199,21 +1199,17 @@ module Impl<FullStateConfigSig Config> {
NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, TypOption argT,
ApOption argAp, Typ t, Ap ap, ApApprox apa
) {
fwdFlow1(node, state, cc, summaryCtx, argT, argAp, _, t, ap, apa)
}
private predicate fwdFlow1(
NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, TypOption argT,
ApOption argAp, Typ t0, Typ t, Ap ap, ApApprox apa
) {
fwdFlow0(node, state, cc, summaryCtx, argT, argAp, t0, ap, apa) and
fwdFlow0(node, state, cc, summaryCtx, argT, argAp, t, ap, apa) and
PrevStage::revFlow(node, state, apa) and
filter(node, state, t0, ap, t)
filter(node, state, t, ap)
}
pragma[nomagic]
private predicate typeStrengthen(Typ t0, Ap ap, Typ t) {
fwdFlow1(_, _, _, _, _, _, t0, t, ap, _) and t0 != t
pragma[inline]
additional predicate fwdFlow(
NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, TypOption argT,
ApOption argAp, Typ t, Ap ap
) {
fwdFlow(node, state, cc, summaryCtx, argT, argAp, t, ap, _)
}
pragma[assume_small_delta]
@@ -1343,11 +1339,6 @@ module Impl<FullStateConfigSig Config> {
private predicate fwdFlowConsCand(Typ t2, Ap cons, Content c, Typ t1, Ap tail) {
fwdFlowStore(_, t1, tail, c, t2, _, _, _, _, _, _) and
cons = apCons(c, t1, tail)
or
exists(Typ t0 |
typeStrengthen(t0, cons, t2) and
fwdFlowConsCand(t0, cons, c, t1, tail)
)
}
pragma[nomagic]
@@ -1368,7 +1359,7 @@ module Impl<FullStateConfigSig Config> {
ParamNodeOption summaryCtx, TypOption argT, ApOption argAp
) {
exists(ApHeadContent apc |
fwdFlow(node1, state, cc, summaryCtx, argT, argAp, t, ap, _) and
fwdFlow(node1, state, cc, summaryCtx, argT, argAp, t, ap) and
apc = getHeadContent(ap) and
readStepCand0(node1, apc, c, node2)
)
@@ -1529,14 +1520,14 @@ module Impl<FullStateConfigSig Config> {
NodeEx node, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap
) {
revFlow0(node, state, returnCtx, returnAp, ap) and
fwdFlow(node, state, _, _, _, _, _, ap, _)
fwdFlow(node, state, _, _, _, _, _, ap)
}
pragma[nomagic]
private predicate revFlow0(
NodeEx node, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap
) {
fwdFlow(node, state, _, _, _, _, _, ap, _) and
fwdFlow(node, state, _, _, _, _, _, ap) and
sinkNode(node, state) and
(
if hasSinkCallCtx()
@@ -1789,13 +1780,13 @@ module Impl<FullStateConfigSig Config> {
boolean fwd, int nodes, int fields, int conscand, int states, int tuples
) {
fwd = true and
nodes = count(NodeEx node | fwdFlow(node, _, _, _, _, _, _, _, _)) and
nodes = count(NodeEx node | fwdFlow(node, _, _, _, _, _, _, _)) and
fields = count(Content f0 | fwdConsCand(f0, _, _)) and
conscand = count(Content f0, Typ t, Ap ap | fwdConsCand(f0, t, ap)) and
states = count(FlowState state | fwdFlow(_, state, _, _, _, _, _, _, _)) and
states = count(FlowState state | fwdFlow(_, state, _, _, _, _, _, _)) and
tuples =
count(NodeEx n, FlowState state, Cc cc, ParamNodeOption summaryCtx, TypOption argT,
ApOption argAp, Typ t, Ap ap | fwdFlow(n, state, cc, summaryCtx, argT, argAp, t, ap, _))
ApOption argAp, Typ t, Ap ap | fwdFlow(n, state, cc, summaryCtx, argT, argAp, t, ap))
or
fwd = false and
nodes = count(NodeEx node | revFlow(node, _, _, _, _)) and
@@ -1972,10 +1963,10 @@ module Impl<FullStateConfigSig Config> {
)
}
bindingset[node, state, t0, ap]
predicate filter(NodeEx node, FlowState state, Typ t0, Ap ap, Typ t) {
bindingset[node, state, t, ap]
predicate filter(NodeEx node, FlowState state, Typ t, Ap ap) {
PrevStage::revFlowState(state) and
t0 = t and
exists(t) and
exists(ap) and
not stateBarrier(node, state) and
(
@@ -2021,8 +2012,7 @@ module Impl<FullStateConfigSig Config> {
FlowCheckNode() {
castNode(this.asNode()) or
clearsContentCached(this.asNode(), _) or
expectsContentCached(this.asNode(), _) or
neverSkipInPathGraph(this.asNode())
expectsContentCached(this.asNode(), _)
}
}
@@ -2207,8 +2197,8 @@ module Impl<FullStateConfigSig Config> {
import BooleanCallContext
predicate localStep(
NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, Typ t,
LocalCc lcc
NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue,
DataFlowType t, LocalCc lcc
) {
localFlowBigStep(node1, state1, node2, state2, preservesValue, t, _) and
exists(lcc)
@@ -2228,16 +2218,10 @@ module Impl<FullStateConfigSig Config> {
)
}
bindingset[node, state, t0, ap]
predicate filter(NodeEx node, FlowState state, Typ t0, Ap ap, Typ t) {
bindingset[node, state, t, ap]
predicate filter(NodeEx node, FlowState state, Typ t, Ap ap) {
exists(state) and
// We can get away with not using type strengthening here, since we aren't
// going to use the tracked types in the construction of Stage 4 access
// paths. For Stage 4 and onwards, the tracked types must be consistent as
// the cons candidates including types are used to construct subsequent
// access path approximations.
t0 = t and
(if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), t0) else any()) and
(if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), t) else any()) and
(
notExpectsContent(node)
or
@@ -2257,16 +2241,6 @@ module Impl<FullStateConfigSig Config> {
import MkStage<Stage2>::Stage<Stage3Param>
}
bindingset[node, t0]
private predicate strengthenType(NodeEx node, DataFlowType t0, DataFlowType t) {
if castingNodeEx(node)
then
exists(DataFlowType nt | nt = node.getDataFlowType() |
if typeStrongerThan(nt, t0) then t = nt else (compatibleTypes(nt, t0) and t = t0)
)
else t = t0
}
private module Stage4Param implements MkStage<Stage3>::StageParam {
private module PrevStage = Stage3;
@@ -2300,8 +2274,8 @@ module Impl<FullStateConfigSig Config> {
pragma[nomagic]
predicate localStep(
NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, Typ t,
LocalCc lcc
NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue,
DataFlowType t, LocalCc lcc
) {
localFlowBigStep(node1, state1, node2, state2, preservesValue, t, _) and
PrevStage::revFlow(node1, pragma[only_bind_into](state1), _) and
@@ -2359,11 +2333,11 @@ module Impl<FullStateConfigSig Config> {
)
}
bindingset[node, state, t0, ap]
predicate filter(NodeEx node, FlowState state, Typ t0, Ap ap, Typ t) {
bindingset[node, state, t, ap]
predicate filter(NodeEx node, FlowState state, Typ t, Ap ap) {
exists(state) and
not clear(node, ap) and
strengthenType(node, t0, t) and
(if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), t) else any()) and
(
notExpectsContent(node)
or
@@ -2391,7 +2365,7 @@ module Impl<FullStateConfigSig Config> {
exists(AccessPathFront apf |
Stage4::revFlow(node, state, TReturnCtxMaybeFlowThrough(_), _, apf) and
Stage4::fwdFlow(node, state, any(Stage4::CcCall ccc), _, _, TAccessPathFrontSome(argApf), _,
apf, _)
apf)
)
}
@@ -2605,8 +2579,8 @@ module Impl<FullStateConfigSig Config> {
import LocalCallContext
predicate localStep(
NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, Typ t,
LocalCc lcc
NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue,
DataFlowType t, LocalCc lcc
) {
localFlowBigStep(node1, state1, node2, state2, preservesValue, t, lcc) and
PrevStage::revFlow(node1, pragma[only_bind_into](state1), _) and
@@ -2635,9 +2609,9 @@ module Impl<FullStateConfigSig Config> {
)
}
bindingset[node, state, t0, ap]
predicate filter(NodeEx node, FlowState state, Typ t0, Ap ap, Typ t) {
strengthenType(node, t0, t) and
bindingset[node, state, t, ap]
predicate filter(NodeEx node, FlowState state, Typ t, Ap ap) {
(if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), t) else any()) and
exists(state) and
exists(ap)
}
@@ -2658,7 +2632,7 @@ module Impl<FullStateConfigSig Config> {
Stage5::parameterMayFlowThrough(p, _) and
Stage5::revFlow(n, state, TReturnCtxMaybeFlowThrough(_), _, apa0) and
Stage5::fwdFlow(n, state, any(CallContextCall ccc), TParamNodeSome(p.asNode()), _,
TAccessPathApproxSome(apa), _, apa0, _)
TAccessPathApproxSome(apa), _, apa0)
)
}
@@ -2675,7 +2649,7 @@ module Impl<FullStateConfigSig Config> {
TSummaryCtxSome(ParamNodeEx p, FlowState state, DataFlowType t, AccessPath ap) {
exists(AccessPathApprox apa | ap.getApprox() = apa |
Stage5::parameterMayFlowThrough(p, apa) and
Stage5::fwdFlow(p, state, _, _, Option<DataFlowType>::some(t), _, _, apa, _) and
Stage5::fwdFlow(p, state, _, _, _, _, t, apa) and
Stage5::revFlow(p, state, _)
)
}
@@ -2846,7 +2820,9 @@ module Impl<FullStateConfigSig Config> {
ap = TAccessPathNil()
or
// ... or a step from an existing PathNode to another node.
pathStep(_, node, state, cc, sc, t, ap)
pathStep(_, node, state, cc, sc, t, ap) and
Stage5::revFlow(node, state, ap.getApprox()) and
(if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), t) else any())
} or
TPathNodeSink(NodeEx node, FlowState state) {
exists(PathNodeMid sink |
@@ -3364,24 +3340,13 @@ module Impl<FullStateConfigSig Config> {
ap = mid.getAp()
}
private predicate pathStep(
PathNodeMid mid, NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, DataFlowType t,
AccessPath ap
) {
exists(DataFlowType t0 |
pathStep0(mid, node, state, cc, sc, t0, ap) and
Stage5::revFlow(node, state, ap.getApprox()) and
strengthenType(node, t0, t)
)
}
/**
* Holds if data may flow from `mid` to `node`. The last step in or out of
* a callable is recorded by `cc`.
*/
pragma[assume_small_delta]
pragma[nomagic]
private predicate pathStep0(
private predicate pathStep(
PathNodeMid mid, NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, DataFlowType t,
AccessPath ap
) {
@@ -3999,7 +3964,7 @@ module Impl<FullStateConfigSig Config> {
ap = TPartialNil() and
exists(explorationLimit())
or
partialPathStep(_, node, state, cc, sc1, sc2, sc3, sc4, t, ap) and
partialPathNodeMk0(node, state, cc, sc1, sc2, sc3, sc4, t, ap) and
distSrc(node.getEnclosingCallable()) <= explorationLimit()
} or
TPartialPathNodeRev(
@@ -4025,20 +3990,11 @@ module Impl<FullStateConfigSig Config> {
}
pragma[nomagic]
private predicate partialPathStep(
PartialPathNodeFwd mid, NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1,
TSummaryCtx2 sc2, TSummaryCtx3 sc3, TSummaryCtx4 sc4, DataFlowType t, PartialAccessPath ap
private predicate partialPathNodeMk0(
NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2,
TSummaryCtx3 sc3, TSummaryCtx4 sc4, DataFlowType t, PartialAccessPath ap
) {
partialPathStep1(mid, node, state, cc, sc1, sc2, sc3, sc4, _, t, ap)
}
pragma[nomagic]
private predicate partialPathStep1(
PartialPathNodeFwd mid, NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1,
TSummaryCtx2 sc2, TSummaryCtx3 sc3, TSummaryCtx4 sc4, DataFlowType t0, DataFlowType t,
PartialAccessPath ap
) {
partialPathStep0(mid, node, state, cc, sc1, sc2, sc3, sc4, t0, ap) and
partialPathStep(_, node, state, cc, sc1, sc2, sc3, sc4, t, ap) and
not fullBarrier(node) and
not stateBarrier(node, state) and
not clearsContentEx(node, ap.getHead()) and
@@ -4046,14 +4002,9 @@ module Impl<FullStateConfigSig Config> {
notExpectsContent(node) or
expectsContentEx(node, ap.getHead())
) and
strengthenType(node, t0, t)
}
pragma[nomagic]
private predicate partialPathTypeStrengthen(
DataFlowType t0, PartialAccessPath ap, DataFlowType t
) {
partialPathStep1(_, _, _, _, _, _, _, _, t0, t, ap) and t0 != t
if node.asNode() instanceof CastingNode
then compatibleTypes(node.getDataFlowType(), t)
else any()
}
/**
@@ -4232,8 +4183,7 @@ module Impl<FullStateConfigSig Config> {
}
}
pragma[nomagic]
private predicate partialPathStep0(
private predicate partialPathStep(
PartialPathNodeFwd mid, NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1,
TSummaryCtx2 sc2, TSummaryCtx3 sc3, TSummaryCtx4 sc4, DataFlowType t, PartialAccessPath ap
) {
@@ -4359,11 +4309,6 @@ module Impl<FullStateConfigSig Config> {
DataFlowType t1, PartialAccessPath ap1, Content c, DataFlowType t2, PartialAccessPath ap2
) {
partialPathStoreStep(_, t1, ap1, c, _, t2, ap2)
or
exists(DataFlowType t0 |
partialPathTypeStrengthen(t0, ap2, t2) and
apConsFwd(t1, ap1, c, t0, ap2)
)
}
pragma[nomagic]

View File

@@ -205,8 +205,6 @@ predicate clearsContent(Node n, Content c) {
*/
predicate expectsContent(Node n, ContentSet c) { none() }
predicate typeStrongerThan(DataFlowType t1, DataFlowType t2) { none() }
/** Gets the type of `n` used for type pruning. */
Type getNodeType(Node n) {
suppressUnusedNode(n) and
@@ -235,12 +233,6 @@ class CastNode extends Node {
CastNode() { none() } // stub implementation
}
/**
* Holds if `n` should never be skipped over in the `PathGraph` and in path
* explanations.
*/
predicate neverSkipInPathGraph(Node n) { none() }
class DataFlowCallable = Function;
class DataFlowExpr = Expr;

View File

@@ -1135,8 +1135,8 @@ module Impl<FullStateConfigSig Config> {
DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow
);
bindingset[node, state, t0, ap]
predicate filter(NodeEx node, FlowState state, Typ t0, Ap ap, Typ t);
bindingset[node, state, t, ap]
predicate filter(NodeEx node, FlowState state, Typ t, Ap ap);
bindingset[typ, contentType]
predicate typecheckStore(Typ typ, DataFlowType contentType);
@@ -1199,21 +1199,17 @@ module Impl<FullStateConfigSig Config> {
NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, TypOption argT,
ApOption argAp, Typ t, Ap ap, ApApprox apa
) {
fwdFlow1(node, state, cc, summaryCtx, argT, argAp, _, t, ap, apa)
}
private predicate fwdFlow1(
NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, TypOption argT,
ApOption argAp, Typ t0, Typ t, Ap ap, ApApprox apa
) {
fwdFlow0(node, state, cc, summaryCtx, argT, argAp, t0, ap, apa) and
fwdFlow0(node, state, cc, summaryCtx, argT, argAp, t, ap, apa) and
PrevStage::revFlow(node, state, apa) and
filter(node, state, t0, ap, t)
filter(node, state, t, ap)
}
pragma[nomagic]
private predicate typeStrengthen(Typ t0, Ap ap, Typ t) {
fwdFlow1(_, _, _, _, _, _, t0, t, ap, _) and t0 != t
pragma[inline]
additional predicate fwdFlow(
NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, TypOption argT,
ApOption argAp, Typ t, Ap ap
) {
fwdFlow(node, state, cc, summaryCtx, argT, argAp, t, ap, _)
}
pragma[assume_small_delta]
@@ -1343,11 +1339,6 @@ module Impl<FullStateConfigSig Config> {
private predicate fwdFlowConsCand(Typ t2, Ap cons, Content c, Typ t1, Ap tail) {
fwdFlowStore(_, t1, tail, c, t2, _, _, _, _, _, _) and
cons = apCons(c, t1, tail)
or
exists(Typ t0 |
typeStrengthen(t0, cons, t2) and
fwdFlowConsCand(t0, cons, c, t1, tail)
)
}
pragma[nomagic]
@@ -1368,7 +1359,7 @@ module Impl<FullStateConfigSig Config> {
ParamNodeOption summaryCtx, TypOption argT, ApOption argAp
) {
exists(ApHeadContent apc |
fwdFlow(node1, state, cc, summaryCtx, argT, argAp, t, ap, _) and
fwdFlow(node1, state, cc, summaryCtx, argT, argAp, t, ap) and
apc = getHeadContent(ap) and
readStepCand0(node1, apc, c, node2)
)
@@ -1529,14 +1520,14 @@ module Impl<FullStateConfigSig Config> {
NodeEx node, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap
) {
revFlow0(node, state, returnCtx, returnAp, ap) and
fwdFlow(node, state, _, _, _, _, _, ap, _)
fwdFlow(node, state, _, _, _, _, _, ap)
}
pragma[nomagic]
private predicate revFlow0(
NodeEx node, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap
) {
fwdFlow(node, state, _, _, _, _, _, ap, _) and
fwdFlow(node, state, _, _, _, _, _, ap) and
sinkNode(node, state) and
(
if hasSinkCallCtx()
@@ -1789,13 +1780,13 @@ module Impl<FullStateConfigSig Config> {
boolean fwd, int nodes, int fields, int conscand, int states, int tuples
) {
fwd = true and
nodes = count(NodeEx node | fwdFlow(node, _, _, _, _, _, _, _, _)) and
nodes = count(NodeEx node | fwdFlow(node, _, _, _, _, _, _, _)) and
fields = count(Content f0 | fwdConsCand(f0, _, _)) and
conscand = count(Content f0, Typ t, Ap ap | fwdConsCand(f0, t, ap)) and
states = count(FlowState state | fwdFlow(_, state, _, _, _, _, _, _, _)) and
states = count(FlowState state | fwdFlow(_, state, _, _, _, _, _, _)) and
tuples =
count(NodeEx n, FlowState state, Cc cc, ParamNodeOption summaryCtx, TypOption argT,
ApOption argAp, Typ t, Ap ap | fwdFlow(n, state, cc, summaryCtx, argT, argAp, t, ap, _))
ApOption argAp, Typ t, Ap ap | fwdFlow(n, state, cc, summaryCtx, argT, argAp, t, ap))
or
fwd = false and
nodes = count(NodeEx node | revFlow(node, _, _, _, _)) and
@@ -1972,10 +1963,10 @@ module Impl<FullStateConfigSig Config> {
)
}
bindingset[node, state, t0, ap]
predicate filter(NodeEx node, FlowState state, Typ t0, Ap ap, Typ t) {
bindingset[node, state, t, ap]
predicate filter(NodeEx node, FlowState state, Typ t, Ap ap) {
PrevStage::revFlowState(state) and
t0 = t and
exists(t) and
exists(ap) and
not stateBarrier(node, state) and
(
@@ -2021,8 +2012,7 @@ module Impl<FullStateConfigSig Config> {
FlowCheckNode() {
castNode(this.asNode()) or
clearsContentCached(this.asNode(), _) or
expectsContentCached(this.asNode(), _) or
neverSkipInPathGraph(this.asNode())
expectsContentCached(this.asNode(), _)
}
}
@@ -2207,8 +2197,8 @@ module Impl<FullStateConfigSig Config> {
import BooleanCallContext
predicate localStep(
NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, Typ t,
LocalCc lcc
NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue,
DataFlowType t, LocalCc lcc
) {
localFlowBigStep(node1, state1, node2, state2, preservesValue, t, _) and
exists(lcc)
@@ -2228,16 +2218,10 @@ module Impl<FullStateConfigSig Config> {
)
}
bindingset[node, state, t0, ap]
predicate filter(NodeEx node, FlowState state, Typ t0, Ap ap, Typ t) {
bindingset[node, state, t, ap]
predicate filter(NodeEx node, FlowState state, Typ t, Ap ap) {
exists(state) and
// We can get away with not using type strengthening here, since we aren't
// going to use the tracked types in the construction of Stage 4 access
// paths. For Stage 4 and onwards, the tracked types must be consistent as
// the cons candidates including types are used to construct subsequent
// access path approximations.
t0 = t and
(if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), t0) else any()) and
(if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), t) else any()) and
(
notExpectsContent(node)
or
@@ -2257,16 +2241,6 @@ module Impl<FullStateConfigSig Config> {
import MkStage<Stage2>::Stage<Stage3Param>
}
bindingset[node, t0]
private predicate strengthenType(NodeEx node, DataFlowType t0, DataFlowType t) {
if castingNodeEx(node)
then
exists(DataFlowType nt | nt = node.getDataFlowType() |
if typeStrongerThan(nt, t0) then t = nt else (compatibleTypes(nt, t0) and t = t0)
)
else t = t0
}
private module Stage4Param implements MkStage<Stage3>::StageParam {
private module PrevStage = Stage3;
@@ -2300,8 +2274,8 @@ module Impl<FullStateConfigSig Config> {
pragma[nomagic]
predicate localStep(
NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, Typ t,
LocalCc lcc
NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue,
DataFlowType t, LocalCc lcc
) {
localFlowBigStep(node1, state1, node2, state2, preservesValue, t, _) and
PrevStage::revFlow(node1, pragma[only_bind_into](state1), _) and
@@ -2359,11 +2333,11 @@ module Impl<FullStateConfigSig Config> {
)
}
bindingset[node, state, t0, ap]
predicate filter(NodeEx node, FlowState state, Typ t0, Ap ap, Typ t) {
bindingset[node, state, t, ap]
predicate filter(NodeEx node, FlowState state, Typ t, Ap ap) {
exists(state) and
not clear(node, ap) and
strengthenType(node, t0, t) and
(if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), t) else any()) and
(
notExpectsContent(node)
or
@@ -2391,7 +2365,7 @@ module Impl<FullStateConfigSig Config> {
exists(AccessPathFront apf |
Stage4::revFlow(node, state, TReturnCtxMaybeFlowThrough(_), _, apf) and
Stage4::fwdFlow(node, state, any(Stage4::CcCall ccc), _, _, TAccessPathFrontSome(argApf), _,
apf, _)
apf)
)
}
@@ -2605,8 +2579,8 @@ module Impl<FullStateConfigSig Config> {
import LocalCallContext
predicate localStep(
NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, Typ t,
LocalCc lcc
NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue,
DataFlowType t, LocalCc lcc
) {
localFlowBigStep(node1, state1, node2, state2, preservesValue, t, lcc) and
PrevStage::revFlow(node1, pragma[only_bind_into](state1), _) and
@@ -2635,9 +2609,9 @@ module Impl<FullStateConfigSig Config> {
)
}
bindingset[node, state, t0, ap]
predicate filter(NodeEx node, FlowState state, Typ t0, Ap ap, Typ t) {
strengthenType(node, t0, t) and
bindingset[node, state, t, ap]
predicate filter(NodeEx node, FlowState state, Typ t, Ap ap) {
(if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), t) else any()) and
exists(state) and
exists(ap)
}
@@ -2658,7 +2632,7 @@ module Impl<FullStateConfigSig Config> {
Stage5::parameterMayFlowThrough(p, _) and
Stage5::revFlow(n, state, TReturnCtxMaybeFlowThrough(_), _, apa0) and
Stage5::fwdFlow(n, state, any(CallContextCall ccc), TParamNodeSome(p.asNode()), _,
TAccessPathApproxSome(apa), _, apa0, _)
TAccessPathApproxSome(apa), _, apa0)
)
}
@@ -2675,7 +2649,7 @@ module Impl<FullStateConfigSig Config> {
TSummaryCtxSome(ParamNodeEx p, FlowState state, DataFlowType t, AccessPath ap) {
exists(AccessPathApprox apa | ap.getApprox() = apa |
Stage5::parameterMayFlowThrough(p, apa) and
Stage5::fwdFlow(p, state, _, _, Option<DataFlowType>::some(t), _, _, apa, _) and
Stage5::fwdFlow(p, state, _, _, _, _, t, apa) and
Stage5::revFlow(p, state, _)
)
}
@@ -2846,7 +2820,9 @@ module Impl<FullStateConfigSig Config> {
ap = TAccessPathNil()
or
// ... or a step from an existing PathNode to another node.
pathStep(_, node, state, cc, sc, t, ap)
pathStep(_, node, state, cc, sc, t, ap) and
Stage5::revFlow(node, state, ap.getApprox()) and
(if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), t) else any())
} or
TPathNodeSink(NodeEx node, FlowState state) {
exists(PathNodeMid sink |
@@ -3364,24 +3340,13 @@ module Impl<FullStateConfigSig Config> {
ap = mid.getAp()
}
private predicate pathStep(
PathNodeMid mid, NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, DataFlowType t,
AccessPath ap
) {
exists(DataFlowType t0 |
pathStep0(mid, node, state, cc, sc, t0, ap) and
Stage5::revFlow(node, state, ap.getApprox()) and
strengthenType(node, t0, t)
)
}
/**
* Holds if data may flow from `mid` to `node`. The last step in or out of
* a callable is recorded by `cc`.
*/
pragma[assume_small_delta]
pragma[nomagic]
private predicate pathStep0(
private predicate pathStep(
PathNodeMid mid, NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, DataFlowType t,
AccessPath ap
) {
@@ -3999,7 +3964,7 @@ module Impl<FullStateConfigSig Config> {
ap = TPartialNil() and
exists(explorationLimit())
or
partialPathStep(_, node, state, cc, sc1, sc2, sc3, sc4, t, ap) and
partialPathNodeMk0(node, state, cc, sc1, sc2, sc3, sc4, t, ap) and
distSrc(node.getEnclosingCallable()) <= explorationLimit()
} or
TPartialPathNodeRev(
@@ -4025,20 +3990,11 @@ module Impl<FullStateConfigSig Config> {
}
pragma[nomagic]
private predicate partialPathStep(
PartialPathNodeFwd mid, NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1,
TSummaryCtx2 sc2, TSummaryCtx3 sc3, TSummaryCtx4 sc4, DataFlowType t, PartialAccessPath ap
private predicate partialPathNodeMk0(
NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2,
TSummaryCtx3 sc3, TSummaryCtx4 sc4, DataFlowType t, PartialAccessPath ap
) {
partialPathStep1(mid, node, state, cc, sc1, sc2, sc3, sc4, _, t, ap)
}
pragma[nomagic]
private predicate partialPathStep1(
PartialPathNodeFwd mid, NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1,
TSummaryCtx2 sc2, TSummaryCtx3 sc3, TSummaryCtx4 sc4, DataFlowType t0, DataFlowType t,
PartialAccessPath ap
) {
partialPathStep0(mid, node, state, cc, sc1, sc2, sc3, sc4, t0, ap) and
partialPathStep(_, node, state, cc, sc1, sc2, sc3, sc4, t, ap) and
not fullBarrier(node) and
not stateBarrier(node, state) and
not clearsContentEx(node, ap.getHead()) and
@@ -4046,14 +4002,9 @@ module Impl<FullStateConfigSig Config> {
notExpectsContent(node) or
expectsContentEx(node, ap.getHead())
) and
strengthenType(node, t0, t)
}
pragma[nomagic]
private predicate partialPathTypeStrengthen(
DataFlowType t0, PartialAccessPath ap, DataFlowType t
) {
partialPathStep1(_, _, _, _, _, _, _, _, t0, t, ap) and t0 != t
if node.asNode() instanceof CastingNode
then compatibleTypes(node.getDataFlowType(), t)
else any()
}
/**
@@ -4232,8 +4183,7 @@ module Impl<FullStateConfigSig Config> {
}
}
pragma[nomagic]
private predicate partialPathStep0(
private predicate partialPathStep(
PartialPathNodeFwd mid, NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1,
TSummaryCtx2 sc2, TSummaryCtx3 sc3, TSummaryCtx4 sc4, DataFlowType t, PartialAccessPath ap
) {
@@ -4359,11 +4309,6 @@ module Impl<FullStateConfigSig Config> {
DataFlowType t1, PartialAccessPath ap1, Content c, DataFlowType t2, PartialAccessPath ap2
) {
partialPathStoreStep(_, t1, ap1, c, _, t2, ap2)
or
exists(DataFlowType t0 |
partialPathTypeStrengthen(t0, ap2, t2) and
apConsFwd(t1, ap1, c, t0, ap2)
)
}
pragma[nomagic]

View File

@@ -753,8 +753,6 @@ predicate clearsContent(Node n, Content c) {
*/
predicate expectsContent(Node n, ContentSet c) { none() }
predicate typeStrongerThan(DataFlowType t1, DataFlowType t2) { none() }
/** Gets the type of `n` used for type pruning. */
DataFlowType getNodeType(Node n) {
suppressUnusedNode(n) and
@@ -783,12 +781,6 @@ class CastNode extends Node {
CastNode() { none() } // stub implementation
}
/**
* Holds if `n` should never be skipped over in the `PathGraph` and in path
* explanations.
*/
predicate neverSkipInPathGraph(Node n) { none() }
/**
* A function that may contain code or a variable that may contain itself. When
* flow crosses from one _enclosing callable_ to another, the interprocedural

View File

@@ -364,25 +364,7 @@ abstract private class OperandBasedUse extends UseImpl {
OperandBasedUse() { any() }
final override predicate hasIndexInBlock(IRBlock block, int index) {
// See the comment in `ssa0`'s `OperandBasedUse` for an explanation of this
// predicate's implementation.
exists(BaseSourceVariableInstruction base | base = this.getBase() |
if base.getAst() = any(Cpp::PostfixCrementOperation c).getOperand()
then
exists(Operand op, int indirectionIndex, int indirection |
indirectionIndex = this.getIndirectionIndex() and
indirection = this.getIndirection() and
op =
min(Operand cand, int i |
isUse(_, cand, base, indirection, indirectionIndex) and
block.getInstruction(i) = cand.getUse()
|
cand order by i
) and
block.getInstruction(index) = op.getUse()
)
else operand.getUse() = block.getInstruction(index)
)
operand.getUse() = block.getInstruction(index)
}
final Operand getOperand() { result = operand }

View File

@@ -122,46 +122,7 @@ abstract private class OperandBasedUse extends UseImpl {
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)
)
operand.getUse() = block.getInstruction(index)
}
final override Cpp::Location getLocation() { result = operand.getLocation() }

View File

@@ -577,6 +577,9 @@ private Overlap getVariableMemoryLocationOverlap(
*/
predicate canReuseSsaForOldResult(Instruction instr) { OldSsa::canReuseSsaForMemoryResult(instr) }
/** DEPRECATED: Alias for canReuseSsaForOldResult */
deprecated predicate canReuseSSAForOldResult = canReuseSsaForOldResult/1;
bindingset[result, b]
private boolean unbindBool(boolean b) { result != b.booleanNot() }

View File

@@ -74,12 +74,20 @@ private module Shared {
class TNonSsaMemoryOperand = Internal::TNonSsaMemoryOperand;
/** DEPRECATED: Alias for TNonSsaMemoryOperand */
deprecated class TNonSSAMemoryOperand = TNonSsaMemoryOperand;
/**
* Returns the non-Phi memory operand with the specified parameters.
*/
TNonSsaMemoryOperand nonSsaMemoryOperand(TRawInstruction useInstr, MemoryOperandTag tag) {
result = Internal::TNonSsaMemoryOperand(useInstr, tag)
}
/** DEPRECATED: Alias for nonSsaMemoryOperand */
deprecated TNonSSAMemoryOperand nonSSAMemoryOperand(TRawInstruction useInstr, MemoryOperandTag tag) {
result = nonSsaMemoryOperand(useInstr, tag)
}
}
/**
@@ -159,6 +167,9 @@ module UnaliasedSsaOperands {
TChiOperand chiOperand(Unaliased::Instruction useInstr, ChiOperandTag tag) { none() }
}
/** DEPRECATED: Alias for UnaliasedSsaOperands */
deprecated module UnaliasedSSAOperands = UnaliasedSsaOperands;
/**
* Provides wrappers for the constructors of each branch of `TOperand` that is used by the
* aliased SSA stage.
@@ -206,3 +217,6 @@ module AliasedSsaOperands {
result = Internal::TAliasedChiOperand(useInstr, tag)
}
}
/** DEPRECATED: Alias for AliasedSsaOperands */
deprecated module AliasedSSAOperands = AliasedSsaOperands;

View File

@@ -375,6 +375,11 @@ Locatable getInstructionAst(TStageInstruction instr) {
)
}
/** DEPRECATED: Alias for getInstructionAst */
deprecated Locatable getInstructionAST(TStageInstruction instr) {
result = getInstructionAst(instr)
}
CppType getInstructionResultType(TStageInstruction instr) {
getInstructionTranslatedElement(instr).hasInstruction(_, getInstructionTag(instr), result)
or

View File

@@ -76,6 +76,9 @@ abstract class TranslatedExpr extends TranslatedElement {
final override Locatable getAst() { result = expr }
/** DEPRECATED: Alias for getAst */
deprecated override Locatable getAST() { result = this.getAst() }
final override Declaration getFunction() { result = getEnclosingDeclaration(expr) }
/**

View File

@@ -40,6 +40,9 @@ library class RangeSsa extends SsaHelper {
}
}
/** DEPRECATED: Alias for RangeSsa */
deprecated class RangeSSA = RangeSsa;
private predicate guard_defn(VariableAccess v, Expr guard, BasicBlock b, boolean branch) {
guardCondition(guard, v, branch) and
guardSuccessor(guard, branch, b)

View File

@@ -1,9 +1,3 @@
## 0.6.3
### New Queries
* Added a new query, `cpp/overrun-write`, to detect buffer overflows in C-style functions that manipulate buffers.
## 0.6.2
No user-facing changes.

View File

@@ -16,6 +16,9 @@ class UntrustedExternalApiDataNode extends ExternalApiDataNode {
DataFlow::Node getAnUntrustedSource() { UntrustedDataToExternalApiFlow::flow(result, this) }
}
/** DEPRECATED: Alias for UntrustedExternalApiDataNode */
deprecated class UntrustedExternalAPIDataNode = UntrustedExternalApiDataNode;
/** An external API which is used with untrusted data. */
private newtype TExternalApi =
/** An untrusted API method `m` where untrusted data is passed at `index`. */
@@ -48,3 +51,6 @@ class ExternalApiUsedWithUntrustedData extends TExternalApi {
)
}
}
/** DEPRECATED: Alias for ExternalApiUsedWithUntrustedData */
deprecated class ExternalAPIUsedWithUntrustedData = ExternalApiUsedWithUntrustedData;

View File

@@ -41,6 +41,9 @@ class ExternalApiDataNode extends DataFlow::Node {
string getFunctionDescription() { result = this.getExternalFunction().toString() }
}
/** DEPRECATED: Alias for ExternalApiDataNode */
deprecated class ExternalAPIDataNode = ExternalApiDataNode;
/** A configuration for tracking flow from `RemoteFlowSource`s to `ExternalApiDataNode`s. */
deprecated class UntrustedDataToExternalApiConfig extends TaintTracking::Configuration {
UntrustedDataToExternalApiConfig() { this = "UntrustedDataToExternalAPIConfig" }
@@ -55,6 +58,9 @@ deprecated class UntrustedDataToExternalApiConfig extends TaintTracking::Configu
override predicate isSink(DataFlow::Node sink) { sink instanceof ExternalApiDataNode }
}
/** DEPRECATED: Alias for UntrustedDataToExternalApiConfig */
deprecated class UntrustedDataToExternalAPIConfig = UntrustedDataToExternalApiConfig;
/** A configuration for tracking flow from `RemoteFlowSource`s to `ExternalApiDataNode`s. */
private module UntrustedDataToExternalApiConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) {

View File

@@ -10,6 +10,9 @@ private import semmle.code.cpp.models.interfaces.SideEffect
*/
abstract class SafeExternalApiFunction extends Function { }
/** DEPRECATED: Alias for SafeExternalApiFunction */
deprecated class SafeExternalAPIFunction = SafeExternalApiFunction;
/** The default set of "safe" external APIs. */
private class DefaultSafeExternalApiFunction extends SafeExternalApiFunction {
DefaultSafeExternalApiFunction() {

View File

@@ -16,6 +16,9 @@ class UntrustedExternalApiDataNode extends ExternalApiDataNode {
DataFlow::Node getAnUntrustedSource() { UntrustedDataToExternalApiFlow::flow(result, this) }
}
/** DEPRECATED: Alias for UntrustedExternalApiDataNode */
deprecated class UntrustedExternalAPIDataNode = UntrustedExternalApiDataNode;
/** An external API which is used with untrusted data. */
private newtype TExternalApi =
/** An untrusted API method `m` where untrusted data is passed at `index`. */
@@ -48,3 +51,6 @@ class ExternalApiUsedWithUntrustedData extends TExternalApi {
)
}
}
/** DEPRECATED: Alias for ExternalApiUsedWithUntrustedData */
deprecated class ExternalAPIUsedWithUntrustedData = ExternalApiUsedWithUntrustedData;

View File

@@ -41,6 +41,9 @@ class ExternalApiDataNode extends DataFlow::Node {
string getFunctionDescription() { result = this.getExternalFunction().toString() }
}
/** DEPRECATED: Alias for ExternalApiDataNode */
deprecated class ExternalAPIDataNode = ExternalApiDataNode;
/** A configuration for tracking flow from `RemoteFlowSource`s to `ExternalApiDataNode`s. */
deprecated class UntrustedDataToExternalApiConfig extends TaintTracking::Configuration {
UntrustedDataToExternalApiConfig() { this = "UntrustedDataToExternalAPIConfigIR" }
@@ -50,6 +53,9 @@ deprecated class UntrustedDataToExternalApiConfig extends TaintTracking::Configu
override predicate isSink(DataFlow::Node sink) { sink instanceof ExternalApiDataNode }
}
/** DEPRECATED: Alias for UntrustedDataToExternalApiConfig */
deprecated class UntrustedDataToExternalAPIConfig = UntrustedDataToExternalApiConfig;
/** A configuration for tracking flow from `RemoteFlowSource`s to `ExternalApiDataNode`s. */
private module UntrustedDataToExternalApiConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource }

View File

@@ -10,6 +10,9 @@ private import semmle.code.cpp.models.interfaces.SideEffect
*/
abstract class SafeExternalApiFunction extends Function { }
/** DEPRECATED: Alias for SafeExternalApiFunction */
deprecated class SafeExternalAPIFunction = SafeExternalApiFunction;
/** The default set of "safe" external APIs. */
private class DefaultSafeExternalApiFunction extends SafeExternalApiFunction {
DefaultSafeExternalApiFunction() {

View File

@@ -5,7 +5,7 @@
* @kind path-problem
* @problem.severity error
* @security-severity 9.3
* @precision low
* @precision medium
* @id cpp/overrun-write
* @tags reliability
* security

View File

@@ -1,5 +1,4 @@
## 0.6.3
### New Queries
---
category: newQuery
---
* Added a new query, `cpp/overrun-write`, to detect buffer overflows in C-style functions that manipulate buffers.

View File

@@ -1,2 +1,2 @@
---
lastReleaseVersion: 0.6.3
lastReleaseVersion: 0.6.2

373
cpp/ql/src/external/CodeDuplication.qll vendored Normal file
View File

@@ -0,0 +1,373 @@
/** Provides classes for detecting duplicate or similar code. */
import cpp
deprecated private newtype TDuplicationOrSimilarity = MKDuplicationOrSimilarity()
/**
* DEPRECATED: This class is no longer used.
*
* A token block used for detection of duplicate and similar code.
*/
deprecated class Copy extends TDuplicationOrSimilarity {
/** Gets the index of the token in this block starting at the location `loc`, if any. */
int tokenStartingAt(Location loc) { none() }
/** Gets the index of the token in this block ending at the location `loc`, if any. */
int tokenEndingAt(Location loc) { none() }
/** Gets the line on which the first token in this block starts. */
int sourceStartLine() { none() }
/** Gets the column on which the first token in this block starts. */
int sourceStartColumn() { none() }
/** Gets the line on which the last token in this block ends. */
int sourceEndLine() { none() }
/** Gets the column on which the last token in this block ends. */
int sourceEndColumn() { none() }
/** Gets the number of lines containing at least (part of) one token in this block. */
int sourceLines() { result = this.sourceEndLine() + 1 - this.sourceStartLine() }
/** Gets an opaque identifier for the equivalence class of this block. */
int getEquivalenceClass() { none() }
/** Gets the source file in which this block appears. */
File sourceFile() { none() }
/**
* Holds if this element is at the specified location.
* The location spans column `startcolumn` of line `startline` to
* column `endcolumn` of line `endline` in file `filepath`.
* For more information, see
* [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/).
*/
predicate hasLocationInfo(
string filepath, int startline, int startcolumn, int endline, int endcolumn
) {
this.sourceFile().getAbsolutePath() = filepath and
startline = this.sourceStartLine() and
startcolumn = this.sourceStartColumn() and
endline = this.sourceEndLine() and
endcolumn = this.sourceEndColumn()
}
/** Gets a textual representation of this element. */
string toString() { none() }
}
/**
* DEPRECATED: This class is no longer used.
*
* A block of duplicated code.
*/
deprecated class DuplicateBlock extends Copy {
override string toString() {
result = "Duplicate code: " + this.sourceLines() + " duplicated lines."
}
}
/**
* DEPRECATED: This class is no longer used.
*
* A block of similar code.
*/
deprecated class SimilarBlock extends Copy {
override string toString() {
result = "Similar code: " + this.sourceLines() + " almost duplicated lines."
}
}
/**
* DEPRECATED: The `CodeDuplication` library will be removed in a future release.
*
* Gets a function with a body and a location.
*/
deprecated FunctionDeclarationEntry sourceMethod() {
result.isDefinition() and
exists(result.getLocation()) and
numlines(unresolveElement(result.getFunction()), _, _, _)
}
/**
* DEPRECATED: The `CodeDuplication` library will be removed in a future release.
*
* Gets the number of member functions in `c` with a body and a location.
*/
deprecated int numberOfSourceMethods(Class c) {
result =
count(FunctionDeclarationEntry m |
m = sourceMethod() and
m.getFunction().getDeclaringType() = c
)
}
deprecated private predicate blockCoversStatement(int equivClass, int first, int last, Stmt stmt) {
exists(DuplicateBlock b, Location loc |
stmt.getLocation() = loc and
first = b.tokenStartingAt(loc) and
last = b.tokenEndingAt(loc) and
b.getEquivalenceClass() = equivClass
)
}
deprecated private Stmt statementInMethod(FunctionDeclarationEntry m) {
result.getParent+() = m.getBlock() and
not result.getLocation() instanceof UnknownStmtLocation and
not result instanceof BlockStmt
}
deprecated private predicate duplicateStatement(
FunctionDeclarationEntry m1, FunctionDeclarationEntry m2, Stmt s1, Stmt s2
) {
exists(int equivClass, int first, int last |
s1 = statementInMethod(m1) and
s2 = statementInMethod(m2) and
blockCoversStatement(equivClass, first, last, s1) and
blockCoversStatement(equivClass, first, last, s2) and
s1 != s2 and
m1 != m2
)
}
/**
* DEPRECATED: Information on duplicated statements is no longer available.
*
* Holds if `m1` is a function with `total` lines, and `m2` is a function
* that has `duplicate` lines in common with `m1`.
*/
deprecated predicate duplicateStatements(
FunctionDeclarationEntry m1, FunctionDeclarationEntry m2, int duplicate, int total
) {
duplicate = strictcount(Stmt s | duplicateStatement(m1, m2, s, _)) and
total = strictcount(statementInMethod(m1))
}
/**
* DEPRECATED: Information on duplicated methods is no longer available.
*
* Holds if `m` and other are identical functions.
*/
deprecated predicate duplicateMethod(FunctionDeclarationEntry m, FunctionDeclarationEntry other) {
exists(int total | duplicateStatements(m, other, total, total))
}
/**
* DEPRECATED: Information on similar lines is no longer available.
*
* INTERNAL: do not use.
*
* Holds if `line` in `f` is similar to a line somewhere else.
*/
deprecated predicate similarLines(File f, int line) {
exists(SimilarBlock b | b.sourceFile() = f and line in [b.sourceStartLine() .. b.sourceEndLine()])
}
deprecated private predicate similarLinesPerEquivalenceClass(int equivClass, int lines, File f) {
lines =
strictsum(SimilarBlock b, int toSum |
(b.sourceFile() = f and b.getEquivalenceClass() = equivClass) and
toSum = b.sourceLines()
|
toSum
)
}
deprecated private predicate similarLinesCoveredFiles(File f, File otherFile) {
exists(int numLines | numLines = f.getMetrics().getNumberOfLines() |
exists(int coveredApprox |
coveredApprox =
strictsum(int num |
exists(int equivClass |
similarLinesPerEquivalenceClass(equivClass, num, f) and
similarLinesPerEquivalenceClass(equivClass, num, otherFile) and
f != otherFile
)
) and
(coveredApprox * 100) / numLines > 75
)
)
}
/**
* DEPRECATED: Information on similar lines is no longer available.
*
* Holds if `coveredLines` lines of `f` are similar to lines in `otherFile`.
*/
deprecated predicate similarLinesCovered(File f, int coveredLines, File otherFile) {
exists(int numLines | numLines = f.getMetrics().getNumberOfLines() |
similarLinesCoveredFiles(f, otherFile) and
exists(int notCovered |
notCovered =
count(int j |
j in [1 .. numLines] and
not similarLines(f, j)
) and
coveredLines = numLines - notCovered
)
)
}
/**
* DEPRECATED: Information on duplicate lines is no longer available.
*
* INTERNAL: do not use.
*
* Holds if `line` in `f` is duplicated by a line somewhere else.
*/
deprecated predicate duplicateLines(File f, int line) {
exists(DuplicateBlock b |
b.sourceFile() = f and line in [b.sourceStartLine() .. b.sourceEndLine()]
)
}
deprecated private predicate duplicateLinesPerEquivalenceClass(int equivClass, int lines, File f) {
lines =
strictsum(DuplicateBlock b, int toSum |
(b.sourceFile() = f and b.getEquivalenceClass() = equivClass) and
toSum = b.sourceLines()
|
toSum
)
}
/**
* DEPRECATED: Information on duplicate lines is no longer available.
*
* Holds if `coveredLines` lines of `f` are duplicates of lines in `otherFile`.
*/
deprecated predicate duplicateLinesCovered(File f, int coveredLines, File otherFile) {
exists(int numLines | numLines = f.getMetrics().getNumberOfLines() |
exists(int coveredApprox |
coveredApprox =
strictsum(int num |
exists(int equivClass |
duplicateLinesPerEquivalenceClass(equivClass, num, f) and
duplicateLinesPerEquivalenceClass(equivClass, num, otherFile) and
f != otherFile
)
) and
(coveredApprox * 100) / numLines > 75
) and
exists(int notCovered |
notCovered =
count(int j |
j in [1 .. numLines] and
not duplicateLines(f, j)
) and
coveredLines = numLines - notCovered
)
)
}
/**
* DEPRECATED: Information on similar files is no longer available.
*
* Holds if most of `f` (`percent`%) is similar to `other`.
*/
deprecated predicate similarFiles(File f, File other, int percent) {
exists(int covered, int total |
similarLinesCovered(f, covered, other) and
total = f.getMetrics().getNumberOfLines() and
covered * 100 / total = percent and
percent > 80
) and
not duplicateFiles(f, other, _)
}
/**
* DEPRECATED: Information on duplicate files is no longer available.
*
* Holds if most of `f` (`percent`%) is duplicated by `other`.
*/
deprecated predicate duplicateFiles(File f, File other, int percent) {
exists(int covered, int total |
duplicateLinesCovered(f, covered, other) and
total = f.getMetrics().getNumberOfLines() and
covered * 100 / total = percent and
percent > 70
)
}
/**
* DEPRECATED: Information on duplicate classes is no longer available.
*
* Holds if most member functions of `c` (`numDup` out of `total`) are
* duplicates of member functions in `other`.
*/
deprecated predicate mostlyDuplicateClassBase(Class c, Class other, int numDup, int total) {
numDup =
strictcount(FunctionDeclarationEntry m1 |
exists(FunctionDeclarationEntry m2 |
duplicateMethod(m1, m2) and
m1 = sourceMethod() and
exists(Function f | f = m1.getFunction() and f.getDeclaringType() = c) and
exists(Function f | f = m2.getFunction() and f.getDeclaringType() = other) and
c != other
)
) and
total = numberOfSourceMethods(c) and
(numDup * 100) / total > 80
}
/**
* DEPRECATED: Information on duplicate classes is no longer available.
*
* Holds if most member functions of `c` are duplicates of member functions in
* `other`. Provides the human-readable `message` to describe the amount of
* duplication.
*/
deprecated predicate mostlyDuplicateClass(Class c, Class other, string message) {
exists(int numDup, int total |
mostlyDuplicateClassBase(c, other, numDup, total) and
(
total != numDup and
exists(string s1, string s2, string s3, string name |
s1 = " out of " and
s2 = " methods in " and
s3 = " are duplicated in $@." and
name = c.getName()
|
message = numDup + s1 + total + s2 + name + s3
)
or
total = numDup and
exists(string s1, string s2, string name |
s1 = "All methods in " and s2 = " are identical in $@." and name = c.getName()
|
message = s1 + name + s2
)
)
)
}
/**
* DEPRECATED: Information on file duplication is no longer available.
*
* Holds if `f` and `other` are similar or duplicates.
*/
deprecated predicate fileLevelDuplication(File f, File other) {
similarFiles(f, other, _) or duplicateFiles(f, other, _)
}
/**
* DEPRECATED: Information on class duplication is no longer available.
*
* Holds if most member functions of `c` are duplicates of member functions in
* `other`.
*/
deprecated predicate classLevelDuplication(Class c, Class other) {
mostlyDuplicateClass(c, other, _)
}
/**
* DEPRECATED: The CodeDuplication library will be removed in a future release.
*
* Holds if `line` in `f` should be allowed to be duplicated. This is the case
* for `#include` directives.
*/
deprecated predicate whitelistedLineForDuplication(File f, int line) {
exists(Include i | i.getFile() = f and i.getLocation().getStartLine() = line)
}

View File

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

View File

@@ -664,6 +664,11 @@ edges
| test.cpp:338:8:338:15 | * ... | test.cpp:342:8:342:17 | * ... |
| test.cpp:341:8:341:17 | * ... | test.cpp:342:8:342:17 | * ... |
| test.cpp:347:14:347:27 | new[] | test.cpp:348:15:348:16 | xs |
| test.cpp:348:15:348:16 | xs | test.cpp:350:16:350:19 | ... ++ |
| test.cpp:348:15:348:16 | xs | test.cpp:350:16:350:19 | ... ++ |
| test.cpp:350:16:350:19 | ... ++ | test.cpp:350:15:350:19 | Load: * ... |
| test.cpp:350:16:350:19 | ... ++ | test.cpp:350:16:350:19 | ... ++ |
| test.cpp:350:16:350:19 | ... ++ | test.cpp:350:16:350:19 | ... ++ |
| test.cpp:355:14:355:27 | new[] | test.cpp:356:15:356:16 | xs |
| test.cpp:356:15:356:16 | xs | test.cpp:356:15:356:23 | ... + ... |
| test.cpp:356:15:356:16 | xs | test.cpp:356:15:356:23 | ... + ... |
@@ -748,46 +753,6 @@ edges
| test.cpp:381:5:381:9 | ... ++ | test.cpp:384:14:384:16 | end |
| test.cpp:381:5:381:9 | ... ++ | test.cpp:384:14:384:16 | end |
| test.cpp:384:14:384:16 | end | test.cpp:384:13:384:16 | Load: * ... |
| test.cpp:388:14:388:27 | new[] | test.cpp:389:16:389:17 | xs |
| test.cpp:388:14:388:27 | new[] | test.cpp:392:5:392:6 | xs |
| test.cpp:389:16:389:17 | xs | test.cpp:392:5:392:8 | ... ++ |
| test.cpp:389:16:389:17 | xs | test.cpp:392:5:392:8 | ... ++ |
| test.cpp:389:16:389:17 | xs | test.cpp:392:5:392:8 | ... ++ |
| test.cpp:389:16:389:17 | xs | test.cpp:392:5:392:8 | ... ++ |
| test.cpp:389:16:389:17 | xs | test.cpp:393:9:393:10 | xs |
| test.cpp:389:16:389:17 | xs | test.cpp:393:9:393:10 | xs |
| test.cpp:392:5:392:8 | ... ++ | test.cpp:392:5:392:8 | ... ++ |
| test.cpp:392:5:392:8 | ... ++ | test.cpp:392:5:392:8 | ... ++ |
| test.cpp:392:5:392:8 | ... ++ | test.cpp:393:9:393:10 | xs |
| test.cpp:392:5:392:8 | ... ++ | test.cpp:393:9:393:10 | xs |
| test.cpp:392:5:392:8 | ... ++ | test.cpp:393:9:393:10 | xs |
| test.cpp:392:5:392:8 | ... ++ | test.cpp:393:9:393:10 | xs |
| test.cpp:392:5:392:8 | ... ++ | test.cpp:395:5:395:6 | xs |
| test.cpp:392:5:392:8 | ... ++ | test.cpp:395:5:395:6 | xs |
| test.cpp:392:5:392:8 | ... ++ | test.cpp:395:5:395:13 | Store: ... = ... |
| test.cpp:392:5:392:8 | ... ++ | test.cpp:395:5:395:13 | Store: ... = ... |
| test.cpp:392:5:392:8 | ... ++ | test.cpp:395:5:395:13 | Store: ... = ... |
| test.cpp:392:5:392:8 | ... ++ | test.cpp:395:5:395:13 | Store: ... = ... |
| test.cpp:393:9:393:10 | xs | test.cpp:395:5:395:6 | xs |
| test.cpp:393:9:393:10 | xs | test.cpp:395:5:395:13 | Store: ... = ... |
| test.cpp:393:9:393:10 | xs | test.cpp:395:5:395:13 | Store: ... = ... |
| test.cpp:395:5:395:6 | xs | test.cpp:395:5:395:13 | Store: ... = ... |
| test.cpp:404:3:404:25 | ... = ... | test.cpp:404:7:404:8 | val indirection [post update] [xs] |
| test.cpp:404:7:404:8 | val indirection [post update] [xs] | test.cpp:407:3:407:5 | val indirection [xs] |
| test.cpp:404:12:404:25 | new[] | test.cpp:404:3:404:25 | ... = ... |
| test.cpp:406:3:406:25 | ... = ... | test.cpp:406:7:406:8 | val indirection [post update] [xs] |
| test.cpp:406:7:406:8 | val indirection [post update] [xs] | test.cpp:407:3:407:5 | val indirection [xs] |
| test.cpp:406:12:406:25 | new[] | test.cpp:406:3:406:25 | ... = ... |
| test.cpp:407:3:407:5 | val indirection [xs] | test.cpp:407:7:407:8 | xs indirection |
| test.cpp:407:3:407:18 | access to array | test.cpp:407:3:407:22 | Store: ... = ... |
| test.cpp:407:7:407:8 | xs | test.cpp:407:3:407:18 | access to array |
| test.cpp:407:7:407:8 | xs indirection | test.cpp:407:7:407:8 | xs |
| test.cpp:417:16:417:33 | new[] | test.cpp:419:7:419:8 | xs |
| test.cpp:419:7:419:8 | xs | test.cpp:419:7:419:11 | access to array |
| test.cpp:419:7:419:11 | access to array | test.cpp:419:7:419:15 | Store: ... = ... |
| test.cpp:427:14:427:27 | new[] | test.cpp:433:5:433:6 | xs |
| test.cpp:433:5:433:6 | xs | test.cpp:433:5:433:17 | access to array |
| test.cpp:433:5:433:17 | access to array | test.cpp:433:5:433:21 | Store: ... = ... |
nodes
| test.cpp:4:15:4:20 | call to malloc | semmle.label | call to malloc |
| test.cpp:5:15:5:15 | p | semmle.label | p |
@@ -1092,6 +1057,10 @@ nodes
| test.cpp:342:8:342:17 | * ... | semmle.label | * ... |
| test.cpp:347:14:347:27 | new[] | semmle.label | new[] |
| test.cpp:348:15:348:16 | xs | semmle.label | xs |
| test.cpp:350:15:350:19 | Load: * ... | semmle.label | Load: * ... |
| test.cpp:350:16:350:19 | ... ++ | semmle.label | ... ++ |
| test.cpp:350:16:350:19 | ... ++ | semmle.label | ... ++ |
| test.cpp:350:16:350:19 | ... ++ | semmle.label | ... ++ |
| test.cpp:355:14:355:27 | new[] | semmle.label | new[] |
| test.cpp:356:15:356:16 | xs | semmle.label | xs |
| test.cpp:356:15:356:23 | ... + ... | semmle.label | ... + ... |
@@ -1127,36 +1096,6 @@ nodes
| test.cpp:381:5:381:9 | ... ++ | semmle.label | ... ++ |
| test.cpp:384:13:384:16 | Load: * ... | semmle.label | Load: * ... |
| test.cpp:384:14:384:16 | end | semmle.label | end |
| test.cpp:388:14:388:27 | new[] | semmle.label | new[] |
| test.cpp:389:16:389:17 | xs | semmle.label | xs |
| test.cpp:392:5:392:6 | xs | semmle.label | xs |
| test.cpp:392:5:392:8 | ... ++ | semmle.label | ... ++ |
| test.cpp:392:5:392:8 | ... ++ | semmle.label | ... ++ |
| test.cpp:392:5:392:8 | ... ++ | semmle.label | ... ++ |
| test.cpp:392:5:392:8 | ... ++ | semmle.label | ... ++ |
| test.cpp:393:9:393:10 | xs | semmle.label | xs |
| test.cpp:393:9:393:10 | xs | semmle.label | xs |
| test.cpp:395:5:395:6 | xs | semmle.label | xs |
| test.cpp:395:5:395:13 | Store: ... = ... | semmle.label | Store: ... = ... |
| test.cpp:404:3:404:25 | ... = ... | semmle.label | ... = ... |
| test.cpp:404:7:404:8 | val indirection [post update] [xs] | semmle.label | val indirection [post update] [xs] |
| test.cpp:404:12:404:25 | new[] | semmle.label | new[] |
| test.cpp:406:3:406:25 | ... = ... | semmle.label | ... = ... |
| test.cpp:406:7:406:8 | val indirection [post update] [xs] | semmle.label | val indirection [post update] [xs] |
| test.cpp:406:12:406:25 | new[] | semmle.label | new[] |
| test.cpp:407:3:407:5 | val indirection [xs] | semmle.label | val indirection [xs] |
| test.cpp:407:3:407:18 | access to array | semmle.label | access to array |
| test.cpp:407:3:407:22 | Store: ... = ... | semmle.label | Store: ... = ... |
| test.cpp:407:7:407:8 | xs | semmle.label | xs |
| test.cpp:407:7:407:8 | xs indirection | semmle.label | xs indirection |
| test.cpp:417:16:417:33 | new[] | semmle.label | new[] |
| test.cpp:419:7:419:8 | xs | semmle.label | xs |
| test.cpp:419:7:419:11 | access to array | semmle.label | access to array |
| test.cpp:419:7:419:15 | Store: ... = ... | semmle.label | Store: ... = ... |
| test.cpp:427:14:427:27 | new[] | semmle.label | new[] |
| test.cpp:433:5:433:6 | xs | semmle.label | xs |
| test.cpp:433:5:433:17 | access to array | semmle.label | access to array |
| test.cpp:433:5:433:21 | Store: ... = ... | semmle.label | Store: ... = ... |
subpaths
#select
| test.cpp:6:14:6:15 | Load: * ... | test.cpp:4:15:4:20 | call to malloc | test.cpp:6:14:6:15 | Load: * ... | This read might be out of bounds, as the pointer might be equal to $@ + $@. | test.cpp:4:15:4:20 | call to malloc | call to malloc | test.cpp:5:19:5:22 | size | size |
@@ -1179,11 +1118,8 @@ subpaths
| test.cpp:264:13:264:14 | Load: * ... | test.cpp:260:13:260:24 | new[] | test.cpp:264:13:264:14 | Load: * ... | This read might be out of bounds, as the pointer might be equal to $@ + $@. | test.cpp:260:13:260:24 | new[] | new[] | test.cpp:261:19:261:21 | len | len |
| test.cpp:274:5:274:10 | Store: ... = ... | test.cpp:270:13:270:24 | new[] | test.cpp:274:5:274:10 | Store: ... = ... | This write might be out of bounds, as the pointer might be equal to $@ + $@. | test.cpp:270:13:270:24 | new[] | new[] | test.cpp:271:19:271:21 | len | len |
| test.cpp:308:5:308:29 | Store: ... = ... | test.cpp:304:15:304:26 | new[] | test.cpp:308:5:308:29 | Store: ... = ... | This write might be out of bounds, as the pointer might be equal to $@ + $@. | test.cpp:304:15:304:26 | new[] | new[] | test.cpp:308:8:308:10 | ... + ... | ... + ... |
| test.cpp:350:15:350:19 | Load: * ... | test.cpp:347:14:347:27 | new[] | test.cpp:350:15:350:19 | Load: * ... | This read might be out of bounds, as the pointer might be equal to $@ + $@. | test.cpp:347:14:347:27 | new[] | new[] | test.cpp:348:20:348:23 | size | size |
| test.cpp:358:14:358:26 | Load: * ... | test.cpp:355:14:355:27 | new[] | test.cpp:358:14:358:26 | Load: * ... | This read might be out of bounds, as the pointer might be equal to $@ + $@ + 1. | test.cpp:355:14:355:27 | new[] | new[] | test.cpp:356:20:356:23 | size | size |
| test.cpp:359:14:359:32 | Load: * ... | test.cpp:355:14:355:27 | new[] | test.cpp:359:14:359:32 | Load: * ... | This read might be out of bounds, as the pointer might be equal to $@ + $@ + 2. | test.cpp:355:14:355:27 | new[] | new[] | test.cpp:356:20:356:23 | size | size |
| test.cpp:372:15:372:16 | Load: * ... | test.cpp:363:14:363:27 | new[] | test.cpp:372:15:372:16 | Load: * ... | This read might be out of bounds, as the pointer might be equal to $@ + $@. | test.cpp:363:14:363:27 | new[] | new[] | test.cpp:365:19:365:22 | size | size |
| test.cpp:384:13:384:16 | Load: * ... | test.cpp:377:14:377:27 | new[] | test.cpp:384:13:384:16 | Load: * ... | This read might be out of bounds, as the pointer might be equal to $@ + $@. | test.cpp:377:14:377:27 | new[] | new[] | test.cpp:378:20:378:23 | size | size |
| test.cpp:395:5:395:13 | Store: ... = ... | test.cpp:388:14:388:27 | new[] | test.cpp:395:5:395:13 | Store: ... = ... | This write might be out of bounds, as the pointer might be equal to $@ + $@. | test.cpp:388:14:388:27 | new[] | new[] | test.cpp:389:19:389:22 | size | size |
| test.cpp:407:3:407:22 | Store: ... = ... | test.cpp:404:12:404:25 | new[] | test.cpp:407:3:407:22 | Store: ... = ... | This write might be out of bounds, as the pointer might be equal to $@ + $@. | test.cpp:404:12:404:25 | new[] | new[] | test.cpp:407:10:407:17 | ... - ... | ... - ... |
| test.cpp:419:7:419:15 | Store: ... = ... | test.cpp:417:16:417:33 | new[] | test.cpp:419:7:419:15 | Store: ... = ... | This write might be out of bounds, as the pointer might be equal to $@ + $@. | test.cpp:417:16:417:33 | new[] | new[] | test.cpp:419:10:419:10 | i | i |
| test.cpp:433:5:433:21 | Store: ... = ... | test.cpp:427:14:427:27 | new[] | test.cpp:433:5:433:21 | Store: ... = ... | This write might be out of bounds, as the pointer might be equal to $@ + $@. | test.cpp:427:14:427:27 | new[] | new[] | test.cpp:433:8:433:16 | ... ++ | ... ++ |

View File

@@ -347,7 +347,7 @@ void test24(unsigned size) {
char *xs = new char[size];
char *end = xs + size;
if (xs < end) {
int val = *xs++; // GOOD
int val = *xs++; // GOOD [FALSE POSITIVE]
}
}
@@ -383,53 +383,3 @@ void test27(unsigned size, bool b) {
int val = *end; // BAD
}
void test28(unsigned size) {
char *xs = new char[size];
char *end = &xs[size];
if (xs >= end)
return;
xs++;
if (xs >= end)
return;
xs[0] = 0; // GOOD [FALSE POSITIVE]
}
struct test29_struct {
char* xs;
};
void test29(unsigned size) {
test29_struct val;
val.xs = new char[size];
size++;
val.xs = new char[size];
val.xs[size - 1] = 0; // GOOD [FALSE POSITIVE]
}
void test30(int *size)
{
int new_size = 0, tmp_size = 0;
test30(&tmp_size);
if (tmp_size + 1 > new_size) {
new_size = tmp_size + 1;
char *xs = new char[new_size];
for (int i = 0; i < new_size; i++) {
xs[i] = 0; // GOOD [FALSE POSITIVE]
}
}
*size = new_size;
}
void test31(unsigned size, unsigned src_pos)
{
char *xs = new char[size];
if (src_pos > size) {
src_pos = size;
}
unsigned dst_pos = src_pos;
if(dst_pos < size - 3) {
xs[dst_pos++] = 0; // GOOD [FALSE POSITIVE]
}
}

View File

@@ -34,6 +34,9 @@ class AstNode extends Node, TAstNode {
override Location getLocation() { result = n.getLocation() }
}
/** DEPRECATED: Alias for AstNode */
deprecated class ASTNode = AstNode;
class IRNode extends Node, TIRNode {
IR::DataFlow::Node n;

View File

@@ -6584,13 +6584,6 @@
| taint.cpp:691:18:691:18 | s [post update] | taint.cpp:695:7:695:7 | s | |
| taint.cpp:691:20:691:20 | ref arg x | taint.cpp:694:9:694:9 | x | |
| taint.cpp:694:7:694:7 | s [post update] | taint.cpp:695:7:695:7 | s | |
| taint.cpp:700:13:700:18 | call to source | taint.cpp:702:11:702:11 | s | |
| taint.cpp:701:9:701:9 | p | taint.cpp:702:4:702:4 | p | |
| taint.cpp:702:4:702:4 | p | taint.cpp:702:4:702:6 | ... ++ | |
| taint.cpp:702:4:702:6 | ... ++ | taint.cpp:702:3:702:6 | * ... | TAINT |
| taint.cpp:702:4:702:6 | ... ++ | taint.cpp:703:8:703:8 | p | TAINT |
| taint.cpp:702:10:702:11 | * ... | taint.cpp:702:3:702:11 | ... = ... | |
| taint.cpp:702:11:702:11 | s | taint.cpp:702:10:702:11 | * ... | TAINT |
| vector.cpp:16:43:16:49 | source1 | vector.cpp:17:26:17:32 | source1 | |
| vector.cpp:16:43:16:49 | source1 | vector.cpp:31:38:31:44 | source1 | |
| vector.cpp:17:21:17:33 | call to vector | vector.cpp:19:14:19:14 | v | |

View File

@@ -693,13 +693,4 @@ void test_argument_source_field_to_obj() {
sink(s); // $ SPURIOUS: ast,ir
sink(s.x); // $ ast,ir
sink(s.y); // clean
}
namespace strings {
void test_write_to_read_then_incr_then_deref() {
char* s = source();
char* p;
*p++ = *s;
sink(p); // $ ast ir
}
}

View File

@@ -24,5 +24,5 @@ Microsoft.Win32,,,8,,,,,,,,,,,,,,8,
MySql.Data.MySqlClient,48,,,,,,,,,,,48,,,,,,
Newtonsoft.Json,,,91,,,,,,,,,,,,,,73,18
ServiceStack,194,,7,27,,,,,75,,,92,,,,,7,
System,65,25,12148,,8,8,9,,,4,3,33,1,17,3,4,10163,1985
System,65,25,12157,,8,8,9,,,4,3,33,1,17,3,4,10163,1994
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:sql-injection source:file source:file-write source:local source:remote summary:taint summary:value
24 MySql.Data.MySqlClient 48 48
25 Newtonsoft.Json 91 73 18
26 ServiceStack 194 7 27 75 92 7
27 System 65 25 12148 12157 8 8 9 4 3 33 1 17 3 4 10163 1985 1994
28 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``",25,12148,65,7
System,"``System.*``, ``System``",25,12157,65,7
Others,"``Dapper``, ``JsonToItemsTaskFactory``, ``Microsoft.ApplicationBlocks.Data``, ``Microsoft.CSharp``, ``Microsoft.EntityFrameworkCore``, ``Microsoft.Extensions.Caching.Distributed``, ``Microsoft.Extensions.Caching.Memory``, ``Microsoft.Extensions.Configuration``, ``Microsoft.Extensions.DependencyInjection``, ``Microsoft.Extensions.DependencyModel``, ``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.NETCore.Platforms.BuildTasks``, ``Microsoft.VisualBasic``, ``Microsoft.Win32``, ``MySql.Data.MySqlClient``, ``Newtonsoft.Json``, ``Windows.Security.Cryptography.Core``",,568,138,
Totals,,25,12723,397,7
Totals,,25,12732,397,7

View File

@@ -120,13 +120,13 @@ namespace Semmle.BuildAnalyser
UseReference(filename);
}
ResolveConflicts();
if (options.UseMscorlib)
{
UseReference(typeof(object).Assembly.Location);
}
ResolveConflicts();
// Output the findings
foreach (var r in usedReferences.Keys)
{

View File

@@ -1,7 +1,3 @@
## 1.5.3
No user-facing changes.
## 1.5.2
No user-facing changes.

View File

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

View File

@@ -1,2 +1,2 @@
---
lastReleaseVersion: 1.5.3
lastReleaseVersion: 1.5.2

View File

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

View File

@@ -1,7 +1,3 @@
## 1.5.3
No user-facing changes.
## 1.5.2
No user-facing changes.

View File

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

View File

@@ -1,2 +1,2 @@
---
lastReleaseVersion: 1.5.3
lastReleaseVersion: 1.5.2

View File

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

View File

@@ -37,13 +37,13 @@ private class MyConsistencyConfiguration extends ConsistencyConfiguration {
}
override predicate postWithInFlowExclude(Node n) {
n instanceof FlowSummaryNode
n instanceof SummaryNode
or
n.asExpr().(ObjectCreation).hasInitializer()
}
override predicate argHasPostUpdateExclude(ArgumentNode n) {
n instanceof FlowSummaryNode
n instanceof SummaryNode
or
not exists(LocalFlow::getAPostUpdateNodeForArg(n.getControlFlowNode()))
or

View File

@@ -1,10 +1,5 @@
from create_database_utils import *
from diagnostics_test_utils import *
# Implicitly build and then run tests.
run_codeql_database_create(['dotnet test'], test_db="test-db", lang="csharp")
run_codeql_database_create(['dotnet test'], db=None, lang="csharp")
check_diagnostics()
# Explicitly build and then run tests.
run_codeql_database_create(['dotnet clean', 'rm -rf test-db', 'dotnet build -o myout', 'dotnet test myout/dotnet_test.dll'], test_db="test2-db", lang="csharp")
check_diagnostics(test_db="test2-db")

View File

@@ -1,10 +0,0 @@
namespace dotnet_test_mstest;
[TestClass]
public class UnitTest1
{
[TestMethod]
public void TestMethod1()
{
}
}

View File

@@ -1 +0,0 @@
global using Microsoft.VisualStudio.TestTools.UnitTesting;

View File

@@ -1,19 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net7.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<IsPackable>false</IsPackable>
<OutputType>Exe</OutputType>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.3.2" />
<PackageReference Include="MSTest.TestAdapter" Version="2.2.10" />
<PackageReference Include="MSTest.TestFramework" Version="2.2.10" />
<PackageReference Include="coverlet.collector" Version="3.1.2" />
</ItemGroup>
</Project>

View File

@@ -1,14 +0,0 @@
import platform
from create_database_utils import *
from diagnostics_test_utils import *
# Implicitly build and then run tests.
run_codeql_database_create(['dotnet test'], test_db="test-db", lang="csharp")
check_diagnostics()
# Fix `dotnet test` picking `x64` on arm-based macOS
architecture = '-a arm64' if platform.machine() == 'arm64' else ''
# Explicitly build and then run tests.
run_codeql_database_create(['dotnet clean', 'rm -rf test-db', 'dotnet build -o myout --os win', 'dotnet test myout/dotnet_test_mstest.exe ' + architecture], test_db="test2-db", lang="csharp")
check_diagnostics(test_db="test2-db")

View File

@@ -1,24 +1,3 @@
## 0.6.3
### Major Analysis Improvements
* The extractor has been changed to run after the traced compiler call. This allows inspecting compiler generated files, such as the output of source generators. With this change, `.cshtml` files and their generated `.cshtml.g.cs` counterparts are extracted on dotnet 6 and above.
### Minor Analysis Improvements
* C#: Analysis of the `dotnet test` command supplied with a `dll` or `exe` file as argument no longer fails due to the addition of an erroneous `-p:SharedCompilation=false` argument.
* Deleted the deprecated `WebConfigXML`, `ConfigurationXMLElement`, `LocationXMLElement`, `SystemWebXMLElement`, `SystemWebServerXMLElement`, `CustomErrorsXMLElement`, and `HttpRuntimeXMLElement` classes from `WebConfig.qll`. The non-deprecated names with PascalCased Xml suffixes should be used instead.
* Deleted the deprecated `Record` class from both `Types.qll` and `Type.qll`.
* Deleted the deprecated `StructuralComparisonConfiguration` class from `StructuralComparison.qll`, use `sameGvn` instead.
* Deleted the deprecated `isParameterOf` predicate from the `ParameterNode` class.
* Deleted the deprecated `SafeExternalAPICallable`, `ExternalAPIDataNode`, `UntrustedDataToExternalAPIConfig`, `UntrustedExternalAPIDataNode`, and `ExternalAPIUsedWithUntrustedData` classes from `ExternalAPIsQuery.qll`. The non-deprecated names with PascalCased Api suffixes should be used instead.
* Updated the following C# sink kind names. Any custom data extensions that use these sink kinds will need to be updated accordingly in order to continue working.
* `code` to `code-injection`
* `sql` to `sql-injection`
* `html` to `html-injection`
* `xss` to `js-injection`
* `remote` to `file-content-store`
## 0.6.2
### Minor Analysis Improvements

View File

@@ -0,0 +1,9 @@
---
category: minorAnalysis
---
* Updated the following C# sink kind names. Any custom data extensions that use these sink kinds will need to be updated accordingly in order to continue working.
* `code` to `code-injection`
* `sql` to `sql-injection`
* `html` to `html-injection`
* `xss` to `js-injection`
* `remote` to `file-content-store`

View File

@@ -0,0 +1,4 @@
---
category: majorAnalysis
---
* The extractor has been changed to run after the traced compiler call. This allows inspecting compiler generated files, such as the output of source generators. With this change, `.cshtml` files and their generated `.cshtml.g.cs` counterparts are extracted on dotnet 6 and above.

View File

@@ -1,20 +1,8 @@
## 0.6.3
### Major Analysis Improvements
* The extractor has been changed to run after the traced compiler call. This allows inspecting compiler generated files, such as the output of source generators. With this change, `.cshtml` files and their generated `.cshtml.g.cs` counterparts are extracted on dotnet 6 and above.
### Minor Analysis Improvements
* C#: Analysis of the `dotnet test` command supplied with a `dll` or `exe` file as argument no longer fails due to the addition of an erroneous `-p:SharedCompilation=false` argument.
---
category: minorAnalysis
---
* Deleted the deprecated `WebConfigXML`, `ConfigurationXMLElement`, `LocationXMLElement`, `SystemWebXMLElement`, `SystemWebServerXMLElement`, `CustomErrorsXMLElement`, and `HttpRuntimeXMLElement` classes from `WebConfig.qll`. The non-deprecated names with PascalCased Xml suffixes should be used instead.
* Deleted the deprecated `Record` class from both `Types.qll` and `Type.qll`.
* Deleted the deprecated `StructuralComparisonConfiguration` class from `StructuralComparison.qll`, use `sameGvn` instead.
* Deleted the deprecated `isParameterOf` predicate from the `ParameterNode` class.
* Deleted the deprecated `SafeExternalAPICallable`, `ExternalAPIDataNode`, `UntrustedDataToExternalAPIConfig`, `UntrustedExternalAPIDataNode`, and `ExternalAPIUsedWithUntrustedData` classes from `ExternalAPIsQuery.qll`. The non-deprecated names with PascalCased Api suffixes should be used instead.
* Updated the following C# sink kind names. Any custom data extensions that use these sink kinds will need to be updated accordingly in order to continue working.
* `code` to `code-injection`
* `sql` to `sql-injection`
* `html` to `html-injection`
* `xss` to `js-injection`
* `remote` to `file-content-store`

View File

@@ -1,4 +0,0 @@
---
category: majorAnalysis
---
* The data flow library now performs type strengthening. This increases precision for all data flow queries by excluding paths that can be inferred to be impossible due to incompatible types.

View File

@@ -1,2 +1,2 @@
---
lastReleaseVersion: 0.6.3
lastReleaseVersion: 0.6.2

View File

@@ -40,7 +40,7 @@ extensions:
- ["System.Collections.Generic", "LinkedList<>", False, "FindLast", "(T)", "", "Argument[this].Element", "ReturnValue", "value", "manual"]
- ["System.Collections.Generic", "LinkedList<>", False, "GetEnumerator", "()", "", "Argument[this].Element", "ReturnValue.Property[System.Collections.Generic.LinkedList<>+Enumerator.Current]", "value", "manual"]
- ["System.Collections.Generic", "List<>", False, "AddRange", "(System.Collections.Generic.IEnumerable<T>)", "", "Argument[0].Element", "Argument[this].Element", "value", "manual"]
- ["System.Collections.Generic", "List<>", False, "AsReadOnly", "()", "", "Argument[this].Element", "ReturnValue.Element", "value", "manual"]
- ["System.Collections.Generic", "List<>", False, "AsReadOnly", "()", "", "Argument[0].Element", "ReturnValue.Element", "value", "manual"]
- ["System.Collections.Generic", "List<>", False, "Find", "(System.Predicate<T>)", "", "Argument[this].Element", "Argument[0].Parameter[0]", "value", "manual"]
- ["System.Collections.Generic", "List<>", False, "Find", "(System.Predicate<T>)", "", "Argument[this].Element", "ReturnValue", "value", "manual"]
- ["System.Collections.Generic", "List<>", False, "FindAll", "(System.Predicate<T>)", "", "Argument[this].Element", "Argument[0].Parameter[0]", "value", "manual"]
@@ -48,8 +48,10 @@ extensions:
- ["System.Collections.Generic", "List<>", False, "FindLast", "(System.Predicate<T>)", "", "Argument[this].Element", "Argument[0].Parameter[0]", "value", "manual"]
- ["System.Collections.Generic", "List<>", False, "FindLast", "(System.Predicate<T>)", "", "Argument[this].Element", "ReturnValue", "value", "manual"]
- ["System.Collections.Generic", "List<>", False, "GetEnumerator", "()", "", "Argument[this].Element", "ReturnValue.Property[System.Collections.Generic.List<>+Enumerator.Current]", "value", "manual"]
- ["System.Collections.Generic", "List<>", False, "GetRange", "(System.Int32,System.Int32)", "", "Argument[this].Element", "ReturnValue.Element", "value", "manual"]
- ["System.Collections.Generic", "List<>", False, "GetRange", "(System.Int32,System.Int32)", "", "Argument[0].Element", "ReturnValue.Element", "value", "manual"]
- ["System.Collections.Generic", "List<>", False, "InsertRange", "(System.Int32,System.Collections.Generic.IEnumerable<T>)", "", "Argument[1].Element", "Argument[this].Element", "value", "manual"]
- ["System.Collections.Generic", "List<>", False, "Reverse", "()", "", "Argument[0].Element", "ReturnValue.Element", "value", "manual"]
- ["System.Collections.Generic", "List<>", False, "Reverse", "(System.Int32,System.Int32)", "", "Argument[0].Element", "ReturnValue.Element", "value", "manual"]
- ["System.Collections.Generic", "Queue<>", False, "Clear", "()", "", "Argument[this].WithoutElement", "Argument[this]", "value", "manual"]
- ["System.Collections.Generic", "Queue<>", False, "CopyTo", "(T[],System.Int32)", "", "Argument[this].Element", "Argument[0].Element", "value", "manual"]
- ["System.Collections.Generic", "Queue<>", False, "GetEnumerator", "()", "", "Argument[this].Element", "ReturnValue.Property[System.Collections.Generic.Queue<>+Enumerator.Current]", "value", "manual"]
@@ -77,7 +79,7 @@ extensions:
- ["System.Collections.Generic", "SortedList<,>+KeyList", False, "Clear", "()", "", "Argument[this].WithoutElement", "Argument[this]", "value", "manual"]
- ["System.Collections.Generic", "SortedList<,>+ValueList", False, "Clear", "()", "", "Argument[this].WithoutElement", "Argument[this]", "value", "manual"]
- ["System.Collections.Generic", "SortedSet<>", False, "GetEnumerator", "()", "", "Argument[this].Element", "ReturnValue.Property[System.Collections.Generic.SortedSet<>+Enumerator.Current]", "value", "manual"]
- ["System.Collections.Generic", "SortedSet<>", False, "Reverse", "()", "", "Argument[this].Element", "ReturnValue.Element", "value", "manual"]
- ["System.Collections.Generic", "SortedSet<>", False, "Reverse", "()", "", "Argument[0].Element", "ReturnValue.Element", "value", "manual"]
- ["System.Collections.Generic", "Stack<>", False, "Clear", "()", "", "Argument[this].WithoutElement", "Argument[this]", "value", "manual"]
- ["System.Collections.Generic", "Stack<>", False, "CopyTo", "(T[],System.Int32)", "", "Argument[this].Element", "Argument[0].Element", "value", "manual"]
- ["System.Collections.Generic", "Stack<>", False, "GetEnumerator", "()", "", "Argument[this].Element", "ReturnValue.Property[System.Collections.Generic.Stack<>+Enumerator.Current]", "value", "manual"]

View File

@@ -20,6 +20,7 @@ extensions:
- ["System.Collections.Immutable", "ImmutableArray<>+Builder", False, "AddRange<>", "(System.Collections.Immutable.ImmutableArray<TDerived>+Builder)", "", "Argument[0].Element", "Argument[this].Element", "value", "manual"]
- ["System.Collections.Immutable", "ImmutableArray<>+Builder", False, "AddRange<>", "(TDerived[])", "", "Argument[0].Element", "Argument[this].Element", "value", "manual"]
- ["System.Collections.Immutable", "ImmutableArray<>+Builder", False, "GetEnumerator", "()", "", "Argument[this].Element", "ReturnValue.Property[System.Collections.Generic.IEnumerator<>.Current]", "value", "manual"]
- ["System.Collections.Immutable", "ImmutableArray<>+Builder", False, "Reverse", "()", "", "Argument[0].Element", "ReturnValue.Element", "value", "manual"]
- ["System.Collections.Immutable", "ImmutableDictionary<,>", False, "Add", "(System.Collections.Generic.KeyValuePair<TKey,TValue>)", "", "Argument[0].Property[System.Collections.Generic.KeyValuePair<,>.Key]", "Argument[this].Element.Property[System.Collections.Generic.KeyValuePair<,>.Key]", "value", "manual"]
- ["System.Collections.Immutable", "ImmutableDictionary<,>", False, "Add", "(System.Collections.Generic.KeyValuePair<TKey,TValue>)", "", "Argument[0].Property[System.Collections.Generic.KeyValuePair<,>.Value]", "Argument[this].Element.Property[System.Collections.Generic.KeyValuePair<,>.Value]", "value", "manual"]
- ["System.Collections.Immutable", "ImmutableDictionary<,>", False, "Add", "(TKey,TValue)", "", "Argument[0]", "Argument[this].Element.Property[System.Collections.Generic.KeyValuePair<,>.Key]", "value", "manual"]
@@ -48,11 +49,11 @@ extensions:
- ["System.Collections.Immutable", "ImmutableList<>", False, "FindLast", "(System.Predicate<T>)", "", "Argument[this].Element", "Argument[0].Parameter[0]", "value", "manual"]
- ["System.Collections.Immutable", "ImmutableList<>", False, "FindLast", "(System.Predicate<T>)", "", "Argument[this].Element", "ReturnValue", "value", "manual"]
- ["System.Collections.Immutable", "ImmutableList<>", False, "GetEnumerator", "()", "", "Argument[this].Element", "ReturnValue.Property[System.Collections.Immutable.ImmutableList<>+Enumerator.Current]", "value", "manual"]
- ["System.Collections.Immutable", "ImmutableList<>", False, "GetRange", "(System.Int32,System.Int32)", "", "Argument[this].Element", "ReturnValue.Element", "value", "manual"]
- ["System.Collections.Immutable", "ImmutableList<>", False, "GetRange", "(System.Int32,System.Int32)", "", "Argument[0].Element", "ReturnValue.Element", "value", "manual"]
- ["System.Collections.Immutable", "ImmutableList<>", False, "Insert", "(System.Int32,T)", "", "Argument[1]", "Argument[this].Element", "value", "manual"]
- ["System.Collections.Immutable", "ImmutableList<>", False, "InsertRange", "(System.Int32,System.Collections.Generic.IEnumerable<T>)", "", "Argument[1].Element", "Argument[this].Element", "value", "manual"]
- ["System.Collections.Immutable", "ImmutableList<>", False, "Reverse", "()", "", "Argument[this].Element", "ReturnValue.Element", "value", "manual"]
- ["System.Collections.Immutable", "ImmutableList<>", False, "Reverse", "(System.Int32,System.Int32)", "", "Argument[this].Element", "ReturnValue.Element", "value", "manual"]
- ["System.Collections.Immutable", "ImmutableList<>", False, "Reverse", "()", "", "Argument[0].Element", "ReturnValue.Element", "value", "manual"]
- ["System.Collections.Immutable", "ImmutableList<>", False, "Reverse", "(System.Int32,System.Int32)", "", "Argument[0].Element", "ReturnValue.Element", "value", "manual"]
- ["System.Collections.Immutable", "ImmutableList<>", False, "get_Item", "(System.Int32)", "", "Argument[this].Element", "ReturnValue", "value", "manual"]
- ["System.Collections.Immutable", "ImmutableList<>+Builder", False, "AddRange", "(System.Collections.Generic.IEnumerable<T>)", "", "Argument[0].Element", "Argument[this].Element", "value", "manual"]
- ["System.Collections.Immutable", "ImmutableList<>+Builder", False, "Find", "(System.Predicate<T>)", "", "Argument[this].Element", "Argument[0].Parameter[0]", "value", "manual"]
@@ -62,8 +63,10 @@ extensions:
- ["System.Collections.Immutable", "ImmutableList<>+Builder", False, "FindLast", "(System.Predicate<T>)", "", "Argument[this].Element", "Argument[0].Parameter[0]", "value", "manual"]
- ["System.Collections.Immutable", "ImmutableList<>+Builder", False, "FindLast", "(System.Predicate<T>)", "", "Argument[this].Element", "ReturnValue", "value", "manual"]
- ["System.Collections.Immutable", "ImmutableList<>+Builder", False, "GetEnumerator", "()", "", "Argument[this].Element", "ReturnValue.Property[System.Collections.Immutable.ImmutableList<>+Enumerator.Current]", "value", "manual"]
- ["System.Collections.Immutable", "ImmutableList<>+Builder", False, "GetRange", "(System.Int32,System.Int32)", "", "Argument[this].Element", "ReturnValue.Element", "value", "manual"]
- ["System.Collections.Immutable", "ImmutableList<>+Builder", False, "GetRange", "(System.Int32,System.Int32)", "", "Argument[0].Element", "ReturnValue.Element", "value", "manual"]
- ["System.Collections.Immutable", "ImmutableList<>+Builder", False, "InsertRange", "(System.Int32,System.Collections.Generic.IEnumerable<T>)", "", "Argument[1].Element", "Argument[this].Element", "value", "manual"]
- ["System.Collections.Immutable", "ImmutableList<>+Builder", False, "Reverse", "()", "", "Argument[0].Element", "ReturnValue.Element", "value", "manual"]
- ["System.Collections.Immutable", "ImmutableList<>+Builder", False, "Reverse", "(System.Int32,System.Int32)", "", "Argument[0].Element", "ReturnValue.Element", "value", "manual"]
- ["System.Collections.Immutable", "ImmutableQueue<>", False, "GetEnumerator", "()", "", "Argument[this].Element", "ReturnValue.Property[System.Collections.Immutable.ImmutableQueue<>+Enumerator.Current]", "value", "manual"]
- ["System.Collections.Immutable", "ImmutableSortedDictionary<,>", False, "Add", "(System.Collections.Generic.KeyValuePair<TKey,TValue>)", "", "Argument[0].Property[System.Collections.Generic.KeyValuePair<,>.Key]", "Argument[this].Element.Property[System.Collections.Generic.KeyValuePair<,>.Key]", "value", "manual"]
- ["System.Collections.Immutable", "ImmutableSortedDictionary<,>", False, "Add", "(System.Collections.Generic.KeyValuePair<TKey,TValue>)", "", "Argument[0].Property[System.Collections.Generic.KeyValuePair<,>.Value]", "Argument[this].Element.Property[System.Collections.Generic.KeyValuePair<,>.Value]", "value", "manual"]
@@ -82,8 +85,8 @@ extensions:
- ["System.Collections.Immutable", "ImmutableSortedDictionary<,>+Builder", False, "get_Values", "()", "", "Argument[this].Element.Property[System.Collections.Generic.KeyValuePair<,>.Value]", "ReturnValue.Element", "value", "manual"]
- ["System.Collections.Immutable", "ImmutableSortedSet<>", False, "Add", "(T)", "", "Argument[0]", "Argument[this].Element", "value", "manual"]
- ["System.Collections.Immutable", "ImmutableSortedSet<>", False, "GetEnumerator", "()", "", "Argument[this].Element", "ReturnValue.Property[System.Collections.Immutable.ImmutableSortedSet<>+Enumerator.Current]", "value", "manual"]
- ["System.Collections.Immutable", "ImmutableSortedSet<>", False, "Reverse", "()", "", "Argument[this].Element", "ReturnValue.Element", "value", "manual"]
- ["System.Collections.Immutable", "ImmutableSortedSet<>", False, "Reverse", "()", "", "Argument[0].Element", "ReturnValue.Element", "value", "manual"]
- ["System.Collections.Immutable", "ImmutableSortedSet<>", False, "get_Item", "(System.Int32)", "", "Argument[this].Element", "ReturnValue", "value", "manual"]
- ["System.Collections.Immutable", "ImmutableSortedSet<>+Builder", False, "GetEnumerator", "()", "", "Argument[this].Element", "ReturnValue.Property[System.Collections.Immutable.ImmutableSortedSet<>+Enumerator.Current]", "value", "manual"]
- ["System.Collections.Immutable", "ImmutableSortedSet<>+Builder", False, "Reverse", "()", "", "Argument[this].Element", "ReturnValue.Element", "value", "manual"]
- ["System.Collections.Immutable", "ImmutableSortedSet<>+Builder", False, "Reverse", "()", "", "Argument[0].Element", "ReturnValue.Element", "value", "manual"]
- ["System.Collections.Immutable", "ImmutableStack<>", False, "GetEnumerator", "()", "", "Argument[this].Element", "ReturnValue.Property[System.Collections.Immutable.ImmutableStack<>+Enumerator.Current]", "value", "manual"]

View File

@@ -9,7 +9,7 @@ extensions:
- ["System.Collections.Specialized", "NameValueCollection", False, "Add", "(System.Collections.Specialized.NameValueCollection)", "", "Argument[0]", "Argument[this].Element", "value", "manual"]
- ["System.Collections.Specialized", "NameValueCollection", True, "Clear", "()", "", "Argument[this].WithoutElement", "Argument[this]", "value", "manual"]
- ["System.Collections.Specialized", "NameValueCollection", False, "CopyTo", "(System.Array,System.Int32)", "", "Argument[this].Element", "Argument[0].Element", "value", "manual"]
- ["System.Collections.Specialized", "OrderedDictionary", False, "AsReadOnly", "()", "", "Argument[this].Element", "ReturnValue.Element", "value", "manual"]
- ["System.Collections.Specialized", "OrderedDictionary", False, "AsReadOnly", "()", "", "Argument[0].Element", "ReturnValue.Element", "value", "manual"]
- ["System.Collections.Specialized", "StringCollection", False, "Add", "(System.String)", "", "Argument[0]", "Argument[this].Element", "value", "manual"]
- ["System.Collections.Specialized", "StringCollection", False, "AddRange", "(System.String[])", "", "Argument[0].Element", "Argument[this].Element", "value", "manual"]
- ["System.Collections.Specialized", "StringCollection", False, "CopyTo", "(System.String[],System.Int32)", "", "Argument[this].Element", "Argument[0].Element", "value", "manual"]

View File

@@ -4,15 +4,17 @@ extensions:
extensible: summaryModel
data:
- ["System.Collections", "ArrayList", False, "AddRange", "(System.Collections.ICollection)", "", "Argument[0].Element", "Argument[this].Element", "value", "manual"]
- ["System.Collections", "ArrayList", False, "Clone", "()", "", "Argument[this].Element", "ReturnValue.Element", "value", "manual"]
- ["System.Collections", "ArrayList", False, "Clone", "()", "", "Argument[0].Element", "ReturnValue.Element", "value", "manual"]
- ["System.Collections", "ArrayList", False, "FixedSize", "(System.Collections.ArrayList)", "", "Argument[0].Element", "ReturnValue.Element", "value", "manual"]
- ["System.Collections", "ArrayList", False, "FixedSize", "(System.Collections.IList)", "", "Argument[0].Element", "ReturnValue.Element", "value", "manual"]
- ["System.Collections", "ArrayList", False, "GetEnumerator", "(System.Int32,System.Int32)", "", "Argument[this].Element", "ReturnValue.Property[System.Collections.IEnumerator.Current]", "value", "manual"]
- ["System.Collections", "ArrayList", False, "GetRange", "(System.Int32,System.Int32)", "", "Argument[this].Element", "ReturnValue.Element", "value", "manual"]
- ["System.Collections", "ArrayList", False, "GetRange", "(System.Int32,System.Int32)", "", "Argument[0].Element", "ReturnValue.Element", "value", "manual"]
- ["System.Collections", "ArrayList", False, "InsertRange", "(System.Int32,System.Collections.ICollection)", "", "Argument[1].Element", "Argument[this].Element", "value", "manual"]
- ["System.Collections", "ArrayList", False, "Repeat", "(System.Object,System.Int32)", "", "Argument[0]", "ReturnValue.Element", "value", "manual"]
- ["System.Collections", "BitArray", False, "Clone", "()", "", "Argument[this].Element", "ReturnValue.Element", "value", "manual"]
- ["System.Collections", "Hashtable", False, "Clone", "()", "", "Argument[this].Element", "ReturnValue.Element", "value", "manual"]
- ["System.Collections", "ArrayList", False, "Reverse", "()", "", "Argument[0].Element", "ReturnValue.Element", "value", "manual"]
- ["System.Collections", "ArrayList", False, "Reverse", "(System.Int32,System.Int32)", "", "Argument[0].Element", "ReturnValue.Element", "value", "manual"]
- ["System.Collections", "BitArray", False, "Clone", "()", "", "Argument[0].Element", "ReturnValue.Element", "value", "manual"]
- ["System.Collections", "Hashtable", False, "Clone", "()", "", "Argument[0].Element", "ReturnValue.Element", "value", "manual"]
- ["System.Collections", "Hashtable", False, "Hashtable", "(System.Collections.IDictionary)", "", "Argument[0].Element.Property[System.Collections.Generic.KeyValuePair<,>.Key]", "Argument[this].Element.Property[System.Collections.Generic.KeyValuePair<,>.Key]", "value", "manual"]
- ["System.Collections", "Hashtable", False, "Hashtable", "(System.Collections.IDictionary)", "", "Argument[0].Element.Property[System.Collections.Generic.KeyValuePair<,>.Value]", "Argument[this].Element.Property[System.Collections.Generic.KeyValuePair<,>.Value]", "value", "manual"]
- ["System.Collections", "Hashtable", False, "Hashtable", "(System.Collections.IDictionary,System.Collections.IEqualityComparer)", "", "Argument[0].Element.Property[System.Collections.Generic.KeyValuePair<,>.Key]", "Argument[this].Element.Property[System.Collections.Generic.KeyValuePair<,>.Key]", "value", "manual"]
@@ -41,9 +43,9 @@ extensions:
- ["System.Collections", "IList", True, "get_Item", "(System.Int32)", "", "Argument[this].Element", "ReturnValue", "value", "manual"]
- ["System.Collections", "IList", True, "set_Item", "(System.Int32,System.Object)", "", "Argument[1]", "Argument[this].Element", "value", "manual"]
- ["System.Collections", "Queue", True, "Clear", "()", "", "Argument[this].WithoutElement", "Argument[this]", "value", "manual"]
- ["System.Collections", "Queue", False, "Clone", "()", "", "Argument[this].Element", "ReturnValue.Element", "value", "manual"]
- ["System.Collections", "Queue", False, "Clone", "()", "", "Argument[0].Element", "ReturnValue.Element", "value", "manual"]
- ["System.Collections", "Queue", False, "Peek", "()", "", "Argument[this].Element", "ReturnValue", "value", "manual"]
- ["System.Collections", "SortedList", False, "Clone", "()", "", "Argument[this].Element", "ReturnValue.Element", "value", "manual"]
- ["System.Collections", "SortedList", False, "Clone", "()", "", "Argument[0].Element", "ReturnValue.Element", "value", "manual"]
- ["System.Collections", "SortedList", False, "GetByIndex", "(System.Int32)", "", "Argument[this].Element.Property[System.Collections.Generic.KeyValuePair<,>.Value]", "ReturnValue", "value", "manual"]
- ["System.Collections", "SortedList", False, "GetValueList", "()", "", "Argument[this].Element.Property[System.Collections.Generic.KeyValuePair<,>.Value]", "ReturnValue.Element", "value", "manual"]
- ["System.Collections", "SortedList", False, "SortedList", "(System.Collections.IDictionary)", "", "Argument[0].Element.Property[System.Collections.Generic.KeyValuePair<,>.Key]", "Argument[this].Element.Property[System.Collections.Generic.KeyValuePair<,>.Key]", "value", "manual"]
@@ -51,6 +53,6 @@ extensions:
- ["System.Collections", "SortedList", False, "SortedList", "(System.Collections.IDictionary,System.Collections.IComparer)", "", "Argument[0].Element.Property[System.Collections.Generic.KeyValuePair<,>.Key]", "Argument[this].Element.Property[System.Collections.Generic.KeyValuePair<,>.Key]", "value", "manual"]
- ["System.Collections", "SortedList", False, "SortedList", "(System.Collections.IDictionary,System.Collections.IComparer)", "", "Argument[0].Element.Property[System.Collections.Generic.KeyValuePair<,>.Value]", "Argument[this].Element.Property[System.Collections.Generic.KeyValuePair<,>.Value]", "value", "manual"]
- ["System.Collections", "Stack", False, "Clear", "()", "", "Argument[this].WithoutElement", "Argument[this]", "value", "manual"]
- ["System.Collections", "Stack", False, "Clone", "()", "", "Argument[this].Element", "ReturnValue.Element", "value", "manual"]
- ["System.Collections", "Stack", False, "Clone", "()", "", "Argument[0].Element", "ReturnValue.Element", "value", "manual"]
- ["System.Collections", "Stack", False, "Peek", "()", "", "Argument[this].Element", "ReturnValue", "value", "manual"]
- ["System.Collections", "Stack", False, "Pop", "()", "", "Argument[this].Element", "ReturnValue", "value", "manual"]

View File

@@ -58,7 +58,7 @@ extensions:
- ["System.Data", "IDataParameterCollection", True, "set_Item", "(System.String,System.Object)", "", "Argument[1]", "Argument[this].Element", "value", "manual"]
- ["System.Data", "ITableMappingCollection", True, "get_Item", "(System.String)", "", "Argument[this].Element", "ReturnValue", "value", "manual"]
- ["System.Data", "ITableMappingCollection", True, "set_Item", "(System.String,System.Object)", "", "Argument[1]", "Argument[this].Element", "value", "manual"]
- ["System.Data", "PropertyCollection", False, "Clone", "()", "", "Argument[this].Element", "ReturnValue.Element", "value", "manual"]
- ["System.Data", "PropertyCollection", False, "Clone", "()", "", "Argument[0].Element", "ReturnValue.Element", "value", "manual"]
- ["System.Data", "TypedTableBaseExtensions", False, "AsEnumerable<>", "(System.Data.TypedTableBase<TRow>)", "", "Argument[0].Element", "ReturnValue.Element", "value", "manual"]
- ["System.Data", "TypedTableBaseExtensions", False, "ElementAtOrDefault<>", "(System.Data.TypedTableBase<TRow>,System.Int32)", "", "Argument[0].Element", "ReturnValue", "value", "manual"]
- ["System.Data", "TypedTableBaseExtensions", False, "OrderBy<,>", "(System.Data.TypedTableBase<TRow>,System.Func<TRow,TKey>)", "", "Argument[0].Element", "Argument[1].Parameter[0]", "value", "manual"]

View File

@@ -6,4 +6,6 @@ extensions:
- ["System.Runtime.CompilerServices", "ConditionalWeakTable<,>", False, "Clear", "()", "", "Argument[this].WithoutElement", "Argument[this]", "value", "manual"]
- ["System.Runtime.CompilerServices", "ConfiguredTaskAwaitable<>", False, "GetAwaiter", "()", "", "Argument[this].SyntheticField[m_configuredTaskAwaiter]", "ReturnValue", "value", "manual"]
- ["System.Runtime.CompilerServices", "ConfiguredTaskAwaitable<>+ConfiguredTaskAwaiter", False, "GetResult", "()", "", "Argument[this].SyntheticField[m_task_configured_task_awaitable].Property[System.Threading.Tasks.Task<>.Result]", "ReturnValue", "value", "manual"]
- ["System.Runtime.CompilerServices", "ReadOnlyCollectionBuilder<>", False, "Reverse", "()", "", "Argument[0].Element", "ReturnValue.Element", "value", "manual"]
- ["System.Runtime.CompilerServices", "ReadOnlyCollectionBuilder<>", False, "Reverse", "(System.Int32,System.Int32)", "", "Argument[0].Element", "ReturnValue.Element", "value", "manual"]
- ["System.Runtime.CompilerServices", "TaskAwaiter<>", False, "GetResult", "()", "", "Argument[this].SyntheticField[m_task_task_awaiter].Property[System.Threading.Tasks.Task<>.Result]", "ReturnValue", "value", "manual"]

View File

@@ -13,7 +13,7 @@ extensions:
- ["System", "Array", False, "AsReadOnly<>", "(T[])", "", "Argument[0].Element", "ReturnValue.Element", "value", "manual"]
- ["System", "Array", False, "Clear", "(System.Array)", "", "Argument[0].WithoutElement", "Argument[0]", "value", "manual"]
- ["System", "Array", False, "Clear", "(System.Array,System.Int32,System.Int32)", "", "Argument[0].WithoutElement", "Argument[0]", "value", "manual"]
- ["System", "Array", False, "Clone", "()", "", "Argument[this].Element", "ReturnValue.Element", "value", "manual"]
- ["System", "Array", False, "Clone", "()", "", "Argument[0].Element", "ReturnValue.Element", "value", "manual"]
- ["System", "Array", False, "CopyTo", "(System.Array,System.Int64)", "", "Argument[this].Element", "Argument[0].Element", "value", "manual"]
- ["System", "Array", False, "Find<>", "(T[],System.Predicate<T>)", "", "Argument[0].Element", "Argument[1].Parameter[0]", "value", "manual"]
- ["System", "Array", False, "Find<>", "(T[],System.Predicate<T>)", "", "Argument[0].Element", "ReturnValue", "value", "manual"]

View File

@@ -1,12 +1,11 @@
name: codeql/csharp-all
version: 0.6.4-dev
version: 0.6.3-dev
groups: csharp
dbscheme: semmlecode.csharp.dbscheme
extractor: csharp
library: true
upgrades: upgrades
dependencies:
codeql/mad: ${workspace}
codeql/ssa: ${workspace}
codeql/tutorial: ${workspace}
codeql/util: ${workspace}

View File

@@ -62,8 +62,8 @@
* in the given range. The range is inclusive at both ends.
* - "ReturnValue": Selects the return value of a call to the selected element.
*
* For summaries, `input` and `output` may be suffixed by any number of the
* following, separated by ".":
* For summaries, `input` and `output` may be prefixed by one of the following,
* separated by the "of" keyword:
* - "Element": Selects an element in a collection.
* - "Field[f]": Selects the contents of field `f`.
* - "Property[p]": Selects the contents of property `p`.
@@ -95,7 +95,6 @@ private import internal.DataFlowPublic
private import internal.FlowSummaryImpl::Public
private import internal.FlowSummaryImpl::Private::External
private import internal.FlowSummaryImplSpecific
private import codeql.mad.ModelValidation as SharedModelVal
/** Holds if a source model exists for the given parameters. */
predicate sourceModel = Extensions::sourceModel/9;
@@ -205,18 +204,30 @@ module ModelValidation {
)
}
private module KindValConfig implements SharedModelVal::KindValidationConfigSig {
predicate summaryKind(string kind) { summaryModel(_, _, _, _, _, _, _, _, kind, _) }
predicate sinkKind(string kind) { sinkModel(_, _, _, _, _, _, _, kind, _) }
predicate sourceKind(string kind) { sourceModel(_, _, _, _, _, _, _, kind, _) }
predicate neutralKind(string kind) { neutralModel(_, _, _, _, kind, _) }
private string getInvalidModelKind() {
exists(string kind | summaryModel(_, _, _, _, _, _, _, _, kind, _) |
not kind = ["taint", "value"] and
result = "Invalid kind \"" + kind + "\" in summary model."
)
or
exists(string kind | sinkModel(_, _, _, _, _, _, _, kind, _) |
not kind =
["code-injection", "sql-injection", "js-injection", "html-injection", "file-content-store"] and
not kind.matches("encryption-%") and
result = "Invalid kind \"" + kind + "\" in sink model."
)
or
exists(string kind | sourceModel(_, _, _, _, _, _, _, kind, _) |
not kind = ["local", "remote", "file", "file-write"] and
result = "Invalid kind \"" + kind + "\" in source model."
)
or
exists(string kind | neutralModel(_, _, _, _, kind, _) |
not kind = ["summary", "source", "sink"] and
result = "Invalid kind \"" + kind + "\" in neutral model."
)
}
private module KindVal = SharedModelVal::KindValidation<KindValConfig>;
private string getInvalidModelSignature() {
exists(
string pred, string namespace, string type, string name, string signature, string ext,
@@ -258,7 +269,7 @@ module ModelValidation {
msg =
[
getInvalidModelSignature(), getInvalidModelInput(), getInvalidModelOutput(),
KindVal::getInvalidModelKind()
getInvalidModelKind()
]
}
}

View File

@@ -64,9 +64,14 @@ module SummaryComponent {
/** Gets a summary component that represents the return value of a call. */
SummaryComponent return() { result = return(any(DataFlowDispatch::NormalReturnKind rk)) }
predicate syntheticGlobal = SummaryComponentInternal::syntheticGlobal/1;
class SyntheticGlobal = SummaryComponentInternal::SyntheticGlobal;
/** Gets a summary component that represents a jump to `c`. */
SummaryComponent jump(Callable c) {
result =
return(any(DataFlowDispatch::JumpReturnKind jrk |
jrk.getTarget() = c.getUnboundDeclaration() and
jrk.getTargetReturnKind() instanceof DataFlowDispatch::NormalReturnKind
))
}
}
class SummaryComponentStack = Impl::Public::SummaryComponentStack;
@@ -105,13 +110,8 @@ module SummaryComponentStack {
/** Gets a singleton stack representing the return value of a call. */
SummaryComponentStack return() { result = singleton(SummaryComponent::return()) }
/** Gets a singleton stack representing a synthetic global with name `name`. */
SummaryComponentStack syntheticGlobal(string synthetic) {
result = singleton(SummaryComponent::syntheticGlobal(synthetic))
}
/** Gets a textual representation of this stack used for flow summaries. */
string getComponentStack(SummaryComponentStack s) { result = Impl::Public::getComponentStack(s) }
/** Gets a singleton stack representing a jump to `c`. */
SummaryComponentStack jump(Callable c) { result = singleton(SummaryComponent::jump(c)) }
}
class SummarizedCallable = Impl::Public::SummarizedCallable;

View File

@@ -74,6 +74,18 @@ newtype TReturnKind =
exists(Ssa::ExplicitDefinition def | def.isCapturedVariableDefinitionFlowOut(_, _) |
v = def.getSourceVariable().getAssignable()
)
} or
TJumpReturnKind(Callable target, ReturnKind rk) {
target.isUnboundDeclaration() and
(
rk instanceof NormalReturnKind and
(
target instanceof Constructor or
not target.getReturnType() instanceof VoidType
)
or
exists(target.getParameter(rk.(OutRefReturnKind).getPosition()))
)
}
/**
@@ -116,9 +128,7 @@ private module Cached {
// No need to include calls that are compiled from source
not call.getImplementation().getMethod().compiledFromSource()
} or
TSummaryCall(
FlowSummaryImpl::Public::SummarizedCallable c, FlowSummaryImpl::Private::SummaryNode receiver
) {
TSummaryCall(FlowSummaryImpl::Public::SummarizedCallable c, Node receiver) {
FlowSummaryImpl::Private::summaryCallbackRange(c, receiver)
}
@@ -245,6 +255,27 @@ class ImplicitCapturedReturnKind extends ReturnKind, TImplicitCapturedReturnKind
override string toString() { result = "captured " + v }
}
/**
* A value returned through the output of another callable.
*
* This is currently only used to model flow summaries where data may flow into
* one API entry point and out of another.
*/
class JumpReturnKind extends ReturnKind, TJumpReturnKind {
private Callable target;
private ReturnKind rk;
JumpReturnKind() { this = TJumpReturnKind(target, rk) }
/** Gets the target of the jump. */
Callable getTarget() { result = target }
/** Gets the return kind of the target. */
ReturnKind getTargetReturnKind() { result = rk }
override string toString() { result = "jump to " + target }
}
/** A callable used for data flow. */
class DataFlowCallable extends TDataFlowCallable {
/** Get the underlying source code callable, if any. */
@@ -441,12 +472,12 @@ class CilDataFlowCall extends DataFlowCall, TCilCall {
*/
class SummaryCall extends DelegateDataFlowCall, TSummaryCall {
private FlowSummaryImpl::Public::SummarizedCallable c;
private FlowSummaryImpl::Private::SummaryNode receiver;
private Node receiver;
SummaryCall() { this = TSummaryCall(c, receiver) }
/** Gets the data flow node that this call targets. */
FlowSummaryImpl::Private::SummaryNode getReceiver() { result = receiver }
Node getReceiver() { result = receiver }
override DataFlowCallable getARuntimeTarget() {
none() // handled by the shared library

View File

@@ -1135,8 +1135,8 @@ module Impl<FullStateConfigSig Config> {
DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow
);
bindingset[node, state, t0, ap]
predicate filter(NodeEx node, FlowState state, Typ t0, Ap ap, Typ t);
bindingset[node, state, t, ap]
predicate filter(NodeEx node, FlowState state, Typ t, Ap ap);
bindingset[typ, contentType]
predicate typecheckStore(Typ typ, DataFlowType contentType);
@@ -1199,21 +1199,17 @@ module Impl<FullStateConfigSig Config> {
NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, TypOption argT,
ApOption argAp, Typ t, Ap ap, ApApprox apa
) {
fwdFlow1(node, state, cc, summaryCtx, argT, argAp, _, t, ap, apa)
}
private predicate fwdFlow1(
NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, TypOption argT,
ApOption argAp, Typ t0, Typ t, Ap ap, ApApprox apa
) {
fwdFlow0(node, state, cc, summaryCtx, argT, argAp, t0, ap, apa) and
fwdFlow0(node, state, cc, summaryCtx, argT, argAp, t, ap, apa) and
PrevStage::revFlow(node, state, apa) and
filter(node, state, t0, ap, t)
filter(node, state, t, ap)
}
pragma[nomagic]
private predicate typeStrengthen(Typ t0, Ap ap, Typ t) {
fwdFlow1(_, _, _, _, _, _, t0, t, ap, _) and t0 != t
pragma[inline]
additional predicate fwdFlow(
NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, TypOption argT,
ApOption argAp, Typ t, Ap ap
) {
fwdFlow(node, state, cc, summaryCtx, argT, argAp, t, ap, _)
}
pragma[assume_small_delta]
@@ -1343,11 +1339,6 @@ module Impl<FullStateConfigSig Config> {
private predicate fwdFlowConsCand(Typ t2, Ap cons, Content c, Typ t1, Ap tail) {
fwdFlowStore(_, t1, tail, c, t2, _, _, _, _, _, _) and
cons = apCons(c, t1, tail)
or
exists(Typ t0 |
typeStrengthen(t0, cons, t2) and
fwdFlowConsCand(t0, cons, c, t1, tail)
)
}
pragma[nomagic]
@@ -1368,7 +1359,7 @@ module Impl<FullStateConfigSig Config> {
ParamNodeOption summaryCtx, TypOption argT, ApOption argAp
) {
exists(ApHeadContent apc |
fwdFlow(node1, state, cc, summaryCtx, argT, argAp, t, ap, _) and
fwdFlow(node1, state, cc, summaryCtx, argT, argAp, t, ap) and
apc = getHeadContent(ap) and
readStepCand0(node1, apc, c, node2)
)
@@ -1529,14 +1520,14 @@ module Impl<FullStateConfigSig Config> {
NodeEx node, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap
) {
revFlow0(node, state, returnCtx, returnAp, ap) and
fwdFlow(node, state, _, _, _, _, _, ap, _)
fwdFlow(node, state, _, _, _, _, _, ap)
}
pragma[nomagic]
private predicate revFlow0(
NodeEx node, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap
) {
fwdFlow(node, state, _, _, _, _, _, ap, _) and
fwdFlow(node, state, _, _, _, _, _, ap) and
sinkNode(node, state) and
(
if hasSinkCallCtx()
@@ -1789,13 +1780,13 @@ module Impl<FullStateConfigSig Config> {
boolean fwd, int nodes, int fields, int conscand, int states, int tuples
) {
fwd = true and
nodes = count(NodeEx node | fwdFlow(node, _, _, _, _, _, _, _, _)) and
nodes = count(NodeEx node | fwdFlow(node, _, _, _, _, _, _, _)) and
fields = count(Content f0 | fwdConsCand(f0, _, _)) and
conscand = count(Content f0, Typ t, Ap ap | fwdConsCand(f0, t, ap)) and
states = count(FlowState state | fwdFlow(_, state, _, _, _, _, _, _, _)) and
states = count(FlowState state | fwdFlow(_, state, _, _, _, _, _, _)) and
tuples =
count(NodeEx n, FlowState state, Cc cc, ParamNodeOption summaryCtx, TypOption argT,
ApOption argAp, Typ t, Ap ap | fwdFlow(n, state, cc, summaryCtx, argT, argAp, t, ap, _))
ApOption argAp, Typ t, Ap ap | fwdFlow(n, state, cc, summaryCtx, argT, argAp, t, ap))
or
fwd = false and
nodes = count(NodeEx node | revFlow(node, _, _, _, _)) and
@@ -1972,10 +1963,10 @@ module Impl<FullStateConfigSig Config> {
)
}
bindingset[node, state, t0, ap]
predicate filter(NodeEx node, FlowState state, Typ t0, Ap ap, Typ t) {
bindingset[node, state, t, ap]
predicate filter(NodeEx node, FlowState state, Typ t, Ap ap) {
PrevStage::revFlowState(state) and
t0 = t and
exists(t) and
exists(ap) and
not stateBarrier(node, state) and
(
@@ -2021,8 +2012,7 @@ module Impl<FullStateConfigSig Config> {
FlowCheckNode() {
castNode(this.asNode()) or
clearsContentCached(this.asNode(), _) or
expectsContentCached(this.asNode(), _) or
neverSkipInPathGraph(this.asNode())
expectsContentCached(this.asNode(), _)
}
}
@@ -2207,8 +2197,8 @@ module Impl<FullStateConfigSig Config> {
import BooleanCallContext
predicate localStep(
NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, Typ t,
LocalCc lcc
NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue,
DataFlowType t, LocalCc lcc
) {
localFlowBigStep(node1, state1, node2, state2, preservesValue, t, _) and
exists(lcc)
@@ -2228,16 +2218,10 @@ module Impl<FullStateConfigSig Config> {
)
}
bindingset[node, state, t0, ap]
predicate filter(NodeEx node, FlowState state, Typ t0, Ap ap, Typ t) {
bindingset[node, state, t, ap]
predicate filter(NodeEx node, FlowState state, Typ t, Ap ap) {
exists(state) and
// We can get away with not using type strengthening here, since we aren't
// going to use the tracked types in the construction of Stage 4 access
// paths. For Stage 4 and onwards, the tracked types must be consistent as
// the cons candidates including types are used to construct subsequent
// access path approximations.
t0 = t and
(if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), t0) else any()) and
(if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), t) else any()) and
(
notExpectsContent(node)
or
@@ -2257,16 +2241,6 @@ module Impl<FullStateConfigSig Config> {
import MkStage<Stage2>::Stage<Stage3Param>
}
bindingset[node, t0]
private predicate strengthenType(NodeEx node, DataFlowType t0, DataFlowType t) {
if castingNodeEx(node)
then
exists(DataFlowType nt | nt = node.getDataFlowType() |
if typeStrongerThan(nt, t0) then t = nt else (compatibleTypes(nt, t0) and t = t0)
)
else t = t0
}
private module Stage4Param implements MkStage<Stage3>::StageParam {
private module PrevStage = Stage3;
@@ -2300,8 +2274,8 @@ module Impl<FullStateConfigSig Config> {
pragma[nomagic]
predicate localStep(
NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, Typ t,
LocalCc lcc
NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue,
DataFlowType t, LocalCc lcc
) {
localFlowBigStep(node1, state1, node2, state2, preservesValue, t, _) and
PrevStage::revFlow(node1, pragma[only_bind_into](state1), _) and
@@ -2359,11 +2333,11 @@ module Impl<FullStateConfigSig Config> {
)
}
bindingset[node, state, t0, ap]
predicate filter(NodeEx node, FlowState state, Typ t0, Ap ap, Typ t) {
bindingset[node, state, t, ap]
predicate filter(NodeEx node, FlowState state, Typ t, Ap ap) {
exists(state) and
not clear(node, ap) and
strengthenType(node, t0, t) and
(if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), t) else any()) and
(
notExpectsContent(node)
or
@@ -2391,7 +2365,7 @@ module Impl<FullStateConfigSig Config> {
exists(AccessPathFront apf |
Stage4::revFlow(node, state, TReturnCtxMaybeFlowThrough(_), _, apf) and
Stage4::fwdFlow(node, state, any(Stage4::CcCall ccc), _, _, TAccessPathFrontSome(argApf), _,
apf, _)
apf)
)
}
@@ -2605,8 +2579,8 @@ module Impl<FullStateConfigSig Config> {
import LocalCallContext
predicate localStep(
NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, Typ t,
LocalCc lcc
NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue,
DataFlowType t, LocalCc lcc
) {
localFlowBigStep(node1, state1, node2, state2, preservesValue, t, lcc) and
PrevStage::revFlow(node1, pragma[only_bind_into](state1), _) and
@@ -2635,9 +2609,9 @@ module Impl<FullStateConfigSig Config> {
)
}
bindingset[node, state, t0, ap]
predicate filter(NodeEx node, FlowState state, Typ t0, Ap ap, Typ t) {
strengthenType(node, t0, t) and
bindingset[node, state, t, ap]
predicate filter(NodeEx node, FlowState state, Typ t, Ap ap) {
(if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), t) else any()) and
exists(state) and
exists(ap)
}
@@ -2658,7 +2632,7 @@ module Impl<FullStateConfigSig Config> {
Stage5::parameterMayFlowThrough(p, _) and
Stage5::revFlow(n, state, TReturnCtxMaybeFlowThrough(_), _, apa0) and
Stage5::fwdFlow(n, state, any(CallContextCall ccc), TParamNodeSome(p.asNode()), _,
TAccessPathApproxSome(apa), _, apa0, _)
TAccessPathApproxSome(apa), _, apa0)
)
}
@@ -2675,7 +2649,7 @@ module Impl<FullStateConfigSig Config> {
TSummaryCtxSome(ParamNodeEx p, FlowState state, DataFlowType t, AccessPath ap) {
exists(AccessPathApprox apa | ap.getApprox() = apa |
Stage5::parameterMayFlowThrough(p, apa) and
Stage5::fwdFlow(p, state, _, _, Option<DataFlowType>::some(t), _, _, apa, _) and
Stage5::fwdFlow(p, state, _, _, _, _, t, apa) and
Stage5::revFlow(p, state, _)
)
}
@@ -2846,7 +2820,9 @@ module Impl<FullStateConfigSig Config> {
ap = TAccessPathNil()
or
// ... or a step from an existing PathNode to another node.
pathStep(_, node, state, cc, sc, t, ap)
pathStep(_, node, state, cc, sc, t, ap) and
Stage5::revFlow(node, state, ap.getApprox()) and
(if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), t) else any())
} or
TPathNodeSink(NodeEx node, FlowState state) {
exists(PathNodeMid sink |
@@ -3364,24 +3340,13 @@ module Impl<FullStateConfigSig Config> {
ap = mid.getAp()
}
private predicate pathStep(
PathNodeMid mid, NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, DataFlowType t,
AccessPath ap
) {
exists(DataFlowType t0 |
pathStep0(mid, node, state, cc, sc, t0, ap) and
Stage5::revFlow(node, state, ap.getApprox()) and
strengthenType(node, t0, t)
)
}
/**
* Holds if data may flow from `mid` to `node`. The last step in or out of
* a callable is recorded by `cc`.
*/
pragma[assume_small_delta]
pragma[nomagic]
private predicate pathStep0(
private predicate pathStep(
PathNodeMid mid, NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, DataFlowType t,
AccessPath ap
) {
@@ -3999,7 +3964,7 @@ module Impl<FullStateConfigSig Config> {
ap = TPartialNil() and
exists(explorationLimit())
or
partialPathStep(_, node, state, cc, sc1, sc2, sc3, sc4, t, ap) and
partialPathNodeMk0(node, state, cc, sc1, sc2, sc3, sc4, t, ap) and
distSrc(node.getEnclosingCallable()) <= explorationLimit()
} or
TPartialPathNodeRev(
@@ -4025,20 +3990,11 @@ module Impl<FullStateConfigSig Config> {
}
pragma[nomagic]
private predicate partialPathStep(
PartialPathNodeFwd mid, NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1,
TSummaryCtx2 sc2, TSummaryCtx3 sc3, TSummaryCtx4 sc4, DataFlowType t, PartialAccessPath ap
private predicate partialPathNodeMk0(
NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2,
TSummaryCtx3 sc3, TSummaryCtx4 sc4, DataFlowType t, PartialAccessPath ap
) {
partialPathStep1(mid, node, state, cc, sc1, sc2, sc3, sc4, _, t, ap)
}
pragma[nomagic]
private predicate partialPathStep1(
PartialPathNodeFwd mid, NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1,
TSummaryCtx2 sc2, TSummaryCtx3 sc3, TSummaryCtx4 sc4, DataFlowType t0, DataFlowType t,
PartialAccessPath ap
) {
partialPathStep0(mid, node, state, cc, sc1, sc2, sc3, sc4, t0, ap) and
partialPathStep(_, node, state, cc, sc1, sc2, sc3, sc4, t, ap) and
not fullBarrier(node) and
not stateBarrier(node, state) and
not clearsContentEx(node, ap.getHead()) and
@@ -4046,14 +4002,9 @@ module Impl<FullStateConfigSig Config> {
notExpectsContent(node) or
expectsContentEx(node, ap.getHead())
) and
strengthenType(node, t0, t)
}
pragma[nomagic]
private predicate partialPathTypeStrengthen(
DataFlowType t0, PartialAccessPath ap, DataFlowType t
) {
partialPathStep1(_, _, _, _, _, _, _, _, t0, t, ap) and t0 != t
if node.asNode() instanceof CastingNode
then compatibleTypes(node.getDataFlowType(), t)
else any()
}
/**
@@ -4232,8 +4183,7 @@ module Impl<FullStateConfigSig Config> {
}
}
pragma[nomagic]
private predicate partialPathStep0(
private predicate partialPathStep(
PartialPathNodeFwd mid, NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1,
TSummaryCtx2 sc2, TSummaryCtx3 sc3, TSummaryCtx4 sc4, DataFlowType t, PartialAccessPath ap
) {
@@ -4359,11 +4309,6 @@ module Impl<FullStateConfigSig Config> {
DataFlowType t1, PartialAccessPath ap1, Content c, DataFlowType t2, PartialAccessPath ap2
) {
partialPathStoreStep(_, t1, ap1, c, _, t2, ap2)
or
exists(DataFlowType t0 |
partialPathTypeStrengthen(t0, ap2, t2) and
apConsFwd(t1, ap1, c, t0, ap2)
)
}
pragma[nomagic]

View File

@@ -500,7 +500,7 @@ module LocalFlow {
* inter-procedurality or field-sensitivity.
*/
predicate excludeFromExposedRelations(Node n) {
n instanceof FlowSummaryNode or
n instanceof SummaryNode or
n instanceof ImplicitCapturedArgumentNode
}
@@ -559,8 +559,7 @@ predicate simpleLocalFlowStep(Node nodeFrom, Node nodeTo) {
or
LocalFlow::localFlowCapturedVarStep(nodeFrom, nodeTo)
or
FlowSummaryImpl::Private::Steps::summaryLocalStep(nodeFrom.(FlowSummaryNode).getSummaryNode(),
nodeTo.(FlowSummaryNode).getSummaryNode(), true)
FlowSummaryImpl::Private::Steps::summaryLocalStep(nodeFrom, nodeTo, true)
or
nodeTo.(ObjectCreationNode).getPreUpdateNode() = nodeFrom.(ObjectInitializerNode)
}
@@ -806,8 +805,7 @@ private module Cached {
// Add artificial dependencies to enforce all cached predicates are evaluated
// in the "DataFlowImplCommon stage"
cached
predicate forceCaching() {
private predicate forceCaching() {
TaintTrackingPrivate::forceCachingInSameStage() or
exists(any(NodeImpl n).getTypeImpl()) or
exists(any(NodeImpl n).getControlFlowNodeImpl()) or
@@ -817,7 +815,10 @@ private module Cached {
cached
newtype TNode =
TExprNode(ControlFlow::Nodes::ElementNode cfn) { cfn.getElement() instanceof Expr } or
TExprNode(ControlFlow::Nodes::ElementNode cfn) {
forceCaching() and
cfn.getElement() instanceof Expr
} or
TCilExprNode(CIL::Expr e) { e.getImplementation() instanceof CIL::BestImplementation } or
TCilSsaDefinitionExtNode(CilSsaImpl::DefinitionExt def) or
TSsaDefinitionExtNode(SsaImpl::DefinitionExt def) {
@@ -866,7 +867,12 @@ private module Cached {
)
)
} or
TFlowSummaryNode(FlowSummaryImpl::Private::SummaryNode sn) or
TSummaryNode(DataFlowSummarizedCallable c, FlowSummaryImpl::Private::SummaryNodeState state) {
FlowSummaryImpl::Private::summaryNodeRange(c, state)
} or
TSummaryParameterNode(DataFlowSummarizedCallable c, ParameterPosition pos) {
FlowSummaryImpl::Private::summaryParameterNodeRange(c, pos)
} or
TParamsArgumentNode(ControlFlow::Node callCfn) {
callCfn = any(Call c | isParamsArg(c, _, _)).getAControlFlowNode()
}
@@ -971,7 +977,9 @@ predicate nodeIsHidden(Node n) {
or
n instanceof MallocNode
or
n instanceof FlowSummaryNode
n instanceof SummaryNode
or
n instanceof SummaryParameterNode
or
n instanceof ParamsArgumentNode
or
@@ -1124,16 +1132,29 @@ private module ParameterNodes {
}
/** A parameter for a library callable with a flow summary. */
class SummaryParameterNode extends ParameterNodeImpl, FlowSummaryNode {
class SummaryParameterNode extends ParameterNodeImpl, TSummaryParameterNode {
private FlowSummaryImpl::Public::SummarizedCallable sc;
private ParameterPosition pos_;
SummaryParameterNode() {
FlowSummaryImpl::Private::summaryParameterNode(this.getSummaryNode(), pos_)
}
SummaryParameterNode() { this = TSummaryParameterNode(sc, pos_) }
override predicate isParameterOf(DataFlowCallable c, ParameterPosition pos) {
this.getSummarizedCallable() = c.asSummarizedCallable() and pos = pos_
sc = c.asSummarizedCallable() and pos = pos_
}
override DataFlowCallable getEnclosingCallableImpl() { result.asSummarizedCallable() = sc }
override Type getTypeImpl() {
exists(int i | pos_.getPosition() = i and result = sc.getParameter(i).getType())
or
pos_.isThisParameter() and result = sc.getDeclaringType()
}
override ControlFlow::Node getControlFlowNodeImpl() { none() }
override EmptyLocation getLocationImpl() { any() }
override string toStringImpl() { result = "parameter " + pos_ + " of " + sc }
}
}
@@ -1302,16 +1323,11 @@ private module ArgumentNodes {
override string toStringImpl() { result = "[implicit array creation] " + callCfn }
}
private class SummaryArgumentNode extends FlowSummaryNode, ArgumentNodeImpl {
private DataFlowCall call_;
private ArgumentPosition pos_;
SummaryArgumentNode() {
FlowSummaryImpl::Private::summaryArgumentNode(call_, this.getSummaryNode(), pos_)
}
private class SummaryArgumentNode extends SummaryNode, ArgumentNodeImpl {
SummaryArgumentNode() { FlowSummaryImpl::Private::summaryArgumentNode(_, this, _) }
override predicate argumentOf(DataFlowCall call, ArgumentPosition pos) {
call = call_ and pos = pos_
FlowSummaryImpl::Private::summaryArgumentNode(call, this, pos)
}
}
}
@@ -1453,11 +1469,12 @@ private module ReturnNodes {
}
}
private class SummaryReturnNode extends FlowSummaryNode, ReturnNode {
private class SummaryReturnNode extends SummaryNode, ReturnNode {
private ReturnKind rk;
SummaryReturnNode() {
FlowSummaryImpl::Private::summaryReturnNode(this.getSummaryNode(), rk)
FlowSummaryImpl::Private::summaryReturnNode(this, rk) and
not rk instanceof JumpReturnKind
or
exists(Parameter p, int pos |
summaryPostUpdateNodeIsOutOrRef(this, p) and
@@ -1477,9 +1494,9 @@ private module ReturnNodes {
* Holds if summary node `n` is a post-update node for `out`/`ref` parameter `p`.
* In this case we adjust it to instead be a return node.
*/
private predicate summaryPostUpdateNodeIsOutOrRef(FlowSummaryNode n, Parameter p) {
exists(SummaryParameterNode pn, DataFlowCallable c, ParameterPosition pos |
FlowSummaryImpl::Private::summaryPostUpdateNode(n.getSummaryNode(), pn.getSummaryNode()) and
private predicate summaryPostUpdateNodeIsOutOrRef(SummaryNode n, Parameter p) {
exists(ParameterNodeImpl pn, DataFlowCallable c, ParameterPosition pos |
FlowSummaryImpl::Private::summaryPostUpdateNode(n, pn) and
pn.isParameterOf(c, pos) and
p = c.asSummarizedCallable().getParameter(pos.getPosition()) and
p.isOutOrRef()
@@ -1592,43 +1609,37 @@ private module OutNodes {
}
}
private class SummaryOutNode extends FlowSummaryNode, OutNode {
private DataFlowCall call;
private ReturnKind kind_;
private class SummaryOutNode extends SummaryNode, OutNode {
SummaryOutNode() { FlowSummaryImpl::Private::summaryOutNode(_, this, _) }
SummaryOutNode() {
FlowSummaryImpl::Private::summaryOutNode(call, this.getSummaryNode(), kind_)
override DataFlowCall getCall(ReturnKind kind) {
FlowSummaryImpl::Private::summaryOutNode(result, this, kind)
}
override DataFlowCall getCall(ReturnKind kind) { result = call and kind = kind_ }
}
}
import OutNodes
/** A data-flow node used to model flow summaries. */
class FlowSummaryNode extends NodeImpl, TFlowSummaryNode {
FlowSummaryImpl::Private::SummaryNode getSummaryNode() { this = TFlowSummaryNode(result) }
class SummaryNode extends NodeImpl, TSummaryNode {
private FlowSummaryImpl::Public::SummarizedCallable c;
private FlowSummaryImpl::Private::SummaryNodeState state;
FlowSummaryImpl::Public::SummarizedCallable getSummarizedCallable() {
result = this.getSummaryNode().getSummarizedCallable()
}
SummaryNode() { this = TSummaryNode(c, state) }
override DataFlowCallable getEnclosingCallableImpl() {
result.asSummarizedCallable() = this.getSummarizedCallable()
}
override DataFlowCallable getEnclosingCallableImpl() { result.asSummarizedCallable() = c }
override DataFlowType getDataFlowType() {
result = FlowSummaryImpl::Private::summaryNodeType(this.getSummaryNode())
result = FlowSummaryImpl::Private::summaryNodeType(this)
}
override DotNet::Type getTypeImpl() { none() }
override ControlFlow::Node getControlFlowNodeImpl() { none() }
override Location getLocationImpl() { result = this.getSummarizedCallable().getLocation() }
override Location getLocationImpl() { result = c.getLocation() }
override string toStringImpl() { result = this.getSummaryNode().toString() }
override string toStringImpl() { result = "[summary] " + state + " in " + c }
}
/** A field or a property. */
@@ -1707,8 +1718,13 @@ predicate jumpStep(Node pred, Node succ) {
flr.hasNonlocalValue()
)
or
FlowSummaryImpl::Private::Steps::summaryJumpStep(pred.(FlowSummaryNode).getSummaryNode(),
succ.(FlowSummaryNode).getSummaryNode())
exists(JumpReturnKind jrk, NonDelegateDataFlowCall call |
FlowSummaryImpl::Private::summaryReturnNode(pred, jrk) and
jrk.getTarget() = call.getATarget(_) and
succ = getAnOutNode(call, jrk.getTargetReturnKind())
)
or
FlowSummaryImpl::Private::Steps::summaryJumpStep(pred, succ)
}
private class StoreStepConfiguration extends ControlFlowReachabilityConfiguration {
@@ -1768,8 +1784,7 @@ predicate storeStep(Node node1, Content c, Node node2) {
c = getResultContent()
)
or
FlowSummaryImpl::Private::Steps::summaryStoreStep(node1.(FlowSummaryNode).getSummaryNode(), c,
node2.(FlowSummaryNode).getSummaryNode())
FlowSummaryImpl::Private::Steps::summaryStoreStep(node1, c, node2)
}
private class ReadStepConfiguration extends ControlFlowReachabilityConfiguration {
@@ -1892,8 +1907,7 @@ predicate readStep(Node node1, Content c, Node node2) {
)
)
or
FlowSummaryImpl::Private::Steps::summaryReadStep(node1.(FlowSummaryNode).getSummaryNode(), c,
node2.(FlowSummaryNode).getSummaryNode())
FlowSummaryImpl::Private::Steps::summaryReadStep(node1, c, node2)
}
/**
@@ -1906,7 +1920,7 @@ predicate clearsContent(Node n, Content c) {
or
fieldOrPropertyStore(_, c, _, n.(ObjectInitializerNode).getInitializer(), false)
or
FlowSummaryImpl::Private::Steps::summaryClearsContent(n.(FlowSummaryNode).getSummaryNode(), c)
FlowSummaryImpl::Private::Steps::summaryClearsContent(n, c)
or
exists(WithExpr we, ObjectInitializer oi, FieldOrProperty f |
oi = we.getInitializer() and
@@ -1921,7 +1935,7 @@ predicate clearsContent(Node n, Content c) {
* at node `n`.
*/
predicate expectsContent(Node n, ContentSet c) {
FlowSummaryImpl::Private::Steps::summaryExpectsContent(n.(FlowSummaryNode).getSummaryNode(), c)
FlowSummaryImpl::Private::Steps::summaryExpectsContent(n, c)
}
/**
@@ -1970,21 +1984,6 @@ private class DataFlowUnknownType extends DataFlowType {
DataFlowUnknownType() { this = Gvn::getGlobalValueNumber(any(UnknownType ut)) }
}
private predicate uselessTypebound(DataFlowType t) {
t instanceof DataFlowUnknownType or
t instanceof Gvn::TypeParameterGvnType
}
pragma[nomagic]
predicate typeStrongerThan(DataFlowType t1, DataFlowType t2) {
t1 != t2 and
t1 = getANonTypeParameterSubTypeRestricted(t2)
or
t1 instanceof RelevantDataFlowType and
not uselessTypebound(t1) and
uselessTypebound(t2)
}
/**
* Holds if `t1` and `t2` are compatible, that is, whether data can flow from
* a node of type `t1` to a node of type `t2`.
@@ -2116,15 +2115,15 @@ private module PostUpdateNodes {
override string toStringImpl() { result = "[post] " + cfn.toString() }
}
private class SummaryPostUpdateNode extends FlowSummaryNode, PostUpdateNode {
private FlowSummaryImpl::Private::SummaryNode preUpdateNode;
private class SummaryPostUpdateNode extends SummaryNode, PostUpdateNode {
SummaryPostUpdateNode() {
FlowSummaryImpl::Private::summaryPostUpdateNode(this.getSummaryNode(), preUpdateNode) and
FlowSummaryImpl::Private::summaryPostUpdateNode(this, _) and
not summaryPostUpdateNodeIsOutOrRef(this, _)
}
override Node getPreUpdateNode() { result.(FlowSummaryNode).getSummaryNode() = preUpdateNode }
override Node getPreUpdateNode() {
FlowSummaryImpl::Private::summaryPostUpdateNode(this, result)
}
}
}
@@ -2140,12 +2139,6 @@ class CastNode extends Node {
}
}
/**
* Holds if `n` should never be skipped over in the `PathGraph` and in path
* explanations.
*/
predicate neverSkipInPathGraph(Node n) { none() }
class DataFlowExpr = DotNet::Expr;
/** Holds if `e` is an expression that always has the same Boolean value `val`. */
@@ -2225,7 +2218,7 @@ predicate lambdaCall(DataFlowCall call, LambdaCallKind kind, Node receiver) {
call.getControlFlowNode())
)
or
receiver.(FlowSummaryNode).getSummaryNode() = call.(SummaryCall).getReceiver()
receiver = call.(SummaryCall).getReceiver()
) and
exists(kind)
}

View File

@@ -180,11 +180,6 @@ module Public {
result = "Argument[" + getParameterPosition(pos) + "]"
)
or
exists(string synthetic |
sc = TSyntheticGlobalSummaryComponent(synthetic) and
result = "SyntheticGlobal[" + synthetic + "]"
)
or
sc = TReturnSummaryComponent(getReturnValueKind()) and result = "ReturnValue"
}
@@ -510,9 +505,6 @@ module Private {
or
// Add the post-update node corresponding to the requested argument node
outputState(c, s) and isCallbackParameter(s)
or
// Add the parameter node for parameter side-effects
outputState(c, s) and s = SummaryComponentStack::argument(_)
}
private newtype TSummaryNodeState =
@@ -538,7 +530,7 @@ module Private {
* this state represents that the components in `s` _remain to be written_ to
* the output.
*/
private class SummaryNodeState extends TSummaryNodeState {
class SummaryNodeState extends TSummaryNodeState {
/** Holds if this state is a valid input state for `c`. */
pragma[nomagic]
predicate isInputState(SummarizedCallable c, SummaryComponentStack s) {
@@ -567,42 +559,6 @@ module Private {
}
}
private newtype TSummaryNode =
TSummaryInternalNode(SummarizedCallable c, SummaryNodeState state) {
summaryNodeRange(c, state)
} or
TSummaryParameterNode(SummarizedCallable c, ParameterPosition pos) {
summaryParameterNodeRange(c, pos)
}
abstract class SummaryNode extends TSummaryNode {
abstract string toString();
abstract SummarizedCallable getSummarizedCallable();
}
private class SummaryInternalNode extends SummaryNode, TSummaryInternalNode {
private SummarizedCallable c;
private SummaryNodeState state;
SummaryInternalNode() { this = TSummaryInternalNode(c, state) }
override string toString() { result = "[summary] " + state + " in " + c }
override SummarizedCallable getSummarizedCallable() { result = c }
}
private class SummaryParamNode extends SummaryNode, TSummaryParameterNode {
private SummarizedCallable c;
private ParameterPosition pos;
SummaryParamNode() { this = TSummaryParameterNode(c, pos) }
override string toString() { result = "[summary param] " + pos + " in " + c }
override SummarizedCallable getSummarizedCallable() { result = c }
}
/**
* Holds if `state` represents having read from a parameter at position
* `pos` in `c`. In this case we are not synthesizing a data-flow node,
@@ -618,7 +574,7 @@ module Private {
* Holds if a synthesized summary node is needed for the state `state` in summarized
* callable `c`.
*/
private predicate summaryNodeRange(SummarizedCallable c, SummaryNodeState state) {
predicate summaryNodeRange(SummarizedCallable c, SummaryNodeState state) {
state.isInputState(c, _) and
not parameterReadState(c, state, _)
or
@@ -626,22 +582,22 @@ module Private {
}
pragma[noinline]
private SummaryNode summaryNodeInputState(SummarizedCallable c, SummaryComponentStack s) {
private Node summaryNodeInputState(SummarizedCallable c, SummaryComponentStack s) {
exists(SummaryNodeState state | state.isInputState(c, s) |
result = TSummaryInternalNode(c, state)
result = summaryNode(c, state)
or
exists(ParameterPosition pos |
parameterReadState(c, state, pos) and
result = TSummaryParameterNode(c, pos)
result.(ParamNode).isParameterOf(inject(c), pos)
)
)
}
pragma[noinline]
private SummaryNode summaryNodeOutputState(SummarizedCallable c, SummaryComponentStack s) {
private Node summaryNodeOutputState(SummarizedCallable c, SummaryComponentStack s) {
exists(SummaryNodeState state |
state.isOutputState(c, s) and
result = TSummaryInternalNode(c, state)
result = summaryNode(c, state)
)
}
@@ -649,14 +605,12 @@ module Private {
* Holds if a write targets `post`, which is a post-update node for a
* parameter at position `pos` in `c`.
*/
private predicate isParameterPostUpdate(
SummaryNode post, SummarizedCallable c, ParameterPosition pos
) {
private predicate isParameterPostUpdate(Node post, SummarizedCallable c, ParameterPosition pos) {
post = summaryNodeOutputState(c, SummaryComponentStack::argument(pos))
}
/** Holds if a parameter node at position `pos` is required for `c`. */
private predicate summaryParameterNodeRange(SummarizedCallable c, ParameterPosition pos) {
predicate summaryParameterNodeRange(SummarizedCallable c, ParameterPosition pos) {
parameterReadState(c, _, pos)
or
// Same as `isParameterPostUpdate(_, c, pos)`, but can be used in a negative context
@@ -664,7 +618,7 @@ module Private {
}
private predicate callbackOutput(
SummarizedCallable c, SummaryComponentStack s, SummaryNode receiver, ReturnKind rk
SummarizedCallable c, SummaryComponentStack s, Node receiver, ReturnKind rk
) {
any(SummaryNodeState state).isInputState(c, s) and
s.head() = TReturnSummaryComponent(rk) and
@@ -672,7 +626,7 @@ module Private {
}
private predicate callbackInput(
SummarizedCallable c, SummaryComponentStack s, SummaryNode receiver, ArgumentPosition pos
SummarizedCallable c, SummaryComponentStack s, Node receiver, ArgumentPosition pos
) {
any(SummaryNodeState state).isOutputState(c, s) and
s.head() = TParameterSummaryComponent(pos) and
@@ -680,7 +634,7 @@ module Private {
}
/** Holds if a call targeting `receiver` should be synthesized inside `c`. */
predicate summaryCallbackRange(SummarizedCallable c, SummaryNode receiver) {
predicate summaryCallbackRange(SummarizedCallable c, Node receiver) {
callbackOutput(c, _, receiver, _)
or
callbackInput(c, _, receiver, _)
@@ -693,10 +647,10 @@ module Private {
* `getContentType()`, `getReturnType()`, `getCallbackParameterType()`, and
* `getCallbackReturnType()`.
*/
DataFlowType summaryNodeType(SummaryNode n) {
exists(SummaryNode pre |
DataFlowType summaryNodeType(Node n) {
exists(Node pre |
summaryPostUpdateNode(n, pre) and
result = summaryNodeType(pre)
result = getNodeType(pre)
)
or
exists(SummarizedCallable c, SummaryComponentStack s, SummaryComponent head | head = s.head() |
@@ -708,12 +662,12 @@ module Private {
)
or
head = TWithoutContentSummaryComponent(_) and
result = summaryNodeType(summaryNodeInputState(c, s.tail()))
result = getNodeType(summaryNodeInputState(c, s.tail()))
or
exists(ReturnKind rk |
head = TReturnSummaryComponent(rk) and
result =
getCallbackReturnType(summaryNodeType(summaryNodeInputState(pragma[only_bind_out](c),
getCallbackReturnType(getNodeType(summaryNodeInputState(pragma[only_bind_out](c),
s.tail())), rk)
)
or
@@ -721,11 +675,6 @@ module Private {
head = TSyntheticGlobalSummaryComponent(sg) and
result = getSyntheticGlobalType(sg)
)
or
exists(ParameterPosition pos |
head = TArgumentSummaryComponent(pos) and
result = getParameterType(c, pos)
)
)
or
n = summaryNodeOutputState(c, s) and
@@ -742,7 +691,7 @@ module Private {
or
exists(ArgumentPosition pos | head = TParameterSummaryComponent(pos) |
result =
getCallbackParameterType(summaryNodeType(summaryNodeInputState(pragma[only_bind_out](c),
getCallbackParameterType(getNodeType(summaryNodeInputState(pragma[only_bind_out](c),
s.tail())), pos)
)
or
@@ -754,14 +703,9 @@ module Private {
)
}
/** Holds if summary node `p` is a parameter with position `pos`. */
predicate summaryParameterNode(SummaryNode p, ParameterPosition pos) {
p = TSummaryParameterNode(_, pos)
}
/** Holds if summary node `out` contains output of kind `rk` from call `c`. */
predicate summaryOutNode(DataFlowCall c, SummaryNode out, ReturnKind rk) {
exists(SummarizedCallable callable, SummaryComponentStack s, SummaryNode receiver |
predicate summaryOutNode(DataFlowCall c, Node out, ReturnKind rk) {
exists(SummarizedCallable callable, SummaryComponentStack s, Node receiver |
callbackOutput(callable, s, receiver, rk) and
out = summaryNodeInputState(callable, s) and
c = summaryDataFlowCall(receiver)
@@ -769,8 +713,8 @@ module Private {
}
/** Holds if summary node `arg` is at position `pos` in the call `c`. */
predicate summaryArgumentNode(DataFlowCall c, SummaryNode arg, ArgumentPosition pos) {
exists(SummarizedCallable callable, SummaryComponentStack s, SummaryNode receiver |
predicate summaryArgumentNode(DataFlowCall c, Node arg, ArgumentPosition pos) {
exists(SummarizedCallable callable, SummaryComponentStack s, Node receiver |
callbackInput(callable, s, receiver, pos) and
arg = summaryNodeOutputState(callable, s) and
c = summaryDataFlowCall(receiver)
@@ -778,10 +722,10 @@ module Private {
}
/** Holds if summary node `post` is a post-update node with pre-update node `pre`. */
predicate summaryPostUpdateNode(SummaryNode post, SummaryNode pre) {
predicate summaryPostUpdateNode(Node post, Node pre) {
exists(SummarizedCallable c, ParameterPosition pos |
isParameterPostUpdate(post, c, pos) and
pre = TSummaryParameterNode(c, pos)
pre.(ParamNode).isParameterOf(inject(c), pos)
)
or
exists(SummarizedCallable callable, SummaryComponentStack s |
@@ -792,7 +736,7 @@ module Private {
}
/** Holds if summary node `ret` is a return node of kind `rk`. */
predicate summaryReturnNode(SummaryNode ret, ReturnKind rk) {
predicate summaryReturnNode(Node ret, ReturnKind rk) {
exists(SummaryComponentStack s |
ret = summaryNodeOutputState(_, s) and
s = TSingletonSummaryComponentStack(TReturnSummaryComponent(rk))
@@ -804,9 +748,7 @@ module Private {
* node, and back out to `p`.
*/
predicate summaryAllowParameterReturnInSelf(ParamNode p) {
exists(SummarizedCallable c, ParameterPosition ppos |
p.isParameterOf(inject(c), pragma[only_bind_into](ppos))
|
exists(SummarizedCallable c, ParameterPosition ppos | p.isParameterOf(inject(c), ppos) |
exists(SummaryComponentStack inputContents, SummaryComponentStack outputContents |
summary(c, inputContents, outputContents, _) and
inputContents.bottom() = pragma[only_bind_into](TArgumentSummaryComponent(ppos)) and
@@ -821,7 +763,7 @@ module Private {
* Holds if there is a local step from `pred` to `succ`, which is synthesized
* from a flow summary.
*/
predicate summaryLocalStep(SummaryNode pred, SummaryNode succ, boolean preservesValue) {
predicate summaryLocalStep(Node pred, Node succ, boolean preservesValue) {
exists(
SummarizedCallable c, SummaryComponentStack inputContents,
SummaryComponentStack outputContents
@@ -847,7 +789,7 @@ module Private {
* Holds if there is a read step of content `c` from `pred` to `succ`, which
* is synthesized from a flow summary.
*/
predicate summaryReadStep(SummaryNode pred, ContentSet c, SummaryNode succ) {
predicate summaryReadStep(Node pred, ContentSet c, Node succ) {
exists(SummarizedCallable sc, SummaryComponentStack s |
pred = summaryNodeInputState(sc, s.tail()) and
succ = summaryNodeInputState(sc, s) and
@@ -859,7 +801,7 @@ module Private {
* Holds if there is a store step of content `c` from `pred` to `succ`, which
* is synthesized from a flow summary.
*/
predicate summaryStoreStep(SummaryNode pred, ContentSet c, SummaryNode succ) {
predicate summaryStoreStep(Node pred, ContentSet c, Node succ) {
exists(SummarizedCallable sc, SummaryComponentStack s |
pred = summaryNodeOutputState(sc, s) and
succ = summaryNodeOutputState(sc, s.tail()) and
@@ -871,7 +813,7 @@ module Private {
* Holds if there is a jump step from `pred` to `succ`, which is synthesized
* from a flow summary.
*/
predicate summaryJumpStep(SummaryNode pred, SummaryNode succ) {
predicate summaryJumpStep(Node pred, Node succ) {
exists(SummaryComponentStack s |
s = SummaryComponentStack::singleton(SummaryComponent::syntheticGlobal(_)) and
pred = summaryNodeOutputState(_, s) and
@@ -898,9 +840,9 @@ module Private {
* `a` on line 2 to the post-update node for `a` on that line (via an intermediate
* node where field `b` is cleared).
*/
predicate summaryClearsContent(SummaryNode n, ContentSet c) {
predicate summaryClearsContent(Node n, ContentSet c) {
exists(SummarizedCallable sc, SummaryNodeState state, SummaryComponentStack stack |
n = TSummaryInternalNode(sc, state) and
n = summaryNode(sc, state) and
state.isInputState(sc, stack) and
stack.head() = SummaryComponent::withoutContent(c)
)
@@ -910,9 +852,9 @@ module Private {
* Holds if the value that is being tracked is expected to be stored inside
* content `c` at `n`.
*/
predicate summaryExpectsContent(SummaryNode n, ContentSet c) {
predicate summaryExpectsContent(Node n, ContentSet c) {
exists(SummarizedCallable sc, SummaryNodeState state, SummaryComponentStack stack |
n = TSummaryInternalNode(sc, state) and
n = summaryNode(sc, state) and
state.isInputState(sc, stack) and
stack.head() = SummaryComponent::withContent(c)
)
@@ -920,17 +862,17 @@ module Private {
pragma[noinline]
private predicate viableParam(
DataFlowCall call, SummarizedCallable sc, ParameterPosition ppos, SummaryParamNode p
DataFlowCall call, SummarizedCallable sc, ParameterPosition ppos, ParamNode p
) {
exists(DataFlowCallable c |
c = inject(sc) and
p = TSummaryParameterNode(sc, ppos) and
p.isParameterOf(c, ppos) and
c = viableCallable(call)
)
}
pragma[nomagic]
private SummaryParamNode summaryArgParam(DataFlowCall call, ArgNode arg, SummarizedCallable sc) {
private ParamNode summaryArgParam0(DataFlowCall call, ArgNode arg, SummarizedCallable sc) {
exists(ParameterPosition ppos |
argumentPositionMatch(call, arg, ppos) and
viableParam(call, sc, ppos, result)
@@ -942,12 +884,12 @@ module Private {
* local steps. `clearsOrExpects` records whether any node on the path from `p` to
* `n` either clears or expects contents.
*/
private predicate paramReachesLocal(SummaryParamNode p, SummaryNode n, boolean clearsOrExpects) {
private predicate paramReachesLocal(ParamNode p, Node n, boolean clearsOrExpects) {
viableParam(_, _, _, p) and
n = p and
clearsOrExpects = false
or
exists(SummaryNode mid, boolean clearsOrExpectsMid |
exists(Node mid, boolean clearsOrExpectsMid |
paramReachesLocal(p, mid, clearsOrExpectsMid) and
summaryLocalStep(mid, n, true) and
if
@@ -967,33 +909,21 @@ module Private {
*/
pragma[nomagic]
predicate prohibitsUseUseFlow(ArgNode arg, SummarizedCallable sc) {
exists(SummaryParamNode p, ParameterPosition ppos, SummaryNode ret |
exists(ParamNode p, ParameterPosition ppos, Node ret |
paramReachesLocal(p, ret, true) and
p = summaryArgParam(_, arg, sc) and
p = TSummaryParameterNode(_, pragma[only_bind_into](ppos)) and
p = summaryArgParam0(_, arg, sc) and
p.isParameterOf(_, pragma[only_bind_into](ppos)) and
isParameterPostUpdate(ret, _, pragma[only_bind_into](ppos))
)
}
pragma[nomagic]
private predicate summaryReturnNodeExt(SummaryNode ret, ReturnKindExt rk) {
summaryReturnNode(ret, rk.(ValueReturnKind).getKind())
or
exists(SummaryParamNode p, SummaryNode pre, ParameterPosition pos |
paramReachesLocal(p, pre, _) and
summaryPostUpdateNode(ret, pre) and
p = TSummaryParameterNode(_, pos) and
rk.(ParamUpdateReturnKind).getPosition() = pos
)
}
bindingset[ret]
private SummaryParamNode summaryArgParamRetOut(
ArgNode arg, SummaryNode ret, OutNodeExt out, SummarizedCallable sc
private ParamNode summaryArgParam(
ArgNode arg, ReturnNodeExt ret, OutNodeExt out, SummarizedCallable sc
) {
exists(DataFlowCall call, ReturnKindExt rk |
result = summaryArgParam(call, arg, sc) and
summaryReturnNodeExt(ret, pragma[only_bind_into](rk)) and
result = summaryArgParam0(call, arg, sc) and
ret.getKind() = pragma[only_bind_into](rk) and
out = pragma[only_bind_into](rk).getAnOutNode(call)
)
}
@@ -1006,9 +936,9 @@ module Private {
* be useful to include in the exposed local data-flow/taint-tracking relations.
*/
predicate summaryThroughStepValue(ArgNode arg, Node out, SummarizedCallable sc) {
exists(ReturnKind rk, SummaryNode ret, DataFlowCall call |
summaryLocalStep(summaryArgParam(call, arg, sc), ret, true) and
summaryReturnNode(ret, pragma[only_bind_into](rk)) and
exists(ReturnKind rk, ReturnNode ret, DataFlowCall call |
summaryLocalStep(summaryArgParam0(call, arg, sc), ret, true) and
ret.getKind() = pragma[only_bind_into](rk) and
out = getAnOutNode(call, pragma[only_bind_into](rk))
)
}
@@ -1021,9 +951,7 @@ module Private {
* be useful to include in the exposed local data-flow/taint-tracking relations.
*/
predicate summaryThroughStepTaint(ArgNode arg, Node out, SummarizedCallable sc) {
exists(SummaryNode ret |
summaryLocalStep(summaryArgParamRetOut(arg, ret, out, sc), ret, false)
)
exists(ReturnNodeExt ret | summaryLocalStep(summaryArgParam(arg, ret, out, sc), ret, false))
}
/**
@@ -1034,8 +962,8 @@ module Private {
* be useful to include in the exposed local data-flow/taint-tracking relations.
*/
predicate summaryGetterStep(ArgNode arg, ContentSet c, Node out, SummarizedCallable sc) {
exists(SummaryNode mid, SummaryNode ret |
summaryReadStep(summaryArgParamRetOut(arg, ret, out, sc), c, mid) and
exists(Node mid, ReturnNodeExt ret |
summaryReadStep(summaryArgParam(arg, ret, out, sc), c, mid) and
summaryLocalStep(mid, ret, _)
)
}
@@ -1048,8 +976,8 @@ module Private {
* be useful to include in the exposed local data-flow/taint-tracking relations.
*/
predicate summarySetterStep(ArgNode arg, ContentSet c, Node out, SummarizedCallable sc) {
exists(SummaryNode mid, SummaryNode ret |
summaryLocalStep(summaryArgParamRetOut(arg, ret, out, sc), mid, _) and
exists(Node mid, ReturnNodeExt ret |
summaryLocalStep(summaryArgParam(arg, ret, out, sc), mid, _) and
summaryStoreStep(mid, c, ret)
)
}
@@ -1416,11 +1344,11 @@ module Private {
}
private newtype TNodeOrCall =
MkNode(SummaryNode n) {
MkNode(Node n) {
exists(RelevantSummarizedCallable c |
n = TSummaryInternalNode(c, _)
n = summaryNode(c, _)
or
n = TSummaryParameterNode(c, _)
n.(ParamNode).isParameterOf(inject(c), _)
)
} or
MkCall(DataFlowCall call) {
@@ -1429,7 +1357,7 @@ module Private {
}
private class NodeOrCall extends TNodeOrCall {
SummaryNode asNode() { this = MkNode(result) }
Node asNode() { this = MkNode(result) }
DataFlowCall asCall() { this = MkCall(result) }
@@ -1449,11 +1377,9 @@ module Private {
predicate hasLocationInfo(
string filepath, int startline, int startcolumn, int endline, int endcolumn
) {
filepath = "" and
startline = 0 and
startcolumn = 0 and
endline = 0 and
endcolumn = 0
this.asNode().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
or
this.asCall().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
}
}

View File

@@ -19,20 +19,16 @@ class SummarizedCallableBase extends Callable {
SummarizedCallableBase() { this.isUnboundDeclaration() }
}
/**
* A module for importing frameworks that define synthetic globals.
*/
private module SyntheticGlobals {
private import semmle.code.csharp.frameworks.EntityFramework
}
DataFlowCallable inject(SummarizedCallable c) { result.asSummarizedCallable() = c }
/** Gets the parameter position of the instance parameter. */
ArgumentPosition callbackSelfParameterPosition() { none() } // disables implicit summary flow to `this` for callbacks
/** Gets the synthesized summary data-flow node for the given values. */
Node summaryNode(SummarizedCallable c, SummaryNodeState state) { result = TSummaryNode(c, state) }
/** Gets the synthesized data-flow call for `receiver`. */
SummaryCall summaryDataFlowCall(SummaryNode receiver) { receiver = result.getReceiver() }
SummaryCall summaryDataFlowCall(Node receiver) { receiver = result.getReceiver() }
/** Gets the type of content `c`. */
DataFlowType getContentType(Content c) {
@@ -48,21 +44,7 @@ DataFlowType getContentType(Content c) {
)
}
/** Gets the type of the parameter at the given position. */
DataFlowType getParameterType(SummarizedCallable c, ParameterPosition pos) {
exists(Type t | result = Gvn::getGlobalValueNumber(t) |
exists(int i |
pos.getPosition() = i and
t = c.getParameter(i).getType()
)
or
pos.isThisParameter() and
t = c.getDeclaringType()
)
}
/** Gets the return type of kind `rk` for callable `c`. */
DataFlowType getReturnType(DotNet::Callable c, ReturnKind rk) {
private DataFlowType getReturnTypeBase(DotNet::Callable c, ReturnKind rk) {
exists(Type t | result = Gvn::getGlobalValueNumber(t) |
rk instanceof NormalReturnKind and
(
@@ -76,6 +58,15 @@ DataFlowType getReturnType(DotNet::Callable c, ReturnKind rk) {
)
}
/** Gets the return type of kind `rk` for callable `c`. */
bindingset[c]
DataFlowType getReturnType(SummarizedCallable c, ReturnKind rk) {
result = getReturnTypeBase(c, rk)
or
rk =
any(JumpReturnKind jrk | result = getReturnTypeBase(jrk.getTarget(), jrk.getTargetReturnKind()))
}
/**
* Gets the type of the parameter matching arguments at position `pos` in a
* synthesized call that targets a callback of type `t`.

View File

@@ -156,8 +156,7 @@ private module Cached {
// tracking configurations where the source is a collection
readStep(nodeFrom, TElementContent(), nodeTo)
or
FlowSummaryImpl::Private::Steps::summaryLocalStep(nodeFrom.(FlowSummaryNode).getSummaryNode(),
nodeTo.(FlowSummaryNode).getSummaryNode(), false)
FlowSummaryImpl::Private::Steps::summaryLocalStep(nodeFrom, nodeTo, false)
or
nodeTo = nodeFrom.(DataFlow::NonLocalJumpNode).getAJumpSuccessor(false)
}

View File

@@ -4,7 +4,6 @@
import csharp
private import DataFlow
private import semmle.code.csharp.commons.QualifiedName
private import semmle.code.csharp.frameworks.System
private import semmle.code.csharp.frameworks.system.data.Entity
private import semmle.code.csharp.frameworks.system.collections.Generic
@@ -237,7 +236,7 @@ module EntityFramework {
* }
* ```
*/
Property getADbSetProperty(Class elementType) {
private Property getADbSetProperty(Class elementType) {
exists(ConstructedClass c |
result.getType() = c and
c.getUnboundDeclaration() instanceof DbSet and
@@ -352,104 +351,22 @@ module EntityFramework {
/** Holds if component stack `head :: tail` is required for the output specification. */
predicate requiresComponentStackOut(
Content head, Type headType, SummaryComponentStack tail, int dist,
DbContextClassSetProperty dbSetProp
Content head, Type headType, SummaryComponentStack tail, int dist
) {
exists(PropertyContent c1 |
exists(Property dbSetProp, PropertyContent c1 |
dbSetProp = this.getADbSetProperty(headType) and
this.stepRev(c1, _, head, headType, 0) and
c1.getProperty() = dbSetProp and
tail = SummaryComponentStack::return() and
tail = SummaryComponentStack::jump(dbSetProp.getGetter()) and
dist = 0
)
or
exists(Content tailHead, SummaryComponentStack tailTail, Type tailType |
this.requiresComponentStackOut(tailHead, tailType, tailTail, dist - 1, dbSetProp) and
this.requiresComponentStackOut(tailHead, tailType, tailTail, dist - 1) and
tail = SummaryComponentStack::push(SummaryComponent::content(tailHead), tailTail) and
this.stepRev(tailHead, tailType, head, headType, dist)
)
}
/**
* Holds if `input` is a valid summary component stack for property `mapped` for this.
*/
pragma[noinline]
predicate input(SummaryComponentStack input, Property mapped) {
exists(PropertyContent head, SummaryComponentStack tail |
this.requiresComponentStackIn(head, _, tail, _) and
head.getProperty() = mapped and
mapped = this.getAColumnProperty(_) and
input = SummaryComponentStack::push(SummaryComponent::content(head), tail)
)
}
/**
* Holds if `output` is a valid summary component stack for the getter of `dbSet`
* for property `mapped` for this.
*/
pragma[noinline]
private predicate output(
SummaryComponentStack output, Property mapped, DbContextClassSetProperty dbSet
) {
exists(PropertyContent head, SummaryComponentStack tail |
this.requiresComponentStackOut(head, _, tail, _, dbSet) and
head.getProperty() = mapped and
mapped = this.getAColumnProperty(_) and
output = SummaryComponentStack::push(SummaryComponent::content(head), tail)
)
}
/**
* Gets the synthetic name for the getter of `dbSet` for property `mapped` for this,
* where `output` is a valid summary component stack for the getter of `dbSet`
* for the property `mapped`.
*/
pragma[nomagic]
string getSyntheticName(
SummaryComponentStack output, Property mapped, DbContextClassSetProperty dbSet
) {
this = dbSet.getDbContextClass() and
this.output(output, mapped, dbSet) and
result = dbSet.getFullName() + "#" + SummaryComponentStack::getComponentStack(output)
}
}
private class DbContextClassSetProperty extends Property {
private DbContextClass c;
DbContextClassSetProperty() { this = c.getADbSetProperty(_) }
/**
* Gets the fully qualified name for this.
*/
string getFullName() {
exists(string qualifier, string type, string name |
this.hasQualifiedName(qualifier, type, name)
|
result = getQualifiedName(qualifier, type, name)
)
}
/**
* Gets the context class where this is a DbSet property.
*/
DbContextClass getDbContextClass() { result = c }
}
private class DbContextClassSetPropertySynthetic extends EFSummarizedCallable {
private DbContextClassSetProperty p;
DbContextClassSetPropertySynthetic() { this = p.getGetter() }
override predicate propagatesFlow(
SummaryComponentStack input, SummaryComponentStack output, boolean preservesValue
) {
exists(string name, DbContextClass c |
preservesValue = true and
name = c.getSyntheticName(output, _, p) and
input = SummaryComponentStack::syntheticGlobal(name)
)
}
}
private class DbContextSaveChanges extends EFSummarizedCallable {
@@ -457,32 +374,44 @@ module EntityFramework {
DbContextSaveChanges() { this = c.getASaveChanges() }
pragma[noinline]
private predicate input(SummaryComponentStack input, Property mapped) {
exists(PropertyContent head, SummaryComponentStack tail |
c.requiresComponentStackIn(head, _, tail, _) and
head.getProperty() = mapped and
mapped = c.getAColumnProperty(_) and
input = SummaryComponentStack::push(SummaryComponent::content(head), tail)
)
}
pragma[noinline]
private predicate output(SummaryComponentStack output, Property mapped) {
exists(PropertyContent head, SummaryComponentStack tail |
c.requiresComponentStackOut(head, _, tail, _) and
head.getProperty() = mapped and
mapped = c.getAColumnProperty(_) and
output = SummaryComponentStack::push(SummaryComponent::content(head), tail)
)
}
override predicate propagatesFlow(
SummaryComponentStack input, SummaryComponentStack output, boolean preservesValue
) {
exists(string name, Property mapped |
exists(Property mapped |
preservesValue = true and
c.input(input, mapped) and
name = c.getSyntheticName(_, mapped, _) and
output = SummaryComponentStack::syntheticGlobal(name)
this.input(input, mapped) and
this.output(output, mapped)
)
}
}
/**
* Add all possible synthetic global names.
*/
private class EFSummarizedCallableSyntheticGlobal extends SummaryComponent::SyntheticGlobal {
EFSummarizedCallableSyntheticGlobal() { this = any(DbContextClass c).getSyntheticName(_, _, _) }
}
private class DbContextSaveChangesRequiredSummaryComponentStack extends RequiredSummaryComponentStack
{
override predicate required(SummaryComponent head, SummaryComponentStack tail) {
exists(Content c | head = SummaryComponent::content(c) |
any(DbContextClass cls).requiresComponentStackIn(c, _, tail, _)
or
any(DbContextClass cls).requiresComponentStackOut(c, _, tail, _, _)
any(DbContextClass cls).requiresComponentStackOut(c, _, tail, _)
)
}
}

View File

@@ -1,7 +1,3 @@
## 0.6.3
No user-facing changes.
## 0.6.2
No user-facing changes.

View File

@@ -3,15 +3,16 @@
"qhelp.dtd">
<qhelp>
<overview>
<p>Extracting files from a malicious zip file, or similar type of archive,
is at risk of directory traversal attacks if filenames from the archive are
not properly validated.</p>
<p>Extracting files from a malicious zip archive without validating that the destination file path
is within the destination directory can cause files outside the destination directory to be
overwritten, due to the possible presence of directory traversal elements (<code>..</code>) in
archive paths.</p>
<p>Zip archives contain archive entries representing each file in the archive. These entries
include a file path for the entry, but these file paths are not restricted and may contain
unexpected special elements such as the directory traversal element (<code>..</code>). If these
file paths are used to create a filesystem path, then a file operation may happen in an
unexpected location. This can result in sensitive information being
file paths are used to determine an output file to write the contents of the archive item to, then
the file may be written to an unexpected location. This can result in sensitive information being
revealed or deleted, or an attacker being able to influence behavior by modifying unexpected
files.</p>

View File

@@ -1,8 +1,8 @@
/**
* @name Arbitrary file access during archive extraction ("Zip Slip")
* @description Extracting files from a malicious ZIP file, or similar type of archive, without
* validating that the destination file path is within the destination directory
* can allow an attacker to unexpectedly gain access to resources.
* @name Arbitrary file write during zip extraction ("Zip Slip")
* @description Extracting files from a malicious zip archive without validating that the
* destination file path is within the destination directory can cause files outside
* the destination directory to be overwritten.
* @kind path-problem
* @id cs/zipslip
* @problem.severity error

View File

@@ -1,4 +0,0 @@
---
category: fix
---
* The query "Arbitrary file write during zip extraction ("Zip Slip")" (`cs/zipslip`) has been renamed to "Arbitrary file access during archive extraction ("Zip Slip")."

View File

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

View File

@@ -1,2 +1,2 @@
---
lastReleaseVersion: 0.6.3
lastReleaseVersion: 0.6.2

View File

@@ -1,5 +1,5 @@
name: codeql/csharp-queries
version: 0.6.4-dev
version: 0.6.3-dev
groups:
- csharp
- queries

View File

@@ -4,12 +4,11 @@
* Example for a test.ql:
* ```ql
* import csharp
* import DefaultValueFlow::PathGraph
* import TestUtilities.InlineFlowTest
* import DefaultFlowTest
* import PathGraph
*
* from PathNode source, PathNode sink
* where flowPath(source, sink)
* from DefaultValueFlow::PathNode source, DefaultValueFlow::PathNode sink
* where DefaultValueFlow::flowPath(source, sink)
* select sink, source, sink, "$@", source, source.toString()
*
* ```
@@ -33,10 +32,14 @@
* }
* ```
*
* If you are only interested in value flow, then instead of importing `DefaultFlowTest`, you can import
* `ValueFlowTest<DefaultFlowConfig>`. Similarly, if you are only interested in taint flow, then instead of
* importing `DefaultFlowTest`, you can import `TaintFlowTest<DefaultFlowConfig>`. In both cases
* `DefaultFlowConfig` can be replaced by another implementation of `DataFlow::ConfigSig`.
* If you're not interested in a specific flow type, you can disable either value or taint flow expectations as follows:
* ```ql
* class HasFlowTest extends InlineFlowTest {
* override DataFlow::Configuration getTaintFlowConfig() { none() }
*
* override DataFlow::Configuration getValueFlowConfig() { none() }
* }
* ```
*
* If you need more fine-grained tuning, consider implementing a test using `InlineExpectationsTest`.
*/
@@ -44,8 +47,8 @@
import csharp
import TestUtilities.InlineExpectationsTest
private predicate defaultSource(DataFlow::Node source) {
source.asExpr().(MethodCall).getTarget().getUndecoratedName() = ["Source", "Taint"]
private predicate defaultSource(DataFlow::Node src) {
src.asExpr().(MethodCall).getTarget().getUndecoratedName() = ["Source", "Taint"]
}
private predicate defaultSink(DataFlow::Node sink) {
@@ -55,66 +58,42 @@ private predicate defaultSink(DataFlow::Node sink) {
}
module DefaultFlowConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) { defaultSource(source) }
predicate isSource(DataFlow::Node n) { defaultSource(n) }
predicate isSink(DataFlow::Node sink) { defaultSink(sink) }
predicate isSink(DataFlow::Node n) { defaultSink(n) }
int fieldFlowBranchLimit() { result = 1000 }
}
private module NoFlowConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) { none() }
module DefaultValueFlow = DataFlow::Global<DefaultFlowConfig>;
predicate isSink(DataFlow::Node sink) { none() }
}
module DefaultTaintFlow = TaintTracking::Global<DefaultFlowConfig>;
private string getSourceArgString(DataFlow::Node src) {
defaultSource(src) and
src.asExpr().(MethodCall).getAnArgument().getValue() = result
}
module FlowTest<DataFlow::ConfigSig ValueFlowConfig, DataFlow::ConfigSig TaintFlowConfig> {
module ValueFlow = DataFlow::Global<ValueFlowConfig>;
class InlineFlowTest extends InlineExpectationsTest {
InlineFlowTest() { this = "HasFlowTest" }
module TaintFlow = TaintTracking::Global<TaintFlowConfig>;
override string getARelevantTag() { result = ["hasValueFlow", "hasTaintFlow"] }
private module InlineTest implements TestSig {
string getARelevantTag() { result = ["hasValueFlow", "hasTaintFlow"] }
predicate hasActualResult(Location location, string element, string tag, string value) {
tag = "hasValueFlow" and
exists(DataFlow::Node src, DataFlow::Node sink | ValueFlow::flow(src, sink) |
sink.getLocation() = location and
element = sink.toString() and
if exists(getSourceArgString(src)) then value = getSourceArgString(src) else value = ""
)
or
tag = "hasTaintFlow" and
exists(DataFlow::Node src, DataFlow::Node sink |
TaintFlow::flow(src, sink) and not ValueFlow::flow(src, sink)
|
sink.getLocation() = location and
element = sink.toString() and
if exists(getSourceArgString(src)) then value = getSourceArgString(src) else value = ""
)
}
}
import MakeTest<InlineTest>
import DataFlow::MergePathGraph<ValueFlow::PathNode, TaintFlow::PathNode, ValueFlow::PathGraph, TaintFlow::PathGraph>
predicate flowPath(PathNode source, PathNode sink) {
ValueFlow::flowPath(source.asPathNode1(), sink.asPathNode1()) or
TaintFlow::flowPath(source.asPathNode2(), sink.asPathNode2())
override predicate hasActualResult(Location location, string element, string tag, string value) {
tag = "hasValueFlow" and
exists(DataFlow::Node src, DataFlow::Node sink | DefaultValueFlow::flow(src, sink) |
sink.getLocation() = location and
element = sink.toString() and
if exists(getSourceArgString(src)) then value = getSourceArgString(src) else value = ""
)
or
tag = "hasTaintFlow" and
exists(DataFlow::Node src, DataFlow::Node sink |
DefaultTaintFlow::flow(src, sink) and not DefaultValueFlow::flow(src, sink)
|
sink.getLocation() = location and
element = sink.toString() and
if exists(getSourceArgString(src)) then value = getSourceArgString(src) else value = ""
)
}
}
module DefaultFlowTest = FlowTest<DefaultFlowConfig, DefaultFlowConfig>;
module ValueFlowTest<DataFlow::ConfigSig ValueFlowConfig> {
import FlowTest<ValueFlowConfig, NoFlowConfig>
}
module TaintFlowTest<DataFlow::ConfigSig TaintFlowConfig> {
import FlowTest<NoFlowConfig, TaintFlowConfig>
}

View File

@@ -1,3 +1,5 @@
// semmle-extractor-options: ${testdir}/../../resources/stubs/System.Web.cs /r:System.Threading.Tasks.dll /r:System.Collections.Specialized.dll /r:System.Runtime.dll /r:System.Private.Uri.dll
using System;
using System.Threading.Tasks;
using System.Web.Mvc;
@@ -36,3 +38,21 @@ namespace RequestForgery.Controllers
}
}
}
// Missing stubs:
namespace System.Net.Http
{
public class HttpClient
{
public async Task SendAsync(HttpRequestMessage request) => throw null;
}
public class HttpRequestMessage
{
public HttpRequestMessage(HttpMethod method, string requestUri) => throw null;
}
public class HttpMethod
{
public static readonly HttpMethod Get;
}
}

View File

@@ -1,8 +1,8 @@
edges
| RequestForgery.cs:12:52:12:54 | url : String | RequestForgery.cs:14:66:14:68 | access to parameter url |
| RequestForgery.cs:14:52:14:54 | url : String | RequestForgery.cs:16:66:16:68 | access to parameter url |
nodes
| RequestForgery.cs:12:52:12:54 | url : String | semmle.label | url : String |
| RequestForgery.cs:14:66:14:68 | access to parameter url | semmle.label | access to parameter url |
| RequestForgery.cs:14:52:14:54 | url : String | semmle.label | url : String |
| RequestForgery.cs:16:66:16:68 | access to parameter url | semmle.label | access to parameter url |
subpaths
#select
| RequestForgery.cs:14:66:14:68 | access to parameter url | RequestForgery.cs:12:52:12:54 | url : String | RequestForgery.cs:14:66:14:68 | access to parameter url | The URL of this request depends on a $@. | RequestForgery.cs:12:52:12:54 | url | user-provided value |
| RequestForgery.cs:16:66:16:68 | access to parameter url | RequestForgery.cs:14:52:14:54 | url : String | RequestForgery.cs:16:66:16:68 | access to parameter url | The URL of this request depends on a $@. | RequestForgery.cs:14:52:14:54 | url | user-provided value |

View File

@@ -1,3 +0,0 @@
semmle-extractor-options: /nostdlib /noconfig
semmle-extractor-options: --load-sources-from-project:${testdir}/../../resources/stubs/_frameworks/Microsoft.NETCore.App/Microsoft.NETCore.App.csproj
semmle-extractor-options: ${testdir}/../../resources/stubs/System.Web.cs

View File

@@ -214,8 +214,8 @@ edges
| CollectionFlow.cs:385:58:385:61 | dict : Dictionary<T,T> [element, property Value] : A | CollectionFlow.cs:385:67:385:70 | access to parameter dict : Dictionary<T,T> [element, property Value] : A |
| CollectionFlow.cs:385:67:385:70 | access to parameter dict : Dictionary<T,T> [element, property Value] : A | CollectionFlow.cs:385:67:385:73 | access to indexer : A |
| CollectionFlow.cs:387:59:387:62 | dict : Dictionary<T,T> [element, property Value] : A | CollectionFlow.cs:387:68:387:71 | access to parameter dict : Dictionary<T,T> [element, property Value] : A |
| CollectionFlow.cs:387:68:387:71 | access to parameter dict : Dictionary<T,T> [element, property Value] : A | CollectionFlow.cs:387:68:387:79 | call to method First<KeyValuePair<Int32,T>> : KeyValuePair<Int32,T> [property Value] : A |
| CollectionFlow.cs:387:68:387:79 | call to method First<KeyValuePair<Int32,T>> : KeyValuePair<Int32,T> [property Value] : A | CollectionFlow.cs:387:68:387:85 | access to property Value : A |
| CollectionFlow.cs:387:68:387:71 | access to parameter dict : Dictionary<T,T> [element, property Value] : A | CollectionFlow.cs:387:68:387:79 | call to method First<KeyValuePair<Int32,T>> : Object [property Value] : A |
| CollectionFlow.cs:387:68:387:79 | call to method First<KeyValuePair<Int32,T>> : Object [property Value] : A | CollectionFlow.cs:387:68:387:85 | access to property Value : A |
| CollectionFlow.cs:389:60:389:63 | dict : Dictionary<T,T> [element, property Value] : A | CollectionFlow.cs:389:69:389:72 | access to parameter dict : Dictionary<T,T> [element, property Value] : A |
| CollectionFlow.cs:389:69:389:72 | access to parameter dict : Dictionary<T,T> [element, property Value] : A | CollectionFlow.cs:389:69:389:79 | access to property Values : ICollection<T> [element] : A |
| CollectionFlow.cs:389:69:389:79 | access to property Values : ICollection<T> [element] : A | CollectionFlow.cs:389:69:389:87 | call to method First<T> : A |
@@ -223,8 +223,8 @@ edges
| CollectionFlow.cs:391:67:391:70 | access to parameter dict : Dictionary<T,T> [element, property Key] : A | CollectionFlow.cs:391:67:391:75 | access to property Keys : ICollection<T> [element] : A |
| CollectionFlow.cs:391:67:391:75 | access to property Keys : ICollection<T> [element] : A | CollectionFlow.cs:391:67:391:83 | call to method First<T> : A |
| CollectionFlow.cs:393:57:393:60 | dict : Dictionary<T,T> [element, property Key] : A | CollectionFlow.cs:393:66:393:69 | access to parameter dict : Dictionary<T,T> [element, property Key] : A |
| CollectionFlow.cs:393:66:393:69 | access to parameter dict : Dictionary<T,T> [element, property Key] : A | CollectionFlow.cs:393:66:393:77 | call to method First<KeyValuePair<T,Int32>> : KeyValuePair<T,Int32> [property Key] : A |
| CollectionFlow.cs:393:66:393:77 | call to method First<KeyValuePair<T,Int32>> : KeyValuePair<T,Int32> [property Key] : A | CollectionFlow.cs:393:66:393:81 | access to property Key : A |
| CollectionFlow.cs:393:66:393:69 | access to parameter dict : Dictionary<T,T> [element, property Key] : A | CollectionFlow.cs:393:66:393:77 | call to method First<KeyValuePair<T,Int32>> : Object [property Key] : A |
| CollectionFlow.cs:393:66:393:77 | call to method First<KeyValuePair<T,Int32>> : Object [property Key] : A | CollectionFlow.cs:393:66:393:81 | access to property Key : A |
| CollectionFlow.cs:395:49:395:52 | args : A[] [element] : A | CollectionFlow.cs:395:63:395:66 | access to parameter args : A[] [element] : A |
| CollectionFlow.cs:395:49:395:52 | args : null [element] : A | CollectionFlow.cs:395:63:395:66 | access to parameter args : null [element] : A |
| CollectionFlow.cs:395:63:395:66 | access to parameter args : A[] [element] : A | CollectionFlow.cs:395:63:395:69 | access to array element |
@@ -440,7 +440,7 @@ nodes
| CollectionFlow.cs:385:67:385:73 | access to indexer : A | semmle.label | access to indexer : A |
| CollectionFlow.cs:387:59:387:62 | dict : Dictionary<T,T> [element, property Value] : A | semmle.label | dict : Dictionary<T,T> [element, property Value] : A |
| CollectionFlow.cs:387:68:387:71 | access to parameter dict : Dictionary<T,T> [element, property Value] : A | semmle.label | access to parameter dict : Dictionary<T,T> [element, property Value] : A |
| CollectionFlow.cs:387:68:387:79 | call to method First<KeyValuePair<Int32,T>> : KeyValuePair<Int32,T> [property Value] : A | semmle.label | call to method First<KeyValuePair<Int32,T>> : KeyValuePair<Int32,T> [property Value] : A |
| CollectionFlow.cs:387:68:387:79 | call to method First<KeyValuePair<Int32,T>> : Object [property Value] : A | semmle.label | call to method First<KeyValuePair<Int32,T>> : Object [property Value] : A |
| CollectionFlow.cs:387:68:387:85 | access to property Value : A | semmle.label | access to property Value : A |
| CollectionFlow.cs:389:60:389:63 | dict : Dictionary<T,T> [element, property Value] : A | semmle.label | dict : Dictionary<T,T> [element, property Value] : A |
| CollectionFlow.cs:389:69:389:72 | access to parameter dict : Dictionary<T,T> [element, property Value] : A | semmle.label | access to parameter dict : Dictionary<T,T> [element, property Value] : A |
@@ -452,7 +452,7 @@ nodes
| CollectionFlow.cs:391:67:391:83 | call to method First<T> : A | semmle.label | call to method First<T> : A |
| CollectionFlow.cs:393:57:393:60 | dict : Dictionary<T,T> [element, property Key] : A | semmle.label | dict : Dictionary<T,T> [element, property Key] : A |
| CollectionFlow.cs:393:66:393:69 | access to parameter dict : Dictionary<T,T> [element, property Key] : A | semmle.label | access to parameter dict : Dictionary<T,T> [element, property Key] : A |
| CollectionFlow.cs:393:66:393:77 | call to method First<KeyValuePair<T,Int32>> : KeyValuePair<T,Int32> [property Key] : A | semmle.label | call to method First<KeyValuePair<T,Int32>> : KeyValuePair<T,Int32> [property Key] : A |
| CollectionFlow.cs:393:66:393:77 | call to method First<KeyValuePair<T,Int32>> : Object [property Key] : A | semmle.label | call to method First<KeyValuePair<T,Int32>> : Object [property Key] : A |
| CollectionFlow.cs:393:66:393:81 | access to property Key : A | semmle.label | access to property Key : A |
| CollectionFlow.cs:395:49:395:52 | args : A[] [element] : A | semmle.label | args : A[] [element] : A |
| CollectionFlow.cs:395:49:395:52 | args : null [element] : A | semmle.label | args : null [element] : A |

View File

@@ -51,5 +51,5 @@ viableLambda
| DelegateFlow.cs:125:9:125:25 | function pointer call | file://:0:0:0:0 | (none) | DelegateFlow.cs:7:17:7:18 | M2 |
| DelegateFlow.cs:132:9:132:11 | delegate call | DelegateFlow.cs:135:25:135:40 | call to method M19 | DelegateFlow.cs:135:29:135:36 | (...) => ... |
| DelegateFlow.cs:132:9:132:11 | delegate call | file://:0:0:0:0 | (none) | DelegateFlow.cs:131:17:131:24 | (...) => ... |
| file://:0:0:0:0 | [summary] call to [summary param] position 0 in Lazy in Lazy | DelegateFlow.cs:105:9:105:24 | object creation of type Lazy<Int32> | DelegateFlow.cs:104:23:104:30 | (...) => ... |
| file://:0:0:0:0 | [summary] call to [summary param] position 0 in Lazy in Lazy | DelegateFlow.cs:107:9:107:24 | object creation of type Lazy<Int32> | DelegateFlow.cs:106:13:106:20 | (...) => ... |
| file://:0:0:0:0 | [summary] call to parameter position 0 of Lazy in Lazy | DelegateFlow.cs:105:9:105:24 | object creation of type Lazy<Int32> | DelegateFlow.cs:104:23:104:30 | (...) => ... |
| file://:0:0:0:0 | [summary] call to parameter position 0 of Lazy in Lazy | DelegateFlow.cs:107:9:107:24 | object creation of type Lazy<Int32> | DelegateFlow.cs:106:13:106:20 | (...) => ... |

View File

@@ -149,9 +149,9 @@ namespace My.Qltest
static T Apply<S, T>(Func<S, T> f, S s) => throw null;
static T[] Map<S, T>(S[] elements, Func<S, T> f) => throw null;
static S[] Map<S, T>(S[] elements, Func<S, T> f) => throw null;
static void Apply2(Action<object> f, D d1, D d2) => throw null;
static void Apply2<S>(Action<S> f, S s1, S s2) => throw null;
static void Parse(string s, out int i) => throw null;
@@ -235,4 +235,4 @@ namespace My.Qltest
static void Sink(object o) { }
}
}
}

View File

@@ -12,10 +12,10 @@ edges
| ExternalFlow.cs:30:13:30:16 | [post] this access : D [field Field] : Object | ExternalFlow.cs:31:18:31:21 | this access : D [field Field] : Object |
| ExternalFlow.cs:30:26:30:37 | object creation of type Object : Object | ExternalFlow.cs:30:13:30:16 | [post] this access : D [field Field] : Object |
| ExternalFlow.cs:31:18:31:21 | this access : D [field Field] : Object | ExternalFlow.cs:31:18:31:39 | call to method StepFieldGetter |
| ExternalFlow.cs:36:19:36:62 | (...) ... : D [field Field] : Object | ExternalFlow.cs:36:18:36:69 | access to field Field |
| ExternalFlow.cs:36:19:36:62 | (...) ... : Object [field Field] : Object | ExternalFlow.cs:36:18:36:69 | access to field Field |
| ExternalFlow.cs:36:22:36:25 | [post] this access : D [field Field] : Object | ExternalFlow.cs:37:18:37:21 | this access : D [field Field] : Object |
| ExternalFlow.cs:36:22:36:55 | call to method StepFieldSetter : D [field Field2, field Field] : Object | ExternalFlow.cs:36:22:36:62 | access to field Field2 : Object [field Field] : Object |
| ExternalFlow.cs:36:22:36:62 | access to field Field2 : Object [field Field] : Object | ExternalFlow.cs:36:19:36:62 | (...) ... : D [field Field] : Object |
| ExternalFlow.cs:36:22:36:62 | access to field Field2 : Object [field Field] : Object | ExternalFlow.cs:36:19:36:62 | (...) ... : Object [field Field] : Object |
| ExternalFlow.cs:36:43:36:54 | object creation of type Object : Object | ExternalFlow.cs:36:22:36:25 | [post] this access : D [field Field] : Object |
| ExternalFlow.cs:36:43:36:54 | object creation of type Object : Object | ExternalFlow.cs:36:22:36:55 | call to method StepFieldSetter : D [field Field2, field Field] : Object |
| ExternalFlow.cs:37:18:37:21 | this access : D [field Field] : Object | ExternalFlow.cs:37:18:37:27 | access to field Field |
@@ -38,7 +38,8 @@ edges
| ExternalFlow.cs:72:23:72:23 | o : Object | ExternalFlow.cs:72:35:72:35 | access to parameter o |
| ExternalFlow.cs:77:24:77:58 | call to method Map<Int32,Object> : T[] [element] : Object | ExternalFlow.cs:78:18:78:21 | access to local variable objs : T[] [element] : Object |
| ExternalFlow.cs:77:46:77:57 | object creation of type Object : Object | ExternalFlow.cs:77:24:77:58 | call to method Map<Int32,Object> : T[] [element] : Object |
| ExternalFlow.cs:78:18:78:21 | access to local variable objs : T[] [element] : Object | ExternalFlow.cs:78:18:78:24 | access to array element |
| ExternalFlow.cs:78:18:78:21 | access to local variable objs : T[] [element] : Object | ExternalFlow.cs:78:18:78:24 | access to array element : Object |
| ExternalFlow.cs:78:18:78:24 | access to array element : Object | ExternalFlow.cs:78:18:78:24 | (...) ... |
| ExternalFlow.cs:83:30:83:45 | { ..., ... } : null [element] : Object | ExternalFlow.cs:84:29:84:32 | access to local variable objs : null [element] : Object |
| ExternalFlow.cs:83:32:83:43 | object creation of type Object : Object | ExternalFlow.cs:83:30:83:45 | { ..., ... } : null [element] : Object |
| ExternalFlow.cs:84:25:84:41 | call to method Map<Object,Object> : T[] [element] : Object | ExternalFlow.cs:85:18:85:22 | access to local variable objs2 : T[] [element] : Object |
@@ -90,7 +91,7 @@ nodes
| ExternalFlow.cs:31:18:31:21 | this access : D [field Field] : Object | semmle.label | this access : D [field Field] : Object |
| ExternalFlow.cs:31:18:31:39 | call to method StepFieldGetter | semmle.label | call to method StepFieldGetter |
| ExternalFlow.cs:36:18:36:69 | access to field Field | semmle.label | access to field Field |
| ExternalFlow.cs:36:19:36:62 | (...) ... : D [field Field] : Object | semmle.label | (...) ... : D [field Field] : Object |
| ExternalFlow.cs:36:19:36:62 | (...) ... : Object [field Field] : Object | semmle.label | (...) ... : Object [field Field] : Object |
| ExternalFlow.cs:36:22:36:25 | [post] this access : D [field Field] : Object | semmle.label | [post] this access : D [field Field] : Object |
| ExternalFlow.cs:36:22:36:55 | call to method StepFieldSetter : D [field Field2, field Field] : Object | semmle.label | call to method StepFieldSetter : D [field Field2, field Field] : Object |
| ExternalFlow.cs:36:22:36:62 | access to field Field2 : Object [field Field] : Object | semmle.label | access to field Field2 : Object [field Field] : Object |
@@ -123,7 +124,8 @@ nodes
| ExternalFlow.cs:77:24:77:58 | call to method Map<Int32,Object> : T[] [element] : Object | semmle.label | call to method Map<Int32,Object> : T[] [element] : Object |
| ExternalFlow.cs:77:46:77:57 | object creation of type Object : Object | semmle.label | object creation of type Object : Object |
| ExternalFlow.cs:78:18:78:21 | access to local variable objs : T[] [element] : Object | semmle.label | access to local variable objs : T[] [element] : Object |
| ExternalFlow.cs:78:18:78:24 | access to array element | semmle.label | access to array element |
| ExternalFlow.cs:78:18:78:24 | (...) ... | semmle.label | (...) ... |
| ExternalFlow.cs:78:18:78:24 | access to array element : Object | semmle.label | access to array element : Object |
| ExternalFlow.cs:83:30:83:45 | { ..., ... } : null [element] : Object | semmle.label | { ..., ... } : null [element] : Object |
| ExternalFlow.cs:83:32:83:43 | object creation of type Object : Object | semmle.label | object creation of type Object : Object |
| ExternalFlow.cs:84:25:84:41 | call to method Map<Object,Object> : T[] [element] : Object | semmle.label | call to method Map<Object,Object> : T[] [element] : Object |
@@ -182,7 +184,7 @@ subpaths
| ExternalFlow.cs:60:47:60:47 | access to parameter o | ExternalFlow.cs:60:64:60:75 | object creation of type Object : Object | ExternalFlow.cs:60:47:60:47 | access to parameter o | $@ | ExternalFlow.cs:60:64:60:75 | object creation of type Object : Object | object creation of type Object : Object |
| ExternalFlow.cs:66:18:66:18 | access to local variable o | ExternalFlow.cs:65:45:65:56 | object creation of type Object : Object | ExternalFlow.cs:66:18:66:18 | access to local variable o | $@ | ExternalFlow.cs:65:45:65:56 | object creation of type Object : Object | object creation of type Object : Object |
| ExternalFlow.cs:72:35:72:35 | access to parameter o | ExternalFlow.cs:71:32:71:43 | object creation of type Object : Object | ExternalFlow.cs:72:35:72:35 | access to parameter o | $@ | ExternalFlow.cs:71:32:71:43 | object creation of type Object : Object | object creation of type Object : Object |
| ExternalFlow.cs:78:18:78:24 | access to array element | ExternalFlow.cs:77:46:77:57 | object creation of type Object : Object | ExternalFlow.cs:78:18:78:24 | access to array element | $@ | ExternalFlow.cs:77:46:77:57 | object creation of type Object : Object | object creation of type Object : Object |
| ExternalFlow.cs:78:18:78:24 | (...) ... | ExternalFlow.cs:77:46:77:57 | object creation of type Object : Object | ExternalFlow.cs:78:18:78:24 | (...) ... | $@ | ExternalFlow.cs:77:46:77:57 | object creation of type Object : Object | object creation of type Object : Object |
| ExternalFlow.cs:85:18:85:25 | access to array element | ExternalFlow.cs:83:32:83:43 | object creation of type Object : Object | ExternalFlow.cs:85:18:85:25 | access to array element | $@ | ExternalFlow.cs:83:32:83:43 | object creation of type Object : Object | object creation of type Object : Object |
| ExternalFlow.cs:92:18:92:18 | (...) ... | ExternalFlow.cs:90:21:90:34 | object creation of type String : String | ExternalFlow.cs:92:18:92:18 | (...) ... | $@ | ExternalFlow.cs:90:21:90:34 | object creation of type String : String | object creation of type String : String |
| ExternalFlow.cs:102:22:102:22 | access to parameter d | ExternalFlow.cs:98:24:98:35 | object creation of type Object : Object | ExternalFlow.cs:102:22:102:22 | access to parameter d | $@ | ExternalFlow.cs:98:24:98:35 | object creation of type Object : Object | object creation of type Object : Object |

View File

@@ -16,8 +16,8 @@ extensions:
- ["My.Qltest", "D", false, "StepElementSetter", "(System.Object)", "", "Argument[0]", "Argument[this].Element", "value", "manual"]
- ["My.Qltest", "D", false, "Apply<,>", "(System.Func<S,T>,S)", "", "Argument[1]", "Argument[0].Parameter[0]", "value", "manual"]
- ["My.Qltest", "D", false, "Apply<,>", "(System.Func<S,T>,S)", "", "Argument[0].ReturnValue", "ReturnValue", "value", "manual"]
- ["My.Qltest", "D", false, "Apply2", "(System.Action<System.Object>,My.Qltest.D,My.Qltest.D)", "", "Argument[1].Field[My.Qltest.D.Field]", "Argument[0].Parameter[0]", "value", "manual"]
- ["My.Qltest", "D", false, "Apply2", "(System.Action<System.Object>,My.Qltest.D,My.Qltest.D)", "", "Argument[2].Field[My.Qltest.D.Field2]", "Argument[0].Parameter[0]", "value", "manual"]
- ["My.Qltest", "D", false, "Apply2<>", "(System.Action<S>,S,S)", "", "Argument[1].Field[My.Qltest.D.Field]", "Argument[0].Parameter[0]", "value", "manual"]
- ["My.Qltest", "D", false, "Apply2<>", "(System.Action<S>,S,S)", "", "Argument[2].Field[My.Qltest.D.Field2]", "Argument[0].Parameter[0]", "value", "manual"]
- ["My.Qltest", "D", false, "Map<,>", "(S[],System.Func<S,T>)", "", "Argument[0].Element", "Argument[1].Parameter[0]", "value", "manual"]
- ["My.Qltest", "D", false, "Map<,>", "(S[],System.Func<S,T>)", "", "Argument[1].ReturnValue", "ReturnValue.Element", "value", "manual"]
- ["My.Qltest", "D", false, "Parse", "(System.String,System.Int32)", "", "Argument[0]", "Argument[1]", "taint", "manual"]

File diff suppressed because it is too large Load Diff

View File

@@ -3,10 +3,9 @@
*/
import csharp
import DefaultValueFlow::PathGraph
import TestUtilities.InlineFlowTest
import DefaultFlowTest
import PathGraph
from PathNode source, PathNode sink
where flowPath(source, sink)
from DefaultValueFlow::PathNode source, DefaultValueFlow::PathNode sink
where DefaultValueFlow::flowPath(source, sink)
select sink, source, sink, "$@", source, source.toString()

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