Merge pull request #15652 from michaelnebel/csharp/constructorflow

C#: Read-only property flow.
This commit is contained in:
Michael Nebel
2024-02-21 10:12:46 +01:00
committed by GitHub
5 changed files with 84 additions and 5 deletions

View File

@@ -0,0 +1,4 @@
---
category: minorAnalysis
---
* C#: Data flow via get only properties like `public object Obj { get; }` is now captured by the data flow library.

View File

@@ -127,6 +127,13 @@ class Property extends DotNet::Property, DeclarationWithGetSetAccessors, @proper
properties(this, _, _, getTypeRef(result), _)
}
private predicate isAutoPartial() {
this.fromSource() and
not this.isExtern() and
not this.isAbstract() and
not this.getAnAccessor().hasBody()
}
/**
* Holds if this property is automatically implemented. For example, `P1`
* on line 2 is automatically implemented, while `P2` on line 5 is not in
@@ -147,11 +154,22 @@ class Property extends DotNet::Property, DeclarationWithGetSetAccessors, @proper
* code.
*/
predicate isAutoImplemented() {
this.fromSource() and
this.isReadWrite() and
not this.isExtern() and
not this.isAbstract() and
not this.getAnAccessor().hasBody()
this.isAutoPartial() and
this.isReadWrite()
}
/**
* Holds if this property is automatically implemented and read-only. For
* example, `P1` on line 2 is automatically implemented and read-only
* ```csharp
* class C {
* public int P1 { get; }
* }
* ```
*/
predicate isAutoImplementedReadOnly() {
this.isAutoPartial() and
this.isReadOnly()
}
override Property getUnboundDeclaration() { properties(this, _, _, _, result) }

View File

