Skip to content

Commit f49bfa7

Browse files
committed
C#: Deprecate Assignable(Read)::getAReachableRead
1 parent d389a18 commit f49bfa7

File tree

5 files changed

+61
-30
lines changed

5 files changed

+61
-30
lines changed

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

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,7 @@ class AssignableRead extends AssignableAccess {
111111
* - The reads of `i` on lines 7 and 8 are next to the read on line 6.
112112
* - The read of `this.Field` on line 11 is next to the read on line 10.
113113
*/
114+
pragma[nomagic]
114115
AssignableRead getANextRead() {
115116
forex(ControlFlow::Node cfn | cfn = result.getAControlFlowNode() |
116117
cfn = this.getAnAdjacentReadSameVar()
@@ -124,7 +125,7 @@ class AssignableRead extends AssignableAccess {
124125
*
125126
* This is the transitive closure of `getANextRead()`.
126127
*/
127-
AssignableRead getAReachableRead() { result = this.getANextRead+() }
128+
deprecated AssignableRead getAReachableRead() { result = this.getANextRead+() }
128129
}
129130

130131
/**
@@ -479,6 +480,7 @@ class AssignableDefinition extends TAssignableDefinition {
479480
* Subsequent reads can be found by following the steps defined by
480481
* `AssignableRead.getANextRead()`.
481482
*/
483+
pragma[nomagic]
482484
AssignableRead getAFirstRead() {
483485
forex(ControlFlow::Node cfn | cfn = result.getAControlFlowNode() |
484486
exists(Ssa::ExplicitDefinition def | result = def.getAFirstReadAtNode(cfn) |
@@ -494,7 +496,7 @@ class AssignableDefinition extends TAssignableDefinition {
494496
*
495497
* This is the equivalent with `getAFirstRead().getANextRead*()`.
496498
*/
497-
AssignableRead getAReachableRead() { result = this.getAFirstRead().getANextRead*() }
499+
deprecated AssignableRead getAReachableRead() { result = this.getAFirstRead().getANextRead*() }
498500

499501
/** Gets a textual representation of this assignable definition. */
500502
string toString() { none() }

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

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -174,7 +174,9 @@ class VariableAccess extends AssignableAccess, @variable_access_expr {
174174
class VariableRead extends VariableAccess, AssignableRead {
175175
override VariableRead getANextRead() { result = AssignableRead.super.getANextRead() }
176176

177-
override VariableRead getAReachableRead() { result = AssignableRead.super.getAReachableRead() }
177+
deprecated override VariableRead getAReachableRead() {
178+
result = AssignableRead.super.getAReachableRead()
179+
}
178180
}
179181

180182
/**
@@ -200,7 +202,7 @@ class LocalScopeVariableAccess extends VariableAccess, @local_scope_variable_acc
200202
class LocalScopeVariableRead extends LocalScopeVariableAccess, VariableRead {
201203
override LocalScopeVariableRead getANextRead() { result = VariableRead.super.getANextRead() }
202204

203-
override LocalScopeVariableRead getAReachableRead() {
205+
deprecated override LocalScopeVariableRead getAReachableRead() {
204206
result = VariableRead.super.getAReachableRead()
205207
}
206208
}
@@ -242,7 +244,7 @@ class ParameterAccess extends LocalScopeVariableAccess, @parameter_access_expr {
242244
class ParameterRead extends ParameterAccess, LocalScopeVariableRead {
243245
override ParameterRead getANextRead() { result = LocalScopeVariableRead.super.getANextRead() }
244246

245-
override ParameterRead getAReachableRead() {
247+
deprecated override ParameterRead getAReachableRead() {
246248
result = LocalScopeVariableRead.super.getAReachableRead()
247249
}
248250
}
@@ -297,7 +299,7 @@ class LocalVariableAccess extends LocalScopeVariableAccess, @local_variable_acce
297299
class LocalVariableRead extends LocalVariableAccess, LocalScopeVariableRead {
298300
override LocalVariableRead getANextRead() { result = LocalScopeVariableRead.super.getANextRead() }
299301

300-
override LocalVariableRead getAReachableRead() {
302+
deprecated override LocalVariableRead getAReachableRead() {
301303
result = LocalScopeVariableRead.super.getAReachableRead()
302304
}
303305
}
@@ -442,7 +444,9 @@ class PropertyAccess extends AssignableMemberAccess, PropertyAccessExpr {
442444
class PropertyRead extends PropertyAccess, AssignableRead {
443445
override PropertyRead getANextRead() { result = AssignableRead.super.getANextRead() }
444446

445-
override PropertyRead getAReachableRead() { result = AssignableRead.super.getAReachableRead() }
447+
deprecated override PropertyRead getAReachableRead() {
448+
result = AssignableRead.super.getAReachableRead()
449+
}
446450
}
447451

448452
/**
@@ -581,7 +585,9 @@ class IndexerAccess extends AssignableMemberAccess, ElementAccess, IndexerAccess
581585
class IndexerRead extends IndexerAccess, ElementRead {
582586
override IndexerRead getANextRead() { result = ElementRead.super.getANextRead() }
583587

584-
override IndexerRead getAReachableRead() { result = ElementRead.super.getAReachableRead() }
588+
deprecated override IndexerRead getAReachableRead() {
589+
result = ElementRead.super.getAReachableRead()
590+
}
585591
}
586592

587593
/**

csharp/ql/lib/semmle/code/csharp/frameworks/Format.qll

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,20 @@ class FormatMethod extends Method {
7171
}
7272
}
7373

74+
pragma[nomagic]
75+
private predicate parameterReadPostDominatesEntry(ParameterRead pr) {
76+
pr.getAControlFlowNode().postDominates(pr.getEnclosingCallable().getEntryPoint()) and
77+
getParameterType(pr.getTarget()) instanceof ObjectType
78+
}
79+
80+
pragma[nomagic]
81+
private predicate alwaysPassedToFormatItemParameter(ParameterRead pr) {
82+
pr = any(StringFormatItemParameter other).getAnAssignedArgument() and
83+
parameterReadPostDominatesEntry(pr)
84+
or
85+
alwaysPassedToFormatItemParameter(pr.getANextRead())
86+
}
87+
7488
/**
7589
* A parameter that is used as a format item for `string.Format()`. Either a
7690
* format item parameter of `string.Format()`, or a parameter of a method that
@@ -85,15 +99,9 @@ class StringFormatItemParameter extends Parameter {
8599
)
86100
or
87101
// Parameter of a source method that forwards to `string.Format()`
88-
exists(
89-
AssignableDefinitions::ImplicitParameterDefinition def, ParameterRead pr,
90-
StringFormatItemParameter other
91-
|
102+
exists(AssignableDefinitions::ImplicitParameterDefinition def |
92103
def.getParameter() = this and
93-
pr = def.getAReachableRead() and
94-
pr.getAControlFlowNode().postDominates(this.getCallable().getEntryPoint()) and
95-
other.getAnAssignedArgument() = pr and
96-
getParameterType(this) instanceof ObjectType
104+
alwaysPassedToFormatItemParameter(def.getAFirstRead())
97105
)
98106
}
99107
}

csharp/ql/src/API Abuse/DisposeNotCalledOnException.ql

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,12 +22,22 @@ private class DisposeCall extends MethodCall {
2222
DisposeCall() { this.getTarget() instanceof DisposeMethod }
2323
}
2424

25-
private predicate localFlowStep(DataFlow::Node nodeFrom, DataFlow::Node nodeTo) {
26-
DataFlow::localFlowStep(nodeFrom, nodeTo) and
27-
not exists(AssignableDefinition def, UsingStmt us |
28-
nodeTo.asExpr() = def.getAReachableRead() and
25+
pragma[nomagic]
26+
private predicate isDisposedAccess(AssignableRead ar) {
27+
exists(AssignableDefinition def, UsingStmt us |
28+
ar = def.getAFirstRead() and
2929
def.getTargetAccess() = us.getAVariableDeclExpr().getAccess()
3030
)
31+
or
32+
exists(AssignableRead mid |
33+
isDisposedAccess(mid) and
34+
ar = mid.getANextRead()
35+
)
36+
}
37+
38+
private predicate localFlowStep(DataFlow::Node nodeFrom, DataFlow::Node nodeTo) {
39+
DataFlow::localFlowStep(nodeFrom, nodeTo) and
40+
not isDisposedAccess(nodeTo.asExpr())
3141
}
3242

3343
private predicate reachesDisposeCall(DisposeCall disposeCall, DataFlow::Node node) {

csharp/ql/src/Useless code/DefaultToStringQuery.qll

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import semmle.code.csharp.frameworks.System
66
* Holds if expression `e`, of type `t`, invokes `ToString()` either explicitly
77
* or implicitly.
88
*/
9+
pragma[nomagic]
910
predicate invokesToString(Expr e, ValueOrRefType t) {
1011
// Explicit invocation
1112
exists(MethodCall mc | mc.getQualifier() = e |
@@ -20,20 +21,24 @@ predicate invokesToString(Expr e, ValueOrRefType t) {
2021
// Implicit invocation via forwarder method
2122
t = e.stripCasts().getType() and
2223
not t instanceof StringType and
23-
exists(Parameter p |
24-
alwaysInvokesToStringOnParameter(p) and
24+
exists(AssignableDefinitions::ImplicitParameterDefinition def, Parameter p |
25+
def.getParameter() = p and
26+
alwaysInvokesToString(def.getAFirstRead()) and
2527
e = p.getAnAssignedArgument()
2628
)
2729
}
2830

29-
pragma[noinline]
30-
private predicate alwaysInvokesToStringOnParameter(Parameter p) {
31-
exists(AssignableDefinitions::ImplicitParameterDefinition def, ParameterRead pr |
32-
def.getParameter() = p and
33-
pr = def.getAReachableRead() and
34-
pr.getAControlFlowNode().postDominates(p.getCallable().getEntryPoint()) and
35-
invokesToString(pr, _)
36-
)
31+
pragma[nomagic]
32+
private predicate parameterReadPostDominatesEntry(ParameterRead pr) {
33+
pr.getAControlFlowNode().postDominates(pr.getEnclosingCallable().getEntryPoint())
34+
}
35+
36+
pragma[nomagic]
37+
private predicate alwaysInvokesToString(ParameterRead pr) {
38+
parameterReadPostDominatesEntry(pr) and
39+
invokesToString(pr, _)
40+
or
41+
alwaysInvokesToString(pr.getANextRead())
3742
}
3843

3944
/**

0 commit comments

Comments
 (0)