Merge pull request #18533 from michaelnebel/csharp/partialmembers

C# 13: Partial properties and indexers.
This commit is contained in:
Michael Nebel
2025-02-03 13:18:43 +01:00
committed by GitHub
25 changed files with 456 additions and 43 deletions

View File

@@ -30,6 +30,10 @@ namespace Semmle.Extraction.CSharp.Entities
return props.SingleOrDefault();
}
public override bool NeedsPopulation =>
base.NeedsPopulation &&
!Symbol.IsPartialDefinition; // Accessors always have an implementing declaration as well.
public override void Populate(TextWriter trapFile)
{
PopulateMethod(trapFile);

View File

@@ -22,16 +22,16 @@ namespace Semmle.Extraction.CSharp.Entities
foreach (var l in Locations)
trapFile.indexer_location(this, l);
var getter = Symbol.GetMethod;
var setter = Symbol.SetMethod;
var getter = BodyDeclaringSymbol.GetMethod;
var setter = BodyDeclaringSymbol.SetMethod;
if (getter is null && setter is null)
Context.ModelError(Symbol, "No indexer accessor defined");
if (!(getter is null))
if (getter is not null)
Method.Create(Context, getter);
if (!(setter is null))
if (setter is not null)
Method.Create(Context, setter);
for (var i = 0; i < Symbol.Parameters.Length; ++i)

View File

@@ -21,6 +21,10 @@ namespace Semmle.Extraction.CSharp.Entities
private Type Type => type.Value;
protected override IPropertySymbol BodyDeclaringSymbol => Symbol.PartialImplementationPart ?? Symbol;
public override Microsoft.CodeAnalysis.Location? ReportingLocation => BodyDeclaringSymbol.Locations.BestOrDefault();
public override void WriteId(EscapingTextWriter trapFile)
{
trapFile.WriteSubId(Type);
@@ -43,13 +47,13 @@ namespace Semmle.Extraction.CSharp.Entities
var type = Type;
trapFile.properties(this, Symbol.GetName(), ContainingType!, type.TypeRef, Create(Context, Symbol.OriginalDefinition));
var getter = Symbol.GetMethod;
var setter = Symbol.SetMethod;
var getter = BodyDeclaringSymbol.GetMethod;
var setter = BodyDeclaringSymbol.SetMethod;
if (!(getter is null))
if (getter is not null)
Method.Create(Context, getter);
if (!(setter is null))
if (setter is not null)
Method.Create(Context, setter);
var declSyntaxReferences = IsSourceDeclaration ?

View File

@@ -0,0 +1,4 @@
---
category: minorAnalysis
---
* C# 13: Added support for partial properties and indexers.

View File

@@ -51,3 +51,41 @@ public class D
static T Source<T>(object source) => throw null;
}
public partial class DPartial
{
private object _backingField;
public partial object PartialProp1
{
get { return _backingField; }
set { _backingField = value; }
}
public partial object PartialProp2
{
get { return null; }
set { }
}
}
public partial class DPartial
{
public partial object PartialProp1 { get; set; }
public partial object PartialProp2 { get; set; }
public void M()
{
var o = Source<object>(1);
var d = new DPartial();
d.PartialProp1 = o;
d.PartialProp2 = o;
Sink(d.PartialProp1); // $ hasValueFlow=1
Sink(d.PartialProp2); // no flow
}
public static void Sink(object o) { }
static T Source<T>(object source) => throw null;
}

View File

@@ -502,6 +502,30 @@ edges
| D.cs:47:14:47:14 | access to local variable d : D [field trivialPropField] : Object | D.cs:14:9:14:11 | this : D [field trivialPropField] : Object | provenance | |
| D.cs:47:14:47:14 | access to local variable d : D [field trivialPropField] : Object | D.cs:47:14:47:26 | access to property ComplexProp | provenance | |
| D.cs:47:14:47:14 | access to local variable d : D [field trivialPropField] : Object | D.cs:47:14:47:26 | access to property ComplexProp | provenance | |
| D.cs:60:9:60:11 | this : DPartial [field _backingField] : Object | D.cs:60:22:60:34 | this access : DPartial [field _backingField] : Object | provenance | |
| D.cs:60:9:60:11 | this : DPartial [field _backingField] : Object | D.cs:60:22:60:34 | this access : DPartial [field _backingField] : Object | provenance | |
| D.cs:60:22:60:34 | this access : DPartial [field _backingField] : Object | D.cs:60:22:60:34 | access to field _backingField : Object | provenance | |
| D.cs:60:22:60:34 | this access : DPartial [field _backingField] : Object | D.cs:60:22:60:34 | access to field _backingField : Object | provenance | |
| D.cs:61:9:61:11 | value : Object | D.cs:61:31:61:35 | access to parameter value : Object | provenance | |
| D.cs:61:9:61:11 | value : Object | D.cs:61:31:61:35 | access to parameter value : Object | provenance | |
| D.cs:61:15:61:27 | [post] this access : DPartial [field _backingField] : Object | D.cs:61:9:61:11 | this [Return] : DPartial [field _backingField] : Object | provenance | |
| D.cs:61:15:61:27 | [post] this access : DPartial [field _backingField] : Object | D.cs:61:9:61:11 | this [Return] : DPartial [field _backingField] : Object | provenance | |
| D.cs:61:31:61:35 | access to parameter value : Object | D.cs:61:15:61:27 | [post] this access : DPartial [field _backingField] : Object | provenance | |
| D.cs:61:31:61:35 | access to parameter value : Object | D.cs:61:15:61:27 | [post] this access : DPartial [field _backingField] : Object | provenance | |
| D.cs:78:13:78:13 | access to local variable o : Object | D.cs:81:26:81:26 | access to local variable o : Object | provenance | |
| D.cs:78:13:78:13 | access to local variable o : Object | D.cs:81:26:81:26 | access to local variable o : Object | provenance | |
| D.cs:78:17:78:33 | call to method Source<Object> : Object | D.cs:78:13:78:13 | access to local variable o : Object | provenance | |
| D.cs:78:17:78:33 | call to method Source<Object> : Object | D.cs:78:13:78:13 | access to local variable o : Object | provenance | |
| D.cs:81:9:81:9 | [post] access to local variable d : DPartial [field _backingField] : Object | D.cs:84:14:84:14 | access to local variable d : DPartial [field _backingField] : Object | provenance | |
| D.cs:81:9:81:9 | [post] access to local variable d : DPartial [field _backingField] : Object | D.cs:84:14:84:14 | access to local variable d : DPartial [field _backingField] : Object | provenance | |
| D.cs:81:26:81:26 | access to local variable o : Object | D.cs:61:9:61:11 | value : Object | provenance | |
| D.cs:81:26:81:26 | access to local variable o : Object | D.cs:61:9:61:11 | value : Object | provenance | |
| D.cs:81:26:81:26 | access to local variable o : Object | D.cs:81:9:81:9 | [post] access to local variable d : DPartial [field _backingField] : Object | provenance | |
| D.cs:81:26:81:26 | access to local variable o : Object | D.cs:81:9:81:9 | [post] access to local variable d : DPartial [field _backingField] : Object | provenance | |
| D.cs:84:14:84:14 | access to local variable d : DPartial [field _backingField] : Object | D.cs:60:9:60:11 | this : DPartial [field _backingField] : Object | provenance | |
| D.cs:84:14:84:14 | access to local variable d : DPartial [field _backingField] : Object | D.cs:60:9:60:11 | this : DPartial [field _backingField] : Object | provenance | |
| D.cs:84:14:84:14 | access to local variable d : DPartial [field _backingField] : Object | D.cs:84:14:84:27 | access to property PartialProp1 | provenance | |
| D.cs:84:14:84:14 | access to local variable d : DPartial [field _backingField] : Object | D.cs:84:14:84:27 | access to property PartialProp1 | provenance | |
| E.cs:8:29:8:29 | o : Object | E.cs:11:21:11:21 | access to parameter o : Object | provenance | |
| E.cs:8:29:8:29 | o : Object | E.cs:11:21:11:21 | access to parameter o : Object | provenance | |
| E.cs:11:9:11:11 | [post] access to local variable ret : S [field Field] : Object | E.cs:12:16:12:18 | access to local variable ret : S [field Field] : Object | provenance | |
@@ -1745,6 +1769,32 @@ nodes
| D.cs:47:14:47:14 | access to local variable d : D [field trivialPropField] : Object | semmle.label | access to local variable d : D [field trivialPropField] : Object |
| D.cs:47:14:47:26 | access to property ComplexProp | semmle.label | access to property ComplexProp |
| D.cs:47:14:47:26 | access to property ComplexProp | semmle.label | access to property ComplexProp |
| D.cs:60:9:60:11 | this : DPartial [field _backingField] : Object | semmle.label | this : DPartial [field _backingField] : Object |
| D.cs:60:9:60:11 | this : DPartial [field _backingField] : Object | semmle.label | this : DPartial [field _backingField] : Object |
| D.cs:60:22:60:34 | access to field _backingField : Object | semmle.label | access to field _backingField : Object |
| D.cs:60:22:60:34 | access to field _backingField : Object | semmle.label | access to field _backingField : Object |
| D.cs:60:22:60:34 | this access : DPartial [field _backingField] : Object | semmle.label | this access : DPartial [field _backingField] : Object |
| D.cs:60:22:60:34 | this access : DPartial [field _backingField] : Object | semmle.label | this access : DPartial [field _backingField] : Object |
| D.cs:61:9:61:11 | this [Return] : DPartial [field _backingField] : Object | semmle.label | this [Return] : DPartial [field _backingField] : Object |
| D.cs:61:9:61:11 | this [Return] : DPartial [field _backingField] : Object | semmle.label | this [Return] : DPartial [field _backingField] : Object |
| D.cs:61:9:61:11 | value : Object | semmle.label | value : Object |
| D.cs:61:9:61:11 | value : Object | semmle.label | value : Object |
| D.cs:61:15:61:27 | [post] this access : DPartial [field _backingField] : Object | semmle.label | [post] this access : DPartial [field _backingField] : Object |
| D.cs:61:15:61:27 | [post] this access : DPartial [field _backingField] : Object | semmle.label | [post] this access : DPartial [field _backingField] : Object |
| D.cs:61:31:61:35 | access to parameter value : Object | semmle.label | access to parameter value : Object |
| D.cs:61:31:61:35 | access to parameter value : Object | semmle.label | access to parameter value : Object |
| D.cs:78:13:78:13 | access to local variable o : Object | semmle.label | access to local variable o : Object |
| D.cs:78:13:78:13 | access to local variable o : Object | semmle.label | access to local variable o : Object |
| D.cs:78:17:78:33 | call to method Source<Object> : Object | semmle.label | call to method Source<Object> : Object |
| D.cs:78:17:78:33 | call to method Source<Object> : Object | semmle.label | call to method Source<Object> : Object |
| D.cs:81:9:81:9 | [post] access to local variable d : DPartial [field _backingField] : Object | semmle.label | [post] access to local variable d : DPartial [field _backingField] : Object |
| D.cs:81:9:81:9 | [post] access to local variable d : DPartial [field _backingField] : Object | semmle.label | [post] access to local variable d : DPartial [field _backingField] : Object |
| D.cs:81:26:81:26 | access to local variable o : Object | semmle.label | access to local variable o : Object |
| D.cs:81:26:81:26 | access to local variable o : Object | semmle.label | access to local variable o : Object |
| D.cs:84:14:84:14 | access to local variable d : DPartial [field _backingField] : Object | semmle.label | access to local variable d : DPartial [field _backingField] : Object |
| D.cs:84:14:84:14 | access to local variable d : DPartial [field _backingField] : Object | semmle.label | access to local variable d : DPartial [field _backingField] : Object |
| D.cs:84:14:84:27 | access to property PartialProp1 | semmle.label | access to property PartialProp1 |
| D.cs:84:14:84:27 | access to property PartialProp1 | semmle.label | access to property PartialProp1 |
| E.cs:8:29:8:29 | o : Object | semmle.label | o : Object |
| E.cs:8:29:8:29 | o : Object | semmle.label | o : Object |
| E.cs:11:9:11:11 | [post] access to local variable ret : S [field Field] : Object | semmle.label | [post] access to local variable ret : S [field Field] : Object |
@@ -2582,6 +2632,10 @@ subpaths
| D.cs:45:14:45:14 | access to local variable d : D [field trivialPropField] : Object | D.cs:8:9:8:11 | this : D [field trivialPropField] : Object | D.cs:8:22:8:42 | access to field trivialPropField : Object | D.cs:45:14:45:26 | access to property TrivialProp |
| D.cs:47:14:47:14 | access to local variable d : D [field trivialPropField] : Object | D.cs:14:9:14:11 | this : D [field trivialPropField] : Object | D.cs:14:22:14:42 | access to field trivialPropField : Object | D.cs:47:14:47:26 | access to property ComplexProp |
| D.cs:47:14:47:14 | access to local variable d : D [field trivialPropField] : Object | D.cs:14:9:14:11 | this : D [field trivialPropField] : Object | D.cs:14:22:14:42 | access to field trivialPropField : Object | D.cs:47:14:47:26 | access to property ComplexProp |
| D.cs:81:26:81:26 | access to local variable o : Object | D.cs:61:9:61:11 | value : Object | D.cs:61:9:61:11 | this [Return] : DPartial [field _backingField] : Object | D.cs:81:9:81:9 | [post] access to local variable d : DPartial [field _backingField] : Object |
| D.cs:81:26:81:26 | access to local variable o : Object | D.cs:61:9:61:11 | value : Object | D.cs:61:9:61:11 | this [Return] : DPartial [field _backingField] : Object | D.cs:81:9:81:9 | [post] access to local variable d : DPartial [field _backingField] : Object |
| D.cs:84:14:84:14 | access to local variable d : DPartial [field _backingField] : Object | D.cs:60:9:60:11 | this : DPartial [field _backingField] : Object | D.cs:60:22:60:34 | access to field _backingField : Object | D.cs:84:14:84:27 | access to property PartialProp1 |
| D.cs:84:14:84:14 | access to local variable d : DPartial [field _backingField] : Object | D.cs:60:9:60:11 | this : DPartial [field _backingField] : Object | D.cs:60:22:60:34 | access to field _backingField : Object | D.cs:84:14:84:27 | access to property PartialProp1 |
| E.cs:23:25:23:25 | access to local variable o : Object | E.cs:8:29:8:29 | o : Object | E.cs:12:16:12:18 | access to local variable ret : S [field Field] : Object | E.cs:23:17:23:26 | call to method CreateS : S [field Field] : Object |
| E.cs:23:25:23:25 | access to local variable o : Object | E.cs:8:29:8:29 | o : Object | E.cs:12:16:12:18 | access to local variable ret : S [field Field] : Object | E.cs:23:17:23:26 | call to method CreateS : S [field Field] : Object |
| E.cs:55:29:55:33 | access to local variable taint : Object | E.cs:43:46:43:46 | o : Object | E.cs:43:36:43:36 | s [Return] : RefS [field RefField] : Object | E.cs:55:23:55:26 | [post] access to local variable refs : RefS [field RefField] : Object |
@@ -2690,6 +2744,8 @@ testFailures
| D.cs:46:14:46:31 | access to field trivialPropField | D.cs:43:32:43:48 | call to method Source<Object> : Object | D.cs:46:14:46:31 | access to field trivialPropField | $@ | D.cs:43:32:43:48 | call to method Source<Object> : Object | call to method Source<Object> : Object |
| D.cs:47:14:47:26 | access to property ComplexProp | D.cs:43:32:43:48 | call to method Source<Object> : Object | D.cs:47:14:47:26 | access to property ComplexProp | $@ | D.cs:43:32:43:48 | call to method Source<Object> : Object | call to method Source<Object> : Object |
| D.cs:47:14:47:26 | access to property ComplexProp | D.cs:43:32:43:48 | call to method Source<Object> : Object | D.cs:47:14:47:26 | access to property ComplexProp | $@ | D.cs:43:32:43:48 | call to method Source<Object> : Object | call to method Source<Object> : Object |
| D.cs:84:14:84:27 | access to property PartialProp1 | D.cs:78:17:78:33 | call to method Source<Object> : Object | D.cs:84:14:84:27 | access to property PartialProp1 | $@ | D.cs:78:17:78:33 | call to method Source<Object> : Object | call to method Source<Object> : Object |
| D.cs:84:14:84:27 | access to property PartialProp1 | D.cs:78:17:78:33 | call to method Source<Object> : Object | D.cs:84:14:84:27 | access to property PartialProp1 | $@ | D.cs:78:17:78:33 | call to method Source<Object> : Object | call to method Source<Object> : Object |
| E.cs:24:14:24:20 | access to field Field | E.cs:22:17:22:33 | call to method Source<Object> : Object | E.cs:24:14:24:20 | access to field Field | $@ | E.cs:22:17:22:33 | call to method Source<Object> : Object | call to method Source<Object> : Object |
| E.cs:24:14:24:20 | access to field Field | E.cs:22:17:22:33 | call to method Source<Object> : Object | E.cs:24:14:24:20 | access to field Field | $@ | E.cs:22:17:22:33 | call to method Source<Object> : Object | call to method Source<Object> : Object |
| E.cs:57:14:57:26 | access to field RefField | E.cs:54:21:54:37 | call to method Source<Object> : Object | E.cs:57:14:57:26 | access to field RefField | $@ | E.cs:54:21:54:37 | call to method Source<Object> : Object | call to method Source<Object> : Object |

View File

@@ -0,0 +1,70 @@
models
edges
| Indexers.cs:6:9:6:11 | this : Partial1 [field _backingArray, element] : Object | Indexers.cs:6:22:6:34 | this access : Partial1 [field _backingArray, element] : Object | provenance | |
| Indexers.cs:6:9:6:11 | this : Partial1 [field _backingArray, element] : Object | Indexers.cs:6:22:6:34 | this access : Partial1 [field _backingArray, element] : Object | provenance | |
| Indexers.cs:6:22:6:34 | access to field _backingArray : Object[] [element] : Object | Indexers.cs:6:22:6:41 | access to array element : Object | provenance | |
| Indexers.cs:6:22:6:34 | access to field _backingArray : Object[] [element] : Object | Indexers.cs:6:22:6:41 | access to array element : Object | provenance | |
| Indexers.cs:6:22:6:34 | this access : Partial1 [field _backingArray, element] : Object | Indexers.cs:6:22:6:34 | access to field _backingArray : Object[] [element] : Object | provenance | |
| Indexers.cs:6:22:6:34 | this access : Partial1 [field _backingArray, element] : Object | Indexers.cs:6:22:6:34 | access to field _backingArray : Object[] [element] : Object | provenance | |
| Indexers.cs:7:9:7:11 | value : Object | Indexers.cs:7:38:7:42 | access to parameter value : Object | provenance | |
| Indexers.cs:7:9:7:11 | value : Object | Indexers.cs:7:38:7:42 | access to parameter value : Object | provenance | |
| Indexers.cs:7:15:7:27 | [post] access to field _backingArray : Object[] [element] : Object | Indexers.cs:7:15:7:27 | [post] this access : Partial1 [field _backingArray, element] : Object | provenance | |
| Indexers.cs:7:15:7:27 | [post] access to field _backingArray : Object[] [element] : Object | Indexers.cs:7:15:7:27 | [post] this access : Partial1 [field _backingArray, element] : Object | provenance | |
| Indexers.cs:7:15:7:27 | [post] this access : Partial1 [field _backingArray, element] : Object | Indexers.cs:7:9:7:11 | this [Return] : Partial1 [field _backingArray, element] : Object | provenance | |
| Indexers.cs:7:15:7:27 | [post] this access : Partial1 [field _backingArray, element] : Object | Indexers.cs:7:9:7:11 | this [Return] : Partial1 [field _backingArray, element] : Object | provenance | |
| Indexers.cs:7:38:7:42 | access to parameter value : Object | Indexers.cs:7:15:7:27 | [post] access to field _backingArray : Object[] [element] : Object | provenance | |
| Indexers.cs:7:38:7:42 | access to parameter value : Object | Indexers.cs:7:15:7:27 | [post] access to field _backingArray : Object[] [element] : Object | provenance | |
| Indexers.cs:34:13:34:13 | access to local variable o : Object | Indexers.cs:37:17:37:17 | access to local variable o : Object | provenance | |
| Indexers.cs:34:13:34:13 | access to local variable o : Object | Indexers.cs:37:17:37:17 | access to local variable o : Object | provenance | |
| Indexers.cs:34:17:34:33 | call to method Source<Object> : Object | Indexers.cs:34:13:34:13 | access to local variable o : Object | provenance | |
| Indexers.cs:34:17:34:33 | call to method Source<Object> : Object | Indexers.cs:34:13:34:13 | access to local variable o : Object | provenance | |
| Indexers.cs:37:9:37:10 | [post] access to local variable p1 : Partial1 [field _backingArray, element] : Object | Indexers.cs:38:14:38:15 | access to local variable p1 : Partial1 [field _backingArray, element] : Object | provenance | |
| Indexers.cs:37:9:37:10 | [post] access to local variable p1 : Partial1 [field _backingArray, element] : Object | Indexers.cs:38:14:38:15 | access to local variable p1 : Partial1 [field _backingArray, element] : Object | provenance | |
| Indexers.cs:37:17:37:17 | access to local variable o : Object | Indexers.cs:7:9:7:11 | value : Object | provenance | |
| Indexers.cs:37:17:37:17 | access to local variable o : Object | Indexers.cs:7:9:7:11 | value : Object | provenance | |
| Indexers.cs:37:17:37:17 | access to local variable o : Object | Indexers.cs:37:9:37:10 | [post] access to local variable p1 : Partial1 [field _backingArray, element] : Object | provenance | |
| Indexers.cs:37:17:37:17 | access to local variable o : Object | Indexers.cs:37:9:37:10 | [post] access to local variable p1 : Partial1 [field _backingArray, element] : Object | provenance | |
| Indexers.cs:38:14:38:15 | access to local variable p1 : Partial1 [field _backingArray, element] : Object | Indexers.cs:6:9:6:11 | this : Partial1 [field _backingArray, element] : Object | provenance | |
| Indexers.cs:38:14:38:15 | access to local variable p1 : Partial1 [field _backingArray, element] : Object | Indexers.cs:6:9:6:11 | this : Partial1 [field _backingArray, element] : Object | provenance | |
| Indexers.cs:38:14:38:15 | access to local variable p1 : Partial1 [field _backingArray, element] : Object | Indexers.cs:38:14:38:18 | access to indexer | provenance | |
| Indexers.cs:38:14:38:15 | access to local variable p1 : Partial1 [field _backingArray, element] : Object | Indexers.cs:38:14:38:18 | access to indexer | provenance | |
nodes
| Indexers.cs:6:9:6:11 | this : Partial1 [field _backingArray, element] : Object | semmle.label | this : Partial1 [field _backingArray, element] : Object |
| Indexers.cs:6:9:6:11 | this : Partial1 [field _backingArray, element] : Object | semmle.label | this : Partial1 [field _backingArray, element] : Object |
| Indexers.cs:6:22:6:34 | access to field _backingArray : Object[] [element] : Object | semmle.label | access to field _backingArray : Object[] [element] : Object |
| Indexers.cs:6:22:6:34 | access to field _backingArray : Object[] [element] : Object | semmle.label | access to field _backingArray : Object[] [element] : Object |
| Indexers.cs:6:22:6:34 | this access : Partial1 [field _backingArray, element] : Object | semmle.label | this access : Partial1 [field _backingArray, element] : Object |
| Indexers.cs:6:22:6:34 | this access : Partial1 [field _backingArray, element] : Object | semmle.label | this access : Partial1 [field _backingArray, element] : Object |
| Indexers.cs:6:22:6:41 | access to array element : Object | semmle.label | access to array element : Object |
| Indexers.cs:6:22:6:41 | access to array element : Object | semmle.label | access to array element : Object |
| Indexers.cs:7:9:7:11 | this [Return] : Partial1 [field _backingArray, element] : Object | semmle.label | this [Return] : Partial1 [field _backingArray, element] : Object |
| Indexers.cs:7:9:7:11 | this [Return] : Partial1 [field _backingArray, element] : Object | semmle.label | this [Return] : Partial1 [field _backingArray, element] : Object |
| Indexers.cs:7:9:7:11 | value : Object | semmle.label | value : Object |
| Indexers.cs:7:9:7:11 | value : Object | semmle.label | value : Object |
| Indexers.cs:7:15:7:27 | [post] access to field _backingArray : Object[] [element] : Object | semmle.label | [post] access to field _backingArray : Object[] [element] : Object |
| Indexers.cs:7:15:7:27 | [post] access to field _backingArray : Object[] [element] : Object | semmle.label | [post] access to field _backingArray : Object[] [element] : Object |
| Indexers.cs:7:15:7:27 | [post] this access : Partial1 [field _backingArray, element] : Object | semmle.label | [post] this access : Partial1 [field _backingArray, element] : Object |
| Indexers.cs:7:15:7:27 | [post] this access : Partial1 [field _backingArray, element] : Object | semmle.label | [post] this access : Partial1 [field _backingArray, element] : Object |
| Indexers.cs:7:38:7:42 | access to parameter value : Object | semmle.label | access to parameter value : Object |
| Indexers.cs:7:38:7:42 | access to parameter value : Object | semmle.label | access to parameter value : Object |
| Indexers.cs:34:13:34:13 | access to local variable o : Object | semmle.label | access to local variable o : Object |
| Indexers.cs:34:13:34:13 | access to local variable o : Object | semmle.label | access to local variable o : Object |
| Indexers.cs:34:17:34:33 | call to method Source<Object> : Object | semmle.label | call to method Source<Object> : Object |
| Indexers.cs:34:17:34:33 | call to method Source<Object> : Object | semmle.label | call to method Source<Object> : Object |
| Indexers.cs:37:9:37:10 | [post] access to local variable p1 : Partial1 [field _backingArray, element] : Object | semmle.label | [post] access to local variable p1 : Partial1 [field _backingArray, element] : Object |
| Indexers.cs:37:9:37:10 | [post] access to local variable p1 : Partial1 [field _backingArray, element] : Object | semmle.label | [post] access to local variable p1 : Partial1 [field _backingArray, element] : Object |
| Indexers.cs:37:17:37:17 | access to local variable o : Object | semmle.label | access to local variable o : Object |
| Indexers.cs:37:17:37:17 | access to local variable o : Object | semmle.label | access to local variable o : Object |
| Indexers.cs:38:14:38:15 | access to local variable p1 : Partial1 [field _backingArray, element] : Object | semmle.label | access to local variable p1 : Partial1 [field _backingArray, element] : Object |
| Indexers.cs:38:14:38:15 | access to local variable p1 : Partial1 [field _backingArray, element] : Object | semmle.label | access to local variable p1 : Partial1 [field _backingArray, element] : Object |
| Indexers.cs:38:14:38:18 | access to indexer | semmle.label | access to indexer |
| Indexers.cs:38:14:38:18 | access to indexer | semmle.label | access to indexer |
subpaths
| Indexers.cs:37:17:37:17 | access to local variable o : Object | Indexers.cs:7:9:7:11 | value : Object | Indexers.cs:7:9:7:11 | this [Return] : Partial1 [field _backingArray, element] : Object | Indexers.cs:37:9:37:10 | [post] access to local variable p1 : Partial1 [field _backingArray, element] : Object |
| Indexers.cs:37:17:37:17 | access to local variable o : Object | Indexers.cs:7:9:7:11 | value : Object | Indexers.cs:7:9:7:11 | this [Return] : Partial1 [field _backingArray, element] : Object | Indexers.cs:37:9:37:10 | [post] access to local variable p1 : Partial1 [field _backingArray, element] : Object |
| Indexers.cs:38:14:38:15 | access to local variable p1 : Partial1 [field _backingArray, element] : Object | Indexers.cs:6:9:6:11 | this : Partial1 [field _backingArray, element] : Object | Indexers.cs:6:22:6:41 | access to array element : Object | Indexers.cs:38:14:38:18 | access to indexer |
| Indexers.cs:38:14:38:15 | access to local variable p1 : Partial1 [field _backingArray, element] : Object | Indexers.cs:6:9:6:11 | this : Partial1 [field _backingArray, element] : Object | Indexers.cs:6:22:6:41 | access to array element : Object | Indexers.cs:38:14:38:18 | access to indexer |
testFailures
#select
| Indexers.cs:38:14:38:18 | access to indexer | Indexers.cs:34:17:34:33 | call to method Source<Object> : Object | Indexers.cs:38:14:38:18 | access to indexer | $@ | Indexers.cs:34:17:34:33 | call to method Source<Object> : Object | call to method Source<Object> : Object |
| Indexers.cs:38:14:38:18 | access to indexer | Indexers.cs:34:17:34:33 | call to method Source<Object> : Object | Indexers.cs:38:14:38:18 | access to indexer | $@ | Indexers.cs:34:17:34:33 | call to method Source<Object> : Object | call to method Source<Object> : Object |

View File

@@ -0,0 +1,12 @@
/**
* @kind path-problem
*/
import csharp
import utils.test.InlineFlowTest
import DefaultFlowTest
import PathGraph
from PathNode source, PathNode sink
where flowPath(source, sink)
select sink, source, sink, "$@", source, source.toString()

View File

@@ -0,0 +1,48 @@
public partial class Partial1
{
private object[] _backingArray = new object[10];
public partial object this[int index]
{
get { return _backingArray[index]; }
set { _backingArray[index] = value; }
}
}
public partial class Partial1
{
public partial object this[int index] { get; set; }
}
public partial class Partial2
{
public partial object this[int index]
{
get { return null; }
set { }
}
}
public partial class Partial2
{
public partial object this[int index] { get; set; }
}
public partial class PartialTest
{
public void M()
{
var o = Source<object>(1);
var p1 = new Partial1();
p1[0] = o;
Sink(p1[0]); // $ hasValueFlow=1
var p2 = new Partial2();
p2[0] = o;
Sink(p2[0]); // no flow
}
public static void Sink(object o) { }
static T Source<T>(object source) => throw null;
}

View File

@@ -270,3 +270,7 @@
| ViableCallable.cs:679:17:679:20 | Run3 | ViableCallable.cs:637:21:637:21 | M |
| ViableCallable.cs:679:17:679:20 | Run3 | ViableCallable.cs:646:21:646:21 | M |
| ViableCallable.cs:679:17:679:20 | Run3 | ViableCallable.cs:648:21:648:21 | M |
| ViableCallable.cs:707:17:707:20 | Run1 | ViableCallable.cs:702:42:702:44 | get_Property |
| ViableCallable.cs:707:17:707:20 | Run1 | ViableCallable.cs:702:63:702:65 | set_Property |
| ViableCallable.cs:707:17:707:20 | Run1 | ViableCallable.cs:704:49:704:51 | get_Item |
| ViableCallable.cs:707:17:707:20 | Run1 | ViableCallable.cs:704:70:704:72 | set_Item |

View File

@@ -379,6 +379,7 @@
| ViableCallable.cs:165:9:165:14 | dynamic access to element | C8.set_Item(int, string) |
| ViableCallable.cs:165:9:165:14 | dynamic access to element | C9`1.set_Item(int, string) |
| ViableCallable.cs:165:9:165:14 | dynamic access to element | C10.set_Item(int, bool) |
| ViableCallable.cs:165:9:165:14 | dynamic access to element | C23+Partial1.set_Item(int, object) |
| ViableCallable.cs:165:18:165:23 | dynamic access to element | C2<System.Decimal>.get_Item(decimal) |
| ViableCallable.cs:165:18:165:23 | dynamic access to element | C2<System.Int32>.get_Item(int) |
| ViableCallable.cs:165:18:165:23 | dynamic access to element | C2`1.get_Item(T) |
@@ -393,6 +394,7 @@
| ViableCallable.cs:165:18:165:23 | dynamic access to element | C8.get_Item(int) |
| ViableCallable.cs:165:18:165:23 | dynamic access to element | C9`1.get_Item(int) |
| ViableCallable.cs:165:18:165:23 | dynamic access to element | C10.get_Item(int) |
| ViableCallable.cs:165:18:165:23 | dynamic access to element | C23+Partial1.get_Item(int) |
| ViableCallable.cs:167:9:167:54 | ... += ... | C2<System.Boolean>.add_Event(EventHandler<string>) |
| ViableCallable.cs:167:9:167:54 | ... += ... | C2<System.Decimal>.add_Event(EventHandler<string>) |
| ViableCallable.cs:167:9:167:54 | ... += ... | C2<System.Int32>.add_Event(EventHandler<string>) |
@@ -516,3 +518,7 @@
| ViableCallable.cs:683:9:683:16 | call to method M | C22+TestOverloadResolution2<System.Int32>.M(Int32[]) |
| ViableCallable.cs:687:9:687:16 | call to method M | C22+TestOverloadResolution1<System.Int32>.M(List<int>) |
| ViableCallable.cs:687:9:687:16 | call to method M | C22+TestOverloadResolution2<System.Int32>.M(List<int>) |
| ViableCallable.cs:712:9:712:18 | access to property Property | C23+Partial1.set_Property(object) |
| ViableCallable.cs:715:13:715:22 | access to property Property | C23+Partial1.get_Property() |
| ViableCallable.cs:718:9:718:12 | access to indexer | C23+Partial1.set_Item(int, object) |
| ViableCallable.cs:721:13:721:16 | access to indexer | C23+Partial1.get_Item(int) |

View File

@@ -687,3 +687,37 @@ public class C22
tor.M(l);
}
}
public class C23
{
public partial class Partial1
{
public partial object Property { get; set; }
public partial object this[int index] { get; set; }
}
public partial class Partial1
{
public partial object Property { get { return null; } set { } }
public partial object this[int index] { get { return null; } set { } }
}
public void Run1(Partial1 p)
{
object o;
// Viable callable: Partial1.set_Property
p.Property = new object();
// Viable callable: Partial1.get_Property
o = p.Property;
// Viable callable: Partial1.set_Item(int, object)
p[0] = new object();
// Viable callable: Partial1.get_Item(int)
o = p[0];
}
}

View File

@@ -199,6 +199,7 @@
| ViableCallable.cs:165:9:165:14 | dynamic access to element | set_Item | C8 |
| ViableCallable.cs:165:9:165:14 | dynamic access to element | set_Item | C9`1 |
| ViableCallable.cs:165:9:165:14 | dynamic access to element | set_Item | C10 |
| ViableCallable.cs:165:9:165:14 | dynamic access to element | set_Item | Partial1 |
| ViableCallable.cs:165:18:165:23 | dynamic access to element | get_Item | C2`1 |
| ViableCallable.cs:165:18:165:23 | dynamic access to element | get_Item | C3 |
| ViableCallable.cs:165:18:165:23 | dynamic access to element | get_Item | C6`2 |
@@ -206,6 +207,7 @@
| ViableCallable.cs:165:18:165:23 | dynamic access to element | get_Item | C8 |
| ViableCallable.cs:165:18:165:23 | dynamic access to element | get_Item | C9`1 |
| ViableCallable.cs:165:18:165:23 | dynamic access to element | get_Item | C10 |
| ViableCallable.cs:165:18:165:23 | dynamic access to element | get_Item | Partial1 |
| ViableCallable.cs:167:9:167:54 | ... += ... | add_Event | C2`1 |
| ViableCallable.cs:167:9:167:54 | ... += ... | add_Event | C3 |
| ViableCallable.cs:167:9:167:54 | ... += ... | add_Event | C5 |

View File

@@ -1,7 +1,7 @@
| Partial.cs:4:18:4:42 | PartialMethodWithoutBody1 | true |
| Partial.cs:5:17:5:23 | Method2 | false |
| Partial.cs:10:18:10:39 | PartialMethodWithBody1 | true |
| Partial.cs:11:17:11:23 | Method3 | false |
| Partial.cs:16:18:16:42 | PartialMethodWithoutBody2 | true |
| Partial.cs:17:17:17:23 | Method4 | false |
| Partial.cs:22:17:22:23 | Method5 | false |
| Partial.cs:14:18:14:39 | PartialMethodWithBody1 | true |
| Partial.cs:15:17:15:23 | Method3 | false |
| Partial.cs:34:18:34:42 | PartialMethodWithoutBody2 | true |
| Partial.cs:35:17:35:23 | Method4 | false |
| Partial.cs:40:17:40:23 | Method5 | false |

View File

@@ -3,12 +3,30 @@ partial class TwoPartClass
partial void PartialMethodWithBody1();
partial void PartialMethodWithoutBody1();
public void Method2() { }
// Declaring declaration.
public partial object PartialProperty1 { get; set; }
// Declaring declaration.
public partial object this[int index] { get; set; }
}
partial class TwoPartClass
{
partial void PartialMethodWithBody1() { }
public void Method3() { }
private object _backingField;
// Implementation declaration.
public partial object PartialProperty1
{
get { return _backingField; }
set { _backingField = value; }
}
private object[] _backingArray;
// Implmentation declaration.
public partial object this[int index]
{
get { return _backingArray[index]; }
set { _backingArray[index] = value; }
}
}
partial class OnePartPartialClass
@@ -20,4 +38,10 @@ partial class OnePartPartialClass
class NonPartialClass
{
public void Method5() { }
}
public object Property { get; set; }
public object this[int index]
{
get { return null; }
set { }
}
}

