Skip to content

Commit 46f10fc

Browse files
committed
C#: Restrict DataFlowType to types belonging to Nodes
1 parent 1f432dc commit 46f10fc

File tree

2 files changed

+45
-21
lines changed

2 files changed

+45
-21
lines changed

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

Lines changed: 39 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ abstract class NodeImpl extends Node {
2626

2727
/** Gets the type of this node used for type pruning. */
2828
cached
29-
DataFlowType getDataFlowType() {
29+
Gvn::GvnType getDataFlowType() {
3030
Stages::DataFlowStage::forceCachingInSameStage() and
3131
exists(Type t0 | result = Gvn::getGlobalValueNumber(t0) |
3232
t0 = getCSharpType(this.getType())
@@ -490,14 +490,23 @@ private Type getCSharpType(DotNet::Type t) {
490490
result.matchesHandle(t)
491491
}
492492

493+
/** A GVN type that is either a `DataFlowType` or unifiable with a `DataFlowType`. */
494+
private class DataFlowTypeOrUnifiable extends Gvn::GvnType {
495+
pragma[nomagic]
496+
DataFlowTypeOrUnifiable() {
497+
this instanceof DataFlowType or
498+
Gvn::unifiable(any(DataFlowType t), this)
499+
}
500+
}
501+
493502
pragma[noinline]
494-
private TypeParameter getATypeParameterSubType(DataFlowType t) {
503+
private TypeParameter getATypeParameterSubType(DataFlowTypeOrUnifiable t) {
495504
not t instanceof Gvn::TypeParameterGvnType and
496505
exists(Type t0 | t = Gvn::getGlobalValueNumber(t0) | implicitConversionRestricted(result, t0))
497506
}
498507

499508
pragma[noinline]
500-
private DataFlowType getANonTypeParameterSubType(DataFlowType t) {
509+
private Gvn::GvnType getANonTypeParameterSubType(DataFlowTypeOrUnifiable t) {
501510
not t instanceof Gvn::TypeParameterGvnType and
502511
not result instanceof Gvn::TypeParameterGvnType and
503512
exists(Type t1, Type t2 |
@@ -728,12 +737,8 @@ private module Cached {
728737
)
729738
}
730739

731-
/**
732-
* Holds if GVNs `t1` and `t2` may have a common sub type. Neither `t1` nor
733-
* `t2` are allowed to be type parameters.
734-
*/
735-
cached
736-
predicate commonSubType(DataFlowType t1, DataFlowType t2) {
740+
pragma[nomagic]
741+
private predicate commonSubTypeGeneral(DataFlowTypeOrUnifiable t1, DataFlowType t2) {
737742
not t1 instanceof Gvn::TypeParameterGvnType and
738743
t1 = t2
739744
or
@@ -742,11 +747,18 @@ private module Cached {
742747
getANonTypeParameterSubType(t1) = getANonTypeParameterSubType(t2)
743748
}
744749

750+
/**
751+
* Holds if GVNs `t1` and `t2` may have a common sub type. Neither `t1` nor
752+
* `t2` are allowed to be type parameters.
753+
*/
754+
cached
755+
predicate commonSubType(DataFlowType t1, DataFlowType t2) { commonSubTypeGeneral(t1, t2) }
756+
745757
cached
746758
predicate commonSubTypeUnifiableLeft(DataFlowType t1, DataFlowType t2) {
747-
exists(DataFlowType t |
759+
exists(Gvn::GvnType t |
748760
Gvn::unifiable(t1, t) and
749-
commonSubType(t, t2)
761+
commonSubTypeGeneral(t, t2)
750762
)
751763
}
752764

@@ -2004,7 +2016,7 @@ module LibraryFlow {
20042016

20052017
/** Gets the type of content `c`. */
20062018
pragma[noinline]
2007-
private DataFlowType getContentType(Content c) {
2019+
private Gvn::GvnType getContentType(Content c) {
20082020
exists(Type t | result = Gvn::getGlobalValueNumber(t) |
20092021
t = c.(FieldContent).getField().getType()
20102022
or
@@ -2031,7 +2043,7 @@ class LibraryCodeNode extends NodeImpl, TLibraryCodeNode {
20312043

20322044
override Callable getEnclosingCallableImpl() { result = callCfn.getEnclosingCallable() }
20332045

2034-
override DataFlowType getDataFlowType() {
2046+
override Gvn::GvnType getDataFlowType() {
20352047
exists(LibraryFlow::AdjustedAccessPath ap |
20362048
state = LibraryFlow::TLibraryCodeNodeAfterReadState(ap) and
20372049
if sinkAp.length() = 0 and state.isLastReadState() and preservesValue = true
@@ -2194,6 +2206,20 @@ private class ReadStepConfiguration extends ControlFlowReachabilityConfiguration
21942206

21952207
predicate readStep = readStepImpl/3;
21962208

2209+
/**
2210+
* An entity used to represent the type of data-flow node. Two nodes will have
2211+
* the same `DataFlowType` when the underlying `Type`s are structurally equal
2212+
* modulo type parameters and identity conversions.
2213+
*
2214+
* For example, `Func<T, int>` and `Func<S, int>` are mapped to the same
2215+
* `DataFlowType`, while `Func<T, int>` and `Func<string, int>` are not, because
2216+
* `string` is not a type parameter.
2217+
*/
2218+
class DataFlowType extends Gvn::GvnType {
2219+
pragma[nomagic]
2220+
DataFlowType() { this = any(NodeImpl n).getDataFlowType() }
2221+
}
2222+
21972223
/** Gets the type of `n` used for type pruning. */
21982224
DataFlowType getNodeType(NodeImpl n) { result = n.getDataFlowType() }
21992225

@@ -2323,8 +2349,6 @@ class CastNode extends Node {
23232349

23242350
class DataFlowExpr = DotNet::Expr;
23252351

2326-
class DataFlowType = Gvn::GvnType;
2327-
23282352
/** Holds if `e` is an expression that always has the same Boolean value `val`. */
23292353
private predicate constantBooleanExpr(Expr e, boolean val) {
23302354
e = any(AbstractValues::BooleanValue bv | val = bv.getValue()).getAnExpr()

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

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -222,10 +222,10 @@ class Content extends TContent {
222222
Location getLocation() { none() }
223223

224224
/** Gets the type of the object containing this content. */
225-
deprecated DataFlowType getContainerType() { none() }
225+
deprecated Gvn::GvnType getContainerType() { none() }
226226

227227
/** Gets the type of this content. */
228-
deprecated DataFlowType getType() { none() }
228+
deprecated Gvn::GvnType getType() { none() }
229229
}
230230

231231
/** A reference to a field. */
@@ -241,11 +241,11 @@ class FieldContent extends Content, TFieldContent {
241241

242242
override Location getLocation() { result = f.getLocation() }
243243

244-
deprecated override DataFlowType getContainerType() {
244+
deprecated override Gvn::GvnType getContainerType() {
245245
result = Gvn::getGlobalValueNumber(f.getDeclaringType())
246246
}
247247

248-
deprecated override DataFlowType getType() { result = Gvn::getGlobalValueNumber(f.getType()) }
248+
deprecated override Gvn::GvnType getType() { result = Gvn::getGlobalValueNumber(f.getType()) }
249249
}
250250

251251
/** A reference to a property. */
@@ -261,11 +261,11 @@ class PropertyContent extends Content, TPropertyContent {
261261

262262
override Location getLocation() { result = p.getLocation() }
263263

264-
deprecated override DataFlowType getContainerType() {
264+
deprecated override Gvn::GvnType getContainerType() {
265265
result = Gvn::getGlobalValueNumber(p.getDeclaringType())
266266
}
267267

268-
deprecated override DataFlowType getType() { result = Gvn::getGlobalValueNumber(p.getType()) }
268+
deprecated override Gvn::GvnType getType() { result = Gvn::getGlobalValueNumber(p.getType()) }
269269
}
270270

271271
/** A reference to an element in a collection. */

0 commit comments

Comments
 (0)