@@ -1899,6 +1899,8 @@ class FieldOrProperty extends Assignable, Modifiable {
(
p.isAutoImplemented()
or
p.isAutoImplementedReadOnly()
or
p.matchesHandle(any(CIL::TrivialProperty tp))
or
p.getDeclaringType() instanceof AnonymousClass

View File

@@ -64,6 +64,20 @@ edges
| Constructors.cs:112:25:112:27 | access to local variable o31 : Object | Constructors.cs:112:18:112:28 | object creation of type C3 : C3 [parameter o31param] : Object | provenance | |
| Constructors.cs:113:14:113:15 | access to local variable c3 : C3 [parameter o31param] : Object | Constructors.cs:106:32:106:39 | this : C3 [parameter o31param] : Object | provenance | |
| Constructors.cs:113:14:113:15 | access to local variable c3 : C3 [parameter o31param] : Object | Constructors.cs:113:14:113:21 | access to property Obj31 | provenance | |
| Constructors.cs:121:26:121:28 | oc1 : Object | Constructors.cs:123:20:123:22 | access to parameter oc1 : Object | provenance | |
| Constructors.cs:121:38:121:40 | oc2 : Object | Constructors.cs:124:20:124:22 | access to parameter oc2 : Object | provenance | |
| Constructors.cs:123:20:123:22 | access to parameter oc1 : Object | Constructors.cs:123:13:123:16 | [post] this access : C4 [property Obj1] : Object | provenance | |
| Constructors.cs:124:20:124:22 | access to parameter oc2 : Object | Constructors.cs:124:13:124:16 | [post] this access : C4 [property Obj2] : Object | provenance | |
| Constructors.cs:130:18:130:34 | call to method Source<Object> : Object | Constructors.cs:132:25:132:26 | access to local variable o1 : Object | provenance | |
| Constructors.cs:131:18:131:34 | call to method Source<Object> : Object | Constructors.cs:132:29:132:30 | access to local variable o2 : Object | provenance | |
| Constructors.cs:132:18:132:31 | object creation of type C4 : C4 [property Obj1] : Object | Constructors.cs:133:14:133:15 | access to local variable c4 : C4 [property Obj1] : Object | provenance | |
| Constructors.cs:132:18:132:31 | object creation of type C4 : C4 [property Obj2] : Object | Constructors.cs:134:14:134:15 | access to local variable c4 : C4 [property Obj2] : Object | provenance | |
| Constructors.cs:132:25:132:26 | access to local variable o1 : Object | Constructors.cs:121:26:121:28 | oc1 : Object | provenance | |
| Constructors.cs:132:25:132:26 | access to local variable o1 : Object | Constructors.cs:132:18:132:31 | object creation of type C4 : C4 [property Obj1] : Object | provenance | |
| Constructors.cs:132:29:132:30 | access to local variable o2 : Object | Constructors.cs:121:38:121:40 | oc2 : Object | provenance | |
| Constructors.cs:132:29:132:30 | access to local variable o2 : Object | Constructors.cs:132:18:132:31 | object creation of type C4 : C4 [property Obj2] : Object | provenance | |
| Constructors.cs:133:14:133:15 | access to local variable c4 : C4 [property Obj1] : Object | Constructors.cs:133:14:133:20 | access to property Obj1 | provenance | |
| Constructors.cs:134:14:134:15 | access to local variable c4 : C4 [property Obj2] : Object | Constructors.cs:134:14:134:20 | access to property Obj2 | provenance | |
nodes
| Constructors.cs:5:24:5:25 | [post] this access : C_no_ctor [field s1] : Object | semmle.label | [post] this access : C_no_ctor [field s1] : Object |
| Constructors.cs:5:29:5:45 | call to method Source<Object> : Object | semmle.label | call to method Source<Object> : Object |
@@ -134,6 +148,22 @@ nodes
| Constructors.cs:112:25:112:27 | access to local variable o31 : Object | semmle.label | access to local variable o31 : Object |
| Constructors.cs:113:14:113:15 | access to local variable c3 : C3 [parameter o31param] : Object | semmle.label | access to local variable c3 : C3 [parameter o31param] : Object |
| Constructors.cs:113:14:113:21 | access to property Obj31 | semmle.label | access to property Obj31 |
| Constructors.cs:121:26:121:28 | oc1 : Object | semmle.label | oc1 : Object |
| Constructors.cs:121:38:121:40 | oc2 : Object | semmle.label | oc2 : Object |
| Constructors.cs:123:13:123:16 | [post] this access : C4 [property Obj1] : Object | semmle.label | [post] this access : C4 [property Obj1] : Object |
| Constructors.cs:123:20:123:22 | access to parameter oc1 : Object | semmle.label | access to parameter oc1 : Object |
| Constructors.cs:124:13:124:16 | [post] this access : C4 [property Obj2] : Object | semmle.label | [post] this access : C4 [property Obj2] : Object |
| Constructors.cs:124:20:124:22 | access to parameter oc2 : Object | semmle.label | access to parameter oc2 : Object |
| Constructors.cs:130:18:130:34 | call to method Source<Object> : Object | semmle.label | call to method Source<Object> : Object |
| Constructors.cs:131:18:131:34 | call to method Source<Object> : Object | semmle.label | call to method Source<Object> : Object |
| Constructors.cs:132:18:132:31 | object creation of type C4 : C4 [property Obj1] : Object | semmle.label | object creation of type C4 : C4 [property Obj1] : Object |
| Constructors.cs:132:18:132:31 | object creation of type C4 : C4 [property Obj2] : Object | semmle.label | object creation of type C4 : C4 [property Obj2] : Object |
| Constructors.cs:132:25:132:26 | access to local variable o1 : Object | semmle.label | access to local variable o1 : Object |
| Constructors.cs:132:29:132:30 | access to local variable o2 : Object | semmle.label | access to local variable o2 : Object |
| Constructors.cs:133:14:133:15 | access to local variable c4 : C4 [property Obj1] : Object | semmle.label | access to local variable c4 : C4 [property Obj1] : Object |
| Constructors.cs:133:14:133:20 | access to property Obj1 | semmle.label | access to property Obj1 |
| Constructors.cs:134:14:134:15 | access to local variable c4 : C4 [property Obj2] : Object | semmle.label | access to local variable c4 : C4 [property Obj2] : Object |
| Constructors.cs:134:14:134:20 | access to property Obj2 | semmle.label | access to property Obj2 |
subpaths
| Constructors.cs:64:37:64:37 | access to parameter o : Object | Constructors.cs:57:54:57:55 | o2 : Object | Constructors.cs:59:13:59:19 | SSA def(o1) : Object | Constructors.cs:64:27:64:34 | SSA def(o22param) : Object |
| Constructors.cs:71:25:71:25 | access to local variable o : Object | Constructors.cs:41:26:41:26 | o : Object | Constructors.cs:41:32:41:34 | [post] this access : C1 [field Obj] : Object | Constructors.cs:71:18:71:26 | object creation of type C1 : C1 [field Obj] : Object |
@@ -147,6 +177,8 @@ subpaths
| Constructors.cs:101:14:101:15 | access to local variable c2 : C2 [parameter o22param] : Object | Constructors.cs:48:32:48:39 | this : C2 [parameter o22param] : Object | Constructors.cs:48:32:48:39 | access to parameter o22param : Object | Constructors.cs:101:14:101:21 | access to property Obj22 |
| Constructors.cs:112:25:112:27 | access to local variable o31 : Object | Constructors.cs:104:28:104:35 | o31param : Object | Constructors.cs:104:28:104:35 | o31param : Object | Constructors.cs:112:18:112:28 | object creation of type C3 : C3 [parameter o31param] : Object |
| Constructors.cs:113:14:113:15 | access to local variable c3 : C3 [parameter o31param] : Object | Constructors.cs:106:32:106:39 | this : C3 [parameter o31param] : Object | Constructors.cs:106:32:106:39 | access to parameter o31param : Object | Constructors.cs:113:14:113:21 | access to property Obj31 |
| Constructors.cs:132:25:132:26 | access to local variable o1 : Object | Constructors.cs:121:26:121:28 | oc1 : Object | Constructors.cs:123:13:123:16 | [post] this access : C4 [property Obj1] : Object | Constructors.cs:132:18:132:31 | object creation of type C4 : C4 [property Obj1] : Object |
| Constructors.cs:132:29:132:30 | access to local variable o2 : Object | Constructors.cs:121:38:121:40 | oc2 : Object | Constructors.cs:124:13:124:16 | [post] this access : C4 [property Obj2] : Object | Constructors.cs:132:18:132:31 | object creation of type C4 : C4 [property Obj2] : Object |
#select
| Constructors.cs:15:18:15:19 | access to field s1 | Constructors.cs:5:29:5:45 | call to method Source<Object> : Object | Constructors.cs:15:18:15:19 | access to field s1 | $@ | Constructors.cs:5:29:5:45 | call to method Source<Object> : Object | call to method Source<Object> : Object |
| Constructors.cs:33:18:33:19 | access to field s1 | Constructors.cs:21:29:21:45 | call to method Source<Object> : Object | Constructors.cs:33:18:33:19 | access to field s1 | $@ | Constructors.cs:21:29:21:45 | call to method Source<Object> : Object | call to method Source<Object> : Object |
@@ -157,3 +189,5 @@ subpaths
| Constructors.cs:93:14:93:21 | access to property Obj22 | Constructors.cs:91:21:91:37 | call to method Source<Object> : Object | Constructors.cs:93:14:93:21 | access to property Obj22 | $@ | Constructors.cs:91:21:91:37 | call to method Source<Object> : Object | call to method Source<Object> : Object |
| Constructors.cs:101:14:101:21 | access to property Obj22 | Constructors.cs:99:21:99:37 | call to method Source<Object> : Object | Constructors.cs:101:14:101:21 | access to property Obj22 | $@ | Constructors.cs:99:21:99:37 | call to method Source<Object> : Object | call to method Source<Object> : Object |
| Constructors.cs:113:14:113:21 | access to property Obj31 | Constructors.cs:111:19:111:35 | call to method Source<Object> : Object | Constructors.cs:113:14:113:21 | access to property Obj31 | $@ | Constructors.cs:111:19:111:35 | call to method Source<Object> : Object | call to method Source<Object> : Object |
| Constructors.cs:133:14:133:20 | access to property Obj1 | Constructors.cs:130:18:130:34 | call to method Source<Object> : Object | Constructors.cs:133:14:133:20 | access to property Obj1 | $@ | Constructors.cs:130:18:130:34 | call to method Source<Object> : Object | call to method Source<Object> : Object |
| Constructors.cs:134:14:134:20 | access to property Obj2 | Constructors.cs:131:18:131:34 | call to method Source<Object> : Object | Constructors.cs:134:14:134:20 | access to property Obj2 | $@ | Constructors.cs:131:18:131:34 | call to method Source<Object> : Object | call to method Source<Object> : Object |

View File

@@ -113,6 +113,27 @@ public class Constructors
Sink(c3.Obj31); // $ hasValueFlow=6
}
public class C4
{
public object Obj1 { get; init; }
public object Obj2 { get; }
public C4(object oc1, object oc2)
{
Obj1 = oc1;
Obj2 = oc2;
}
}
public void M6()
{
var o1 = Source<object>(7);
var o2 = Source<object>(8);
var c4 = new C4(o1, o2);
Sink(c4.Obj1); // $ hasValueFlow=7
Sink(c4.Obj2); // $ hasValueFlow=8
}
public static void Sink(object o) { }
public static T Source<T>(object source) => throw null;