mirror of
https://github.com/github/codeql.git
synced 2026-04-24 00:05:14 +02:00
Merge pull request #18195 from MathiasVP/dynamic-property-field-flow
C#: Add field-flow for dynamic fields
This commit is contained in:
@@ -0,0 +1,4 @@
|
||||
---
|
||||
category: minorAnalysis
|
||||
---
|
||||
* Added support for data-flow through member accesses of objects with `dynamic` types.
|
||||
@@ -883,6 +883,17 @@ private predicate fieldOrPropertyStore(Expr e, ContentSet c, Expr src, Expr q, b
|
||||
)
|
||||
)
|
||||
)
|
||||
or
|
||||
// A write to a dynamic property
|
||||
exists(DynamicMemberAccess dma, AssignableDefinition def, DynamicProperty dp |
|
||||
def.getTargetAccess() = dma and
|
||||
dp.getAnAccess() = dma and
|
||||
c.isDynamicProperty(dp) and
|
||||
src = def.getSource() and
|
||||
q = dma.getQualifier() and
|
||||
e = def.getExpr() and
|
||||
postUpdate = true
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -894,6 +905,18 @@ private predicate fieldOrPropertyRead(Expr e1, ContentSet c, FieldOrPropertyRead
|
||||
c = e2.getTarget().(FieldOrProperty).getContentSet()
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `e2` is an expression that reads the dynamic property `c` from
|
||||
* expression `e1`.
|
||||
*/
|
||||
private predicate dynamicPropertyRead(Expr e1, ContentSet c, DynamicMemberRead e2) {
|
||||
exists(DynamicPropertyContent dpc |
|
||||
e1 = e2.getQualifier() and
|
||||
dpc.getAnAccess() = e2 and
|
||||
c.isDynamicProperty(dpc.getName())
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `ce` is a collection expression that adds `src` to the collection `ce`.
|
||||
*/
|
||||
@@ -1099,6 +1122,8 @@ private module Cached {
|
||||
|
|
||||
fieldOrPropertyRead(e, _, read)
|
||||
or
|
||||
dynamicPropertyRead(e, _, read)
|
||||
or
|
||||
arrayRead(e, read)
|
||||
)
|
||||
)
|
||||
@@ -1140,6 +1165,7 @@ private module Cached {
|
||||
newtype TContent =
|
||||
TFieldContent(Field f) { f.isUnboundDeclaration() } or
|
||||
TPropertyContent(Property p) { p.isUnboundDeclaration() } or
|
||||
TDynamicPropertyContent(DynamicProperty dp) or
|
||||
TElementContent() or
|
||||
TSyntheticFieldContent(SyntheticField f) or
|
||||
TPrimaryConstructorParameterContent(Parameter p) {
|
||||
@@ -1154,12 +1180,16 @@ private module Cached {
|
||||
cached
|
||||
newtype TContentSet =
|
||||
TSingletonContent(Content c) { not c instanceof PropertyContent } or
|
||||
TPropertyContentSet(Property p) { p.isUnboundDeclaration() }
|
||||
TPropertyContentSet(Property p) { p.isUnboundDeclaration() } or
|
||||
TDynamicPropertyContentSet(DynamicProperty dp)
|
||||
|
||||
cached
|
||||
newtype TContentApprox =
|
||||
TFieldApproxContent(string firstChar) { firstChar = approximateFieldContent(_) } or
|
||||
TPropertyApproxContent(string firstChar) { firstChar = approximatePropertyContent(_) } or
|
||||
TDynamicPropertyApproxContent(string firstChar) {
|
||||
firstChar = approximateDynamicPropertyContent(_)
|
||||
} or
|
||||
TElementApproxContent() or
|
||||
TSyntheticFieldApproxContent() or
|
||||
TPrimaryConstructorParameterApproxContent(string firstChar) {
|
||||
@@ -2084,6 +2114,18 @@ class FieldOrProperty extends Assignable, Modifiable {
|
||||
}
|
||||
}
|
||||
|
||||
/** A string that is a reference to a late-bound target of a dynamic member access. */
|
||||
class DynamicProperty extends string {
|
||||
private DynamicMemberAccess dma;
|
||||
|
||||
DynamicProperty() { this = dma.getLateBoundTargetName() }
|
||||
|
||||
ContentSet getContentSet() { result.isDynamicProperty(this) }
|
||||
|
||||
/** Gets an access of this dynamic property. */
|
||||
DynamicMemberAccess getAnAccess() { result = dma }
|
||||
}
|
||||
|
||||
private class InstanceFieldOrProperty extends FieldOrProperty {
|
||||
InstanceFieldOrProperty() { not this.isStatic() }
|
||||
}
|
||||
@@ -2342,6 +2384,11 @@ private class ReadStepConfiguration extends ControlFlowReachabilityConfiguration
|
||||
or
|
||||
exactScope = false and
|
||||
isSuccessor = true and
|
||||
dynamicPropertyRead(e1, _, e2) and
|
||||
scope = e2
|
||||
or
|
||||
exactScope = false and
|
||||
isSuccessor = true and
|
||||
arrayRead(e1, e2) and
|
||||
scope = e2
|
||||
or
|
||||
@@ -2474,6 +2521,8 @@ predicate readStep(Node node1, ContentSet c, Node node2) {
|
||||
exists(ReadStepConfiguration x | hasNodePath(x, node1, node2) |
|
||||
fieldOrPropertyRead(node1.asExpr(), c, node2.asExpr())
|
||||
or
|
||||
dynamicPropertyRead(node1.asExpr(), c, node2.asExpr())
|
||||
or
|
||||
node2.asExpr().(AwaitExpr).getExpr() = node1.asExpr() and
|
||||
c = getResultContent()
|
||||
)
|
||||
@@ -3064,6 +3113,11 @@ class ContentApprox extends TContentApprox {
|
||||
this = TPropertyApproxContent(firstChar) and result = "approximated property " + firstChar
|
||||
)
|
||||
or
|
||||
exists(string firstChar |
|
||||
this = TDynamicPropertyApproxContent(firstChar) and
|
||||
result = "approximated dynamic property " + firstChar
|
||||
)
|
||||
or
|
||||
this = TElementApproxContent() and result = "element"
|
||||
or
|
||||
this = TSyntheticFieldApproxContent() and result = "approximated synthetic field"
|
||||
@@ -3095,6 +3149,11 @@ private string approximatePropertyContent(PropertyContent pc) {
|
||||
result = pc.getProperty().getName().prefix(1)
|
||||
}
|
||||
|
||||
/** Gets a string for approximating the name of a dynamic property. */
|
||||
private string approximateDynamicPropertyContent(DynamicPropertyContent dpc) {
|
||||
result = dpc.getName().prefix(1)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a string for approximating the name of a synthetic field corresponding
|
||||
* to a primary constructor parameter.
|
||||
@@ -3110,6 +3169,8 @@ ContentApprox getContentApprox(Content c) {
|
||||
or
|
||||
result = TPropertyApproxContent(approximatePropertyContent(c))
|
||||
or
|
||||
result = TDynamicPropertyApproxContent(approximateDynamicPropertyContent(c))
|
||||
or
|
||||
c instanceof ElementContent and result = TElementApproxContent()
|
||||
or
|
||||
c instanceof SyntheticFieldContent and result = TSyntheticFieldApproxContent()
|
||||
|
||||
@@ -239,6 +239,23 @@ class PropertyContent extends Content, TPropertyContent {
|
||||
override Location getLocation() { result = p.getLocation() }
|
||||
}
|
||||
|
||||
/** A reference to a dynamic property. */
|
||||
class DynamicPropertyContent extends Content, TDynamicPropertyContent {
|
||||
private DynamicProperty name;
|
||||
|
||||
DynamicPropertyContent() { this = TDynamicPropertyContent(name) }
|
||||
|
||||
/** Gets an access of this dynamic property. */
|
||||
DynamicMemberAccess getAnAccess() { result = name.getAnAccess() }
|
||||
|
||||
override string toString() { result = "dynamic property " + name }
|
||||
|
||||
override EmptyLocation getLocation() { any() }
|
||||
|
||||
/** Gets the name that is referenced. */
|
||||
string getName() { result = name }
|
||||
}
|
||||
|
||||
/**
|
||||
* A reference to the index of an argument of a delegate call.
|
||||
*/
|
||||
@@ -324,6 +341,9 @@ class ContentSet extends TContentSet {
|
||||
*/
|
||||
predicate isProperty(Property p) { this = TPropertyContentSet(p) }
|
||||
|
||||
/** Holds if this content set represents the dynamic property `name`. */
|
||||
predicate isDynamicProperty(string name) { this = TDynamicPropertyContentSet(name) }
|
||||
|
||||
/**
|
||||
* Holds if this content set represents the `i`th argument of a delegate call.
|
||||
*/
|
||||
@@ -348,6 +368,8 @@ class ContentSet extends TContentSet {
|
||||
this.isSingleton(result)
|
||||
or
|
||||
this.isProperty(result.(PropertyContent).getProperty())
|
||||
or
|
||||
this.isDynamicProperty(result.(DynamicPropertyContent).getName())
|
||||
}
|
||||
|
||||
/** Gets a content that may be read from when reading from this set. */
|
||||
@@ -362,6 +384,17 @@ class ContentSet extends TContentSet {
|
||||
or
|
||||
overridesOrImplementsSourceDecl(p1, p2)
|
||||
)
|
||||
or
|
||||
exists(FieldOrProperty p |
|
||||
this = p.getContentSet() and
|
||||
result.(DynamicPropertyContent).getName() = p.getName()
|
||||
)
|
||||
or
|
||||
this.isDynamicProperty([
|
||||
result.(DynamicPropertyContent).getName(),
|
||||
result.(PropertyContent).getProperty().getName(),
|
||||
result.(FieldContent).getField().getName()
|
||||
])
|
||||
}
|
||||
|
||||
/** Gets a textual representation of this content set. */
|
||||
@@ -375,6 +408,11 @@ class ContentSet extends TContentSet {
|
||||
this.isProperty(p) and
|
||||
result = "property " + p.getName()
|
||||
)
|
||||
or
|
||||
exists(string name |
|
||||
this.isDynamicProperty(name) and
|
||||
result = "dynamic property " + name
|
||||
)
|
||||
}
|
||||
|
||||
/** Gets the location of this content set. */
|
||||
@@ -388,5 +426,8 @@ class ContentSet extends TContentSet {
|
||||
this.isProperty(p) and
|
||||
result = p.getLocation()
|
||||
)
|
||||
or
|
||||
this.isDynamicProperty(_) and
|
||||
result instanceof EmptyLocation
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1162,6 +1162,54 @@ edges
|
||||
| K.cs:8:22:8:22 | access to local variable o : String | K.cs:8:9:8:15 | [post] access to field Strings : String[] [element] : String | provenance | |
|
||||
| K.cs:13:14:13:20 | access to field Strings : String[] [element] : String | K.cs:13:14:13:23 | access to array element | provenance | |
|
||||
| K.cs:13:14:13:20 | access to field Strings : String[] [element] : String | K.cs:13:14:13:23 | access to array element | provenance | |
|
||||
| L.cs:17:9:17:10 | [post] access to local variable d1 : Object [dynamic property p1] : String | L.cs:18:14:18:15 | access to local variable d1 : Object [dynamic property p1] : String | provenance | |
|
||||
| L.cs:17:9:17:10 | [post] access to local variable d1 : Object [dynamic property p1] : String | L.cs:18:14:18:15 | access to local variable d1 : Object [dynamic property p1] : String | provenance | |
|
||||
| L.cs:17:17:17:33 | call to method Source<String> : String | L.cs:17:9:17:10 | [post] access to local variable d1 : Object [dynamic property p1] : String | provenance | |
|
||||
| L.cs:17:17:17:33 | call to method Source<String> : String | L.cs:17:9:17:10 | [post] access to local variable d1 : Object [dynamic property p1] : String | provenance | |
|
||||
| L.cs:18:14:18:15 | access to local variable d1 : Object [dynamic property p1] : String | L.cs:18:14:18:18 | dynamic access to member p1 | provenance | |
|
||||
| L.cs:18:14:18:15 | access to local variable d1 : Object [dynamic property p1] : String | L.cs:18:14:18:18 | dynamic access to member p1 | provenance | |
|
||||
| L.cs:22:9:22:10 | [post] access to local variable d2 : Object [dynamic property p2] : String | L.cs:23:16:23:17 | (...) ... : L [dynamic property p2] : String | provenance | |
|
||||
| L.cs:22:9:22:10 | [post] access to local variable d2 : Object [dynamic property p2] : String | L.cs:23:16:23:17 | (...) ... : L [dynamic property p2] : String | provenance | |
|
||||
| L.cs:22:17:22:33 | call to method Source<String> : String | L.cs:22:9:22:10 | [post] access to local variable d2 : Object [dynamic property p2] : String | provenance | |
|
||||
| L.cs:22:17:22:33 | call to method Source<String> : String | L.cs:22:9:22:10 | [post] access to local variable d2 : Object [dynamic property p2] : String | provenance | |
|
||||
| L.cs:23:11:23:12 | access to local variable l2 : L [dynamic property p2] : String | L.cs:24:14:24:15 | access to local variable l2 : L [dynamic property p2] : String | provenance | |
|
||||
| L.cs:23:11:23:12 | access to local variable l2 : L [dynamic property p2] : String | L.cs:24:14:24:15 | access to local variable l2 : L [dynamic property p2] : String | provenance | |
|
||||
| L.cs:23:16:23:17 | (...) ... : L [dynamic property p2] : String | L.cs:23:11:23:12 | access to local variable l2 : L [dynamic property p2] : String | provenance | |
|
||||
| L.cs:23:16:23:17 | (...) ... : L [dynamic property p2] : String | L.cs:23:11:23:12 | access to local variable l2 : L [dynamic property p2] : String | provenance | |
|
||||
| L.cs:24:14:24:15 | access to local variable l2 : L [dynamic property p2] : String | L.cs:24:14:24:18 | access to property p2 | provenance | |
|
||||
| L.cs:24:14:24:15 | access to local variable l2 : L [dynamic property p2] : String | L.cs:24:14:24:18 | access to property p2 | provenance | |
|
||||
| L.cs:27:9:27:12 | [post] this access : L [property p3] : String | L.cs:28:17:28:18 | access to local variable d3 : L [property p3] : String | provenance | |
|
||||
| L.cs:27:9:27:12 | [post] this access : L [property p3] : String | L.cs:28:17:28:18 | access to local variable d3 : L [property p3] : String | provenance | |
|
||||
| L.cs:27:19:27:35 | call to method Source<String> : String | L.cs:27:9:27:12 | [post] this access : L [property p3] : String | provenance | |
|
||||
| L.cs:27:19:27:35 | call to method Source<String> : String | L.cs:27:9:27:12 | [post] this access : L [property p3] : String | provenance | |
|
||||
| L.cs:28:17:28:18 | access to local variable d3 : L [property p3] : String | L.cs:29:14:29:15 | access to local variable d3 : L [property p3] : String | provenance | |
|
||||
| L.cs:28:17:28:18 | access to local variable d3 : L [property p3] : String | L.cs:29:14:29:15 | access to local variable d3 : L [property p3] : String | provenance | |
|
||||
| L.cs:29:14:29:15 | access to local variable d3 : L [property p3] : String | L.cs:29:14:29:18 | dynamic access to member p3 | provenance | |
|
||||
| L.cs:29:14:29:15 | access to local variable d3 : L [property p3] : String | L.cs:29:14:29:18 | dynamic access to member p3 | provenance | |
|
||||
| L.cs:33:9:33:10 | [post] access to local variable d4 : Object [dynamic property f1] : String | L.cs:34:14:34:15 | access to local variable d4 : Object [dynamic property f1] : String | provenance | |
|
||||
| L.cs:33:9:33:10 | [post] access to local variable d4 : Object [dynamic property f1] : String | L.cs:34:14:34:15 | access to local variable d4 : Object [dynamic property f1] : String | provenance | |
|
||||
| L.cs:33:17:33:33 | call to method Source<String> : String | L.cs:33:9:33:10 | [post] access to local variable d4 : Object [dynamic property f1] : String | provenance | |
|
||||
| L.cs:33:17:33:33 | call to method Source<String> : String | L.cs:33:9:33:10 | [post] access to local variable d4 : Object [dynamic property f1] : String | provenance | |
|
||||
| L.cs:34:14:34:15 | access to local variable d4 : Object [dynamic property f1] : String | L.cs:34:14:34:18 | dynamic access to member f1 | provenance | |
|
||||
| L.cs:34:14:34:15 | access to local variable d4 : Object [dynamic property f1] : String | L.cs:34:14:34:18 | dynamic access to member f1 | provenance | |
|
||||
| L.cs:38:9:38:10 | [post] access to local variable d5 : Object [dynamic property f2] : String | L.cs:39:16:39:17 | (...) ... : L [dynamic property f2] : String | provenance | |
|
||||
| L.cs:38:9:38:10 | [post] access to local variable d5 : Object [dynamic property f2] : String | L.cs:39:16:39:17 | (...) ... : L [dynamic property f2] : String | provenance | |
|
||||
| L.cs:38:17:38:33 | call to method Source<String> : String | L.cs:38:9:38:10 | [post] access to local variable d5 : Object [dynamic property f2] : String | provenance | |
|
||||
| L.cs:38:17:38:33 | call to method Source<String> : String | L.cs:38:9:38:10 | [post] access to local variable d5 : Object [dynamic property f2] : String | provenance | |
|
||||
| L.cs:39:11:39:12 | access to local variable l5 : L [dynamic property f2] : String | L.cs:40:14:40:15 | access to local variable l5 : L [dynamic property f2] : String | provenance | |
|
||||
| L.cs:39:11:39:12 | access to local variable l5 : L [dynamic property f2] : String | L.cs:40:14:40:15 | access to local variable l5 : L [dynamic property f2] : String | provenance | |
|
||||
| L.cs:39:16:39:17 | (...) ... : L [dynamic property f2] : String | L.cs:39:11:39:12 | access to local variable l5 : L [dynamic property f2] : String | provenance | |
|
||||
| L.cs:39:16:39:17 | (...) ... : L [dynamic property f2] : String | L.cs:39:11:39:12 | access to local variable l5 : L [dynamic property f2] : String | provenance | |
|
||||
| L.cs:40:14:40:15 | access to local variable l5 : L [dynamic property f2] : String | L.cs:40:14:40:18 | access to field f2 | provenance | |
|
||||
| L.cs:40:14:40:15 | access to local variable l5 : L [dynamic property f2] : String | L.cs:40:14:40:18 | access to field f2 | provenance | |
|
||||
| L.cs:43:9:43:12 | [post] this access : L [field f3] : String | L.cs:44:17:44:18 | access to local variable d6 : L [field f3] : String | provenance | |
|
||||
| L.cs:43:9:43:12 | [post] this access : L [field f3] : String | L.cs:44:17:44:18 | access to local variable d6 : L [field f3] : String | provenance | |
|
||||
| L.cs:43:19:43:35 | call to method Source<String> : String | L.cs:43:9:43:12 | [post] this access : L [field f3] : String | provenance | |
|
||||
| L.cs:43:19:43:35 | call to method Source<String> : String | L.cs:43:9:43:12 | [post] this access : L [field f3] : String | provenance | |
|
||||
| L.cs:44:17:44:18 | access to local variable d6 : L [field f3] : String | L.cs:45:14:45:15 | access to local variable d6 : L [field f3] : String | provenance | |
|
||||
| L.cs:44:17:44:18 | access to local variable d6 : L [field f3] : String | L.cs:45:14:45:15 | access to local variable d6 : L [field f3] : String | provenance | |
|
||||
| L.cs:45:14:45:15 | access to local variable d6 : L [field f3] : String | L.cs:45:14:45:18 | dynamic access to member f3 | provenance | |
|
||||
| L.cs:45:14:45:15 | access to local variable d6 : L [field f3] : String | L.cs:45:14:45:18 | dynamic access to member f3 | provenance | |
|
||||
nodes
|
||||
| A.cs:5:13:5:13 | access to local variable c : C | semmle.label | access to local variable c : C |
|
||||
| A.cs:5:13:5:13 | access to local variable c : C | semmle.label | access to local variable c : C |
|
||||
@@ -2415,6 +2463,66 @@ nodes
|
||||
| K.cs:13:14:13:20 | access to field Strings : String[] [element] : String | semmle.label | access to field Strings : String[] [element] : String |
|
||||
| K.cs:13:14:13:23 | access to array element | semmle.label | access to array element |
|
||||
| K.cs:13:14:13:23 | access to array element | semmle.label | access to array element |
|
||||
| L.cs:17:9:17:10 | [post] access to local variable d1 : Object [dynamic property p1] : String | semmle.label | [post] access to local variable d1 : Object [dynamic property p1] : String |
|
||||
| L.cs:17:9:17:10 | [post] access to local variable d1 : Object [dynamic property p1] : String | semmle.label | [post] access to local variable d1 : Object [dynamic property p1] : String |
|
||||
| L.cs:17:17:17:33 | call to method Source<String> : String | semmle.label | call to method Source<String> : String |
|
||||
| L.cs:17:17:17:33 | call to method Source<String> : String | semmle.label | call to method Source<String> : String |
|
||||
| L.cs:18:14:18:15 | access to local variable d1 : Object [dynamic property p1] : String | semmle.label | access to local variable d1 : Object [dynamic property p1] : String |
|
||||
| L.cs:18:14:18:15 | access to local variable d1 : Object [dynamic property p1] : String | semmle.label | access to local variable d1 : Object [dynamic property p1] : String |
|
||||
| L.cs:18:14:18:18 | dynamic access to member p1 | semmle.label | dynamic access to member p1 |
|
||||
| L.cs:18:14:18:18 | dynamic access to member p1 | semmle.label | dynamic access to member p1 |
|
||||
| L.cs:22:9:22:10 | [post] access to local variable d2 : Object [dynamic property p2] : String | semmle.label | [post] access to local variable d2 : Object [dynamic property p2] : String |
|
||||
| L.cs:22:9:22:10 | [post] access to local variable d2 : Object [dynamic property p2] : String | semmle.label | [post] access to local variable d2 : Object [dynamic property p2] : String |
|
||||
| L.cs:22:17:22:33 | call to method Source<String> : String | semmle.label | call to method Source<String> : String |
|
||||
| L.cs:22:17:22:33 | call to method Source<String> : String | semmle.label | call to method Source<String> : String |
|
||||
| L.cs:23:11:23:12 | access to local variable l2 : L [dynamic property p2] : String | semmle.label | access to local variable l2 : L [dynamic property p2] : String |
|
||||
| L.cs:23:11:23:12 | access to local variable l2 : L [dynamic property p2] : String | semmle.label | access to local variable l2 : L [dynamic property p2] : String |
|
||||
| L.cs:23:16:23:17 | (...) ... : L [dynamic property p2] : String | semmle.label | (...) ... : L [dynamic property p2] : String |
|
||||
| L.cs:23:16:23:17 | (...) ... : L [dynamic property p2] : String | semmle.label | (...) ... : L [dynamic property p2] : String |
|
||||
| L.cs:24:14:24:15 | access to local variable l2 : L [dynamic property p2] : String | semmle.label | access to local variable l2 : L [dynamic property p2] : String |
|
||||
| L.cs:24:14:24:15 | access to local variable l2 : L [dynamic property p2] : String | semmle.label | access to local variable l2 : L [dynamic property p2] : String |
|
||||
| L.cs:24:14:24:18 | access to property p2 | semmle.label | access to property p2 |
|
||||
| L.cs:24:14:24:18 | access to property p2 | semmle.label | access to property p2 |
|
||||
| L.cs:27:9:27:12 | [post] this access : L [property p3] : String | semmle.label | [post] this access : L [property p3] : String |
|
||||
| L.cs:27:9:27:12 | [post] this access : L [property p3] : String | semmle.label | [post] this access : L [property p3] : String |
|
||||
| L.cs:27:19:27:35 | call to method Source<String> : String | semmle.label | call to method Source<String> : String |
|
||||
| L.cs:27:19:27:35 | call to method Source<String> : String | semmle.label | call to method Source<String> : String |
|
||||
| L.cs:28:17:28:18 | access to local variable d3 : L [property p3] : String | semmle.label | access to local variable d3 : L [property p3] : String |
|
||||
| L.cs:28:17:28:18 | access to local variable d3 : L [property p3] : String | semmle.label | access to local variable d3 : L [property p3] : String |
|
||||
| L.cs:29:14:29:15 | access to local variable d3 : L [property p3] : String | semmle.label | access to local variable d3 : L [property p3] : String |
|
||||
| L.cs:29:14:29:15 | access to local variable d3 : L [property p3] : String | semmle.label | access to local variable d3 : L [property p3] : String |
|
||||
| L.cs:29:14:29:18 | dynamic access to member p3 | semmle.label | dynamic access to member p3 |
|
||||
| L.cs:29:14:29:18 | dynamic access to member p3 | semmle.label | dynamic access to member p3 |
|
||||
| L.cs:33:9:33:10 | [post] access to local variable d4 : Object [dynamic property f1] : String | semmle.label | [post] access to local variable d4 : Object [dynamic property f1] : String |
|
||||
| L.cs:33:9:33:10 | [post] access to local variable d4 : Object [dynamic property f1] : String | semmle.label | [post] access to local variable d4 : Object [dynamic property f1] : String |
|
||||
| L.cs:33:17:33:33 | call to method Source<String> : String | semmle.label | call to method Source<String> : String |
|
||||
| L.cs:33:17:33:33 | call to method Source<String> : String | semmle.label | call to method Source<String> : String |
|
||||
| L.cs:34:14:34:15 | access to local variable d4 : Object [dynamic property f1] : String | semmle.label | access to local variable d4 : Object [dynamic property f1] : String |
|
||||
| L.cs:34:14:34:15 | access to local variable d4 : Object [dynamic property f1] : String | semmle.label | access to local variable d4 : Object [dynamic property f1] : String |
|
||||
| L.cs:34:14:34:18 | dynamic access to member f1 | semmle.label | dynamic access to member f1 |
|
||||
| L.cs:34:14:34:18 | dynamic access to member f1 | semmle.label | dynamic access to member f1 |
|
||||
| L.cs:38:9:38:10 | [post] access to local variable d5 : Object [dynamic property f2] : String | semmle.label | [post] access to local variable d5 : Object [dynamic property f2] : String |
|
||||
| L.cs:38:9:38:10 | [post] access to local variable d5 : Object [dynamic property f2] : String | semmle.label | [post] access to local variable d5 : Object [dynamic property f2] : String |
|
||||
| L.cs:38:17:38:33 | call to method Source<String> : String | semmle.label | call to method Source<String> : String |
|
||||
| L.cs:38:17:38:33 | call to method Source<String> : String | semmle.label | call to method Source<String> : String |
|
||||
| L.cs:39:11:39:12 | access to local variable l5 : L [dynamic property f2] : String | semmle.label | access to local variable l5 : L [dynamic property f2] : String |
|
||||
| L.cs:39:11:39:12 | access to local variable l5 : L [dynamic property f2] : String | semmle.label | access to local variable l5 : L [dynamic property f2] : String |
|
||||
| L.cs:39:16:39:17 | (...) ... : L [dynamic property f2] : String | semmle.label | (...) ... : L [dynamic property f2] : String |
|
||||
| L.cs:39:16:39:17 | (...) ... : L [dynamic property f2] : String | semmle.label | (...) ... : L [dynamic property f2] : String |
|
||||
| L.cs:40:14:40:15 | access to local variable l5 : L [dynamic property f2] : String | semmle.label | access to local variable l5 : L [dynamic property f2] : String |
|
||||
| L.cs:40:14:40:15 | access to local variable l5 : L [dynamic property f2] : String | semmle.label | access to local variable l5 : L [dynamic property f2] : String |
|
||||
| L.cs:40:14:40:18 | access to field f2 | semmle.label | access to field f2 |
|
||||
| L.cs:40:14:40:18 | access to field f2 | semmle.label | access to field f2 |
|
||||
| L.cs:43:9:43:12 | [post] this access : L [field f3] : String | semmle.label | [post] this access : L [field f3] : String |
|
||||
| L.cs:43:9:43:12 | [post] this access : L [field f3] : String | semmle.label | [post] this access : L [field f3] : String |
|
||||
| L.cs:43:19:43:35 | call to method Source<String> : String | semmle.label | call to method Source<String> : String |
|
||||
| L.cs:43:19:43:35 | call to method Source<String> : String | semmle.label | call to method Source<String> : String |
|
||||
| L.cs:44:17:44:18 | access to local variable d6 : L [field f3] : String | semmle.label | access to local variable d6 : L [field f3] : String |
|
||||
| L.cs:44:17:44:18 | access to local variable d6 : L [field f3] : String | semmle.label | access to local variable d6 : L [field f3] : String |
|
||||
| L.cs:45:14:45:15 | access to local variable d6 : L [field f3] : String | semmle.label | access to local variable d6 : L [field f3] : String |
|
||||
| L.cs:45:14:45:15 | access to local variable d6 : L [field f3] : String | semmle.label | access to local variable d6 : L [field f3] : String |
|
||||
| L.cs:45:14:45:18 | dynamic access to member f3 | semmle.label | dynamic access to member f3 |
|
||||
| L.cs:45:14:45:18 | dynamic access to member f3 | semmle.label | dynamic access to member f3 |
|
||||
subpaths
|
||||
| A.cs:6:24:6:24 | access to local variable c : C | A.cs:147:32:147:32 | c : C | A.cs:149:20:149:27 | object creation of type B : B [field c] : C | A.cs:6:17:6:25 | call to method Make : B [field c] : C |
|
||||
| A.cs:6:24:6:24 | access to local variable c : C | A.cs:147:32:147:32 | c : C | A.cs:149:20:149:27 | object creation of type B : B [field c] : C | A.cs:6:17:6:25 | call to method Make : B [field c] : C |
|
||||
@@ -2672,3 +2780,15 @@ testFailures
|
||||
| J.cs:125:14:125:17 | (...) ... | J.cs:119:20:119:34 | call to method Source<Int32> : Int32 | J.cs:125:14:125:17 | (...) ... | $@ | J.cs:119:20:119:34 | call to method Source<Int32> : Int32 | call to method Source<Int32> : Int32 |
|
||||
| K.cs:13:14:13:23 | access to array element | K.cs:7:17:7:33 | call to method Source<String> : String | K.cs:13:14:13:23 | access to array element | $@ | K.cs:7:17:7:33 | call to method Source<String> : String | call to method Source<String> : String |
|
||||
| K.cs:13:14:13:23 | access to array element | K.cs:7:17:7:33 | call to method Source<String> : String | K.cs:13:14:13:23 | access to array element | $@ | K.cs:7:17:7:33 | call to method Source<String> : String | call to method Source<String> : String |
|
||||
| L.cs:18:14:18:18 | dynamic access to member p1 | L.cs:17:17:17:33 | call to method Source<String> : String | L.cs:18:14:18:18 | dynamic access to member p1 | $@ | L.cs:17:17:17:33 | call to method Source<String> : String | call to method Source<String> : String |
|
||||
| L.cs:18:14:18:18 | dynamic access to member p1 | L.cs:17:17:17:33 | call to method Source<String> : String | L.cs:18:14:18:18 | dynamic access to member p1 | $@ | L.cs:17:17:17:33 | call to method Source<String> : String | call to method Source<String> : String |
|
||||
| L.cs:24:14:24:18 | access to property p2 | L.cs:22:17:22:33 | call to method Source<String> : String | L.cs:24:14:24:18 | access to property p2 | $@ | L.cs:22:17:22:33 | call to method Source<String> : String | call to method Source<String> : String |
|
||||
| L.cs:24:14:24:18 | access to property p2 | L.cs:22:17:22:33 | call to method Source<String> : String | L.cs:24:14:24:18 | access to property p2 | $@ | L.cs:22:17:22:33 | call to method Source<String> : String | call to method Source<String> : String |
|
||||
| L.cs:29:14:29:18 | dynamic access to member p3 | L.cs:27:19:27:35 | call to method Source<String> : String | L.cs:29:14:29:18 | dynamic access to member p3 | $@ | L.cs:27:19:27:35 | call to method Source<String> : String | call to method Source<String> : String |
|
||||
| L.cs:29:14:29:18 | dynamic access to member p3 | L.cs:27:19:27:35 | call to method Source<String> : String | L.cs:29:14:29:18 | dynamic access to member p3 | $@ | L.cs:27:19:27:35 | call to method Source<String> : String | call to method Source<String> : String |
|
||||
| L.cs:34:14:34:18 | dynamic access to member f1 | L.cs:33:17:33:33 | call to method Source<String> : String | L.cs:34:14:34:18 | dynamic access to member f1 | $@ | L.cs:33:17:33:33 | call to method Source<String> : String | call to method Source<String> : String |
|
||||
| L.cs:34:14:34:18 | dynamic access to member f1 | L.cs:33:17:33:33 | call to method Source<String> : String | L.cs:34:14:34:18 | dynamic access to member f1 | $@ | L.cs:33:17:33:33 | call to method Source<String> : String | call to method Source<String> : String |
|
||||
| L.cs:40:14:40:18 | access to field f2 | L.cs:38:17:38:33 | call to method Source<String> : String | L.cs:40:14:40:18 | access to field f2 | $@ | L.cs:38:17:38:33 | call to method Source<String> : String | call to method Source<String> : String |
|
||||
| L.cs:40:14:40:18 | access to field f2 | L.cs:38:17:38:33 | call to method Source<String> : String | L.cs:40:14:40:18 | access to field f2 | $@ | L.cs:38:17:38:33 | call to method Source<String> : String | call to method Source<String> : String |
|
||||
| L.cs:45:14:45:18 | dynamic access to member f3 | L.cs:43:19:43:35 | call to method Source<String> : String | L.cs:45:14:45:18 | dynamic access to member f3 | $@ | L.cs:43:19:43:35 | call to method Source<String> : String | call to method Source<String> : String |
|
||||
| L.cs:45:14:45:18 | dynamic access to member f3 | L.cs:43:19:43:35 | call to method Source<String> : String | L.cs:45:14:45:18 | dynamic access to member f3 | $@ | L.cs:43:19:43:35 | call to method Source<String> : String | call to method Source<String> : String |
|
||||
|
||||
51
csharp/ql/test/library-tests/dataflow/fields/L.cs
Normal file
51
csharp/ql/test/library-tests/dataflow/fields/L.cs
Normal file
@@ -0,0 +1,51 @@
|
||||
using System;
|
||||
|
||||
public class L
|
||||
{
|
||||
public string p1 { get; set; }
|
||||
public string p2 { get; set; }
|
||||
public string p3 { get; set; }
|
||||
|
||||
private string f1;
|
||||
private string f2;
|
||||
private string f3;
|
||||
|
||||
private void M1()
|
||||
{
|
||||
// dynamic property write followed by dynamic property read
|
||||
dynamic d1 = this;
|
||||
d1.p1 = Source<string>(1);
|
||||
Sink(d1.p1); // $ hasValueFlow=1
|
||||
|
||||
// dynamic property write followed by static property read
|
||||
dynamic d2 = this;
|
||||
d2.p2 = Source<string>(2);
|
||||
L l2 = d2;
|
||||
Sink(l2.p2); // $ hasValueFlow=2
|
||||
|
||||
// static property write followed by dynamic property read
|
||||
this.p3 = Source<string>(3);
|
||||
dynamic d3 = this;
|
||||
Sink(d3.p3); // $ hasValueFlow=3
|
||||
|
||||
// dynamic property write followed by dynamic field read
|
||||
dynamic d4 = this;
|
||||
d4.f1 = Source<string>(4);
|
||||
Sink(d4.f1); // $ hasValueFlow=4
|
||||
|
||||
// dynamic property write followed by static field read
|
||||
dynamic d5 = this;
|
||||
d5.f2 = Source<string>(5);
|
||||
L l5 = d5;
|
||||
Sink(l5.f2); // $ hasValueFlow=5
|
||||
|
||||
// static field write followed by dynamic property read
|
||||
this.f3 = Source<string>(6);
|
||||
dynamic d6 = this;
|
||||
Sink(d6.f3); // $ hasValueFlow=6
|
||||
}
|
||||
|
||||
public static void Sink(object o) { }
|
||||
|
||||
static T Source<T>(object source) => throw null;
|
||||
}
|
||||
Reference in New Issue
Block a user