Skip to content

Commit 4c8861a

Browse files
authored
Merge pull request github#14832 from hvitved/csharp/callback-heuristics
C#: Strengthen call-back heuristics by considering body-less methods
2 parents e028c59 + 23d09ed commit 4c8861a

File tree

9 files changed

+46
-38
lines changed

9 files changed

+46
-38
lines changed

csharp/ql/lib/semmle/code/csharp/Callable.qll

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,10 @@ class Callable extends DotNet::Callable, Parameterizable, ExprOrStmtParent, @cal
105105
* then both `{ return 0; }` and `{ return 1; }` are statement bodies of
106106
* `N.C.M()`.
107107
*/
108-
final BlockStmt getStatementBody() { result = this.getAChildStmt() }
108+
final BlockStmt getStatementBody() {
109+
result = getStatementBody(this) and
110+
not this.getFile().isStub()
111+
}
109112

110113
/**
111114
* DEPRECATED: Use `getStatementBody` instead.
@@ -143,8 +146,8 @@ class Callable extends DotNet::Callable, Parameterizable, ExprOrStmtParent, @cal
143146
* then both `0` and `1` are expression bodies of `N.C.M()`.
144147
*/
145148
final Expr getExpressionBody() {
146-
result = this.getAChildExpr() and
147-
not result = this.(Constructor).getInitializer()
149+
result = getExpressionBody(this) and
150+
not this.getFile().isStub()
148151
}
149152

150153
/** Holds if this callable has an expression body. */

