Skip to content

Commit e949458

Browse files
authored
Merge pull request #10066 from hvitved/csharp/underlying-as-callable
C#: Include both source code and hand-written summaries in data flow
2 parents 349331d + 93830f4 commit e949458

File tree

5 files changed

+35
-38
lines changed

5 files changed

+35
-38
lines changed

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

Lines changed: 8 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -105,15 +105,12 @@ class DataFlowSummarizedCallable instanceof FlowSummary::SummarizedCallable {
105105
private module Cached {
106106
/**
107107
* The following heuristic is used to rank when to use source code or when to use summaries for DataFlowCallables.
108-
* 1. Use hand written summaries.
109-
* 2. Use source code.
110-
* 3. Use auto generated summaries.
108+
* 1. Use hand written summaries or source code.
109+
* 2. Use auto generated summaries.
111110
*/
112111
cached
113112
newtype TDataFlowCallable =
114-
TDotNetCallable(DotNet::Callable c) {
115-
c.isUnboundDeclaration() and not c instanceof DataFlowSummarizedCallable
116-
} or
113+
TDotNetCallable(DotNet::Callable c) { c.isUnboundDeclaration() } or
117114
TSummarizedCallable(DataFlowSummarizedCallable sc)
118115

119116
cached
@@ -370,7 +367,7 @@ class NonDelegateDataFlowCall extends DataFlowCall, TNonDelegateCall {
370367
override DataFlow::ExprNode getNode() { result.getControlFlowNode() = cfn }
371368

372369
override DataFlowCallable getEnclosingCallable() {
373-
result.getUnderlyingCallable() = cfn.getEnclosingCallable()
370+
result.asCallable() = cfn.getEnclosingCallable()
374371
}
375372

376373
override string toString() { result = cfn.toString() }
@@ -400,7 +397,7 @@ class ExplicitDelegateLikeDataFlowCall extends DelegateDataFlowCall, TExplicitDe
400397
override DataFlow::ExprNode getNode() { result.getControlFlowNode() = cfn }
401398

402399
override DataFlowCallable getEnclosingCallable() {
403-
result.getUnderlyingCallable() = cfn.getEnclosingCallable()
400+
result.asCallable() = cfn.getEnclosingCallable()
404401
}
405402

406403
override string toString() { result = cfn.toString() }
@@ -419,14 +416,14 @@ class TransitiveCapturedDataFlowCall extends DataFlowCall, TTransitiveCapturedCa
419416

420417
TransitiveCapturedDataFlowCall() { this = TTransitiveCapturedCall(cfn, target) }
421418

422-
override DataFlowCallable getARuntimeTarget() { result.getUnderlyingCallable() = target }
419+
override DataFlowCallable getARuntimeTarget() { result.asCallable() = target }
423420

424421
override ControlFlow::Nodes::ElementNode getControlFlowNode() { result = cfn }
425422

426423
override DataFlow::ExprNode getNode() { none() }
427424

428425
override DataFlowCallable getEnclosingCallable() {
429-
result.getUnderlyingCallable() = cfn.getEnclosingCallable()
426+
result.asCallable() = cfn.getEnclosingCallable()
430427
}
431428

432429
override string toString() { result = "[transitive] " + cfn.toString() }
@@ -450,7 +447,7 @@ class CilDataFlowCall extends DataFlowCall, TCilCall {
450447
override DataFlow::ExprNode getNode() { result.getExpr() = call }
451448

452449
override DataFlowCallable getEnclosingCallable() {
453-
result.getUnderlyingCallable() = call.getEnclosingCallable()
450+
result.asCallable() = call.getEnclosingCallable()
454451
}
455452

456453
override string toString() { result = call.toString() }

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

Lines changed: 23 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -65,9 +65,11 @@ abstract class NodeImpl extends Node {
6565

6666
private class ExprNodeImpl extends ExprNode, NodeImpl {
6767
override DataFlowCallable getEnclosingCallableImpl() {
68-
result.getUnderlyingCallable() = this.getExpr().(CIL::Expr).getEnclosingCallable()
69-
or
70-
result.getUnderlyingCallable() = this.getControlFlowNodeImpl().getEnclosingCallable()
68+
result.asCallable() =
69+
[
70+
this.getExpr().(CIL::Expr).getEnclosingCallable().(DotNet::Callable),
71+
this.getControlFlowNodeImpl().getEnclosingCallable()
72+
]
7173
}
7274

7375
override DotNet::Type getTypeImpl() {
@@ -852,7 +854,7 @@ class SsaDefinitionNode extends NodeImpl, TSsaDefinitionNode {
852854
Ssa::Definition getDefinition() { result = def }
853855

854856
override DataFlowCallable getEnclosingCallableImpl() {
855-
result.getUnderlyingCallable() = def.getEnclosingCallable()
857+
result.asCallable() = def.getEnclosingCallable()
856858
}
857859

858860
override Type getTypeImpl() { result = def.getSourceVariable().getType() }
@@ -914,9 +916,7 @@ private module ParameterNodes {
914916
callable = c.asCallable() and pos.isThisParameter()
915917
}
916918

917-
override DataFlowCallable getEnclosingCallableImpl() {
918-
result.getUnderlyingCallable() = callable
919-
}
919+
override DataFlowCallable getEnclosingCallableImpl() { result.asCallable() = callable }
920920

921921
override Type getTypeImpl() { result = callable.getDeclaringType() }
922922

@@ -963,7 +963,7 @@ private module ParameterNodes {
963963

964964
override predicate isParameterOf(DataFlowCallable c, ParameterPosition pos) {
965965
pos.isImplicitCapturedParameterPosition(def.getSourceVariable().getAssignable()) and
966-
c.getUnderlyingCallable() = this.getEnclosingCallable()
966+
c.asCallable() = this.getEnclosingCallable()
967967
}
968968
}
969969

@@ -1078,7 +1078,7 @@ private module ArgumentNodes {
10781078
}
10791079

10801080
override DataFlowCallable getEnclosingCallableImpl() {
1081-
result.getUnderlyingCallable() = cfn.getEnclosingCallable()
1081+
result.asCallable() = cfn.getEnclosingCallable()
10821082
}
10831083

10841084
override Type getTypeImpl() { result = v.getType() }
@@ -1107,7 +1107,7 @@ private module ArgumentNodes {
11071107
override ControlFlow::Node getControlFlowNodeImpl() { result = cfn }
11081108

11091109
override DataFlowCallable getEnclosingCallableImpl() {
1110-
result.getUnderlyingCallable() = cfn.getEnclosingCallable()
1110+
result.asCallable() = cfn.getEnclosingCallable()
11111111
}
11121112

11131113
override Type getTypeImpl() { result = cfn.getElement().(Expr).getType() }
@@ -1146,7 +1146,7 @@ private module ArgumentNodes {
11461146
}
11471147

11481148
override DataFlowCallable getEnclosingCallableImpl() {
1149-
result.getUnderlyingCallable() = callCfn.getEnclosingCallable()
1149+
result.asCallable() = callCfn.getEnclosingCallable()
11501150
}
11511151

11521152
override Type getTypeImpl() { result = this.getParameter().getType() }
@@ -1227,7 +1227,7 @@ private module ReturnNodes {
12271227
override NormalReturnKind getKind() { any() }
12281228

12291229
override DataFlowCallable getEnclosingCallableImpl() {
1230-
result.getUnderlyingCallable() = yrs.getEnclosingCallable()
1230+
result.asCallable() = yrs.getEnclosingCallable()
12311231
}
12321232

12331233
override Type getTypeImpl() { result = yrs.getEnclosingCallable().getReturnType() }
@@ -1253,7 +1253,7 @@ private module ReturnNodes {
12531253
override NormalReturnKind getKind() { any() }
12541254

12551255
override DataFlowCallable getEnclosingCallableImpl() {
1256-
result.getUnderlyingCallable() = expr.getEnclosingCallable()
1256+
result.asCallable() = expr.getEnclosingCallable()
12571257
}
12581258

12591259
override Type getTypeImpl() { result = expr.getEnclosingCallable().getReturnType() }
@@ -1330,9 +1330,10 @@ private module ReturnNodes {
13301330
* In this case we adjust it to instead be a return node.
13311331
*/
13321332
private predicate summaryPostUpdateNodeIsOutOrRef(SummaryNode n, Parameter p) {
1333-
exists(ParameterNode pn |
1333+
exists(ParameterNodeImpl pn, DataFlowCallable c, ParameterPosition pos |
13341334
FlowSummaryImpl::Private::summaryPostUpdateNode(n, pn) and
1335-
pn.getParameter() = p and
1335+
pn.isParameterOf(c, pos) and
1336+
p = c.asSummarizedCallable().getParameter(pos.getPosition()) and
13361337
p.isOutOrRef()
13371338
)
13381339
}
@@ -1903,7 +1904,7 @@ private module PostUpdateNodes {
19031904
}
19041905

19051906
override DataFlowCallable getEnclosingCallableImpl() {
1906-
result.getUnderlyingCallable() = cfn.getEnclosingCallable()
1907+
result.asCallable() = cfn.getEnclosingCallable()
19071908
}
19081909

19091910
override DotNet::Type getTypeImpl() { result = oc.getType() }
@@ -1923,7 +1924,7 @@ private module PostUpdateNodes {
19231924
override ExprNode getPreUpdateNode() { cfn = result.getControlFlowNode() }
19241925

19251926
override DataFlowCallable getEnclosingCallableImpl() {
1926-
result.getUnderlyingCallable() = cfn.getEnclosingCallable()
1927+
result.asCallable() = cfn.getEnclosingCallable()
19271928
}
19281929

19291930
override Type getTypeImpl() { result = cfn.getElement().(Expr).getType() }
@@ -2012,12 +2013,11 @@ class LambdaCallKind = Unit;
20122013
/** Holds if `creation` is an expression that creates a delegate for `c`. */
20132014
predicate lambdaCreation(ExprNode creation, LambdaCallKind kind, DataFlowCallable c) {
20142015
exists(Expr e | e = creation.getExpr() |
2015-
c.getUnderlyingCallable() = e.(AnonymousFunctionExpr)
2016-
or
2017-
c.getUnderlyingCallable() = e.(CallableAccess).getTarget().getUnboundDeclaration()
2018-
or
2019-
c.getUnderlyingCallable() =
2020-
e.(AddressOfExpr).getOperand().(CallableAccess).getTarget().getUnboundDeclaration()
2016+
c.asCallable() =
2017+
[
2018+
e.(AnonymousFunctionExpr), e.(CallableAccess).getTarget().getUnboundDeclaration(),
2019+
e.(AddressOfExpr).getOperand().(CallableAccess).getTarget().getUnboundDeclaration()
2020+
]
20212021
) and
20222022
kind = TMkUnit()
20232023
}

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ class Node extends TNode {
4141

4242
/** Gets the enclosing callable of this node. */
4343
final Callable getEnclosingCallable() {
44-
result = this.(NodeImpl).getEnclosingCallableImpl().getUnderlyingCallable()
44+
result = this.(NodeImpl).getEnclosingCallableImpl().asCallable()
4545
}
4646

4747
/** Gets the control flow node corresponding to this node, if any. */
@@ -103,7 +103,7 @@ class ParameterNode extends Node instanceof ParameterNodeImpl {
103103
DotNet::Parameter getParameter() {
104104
exists(DataFlowCallable c, ParameterPosition ppos |
105105
super.isParameterOf(c, ppos) and
106-
result = c.getUnderlyingCallable().getParameter(ppos.getPosition())
106+
result = c.asCallable().getParameter(ppos.getPosition())
107107
)
108108
}
109109

csharp/ql/lib/semmle/code/csharp/exprs/Call.qll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -553,7 +553,7 @@ class DelegateLikeCall extends Call, DelegateLikeCall_ {
553553
final override Callable getARuntimeTarget() {
554554
exists(ExplicitDelegateLikeDataFlowCall call |
555555
this = call.getCall() and
556-
result = viableCallableLambda(call, _).getUnderlyingCallable()
556+
result = viableCallableLambda(call, _).asCallable()
557557
)
558558
}
559559

csharp/ql/src/utils/model-generator/internal/CaptureModelsSpecific.qll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ string returnNodeAsOutput(DataFlowImplCommon::ReturnNodeExt node) {
112112
* Gets the enclosing callable of `ret`.
113113
*/
114114
CS::Callable returnNodeEnclosingCallable(DataFlowImplCommon::ReturnNodeExt ret) {
115-
result = DataFlowImplCommon::getNodeEnclosingCallable(ret).getUnderlyingCallable()
115+
result = DataFlowImplCommon::getNodeEnclosingCallable(ret).asCallable()
116116
}
117117

118118
/**

0 commit comments

Comments
 (0)