mirror of
https://github.com/github/codeql.git
synced 2026-04-30 11:15:13 +02:00
Merge branch 'main' into atorralba/java/command-injection-mad-sinks
This commit is contained in:
3
.github/labeler.yml
vendored
3
.github/labeler.yml
vendored
@@ -11,7 +11,7 @@ Go:
|
||||
- change-notes/**/*go.*
|
||||
|
||||
Java:
|
||||
- any: [ 'java/**/*', '!java/kotlin-extractor/**/*', '!java/kotlin-explorer/**/*', '!java/ql/test/kotlin/**/*' ]
|
||||
- any: [ 'java/**/*', '!java/kotlin-extractor/**/*', '!java/ql/test/kotlin/**/*' ]
|
||||
- change-notes/**/*java.*
|
||||
|
||||
JS:
|
||||
@@ -20,7 +20,6 @@ JS:
|
||||
|
||||
Kotlin:
|
||||
- java/kotlin-extractor/**/*
|
||||
- java/kotlin-explorer/**/*
|
||||
- java/ql/test/kotlin/**/*
|
||||
|
||||
Python:
|
||||
|
||||
@@ -10,6 +10,7 @@ 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"
|
||||
|
||||
@@ -8,7 +8,6 @@
|
||||
/swift/ @github/codeql-swift
|
||||
/misc/codegen/ @github/codeql-swift
|
||||
/java/kotlin-extractor/ @github/codeql-kotlin
|
||||
/java/kotlin-explorer/ @github/codeql-kotlin
|
||||
|
||||
# ML-powered queries
|
||||
/javascript/ql/experimental/adaptivethreatmodeling/ @github/codeql-ml-powered-queries-reviewers
|
||||
|
||||
@@ -511,7 +511,8 @@
|
||||
"SensitiveDataHeuristics Python/JS": [
|
||||
"javascript/ql/lib/semmle/javascript/security/internal/SensitiveDataHeuristics.qll",
|
||||
"python/ql/lib/semmle/python/security/internal/SensitiveDataHeuristics.qll",
|
||||
"ruby/ql/lib/codeql/ruby/security/internal/SensitiveDataHeuristics.qll"
|
||||
"ruby/ql/lib/codeql/ruby/security/internal/SensitiveDataHeuristics.qll",
|
||||
"swift/ql/lib/codeql/swift/security/internal/SensitiveDataHeuristics.qll"
|
||||
],
|
||||
"CFG": [
|
||||
"csharp/ql/lib/semmle/code/csharp/controlflow/internal/ControlFlowGraphImplShared.qll",
|
||||
@@ -598,4 +599,4 @@
|
||||
"python/ql/lib/semmle/python/security/internal/EncryptionKeySizes.qll",
|
||||
"java/ql/lib/semmle/code/java/security/internal/EncryptionKeySizes.qll"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
6
cpp/ql/lib/change-notes/2022-08-06-delete-deps.md
Normal file
6
cpp/ql/lib/change-notes/2022-08-06-delete-deps.md
Normal file
@@ -0,0 +1,6 @@
|
||||
---
|
||||
category: minorAnalysis
|
||||
---
|
||||
* 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.
|
||||
@@ -176,20 +176,6 @@ 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.
|
||||
|
||||
@@ -27,9 +27,6 @@ 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))
|
||||
}
|
||||
@@ -239,9 +236,6 @@ class PrintAstNode extends TPrintAstNode {
|
||||
}
|
||||
}
|
||||
|
||||
/** DEPRECATED: Alias for PrintAstNode */
|
||||
deprecated class PrintASTNode = PrintAstNode;
|
||||
|
||||
/**
|
||||
* Class that restricts the elements that we compute `qlClass` for.
|
||||
*/
|
||||
@@ -286,9 +280,6 @@ 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`.
|
||||
*/
|
||||
@@ -296,9 +287,6 @@ abstract class AstNode extends BaseAstNode, TAstNode {
|
||||
AstNode() { this = TAstNode(ast) }
|
||||
}
|
||||
|
||||
/** DEPRECATED: Alias for AstNode */
|
||||
deprecated class ASTNode = AstNode;
|
||||
|
||||
/**
|
||||
* A node representing an `Expr`.
|
||||
*/
|
||||
|
||||
@@ -14,9 +14,6 @@ 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
|
||||
|
||||
@@ -312,6 +312,3 @@ library class SsaHelper extends int {
|
||||
ssa_use(v, result, _, _)
|
||||
}
|
||||
}
|
||||
|
||||
/** DEPRECATED: Alias for SsaHelper */
|
||||
deprecated class SSAHelper = SsaHelper;
|
||||
|
||||
@@ -1385,9 +1385,6 @@ 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.
|
||||
@@ -1398,9 +1395,6 @@ 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.
|
||||
@@ -1410,7 +1404,4 @@ private module Cached {
|
||||
conditionalSuccessor(n1, false, n2) and
|
||||
not conditionalSuccessor(n1, true, n2)
|
||||
}
|
||||
|
||||
/** DEPRECATED: Alias for qlCfgFalseSuccessor */
|
||||
deprecated predicate qlCFGFalseSuccessor = qlCfgFalseSuccessor/2;
|
||||
}
|
||||
|
||||
@@ -1135,8 +1135,8 @@ module Impl<FullStateConfigSig Config> {
|
||||
DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow
|
||||
);
|
||||
|
||||
bindingset[node, state, t, ap]
|
||||
predicate filter(NodeEx node, FlowState state, Typ t, Ap ap);
|
||||
bindingset[node, state, t0, ap]
|
||||
predicate filter(NodeEx node, FlowState state, Typ t0, Ap ap, Typ t);
|
||||
|
||||
bindingset[typ, contentType]
|
||||
predicate typecheckStore(Typ typ, DataFlowType contentType);
|
||||
@@ -1199,17 +1199,21 @@ module Impl<FullStateConfigSig Config> {
|
||||
NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, TypOption argT,
|
||||
ApOption argAp, Typ t, Ap ap, ApApprox apa
|
||||
) {
|
||||
fwdFlow0(node, state, cc, summaryCtx, argT, argAp, t, ap, apa) and
|
||||
PrevStage::revFlow(node, state, apa) and
|
||||
filter(node, state, t, ap)
|
||||
fwdFlow1(node, state, cc, summaryCtx, argT, argAp, _, t, ap, apa)
|
||||
}
|
||||
|
||||
pragma[inline]
|
||||
additional predicate fwdFlow(
|
||||
private predicate fwdFlow1(
|
||||
NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, TypOption argT,
|
||||
ApOption argAp, Typ t, Ap ap
|
||||
ApOption argAp, Typ t0, Typ t, Ap ap, ApApprox apa
|
||||
) {
|
||||
fwdFlow(node, state, cc, summaryCtx, argT, argAp, t, ap, _)
|
||||
fwdFlow0(node, state, cc, summaryCtx, argT, argAp, t0, ap, apa) and
|
||||
PrevStage::revFlow(node, state, apa) and
|
||||
filter(node, state, t0, ap, t)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate typeStrengthen(Typ t0, Ap ap, Typ t) {
|
||||
fwdFlow1(_, _, _, _, _, _, t0, t, ap, _) and t0 != t
|
||||
}
|
||||
|
||||
pragma[assume_small_delta]
|
||||
@@ -1339,6 +1343,11 @@ 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]
|
||||
@@ -1359,7 +1368,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)
|
||||
)
|
||||
@@ -1520,14 +1529,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()
|
||||
@@ -1780,13 +1789,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
|
||||
@@ -1963,10 +1972,10 @@ module Impl<FullStateConfigSig Config> {
|
||||
)
|
||||
}
|
||||
|
||||
bindingset[node, state, t, ap]
|
||||
predicate filter(NodeEx node, FlowState state, Typ t, Ap ap) {
|
||||
bindingset[node, state, t0, ap]
|
||||
predicate filter(NodeEx node, FlowState state, Typ t0, Ap ap, Typ t) {
|
||||
PrevStage::revFlowState(state) and
|
||||
exists(t) and
|
||||
t0 = t and
|
||||
exists(ap) and
|
||||
not stateBarrier(node, state) and
|
||||
(
|
||||
@@ -2197,8 +2206,8 @@ module Impl<FullStateConfigSig Config> {
|
||||
import BooleanCallContext
|
||||
|
||||
predicate localStep(
|
||||
NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue,
|
||||
DataFlowType t, LocalCc lcc
|
||||
NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, Typ t,
|
||||
LocalCc lcc
|
||||
) {
|
||||
localFlowBigStep(node1, state1, node2, state2, preservesValue, t, _) and
|
||||
exists(lcc)
|
||||
@@ -2218,10 +2227,16 @@ module Impl<FullStateConfigSig Config> {
|
||||
)
|
||||
}
|
||||
|
||||
bindingset[node, state, t, ap]
|
||||
predicate filter(NodeEx node, FlowState state, Typ t, Ap ap) {
|
||||
bindingset[node, state, t0, ap]
|
||||
predicate filter(NodeEx node, FlowState state, Typ t0, Ap ap, Typ t) {
|
||||
exists(state) and
|
||||
(if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), t) else any()) 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
|
||||
(
|
||||
notExpectsContent(node)
|
||||
or
|
||||
@@ -2241,6 +2256,16 @@ 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;
|
||||
|
||||
@@ -2274,8 +2299,8 @@ module Impl<FullStateConfigSig Config> {
|
||||
|
||||
pragma[nomagic]
|
||||
predicate localStep(
|
||||
NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue,
|
||||
DataFlowType t, LocalCc lcc
|
||||
NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, Typ t,
|
||||
LocalCc lcc
|
||||
) {
|
||||
localFlowBigStep(node1, state1, node2, state2, preservesValue, t, _) and
|
||||
PrevStage::revFlow(node1, pragma[only_bind_into](state1), _) and
|
||||
@@ -2333,11 +2358,11 @@ module Impl<FullStateConfigSig Config> {
|
||||
)
|
||||
}
|
||||
|
||||
bindingset[node, state, t, ap]
|
||||
predicate filter(NodeEx node, FlowState state, Typ t, Ap ap) {
|
||||
bindingset[node, state, t0, ap]
|
||||
predicate filter(NodeEx node, FlowState state, Typ t0, Ap ap, Typ t) {
|
||||
exists(state) and
|
||||
not clear(node, ap) and
|
||||
(if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), t) else any()) and
|
||||
strengthenType(node, t0, t) and
|
||||
(
|
||||
notExpectsContent(node)
|
||||
or
|
||||
@@ -2365,7 +2390,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, _)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -2579,8 +2604,8 @@ module Impl<FullStateConfigSig Config> {
|
||||
import LocalCallContext
|
||||
|
||||
predicate localStep(
|
||||
NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue,
|
||||
DataFlowType t, LocalCc lcc
|
||||
NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, Typ t,
|
||||
LocalCc lcc
|
||||
) {
|
||||
localFlowBigStep(node1, state1, node2, state2, preservesValue, t, lcc) and
|
||||
PrevStage::revFlow(node1, pragma[only_bind_into](state1), _) and
|
||||
@@ -2609,9 +2634,9 @@ module Impl<FullStateConfigSig Config> {
|
||||
)
|
||||
}
|
||||
|
||||
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
|
||||
bindingset[node, state, t0, ap]
|
||||
predicate filter(NodeEx node, FlowState state, Typ t0, Ap ap, Typ t) {
|
||||
strengthenType(node, t0, t) and
|
||||
exists(state) and
|
||||
exists(ap)
|
||||
}
|
||||
@@ -2632,7 +2657,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, _)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -2649,7 +2674,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, _, _, _, _, t, apa) and
|
||||
Stage5::fwdFlow(p, state, _, _, Option<DataFlowType>::some(t), _, _, apa, _) and
|
||||
Stage5::revFlow(p, state, _)
|
||||
)
|
||||
}
|
||||
@@ -2820,9 +2845,7 @@ module Impl<FullStateConfigSig Config> {
|
||||
ap = TAccessPathNil()
|
||||
or
|
||||
// ... or a step from an existing PathNode to another node.
|
||||
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())
|
||||
pathStep(_, node, state, cc, sc, t, ap)
|
||||
} or
|
||||
TPathNodeSink(NodeEx node, FlowState state) {
|
||||
exists(PathNodeMid sink |
|
||||
@@ -3340,13 +3363,24 @@ 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 pathStep(
|
||||
private predicate pathStep0(
|
||||
PathNodeMid mid, NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, DataFlowType t,
|
||||
AccessPath ap
|
||||
) {
|
||||
@@ -3964,7 +3998,7 @@ module Impl<FullStateConfigSig Config> {
|
||||
ap = TPartialNil() and
|
||||
exists(explorationLimit())
|
||||
or
|
||||
partialPathNodeMk0(node, state, cc, sc1, sc2, sc3, sc4, t, ap) and
|
||||
partialPathStep(_, node, state, cc, sc1, sc2, sc3, sc4, t, ap) and
|
||||
distSrc(node.getEnclosingCallable()) <= explorationLimit()
|
||||
} or
|
||||
TPartialPathNodeRev(
|
||||
@@ -3990,11 +4024,20 @@ module Impl<FullStateConfigSig Config> {
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate partialPathNodeMk0(
|
||||
NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2,
|
||||
TSummaryCtx3 sc3, TSummaryCtx4 sc4, DataFlowType t, PartialAccessPath ap
|
||||
private predicate partialPathStep(
|
||||
PartialPathNodeFwd mid, NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1,
|
||||
TSummaryCtx2 sc2, TSummaryCtx3 sc3, TSummaryCtx4 sc4, DataFlowType t, PartialAccessPath ap
|
||||
) {
|
||||
partialPathStep(_, node, state, cc, sc1, sc2, sc3, sc4, t, ap) and
|
||||
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
|
||||
not fullBarrier(node) and
|
||||
not stateBarrier(node, state) and
|
||||
not clearsContentEx(node, ap.getHead()) and
|
||||
@@ -4002,9 +4045,14 @@ module Impl<FullStateConfigSig Config> {
|
||||
notExpectsContent(node) or
|
||||
expectsContentEx(node, ap.getHead())
|
||||
) and
|
||||
if node.asNode() instanceof CastingNode
|
||||
then compatibleTypes(node.getDataFlowType(), t)
|
||||
else any()
|
||||
strengthenType(node, t0, t)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate partialPathTypeStrengthen(
|
||||
DataFlowType t0, PartialAccessPath ap, DataFlowType t
|
||||
) {
|
||||
partialPathStep1(_, _, _, _, _, _, _, _, t0, t, ap) and t0 != t
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -4183,7 +4231,8 @@ module Impl<FullStateConfigSig Config> {
|
||||
}
|
||||
}
|
||||
|
||||
private predicate partialPathStep(
|
||||
pragma[nomagic]
|
||||
private predicate partialPathStep0(
|
||||
PartialPathNodeFwd mid, NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1,
|
||||
TSummaryCtx2 sc2, TSummaryCtx3 sc3, TSummaryCtx4 sc4, DataFlowType t, PartialAccessPath ap
|
||||
) {
|
||||
@@ -4309,6 +4358,11 @@ 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]
|
||||
|
||||
@@ -205,6 +205,8 @@ 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
|
||||
|
||||
@@ -1135,8 +1135,8 @@ module Impl<FullStateConfigSig Config> {
|
||||
DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow
|
||||
);
|
||||
|
||||
bindingset[node, state, t, ap]
|
||||
predicate filter(NodeEx node, FlowState state, Typ t, Ap ap);
|
||||
bindingset[node, state, t0, ap]
|
||||
predicate filter(NodeEx node, FlowState state, Typ t0, Ap ap, Typ t);
|
||||
|
||||
bindingset[typ, contentType]
|
||||
predicate typecheckStore(Typ typ, DataFlowType contentType);
|
||||
@@ -1199,17 +1199,21 @@ module Impl<FullStateConfigSig Config> {
|
||||
NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, TypOption argT,
|
||||
ApOption argAp, Typ t, Ap ap, ApApprox apa
|
||||
) {
|
||||
fwdFlow0(node, state, cc, summaryCtx, argT, argAp, t, ap, apa) and
|
||||
PrevStage::revFlow(node, state, apa) and
|
||||
filter(node, state, t, ap)
|
||||
fwdFlow1(node, state, cc, summaryCtx, argT, argAp, _, t, ap, apa)
|
||||
}
|
||||
|
||||
pragma[inline]
|
||||
additional predicate fwdFlow(
|
||||
private predicate fwdFlow1(
|
||||
NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, TypOption argT,
|
||||
ApOption argAp, Typ t, Ap ap
|
||||
ApOption argAp, Typ t0, Typ t, Ap ap, ApApprox apa
|
||||
) {
|
||||
fwdFlow(node, state, cc, summaryCtx, argT, argAp, t, ap, _)
|
||||
fwdFlow0(node, state, cc, summaryCtx, argT, argAp, t0, ap, apa) and
|
||||
PrevStage::revFlow(node, state, apa) and
|
||||
filter(node, state, t0, ap, t)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate typeStrengthen(Typ t0, Ap ap, Typ t) {
|
||||
fwdFlow1(_, _, _, _, _, _, t0, t, ap, _) and t0 != t
|
||||
}
|
||||
|
||||
pragma[assume_small_delta]
|
||||
@@ -1339,6 +1343,11 @@ 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]
|
||||
@@ -1359,7 +1368,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)
|
||||
)
|
||||
@@ -1520,14 +1529,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()
|
||||
@@ -1780,13 +1789,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
|
||||
@@ -1963,10 +1972,10 @@ module Impl<FullStateConfigSig Config> {
|
||||
)
|
||||
}
|
||||
|
||||
bindingset[node, state, t, ap]
|
||||
predicate filter(NodeEx node, FlowState state, Typ t, Ap ap) {
|
||||
bindingset[node, state, t0, ap]
|
||||
predicate filter(NodeEx node, FlowState state, Typ t0, Ap ap, Typ t) {
|
||||
PrevStage::revFlowState(state) and
|
||||
exists(t) and
|
||||
t0 = t and
|
||||
exists(ap) and
|
||||
not stateBarrier(node, state) and
|
||||
(
|
||||
@@ -2197,8 +2206,8 @@ module Impl<FullStateConfigSig Config> {
|
||||
import BooleanCallContext
|
||||
|
||||
predicate localStep(
|
||||
NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue,
|
||||
DataFlowType t, LocalCc lcc
|
||||
NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, Typ t,
|
||||
LocalCc lcc
|
||||
) {
|
||||
localFlowBigStep(node1, state1, node2, state2, preservesValue, t, _) and
|
||||
exists(lcc)
|
||||
@@ -2218,10 +2227,16 @@ module Impl<FullStateConfigSig Config> {
|
||||
)
|
||||
}
|
||||
|
||||
bindingset[node, state, t, ap]
|
||||
predicate filter(NodeEx node, FlowState state, Typ t, Ap ap) {
|
||||
bindingset[node, state, t0, ap]
|
||||
predicate filter(NodeEx node, FlowState state, Typ t0, Ap ap, Typ t) {
|
||||
exists(state) and
|
||||
(if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), t) else any()) 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
|
||||
(
|
||||
notExpectsContent(node)
|
||||
or
|
||||
@@ -2241,6 +2256,16 @@ 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;
|
||||
|
||||
@@ -2274,8 +2299,8 @@ module Impl<FullStateConfigSig Config> {
|
||||
|
||||
pragma[nomagic]
|
||||
predicate localStep(
|
||||
NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue,
|
||||
DataFlowType t, LocalCc lcc
|
||||
NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, Typ t,
|
||||
LocalCc lcc
|
||||
) {
|
||||
localFlowBigStep(node1, state1, node2, state2, preservesValue, t, _) and
|
||||
PrevStage::revFlow(node1, pragma[only_bind_into](state1), _) and
|
||||
@@ -2333,11 +2358,11 @@ module Impl<FullStateConfigSig Config> {
|
||||
)
|
||||
}
|
||||
|
||||
bindingset[node, state, t, ap]
|
||||
predicate filter(NodeEx node, FlowState state, Typ t, Ap ap) {
|
||||
bindingset[node, state, t0, ap]
|
||||
predicate filter(NodeEx node, FlowState state, Typ t0, Ap ap, Typ t) {
|
||||
exists(state) and
|
||||
not clear(node, ap) and
|
||||
(if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), t) else any()) and
|
||||
strengthenType(node, t0, t) and
|
||||
(
|
||||
notExpectsContent(node)
|
||||
or
|
||||
@@ -2365,7 +2390,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, _)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -2579,8 +2604,8 @@ module Impl<FullStateConfigSig Config> {
|
||||
import LocalCallContext
|
||||
|
||||
predicate localStep(
|
||||
NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue,
|
||||
DataFlowType t, LocalCc lcc
|
||||
NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, Typ t,
|
||||
LocalCc lcc
|
||||
) {
|
||||
localFlowBigStep(node1, state1, node2, state2, preservesValue, t, lcc) and
|
||||
PrevStage::revFlow(node1, pragma[only_bind_into](state1), _) and
|
||||
@@ -2609,9 +2634,9 @@ module Impl<FullStateConfigSig Config> {
|
||||
)
|
||||
}
|
||||
|
||||
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
|
||||
bindingset[node, state, t0, ap]
|
||||
predicate filter(NodeEx node, FlowState state, Typ t0, Ap ap, Typ t) {
|
||||
strengthenType(node, t0, t) and
|
||||
exists(state) and
|
||||
exists(ap)
|
||||
}
|
||||
@@ -2632,7 +2657,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, _)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -2649,7 +2674,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, _, _, _, _, t, apa) and
|
||||
Stage5::fwdFlow(p, state, _, _, Option<DataFlowType>::some(t), _, _, apa, _) and
|
||||
Stage5::revFlow(p, state, _)
|
||||
)
|
||||
}
|
||||
@@ -2820,9 +2845,7 @@ module Impl<FullStateConfigSig Config> {
|
||||
ap = TAccessPathNil()
|
||||
or
|
||||
// ... or a step from an existing PathNode to another node.
|
||||
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())
|
||||
pathStep(_, node, state, cc, sc, t, ap)
|
||||
} or
|
||||
TPathNodeSink(NodeEx node, FlowState state) {
|
||||
exists(PathNodeMid sink |
|
||||
@@ -3340,13 +3363,24 @@ 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 pathStep(
|
||||
private predicate pathStep0(
|
||||
PathNodeMid mid, NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, DataFlowType t,
|
||||
AccessPath ap
|
||||
) {
|
||||
@@ -3964,7 +3998,7 @@ module Impl<FullStateConfigSig Config> {
|
||||
ap = TPartialNil() and
|
||||
exists(explorationLimit())
|
||||
or
|
||||
partialPathNodeMk0(node, state, cc, sc1, sc2, sc3, sc4, t, ap) and
|
||||
partialPathStep(_, node, state, cc, sc1, sc2, sc3, sc4, t, ap) and
|
||||
distSrc(node.getEnclosingCallable()) <= explorationLimit()
|
||||
} or
|
||||
TPartialPathNodeRev(
|
||||
@@ -3990,11 +4024,20 @@ module Impl<FullStateConfigSig Config> {
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate partialPathNodeMk0(
|
||||
NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2,
|
||||
TSummaryCtx3 sc3, TSummaryCtx4 sc4, DataFlowType t, PartialAccessPath ap
|
||||
private predicate partialPathStep(
|
||||
PartialPathNodeFwd mid, NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1,
|
||||
TSummaryCtx2 sc2, TSummaryCtx3 sc3, TSummaryCtx4 sc4, DataFlowType t, PartialAccessPath ap
|
||||
) {
|
||||
partialPathStep(_, node, state, cc, sc1, sc2, sc3, sc4, t, ap) and
|
||||
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
|
||||
not fullBarrier(node) and
|
||||
not stateBarrier(node, state) and
|
||||
not clearsContentEx(node, ap.getHead()) and
|
||||
@@ -4002,9 +4045,14 @@ module Impl<FullStateConfigSig Config> {
|
||||
notExpectsContent(node) or
|
||||
expectsContentEx(node, ap.getHead())
|
||||
) and
|
||||
if node.asNode() instanceof CastingNode
|
||||
then compatibleTypes(node.getDataFlowType(), t)
|
||||
else any()
|
||||
strengthenType(node, t0, t)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate partialPathTypeStrengthen(
|
||||
DataFlowType t0, PartialAccessPath ap, DataFlowType t
|
||||
) {
|
||||
partialPathStep1(_, _, _, _, _, _, _, _, t0, t, ap) and t0 != t
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -4183,7 +4231,8 @@ module Impl<FullStateConfigSig Config> {
|
||||
}
|
||||
}
|
||||
|
||||
private predicate partialPathStep(
|
||||
pragma[nomagic]
|
||||
private predicate partialPathStep0(
|
||||
PartialPathNodeFwd mid, NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1,
|
||||
TSummaryCtx2 sc2, TSummaryCtx3 sc3, TSummaryCtx4 sc4, DataFlowType t, PartialAccessPath ap
|
||||
) {
|
||||
@@ -4309,6 +4358,11 @@ 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]
|
||||
|
||||
@@ -753,6 +753,8 @@ 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
|
||||
|
||||
@@ -364,7 +364,25 @@ abstract private class OperandBasedUse extends UseImpl {
|
||||
OperandBasedUse() { any() }
|
||||
|
||||
final override predicate hasIndexInBlock(IRBlock block, int index) {
|
||||
operand.getUse() = block.getInstruction(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)
|
||||
)
|
||||
}
|
||||
|
||||
final Operand getOperand() { result = operand }
|
||||
|
||||
@@ -144,6 +144,20 @@ class AllocationInstruction extends CallInstruction {
|
||||
AllocationInstruction() { this.getStaticCallTarget() instanceof Cpp::AllocationFunction }
|
||||
}
|
||||
|
||||
private predicate isIndirectionType(Type t) { t instanceof Indirection }
|
||||
|
||||
private predicate hasUnspecifiedBaseType(Indirection t, Type base) {
|
||||
base = t.getBaseType().getUnspecifiedType()
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `t2` is the same type as `t1`, but after stripping away `result` number
|
||||
* of indirections.
|
||||
* Furthermore, specifies in `t2` been deeply stripped and typedefs has been resolved.
|
||||
*/
|
||||
private int getNumberOfIndirectionsImpl(Type t1, Type t2) =
|
||||
shortestDistances(isIndirectionType/1, hasUnspecifiedBaseType/2)(t1, t2, result)
|
||||
|
||||
/**
|
||||
* An abstract class for handling indirections.
|
||||
*
|
||||
@@ -162,7 +176,10 @@ abstract class Indirection extends Type {
|
||||
* For example, the number of indirections of a variable `p` of type
|
||||
* `int**` is `3` (i.e., `p`, `*p` and `**p`).
|
||||
*/
|
||||
abstract int getNumberOfIndirections();
|
||||
final int getNumberOfIndirections() {
|
||||
result =
|
||||
getNumberOfIndirectionsImpl(this.getType(), any(Type end | not end instanceof Indirection))
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `deref` is an instruction that behaves as a `LoadInstruction`
|
||||
@@ -200,19 +217,11 @@ private class PointerOrArrayOrReferenceTypeIndirection extends Indirection insta
|
||||
PointerOrArrayOrReferenceTypeIndirection() {
|
||||
baseType = PointerOrArrayOrReferenceType.super.getBaseType()
|
||||
}
|
||||
|
||||
override int getNumberOfIndirections() {
|
||||
result = 1 + countIndirections(this.getBaseType().getUnspecifiedType())
|
||||
}
|
||||
}
|
||||
|
||||
private class PointerWrapperTypeIndirection extends Indirection instanceof PointerWrapper {
|
||||
PointerWrapperTypeIndirection() { baseType = PointerWrapper.super.getBaseType() }
|
||||
|
||||
override int getNumberOfIndirections() {
|
||||
result = 1 + countIndirections(this.getBaseType().getUnspecifiedType())
|
||||
}
|
||||
|
||||
override predicate isAdditionalDereference(Instruction deref, Operand address) {
|
||||
exists(CallInstruction call |
|
||||
operandForFullyConvertedCall(getAUse(deref), call) and
|
||||
@@ -233,10 +242,6 @@ private module IteratorIndirections {
|
||||
baseType = super.getValueType()
|
||||
}
|
||||
|
||||
override int getNumberOfIndirections() {
|
||||
result = 1 + countIndirections(this.getBaseType().getUnspecifiedType())
|
||||
}
|
||||
|
||||
override predicate isAdditionalDereference(Instruction deref, Operand address) {
|
||||
exists(CallInstruction call |
|
||||
operandForFullyConvertedCall(getAUse(deref), call) and
|
||||
|
||||
@@ -122,7 +122,46 @@ abstract private class OperandBasedUse extends UseImpl {
|
||||
override string toString() { result = operand.toString() }
|
||||
|
||||
final override predicate hasIndexInBlock(IRBlock block, int index) {
|
||||
operand.getUse() = block.getInstruction(index)
|
||||
// Ideally, this would just be implemented as:
|
||||
// ```
|
||||
// operand.getUse() = block.getInstruction(index)
|
||||
// ```
|
||||
// but because the IR generated for a snippet such as
|
||||
// ```
|
||||
// int x = *p++;
|
||||
// ```
|
||||
// looks like
|
||||
// ```
|
||||
// r1(glval<int>) = VariableAddress[x] :
|
||||
// r2(glval<int *>) = VariableAddress[p] :
|
||||
// r3(int *) = Load[p] : &:r2, m1
|
||||
// r4(int) = Constant[1] :
|
||||
// r5(int *) = PointerAdd[4] : r3, r4
|
||||
// m3(int *) = Store[p] : &:r2, r5
|
||||
// r6(int *) = CopyValue : r3
|
||||
// r7(int) = Load[?] : &:r6, ~m2
|
||||
// m2(int) = Store[x] : &:r1, r7
|
||||
// ```
|
||||
// we need to ensure that the `r3` operand of the `CopyValue` instruction isn't seen as a fresh use
|
||||
// of `p` that happens after the increment. So if the base instruction of this use comes from a
|
||||
// post-fix crement operation we set the index of the SSA use that wraps the `r3` operand at the
|
||||
// `CopyValue` instruction to be the same index as the `r3` operand at the `PointerAdd` instruction.
|
||||
// This ensures that the SSA library doesn't create flow from the `PointerAdd` to `r6`.
|
||||
exists(BaseSourceVariableInstruction base | base = this.getBase() |
|
||||
if base.getAst() = any(Cpp::PostfixCrementOperation c).getOperand()
|
||||
then
|
||||
exists(Operand op |
|
||||
op =
|
||||
min(Operand cand, int i |
|
||||
isUse(_, cand, base, _, _) and
|
||||
block.getInstruction(i) = cand.getUse()
|
||||
|
|
||||
cand order by i
|
||||
) and
|
||||
block.getInstruction(index) = op.getUse()
|
||||
)
|
||||
else operand.getUse() = block.getInstruction(index)
|
||||
)
|
||||
}
|
||||
|
||||
final override Cpp::Location getLocation() { result = operand.getLocation() }
|
||||
|
||||
@@ -210,9 +210,6 @@ class Instruction extends Construction::TStageInstruction {
|
||||
*/
|
||||
final Language::AST getAst() { result = Construction::getInstructionAst(this) }
|
||||
|
||||
/** DEPRECATED: Alias for getAst */
|
||||
deprecated Language::AST getAST() { result = this.getAst() }
|
||||
|
||||
/**
|
||||
* Gets the location of the source code for this instruction.
|
||||
*/
|
||||
@@ -463,9 +460,6 @@ class VariableInstruction extends Instruction {
|
||||
* Gets the AST variable that this instruction's IR variable refers to, if one exists.
|
||||
*/
|
||||
final Language::Variable getAstVariable() { result = var.(IRUserVariable).getVariable() }
|
||||
|
||||
/** DEPRECATED: Alias for getAstVariable */
|
||||
deprecated Language::Variable getASTVariable() { result = this.getAstVariable() }
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -577,9 +577,6 @@ 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() }
|
||||
|
||||
|
||||
@@ -422,12 +422,6 @@ private module Cached {
|
||||
)
|
||||
}
|
||||
|
||||
/** DEPRECATED: Alias for getInstructionAst */
|
||||
cached
|
||||
deprecated Language::AST getInstructionAST(Instruction instr) {
|
||||
result = getInstructionAst(instr)
|
||||
}
|
||||
|
||||
cached
|
||||
Language::LanguageType getInstructionResultType(Instruction instr) {
|
||||
result = instr.(RawIR::Instruction).getResultLanguageType()
|
||||
@@ -993,9 +987,6 @@ predicate canReuseSsaForMemoryResult(Instruction instruction) {
|
||||
// We don't support reusing SSA for any location that could create a `Chi` instruction.
|
||||
}
|
||||
|
||||
/** DEPRECATED: Alias for canReuseSsaForMemoryResult */
|
||||
deprecated predicate canReuseSSAForMemoryResult = canReuseSsaForMemoryResult/1;
|
||||
|
||||
/**
|
||||
* Expose some of the internal predicates to PrintSSA.qll. We do this by publicly importing those modules in the
|
||||
* `DebugSsa` module, which is then imported by PrintSSA.
|
||||
@@ -1005,9 +996,6 @@ module DebugSsa {
|
||||
import DefUse
|
||||
}
|
||||
|
||||
/** DEPRECATED: Alias for DebugSsa */
|
||||
deprecated module DebugSSA = DebugSsa;
|
||||
|
||||
import CachedForDebugging
|
||||
|
||||
cached
|
||||
|
||||
@@ -73,9 +73,6 @@ module UnaliasedSsaInstructions {
|
||||
}
|
||||
}
|
||||
|
||||
/** DEPRECATED: Alias for UnaliasedSsaInstructions */
|
||||
deprecated module UnaliasedSSAInstructions = UnaliasedSsaInstructions;
|
||||
|
||||
/**
|
||||
* Provides wrappers for the constructors of each branch of `TInstruction` that is used by the
|
||||
* aliased SSA stage.
|
||||
@@ -107,6 +104,3 @@ module AliasedSsaInstructions {
|
||||
result = TAliasedSsaUnreachedInstruction(irFunc)
|
||||
}
|
||||
}
|
||||
|
||||
/** DEPRECATED: Alias for AliasedSsaInstructions */
|
||||
deprecated module AliasedSSAInstructions = AliasedSsaInstructions;
|
||||
|
||||
@@ -74,20 +74,12 @@ 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)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -167,9 +159,6 @@ 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.
|
||||
@@ -217,6 +206,3 @@ module AliasedSsaOperands {
|
||||
result = Internal::TAliasedChiOperand(useInstr, tag)
|
||||
}
|
||||
}
|
||||
|
||||
/** DEPRECATED: Alias for AliasedSsaOperands */
|
||||
deprecated module AliasedSSAOperands = AliasedSsaOperands;
|
||||
|
||||
@@ -210,9 +210,6 @@ class Instruction extends Construction::TStageInstruction {
|
||||
*/
|
||||
final Language::AST getAst() { result = Construction::getInstructionAst(this) }
|
||||
|
||||
/** DEPRECATED: Alias for getAst */
|
||||
deprecated Language::AST getAST() { result = this.getAst() }
|
||||
|
||||
/**
|
||||
* Gets the location of the source code for this instruction.
|
||||
*/
|
||||
@@ -463,9 +460,6 @@ class VariableInstruction extends Instruction {
|
||||
* Gets the AST variable that this instruction's IR variable refers to, if one exists.
|
||||
*/
|
||||
final Language::Variable getAstVariable() { result = var.(IRUserVariable).getVariable() }
|
||||
|
||||
/** DEPRECATED: Alias for getAstVariable */
|
||||
deprecated Language::Variable getASTVariable() { result = this.getAstVariable() }
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -375,11 +375,6 @@ 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
|
||||
|
||||
@@ -76,9 +76,6 @@ 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) }
|
||||
|
||||
/**
|
||||
|
||||
@@ -210,9 +210,6 @@ class Instruction extends Construction::TStageInstruction {
|
||||
*/
|
||||
final Language::AST getAst() { result = Construction::getInstructionAst(this) }
|
||||
|
||||
/** DEPRECATED: Alias for getAst */
|
||||
deprecated Language::AST getAST() { result = this.getAst() }
|
||||
|
||||
/**
|
||||
* Gets the location of the source code for this instruction.
|
||||
*/
|
||||
@@ -463,9 +460,6 @@ class VariableInstruction extends Instruction {
|
||||
* Gets the AST variable that this instruction's IR variable refers to, if one exists.
|
||||
*/
|
||||
final Language::Variable getAstVariable() { result = var.(IRUserVariable).getVariable() }
|
||||
|
||||
/** DEPRECATED: Alias for getAstVariable */
|
||||
deprecated Language::Variable getASTVariable() { result = this.getAstVariable() }
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -422,12 +422,6 @@ private module Cached {
|
||||
)
|
||||
}
|
||||
|
||||
/** DEPRECATED: Alias for getInstructionAst */
|
||||
cached
|
||||
deprecated Language::AST getInstructionAST(Instruction instr) {
|
||||
result = getInstructionAst(instr)
|
||||
}
|
||||
|
||||
cached
|
||||
Language::LanguageType getInstructionResultType(Instruction instr) {
|
||||
result = instr.(RawIR::Instruction).getResultLanguageType()
|
||||
@@ -993,9 +987,6 @@ predicate canReuseSsaForMemoryResult(Instruction instruction) {
|
||||
// We don't support reusing SSA for any location that could create a `Chi` instruction.
|
||||
}
|
||||
|
||||
/** DEPRECATED: Alias for canReuseSsaForMemoryResult */
|
||||
deprecated predicate canReuseSSAForMemoryResult = canReuseSsaForMemoryResult/1;
|
||||
|
||||
/**
|
||||
* Expose some of the internal predicates to PrintSSA.qll. We do this by publicly importing those modules in the
|
||||
* `DebugSsa` module, which is then imported by PrintSSA.
|
||||
@@ -1005,9 +996,6 @@ module DebugSsa {
|
||||
import DefUse
|
||||
}
|
||||
|
||||
/** DEPRECATED: Alias for DebugSsa */
|
||||
deprecated module DebugSSA = DebugSsa;
|
||||
|
||||
import CachedForDebugging
|
||||
|
||||
cached
|
||||
|
||||
@@ -46,9 +46,6 @@ predicate canReuseSsaForVariable(IRAutomaticVariable var) {
|
||||
not allocationEscapes(var)
|
||||
}
|
||||
|
||||
/** DEPRECATED: Alias for canReuseSsaForVariable */
|
||||
deprecated predicate canReuseSSAForVariable = canReuseSsaForVariable/1;
|
||||
|
||||
private newtype TMemoryLocation = MkMemoryLocation(Allocation var) { isVariableModeled(var) }
|
||||
|
||||
private MemoryLocation getMemoryLocation(Allocation var) { result.getAllocation() = var }
|
||||
@@ -80,9 +77,6 @@ class MemoryLocation extends TMemoryLocation {
|
||||
|
||||
predicate canReuseSsaForOldResult(Instruction instr) { none() }
|
||||
|
||||
/** DEPRECATED: Alias for canReuseSsaForOldResult */
|
||||
deprecated predicate canReuseSSAForOldResult = canReuseSsaForOldResult/1;
|
||||
|
||||
/**
|
||||
* Represents a set of `MemoryLocation`s that cannot overlap with
|
||||
* `MemoryLocation`s outside of the set. The `VirtualVariable` will be
|
||||
|
||||
@@ -40,9 +40,6 @@ 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)
|
||||
|
||||
@@ -16,9 +16,6 @@ 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`. */
|
||||
@@ -51,6 +48,3 @@ class ExternalApiUsedWithUntrustedData extends TExternalApi {
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/** DEPRECATED: Alias for ExternalApiUsedWithUntrustedData */
|
||||
deprecated class ExternalAPIUsedWithUntrustedData = ExternalApiUsedWithUntrustedData;
|
||||
|
||||
@@ -41,9 +41,6 @@ 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" }
|
||||
@@ -58,9 +55,6 @@ 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) {
|
||||
|
||||
@@ -10,9 +10,6 @@ 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() {
|
||||
|
||||
@@ -16,9 +16,6 @@ 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`. */
|
||||
@@ -51,6 +48,3 @@ class ExternalApiUsedWithUntrustedData extends TExternalApi {
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/** DEPRECATED: Alias for ExternalApiUsedWithUntrustedData */
|
||||
deprecated class ExternalAPIUsedWithUntrustedData = ExternalApiUsedWithUntrustedData;
|
||||
|
||||
@@ -41,9 +41,6 @@ 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" }
|
||||
@@ -53,9 +50,6 @@ 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 }
|
||||
|
||||
@@ -10,9 +10,6 @@ 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() {
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
<!DOCTYPE qhelp PUBLIC
|
||||
"-//Semmle//qhelp//EN"
|
||||
"qhelp.dtd">
|
||||
<qhelp>
|
||||
|
||||
<overview>
|
||||
<p>
|
||||
Detects <code>if (a+b>c) a=c-b</code>, which incorrectly implements
|
||||
<code>a = min(a,c-b)</code> if <code>a+b</code> overflows.
|
||||
</p>
|
||||
<p>
|
||||
Also detects variants such as <code>if (b+a>c) a=c-b</code> (swapped
|
||||
terms in addition), <code>if (a+b>c) { a=c-b }</code> (assignment
|
||||
inside block), <code>c<a+b</code> (swapped operands), and
|
||||
<code>>=</code>, <code><</code>, <code><=</code> instead of
|
||||
<code>></code> (all operators).
|
||||
</p>
|
||||
<p>
|
||||
This integer overflow is the root cause of the buffer overflow in
|
||||
the SHA-3 reference implementation (CVE-2022-37454).
|
||||
</p>
|
||||
</overview>
|
||||
<recommendation>
|
||||
<p>
|
||||
Replace by <code>if (a>c-b) a=c-b</code>. This avoids the overflow
|
||||
and makes it easy to see that <code>a = min(a,c-b)</code>.
|
||||
</p>
|
||||
</recommendation>
|
||||
<references>
|
||||
<li>CVE-2022-37454: <a href="https://nvd.nist.gov/vuln/detail/CVE-2022-37454">The Keccak XKCP SHA-3 reference implementation before fdc6fef has an integer overflow and resultant buffer overflow that allows attackers to execute arbitrary code or eliminate expected cryptographic properties. This occurs in the sponge function interface.</a></li>
|
||||
<li>GitHub Advisory Database: <a href="https://github.com/advisories/GHSA-6w4m-2xhg-2658">CVE-2022-37454: Buffer overflow in sponge queue functions</a></li>
|
||||
</references>
|
||||
</qhelp>
|
||||
@@ -0,0 +1,42 @@
|
||||
/**
|
||||
* @name Integer addition may overflow inside if statement
|
||||
* @description Writing 'if (a+b>c) a=c-b' incorrectly implements
|
||||
* 'a = min(a,c-b)' if 'a+b' overflows. This integer
|
||||
* overflow is the root cause of the buffer overflow
|
||||
* in the SHA-3 reference implementation (CVE-2022-37454).
|
||||
* @kind problem
|
||||
* @problem.severity warning
|
||||
* @id cpp/if-statement-addition-overflow
|
||||
* @tags: experimental
|
||||
* correctness
|
||||
* security
|
||||
* external/cwe/cwe-190
|
||||
*/
|
||||
|
||||
import cpp
|
||||
import semmle.code.cpp.valuenumbering.GlobalValueNumbering
|
||||
import semmle.code.cpp.valuenumbering.HashCons
|
||||
import semmle.code.cpp.rangeanalysis.SimpleRangeAnalysis
|
||||
import semmle.code.cpp.controlflow.Guards
|
||||
|
||||
from
|
||||
GuardCondition guard, Expr expr, ExprStmt exprstmt, BasicBlock block, AssignExpr assignexpr,
|
||||
AddExpr addexpr, SubExpr subexpr
|
||||
where
|
||||
(guard.ensuresLt(expr, addexpr, 0, block, _) or guard.ensuresLt(addexpr, expr, 0, block, _)) and
|
||||
addexpr.getUnspecifiedType() instanceof IntegralType and
|
||||
exprMightOverflowPositively(addexpr) and
|
||||
block.getANode() = exprstmt and
|
||||
exprstmt.getExpr() = assignexpr and
|
||||
assignexpr.getRValue() = subexpr and
|
||||
(
|
||||
hashCons(addexpr.getLeftOperand()) = hashCons(assignexpr.getLValue()) and
|
||||
globalValueNumber(addexpr.getRightOperand()) = globalValueNumber(subexpr.getRightOperand())
|
||||
or
|
||||
hashCons(addexpr.getRightOperand()) = hashCons(assignexpr.getLValue()) and
|
||||
globalValueNumber(addexpr.getLeftOperand()) = globalValueNumber(subexpr.getRightOperand())
|
||||
) and
|
||||
globalValueNumber(expr) = globalValueNumber(subexpr.getLeftOperand())
|
||||
select guard,
|
||||
"\"if (a+b>c) a=c-b\" was detected where the $@ may potentially overflow/wraparound. The code can be rewritten as \"if (a>c-b) a=c-b\" which avoids the overflow.",
|
||||
addexpr, "addition"
|
||||
@@ -179,6 +179,24 @@ predicate isSinkImpl(
|
||||
pointerAddInstructionHasBounds(pai, sink1, sink2, delta)
|
||||
}
|
||||
|
||||
/**
|
||||
* Yields any instruction that is control-flow reachable from `instr`.
|
||||
*/
|
||||
bindingset[instr, result]
|
||||
pragma[inline_late]
|
||||
Instruction getASuccessor(Instruction instr) {
|
||||
exists(IRBlock b, int instrIndex, int resultIndex |
|
||||
result.getBlock() = b and
|
||||
instr.getBlock() = b and
|
||||
b.getInstruction(instrIndex) = instr and
|
||||
b.getInstruction(resultIndex) = result
|
||||
|
|
||||
resultIndex >= instrIndex
|
||||
)
|
||||
or
|
||||
instr.getBlock().getASuccessor+() = result.getBlock()
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `sink` is a sink for `InvalidPointerToDerefConfig` and `i` is a `StoreInstruction` that
|
||||
* writes to an address that non-strictly upper-bounds `sink`, or `i` is a `LoadInstruction` that
|
||||
@@ -186,8 +204,9 @@ predicate isSinkImpl(
|
||||
*/
|
||||
pragma[inline]
|
||||
predicate isInvalidPointerDerefSink(DataFlow::Node sink, Instruction i, string operation, int delta) {
|
||||
exists(AddressOperand addr |
|
||||
bounded1(addr.getDef(), sink.asInstruction(), delta) and
|
||||
exists(AddressOperand addr, Instruction s |
|
||||
s = sink.asInstruction() and
|
||||
bounded1(addr.getDef(), s, delta) and
|
||||
delta >= 0 and
|
||||
i.getAnOperand() = addr
|
||||
|
|
||||
@@ -247,7 +266,8 @@ newtype TMergedPathNode =
|
||||
TPathNodeSink(Instruction i) {
|
||||
exists(DataFlow::Node n |
|
||||
InvalidPointerToDerefFlow::flowTo(n) and
|
||||
isInvalidPointerDerefSink(n, i, _, _)
|
||||
isInvalidPointerDerefSink(n, i, _, _) and
|
||||
i = getASuccessor(n.asInstruction())
|
||||
)
|
||||
}
|
||||
|
||||
@@ -377,15 +397,19 @@ predicate hasFlowPath(
|
||||
}
|
||||
|
||||
from
|
||||
MergedPathNode source, MergedPathNode sink, int k2, int k3, string kstr,
|
||||
InvalidPointerToDerefFlow::PathNode source3, PointerArithmeticInstruction pai, string operation,
|
||||
Expr offset, DataFlow::Node n
|
||||
MergedPathNode source, MergedPathNode sink, int k, string kstr, PointerArithmeticInstruction pai,
|
||||
string operation, Expr offset, DataFlow::Node n
|
||||
where
|
||||
hasFlowPath(source, sink, source3, pai, operation, k3) and
|
||||
invalidPointerToDerefSource(pai, source3.getNode(), k2) and
|
||||
k =
|
||||
min(int k2, int k3, InvalidPointerToDerefFlow::PathNode source3 |
|
||||
hasFlowPath(source, sink, source3, pai, operation, k3) and
|
||||
invalidPointerToDerefSource(pai, source3.getNode(), k2)
|
||||
|
|
||||
k2 + k3
|
||||
) and
|
||||
offset = pai.getRight().getUnconvertedResultExpression() and
|
||||
n = source.asPathNode1().getNode() and
|
||||
if (k2 + k3) = 0 then kstr = "" else kstr = " + " + (k2 + k3)
|
||||
if k = 0 then kstr = "" else kstr = " + " + k
|
||||
select sink, source, sink,
|
||||
"This " + operation + " might be out of bounds, as the pointer might be equal to $@ + $@" + kstr +
|
||||
".", n, n.toString(), offset, offset.toString()
|
||||
|
||||
373
cpp/ql/src/external/CodeDuplication.qll
vendored
373
cpp/ql/src/external/CodeDuplication.qll
vendored
@@ -1,373 +0,0 @@
|
||||
/** 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)
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
| test.cpp:18:6:18:10 | ... > ... | "if (a+b>c) a=c-b" was detected where the $@ may potentially overflow/wraparound. The code can be rewritten as "if (a>c-b) a=c-b" which avoids the overflow. | test.cpp:18:6:18:8 | ... + ... | addition |
|
||||
| test.cpp:19:6:19:10 | ... > ... | "if (a+b>c) a=c-b" was detected where the $@ may potentially overflow/wraparound. The code can be rewritten as "if (a>c-b) a=c-b" which avoids the overflow. | test.cpp:19:6:19:8 | ... + ... | addition |
|
||||
| test.cpp:20:6:20:10 | ... > ... | "if (a+b>c) a=c-b" was detected where the $@ may potentially overflow/wraparound. The code can be rewritten as "if (a>c-b) a=c-b" which avoids the overflow. | test.cpp:20:6:20:8 | ... + ... | addition |
|
||||
| test.cpp:21:6:21:10 | ... > ... | "if (a+b>c) a=c-b" was detected where the $@ may potentially overflow/wraparound. The code can be rewritten as "if (a>c-b) a=c-b" which avoids the overflow. | test.cpp:21:6:21:8 | ... + ... | addition |
|
||||
| test.cpp:22:6:22:10 | ... > ... | "if (a+b>c) a=c-b" was detected where the $@ may potentially overflow/wraparound. The code can be rewritten as "if (a>c-b) a=c-b" which avoids the overflow. | test.cpp:22:8:22:10 | ... + ... | addition |
|
||||
| test.cpp:23:6:23:10 | ... > ... | "if (a+b>c) a=c-b" was detected where the $@ may potentially overflow/wraparound. The code can be rewritten as "if (a>c-b) a=c-b" which avoids the overflow. | test.cpp:23:8:23:10 | ... + ... | addition |
|
||||
| test.cpp:24:6:24:10 | ... > ... | "if (a+b>c) a=c-b" was detected where the $@ may potentially overflow/wraparound. The code can be rewritten as "if (a>c-b) a=c-b" which avoids the overflow. | test.cpp:24:8:24:10 | ... + ... | addition |
|
||||
| test.cpp:25:6:25:10 | ... > ... | "if (a+b>c) a=c-b" was detected where the $@ may potentially overflow/wraparound. The code can be rewritten as "if (a>c-b) a=c-b" which avoids the overflow. | test.cpp:25:8:25:10 | ... + ... | addition |
|
||||
| test.cpp:27:6:27:11 | ... >= ... | "if (a+b>c) a=c-b" was detected where the $@ may potentially overflow/wraparound. The code can be rewritten as "if (a>c-b) a=c-b" which avoids the overflow. | test.cpp:27:6:27:8 | ... + ... | addition |
|
||||
| test.cpp:28:6:28:11 | ... >= ... | "if (a+b>c) a=c-b" was detected where the $@ may potentially overflow/wraparound. The code can be rewritten as "if (a>c-b) a=c-b" which avoids the overflow. | test.cpp:28:6:28:8 | ... + ... | addition |
|
||||
| test.cpp:29:6:29:11 | ... >= ... | "if (a+b>c) a=c-b" was detected where the $@ may potentially overflow/wraparound. The code can be rewritten as "if (a>c-b) a=c-b" which avoids the overflow. | test.cpp:29:6:29:8 | ... + ... | addition |
|
||||
| test.cpp:30:6:30:11 | ... >= ... | "if (a+b>c) a=c-b" was detected where the $@ may potentially overflow/wraparound. The code can be rewritten as "if (a>c-b) a=c-b" which avoids the overflow. | test.cpp:30:6:30:8 | ... + ... | addition |
|
||||
| test.cpp:31:6:31:11 | ... >= ... | "if (a+b>c) a=c-b" was detected where the $@ may potentially overflow/wraparound. The code can be rewritten as "if (a>c-b) a=c-b" which avoids the overflow. | test.cpp:31:9:31:11 | ... + ... | addition |
|
||||
| test.cpp:32:6:32:11 | ... >= ... | "if (a+b>c) a=c-b" was detected where the $@ may potentially overflow/wraparound. The code can be rewritten as "if (a>c-b) a=c-b" which avoids the overflow. | test.cpp:32:9:32:11 | ... + ... | addition |
|
||||
| test.cpp:33:6:33:11 | ... >= ... | "if (a+b>c) a=c-b" was detected where the $@ may potentially overflow/wraparound. The code can be rewritten as "if (a>c-b) a=c-b" which avoids the overflow. | test.cpp:33:9:33:11 | ... + ... | addition |
|
||||
| test.cpp:34:6:34:11 | ... >= ... | "if (a+b>c) a=c-b" was detected where the $@ may potentially overflow/wraparound. The code can be rewritten as "if (a>c-b) a=c-b" which avoids the overflow. | test.cpp:34:9:34:11 | ... + ... | addition |
|
||||
| test.cpp:36:6:36:10 | ... < ... | "if (a+b>c) a=c-b" was detected where the $@ may potentially overflow/wraparound. The code can be rewritten as "if (a>c-b) a=c-b" which avoids the overflow. | test.cpp:36:6:36:8 | ... + ... | addition |
|
||||
| test.cpp:37:6:37:10 | ... < ... | "if (a+b>c) a=c-b" was detected where the $@ may potentially overflow/wraparound. The code can be rewritten as "if (a>c-b) a=c-b" which avoids the overflow. | test.cpp:37:6:37:8 | ... + ... | addition |
|
||||
| test.cpp:38:6:38:10 | ... < ... | "if (a+b>c) a=c-b" was detected where the $@ may potentially overflow/wraparound. The code can be rewritten as "if (a>c-b) a=c-b" which avoids the overflow. | test.cpp:38:6:38:8 | ... + ... | addition |
|
||||
| test.cpp:39:6:39:10 | ... < ... | "if (a+b>c) a=c-b" was detected where the $@ may potentially overflow/wraparound. The code can be rewritten as "if (a>c-b) a=c-b" which avoids the overflow. | test.cpp:39:6:39:8 | ... + ... | addition |
|
||||
| test.cpp:40:6:40:10 | ... < ... | "if (a+b>c) a=c-b" was detected where the $@ may potentially overflow/wraparound. The code can be rewritten as "if (a>c-b) a=c-b" which avoids the overflow. | test.cpp:40:8:40:10 | ... + ... | addition |
|
||||
| test.cpp:41:6:41:10 | ... < ... | "if (a+b>c) a=c-b" was detected where the $@ may potentially overflow/wraparound. The code can be rewritten as "if (a>c-b) a=c-b" which avoids the overflow. | test.cpp:41:8:41:10 | ... + ... | addition |
|
||||
| test.cpp:42:6:42:10 | ... < ... | "if (a+b>c) a=c-b" was detected where the $@ may potentially overflow/wraparound. The code can be rewritten as "if (a>c-b) a=c-b" which avoids the overflow. | test.cpp:42:8:42:10 | ... + ... | addition |
|
||||
| test.cpp:43:6:43:10 | ... < ... | "if (a+b>c) a=c-b" was detected where the $@ may potentially overflow/wraparound. The code can be rewritten as "if (a>c-b) a=c-b" which avoids the overflow. | test.cpp:43:8:43:10 | ... + ... | addition |
|
||||
| test.cpp:45:6:45:11 | ... <= ... | "if (a+b>c) a=c-b" was detected where the $@ may potentially overflow/wraparound. The code can be rewritten as "if (a>c-b) a=c-b" which avoids the overflow. | test.cpp:45:6:45:8 | ... + ... | addition |
|
||||
| test.cpp:46:6:46:11 | ... <= ... | "if (a+b>c) a=c-b" was detected where the $@ may potentially overflow/wraparound. The code can be rewritten as "if (a>c-b) a=c-b" which avoids the overflow. | test.cpp:46:6:46:8 | ... + ... | addition |
|
||||
| test.cpp:47:6:47:11 | ... <= ... | "if (a+b>c) a=c-b" was detected where the $@ may potentially overflow/wraparound. The code can be rewritten as "if (a>c-b) a=c-b" which avoids the overflow. | test.cpp:47:6:47:8 | ... + ... | addition |
|
||||
| test.cpp:48:6:48:11 | ... <= ... | "if (a+b>c) a=c-b" was detected where the $@ may potentially overflow/wraparound. The code can be rewritten as "if (a>c-b) a=c-b" which avoids the overflow. | test.cpp:48:6:48:8 | ... + ... | addition |
|
||||
| test.cpp:49:6:49:11 | ... <= ... | "if (a+b>c) a=c-b" was detected where the $@ may potentially overflow/wraparound. The code can be rewritten as "if (a>c-b) a=c-b" which avoids the overflow. | test.cpp:49:9:49:11 | ... + ... | addition |
|
||||
| test.cpp:50:6:50:11 | ... <= ... | "if (a+b>c) a=c-b" was detected where the $@ may potentially overflow/wraparound. The code can be rewritten as "if (a>c-b) a=c-b" which avoids the overflow. | test.cpp:50:9:50:11 | ... + ... | addition |
|
||||
| test.cpp:51:6:51:11 | ... <= ... | "if (a+b>c) a=c-b" was detected where the $@ may potentially overflow/wraparound. The code can be rewritten as "if (a>c-b) a=c-b" which avoids the overflow. | test.cpp:51:9:51:11 | ... + ... | addition |
|
||||
| test.cpp:52:6:52:11 | ... <= ... | "if (a+b>c) a=c-b" was detected where the $@ may potentially overflow/wraparound. The code can be rewritten as "if (a>c-b) a=c-b" which avoids the overflow. | test.cpp:52:9:52:11 | ... + ... | addition |
|
||||
| test.cpp:54:6:54:10 | ... > ... | "if (a+b>c) a=c-b" was detected where the $@ may potentially overflow/wraparound. The code can be rewritten as "if (a>c-b) a=c-b" which avoids the overflow. | test.cpp:54:6:54:8 | ... + ... | addition |
|
||||
| test.cpp:61:6:61:11 | ... <= ... | "if (a+b>c) a=c-b" was detected where the $@ may potentially overflow/wraparound. The code can be rewritten as "if (a>c-b) a=c-b" which avoids the overflow. | test.cpp:61:6:61:8 | ... + ... | addition |
|
||||
| test.cpp:62:6:62:11 | ... <= ... | "if (a+b>c) a=c-b" was detected where the $@ may potentially overflow/wraparound. The code can be rewritten as "if (a>c-b) a=c-b" which avoids the overflow. | test.cpp:62:6:62:8 | ... + ... | addition |
|
||||
@@ -0,0 +1 @@
|
||||
experimental/Security/CWE/CWE-190/IfStatementAdditionOverflow.ql
|
||||
@@ -0,0 +1,63 @@
|
||||
|
||||
int getAnInt();
|
||||
double getADouble();
|
||||
unsigned short getAnUnsignedShort();
|
||||
|
||||
void test()
|
||||
{
|
||||
int a = getAnInt();
|
||||
int b = getAnInt();
|
||||
int c = getAnInt();
|
||||
int x = getAnInt();
|
||||
int y = getAnInt();
|
||||
double d = getADouble();
|
||||
unsigned short a1 = getAnUnsignedShort();
|
||||
unsigned short b1 = getAnUnsignedShort();
|
||||
unsigned short c1 = getAnUnsignedShort();
|
||||
|
||||
if (a+b>c) a = c-b; // BAD
|
||||
if (a+b>c) { a = c-b; } // BAD
|
||||
if (b+a>c) a = c-b; // BAD
|
||||
if (b+a>c) { a = c-b; } // BAD
|
||||
if (c>a+b) a = c-b; // BAD
|
||||
if (c>a+b) { a = c-b; } // BAD
|
||||
if (c>b+a) a = c-b; // BAD
|
||||
if (c>b+a) { a = c-b; } // BAD
|
||||
|
||||
if (a+b>=c) a = c-b; // BAD
|
||||
if (a+b>=c) { a = c-b; } // BAD
|
||||
if (b+a>=c) a = c-b; // BAD
|
||||
if (b+a>=c) { a = c-b; } // BAD
|
||||
if (c>=a+b) a = c-b; // BAD
|
||||
if (c>=a+b) { a = c-b; } // BAD
|
||||
if (c>=b+a) a = c-b; // BAD
|
||||
if (c>=b+a) { a = c-b; } // BAD
|
||||
|
||||
if (a+b<c) a = c-b; // BAD
|
||||
if (a+b<c) { a = c-b; } // BAD
|
||||
if (b+a<c) a = c-b; // BAD
|
||||
if (b+a<c) { a = c-b; } // BAD
|
||||
if (c<a+b) a = c-b; // BAD
|
||||
if (c<a+b) { a = c-b; } // BAD
|
||||
if (c<b+a) a = c-b; // BAD
|
||||
if (c<b+a) { a = c-b; } // BAD
|
||||
|
||||
if (a+b<=c) a = c-b; // BAD
|
||||
if (a+b<=c) { a = c-b; } // BAD
|
||||
if (b+a<=c) a = c-b; // BAD
|
||||
if (b+a<=c) { a = c-b; } // BAD
|
||||
if (c<=a+b) a = c-b; // BAD
|
||||
if (c<=a+b) { a = c-b; } // BAD
|
||||
if (c<=b+a) a = c-b; // BAD
|
||||
if (c<=b+a) { a = c-b; } // BAD
|
||||
|
||||
if (a+b>d) a = d-b; // BAD
|
||||
if (a+(double)b>c) a = c-b; // GOOD
|
||||
if (a+(-x)>c) a = c-(-y); // GOOD
|
||||
if (a+b>c) { b++; a = c-b; } // GOOD
|
||||
if (a+d>c) a = c-d; // GOOD
|
||||
if (a1+b1>c1) a1 = c1-b1; // GOOD
|
||||
|
||||
if (a+b<=c) { /* ... */ } else { a = c-b; } // BAD
|
||||
if (a+b<=c) { return; } a = c-b; // BAD
|
||||
}
|
||||
@@ -663,14 +663,7 @@ edges
|
||||
| test.cpp:326:15:326:23 | ... + ... | test.cpp:342:8:342:17 | * ... |
|
||||
| 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:342:8:342:17 | * ... | test.cpp:333:5:333:21 | Store: ... = ... |
|
||||
| test.cpp:342:8:342:17 | * ... | test.cpp:341:5:341:21 | Store: ... = ... |
|
||||
| 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 | ... + ... |
|
||||
@@ -732,6 +725,29 @@ edges
|
||||
| test.cpp:368:5:368:10 | ... += ... | test.cpp:372:16:372:16 | p |
|
||||
| test.cpp:371:7:371:7 | p | test.cpp:372:15:372:16 | Load: * ... |
|
||||
| test.cpp:372:16:372:16 | p | test.cpp:372:15:372:16 | Load: * ... |
|
||||
| test.cpp:377:14:377:27 | new[] | test.cpp:378:15:378:16 | xs |
|
||||
| test.cpp:378:15:378:16 | xs | test.cpp:378:15:378:23 | ... + ... |
|
||||
| test.cpp:378:15:378:16 | xs | test.cpp:378:15:378:23 | ... + ... |
|
||||
| test.cpp:378:15:378:16 | xs | test.cpp:378:15:378:23 | ... + ... |
|
||||
| test.cpp:378:15:378:16 | xs | test.cpp:378:15:378:23 | ... + ... |
|
||||
| test.cpp:378:15:378:16 | xs | test.cpp:381:5:381:7 | end |
|
||||
| test.cpp:378:15:378:16 | xs | test.cpp:381:5:381:9 | ... ++ |
|
||||
| test.cpp:378:15:378:16 | xs | test.cpp:381:5:381:9 | ... ++ |
|
||||
| test.cpp:378:15:378:16 | xs | test.cpp:384:14:384:16 | end |
|
||||
| test.cpp:378:15:378:23 | ... + ... | test.cpp:378:15:378:23 | ... + ... |
|
||||
| test.cpp:378:15:378:23 | ... + ... | test.cpp:378:15:378:23 | ... + ... |
|
||||
| test.cpp:378:15:378:23 | ... + ... | test.cpp:381:5:381:7 | end |
|
||||
| test.cpp:378:15:378:23 | ... + ... | test.cpp:381:5:381:7 | end |
|
||||
| test.cpp:378:15:378:23 | ... + ... | test.cpp:384:13:384:16 | Load: * ... |
|
||||
| test.cpp:378:15:378:23 | ... + ... | test.cpp:384:13:384:16 | Load: * ... |
|
||||
| test.cpp:378:15:378:23 | ... + ... | test.cpp:384:13:384:16 | Load: * ... |
|
||||
| test.cpp:378:15:378:23 | ... + ... | test.cpp:384:13:384:16 | Load: * ... |
|
||||
| test.cpp:378:15:378:23 | ... + ... | test.cpp:384:14:384:16 | end |
|
||||
| test.cpp:378:15:378:23 | ... + ... | test.cpp:384:14:384:16 | end |
|
||||
| test.cpp:381:5:381:7 | end | test.cpp:384:13:384:16 | Load: * ... |
|
||||
| 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: * ... |
|
||||
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 |
|
||||
@@ -1031,17 +1047,11 @@ nodes
|
||||
| test.cpp:326:15:326:16 | xs | semmle.label | xs |
|
||||
| test.cpp:326:15:326:23 | ... + ... | semmle.label | ... + ... |
|
||||
| test.cpp:326:15:326:23 | ... + ... | semmle.label | ... + ... |
|
||||
| test.cpp:333:5:333:21 | Store: ... = ... | semmle.label | Store: ... = ... |
|
||||
| test.cpp:338:8:338:15 | * ... | semmle.label | * ... |
|
||||
| test.cpp:341:5:341:21 | Store: ... = ... | semmle.label | Store: ... = ... |
|
||||
| test.cpp:341:8:341:17 | * ... | semmle.label | * ... |
|
||||
| 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 | ... + ... |
|
||||
@@ -1066,6 +1076,17 @@ nodes
|
||||
| test.cpp:371:7:371:7 | p | semmle.label | p |
|
||||
| test.cpp:372:15:372:16 | Load: * ... | semmle.label | Load: * ... |
|
||||
| test.cpp:372:16:372:16 | p | semmle.label | p |
|
||||
| test.cpp:377:14:377:27 | new[] | semmle.label | new[] |
|
||||
| test.cpp:378:15:378:16 | xs | semmle.label | xs |
|
||||
| test.cpp:378:15:378:23 | ... + ... | semmle.label | ... + ... |
|
||||
| test.cpp:378:15:378:23 | ... + ... | semmle.label | ... + ... |
|
||||
| test.cpp:378:15:378:23 | ... + ... | semmle.label | ... + ... |
|
||||
| test.cpp:378:15:378:23 | ... + ... | semmle.label | ... + ... |
|
||||
| test.cpp:381:5:381:7 | end | semmle.label | end |
|
||||
| test.cpp:381:5:381:9 | ... ++ | semmle.label | ... ++ |
|
||||
| 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 |
|
||||
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 |
|
||||
@@ -1088,9 +1109,7 @@ 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:333:5:333:21 | Store: ... = ... | test.cpp:325:14:325:27 | new[] | test.cpp:333:5:333:21 | Store: ... = ... | This write might be out of bounds, as the pointer might be equal to $@ + $@. | test.cpp:325:14:325:27 | new[] | new[] | test.cpp:326:20:326:23 | size | size |
|
||||
| test.cpp:341:5:341:21 | Store: ... = ... | test.cpp:325:14:325:27 | new[] | test.cpp:341:5:341:21 | Store: ... = ... | This write might be out of bounds, as the pointer might be equal to $@ + $@. | test.cpp:325:14:325:27 | new[] | new[] | test.cpp:326:20:326:23 | size | size |
|
||||
| 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 |
|
||||
|
||||
@@ -330,7 +330,7 @@ void test23(unsigned size, int val) {
|
||||
if(*current - xs < 1)
|
||||
return;
|
||||
|
||||
*--(*current) = 0; // GOOD [FALSE POSITIVE]
|
||||
*--(*current) = 0; // GOOD
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -338,7 +338,7 @@ void test23(unsigned size, int val) {
|
||||
if(*current - xs < 2)
|
||||
return;
|
||||
|
||||
*--(*current) = 0; // GOOD [FALSE POSITIVE]
|
||||
*--(*current) = 0; // GOOD
|
||||
*--(*current) = 0; // GOOD
|
||||
}
|
||||
}
|
||||
@@ -347,7 +347,7 @@ void test24(unsigned size) {
|
||||
char *xs = new char[size];
|
||||
char *end = xs + size;
|
||||
if (xs < end) {
|
||||
int val = *xs++; // GOOD [FALSE POSITIVE]
|
||||
int val = *xs++; // GOOD
|
||||
}
|
||||
}
|
||||
|
||||
@@ -372,3 +372,14 @@ void test26(unsigned size) {
|
||||
int val = *p; // GOOD [FALSE POSITIVE]
|
||||
}
|
||||
}
|
||||
|
||||
void test27(unsigned size, bool b) {
|
||||
char *xs = new char[size];
|
||||
char *end = xs + size;
|
||||
|
||||
if (b) {
|
||||
end++;
|
||||
}
|
||||
|
||||
int val = *end; // BAD
|
||||
}
|
||||
|
||||
@@ -34,9 +34,6 @@ 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;
|
||||
|
||||
|
||||
@@ -6584,6 +6584,13 @@
|
||||
| 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 | |
|
||||
|
||||
@@ -693,4 +693,13 @@ 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
|
||||
}
|
||||
}
|
||||
@@ -33,7 +33,9 @@ namespace Semmle.Extraction.CSharp.Standalone
|
||||
CSharp.Extractor.Analyse(stopwatch, analyser, options,
|
||||
references => GetResolvedReferencesStandalone(referencePaths, references),
|
||||
(analyser, syntaxTrees) => CSharp.Extractor.ReadSyntaxTrees(sources, analyser, null, null, syntaxTrees),
|
||||
(syntaxTrees, references) => CSharpCompilation.Create("csharp.dll", syntaxTrees, references),
|
||||
(syntaxTrees, references) => CSharpCompilation.Create(
|
||||
"csharp.dll", syntaxTrees, references, new CSharpCompilationOptions(OutputKind.ConsoleApplication, allowUnsafe: true)
|
||||
),
|
||||
(compilation, options) => analyser.Initialize(compilation, options),
|
||||
() => { },
|
||||
_ => { },
|
||||
|
||||
@@ -211,6 +211,11 @@ namespace Semmle.Extraction.CSharp.Entities
|
||||
return Default.CreateGenerated(cx, parent, childIndex, location, ValueAsString(null));
|
||||
}
|
||||
|
||||
if (type.SpecialType is SpecialType.None)
|
||||
{
|
||||
return ImplicitCast.CreateGenerated(cx, parent, childIndex, type, defaultValue, location);
|
||||
}
|
||||
|
||||
if (type.SpecialType is SpecialType.System_DateTime)
|
||||
{
|
||||
return DateTimeObjectCreation.CreateGenerated(cx, parent, childIndex, type, defaultValue, location);
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
using System.Linq;
|
||||
using Microsoft.CodeAnalysis;
|
||||
using Semmle.Extraction.Kinds;
|
||||
|
||||
@@ -11,33 +12,73 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions
|
||||
private set;
|
||||
}
|
||||
|
||||
public ImplicitCast(ExpressionNodeInfo info)
|
||||
private ImplicitCast(ExpressionNodeInfo info)
|
||||
: base(new ExpressionInfo(info.Context, info.ConvertedType, info.Location, ExprKind.CAST, info.Parent, info.Child, true, info.ExprValue))
|
||||
{
|
||||
Expr = Factory.Create(new ExpressionNodeInfo(Context, info.Node, this, 0));
|
||||
}
|
||||
|
||||
public ImplicitCast(ExpressionNodeInfo info, IMethodSymbol method)
|
||||
private ImplicitCast(ExpressionNodeInfo info, IMethodSymbol method)
|
||||
: base(new ExpressionInfo(info.Context, info.ConvertedType, info.Location, ExprKind.OPERATOR_INVOCATION, info.Parent, info.Child, true, info.ExprValue))
|
||||
{
|
||||
Expr = Factory.Create(info.SetParent(this, 0));
|
||||
|
||||
var target = Method.Create(Context, method);
|
||||
if (target is not null)
|
||||
Context.TrapWriter.Writer.expr_call(this, target);
|
||||
else
|
||||
Context.ModelError(info.Node, "Failed to resolve target for operator invocation");
|
||||
AddOperatorCall(method);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new expression, adding casts as required.
|
||||
/// </summary>
|
||||
/// <param name="cx">The extraction context.</param>
|
||||
/// <param name="node">The expression node.</param>
|
||||
/// <param name="parent">The parent of the expression.</param>
|
||||
/// <param name="child">The child number.</param>
|
||||
/// <param name="type">A type hint.</param>
|
||||
/// <returns>A new expression.</returns>
|
||||
private ImplicitCast(ExpressionInfo info, IMethodSymbol method, object value) : base(info)
|
||||
{
|
||||
Expr = Literal.CreateGenerated(Context, this, 0, method.Parameters[0].Type, value, info.Location);
|
||||
|
||||
AddOperatorCall(method);
|
||||
}
|
||||
|
||||
private void AddOperatorCall(IMethodSymbol method)
|
||||
{
|
||||
var target = Method.Create(Context, method);
|
||||
Context.TrapWriter.Writer.expr_call(this, target);
|
||||
}
|
||||
|
||||
private static IMethodSymbol? GetImplicitConversionMethod(ITypeSymbol type, object value) =>
|
||||
type
|
||||
.GetMembers()
|
||||
.OfType<IMethodSymbol>()
|
||||
.Where(method =>
|
||||
method.GetName() == "op_Implicit" &&
|
||||
method.Parameters.Length == 1 &&
|
||||
method.Parameters[0].Type.Name == value.GetType().Name
|
||||
)
|
||||
.FirstOrDefault();
|
||||
|
||||
// Creates a new generated expression with an implicit cast added, if needed.
|
||||
public static Expression CreateGenerated(Context cx, IExpressionParentEntity parent, int childIndex, ITypeSymbol type, object value,
|
||||
Extraction.Entities.Location location)
|
||||
{
|
||||
ExpressionInfo create(ExprKind kind, string? v) =>
|
||||
new ExpressionInfo(
|
||||
cx,
|
||||
AnnotatedTypeSymbol.CreateNotAnnotated(type),
|
||||
location,
|
||||
kind,
|
||||
parent,
|
||||
childIndex,
|
||||
true,
|
||||
v);
|
||||
|
||||
var method = GetImplicitConversionMethod(type, value);
|
||||
if (method is not null)
|
||||
{
|
||||
var info = create(ExprKind.OPERATOR_INVOCATION, null);
|
||||
return new ImplicitCast(info, method, value);
|
||||
}
|
||||
else
|
||||
{
|
||||
cx.ModelError(location, "Failed to resolve target for implicit operator invocation for a parameter default.");
|
||||
return new Expression(create(ExprKind.UNKNOWN, ValueAsString(value)));
|
||||
}
|
||||
}
|
||||
|
||||
// Creates a new expression, adding casts as required.
|
||||
public static Expression Create(ExpressionNodeInfo info)
|
||||
{
|
||||
var resolvedType = info.ResolvedType;
|
||||
|
||||
@@ -243,7 +243,12 @@ namespace Semmle.Extraction.CSharp.Entities
|
||||
if (methodKind == MethodKind.ExplicitInterfaceImplementation)
|
||||
{
|
||||
// Retrieve the original method kind
|
||||
methodKind = methodDecl.ExplicitInterfaceImplementations.Select(m => m.MethodKind).FirstOrDefault();
|
||||
if (methodDecl.ExplicitInterfaceImplementations.IsEmpty)
|
||||
{
|
||||
throw new InternalError(methodDecl, "Couldn't get the original method kind for an explicit interface implementation");
|
||||
}
|
||||
|
||||
methodKind = methodDecl.ExplicitInterfaceImplementations.Select(m => m.MethodKind).First();
|
||||
}
|
||||
|
||||
switch (methodKind)
|
||||
|
||||
@@ -25,7 +25,7 @@ namespace Semmle.Extraction.CSharp
|
||||
Nullability = nullability;
|
||||
}
|
||||
|
||||
public static AnnotatedTypeSymbol? CreateNotAnnotated(ITypeSymbol symbol) =>
|
||||
public static AnnotatedTypeSymbol? CreateNotAnnotated(ITypeSymbol? symbol) =>
|
||||
symbol is null ? (AnnotatedTypeSymbol?)null : new AnnotatedTypeSymbol(symbol, NullableAnnotation.None);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,10 @@
|
||||
from create_database_utils import *
|
||||
from diagnostics_test_utils import *
|
||||
|
||||
run_codeql_database_create(['dotnet test'], db=None, lang="csharp")
|
||||
# Implicitly build and then run tests.
|
||||
run_codeql_database_create(['dotnet test'], test_db="test-db", 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")
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
namespace dotnet_test_mstest;
|
||||
|
||||
[TestClass]
|
||||
public class UnitTest1
|
||||
{
|
||||
[TestMethod]
|
||||
public void TestMethod1()
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
global using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
@@ -0,0 +1,19 @@
|
||||
<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>
|
||||
@@ -0,0 +1,14 @@
|
||||
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")
|
||||
8
csharp/ql/lib/change-notes/2023-06-02-delete-deps.md
Normal file
8
csharp/ql/lib/change-notes/2023-06-02-delete-deps.md
Normal file
@@ -0,0 +1,8 @@
|
||||
---
|
||||
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.
|
||||
4
csharp/ql/lib/change-notes/2023-06-06-dotnettest.md
Normal file
4
csharp/ql/lib/change-notes/2023-06-06-dotnettest.md
Normal file
@@ -0,0 +1,4 @@
|
||||
---
|
||||
category: minorAnalysis
|
||||
---
|
||||
* 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.
|
||||
@@ -0,0 +1,4 @@
|
||||
---
|
||||
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.
|
||||
@@ -18,9 +18,6 @@ class WebConfigReleaseTransformXml extends XmlFile {
|
||||
WebConfigReleaseTransformXml() { this.getName().matches("%Web.Release.config") }
|
||||
}
|
||||
|
||||
/** DEPRECATED: Alias for WebConfigXml */
|
||||
deprecated class WebConfigXML = WebConfigXml;
|
||||
|
||||
/** A `<configuration>` tag in an ASP.NET configuration file. */
|
||||
class ConfigurationXmlElement extends XmlElement {
|
||||
ConfigurationXmlElement() { this.getName().toLowerCase() = "configuration" }
|
||||
@@ -31,9 +28,6 @@ class CompilationXmlElement extends XmlElement {
|
||||
CompilationXmlElement() { this.getName().toLowerCase() = "compilation" }
|
||||
}
|
||||
|
||||
/** DEPRECATED: Alias for ConfigurationXmlElement */
|
||||
deprecated class ConfigurationXMLElement = ConfigurationXmlElement;
|
||||
|
||||
/** A `<location>` tag in an ASP.NET configuration file. */
|
||||
class LocationXmlElement extends XmlElement {
|
||||
LocationXmlElement() {
|
||||
@@ -42,9 +36,6 @@ class LocationXmlElement extends XmlElement {
|
||||
}
|
||||
}
|
||||
|
||||
/** DEPRECATED: Alias for LocationXmlElement */
|
||||
deprecated class LocationXMLElement = LocationXmlElement;
|
||||
|
||||
/** A `<system.web>` tag in an ASP.NET configuration file. */
|
||||
class SystemWebXmlElement extends XmlElement {
|
||||
SystemWebXmlElement() {
|
||||
@@ -57,9 +48,6 @@ class SystemWebXmlElement extends XmlElement {
|
||||
}
|
||||
}
|
||||
|
||||
/** DEPRECATED: Alias for SystemWebXmlElement */
|
||||
deprecated class SystemWebXMLElement = SystemWebXmlElement;
|
||||
|
||||
/** A `<system.webServer>` tag in an ASP.NET configuration file. */
|
||||
class SystemWebServerXmlElement extends XmlElement {
|
||||
SystemWebServerXmlElement() {
|
||||
@@ -72,9 +60,6 @@ class SystemWebServerXmlElement extends XmlElement {
|
||||
}
|
||||
}
|
||||
|
||||
/** DEPRECATED: Alias for SystemWebServerXmlElement */
|
||||
deprecated class SystemWebServerXMLElement = SystemWebServerXmlElement;
|
||||
|
||||
/** A `<customErrors>` tag in an ASP.NET configuration file. */
|
||||
class CustomErrorsXmlElement extends XmlElement {
|
||||
CustomErrorsXmlElement() {
|
||||
@@ -83,9 +68,6 @@ class CustomErrorsXmlElement extends XmlElement {
|
||||
}
|
||||
}
|
||||
|
||||
/** DEPRECATED: Alias for CustomErrorsXmlElement */
|
||||
deprecated class CustomErrorsXMLElement = CustomErrorsXmlElement;
|
||||
|
||||
/** A `<httpRuntime>` tag in an ASP.NET configuration file. */
|
||||
class HttpRuntimeXmlElement extends XmlElement {
|
||||
HttpRuntimeXmlElement() {
|
||||
@@ -94,9 +76,6 @@ class HttpRuntimeXmlElement extends XmlElement {
|
||||
}
|
||||
}
|
||||
|
||||
/** DEPRECATED: Alias for HttpRuntimeXmlElement */
|
||||
deprecated class HttpRuntimeXMLElement = HttpRuntimeXmlElement;
|
||||
|
||||
/** A `<forms>` tag under `<system.web><authentication>` in an ASP.NET configuration file. */
|
||||
class FormsElement extends XmlElement {
|
||||
FormsElement() {
|
||||
|
||||
@@ -60,11 +60,6 @@ class Class extends ValueOrRefType {
|
||||
Class() { this.isClass() }
|
||||
}
|
||||
|
||||
/** A `record`. */
|
||||
deprecated class Record extends Class {
|
||||
Record() { this.isRecord() }
|
||||
}
|
||||
|
||||
/** An `interface`. */
|
||||
class Interface extends ValueOrRefType {
|
||||
Interface() { this.isInterface() }
|
||||
|
||||
@@ -780,16 +780,6 @@ class Class extends RefType, @class_type {
|
||||
override string getAPrimaryQlClass() { result = "Class" }
|
||||
}
|
||||
|
||||
/**
|
||||
* DEPRECATED: Use `RecordClass` instead.
|
||||
*/
|
||||
deprecated class Record extends Class {
|
||||
Record() { this.isRecord() }
|
||||
|
||||
/** Gets the clone method of this record. */
|
||||
RecordCloneMethod getCloneMethod() { result = this.getAMember() }
|
||||
}
|
||||
|
||||
/**
|
||||
* A `record`, for example
|
||||
*
|
||||
|
||||
@@ -200,45 +200,3 @@ predicate sameGvn(ControlFlowElement x, ControlFlowElement y) {
|
||||
pragma[only_bind_into](toGvn(pragma[only_bind_out](x))) =
|
||||
pragma[only_bind_into](toGvn(pragma[only_bind_out](y)))
|
||||
}
|
||||
|
||||
/**
|
||||
* DEPRECATED: Use `sameGvn` instead.
|
||||
*
|
||||
* A configuration for performing structural comparisons of program elements
|
||||
* (expressions and statements).
|
||||
*
|
||||
* The predicate `candidate()` must be overridden, in order to identify the
|
||||
* elements for which to perform structural comparison.
|
||||
*
|
||||
* Each use of the library is identified by a unique string value.
|
||||
*/
|
||||
abstract deprecated class StructuralComparisonConfiguration extends string {
|
||||
bindingset[this]
|
||||
StructuralComparisonConfiguration() { any() }
|
||||
|
||||
/**
|
||||
* Holds if elements `x` and `y` are candidates for testing structural
|
||||
* equality.
|
||||
*
|
||||
* Subclasses are expected to override this predicate to identify the
|
||||
* top-level elements which they want to compare. Care should be
|
||||
* taken to avoid identifying too many pairs of elements, as in general
|
||||
* there are very many structurally equal subtrees in a program, and
|
||||
* in order to keep the computation feasible we must focus attention.
|
||||
*
|
||||
* Note that this relation is not expected to be symmetric -- it's
|
||||
* fine to include a pair `(x, y)` but not `(y, x)`.
|
||||
* In fact, not including the symmetrically implied fact will save
|
||||
* half the computation time on the structural comparison.
|
||||
*/
|
||||
abstract predicate candidate(ControlFlowElement x, ControlFlowElement y);
|
||||
|
||||
/**
|
||||
* Holds if elements `x` and `y` structurally equal. `x` and `y` must be
|
||||
* flagged as candidates for structural equality, that is,
|
||||
* `candidate(x, y)` must hold.
|
||||
*/
|
||||
predicate same(ControlFlowElement x, ControlFlowElement y) {
|
||||
this.candidate(x, y) and sameGvn(x, y)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1135,8 +1135,8 @@ module Impl<FullStateConfigSig Config> {
|
||||
DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow
|
||||
);
|
||||
|
||||
bindingset[node, state, t, ap]
|
||||
predicate filter(NodeEx node, FlowState state, Typ t, Ap ap);
|
||||
bindingset[node, state, t0, ap]
|
||||
predicate filter(NodeEx node, FlowState state, Typ t0, Ap ap, Typ t);
|
||||
|
||||
bindingset[typ, contentType]
|
||||
predicate typecheckStore(Typ typ, DataFlowType contentType);
|
||||
@@ -1199,17 +1199,21 @@ module Impl<FullStateConfigSig Config> {
|
||||
NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, TypOption argT,
|
||||
ApOption argAp, Typ t, Ap ap, ApApprox apa
|
||||
) {
|
||||
fwdFlow0(node, state, cc, summaryCtx, argT, argAp, t, ap, apa) and
|
||||
PrevStage::revFlow(node, state, apa) and
|
||||
filter(node, state, t, ap)
|
||||
fwdFlow1(node, state, cc, summaryCtx, argT, argAp, _, t, ap, apa)
|
||||
}
|
||||
|
||||
pragma[inline]
|
||||
additional predicate fwdFlow(
|
||||
private predicate fwdFlow1(
|
||||
NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, TypOption argT,
|
||||
ApOption argAp, Typ t, Ap ap
|
||||
ApOption argAp, Typ t0, Typ t, Ap ap, ApApprox apa
|
||||
) {
|
||||
fwdFlow(node, state, cc, summaryCtx, argT, argAp, t, ap, _)
|
||||
fwdFlow0(node, state, cc, summaryCtx, argT, argAp, t0, ap, apa) and
|
||||
PrevStage::revFlow(node, state, apa) and
|
||||
filter(node, state, t0, ap, t)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate typeStrengthen(Typ t0, Ap ap, Typ t) {
|
||||
fwdFlow1(_, _, _, _, _, _, t0, t, ap, _) and t0 != t
|
||||
}
|
||||
|
||||
pragma[assume_small_delta]
|
||||
@@ -1339,6 +1343,11 @@ 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]
|
||||
@@ -1359,7 +1368,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)
|
||||
)
|
||||
@@ -1520,14 +1529,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()
|
||||
@@ -1780,13 +1789,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
|
||||
@@ -1963,10 +1972,10 @@ module Impl<FullStateConfigSig Config> {
|
||||
)
|
||||
}
|
||||
|
||||
bindingset[node, state, t, ap]
|
||||
predicate filter(NodeEx node, FlowState state, Typ t, Ap ap) {
|
||||
bindingset[node, state, t0, ap]
|
||||
predicate filter(NodeEx node, FlowState state, Typ t0, Ap ap, Typ t) {
|
||||
PrevStage::revFlowState(state) and
|
||||
exists(t) and
|
||||
t0 = t and
|
||||
exists(ap) and
|
||||
not stateBarrier(node, state) and
|
||||
(
|
||||
@@ -2197,8 +2206,8 @@ module Impl<FullStateConfigSig Config> {
|
||||
import BooleanCallContext
|
||||
|
||||
predicate localStep(
|
||||
NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue,
|
||||
DataFlowType t, LocalCc lcc
|
||||
NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, Typ t,
|
||||
LocalCc lcc
|
||||
) {
|
||||
localFlowBigStep(node1, state1, node2, state2, preservesValue, t, _) and
|
||||
exists(lcc)
|
||||
@@ -2218,10 +2227,16 @@ module Impl<FullStateConfigSig Config> {
|
||||
)
|
||||
}
|
||||
|
||||
bindingset[node, state, t, ap]
|
||||
predicate filter(NodeEx node, FlowState state, Typ t, Ap ap) {
|
||||
bindingset[node, state, t0, ap]
|
||||
predicate filter(NodeEx node, FlowState state, Typ t0, Ap ap, Typ t) {
|
||||
exists(state) and
|
||||
(if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), t) else any()) 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
|
||||
(
|
||||
notExpectsContent(node)
|
||||
or
|
||||
@@ -2241,6 +2256,16 @@ 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;
|
||||
|
||||
@@ -2274,8 +2299,8 @@ module Impl<FullStateConfigSig Config> {
|
||||
|
||||
pragma[nomagic]
|
||||
predicate localStep(
|
||||
NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue,
|
||||
DataFlowType t, LocalCc lcc
|
||||
NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, Typ t,
|
||||
LocalCc lcc
|
||||
) {
|
||||
localFlowBigStep(node1, state1, node2, state2, preservesValue, t, _) and
|
||||
PrevStage::revFlow(node1, pragma[only_bind_into](state1), _) and
|
||||
@@ -2333,11 +2358,11 @@ module Impl<FullStateConfigSig Config> {
|
||||
)
|
||||
}
|
||||
|
||||
bindingset[node, state, t, ap]
|
||||
predicate filter(NodeEx node, FlowState state, Typ t, Ap ap) {
|
||||
bindingset[node, state, t0, ap]
|
||||
predicate filter(NodeEx node, FlowState state, Typ t0, Ap ap, Typ t) {
|
||||
exists(state) and
|
||||
not clear(node, ap) and
|
||||
(if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), t) else any()) and
|
||||
strengthenType(node, t0, t) and
|
||||
(
|
||||
notExpectsContent(node)
|
||||
or
|
||||
@@ -2365,7 +2390,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, _)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -2579,8 +2604,8 @@ module Impl<FullStateConfigSig Config> {
|
||||
import LocalCallContext
|
||||
|
||||
predicate localStep(
|
||||
NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue,
|
||||
DataFlowType t, LocalCc lcc
|
||||
NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, Typ t,
|
||||
LocalCc lcc
|
||||
) {
|
||||
localFlowBigStep(node1, state1, node2, state2, preservesValue, t, lcc) and
|
||||
PrevStage::revFlow(node1, pragma[only_bind_into](state1), _) and
|
||||
@@ -2609,9 +2634,9 @@ module Impl<FullStateConfigSig Config> {
|
||||
)
|
||||
}
|
||||
|
||||
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
|
||||
bindingset[node, state, t0, ap]
|
||||
predicate filter(NodeEx node, FlowState state, Typ t0, Ap ap, Typ t) {
|
||||
strengthenType(node, t0, t) and
|
||||
exists(state) and
|
||||
exists(ap)
|
||||
}
|
||||
@@ -2632,7 +2657,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, _)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -2649,7 +2674,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, _, _, _, _, t, apa) and
|
||||
Stage5::fwdFlow(p, state, _, _, Option<DataFlowType>::some(t), _, _, apa, _) and
|
||||
Stage5::revFlow(p, state, _)
|
||||
)
|
||||
}
|
||||
@@ -2820,9 +2845,7 @@ module Impl<FullStateConfigSig Config> {
|
||||
ap = TAccessPathNil()
|
||||
or
|
||||
// ... or a step from an existing PathNode to another node.
|
||||
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())
|
||||
pathStep(_, node, state, cc, sc, t, ap)
|
||||
} or
|
||||
TPathNodeSink(NodeEx node, FlowState state) {
|
||||
exists(PathNodeMid sink |
|
||||
@@ -3340,13 +3363,24 @@ 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 pathStep(
|
||||
private predicate pathStep0(
|
||||
PathNodeMid mid, NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, DataFlowType t,
|
||||
AccessPath ap
|
||||
) {
|
||||
@@ -3964,7 +3998,7 @@ module Impl<FullStateConfigSig Config> {
|
||||
ap = TPartialNil() and
|
||||
exists(explorationLimit())
|
||||
or
|
||||
partialPathNodeMk0(node, state, cc, sc1, sc2, sc3, sc4, t, ap) and
|
||||
partialPathStep(_, node, state, cc, sc1, sc2, sc3, sc4, t, ap) and
|
||||
distSrc(node.getEnclosingCallable()) <= explorationLimit()
|
||||
} or
|
||||
TPartialPathNodeRev(
|
||||
@@ -3990,11 +4024,20 @@ module Impl<FullStateConfigSig Config> {
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate partialPathNodeMk0(
|
||||
NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2,
|
||||
TSummaryCtx3 sc3, TSummaryCtx4 sc4, DataFlowType t, PartialAccessPath ap
|
||||
private predicate partialPathStep(
|
||||
PartialPathNodeFwd mid, NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1,
|
||||
TSummaryCtx2 sc2, TSummaryCtx3 sc3, TSummaryCtx4 sc4, DataFlowType t, PartialAccessPath ap
|
||||
) {
|
||||
partialPathStep(_, node, state, cc, sc1, sc2, sc3, sc4, t, ap) and
|
||||
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
|
||||
not fullBarrier(node) and
|
||||
not stateBarrier(node, state) and
|
||||
not clearsContentEx(node, ap.getHead()) and
|
||||
@@ -4002,9 +4045,14 @@ module Impl<FullStateConfigSig Config> {
|
||||
notExpectsContent(node) or
|
||||
expectsContentEx(node, ap.getHead())
|
||||
) and
|
||||
if node.asNode() instanceof CastingNode
|
||||
then compatibleTypes(node.getDataFlowType(), t)
|
||||
else any()
|
||||
strengthenType(node, t0, t)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate partialPathTypeStrengthen(
|
||||
DataFlowType t0, PartialAccessPath ap, DataFlowType t
|
||||
) {
|
||||
partialPathStep1(_, _, _, _, _, _, _, _, t0, t, ap) and t0 != t
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -4183,7 +4231,8 @@ module Impl<FullStateConfigSig Config> {
|
||||
}
|
||||
}
|
||||
|
||||
private predicate partialPathStep(
|
||||
pragma[nomagic]
|
||||
private predicate partialPathStep0(
|
||||
PartialPathNodeFwd mid, NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1,
|
||||
TSummaryCtx2 sc2, TSummaryCtx3 sc3, TSummaryCtx4 sc4, DataFlowType t, PartialAccessPath ap
|
||||
) {
|
||||
@@ -4309,6 +4358,11 @@ 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]
|
||||
|
||||
@@ -1984,6 +1984,21 @@ 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`.
|
||||
|
||||
@@ -106,16 +106,6 @@ class ParameterNode extends Node instanceof ParameterNodeImpl {
|
||||
result = c.asCallable().getParameter(ppos.getPosition())
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* DEPRECATED
|
||||
*
|
||||
* Holds if this node is the parameter of callable `c` at the specified
|
||||
* (zero-based) position.
|
||||
*/
|
||||
deprecated predicate isParameterOf(DataFlowCallable c, int i) {
|
||||
super.isParameterOf(c, any(ParameterPosition pos | i = pos.getPosition()))
|
||||
}
|
||||
}
|
||||
|
||||
/** A definition, viewed as a node in a data flow graph. */
|
||||
|
||||
@@ -14,9 +14,6 @@ private import semmle.code.csharp.dataflow.FlowSummary
|
||||
*/
|
||||
abstract class SafeExternalApiCallable extends Callable { }
|
||||
|
||||
/** DEPRECATED: Alias for SafeExternalApiCallable */
|
||||
deprecated class SafeExternalAPICallable = SafeExternalApiCallable;
|
||||
|
||||
private class SummarizedCallableSafe extends SafeExternalApiCallable instanceof SummarizedCallable {
|
||||
}
|
||||
|
||||
@@ -87,9 +84,6 @@ class ExternalApiDataNode extends DataFlow::Node {
|
||||
}
|
||||
}
|
||||
|
||||
/** DEPRECATED: Alias for ExternalApiDataNode */
|
||||
deprecated class ExternalAPIDataNode = ExternalApiDataNode;
|
||||
|
||||
/**
|
||||
* DEPRECATED: Use `RemoteSourceToExternalApi` instead.
|
||||
*
|
||||
@@ -113,9 +107,6 @@ private module RemoteSourceToExternalApiConfig implements DataFlow::ConfigSig {
|
||||
/** A module for tracking flow from `RemoteFlowSource`s to `ExternalApiDataNode`s. */
|
||||
module RemoteSourceToExternalApi = TaintTracking::Global<RemoteSourceToExternalApiConfig>;
|
||||
|
||||
/** DEPRECATED: Alias for UntrustedDataToExternalApiConfig */
|
||||
deprecated class UntrustedDataToExternalAPIConfig = UntrustedDataToExternalApiConfig;
|
||||
|
||||
/** A node representing untrusted data being passed to an external API. */
|
||||
class UntrustedExternalApiDataNode extends ExternalApiDataNode {
|
||||
UntrustedExternalApiDataNode() { RemoteSourceToExternalApi::flow(_, this) }
|
||||
@@ -124,9 +115,6 @@ class UntrustedExternalApiDataNode extends ExternalApiDataNode {
|
||||
DataFlow::Node getAnUntrustedSource() { RemoteSourceToExternalApi::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`. */
|
||||
@@ -161,6 +149,3 @@ class ExternalApiUsedWithUntrustedData extends TExternalApi {
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/** DEPRECATED: Alias for ExternalApiUsedWithUntrustedData */
|
||||
deprecated class ExternalAPIUsedWithUntrustedData = ExternalApiUsedWithUntrustedData;
|
||||
|
||||
@@ -149,9 +149,6 @@ class LdapEncodeSanitizer extends Sanitizer {
|
||||
}
|
||||
}
|
||||
|
||||
/** DEPRECATED: Alias for LdapEncodeSanitizer */
|
||||
deprecated class LDAPEncodeSanitizer = LdapEncodeSanitizer;
|
||||
|
||||
private class SimpleTypeSanitizer extends Sanitizer, SimpleTypeSanitizedExpr { }
|
||||
|
||||
private class GuidSanitizer extends Sanitizer, GuidSanitizedExpr { }
|
||||
|
||||
@@ -78,4 +78,4 @@ where
|
||||
exposesByStore(c, f, why, whyText)
|
||||
select c,
|
||||
"'" + c.getName() + "' exposes the internal representation stored in field '" + f.getName() +
|
||||
"'. The value may be modified $@.", why.getLocation(), whyText
|
||||
"'. The value may be modified $@.", why, whyText
|
||||
|
||||
@@ -26,4 +26,4 @@ where
|
||||
operators =
|
||||
count(BinaryLogicalOperation op | logicalParent*(op, e) and nontrivialLogicalOperator(op)) and
|
||||
operators > 3
|
||||
select e.getLocation(), "Complex condition: too many logical operations in this expression."
|
||||
select e, "Complex condition: too many logical operations in this expression."
|
||||
|
||||
@@ -73,9 +73,6 @@ module UnaliasedSsaInstructions {
|
||||
}
|
||||
}
|
||||
|
||||
/** DEPRECATED: Alias for UnaliasedSsaInstructions */
|
||||
deprecated module UnaliasedSSAInstructions = UnaliasedSsaInstructions;
|
||||
|
||||
/**
|
||||
* Provides wrappers for the constructors of each branch of `TInstruction` that is used by the
|
||||
* aliased SSA stage.
|
||||
@@ -107,6 +104,3 @@ module AliasedSsaInstructions {
|
||||
result = TAliasedSsaUnreachedInstruction(irFunc)
|
||||
}
|
||||
}
|
||||
|
||||
/** DEPRECATED: Alias for AliasedSsaInstructions */
|
||||
deprecated module AliasedSSAInstructions = AliasedSsaInstructions;
|
||||
|
||||
@@ -59,20 +59,12 @@ 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)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -156,6 +148,3 @@ module UnaliasedSsaOperands {
|
||||
*/
|
||||
TChiOperand chiOperand(Unaliased::Instruction useInstr, ChiOperandTag tag) { none() }
|
||||
}
|
||||
|
||||
/** DEPRECATED: Alias for UnaliasedSsaOperands */
|
||||
deprecated module UnaliasedSSAOperands = UnaliasedSsaOperands;
|
||||
|
||||
@@ -210,9 +210,6 @@ class Instruction extends Construction::TStageInstruction {
|
||||
*/
|
||||
final Language::AST getAst() { result = Construction::getInstructionAst(this) }
|
||||
|
||||
/** DEPRECATED: Alias for getAst */
|
||||
deprecated Language::AST getAST() { result = this.getAst() }
|
||||
|
||||
/**
|
||||
* Gets the location of the source code for this instruction.
|
||||
*/
|
||||
@@ -463,9 +460,6 @@ class VariableInstruction extends Instruction {
|
||||
* Gets the AST variable that this instruction's IR variable refers to, if one exists.
|
||||
*/
|
||||
final Language::Variable getAstVariable() { result = var.(IRUserVariable).getVariable() }
|
||||
|
||||
/** DEPRECATED: Alias for getAstVariable */
|
||||
deprecated Language::Variable getASTVariable() { result = this.getAstVariable() }
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -378,12 +378,6 @@ private module Cached {
|
||||
result = getInstructionTranslatedElement(instruction).getAst()
|
||||
}
|
||||
|
||||
/** DEPRECATED: Alias for getInstructionAst */
|
||||
cached
|
||||
deprecated Language::AST getInstructionAST(Instruction instruction) {
|
||||
result = getInstructionAst(instruction)
|
||||
}
|
||||
|
||||
cached
|
||||
CSharpType getInstructionResultType(Instruction instruction) {
|
||||
getInstructionTranslatedElement(instruction)
|
||||
|
||||
@@ -17,9 +17,6 @@ abstract class TranslatedCondition extends ConditionBase {
|
||||
|
||||
final override Language::AST getAst() { result = expr }
|
||||
|
||||
/** DEPRECATED: Alias for getAst */
|
||||
deprecated override Language::AST getAST() { result = this.getAst() }
|
||||
|
||||
final Expr getExpr() { result = expr }
|
||||
|
||||
final override Callable getFunction() { result = expr.getEnclosingCallable() }
|
||||
|
||||
@@ -30,9 +30,6 @@ abstract class TranslatedLocalDeclaration extends TranslatedElement, TTranslated
|
||||
final override string toString() { result = expr.toString() }
|
||||
|
||||
final override Language::AST getAst() { result = expr }
|
||||
|
||||
/** DEPRECATED: Alias for getAst */
|
||||
deprecated override Language::AST getAST() { result = this.getAst() }
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -366,9 +366,6 @@ abstract class TranslatedElement extends TTranslatedElement {
|
||||
*/
|
||||
abstract Language::AST getAst();
|
||||
|
||||
/** DEPRECATED: Alias for getAst */
|
||||
deprecated Language::AST getAST() { result = this.getAst() }
|
||||
|
||||
/**
|
||||
* Get the first instruction to be executed in the evaluation of this element.
|
||||
*/
|
||||
|
||||
@@ -63,9 +63,6 @@ abstract class TranslatedExpr extends TranslatedExprBase {
|
||||
|
||||
final override Language::AST getAst() { result = expr }
|
||||
|
||||
/** DEPRECATED: Alias for getAst */
|
||||
deprecated override Language::AST getAST() { result = this.getAst() }
|
||||
|
||||
final override Callable getFunction() { result = expr.getEnclosingCallable() }
|
||||
|
||||
/**
|
||||
|
||||
@@ -30,9 +30,6 @@ class TranslatedFunction extends TranslatedElement, TTranslatedFunction {
|
||||
|
||||
final override Language::AST getAst() { result = callable }
|
||||
|
||||
/** DEPRECATED: Alias for getAst */
|
||||
deprecated override Language::AST getAST() { result = this.getAst() }
|
||||
|
||||
/**
|
||||
* Gets the function being translated.
|
||||
*/
|
||||
@@ -287,9 +284,6 @@ class TranslatedParameter extends TranslatedElement, TTranslatedParameter {
|
||||
|
||||
final override Language::AST getAst() { result = param }
|
||||
|
||||
/** DEPRECATED: Alias for getAst */
|
||||
deprecated override Language::AST getAST() { result = this.getAst() }
|
||||
|
||||
final override Callable getFunction() { result = param.getCallable() }
|
||||
|
||||
final override Instruction getFirstInstruction() {
|
||||
|
||||
@@ -52,9 +52,6 @@ abstract class TranslatedInitialization extends TranslatedElement, TTranslatedIn
|
||||
|
||||
final override Language::AST getAst() { result = expr }
|
||||
|
||||
/** DEPRECATED: Alias for getAst */
|
||||
deprecated override Language::AST getAST() { result = this.getAst() }
|
||||
|
||||
/**
|
||||
* Gets the expression that is doing the initialization.
|
||||
*/
|
||||
@@ -210,9 +207,6 @@ abstract class TranslatedElementInitialization extends TranslatedElement {
|
||||
|
||||
final override Language::AST getAst() { result = initList }
|
||||
|
||||
/** DEPRECATED: Alias for getAst */
|
||||
deprecated override Language::AST getAST() { result = this.getAst() }
|
||||
|
||||
final override Callable getFunction() { result = initList.getEnclosingCallable() }
|
||||
|
||||
final override Instruction getFirstInstruction() {
|
||||
@@ -319,9 +313,6 @@ abstract class TranslatedConstructorCallFromConstructor extends TranslatedElemen
|
||||
|
||||
final override Language::AST getAst() { result = call }
|
||||
|
||||
/** DEPRECATED: Alias for getAst */
|
||||
deprecated override Language::AST getAST() { result = this.getAst() }
|
||||
|
||||
final override TranslatedElement getChild(int id) {
|
||||
id = 0 and result = this.getConstructorCall()
|
||||
}
|
||||
|
||||
@@ -26,9 +26,6 @@ abstract class TranslatedStmt extends TranslatedElement, TTranslatedStmt {
|
||||
|
||||
final override Language::AST getAst() { result = stmt }
|
||||
|
||||
/** DEPRECATED: Alias for getAst */
|
||||
deprecated override Language::AST getAST() { result = this.getAst() }
|
||||
|
||||
final override Callable getFunction() { result = stmt.getEnclosingCallable() }
|
||||
}
|
||||
|
||||
|
||||
@@ -20,7 +20,4 @@ abstract class TranslatedCompilerGeneratedElement extends TranslatedElement,
|
||||
final override Callable getFunction() { result = generatedBy.getEnclosingCallable() }
|
||||
|
||||
final override Language::AST getAst() { result = generatedBy }
|
||||
|
||||
/** DEPRECATED: Alias for getAst */
|
||||
deprecated override Language::AST getAST() { result = this.getAst() }
|
||||
}
|
||||
|
||||
@@ -210,9 +210,6 @@ class Instruction extends Construction::TStageInstruction {
|
||||
*/
|
||||
final Language::AST getAst() { result = Construction::getInstructionAst(this) }
|
||||
|
||||
/** DEPRECATED: Alias for getAst */
|
||||
deprecated Language::AST getAST() { result = this.getAst() }
|
||||
|
||||
/**
|
||||
* Gets the location of the source code for this instruction.
|
||||
*/
|
||||
@@ -463,9 +460,6 @@ class VariableInstruction extends Instruction {
|
||||
* Gets the AST variable that this instruction's IR variable refers to, if one exists.
|
||||
*/
|
||||
final Language::Variable getAstVariable() { result = var.(IRUserVariable).getVariable() }
|
||||
|
||||
/** DEPRECATED: Alias for getAstVariable */
|
||||
deprecated Language::Variable getASTVariable() { result = this.getAstVariable() }
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -422,12 +422,6 @@ private module Cached {
|
||||
)
|
||||
}
|
||||
|
||||
/** DEPRECATED: Alias for getInstructionAst */
|
||||
cached
|
||||
deprecated Language::AST getInstructionAST(Instruction instr) {
|
||||
result = getInstructionAst(instr)
|
||||
}
|
||||
|
||||
cached
|
||||
Language::LanguageType getInstructionResultType(Instruction instr) {
|
||||
result = instr.(RawIR::Instruction).getResultLanguageType()
|
||||
@@ -993,9 +987,6 @@ predicate canReuseSsaForMemoryResult(Instruction instruction) {
|
||||
// We don't support reusing SSA for any location that could create a `Chi` instruction.
|
||||
}
|
||||
|
||||
/** DEPRECATED: Alias for canReuseSsaForMemoryResult */
|
||||
deprecated predicate canReuseSSAForMemoryResult = canReuseSsaForMemoryResult/1;
|
||||
|
||||
/**
|
||||
* Expose some of the internal predicates to PrintSSA.qll. We do this by publicly importing those modules in the
|
||||
* `DebugSsa` module, which is then imported by PrintSSA.
|
||||
@@ -1005,9 +996,6 @@ module DebugSsa {
|
||||
import DefUse
|
||||
}
|
||||
|
||||
/** DEPRECATED: Alias for DebugSsa */
|
||||
deprecated module DebugSSA = DebugSsa;
|
||||
|
||||
import CachedForDebugging
|
||||
|
||||
cached
|
||||
|
||||
@@ -46,9 +46,6 @@ predicate canReuseSsaForVariable(IRAutomaticVariable var) {
|
||||
not allocationEscapes(var)
|
||||
}
|
||||
|
||||
/** DEPRECATED: Alias for canReuseSsaForVariable */
|
||||
deprecated predicate canReuseSSAForVariable = canReuseSsaForVariable/1;
|
||||
|
||||
private newtype TMemoryLocation = MkMemoryLocation(Allocation var) { isVariableModeled(var) }
|
||||
|
||||
private MemoryLocation getMemoryLocation(Allocation var) { result.getAllocation() = var }
|
||||
@@ -80,9 +77,6 @@ class MemoryLocation extends TMemoryLocation {
|
||||
|
||||
predicate canReuseSsaForOldResult(Instruction instr) { none() }
|
||||
|
||||
/** DEPRECATED: Alias for canReuseSsaForOldResult */
|
||||
deprecated predicate canReuseSSAForOldResult = canReuseSsaForOldResult/1;
|
||||
|
||||
/**
|
||||
* Represents a set of `MemoryLocation`s that cannot overlap with
|
||||
* `MemoryLocation`s outside of the set. The `VirtualVariable` will be
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
*
|
||||
* ```
|
||||
*
|
||||
* To declare expecations, you can use the $hasTaintFlow or $hasValueFlow comments within the test source files.
|
||||
* To declare expectations, you can use the $hasTaintFlow or $hasValueFlow comments within the test source files.
|
||||
* Example of the corresponding test file, e.g. Test.cs
|
||||
* ```csharp
|
||||
* public class Test
|
||||
|
||||
@@ -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>> : 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: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: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>> : 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: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: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>> : Object [property Value] : A | semmle.label | call to method First<KeyValuePair<Int32,T>> : Object [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: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>> : Object [property Key] : A | semmle.label | call to method First<KeyValuePair<T,Int32>> : Object [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: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 |
|
||||
|
||||
@@ -149,9 +149,9 @@ namespace My.Qltest
|
||||
|
||||
static T Apply<S, T>(Func<S, T> f, S s) => throw null;
|
||||
|
||||
static S[] Map<S, T>(S[] elements, Func<S, T> f) => throw null;
|
||||
static T[] Map<S, T>(S[] elements, Func<S, T> f) => throw null;
|
||||
|
||||
static void Apply2<S>(Action<S> f, S s1, S s2) => throw null;
|
||||
static void Apply2(Action<object> f, D d1, D d2) => throw null;
|
||||
|
||||
static void Parse(string s, out int i) => throw null;
|
||||
|
||||
@@ -235,4 +235,4 @@ namespace My.Qltest
|
||||
|
||||
static void Sink(object o) { }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 | (...) ... : Object [field Field] : Object | ExternalFlow.cs:36:18:36:69 | access to field Field |
|
||||
| ExternalFlow.cs:36:19:36:62 | (...) ... : D [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 | (...) ... : 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: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,8 +38,7 @@ 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 : Object |
|
||||
| ExternalFlow.cs:78:18:78:24 | access to array element : Object | ExternalFlow.cs:78:18:78:24 | (...) ... |
|
||||
| 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: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 |
|
||||
@@ -91,7 +90,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 | (...) ... : Object [field Field] : Object | semmle.label | (...) ... : Object [field Field] : Object |
|
||||
| ExternalFlow.cs:36:19:36:62 | (...) ... : D [field Field] : Object | semmle.label | (...) ... : D [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 |
|
||||
@@ -124,8 +123,7 @@ 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 | (...) ... | semmle.label | (...) ... |
|
||||
| ExternalFlow.cs:78:18:78:24 | access to array element : Object | semmle.label | access to array element : Object |
|
||||
| ExternalFlow.cs:78:18:78:24 | access to array element | semmle.label | access to array element |
|
||||
| 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 |
|
||||
@@ -184,7 +182,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 | (...) ... | 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: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: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 |
|
||||
|
||||
@@ -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<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, "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, "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"]
|
||||
|
||||
@@ -267,7 +267,7 @@ edges
|
||||
| GlobalDataFlow.cs:500:9:500:10 | [post] access to parameter sc : SimpleClass [field field] : String | GlobalDataFlow.cs:514:31:514:32 | [post] access to local variable y1 : SimpleClass [field field] : String |
|
||||
| GlobalDataFlow.cs:500:9:500:10 | [post] access to parameter sc : SimpleClass [field field] : String | GlobalDataFlow.cs:514:36:514:37 | [post] access to local variable y2 : SimpleClass [field field] : String |
|
||||
| GlobalDataFlow.cs:500:9:500:10 | [post] access to parameter sc : SimpleClass [field field] : String | GlobalDataFlow.cs:514:42:514:43 | [post] access to local variable y3 : SimpleClass [field field] : String |
|
||||
| GlobalDataFlow.cs:500:9:500:10 | [post] access to parameter sc : SimpleClass [field field] : String | GlobalDataFlow.cs:525:33:525:33 | [post] access to local variable x : SimpleClass [field field] : String |
|
||||
| GlobalDataFlow.cs:500:9:500:10 | [post] access to parameter sc : SimpleClass [field field] : String | GlobalDataFlow.cs:525:33:525:33 | [post] access to local variable x : SubSimpleClass [field field] : String |
|
||||
| GlobalDataFlow.cs:500:9:500:10 | [post] access to parameter sc : SimpleClass [field field] : String | GlobalDataFlow.cs:532:20:532:20 | [post] access to parameter x : SimpleClass [field field] : String |
|
||||
| GlobalDataFlow.cs:500:9:500:10 | [post] access to parameter sc : SimpleClass [field field] : String | GlobalDataFlow.cs:532:25:532:25 | [post] access to local variable y : SimpleClass [field field] : String |
|
||||
| GlobalDataFlow.cs:500:9:500:10 | [post] access to parameter sc : SimpleClass [field field] : String | GlobalDataFlow.cs:544:20:544:20 | [post] access to local variable x : SimpleClass [field field] : String |
|
||||
@@ -286,8 +286,8 @@ edges
|
||||
| GlobalDataFlow.cs:515:15:515:16 | access to local variable y1 : SimpleClass [field field] : String | GlobalDataFlow.cs:515:15:515:22 | access to field field |
|
||||
| GlobalDataFlow.cs:516:15:516:16 | access to local variable y2 : SimpleClass [field field] : String | GlobalDataFlow.cs:516:15:516:22 | access to field field |
|
||||
| GlobalDataFlow.cs:517:15:517:16 | access to local variable y3 : SimpleClass [field field] : String | GlobalDataFlow.cs:517:15:517:22 | access to field field |
|
||||
| GlobalDataFlow.cs:525:33:525:33 | [post] access to local variable x : SimpleClass [field field] : String | GlobalDataFlow.cs:526:15:526:15 | access to local variable x : SimpleClass [field field] : String |
|
||||
| GlobalDataFlow.cs:526:15:526:15 | access to local variable x : SimpleClass [field field] : String | GlobalDataFlow.cs:526:15:526:21 | access to field field |
|
||||
| GlobalDataFlow.cs:525:33:525:33 | [post] access to local variable x : SubSimpleClass [field field] : String | GlobalDataFlow.cs:526:15:526:15 | access to local variable x : SubSimpleClass [field field] : String |
|
||||
| GlobalDataFlow.cs:526:15:526:15 | access to local variable x : SubSimpleClass [field field] : String | GlobalDataFlow.cs:526:15:526:21 | access to field field |
|
||||
| GlobalDataFlow.cs:532:20:532:20 | [post] access to parameter x : SimpleClass [field field] : String | GlobalDataFlow.cs:533:15:533:15 | access to parameter x : SimpleClass [field field] : String |
|
||||
| GlobalDataFlow.cs:532:25:532:25 | [post] access to local variable y : SimpleClass [field field] : String | GlobalDataFlow.cs:534:15:534:15 | access to local variable y : SimpleClass [field field] : String |
|
||||
| GlobalDataFlow.cs:533:15:533:15 | access to parameter x : SimpleClass [field field] : String | GlobalDataFlow.cs:533:15:533:21 | access to field field |
|
||||
@@ -579,8 +579,8 @@ nodes
|
||||
| GlobalDataFlow.cs:516:15:516:22 | access to field field | semmle.label | access to field field |
|
||||
| GlobalDataFlow.cs:517:15:517:16 | access to local variable y3 : SimpleClass [field field] : String | semmle.label | access to local variable y3 : SimpleClass [field field] : String |
|
||||
| GlobalDataFlow.cs:517:15:517:22 | access to field field | semmle.label | access to field field |
|
||||
| GlobalDataFlow.cs:525:33:525:33 | [post] access to local variable x : SimpleClass [field field] : String | semmle.label | [post] access to local variable x : SimpleClass [field field] : String |
|
||||
| GlobalDataFlow.cs:526:15:526:15 | access to local variable x : SimpleClass [field field] : String | semmle.label | access to local variable x : SimpleClass [field field] : String |
|
||||
| GlobalDataFlow.cs:525:33:525:33 | [post] access to local variable x : SubSimpleClass [field field] : String | semmle.label | [post] access to local variable x : SubSimpleClass [field field] : String |
|
||||
| GlobalDataFlow.cs:526:15:526:15 | access to local variable x : SubSimpleClass [field field] : String | semmle.label | access to local variable x : SubSimpleClass [field field] : String |
|
||||
| GlobalDataFlow.cs:526:15:526:21 | access to field field | semmle.label | access to field field |
|
||||
| GlobalDataFlow.cs:532:20:532:20 | [post] access to parameter x : SimpleClass [field field] : String | semmle.label | [post] access to parameter x : SimpleClass [field field] : String |
|
||||
| GlobalDataFlow.cs:532:25:532:25 | [post] access to local variable y : SimpleClass [field field] : String | semmle.label | [post] access to local variable y : SimpleClass [field field] : String |
|
||||
|
||||
@@ -293,7 +293,7 @@ edges
|
||||
| GlobalDataFlow.cs:500:9:500:10 | [post] access to parameter sc : SimpleClass [field field] : String | GlobalDataFlow.cs:514:31:514:32 | [post] access to local variable y1 : SimpleClass [field field] : String |
|
||||
| GlobalDataFlow.cs:500:9:500:10 | [post] access to parameter sc : SimpleClass [field field] : String | GlobalDataFlow.cs:514:36:514:37 | [post] access to local variable y2 : SimpleClass [field field] : String |
|
||||
| GlobalDataFlow.cs:500:9:500:10 | [post] access to parameter sc : SimpleClass [field field] : String | GlobalDataFlow.cs:514:42:514:43 | [post] access to local variable y3 : SimpleClass [field field] : String |
|
||||
| GlobalDataFlow.cs:500:9:500:10 | [post] access to parameter sc : SimpleClass [field field] : String | GlobalDataFlow.cs:525:33:525:33 | [post] access to local variable x : SimpleClass [field field] : String |
|
||||
| GlobalDataFlow.cs:500:9:500:10 | [post] access to parameter sc : SimpleClass [field field] : String | GlobalDataFlow.cs:525:33:525:33 | [post] access to local variable x : SubSimpleClass [field field] : String |
|
||||
| GlobalDataFlow.cs:500:9:500:10 | [post] access to parameter sc : SimpleClass [field field] : String | GlobalDataFlow.cs:532:20:532:20 | [post] access to parameter x : SimpleClass [field field] : String |
|
||||
| GlobalDataFlow.cs:500:9:500:10 | [post] access to parameter sc : SimpleClass [field field] : String | GlobalDataFlow.cs:532:25:532:25 | [post] access to local variable y : SimpleClass [field field] : String |
|
||||
| GlobalDataFlow.cs:500:9:500:10 | [post] access to parameter sc : SimpleClass [field field] : String | GlobalDataFlow.cs:544:20:544:20 | [post] access to local variable x : SimpleClass [field field] : String |
|
||||
@@ -312,8 +312,8 @@ edges
|
||||
| GlobalDataFlow.cs:515:15:515:16 | access to local variable y1 : SimpleClass [field field] : String | GlobalDataFlow.cs:515:15:515:22 | access to field field |
|
||||
| GlobalDataFlow.cs:516:15:516:16 | access to local variable y2 : SimpleClass [field field] : String | GlobalDataFlow.cs:516:15:516:22 | access to field field |
|
||||
| GlobalDataFlow.cs:517:15:517:16 | access to local variable y3 : SimpleClass [field field] : String | GlobalDataFlow.cs:517:15:517:22 | access to field field |
|
||||
| GlobalDataFlow.cs:525:33:525:33 | [post] access to local variable x : SimpleClass [field field] : String | GlobalDataFlow.cs:526:15:526:15 | access to local variable x : SimpleClass [field field] : String |
|
||||
| GlobalDataFlow.cs:526:15:526:15 | access to local variable x : SimpleClass [field field] : String | GlobalDataFlow.cs:526:15:526:21 | access to field field |
|
||||
| GlobalDataFlow.cs:525:33:525:33 | [post] access to local variable x : SubSimpleClass [field field] : String | GlobalDataFlow.cs:526:15:526:15 | access to local variable x : SubSimpleClass [field field] : String |
|
||||
| GlobalDataFlow.cs:526:15:526:15 | access to local variable x : SubSimpleClass [field field] : String | GlobalDataFlow.cs:526:15:526:21 | access to field field |
|
||||
| GlobalDataFlow.cs:532:20:532:20 | [post] access to parameter x : SimpleClass [field field] : String | GlobalDataFlow.cs:533:15:533:15 | access to parameter x : SimpleClass [field field] : String |
|
||||
| GlobalDataFlow.cs:532:25:532:25 | [post] access to local variable y : SimpleClass [field field] : String | GlobalDataFlow.cs:534:15:534:15 | access to local variable y : SimpleClass [field field] : String |
|
||||
| GlobalDataFlow.cs:533:15:533:15 | access to parameter x : SimpleClass [field field] : String | GlobalDataFlow.cs:533:15:533:21 | access to field field |
|
||||
@@ -633,8 +633,8 @@ nodes
|
||||
| GlobalDataFlow.cs:516:15:516:22 | access to field field | semmle.label | access to field field |
|
||||
| GlobalDataFlow.cs:517:15:517:16 | access to local variable y3 : SimpleClass [field field] : String | semmle.label | access to local variable y3 : SimpleClass [field field] : String |
|
||||
| GlobalDataFlow.cs:517:15:517:22 | access to field field | semmle.label | access to field field |
|
||||
| GlobalDataFlow.cs:525:33:525:33 | [post] access to local variable x : SimpleClass [field field] : String | semmle.label | [post] access to local variable x : SimpleClass [field field] : String |
|
||||
| GlobalDataFlow.cs:526:15:526:15 | access to local variable x : SimpleClass [field field] : String | semmle.label | access to local variable x : SimpleClass [field field] : String |
|
||||
| GlobalDataFlow.cs:525:33:525:33 | [post] access to local variable x : SubSimpleClass [field field] : String | semmle.label | [post] access to local variable x : SubSimpleClass [field field] : String |
|
||||
| GlobalDataFlow.cs:526:15:526:15 | access to local variable x : SubSimpleClass [field field] : String | semmle.label | access to local variable x : SubSimpleClass [field field] : String |
|
||||
| GlobalDataFlow.cs:526:15:526:21 | access to field field | semmle.label | access to field field |
|
||||
| GlobalDataFlow.cs:532:20:532:20 | [post] access to parameter x : SimpleClass [field field] : String | semmle.label | [post] access to parameter x : SimpleClass [field field] : String |
|
||||
| GlobalDataFlow.cs:532:25:532:25 | [post] access to local variable y : SimpleClass [field field] : String | semmle.label | [post] access to local variable y : SimpleClass [field field] : String |
|
||||
|
||||
@@ -74,14 +74,14 @@ edges
|
||||
| EntityFramework.cs:196:13:196:23 | [post] access to property Persons : DbSet<T> [element, property Name] : String | EntityFramework.cs:196:13:196:15 | [post] access to local variable ctx : MyContext [property Persons, element, property Name] : String |
|
||||
| EntityFramework.cs:196:29:196:29 | access to parameter p : Person [property Name] : String | EntityFramework.cs:196:13:196:23 | [post] access to property Persons : DbSet<T> [element, property Name] : String |
|
||||
| EntityFramework.cs:197:13:197:15 | access to local variable ctx : MyContext [property Persons, element, property Name] : String | EntityFramework.cs:204:18:204:28 | access to property Persons : DbSet<Person> [element, property Name] : String |
|
||||
| EntityFramework.cs:204:18:204:28 | access to property Persons : DbSet<Person> [element, property Name] : String | EntityFramework.cs:204:18:204:36 | call to method First<Person> : Object [property Name] : String |
|
||||
| EntityFramework.cs:204:18:204:36 | call to method First<Person> : Object [property Name] : String | EntityFramework.cs:204:18:204:41 | access to property Name |
|
||||
| EntityFramework.cs:212:18:212:30 | access to property Addresses : DbSet<Address> [element, property Street] : String | EntityFramework.cs:212:18:212:38 | call to method First<Address> : Object [property Street] : String |
|
||||
| EntityFramework.cs:212:18:212:38 | call to method First<Address> : Object [property Street] : String | EntityFramework.cs:212:18:212:45 | access to property Street |
|
||||
| EntityFramework.cs:219:18:219:28 | access to property Persons : DbSet<Person> [element, property Addresses, element, property Street] : String | EntityFramework.cs:219:18:219:36 | call to method First<Person> : Object [property Addresses, element, property Street] : String |
|
||||
| EntityFramework.cs:219:18:219:36 | call to method First<Person> : Object [property Addresses, element, property Street] : String | EntityFramework.cs:219:18:219:46 | access to property Addresses : ICollection<Address> [element, property Street] : String |
|
||||
| EntityFramework.cs:219:18:219:46 | access to property Addresses : ICollection<Address> [element, property Street] : String | EntityFramework.cs:219:18:219:54 | call to method First<Address> : Object [property Street] : String |
|
||||
| EntityFramework.cs:219:18:219:54 | call to method First<Address> : Object [property Street] : String | EntityFramework.cs:219:18:219:61 | access to property Street |
|
||||
| EntityFramework.cs:204:18:204:28 | access to property Persons : DbSet<Person> [element, property Name] : String | EntityFramework.cs:204:18:204:36 | call to method First<Person> : Person [property Name] : String |
|
||||
| EntityFramework.cs:204:18:204:36 | call to method First<Person> : Person [property Name] : String | EntityFramework.cs:204:18:204:41 | access to property Name |
|
||||
| EntityFramework.cs:212:18:212:30 | access to property Addresses : DbSet<Address> [element, property Street] : String | EntityFramework.cs:212:18:212:38 | call to method First<Address> : Address [property Street] : String |
|
||||
| EntityFramework.cs:212:18:212:38 | call to method First<Address> : Address [property Street] : String | EntityFramework.cs:212:18:212:45 | access to property Street |
|
||||
| EntityFramework.cs:219:18:219:28 | access to property Persons : DbSet<Person> [element, property Addresses, element, property Street] : String | EntityFramework.cs:219:18:219:36 | call to method First<Person> : Person [property Addresses, element, property Street] : String |
|
||||
| EntityFramework.cs:219:18:219:36 | call to method First<Person> : Person [property Addresses, element, property Street] : String | EntityFramework.cs:219:18:219:46 | access to property Addresses : ICollection<Address> [element, property Street] : String |
|
||||
| EntityFramework.cs:219:18:219:46 | access to property Addresses : ICollection<Address> [element, property Street] : String | EntityFramework.cs:219:18:219:54 | call to method First<Address> : Address [property Street] : String |
|
||||
| EntityFramework.cs:219:18:219:54 | call to method First<Address> : Address [property Street] : String | EntityFramework.cs:219:18:219:61 | access to property Street |
|
||||
| EntityFrameworkCore.cs:82:31:82:39 | "tainted" : String | EntityFrameworkCore.cs:83:18:83:28 | access to local variable taintSource |
|
||||
| EntityFrameworkCore.cs:82:31:82:39 | "tainted" : String | EntityFrameworkCore.cs:84:35:84:45 | access to local variable taintSource : String |
|
||||
| EntityFrameworkCore.cs:82:31:82:39 | "tainted" : String | EntityFrameworkCore.cs:85:18:85:42 | (...) ... |
|
||||
@@ -165,14 +165,14 @@ edges
|
||||
| EntityFrameworkCore.cs:229:13:229:23 | [post] access to property Persons : DbSet<T> [element, property Name] : String | EntityFrameworkCore.cs:229:13:229:15 | [post] access to local variable ctx : MyContext [property Persons, element, property Name] : String |
|
||||
| EntityFrameworkCore.cs:229:29:229:29 | access to parameter p : Person [property Name] : String | EntityFrameworkCore.cs:229:13:229:23 | [post] access to property Persons : DbSet<T> [element, property Name] : String |
|
||||
| EntityFrameworkCore.cs:230:13:230:15 | access to local variable ctx : MyContext [property Persons, element, property Name] : String | EntityFrameworkCore.cs:237:18:237:28 | access to property Persons : DbSet<Person> [element, property Name] : String |
|
||||
| EntityFrameworkCore.cs:237:18:237:28 | access to property Persons : DbSet<Person> [element, property Name] : String | EntityFrameworkCore.cs:237:18:237:36 | call to method First<Person> : Object [property Name] : String |
|
||||
| EntityFrameworkCore.cs:237:18:237:36 | call to method First<Person> : Object [property Name] : String | EntityFrameworkCore.cs:237:18:237:41 | access to property Name |
|
||||
| EntityFrameworkCore.cs:245:18:245:30 | access to property Addresses : DbSet<Address> [element, property Street] : String | EntityFrameworkCore.cs:245:18:245:38 | call to method First<Address> : Object [property Street] : String |
|
||||
| EntityFrameworkCore.cs:245:18:245:38 | call to method First<Address> : Object [property Street] : String | EntityFrameworkCore.cs:245:18:245:45 | access to property Street |
|
||||
| EntityFrameworkCore.cs:252:18:252:28 | access to property Persons : DbSet<Person> [element, property Addresses, element, property Street] : String | EntityFrameworkCore.cs:252:18:252:36 | call to method First<Person> : Object [property Addresses, element, property Street] : String |
|
||||
| EntityFrameworkCore.cs:252:18:252:36 | call to method First<Person> : Object [property Addresses, element, property Street] : String | EntityFrameworkCore.cs:252:18:252:46 | access to property Addresses : ICollection<Address> [element, property Street] : String |
|
||||
| EntityFrameworkCore.cs:252:18:252:46 | access to property Addresses : ICollection<Address> [element, property Street] : String | EntityFrameworkCore.cs:252:18:252:54 | call to method First<Address> : Object [property Street] : String |
|
||||
| EntityFrameworkCore.cs:252:18:252:54 | call to method First<Address> : Object [property Street] : String | EntityFrameworkCore.cs:252:18:252:61 | access to property Street |
|
||||
| EntityFrameworkCore.cs:237:18:237:28 | access to property Persons : DbSet<Person> [element, property Name] : String | EntityFrameworkCore.cs:237:18:237:36 | call to method First<Person> : Person [property Name] : String |
|
||||
| EntityFrameworkCore.cs:237:18:237:36 | call to method First<Person> : Person [property Name] : String | EntityFrameworkCore.cs:237:18:237:41 | access to property Name |
|
||||
| EntityFrameworkCore.cs:245:18:245:30 | access to property Addresses : DbSet<Address> [element, property Street] : String | EntityFrameworkCore.cs:245:18:245:38 | call to method First<Address> : Address [property Street] : String |
|
||||
| EntityFrameworkCore.cs:245:18:245:38 | call to method First<Address> : Address [property Street] : String | EntityFrameworkCore.cs:245:18:245:45 | access to property Street |
|
||||
| EntityFrameworkCore.cs:252:18:252:28 | access to property Persons : DbSet<Person> [element, property Addresses, element, property Street] : String | EntityFrameworkCore.cs:252:18:252:36 | call to method First<Person> : Person [property Addresses, element, property Street] : String |
|
||||
| EntityFrameworkCore.cs:252:18:252:36 | call to method First<Person> : Person [property Addresses, element, property Street] : String | EntityFrameworkCore.cs:252:18:252:46 | access to property Addresses : ICollection<Address> [element, property Street] : String |
|
||||
| EntityFrameworkCore.cs:252:18:252:46 | access to property Addresses : ICollection<Address> [element, property Street] : String | EntityFrameworkCore.cs:252:18:252:54 | call to method First<Address> : Address [property Street] : String |
|
||||
| EntityFrameworkCore.cs:252:18:252:54 | call to method First<Address> : Address [property Street] : String | EntityFrameworkCore.cs:252:18:252:61 | access to property Street |
|
||||
nodes
|
||||
| EntityFramework.cs:59:13:62:13 | { ..., ... } : Person [property Name] : String | semmle.label | { ..., ... } : Person [property Name] : String |
|
||||
| EntityFramework.cs:61:24:61:32 | "tainted" : String | semmle.label | "tainted" : String |
|
||||
@@ -237,15 +237,15 @@ nodes
|
||||
| EntityFramework.cs:196:29:196:29 | access to parameter p : Person [property Name] : String | semmle.label | access to parameter p : Person [property Name] : String |
|
||||
| EntityFramework.cs:197:13:197:15 | access to local variable ctx : MyContext [property Persons, element, property Name] : String | semmle.label | access to local variable ctx : MyContext [property Persons, element, property Name] : String |
|
||||
| EntityFramework.cs:204:18:204:28 | access to property Persons : DbSet<Person> [element, property Name] : String | semmle.label | access to property Persons : DbSet<Person> [element, property Name] : String |
|
||||
| EntityFramework.cs:204:18:204:36 | call to method First<Person> : Object [property Name] : String | semmle.label | call to method First<Person> : Object [property Name] : String |
|
||||
| EntityFramework.cs:204:18:204:36 | call to method First<Person> : Person [property Name] : String | semmle.label | call to method First<Person> : Person [property Name] : String |
|
||||
| EntityFramework.cs:204:18:204:41 | access to property Name | semmle.label | access to property Name |
|
||||
| EntityFramework.cs:212:18:212:30 | access to property Addresses : DbSet<Address> [element, property Street] : String | semmle.label | access to property Addresses : DbSet<Address> [element, property Street] : String |
|
||||
| EntityFramework.cs:212:18:212:38 | call to method First<Address> : Object [property Street] : String | semmle.label | call to method First<Address> : Object [property Street] : String |
|
||||
| EntityFramework.cs:212:18:212:38 | call to method First<Address> : Address [property Street] : String | semmle.label | call to method First<Address> : Address [property Street] : String |
|
||||
| EntityFramework.cs:212:18:212:45 | access to property Street | semmle.label | access to property Street |
|
||||
| EntityFramework.cs:219:18:219:28 | access to property Persons : DbSet<Person> [element, property Addresses, element, property Street] : String | semmle.label | access to property Persons : DbSet<Person> [element, property Addresses, element, property Street] : String |
|
||||
| EntityFramework.cs:219:18:219:36 | call to method First<Person> : Object [property Addresses, element, property Street] : String | semmle.label | call to method First<Person> : Object [property Addresses, element, property Street] : String |
|
||||
| EntityFramework.cs:219:18:219:36 | call to method First<Person> : Person [property Addresses, element, property Street] : String | semmle.label | call to method First<Person> : Person [property Addresses, element, property Street] : String |
|
||||
| EntityFramework.cs:219:18:219:46 | access to property Addresses : ICollection<Address> [element, property Street] : String | semmle.label | access to property Addresses : ICollection<Address> [element, property Street] : String |
|
||||
| EntityFramework.cs:219:18:219:54 | call to method First<Address> : Object [property Street] : String | semmle.label | call to method First<Address> : Object [property Street] : String |
|
||||
| EntityFramework.cs:219:18:219:54 | call to method First<Address> : Address [property Street] : String | semmle.label | call to method First<Address> : Address [property Street] : String |
|
||||
| EntityFramework.cs:219:18:219:61 | access to property Street | semmle.label | access to property Street |
|
||||
| EntityFrameworkCore.cs:82:31:82:39 | "tainted" : String | semmle.label | "tainted" : String |
|
||||
| EntityFrameworkCore.cs:83:18:83:28 | access to local variable taintSource | semmle.label | access to local variable taintSource |
|
||||
@@ -318,15 +318,15 @@ nodes
|
||||
| EntityFrameworkCore.cs:229:29:229:29 | access to parameter p : Person [property Name] : String | semmle.label | access to parameter p : Person [property Name] : String |
|
||||
| EntityFrameworkCore.cs:230:13:230:15 | access to local variable ctx : MyContext [property Persons, element, property Name] : String | semmle.label | access to local variable ctx : MyContext [property Persons, element, property Name] : String |
|
||||
| EntityFrameworkCore.cs:237:18:237:28 | access to property Persons : DbSet<Person> [element, property Name] : String | semmle.label | access to property Persons : DbSet<Person> [element, property Name] : String |
|
||||
| EntityFrameworkCore.cs:237:18:237:36 | call to method First<Person> : Object [property Name] : String | semmle.label | call to method First<Person> : Object [property Name] : String |
|
||||
| EntityFrameworkCore.cs:237:18:237:36 | call to method First<Person> : Person [property Name] : String | semmle.label | call to method First<Person> : Person [property Name] : String |
|
||||
| EntityFrameworkCore.cs:237:18:237:41 | access to property Name | semmle.label | access to property Name |
|
||||
| EntityFrameworkCore.cs:245:18:245:30 | access to property Addresses : DbSet<Address> [element, property Street] : String | semmle.label | access to property Addresses : DbSet<Address> [element, property Street] : String |
|
||||
| EntityFrameworkCore.cs:245:18:245:38 | call to method First<Address> : Object [property Street] : String | semmle.label | call to method First<Address> : Object [property Street] : String |
|
||||
| EntityFrameworkCore.cs:245:18:245:38 | call to method First<Address> : Address [property Street] : String | semmle.label | call to method First<Address> : Address [property Street] : String |
|
||||
| EntityFrameworkCore.cs:245:18:245:45 | access to property Street | semmle.label | access to property Street |
|
||||
| EntityFrameworkCore.cs:252:18:252:28 | access to property Persons : DbSet<Person> [element, property Addresses, element, property Street] : String | semmle.label | access to property Persons : DbSet<Person> [element, property Addresses, element, property Street] : String |
|
||||
| EntityFrameworkCore.cs:252:18:252:36 | call to method First<Person> : Object [property Addresses, element, property Street] : String | semmle.label | call to method First<Person> : Object [property Addresses, element, property Street] : String |
|
||||
| EntityFrameworkCore.cs:252:18:252:36 | call to method First<Person> : Person [property Addresses, element, property Street] : String | semmle.label | call to method First<Person> : Person [property Addresses, element, property Street] : String |
|
||||
| EntityFrameworkCore.cs:252:18:252:46 | access to property Addresses : ICollection<Address> [element, property Street] : String | semmle.label | access to property Addresses : ICollection<Address> [element, property Street] : String |
|
||||
| EntityFrameworkCore.cs:252:18:252:54 | call to method First<Address> : Object [property Street] : String | semmle.label | call to method First<Address> : Object [property Street] : String |
|
||||
| EntityFrameworkCore.cs:252:18:252:54 | call to method First<Address> : Address [property Street] : String | semmle.label | call to method First<Address> : Address [property Street] : String |
|
||||
| EntityFrameworkCore.cs:252:18:252:61 | access to property Street | semmle.label | access to property Street |
|
||||
subpaths
|
||||
#select
|
||||
|
||||
@@ -25,7 +25,14 @@ public class Parameters
|
||||
public void M17([Optional, DefaultParameterValue(null)] object arg7) => throw null;
|
||||
public void M18([Optional, DefaultParameterValue(3)] int? arg8) => throw null;
|
||||
public void M19([Optional, DecimalConstant(1, 0, 0, 0, 103)] decimal arg9) => throw null;
|
||||
public void M20([Optional, DefaultParameterValue(7)] MyStruct arg10) => throw null;
|
||||
public void M21([Optional, DefaultParameterValue("mystring")] MyStruct arg10) => throw null;
|
||||
|
||||
public struct MyStruct { }
|
||||
public struct MyStruct
|
||||
{
|
||||
public static implicit operator MyStruct(int i) => new MyStruct();
|
||||
public static implicit operator MyStruct(string s) => new MyStruct();
|
||||
|
||||
}
|
||||
public enum MyEnum { A = 1, B = 2 }
|
||||
}
|
||||
@@ -25,7 +25,14 @@ public class ParametersDll
|
||||
public void M17([Optional, DefaultParameterValue(null)] object arg7) => throw null;
|
||||
public void M18([Optional, DefaultParameterValue(3)] int? arg8) => throw null;
|
||||
public void M19([Optional, DecimalConstant(1, 0, 0, 0, 103)] decimal arg9) => throw null;
|
||||
public void M20([Optional, DefaultParameterValue(7)] MyStruct arg10) => throw null;
|
||||
public void M21([Optional, DefaultParameterValue("mystring")] MyStruct arg10) => throw null;
|
||||
|
||||
public struct MyStruct { }
|
||||
public struct MyStruct
|
||||
{
|
||||
public static implicit operator MyStruct(int i) => new MyStruct();
|
||||
public static implicit operator MyStruct(string s) => new MyStruct();
|
||||
|
||||
}
|
||||
public enum MyEnum { A = 1, B = 2 }
|
||||
}
|
||||
Binary file not shown.
@@ -5,12 +5,16 @@ noDefaultValue
|
||||
| Parameters.cs:8:17:8:18 | M2 | Parameters.cs:8:24:8:24 | a | 0 |
|
||||
| Parameters.cs:12:17:12:18 | M6 | Parameters.cs:12:29:12:30 | s1 | 0 |
|
||||
| Parameters.cs:13:17:13:18 | M7 | Parameters.cs:13:27:13:28 | e1 | 0 |
|
||||
| Parameters.cs:33:32:33:39 | implicit conversion | Parameters.cs:33:54:33:54 | i | 0 |
|
||||
| Parameters.cs:34:32:34:39 | implicit conversion | Parameters.cs:34:57:34:57 | s | 0 |
|
||||
| Parameters.dll:0:0:0:0 | M1 | Parameters.dll:0:0:0:0 | a | 0 |
|
||||
| Parameters.dll:0:0:0:0 | M1 | Parameters.dll:0:0:0:0 | b | 1 |
|
||||
| Parameters.dll:0:0:0:0 | M1 | Parameters.dll:0:0:0:0 | c | 2 |
|
||||
| Parameters.dll:0:0:0:0 | M2 | Parameters.dll:0:0:0:0 | a | 0 |
|
||||
| Parameters.dll:0:0:0:0 | M6 | Parameters.dll:0:0:0:0 | s1 | 0 |
|
||||
| Parameters.dll:0:0:0:0 | M7 | Parameters.dll:0:0:0:0 | e1 | 0 |
|
||||
| Parameters.dll:0:0:0:0 | implicit conversion | Parameters.dll:0:0:0:0 | i | 0 |
|
||||
| Parameters.dll:0:0:0:0 | implicit conversion | Parameters.dll:0:0:0:0 | s | 0 |
|
||||
withDefaultValue
|
||||
| Parameters.cs:8:17:8:18 | M2 | Parameters.cs:8:34:8:34 | b | 1 | Parameters.cs:8:38:8:41 | null | null |
|
||||
| Parameters.cs:8:17:8:18 | M2 | Parameters.cs:8:51:8:51 | c | 2 | Parameters.cs:8:55:8:70 | "default string" | default string |
|
||||
@@ -39,6 +43,8 @@ withDefaultValue
|
||||
| Parameters.cs:25:17:25:19 | M17 | Parameters.cs:25:68:25:71 | arg7 | 0 | Parameters.cs:25:21:25:71 | default | null |
|
||||
| Parameters.cs:26:17:26:19 | M18 | Parameters.cs:26:63:26:66 | arg8 | 0 | Parameters.cs:26:21:26:66 | 3 | 3 |
|
||||
| Parameters.cs:27:17:27:19 | M19 | Parameters.cs:27:74:27:77 | arg9 | 0 | Parameters.cs:27:21:27:77 | 10.3 | 10.3 |
|
||||
| Parameters.cs:28:17:28:19 | M20 | Parameters.cs:28:67:28:71 | arg10 | 0 | Parameters.cs:28:21:28:71 | call to operator implicit conversion | - |
|
||||
| Parameters.cs:29:17:29:19 | M21 | Parameters.cs:29:76:29:80 | arg10 | 0 | Parameters.cs:29:21:29:80 | call to operator implicit conversion | - |
|
||||
| Parameters.dll:0:0:0:0 | M2 | Parameters.dll:0:0:0:0 | b | 1 | Parameters.dll:0:0:0:0 | default | null |
|
||||
| Parameters.dll:0:0:0:0 | M2 | Parameters.dll:0:0:0:0 | c | 2 | Parameters.dll:0:0:0:0 | "default string" | default string |
|
||||
| Parameters.dll:0:0:0:0 | M3 | Parameters.dll:0:0:0:0 | a | 0 | Parameters.dll:0:0:0:0 | 1 | 1 |
|
||||
@@ -66,8 +72,15 @@ withDefaultValue
|
||||
| Parameters.dll:0:0:0:0 | M17 | Parameters.dll:0:0:0:0 | arg7 | 0 | Parameters.dll:0:0:0:0 | default | null |
|
||||
| Parameters.dll:0:0:0:0 | M18 | Parameters.dll:0:0:0:0 | arg8 | 0 | Parameters.dll:0:0:0:0 | 3 | 3 |
|
||||
| Parameters.dll:0:0:0:0 | M19 | Parameters.dll:0:0:0:0 | arg9 | 0 | Parameters.dll:0:0:0:0 | 10.3 | 10.3 |
|
||||
| Parameters.dll:0:0:0:0 | M20 | Parameters.dll:0:0:0:0 | arg10 | 0 | Parameters.dll:0:0:0:0 | call to operator implicit conversion | - |
|
||||
| Parameters.dll:0:0:0:0 | M21 | Parameters.dll:0:0:0:0 | arg10 | 0 | Parameters.dll:0:0:0:0 | call to operator implicit conversion | - |
|
||||
dateTimeDefaults
|
||||
| Parameters.cs:22:17:22:19 | M14 | Parameters.cs:22:64:22:67 | arg4 | Parameters.cs:22:21:22:67 | object creation of type DateTime | DateTime(long) | 14 |
|
||||
| Parameters.cs:23:17:23:19 | M15 | Parameters.cs:23:68:23:71 | arg5 | Parameters.cs:23:21:23:71 | object creation of type DateTime | DateTime(long) | 10001 |
|
||||
| Parameters.dll:0:0:0:0 | M14 | Parameters.dll:0:0:0:0 | arg4 | Parameters.dll:0:0:0:0 | object creation of type DateTime | DateTime(long) | 14 |
|
||||
| Parameters.dll:0:0:0:0 | M15 | Parameters.dll:0:0:0:0 | arg5 | Parameters.dll:0:0:0:0 | object creation of type DateTime | DateTime(long) | 10001 |
|
||||
implicitConversionDefaults
|
||||
| Parameters.cs:28:17:28:19 | M20 | Parameters.cs:28:67:28:71 | arg10 | Parameters.cs:28:21:28:71 | call to operator implicit conversion | Parameters.cs:28:21:28:71 | 7 | Int32 | 7 |
|
||||
| Parameters.cs:29:17:29:19 | M21 | Parameters.cs:29:76:29:80 | arg10 | Parameters.cs:29:21:29:80 | call to operator implicit conversion | Parameters.cs:29:21:29:80 | "mystring" | String | mystring |
|
||||
| Parameters.dll:0:0:0:0 | M20 | Parameters.dll:0:0:0:0 | arg10 | Parameters.dll:0:0:0:0 | call to operator implicit conversion | Parameters.dll:0:0:0:0 | 7 | Int32 | 7 |
|
||||
| Parameters.dll:0:0:0:0 | M21 | Parameters.dll:0:0:0:0 | arg10 | Parameters.dll:0:0:0:0 | call to operator implicit conversion | Parameters.dll:0:0:0:0 | "mystring" | String | mystring |
|
||||
|
||||
@@ -16,11 +16,15 @@ query predicate noDefaultValue(Parameterizable container, Parameter p, int i) {
|
||||
not compilerGeneratedAttribute(container)
|
||||
}
|
||||
|
||||
query predicate withDefaultValue(Parameterizable container, Parameter p, int i, Expr e, string value) {
|
||||
private predicate defaultValue(Parameterizable container, Parameter p, int i, Expr e) {
|
||||
fromTestLocation(container) and
|
||||
p.hasDefaultValue() and
|
||||
container.getParameter(i) = p and
|
||||
p.getDefaultValue() = e and
|
||||
p.getDefaultValue() = e
|
||||
}
|
||||
|
||||
query predicate withDefaultValue(Parameterizable container, Parameter p, int i, Expr e, string value) {
|
||||
defaultValue(container, p, i, e) and
|
||||
(if exists(e.getValue()) then value = e.getValue() else value = "-") and
|
||||
not compilerGeneratedAttribute(container)
|
||||
}
|
||||
@@ -28,11 +32,17 @@ query predicate withDefaultValue(Parameterizable container, Parameter p, int i,
|
||||
query predicate dateTimeDefaults(
|
||||
Parameterizable container, Parameter p, ObjectCreation o, string constructor, string value
|
||||
) {
|
||||
fromTestLocation(container) and
|
||||
p.hasDefaultValue() and
|
||||
container.getAParameter() = p and
|
||||
p.getDefaultValue() = o and
|
||||
defaultValue(container, p, _, o) and
|
||||
o.getTarget().toStringWithTypes() = constructor and
|
||||
o.getAnArgument().getValue() = value and
|
||||
not compilerGeneratedAttribute(container)
|
||||
}
|
||||
|
||||
query predicate implicitConversionDefaults(
|
||||
Parameterizable container, Parameter p, OperatorCall o, Expr e, string type, string value
|
||||
) {
|
||||
defaultValue(container, p, _, o) and
|
||||
o.getAnArgument() = e and
|
||||
type = e.getType().toString() and
|
||||
value = e.getValue()
|
||||
}
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
| ExposeRepresentation.cs:8:21:8:23 | Set | 'Set' exposes the internal representation stored in field 'rarray'. The value may be modified $@. | ExposeRepresentation.cs:16:9:16:9 | ExposeRepresentation.cs:16:9:16:9 | through the variable a |
|
||||
| ExposeRepresentationBad.cs:18:22:18:24 | Get | 'Get' exposes the internal representation stored in field 'rarray'. The value may be modified $@. | ExposeRepresentationBad.cs:24:23:24:29 | ExposeRepresentationBad.cs:24:23:24:29 | after this call to Get |
|
||||
| ExposeRepresentation.cs:8:21:8:23 | Set | 'Set' exposes the internal representation stored in field 'rarray'. The value may be modified $@. | ExposeRepresentation.cs:16:9:16:9 | access to local variable a | through the variable a |
|
||||
| ExposeRepresentationBad.cs:18:22:18:24 | Get | 'Get' exposes the internal representation stored in field 'rarray'. The value may be modified $@. | ExposeRepresentationBad.cs:24:23:24:29 | call to method Get | after this call to Get |
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user