View File

@@ -1,6 +1,12 @@
| Partial.cs:1:15:1:26 | TwoPartClass |
| Partial.cs:4:18:4:42 | PartialMethodWithoutBody1 |
| Partial.cs:8:15:8:26 | TwoPartClass |
| Partial.cs:10:18:10:39 | PartialMethodWithBody1 |
| Partial.cs:14:15:14:33 | OnePartPartialClass |
| Partial.cs:16:18:16:42 | PartialMethodWithoutBody2 |
| Partial.cs:12:15:12:26 | TwoPartClass |
| Partial.cs:14:18:14:39 | PartialMethodWithBody1 |
| Partial.cs:18:27:18:42 | PartialProperty1 |
| Partial.cs:20:9:20:11 | get_PartialProperty1 |
| Partial.cs:21:9:21:11 | set_PartialProperty1 |
| Partial.cs:25:27:25:30 | Item |
| Partial.cs:27:9:27:11 | get_Item |
| Partial.cs:28:9:28:11 | set_Item |
| Partial.cs:32:15:32:33 | OnePartPartialClass |
| Partial.cs:34:18:34:42 | PartialMethodWithoutBody2 |

View File

@@ -1,10 +1,10 @@
| Partial.cs:1:15:1:26 | TwoPartClass | Partial.cs:4:18:4:42 | PartialMethodWithoutBody1 |
| Partial.cs:1:15:1:26 | TwoPartClass | Partial.cs:5:17:5:23 | Method2 |
| Partial.cs:1:15:1:26 | TwoPartClass | Partial.cs:10:18:10:39 | PartialMethodWithBody1 |
| Partial.cs:1:15:1:26 | TwoPartClass | Partial.cs:11:17:11:23 | Method3 |
| Partial.cs:8:15:8:26 | TwoPartClass | Partial.cs:4:18:4:42 | PartialMethodWithoutBody1 |
| Partial.cs:8:15:8:26 | TwoPartClass | Partial.cs:5:17:5:23 | Method2 |
| Partial.cs:8:15:8:26 | TwoPartClass | Partial.cs:10:18:10:39 | PartialMethodWithBody1 |
| Partial.cs:8:15:8:26 | TwoPartClass | Partial.cs:11:17:11:23 | Method3 |
| Partial.cs:14:15:14:33 | OnePartPartialClass | Partial.cs:16:18:16:42 | PartialMethodWithoutBody2 |
| Partial.cs:14:15:14:33 | OnePartPartialClass | Partial.cs:17:17:17:23 | Method4 |
| Partial.cs:1:15:1:26 | TwoPartClass | Partial.cs:14:18:14:39 | PartialMethodWithBody1 |
| Partial.cs:1:15:1:26 | TwoPartClass | Partial.cs:15:17:15:23 | Method3 |
| Partial.cs:12:15:12:26 | TwoPartClass | Partial.cs:4:18:4:42 | PartialMethodWithoutBody1 |
| Partial.cs:12:15:12:26 | TwoPartClass | Partial.cs:5:17:5:23 | Method2 |
| Partial.cs:12:15:12:26 | TwoPartClass | Partial.cs:14:18:14:39 | PartialMethodWithBody1 |
| Partial.cs:12:15:12:26 | TwoPartClass | Partial.cs:15:17:15:23 | Method3 |
| Partial.cs:32:15:32:33 | OnePartPartialClass | Partial.cs:34:18:34:42 | PartialMethodWithoutBody2 |
| Partial.cs:32:15:32:33 | OnePartPartialClass | Partial.cs:35:17:35:23 | Method4 |

