Skip to content

Commit 1eef77c

Browse files
committed
Restrict TNodeReverse
1 parent 5ed89fd commit 1eef77c

File tree

2 files changed

+101
-1
lines changed

2 files changed

+101
-1
lines changed

csharp/ql/lib/semmle/code/csharp/security/dataflow/flowsinks/ExternalLocationSink.qll

+2
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,8 @@ private module LocalFileOutputStreamConfig implements DataFlow::ConfigSig {
115115

116116
private module LocalFileOutputStreamFlow = DataFlow::Global<LocalFileOutputStreamConfig>;
117117

118+
private predicate sdf = LocalFileOutputStreamFlow::Debug::stageStats/10;
119+
118120
/**
119121
* A write to the local filesystem.
120122
*/

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

+99-1
Original file line numberDiff line numberDiff line change
@@ -1046,6 +1046,102 @@ module MakeImplCommon<LocationSig Location, InputSig<Location> Lang> {
10461046
}
10471047

10481048
private module ReverseFlow {
1049+
module Cand {
1050+
/**
1051+
* Holds if `p` can flow to `node` in the same callable using only
1052+
* value-preserving steps.
1053+
*
1054+
* `read` indicates whether it is contents of `p` that can flow to `node`.
1055+
*/
1056+
pragma[nomagic]
1057+
private predicate parameterValueFlowCand(ParamNode p, Node node) {
1058+
(
1059+
p = node
1060+
or
1061+
// local flow
1062+
exists(Node mid |
1063+
parameterValueFlowCand(p, mid) and
1064+
simpleLocalFlowStep(mid, node, _) and
1065+
validParameterAliasStep(mid, node)
1066+
)
1067+
or
1068+
// store
1069+
exists(Node mid |
1070+
parameterValueFlowCand(p, mid) and
1071+
Lang::storeStep(mid, _, node)
1072+
)
1073+
or
1074+
// read
1075+
exists(Node mid |
1076+
parameterValueFlowCand(p, mid) and
1077+
Lang::readStep(mid, _, node)
1078+
)
1079+
or
1080+
// flow through
1081+
exists(ArgNode arg |
1082+
parameterValueFlowArgCand(p, arg) and
1083+
argumentValueFlowsThroughCand(arg, node)
1084+
)
1085+
)
1086+
}
1087+
1088+
pragma[nomagic]
1089+
private predicate parameterValueFlowArgCand(ParamNode p, ArgNode arg) {
1090+
parameterValueFlowCand(p, arg)
1091+
}
1092+
1093+
pragma[nomagic]
1094+
predicate parameterValueFlowsToPreUpdateCand(ParamNode p, PostUpdateNode n) {
1095+
parameterValueFlowCand(p, n.getPreUpdateNode())
1096+
}
1097+
1098+
/**
1099+
* Holds if `p` can flow to a return node of kind `kind` in the same
1100+
* callable using only value-preserving steps, not taking call contexts
1101+
* into account.
1102+
*
1103+
* `read` indicates whether it is contents of `p` that can flow to the return
1104+
* node.
1105+
*/
1106+
predicate parameterValueFlowReturnCand(ParamNode p, ReturnKind kind) {
1107+
exists(ReturnNode ret |
1108+
parameterValueFlowCand(p, ret) and
1109+
kind = ret.getKind()
1110+
)
1111+
}
1112+
1113+
pragma[nomagic]
1114+
private predicate argumentValueFlowsThroughCand0(
1115+
DataFlowCall call, ArgNode arg, ReturnKind kind
1116+
) {
1117+
exists(ParamNode param | viableParamArg(call, param, arg) |
1118+
parameterValueFlowReturnCand(param, kind)
1119+
)
1120+
}
1121+
1122+
/**
1123+
* Holds if `arg` flows to `out` through a call using only value-preserving steps,
1124+
* not taking call contexts into account.
1125+
*
1126+
* `read` indicates whether it is contents of `arg` that can flow to `out`.
1127+
*/
1128+
predicate argumentValueFlowsThroughCand(ArgNode arg, Node out) {
1129+
exists(DataFlowCall call, ReturnKind kind |
1130+
argumentValueFlowsThroughCand0(call, arg, kind) and
1131+
out = getAnOutNode(call, kind)
1132+
)
1133+
}
1134+
1135+
predicate cand(ParamNode p, Node n) {
1136+
parameterValueFlowCand(p, n) and
1137+
(
1138+
parameterValueFlowReturnCand(p, _)
1139+
or
1140+
parameterValueFlowsToPreUpdateCand(p, _)
1141+
)
1142+
}
1143+
}
1144+
10491145
/**
10501146
* Holds if the local step from `arg` to `out` actually models a flow-through
10511147
* step.
@@ -2091,7 +2187,9 @@ module MakeImplCommon<LocationSig Location, InputSig<Location> Lang> {
20912187
newtype TNodeEx =
20922188
TNodeNormal(Node n) or
20932189
TNodeImplicitRead(Node n) or // will be restricted to nodes with actual implicit reads in `DataFlowImpl.qll`
2094-
TNodeReverse(Node n, Boolean allowFwdFlowOut)
2190+
TNodeReverse(Node n, Boolean allowFwdFlowOut) {
2191+
ReverseFlow::Cand::cand(_, n) or n = any(PostUpdateNode p).getPreUpdateNode()
2192+
}
20952193

20962194
/**
20972195
* Holds if data can flow in one local step from `node1` to `node2`.

0 commit comments

Comments
 (0)