Skip to content

Commit 212b49f

Browse files
authored
Merge pull request #4416 from hvitved/csharp/dataflow/tuples
C#: Add flow summaries for `System.[Value]Tuple`
2 parents e825af2 + 29fb23e commit 212b49f

File tree

4 files changed

+458
-3
lines changed

4 files changed

+458
-3
lines changed

csharp/ql/src/semmle/code/csharp/Type.qll

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -258,8 +258,11 @@ class ValueOrRefType extends DotNet::ValueOrRefType, Type, Attributable, @value_
258258
getAMember().(Virtualizable).getOverridee() = v
259259
}
260260

261+
/** Gets a field (or member constant) with the given name. */
262+
Field getField(string name) { result = getAMember() and result.hasName(name) }
263+
261264
/** Gets a field (or member constant) of this type, if any. */
262-
Field getAField() { result = getAMember() }
265+
Field getAField() { result = this.getField(_) }
263266

264267
/** Gets a member constant of this type, if any. */
265268
MemberConstant getAConstant() { result = getAMember() }

csharp/ql/src/semmle/code/csharp/dataflow/LibraryTypeDataFlow.qll

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1653,6 +1653,62 @@ class SystemCollectionsGenericKeyValuePairStructFlow extends LibraryTypeDataFlow
16531653
}
16541654
}
16551655

1656+
/** Data flow for `System.[Value]Tuple<,...,>`. */
1657+
class SystemTupleFlow extends LibraryTypeDataFlow, ValueOrRefType {
1658+
SystemTupleFlow() {
1659+
this.getNamespace() instanceof SystemNamespace and
1660+
this.getName().regexpMatch("(Value)?Tuple(<,*>)?")
1661+
or
1662+
this instanceof TupleType
1663+
}
1664+
1665+
private AccessPath getItemAccessPath(int i) {
1666+
i in [1 .. count(this.getAMember())] and
1667+
result in [AccessPath::field(this.getField("Item" + i)),
1668+
AccessPath::property(this.getProperty("Item" + i))]
1669+
}
1670+
1671+
override predicate callableFlow(
1672+
CallableFlowSource source, AccessPath sourceAp, CallableFlowSink sink, AccessPath sinkAp,
1673+
SourceDeclarationCallable c, boolean preservesValue
1674+
) {
1675+
preservesValue = true and
1676+
(
1677+
exists(SystemTupleFlow t, int i |
1678+
source = getFlowSourceArg(c, i - 1, _) and
1679+
sourceAp = AccessPath::empty() and
1680+
sink = TCallableFlowSinkReturn() and
1681+
sinkAp = t.getItemAccessPath(i)
1682+
|
1683+
c.(Constructor).getDeclaringType() = this and
1684+
t = this
1685+
or
1686+
c = this.getAMethod(any(string name | name.regexpMatch("Create(<,*>)?"))) and
1687+
t = c.getReturnType().getSourceDeclaration()
1688+
)
1689+
or
1690+
c =
1691+
any(ExtensionMethod m |
1692+
m.hasName("Deconstruct") and
1693+
this = m.getExtendedType().getSourceDeclaration() and
1694+
exists(int i |
1695+
m.getParameter(i).isOut() and
1696+
source = getFlowSourceArg(c, 0, _) and
1697+
sourceAp = this.getItemAccessPath(i) and
1698+
sink = TCallableFlowSinkArg(i) and
1699+
sinkAp = AccessPath::empty()
1700+
)
1701+
)
1702+
or
1703+
c = this.getAnIndexer().getGetter() and
1704+
source = TCallableFlowSourceQualifier() and
1705+
sourceAp = this.getItemAccessPath(_) and
1706+
sink = TCallableFlowSinkReturn() and
1707+
sinkAp = AccessPath::empty()
1708+
)
1709+
}
1710+
}
1711+
16561712
/** Data flow for `System.Threading.Tasks.Task`. */
16571713
class SystemThreadingTasksTaskFlow extends LibraryTypeDataFlow, SystemThreadingTasksTaskClass {
16581714
override predicate callableFlow(

0 commit comments

Comments
 (0)