View File

@@ -0,0 +1,8 @@
| Partial.cs:20:9:20:11 | get_PartialProperty1 | true |
| Partial.cs:21:9:21:11 | set_PartialProperty1 | true |
| Partial.cs:27:9:27:11 | get_Item | true |
| Partial.cs:28:9:28:11 | set_Item | true |
| Partial.cs:41:30:41:32 | get_Property | false |
| Partial.cs:41:35:41:37 | set_Property | false |
| Partial.cs:44:9:44:11 | get_Item | false |
| Partial.cs:45:9:45:11 | set_Item | false |

View File

@@ -0,0 +1,7 @@
import csharp
private boolean isPartial(Accessor a) { if a.isPartial() then result = true else result = false }
from Accessor a
where a.fromSource()
select a, isPartial(a)

View File

@@ -0,0 +1,2 @@
| Partial.cs:25:27:25:30 | Item | true |
| Partial.cs:42:19:42:22 | Item | false |

View File

@@ -0,0 +1,7 @@
import csharp
private boolean isPartial(Indexer i) { if i.isPartial() then result = true else result = false }
from Indexer i
where i.fromSource()
select i, isPartial(i)

View File

@@ -1,3 +1,3 @@
| Partial.cs:4:18:4:42 | PartialMethodWithoutBody1 | false |
| Partial.cs:10:18:10:39 | PartialMethodWithBody1 | true |
| Partial.cs:16:18:16:42 | PartialMethodWithoutBody2 | false |
| Partial.cs:14:18:14:39 | PartialMethodWithBody1 | true |
| Partial.cs:34:18:34:42 | PartialMethodWithoutBody2 | false |

