Skip to content

Commit b13d026

Browse files
committed
Dataflow: Review fixes.
1 parent 74787bf commit b13d026

File tree

3 files changed

+49
-32
lines changed

3 files changed

+49
-32
lines changed

csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowPrivate.qll

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -546,7 +546,11 @@ module LocalFlow {
546546
)
547547
or
548548
hasNodePath(any(LocalExprStepConfiguration x), node1, node2) and
549-
(node2 instanceof SsaDefinitionExtNode or node2.asExpr() instanceof Cast)
549+
(
550+
node2 instanceof SsaDefinitionExtNode or
551+
node2.asExpr() instanceof Cast or
552+
node2.asExpr() instanceof AssignExpr
553+
)
550554
or
551555
exists(SsaImpl::Definition def |
552556
def = getSsaDefinitionExt(node1) and

shared/dataflow/codeql/dataflow/internal/DataFlowImpl.qll

Lines changed: 21 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1316,7 +1316,7 @@ module MakeImpl<InputSig Lang> {
13161316
)
13171317
or
13181318
// flow into a callable
1319-
fwdFlowIn(_, node, state, _, cc, _, _, _, t, ap, apa) and
1319+
fwdFlowIn(_, _, node, state, _, cc, _, _, _, t, ap, apa, _) and
13201320
if PrevStage::parameterMayFlowThrough(node, apa)
13211321
then (
13221322
summaryCtx = TParamNodeSome(node.asNode()) and
@@ -1476,15 +1476,14 @@ module MakeImpl<InputSig Lang> {
14761476

14771477
pragma[nomagic]
14781478
private predicate fwdFlowIn(
1479-
DataFlowCall call, ParamNodeEx p, FlowState state, Cc outercc, CcCall innercc,
1480-
ParamNodeOption summaryCtx, TypOption argT, ApOption argAp, Typ t, Ap ap, ApApprox apa
1479+
DataFlowCall call, DataFlowCallable inner, ParamNodeEx p, FlowState state, Cc outercc,
1480+
CcCall innercc, ParamNodeOption summaryCtx, TypOption argT, ApOption argAp, Typ t, Ap ap,
1481+
ApApprox apa, boolean cc
14811482
) {
1482-
exists(DataFlowCallable inner, boolean cc |
1483-
fwdFlowInCand(call, inner, p, state, outercc, summaryCtx, argT, argAp, t, ap, apa) and
1484-
FwdTypeFlow::typeFlowValidEdgeIn(call, inner, cc) and
1485-
innercc = getCallContextCall(call, inner) and
1486-
if outercc instanceof CcCall then cc = true else cc = false
1487-
)
1483+
fwdFlowInCand(call, inner, p, state, outercc, summaryCtx, argT, argAp, t, ap, apa) and
1484+
FwdTypeFlow::typeFlowValidEdgeIn(call, inner, cc) and
1485+
innercc = getCallContextCall(call, inner) and
1486+
if outercc instanceof CcCall then cc = true else cc = false
14881487
}
14891488

14901489
bindingset[ctx, result]
@@ -1535,6 +1534,7 @@ module MakeImpl<InputSig Lang> {
15351534
)
15361535
}
15371536

1537+
pragma[nomagic]
15381538
private predicate fwdFlowOut(
15391539
DataFlowCall call, DataFlowCallable inner, NodeEx out, FlowState state, CcNoCall outercc,
15401540
ParamNodeOption summaryCtx, TypOption argT, ApOption argAp, Typ t, Ap ap, ApApprox apa
@@ -1557,11 +1557,9 @@ module MakeImpl<InputSig Lang> {
15571557

15581558
pragma[nomagic]
15591559
predicate dataFlowTakenCallEdgeIn(DataFlowCall call, DataFlowCallable c, boolean cc) {
1560-
exists(ParamNodeEx p, Cc outercc, FlowState state, Cc innercc, Typ t, Ap ap |
1561-
fwdFlowIn(call, p, state, outercc, innercc, _, _, _, t, ap, _) and
1562-
fwdFlow1(p, state, innercc, _, _, _, t, _, ap, _) and
1563-
c = p.getEnclosingCallable() and
1564-
if outercc instanceof CcCall then cc = true else cc = false
1560+
exists(ParamNodeEx p, FlowState state, Cc innercc, Typ t, Ap ap |
1561+
fwdFlowIn(call, c, p, state, _, innercc, _, _, _, t, ap, _, cc) and
1562+
fwdFlow1(p, state, innercc, _, _, _, t, _, ap, _)
15651563
)
15661564
}
15671565

@@ -1647,8 +1645,8 @@ module MakeImpl<InputSig Lang> {
16471645
ApOption argAp, ParamNodeEx p, Typ t, Ap ap
16481646
) {
16491647
exists(ApApprox apa |
1650-
fwdFlowIn(call, pragma[only_bind_into](p), _, cc, innerCc, summaryCtx, argT, argAp, t,
1651-
ap, pragma[only_bind_into](apa)) and
1648+
fwdFlowIn(call, _, pragma[only_bind_into](p), _, cc, innerCc, summaryCtx, argT, argAp,
1649+
t, ap, pragma[only_bind_into](apa), _) and
16521650
PrevStage::parameterMayFlowThrough(p, apa) and
16531651
PrevStage::callMayFlowThroughRev(call)
16541652
)
@@ -1802,7 +1800,7 @@ module MakeImpl<InputSig Lang> {
18021800
or
18031801
// flow out of a callable
18041802
exists(ReturnPosition pos |
1805-
revFlowOut(_, node, pos, state, _, _, ap) and
1803+
revFlowOut(_, node, pos, state, _, _, _, ap) and
18061804
if returnFlowsThrough(node, pos, state, _, _, _, _, ap)
18071805
then (
18081806
returnCtx = TReturnCtxMaybeFlowThrough(pos) and
@@ -1867,10 +1865,9 @@ module MakeImpl<InputSig Lang> {
18671865

18681866
pragma[nomagic]
18691867
predicate dataFlowTakenCallEdgeIn(DataFlowCall call, DataFlowCallable c, boolean cc) {
1870-
exists(RetNodeEx ret, ReturnCtx returnCtx |
1871-
revFlowOut(call, ret, _, _, returnCtx, _, _) and
1872-
c = ret.getEnclosingCallable() and
1873-
if returnCtx instanceof TReturnCtxNone then cc = false else cc = true
1868+
exists(RetNodeEx ret |
1869+
revFlowOut(call, ret, _, _, _, cc, _, _) and
1870+
c = ret.getEnclosingCallable()
18741871
)
18751872
}
18761873

@@ -1925,9 +1922,9 @@ module MakeImpl<InputSig Lang> {
19251922
pragma[nomagic]
19261923
private predicate revFlowOut(
19271924
DataFlowCall call, RetNodeEx ret, ReturnPosition pos, FlowState state,
1928-
ReturnCtx returnCtx, ApOption returnAp, Ap ap
1925+
ReturnCtx returnCtx, boolean cc, ApOption returnAp, Ap ap
19291926
) {
1930-
exists(NodeEx out, boolean cc |
1927+
exists(NodeEx out |
19311928
revFlow(out, state, returnCtx, returnAp, ap) and
19321929
flowOutOfCallApValid(call, ret, pos, out, ap, cc) and
19331930
if returnCtx instanceof TReturnCtxNone then cc = false else cc = true
@@ -1963,7 +1960,7 @@ module MakeImpl<InputSig Lang> {
19631960
DataFlowCall call, ReturnCtx returnCtx, ApOption returnAp, ReturnPosition pos, Ap ap
19641961
) {
19651962
exists(RetNodeEx ret, FlowState state, CcCall ccc |
1966-
revFlowOut(call, ret, pos, state, returnCtx, returnAp, ap) and
1963+
revFlowOut(call, ret, pos, state, returnCtx, _, returnAp, ap) and
19671964
returnFlowsThrough(ret, pos, state, ccc, _, _, _, ap) and
19681965
matchesCall(ccc, call)
19691966
)

shared/dataflow/codeql/dataflow/internal/DataFlowImplCommon.qll

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1002,7 +1002,7 @@ module MakeImplCommon<InputSig Lang> {
10021002
* flow between parameter and argument nodes in the cases where it is possible
10031003
* for a type to first be weakened and then strengthened again. When the
10041004
* stronger types at the end-points of such a type flow path are incompatible,
1005-
* the call relevant call edges can be excluded as impossible.
1005+
* the relevant call edges can be excluded as impossible.
10061006
*
10071007
* The predicates `relevantCallEdgeIn` and `relevantCallEdgeOut` give the
10081008
* graph to be explored prior to the recursion, and the other three predicates
@@ -1021,7 +1021,7 @@ module MakeImplCommon<InputSig Lang> {
10211021
}
10221022

10231023
/**
1024-
* Holds if a sequence calls may propagates the value of `p` to some
1024+
* Holds if a sequence of calls may propagate the value of `p` to some
10251025
* argument-to-parameter call edge that strengthens the static type.
10261026
*/
10271027
pragma[nomagic]
@@ -1033,7 +1033,7 @@ module MakeImplCommon<InputSig Lang> {
10331033
}
10341034

10351035
/**
1036-
* Holds if a sequence calls may propagates the value of `arg` to some
1036+
* Holds if a sequence of calls may propagate the value of `arg` to some
10371037
* argument-to-parameter call edge that strengthens the static type.
10381038
*/
10391039
pragma[nomagic]
@@ -1048,6 +1048,9 @@ module MakeImplCommon<InputSig Lang> {
10481048
)
10491049
or
10501050
exists(ParamNode p, DataFlowType at, DataFlowType pt |
1051+
// A call edge may implicitly strengthen a type by ensuring that a
1052+
// specific argument node was reached if the type of that argument was
1053+
// strengthened via a cast.
10511054
at = getNodeType(arg) and
10521055
pt = getNodeType(p) and
10531056
paramMustFlow(p, arg) and
@@ -1072,6 +1075,10 @@ module MakeImplCommon<InputSig Lang> {
10721075
DataFlowCall call1, DataFlowCallable c1, ArgNode argOut, DataFlowCall call2,
10731076
DataFlowCallable c2, ArgNode argIn
10741077
|
1078+
// Data flow may exit `call1` and enter `call2`. If a stronger type is
1079+
// known for `argOut`, `argIn` may reach a strengthening, and both are
1080+
// determined by the same parameter `p` so we know they're equal, then
1081+
// we should track those nodes.
10751082
trackedParamTypeCand(p) and
10761083
callEdge(call1, c1, argOut, _) and
10771084
Input::relevantCallEdgeOut(call1, c1) and
@@ -1152,6 +1159,15 @@ module MakeImplCommon<InputSig Lang> {
11521159
paramMustFlow(_, arg)
11531160
}
11541161

1162+
/**
1163+
* Gets the strongest of the two types `t1` and `t2`. If neither type is
1164+
* stronger then compatibility is checked and `t1` is returned.
1165+
*/
1166+
bindingset[t1, t2]
1167+
DataFlowType getStrongestType(DataFlowType t1, DataFlowType t2) {
1168+
if typeStrongerThan(t2, t1) then result = t2 else (compatibleTypes(t1, t2) and result = t1)
1169+
}
1170+
11551171
/**
11561172
* Holds if `t` is a possible type for an argument reaching the tracked
11571173
* parameter `p` through an in-going edge in the current data flow stage.
@@ -1179,15 +1195,15 @@ module MakeImplCommon<InputSig Lang> {
11791195
cc = true and
11801196
typeFlowParamTypeCand(p, t1) and
11811197
nodeDataFlowType(p, t2) and
1182-
if typeStrongerThan(t2, t1) then t = t2 else (compatibleTypes(t1, t2) and t = t1)
1198+
t = getStrongestType(t1, t2)
11831199
)
11841200
or
11851201
exists(ArgNode arg, DataFlowType t1, DataFlowType t2 |
11861202
cc = false and
11871203
typeFlowArgTypeFromReturn(arg, t1) and
11881204
paramMustFlow(p, arg) and
11891205
nodeDataFlowType(p, t2) and
1190-
if typeStrongerThan(t2, t1) then t = t2 else (compatibleTypes(t1, t2) and t = t1)
1206+
t = getStrongestType(t1, t2)
11911207
)
11921208
or
11931209
exists(DataFlowCall call |
@@ -1208,7 +1224,7 @@ module MakeImplCommon<InputSig Lang> {
12081224
dataFlowTakenCallEdgeOut(_, _, arg, p) and
12091225
(if trackedParamType(p) then typeFlowParamType(p, t1, false) else nodeDataFlowType(p, t1)) and
12101226
nodeDataFlowType(arg, t2) and
1211-
if typeStrongerThan(t2, t1) then t = t2 else (compatibleTypes(t1, t2) and t = t1)
1227+
t = getStrongestType(t1, t2)
12121228
)
12131229
}
12141230

@@ -1224,7 +1240,7 @@ module MakeImplCommon<InputSig Lang> {
12241240
paramMustFlow(p, arg) and
12251241
typeFlowParamType(p, t1, cc) and
12261242
nodeDataFlowType(arg, t2) and
1227-
if typeStrongerThan(t2, t1) then t = t2 else (compatibleTypes(t1, t2) and t = t1)
1243+
t = getStrongestType(t1, t2)
12281244
)
12291245
or
12301246
cc = [true, false] and

0 commit comments

Comments
 (0)