Skip to content

Commit 5c38935

Browse files
committed
C#: Simplify delegate read and store steps (remove dependency on parameter).
1 parent a86cd18 commit 5c38935

File tree

3 files changed

+42
-103
lines changed

3 files changed

+42
-103
lines changed

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

Lines changed: 19 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -1148,17 +1148,10 @@ private module Cached {
11481148
p.getCallable() instanceof PrimaryConstructor
11491149
} or
11501150
TCapturedVariableContent(VariableCapture::CapturedVariable v) or
1151-
TDelegateCallArgumentContent(Parameter p, int i) {
1152-
i =
1153-
[0 .. p.getType()
1154-
.getUnboundDeclaration()
1155-
.(SystemLinqExpressions::DelegateExtType)
1156-
.getDelegateType()
1157-
.getNumberOfParameters() - 1]
1151+
TDelegateCallArgumentContent(int i) {
1152+
i = [0 .. max(int j | j = any(DelegateCall dc).getNumberOfArguments())]
11581153
} or
1159-
TDelegateCallReturnContent(Parameter p) {
1160-
p.getType().getUnboundDeclaration() instanceof SystemLinqExpressions::DelegateExtType
1161-
}
1154+
TDelegateCallReturnContent()
11621155

11631156
cached
11641157
newtype TContentSet =
@@ -1175,12 +1168,8 @@ private module Cached {
11751168
firstChar = approximatePrimaryConstructorParameterContent(_)
11761169
} or
11771170
TCapturedVariableContentApprox(VariableCapture::CapturedVariable v) or
1178-
TDelegateCallArgumentApproxContent(string firstChar) {
1179-
firstChar = approximateDelegateCallArgumentContent(_)
1180-
} or
1181-
TDelegateCallReturnApproxContent(string firstChar) {
1182-
firstChar = approximateDelegateCallReturnContent(_)
1183-
}
1171+
TDelegateCallArgumentApproxContent() or
1172+
TDelegateCallReturnApproxContent()
11841173

11851174
pragma[nomagic]
11861175
private predicate commonSubTypeGeneral(DataFlowTypeOrUnifiable t1, RelevantGvnType t2) {
@@ -2296,14 +2285,13 @@ private predicate recordProperty(RecordType t, ContentSet c, string name) {
22962285
* the content set `c` of a delegate call.
22972286
*
22982287
* If there is a delegate call f(x), then we store "x" on "f"
2299-
* using a delegate parameter content set.
2288+
* using a delegate argument content set.
23002289
*/
23012290
private predicate storeStepDelegateCall(Node node1, ContentSet c, Node node2) {
2302-
exists(DelegateCall call, Parameter p, int i |
2291+
exists(DelegateCall call, int i |
23032292
node1.asExpr() = call.getArgument(i) and
23042293
node2.(PostUpdateNode).getPreUpdateNode().asExpr() = call.getExpr() and
2305-
call.getExpr() = p.getAnAccess() and
2306-
c.isDelegateCallArgument(p, i)
2294+
c.isDelegateCallArgument(i)
23072295
)
23082296
}
23092297

@@ -2465,15 +2453,14 @@ private predicate readContentStep(Node node1, Content c, Node node2) {
24652453
* Holds if data can flow from `node1` to `node2` via an assignment to
24662454
* the content set `c` of a delegate call.
24672455
*
2468-
* If there is a delegate call f(x), then we read the result of the delegate
2456+
* If there is a delegate call f(x), then we read the return of the delegate
24692457
* call.
24702458
*/
24712459
private predicate readStepDelegateCall(Node node1, ContentSet c, Node node2) {
2472-
exists(DelegateCall call, Parameter p |
2460+
exists(DelegateCall call |
24732461
node1.asExpr() = call.getExpr() and
24742462
node2.asExpr() = call and
2475-
call.getExpr() = p.getAnAccess() and
2476-
c.isDelegateCallReturn(p)
2463+
c.isDelegateCallReturn()
24772464
)
24782465
}
24792466

@@ -3092,15 +3079,11 @@ class ContentApprox extends TContentApprox {
30923079
this = TCapturedVariableContentApprox(v) and result = "captured " + v
30933080
)
30943081
or
3095-
exists(string firstChar |
3096-
this = TDelegateCallArgumentApproxContent(firstChar) and
3097-
result = "approximated delegate call argument " + firstChar
3098-
)
3082+
this = TDelegateCallArgumentApproxContent() and
3083+
result = "approximated delegate call argument"
30993084
or
3100-
exists(string firstChar |
3101-
this = TDelegateCallReturnApproxContent(firstChar) and
3102-
result = "approximated delegate call return " + firstChar
3103-
)
3085+
this = TDelegateCallReturnApproxContent() and
3086+
result = "approximated delegate call return"
31043087
}
31053088
}
31063089

@@ -3122,22 +3105,6 @@ private string approximatePrimaryConstructorParameterContent(PrimaryConstructorP
31223105
result = pc.getParameter().getName().prefix(1)
31233106
}
31243107

3125-
private string getApproximateParameterName(Parameter p) {
3126-
exists(string name | name = p.getName() |
3127-
name = "" and result = ""
3128-
or
3129-
result = name.prefix(1)
3130-
)
3131-
}
3132-
3133-
private string approximateDelegateCallArgumentContent(DelegateCallArgumentContent dc) {
3134-
result = getApproximateParameterName(dc.getParameter())
3135-
}
3136-
3137-
private string approximateDelegateCallReturnContent(DelegateCallReturnContent dc) {
3138-
result = getApproximateParameterName(dc.getParameter())
3139-
}
3140-
31413108
/** Gets an approximated value for content `c`. */
31423109
pragma[nomagic]
31433110
ContentApprox getContentApprox(Content c) {
@@ -3154,9 +3121,11 @@ ContentApprox getContentApprox(Content c) {
31543121
or
31553122
result = TCapturedVariableContentApprox(VariableCapture::getCapturedVariableContent(c))
31563123
or
3157-
result = TDelegateCallArgumentApproxContent(approximateDelegateCallArgumentContent(c))
3124+
c instanceof DelegateCallArgumentContent and
3125+
result = TDelegateCallArgumentApproxContent()
31583126
or
3159-
result = TDelegateCallReturnApproxContent(approximateDelegateCallReturnContent(c))
3127+
c instanceof DelegateCallReturnContent and
3128+
result = TDelegateCallReturnApproxContent()
31603129
}
31613130

31623131
/**

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

Lines changed: 12 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -240,58 +240,27 @@ class PropertyContent extends Content, TPropertyContent {
240240
}
241241

242242
/**
243-
* A reference to the index of an argument of a delegate call
244-
* (where the delegate is a parameter)
243+
* A reference to the index of an argument of a delegate call.
245244
*/
246245
class DelegateCallArgumentContent extends Content, TDelegateCallArgumentContent {
247-
private Parameter p;
248246
private int i;
249247

250-
DelegateCallArgumentContent() { this = TDelegateCallArgumentContent(p, i) }
248+
DelegateCallArgumentContent() { this = TDelegateCallArgumentContent(i) }
251249

252-
/** Gets the underlying parameter. */
253-
Parameter getParameter() { result = p }
250+
override string toString() { result = "delegate argument at position " + i }
254251

255-
/**
256-
* Gets the type of the `i`th parameter of the underlying parameter `p`
257-
* (which is of delegate type).
258-
*/
259-
Type getType() {
260-
result =
261-
p.getType()
262-
.(SystemLinqExpressions::DelegateExtType)
263-
.getDelegateType()
264-
.getParameter(i)
265-
.getType()
266-
}
267-
268-
override string toString() { result = "delegate parameter " + p.getName() + " at position " + i }
269-
270-
override Location getLocation() { result = p.getLocation() }
252+
override Location getLocation() { result instanceof EmptyLocation }
271253
}
272254

273255
/**
274-
* A reference to the return of a delegate call
275-
* (where the delegate is a parameter)
256+
* A reference to the return of a delegate call.
276257
*/
277258
class DelegateCallReturnContent extends Content, TDelegateCallReturnContent {
278-
private Parameter p;
259+
DelegateCallReturnContent() { this = TDelegateCallReturnContent() }
279260

280-
DelegateCallReturnContent() { this = TDelegateCallReturnContent(p) }
261+
override string toString() { result = "delegate return" }
281262

282-
/** Gets the underlying parameter. */
283-
Parameter getParameter() { result = p }
284-
285-
/**
286-
* Gets the return type of the underlying parameter `p` (which is of delegate type).
287-
*/
288-
Type getType() {
289-
result = p.getType().(SystemLinqExpressions::DelegateExtType).getDelegateType().getReturnType()
290-
}
291-
292-
override string toString() { result = "delegate parameter " + p.getName() + " result" }
293-
294-
override Location getLocation() { result = p.getLocation() }
263+
override Location getLocation() { result instanceof EmptyLocation }
295264
}
296265

297266
/**
@@ -356,18 +325,14 @@ class ContentSet extends TContentSet {
356325
predicate isProperty(Property p) { this = TPropertyContentSet(p) }
357326

358327
/**
359-
* Holds if this content set represents the `i`th argument of
360-
* the parameter `p` of delegate type in a delegate call.
328+
* Holds if this content set represents the `i`th argument of a delegate call.
361329
*/
362-
predicate isDelegateCallArgument(Parameter p, int i) {
363-
this.isSingleton(TDelegateCallArgumentContent(p, i))
364-
}
330+
predicate isDelegateCallArgument(int i) { this.isSingleton(TDelegateCallArgumentContent(i)) }
365331

366332
/**
367-
* Holds if this content set represents the return of a delegate call
368-
* of parameter `p` (which is of delegate type).
333+
* Holds if this content set represents the return of a delegate call.
369334
*/
370-
predicate isDelegateCallReturn(Parameter p) { this.isSingleton(TDelegateCallReturnContent(p)) }
335+
predicate isDelegateCallReturn() { this.isSingleton(TDelegateCallReturnContent()) }
371336

372337
/** Holds if this content set represents the field `f`. */
373338
predicate isField(Field f) { this.isSingleton(TFieldContent(f)) }

csharp/ql/src/utils/modelgenerator/internal/CaptureModels.qll

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -176,10 +176,15 @@ module ModelGeneratorInput implements ModelGeneratorInputSig<Location, CsharpDat
176176
* Gets the underlying type of the content `c`.
177177
*/
178178
private CS::Type getUnderlyingContType(DataFlow::Content c) {
179-
result = c.(DataFlow::FieldContent).getField().getType() or
180-
result = c.(DataFlow::SyntheticFieldContent).getField().getType() or
181-
result = c.(DataFlow::DelegateCallArgumentContent).getType() or
182-
result = c.(DataFlow::DelegateCallReturnContent).getType()
179+
result = c.(DataFlow::FieldContent).getField().getType()
180+
or
181+
result = c.(DataFlow::SyntheticFieldContent).getField().getType()
182+
or
183+
// Use System.Object as the type of delegate arguments and returns as the content doesn't
184+
// contain any type information.
185+
c instanceof DataFlow::DelegateCallArgumentContent and result instanceof ObjectType
186+
or
187+
c instanceof DataFlow::DelegateCallReturnContent and result instanceof ObjectType
183188
}
184189

185190
Type getUnderlyingContentType(DataFlow::ContentSet c) {
@@ -347,9 +352,9 @@ module ModelGeneratorInput implements ModelGeneratorInputSig<Location, CsharpDat
347352
c.isElement() and
348353
result = "Element"
349354
or
350-
exists(int i | c.isDelegateCallArgument(_, i) and result = "Parameter[" + i + "]")
355+
exists(int i | c.isDelegateCallArgument(i) and result = "Parameter[" + i + "]")
351356
or
352-
c.isDelegateCallReturn(_) and result = "ReturnValue"
357+
c.isDelegateCallReturn() and result = "ReturnValue"
353358
}
354359

355360
predicate partialModel = ExternalFlow::partialModel/6;

0 commit comments

Comments
 (0)