csharp/ql/lib/semmle/code/csharp/ExprOrStmtParent.qll

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,20 @@ class TopLevelExprParent extends Element, @top_level_expr_parent {
5353

5454
private predicate hasNoSourceLocation(Element e) { not e.getALocation() instanceof SourceLocation }
5555

56+
/** INTERNAL: Do not use. */
57+
Expr getExpressionBody(Callable c) {
58+
result = c.getAChildExpr() and
59+
not result = c.(Constructor).getInitializer()
60+
}
61+
62+
/** INTERNAL: Do not use. */
63+
BlockStmt getStatementBody(Callable c) { result = c.getAChildStmt() }
64+
65+
private ControlFlowElement getBody(Callable c) {
66+
result = getExpressionBody(c) or
67+
result = getStatementBody(c)
68+
}
69+
5670
cached
5771
private module Cached {
5872
cached
@@ -161,20 +175,20 @@ private module Cached {
161175

162176
private predicate parent(ControlFlowElement child, ExprOrStmtParent parent) {
163177
child = getAChild(parent) and
164-
not child = any(Callable c).getBody()
178+
not child = getBody(_)
165179
}
166180

167181
/** Holds if the enclosing body of `cfe` is `body`. */
168182
cached
169183
predicate enclosingBody(ControlFlowElement cfe, ControlFlowElement body) {
170-
body = any(Callable c).getBody() and
184+
body = getBody(_) and
171185
parent*(enclosingStart(cfe), body)
172186
}
173187

174188
/** Holds if the enclosing callable of `cfe` is `c`. */
175189
cached
176190
predicate enclosingCallable(ControlFlowElement cfe, Callable c) {
177-
enclosingBody(cfe, c.getBody())
191+
enclosingBody(cfe, getBody(c))
178192
or
179193
parent*(enclosingStart(cfe), c.(Constructor).getInitializer())
180194
}

csharp/ql/lib/semmle/code/csharp/File.qll

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,14 +54,14 @@ class File extends Container, Impl::File {
5454

5555
/** Holds if this file is a QL test stub file. */
5656
pragma[noinline]
57-
private predicate isStub() {
57+
predicate isStub() {
5858
this.extractedQlTest() and
5959
this.getAbsolutePath().matches("%resources/stubs/%")
6060
}
6161

6262
/** Holds if this file contains source code. */
6363
final predicate fromSource() {
64-
this.getExtension() = "cs" and
64+
this.getExtension() = ["cs", "cshtml"] and
6565
not this.isStub()
6666
}
6767

csharp/ql/lib/semmle/code/csharp/controlflow/internal/ControlFlowGraphImpl.qll

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,14 @@ private import semmle.code.csharp.commons.Compilation
1313
/** An element that defines a new CFG scope. */
1414
class CfgScope extends Element, @top_level_exprorstmt_parent {
1515
CfgScope() {
16-
this instanceof Callable
17-
or
18-
// For now, static initializer values have their own scope. Eventually, they
19-
// should be treated like instance initializers.
20-
this.(Assignable).(Modifiable).isStatic()
16+
this.getFile().fromSource() and
17+
(
18+
this instanceof Callable
19+
or
20+
// For now, static initializer values have their own scope. Eventually, they
21+
// should be treated like instance initializers.
22+
this.(Assignable).(Modifiable).isStatic()
23+
)
2124
}
2225
}
2326

csharp/ql/lib/semmle/code/csharp/dataflow/FlowSummary.qll

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,8 @@ private SummaryComponent delegateSelf() {
168168

169169
private predicate mayInvokeCallback(Callable c, int n) {
170170
c.getParameter(n).getType() instanceof SystemLinqExpressions::DelegateExtType and
171-
not c.fromSource()
171+
not c.hasBody() and
172+
(if c instanceof Accessor then not c.fromSource() else any())
172173
}
173174

174175
private class SummarizedCallableWithCallback extends SummarizedCallable {

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -81,9 +81,9 @@ newtype TReturnKind =
8181
*/
8282
class DataFlowSummarizedCallable instanceof FlowSummary::SummarizedCallable {
8383
DataFlowSummarizedCallable() {
84-
not this.fromSource()
84+
not this.hasBody()
8585
or
86-
this.fromSource() and not this.applyGeneratedModel()
86+
this.hasBody() and not this.applyGeneratedModel()
8787
}
8888

8989
string toString() { result = super.toString() }

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

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -310,7 +310,12 @@ private module CallGraph {
310310
c = any(DelegateCall dc | e = dc.getExpr()) and
311311
libraryDelegateCall = false
312312
or
313-
c.getTarget().fromLibrary() and
313+
exists(Callable target |
314+
target = c.getTarget() and
315+
not target.hasBody()
316+
|
317+
if target instanceof Accessor then not target.fromSource() else any()
318+
) and
314319
e = c.getAnArgument() and
315320
e.getType() instanceof SystemLinqExpressions::DelegateExtType and
316321
libraryDelegateCall = true

csharp/ql/test/library-tests/dataflow/external-models/ExternalFlow.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -185,16 +185,16 @@ public class G
185185
void M1()
186186
{
187187
var o = new object();
188-
Sink(GeneratedFlow(o));
188+
Sink(GeneratedFlow(o)); // no flow because the modelled method exists in source code
189189
}
190190

191191
void M2()
192192
{
193193
var o1 = new object();
194-
Sink(GeneratedFlowArgs(o1, null));
194+
Sink(GeneratedFlowArgs(o1, null)); // no flow because the modelled method exists in source code
195195

196196
var o2 = new object();
197-
Sink(GeneratedFlowArgs(null, o2));
197+
Sink(GeneratedFlowArgs(null, o2)); // no flow because the modelled method exists in source code
198198
}
199199

200200
void M3()

csharp/ql/test/library-tests/dataflow/external-models/ExternalFlow.expected

Lines changed: 0 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -61,12 +61,6 @@ edges
6161
| ExternalFlow.cs:118:21:118:30 | call to method Reverse : null [element] : Object | ExternalFlow.cs:120:18:120:18 | access to local variable b : null [element] : Object |
6262
| ExternalFlow.cs:118:29:118:29 | access to local variable a : null [element] : Object | ExternalFlow.cs:118:21:118:30 | call to method Reverse : null [element] : Object |
6363
| ExternalFlow.cs:120:18:120:18 | access to local variable b : null [element] : Object | ExternalFlow.cs:120:18:120:21 | access to array element |
64-
| ExternalFlow.cs:187:21:187:32 | object creation of type Object : Object | ExternalFlow.cs:188:32:188:32 | access to local variable o : Object |
65-
| ExternalFlow.cs:188:32:188:32 | access to local variable o : Object | ExternalFlow.cs:188:18:188:33 | call to method GeneratedFlow |
66-
| ExternalFlow.cs:193:22:193:33 | object creation of type Object : Object | ExternalFlow.cs:194:36:194:37 | access to local variable o1 : Object |
67-
| ExternalFlow.cs:194:36:194:37 | access to local variable o1 : Object | ExternalFlow.cs:194:18:194:44 | call to method GeneratedFlowArgs |
68-
| ExternalFlow.cs:196:22:196:33 | object creation of type Object : Object | ExternalFlow.cs:197:42:197:43 | access to local variable o2 : Object |
69-
| ExternalFlow.cs:197:42:197:43 | access to local variable o2 : Object | ExternalFlow.cs:197:18:197:44 | call to method GeneratedFlowArgs |
7064
| ExternalFlow.cs:205:22:205:33 | object creation of type Object : Object | ExternalFlow.cs:206:38:206:39 | access to local variable o2 : Object |
7165
| ExternalFlow.cs:206:38:206:39 | access to local variable o2 : Object | ExternalFlow.cs:206:18:206:40 | call to method MixedFlowArgs |
7266
| ExternalFlow.cs:231:21:231:28 | object creation of type HC : HC | ExternalFlow.cs:232:21:232:21 | access to local variable h : HC |
@@ -151,15 +145,6 @@ nodes
151145
| ExternalFlow.cs:118:29:118:29 | access to local variable a : null [element] : Object | semmle.label | access to local variable a : null [element] : Object |
152146
| ExternalFlow.cs:120:18:120:18 | access to local variable b : null [element] : Object | semmle.label | access to local variable b : null [element] : Object |
153147
| ExternalFlow.cs:120:18:120:21 | access to array element | semmle.label | access to array element |
154-
| ExternalFlow.cs:187:21:187:32 | object creation of type Object : Object | semmle.label | object creation of type Object : Object |
155-
| ExternalFlow.cs:188:18:188:33 | call to method GeneratedFlow | semmle.label | call to method GeneratedFlow |
156-
| ExternalFlow.cs:188:32:188:32 | access to local variable o : Object | semmle.label | access to local variable o : Object |
157-
| ExternalFlow.cs:193:22:193:33 | object creation of type Object : Object | semmle.label | object creation of type Object : Object |
158-
| ExternalFlow.cs:194:18:194:44 | call to method GeneratedFlowArgs | semmle.label | call to method GeneratedFlowArgs |
159-
| ExternalFlow.cs:194:36:194:37 | access to local variable o1 : Object | semmle.label | access to local variable o1 : Object |
160-
| ExternalFlow.cs:196:22:196:33 | object creation of type Object : Object | semmle.label | object creation of type Object : Object |
161-
| ExternalFlow.cs:197:18:197:44 | call to method GeneratedFlowArgs | semmle.label | call to method GeneratedFlowArgs |
162-
| ExternalFlow.cs:197:42:197:43 | access to local variable o2 : Object | semmle.label | access to local variable o2 : Object |
163148
| ExternalFlow.cs:205:22:205:33 | object creation of type Object : Object | semmle.label | object creation of type Object : Object |
164149
| ExternalFlow.cs:206:18:206:40 | call to method MixedFlowArgs | semmle.label | call to method MixedFlowArgs |
165150
| ExternalFlow.cs:206:38:206:39 | access to local variable o2 : Object | semmle.label | access to local variable o2 : Object |
@@ -189,8 +174,5 @@ subpaths
189174
| ExternalFlow.cs:104:18:104:25 | access to field Field | ExternalFlow.cs:98:24:98:35 | object creation of type Object : Object | ExternalFlow.cs:104:18:104:25 | access to field Field | $@ | ExternalFlow.cs:98:24:98:35 | object creation of type Object : Object | object creation of type Object : Object |
190175
| ExternalFlow.cs:112:18:112:25 | access to property MyProp | ExternalFlow.cs:111:24:111:35 | object creation of type Object : Object | ExternalFlow.cs:112:18:112:25 | access to property MyProp | $@ | ExternalFlow.cs:111:24:111:35 | object creation of type Object : Object | object creation of type Object : Object |
191176
| ExternalFlow.cs:120:18:120:21 | access to array element | ExternalFlow.cs:117:36:117:47 | object creation of type Object : Object | ExternalFlow.cs:120:18:120:21 | access to array element | $@ | ExternalFlow.cs:117:36:117:47 | object creation of type Object : Object | object creation of type Object : Object |
192-
| ExternalFlow.cs:188:18:188:33 | call to method GeneratedFlow | ExternalFlow.cs:187:21:187:32 | object creation of type Object : Object | ExternalFlow.cs:188:18:188:33 | call to method GeneratedFlow | $@ | ExternalFlow.cs:187:21:187:32 | object creation of type Object : Object | object creation of type Object : Object |
193-
| ExternalFlow.cs:194:18:194:44 | call to method GeneratedFlowArgs | ExternalFlow.cs:193:22:193:33 | object creation of type Object : Object | ExternalFlow.cs:194:18:194:44 | call to method GeneratedFlowArgs | $@ | ExternalFlow.cs:193:22:193:33 | object creation of type Object : Object | object creation of type Object : Object |
194-
| ExternalFlow.cs:197:18:197:44 | call to method GeneratedFlowArgs | ExternalFlow.cs:196:22:196:33 | object creation of type Object : Object | ExternalFlow.cs:197:18:197:44 | call to method GeneratedFlowArgs | $@ | ExternalFlow.cs:196:22:196:33 | object creation of type Object : Object | object creation of type Object : Object |
195177
| ExternalFlow.cs:206:18:206:40 | call to method MixedFlowArgs | ExternalFlow.cs:205:22:205:33 | object creation of type Object : Object | ExternalFlow.cs:206:18:206:40 | call to method MixedFlowArgs | $@ | ExternalFlow.cs:205:22:205:33 | object creation of type Object : Object | object creation of type Object : Object |
196178
| ExternalFlow.cs:233:18:233:18 | access to local variable o | ExternalFlow.cs:231:21:231:28 | object creation of type HC : HC | ExternalFlow.cs:233:18:233:18 | access to local variable o | $@ | ExternalFlow.cs:231:21:231:28 | object creation of type HC : HC | object creation of type HC : HC |

0 commit comments

Comments
 (0)