View File

@@ -0,0 +1,2 @@
| Partial.cs:18:27:18:42 | PartialProperty1 | true |
| Partial.cs:41:19:41:26 | Property | false |

View File

@@ -0,0 +1,7 @@
import csharp
private boolean isPartial(Property p) { if p.isPartial() then result = true else result = false }
from Property p
where p.fromSource()
select p, isPartial(p)

View File

@@ -5,19 +5,87 @@ Partial.cs:
# 5| 6: [Method] Method2
# 5| -1: [TypeMention] Void
# 5| 4: [BlockStmt] {...}
# 10| 7: [Method] PartialMethodWithBody1
# 14| 7: [Method] PartialMethodWithBody1
# 3| -1: [TypeMention] Void
# 10| 4: [BlockStmt] {...}
# 11| 8: [Method] Method3
# 11| -1: [TypeMention] Void
# 11| 4: [BlockStmt] {...}
# 14| [Class] OnePartPartialClass
# 16| 5: [Method] PartialMethodWithoutBody2
# 16| -1: [TypeMention] Void
# 17| 6: [Method] Method4
# 17| -1: [TypeMention] Void
# 17| 4: [BlockStmt] {...}
# 20| [Class] NonPartialClass
# 22| 5: [Method] Method5
# 22| -1: [TypeMention] Void
# 22| 4: [BlockStmt] {...}
# 14| 4: [BlockStmt] {...}
# 15| 8: [Method] Method3
# 15| -1: [TypeMention] Void
# 15| 4: [BlockStmt] {...}
# 16| 9: [Field] _backingField
# 16| -1: [TypeMention] object
# 18| 10: [Property] PartialProperty1
# 7| -1: [TypeMention] object
# 18| -1: [TypeMention] object
# 20| 3: [Getter] get_PartialProperty1
# 20| 4: [BlockStmt] {...}
# 20| 0: [ReturnStmt] return ...;
# 20| 0: [FieldAccess] access to field _backingField
# 21| 4: [Setter] set_PartialProperty1
#-----| 2: (Parameters)
# 21| 0: [Parameter] value
# 21| 4: [BlockStmt] {...}
# 21| 0: [ExprStmt] ...;
# 21| 0: [AssignExpr] ... = ...
# 21| 0: [FieldAccess] access to field _backingField
# 21| 1: [ParameterAccess] access to parameter value
# 23| 11: [Field] _backingArray
# 23| -1: [TypeMention] Object[]
# 23| 1: [TypeMention] object
# 25| 12: [Indexer] Item
# 9| -1: [TypeMention] object
# 25| -1: [TypeMention] object
#-----| 1: (Parameters)
# 9| 0: [Parameter] index
# 9| -1: [TypeMention] int
# 25| -1: [TypeMention] int
# 27| 3: [Getter] get_Item
#-----| 2: (Parameters)
# 25| 0: [Parameter] index
# 27| 4: [BlockStmt] {...}
# 27| 0: [ReturnStmt] return ...;
# 27| 0: [ArrayAccess] access to array element
# 27| -1: [FieldAccess] access to field _backingArray
# 27| 0: [ParameterAccess] access to parameter index
# 28| 4: [Setter] set_Item
#-----| 2: (Parameters)
# 25| 0: [Parameter] index
# 28| 1: [Parameter] value
# 28| 4: [BlockStmt] {...}
# 28| 0: [ExprStmt] ...;
# 28| 0: [AssignExpr] ... = ...
# 28| 0: [ArrayAccess] access to array element
# 28| -1: [FieldAccess] access to field _backingArray
# 28| 0: [ParameterAccess] access to parameter index
# 28| 1: [ParameterAccess] access to parameter value
# 32| [Class] OnePartPartialClass
# 34| 5: [Method] PartialMethodWithoutBody2
# 34| -1: [TypeMention] Void
# 35| 6: [Method] Method4
# 35| -1: [TypeMention] Void
# 35| 4: [BlockStmt] {...}
# 38| [Class] NonPartialClass
# 40| 5: [Method] Method5
# 40| -1: [TypeMention] Void
# 40| 4: [BlockStmt] {...}
# 41| 6: [Property] Property
# 41| -1: [TypeMention] object
# 41| 3: [Getter] get_Property
# 41| 4: [Setter] set_Property
#-----| 2: (Parameters)
# 41| 0: [Parameter] value
# 42| 7: [Indexer] Item
# 42| -1: [TypeMention] object
#-----| 1: (Parameters)
# 42| 0: [Parameter] index
# 42| -1: [TypeMention] int
# 44| 3: [Getter] get_Item
#-----| 2: (Parameters)
# 42| 0: [Parameter] index
# 44| 4: [BlockStmt] {...}
# 44| 0: [ReturnStmt] return ...;
# 44| 0: [NullLiteral] null
# 45| 4: [Setter] set_Item
#-----| 2: (Parameters)
# 42| 0: [Parameter] index
# 45| 1: [Parameter] value
# 45| 4: [BlockStmt] {...}