From 963e65861954e9c4c104d0ea89edfe1bfe442d4f Mon Sep 17 00:00:00 2001 From: Michael Nebel Date: Mon, 20 Jan 2025 11:36:22 +0100 Subject: [PATCH 01/12] C#: Add partial properties and indexers examples. --- .../ql/test/library-tests/partial/Partial.cs | 26 ++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/csharp/ql/test/library-tests/partial/Partial.cs b/csharp/ql/test/library-tests/partial/Partial.cs index 1d54614fc86d..5a3e4af2e8c0 100644 --- a/csharp/ql/test/library-tests/partial/Partial.cs +++ b/csharp/ql/test/library-tests/partial/Partial.cs @@ -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 @@ public void Method4() { } class NonPartialClass { public void Method5() { } -} \ No newline at end of file + public object Property { get; set; } + public object this[int index] + { + get { return null; } + set { } + } +} From ff7719f96e8ecde6fa551cd61ee200e3eb55391b Mon Sep 17 00:00:00 2001 From: Michael Nebel Date: Mon, 20 Jan 2025 11:44:03 +0100 Subject: [PATCH 02/12] C#: Updated expected test output. --- .../partial/MethodIsPartial.expected | 10 +-- .../library-tests/partial/Partial1.expected | 14 +++- .../library-tests/partial/Partial2.expected | 16 ++-- .../partial/PartialMethodBody.expected | 4 +- .../library-tests/partial/PrintAst.expected | 75 +++++++++++++++---- 5 files changed, 85 insertions(+), 34 deletions(-) diff --git a/csharp/ql/test/library-tests/partial/MethodIsPartial.expected b/csharp/ql/test/library-tests/partial/MethodIsPartial.expected index 66f2dc7d3a09..4c0e905d8c56 100644 --- a/csharp/ql/test/library-tests/partial/MethodIsPartial.expected +++ b/csharp/ql/test/library-tests/partial/MethodIsPartial.expected @@ -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 | diff --git a/csharp/ql/test/library-tests/partial/Partial1.expected b/csharp/ql/test/library-tests/partial/Partial1.expected index 6830307e8e72..7f888c73e35f 100644 --- a/csharp/ql/test/library-tests/partial/Partial1.expected +++ b/csharp/ql/test/library-tests/partial/Partial1.expected @@ -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:7:27:7:42 | PartialProperty1 | +| Partial.cs:7:46:7:48 | get_PartialProperty1 | +| Partial.cs:7:51:7:53 | set_PartialProperty1 | +| Partial.cs:9:27:9:30 | Item | +| Partial.cs:9:45:9:47 | get_Item | +| Partial.cs:9:50:9:52 | set_Item | +| Partial.cs:12:15:12:26 | TwoPartClass | +| Partial.cs:14:18:14:39 | PartialMethodWithBody1 | +| Partial.cs:32:15:32:33 | OnePartPartialClass | +| Partial.cs:34:18:34:42 | PartialMethodWithoutBody2 | diff --git a/csharp/ql/test/library-tests/partial/Partial2.expected b/csharp/ql/test/library-tests/partial/Partial2.expected index de1327fe159d..9dc3a24a4ce8 100644 --- a/csharp/ql/test/library-tests/partial/Partial2.expected +++ b/csharp/ql/test/library-tests/partial/Partial2.expected @@ -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 | diff --git a/csharp/ql/test/library-tests/partial/PartialMethodBody.expected b/csharp/ql/test/library-tests/partial/PartialMethodBody.expected index b440bfb640b9..b75a105bea05 100644 --- a/csharp/ql/test/library-tests/partial/PartialMethodBody.expected +++ b/csharp/ql/test/library-tests/partial/PartialMethodBody.expected @@ -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 | diff --git a/csharp/ql/test/library-tests/partial/PrintAst.expected b/csharp/ql/test/library-tests/partial/PrintAst.expected index 08e8e66d40ec..3ba40a50a78b 100644 --- a/csharp/ql/test/library-tests/partial/PrintAst.expected +++ b/csharp/ql/test/library-tests/partial/PrintAst.expected @@ -5,19 +5,64 @@ Partial.cs: # 5| 6: [Method] Method2 # 5| -1: [TypeMention] Void # 5| 4: [BlockStmt] {...} -# 10| 7: [Method] PartialMethodWithBody1 +# 7| 7: [Property] PartialProperty1 +# 7| -1: [TypeMention] object +# 7| 3: [Getter] get_PartialProperty1 +# 7| 4: [Setter] set_PartialProperty1 +#-----| 2: (Parameters) +# 7| 0: [Parameter] value +# 9| 8: [Indexer] Item +# 9| -1: [TypeMention] object +#-----| 1: (Parameters) +# 9| 0: [Parameter] index +# 9| -1: [TypeMention] int +# 9| 3: [Getter] get_Item +#-----| 2: (Parameters) +# 9| 0: [Parameter] index +# 9| 4: [Setter] set_Item +#-----| 2: (Parameters) +# 9| 0: [Parameter] index +# 9| 1: [Parameter] value +# 14| 9: [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| 10: [Method] Method3 +# 15| -1: [TypeMention] Void +# 15| 4: [BlockStmt] {...} +# 16| 11: [Field] _backingField +# 16| -1: [TypeMention] object +# 23| 12: [Field] _backingArray +# 23| -1: [TypeMention] Object[] +# 23| 1: [TypeMention] object +# 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] {...} From b3e56e60238e6cecf358e00cffc413e92dd1e44f Mon Sep 17 00:00:00 2001 From: Michael Nebel Date: Tue, 21 Jan 2025 16:03:32 +0100 Subject: [PATCH 03/12] C#: Add dispatch examples for partial properties and indexers. --- .../library-tests/dispatch/ViableCallable.cs | 34 +++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/csharp/ql/test/library-tests/dispatch/ViableCallable.cs b/csharp/ql/test/library-tests/dispatch/ViableCallable.cs index b6bdc72e3b4d..99b4ec54a99d 100644 --- a/csharp/ql/test/library-tests/dispatch/ViableCallable.cs +++ b/csharp/ql/test/library-tests/dispatch/ViableCallable.cs @@ -687,3 +687,37 @@ public void Run3(I tor) 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]; + } +} From e53c7508766c8b2fd30a08ca68f9b4ead04383bb Mon Sep 17 00:00:00 2001 From: Michael Nebel Date: Tue, 21 Jan 2025 16:04:02 +0100 Subject: [PATCH 04/12] C#: Update expected output for dispatch tests. --- csharp/ql/test/library-tests/dispatch/CallGraph.expected | 4 ++++ .../test/library-tests/dispatch/GetADynamicTarget.expected | 6 ++++++ .../ql/test/library-tests/dispatch/viableCallable.expected | 2 ++ 3 files changed, 12 insertions(+) diff --git a/csharp/ql/test/library-tests/dispatch/CallGraph.expected b/csharp/ql/test/library-tests/dispatch/CallGraph.expected index 6ee5e1a8dd8c..67710dc314f5 100644 --- a/csharp/ql/test/library-tests/dispatch/CallGraph.expected +++ b/csharp/ql/test/library-tests/dispatch/CallGraph.expected @@ -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:695:42:695:44 | get_Property | +| ViableCallable.cs:707:17:707:20 | Run1 | ViableCallable.cs:695:47:695:49 | set_Property | +| ViableCallable.cs:707:17:707:20 | Run1 | ViableCallable.cs:697:49:697:51 | get_Item | +| ViableCallable.cs:707:17:707:20 | Run1 | ViableCallable.cs:697:54:697:56 | set_Item | diff --git a/csharp/ql/test/library-tests/dispatch/GetADynamicTarget.expected b/csharp/ql/test/library-tests/dispatch/GetADynamicTarget.expected index 3075f48595d2..b38eed691b9c 100644 --- a/csharp/ql/test/library-tests/dispatch/GetADynamicTarget.expected +++ b/csharp/ql/test/library-tests/dispatch/GetADynamicTarget.expected @@ -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.get_Item(decimal) | | ViableCallable.cs:165:18:165:23 | dynamic access to element | C2.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.add_Event(EventHandler) | | ViableCallable.cs:167:9:167:54 | ... += ... | C2.add_Event(EventHandler) | | ViableCallable.cs:167:9:167:54 | ... += ... | C2.add_Event(EventHandler) | @@ -516,3 +518,7 @@ | ViableCallable.cs:683:9:683:16 | call to method M | C22+TestOverloadResolution2.M(Int32[]) | | ViableCallable.cs:687:9:687:16 | call to method M | C22+TestOverloadResolution1.M(List) | | ViableCallable.cs:687:9:687:16 | call to method M | C22+TestOverloadResolution2.M(List) | +| 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) | diff --git a/csharp/ql/test/library-tests/dispatch/viableCallable.expected b/csharp/ql/test/library-tests/dispatch/viableCallable.expected index 722d07385a5e..c4abbbd2e582 100644 --- a/csharp/ql/test/library-tests/dispatch/viableCallable.expected +++ b/csharp/ql/test/library-tests/dispatch/viableCallable.expected @@ -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 | From dae5ca81a25bfac312b88c7fcc982de2cfb603f1 Mon Sep 17 00:00:00 2001 From: Michael Nebel Date: Wed, 22 Jan 2025 09:24:40 +0100 Subject: [PATCH 05/12] C#: Add dataflow examples for partial properties. --- .../test/library-tests/dataflow/fields/D.cs | 38 +++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/csharp/ql/test/library-tests/dataflow/fields/D.cs b/csharp/ql/test/library-tests/dataflow/fields/D.cs index 7a3fe9851372..7f07cf5ca0b9 100644 --- a/csharp/ql/test/library-tests/dataflow/fields/D.cs +++ b/csharp/ql/test/library-tests/dataflow/fields/D.cs @@ -51,3 +51,41 @@ public static void Sink(object o) { } static T Source(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(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(object source) => throw null; +} From 5836c8d0ce0aab2339b445398449c6644802412a Mon Sep 17 00:00:00 2001 From: Michael Nebel Date: Wed, 22 Jan 2025 09:25:21 +0100 Subject: [PATCH 06/12] C#: Update expected test output for data flow tests. --- .../dataflow/fields/FieldFlow.expected | 47 +++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/csharp/ql/test/library-tests/dataflow/fields/FieldFlow.expected b/csharp/ql/test/library-tests/dataflow/fields/FieldFlow.expected index 3135ce254bdd..b0118c3f427a 100644 --- a/csharp/ql/test/library-tests/dataflow/fields/FieldFlow.expected +++ b/csharp/ql/test/library-tests/dataflow/fields/FieldFlow.expected @@ -502,6 +502,26 @@ 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: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:13:78:13 | access to local variable o : Object | D.cs:82:26:82:26 | access to local variable o : Object | provenance | | +| D.cs:78:13:78:13 | access to local variable o : Object | D.cs:82:26:82:26 | access to local variable o : Object | provenance | | +| D.cs:78:17:78:33 | call to method Source : 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 | 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 [property PartialProp1] : Object | D.cs:82:9:82:9 | access to local variable d : DPartial [property PartialProp1] : Object | provenance | | +| D.cs:81:9:81:9 | [post] access to local variable d : DPartial [property PartialProp1] : Object | D.cs:82:9:82:9 | access to local variable d : DPartial [property PartialProp1] : 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 [property PartialProp1] : 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 [property PartialProp1] : Object | provenance | | +| D.cs:82:9:82:9 | [post] access to local variable d : DPartial [property PartialProp2] : Object | D.cs:85:14:85:14 | access to local variable d : DPartial [property PartialProp2] : Object | provenance | | +| D.cs:82:9:82:9 | [post] access to local variable d : DPartial [property PartialProp2] : Object | D.cs:85:14:85:14 | access to local variable d : DPartial [property PartialProp2] : Object | provenance | | +| D.cs:82:9:82:9 | access to local variable d : DPartial [property PartialProp1] : Object | D.cs:84:14:84:14 | access to local variable d : DPartial [property PartialProp1] : Object | provenance | | +| D.cs:82:9:82:9 | access to local variable d : DPartial [property PartialProp1] : Object | D.cs:84:14:84:14 | access to local variable d : DPartial [property PartialProp1] : Object | provenance | | +| D.cs:82:26:82:26 | access to local variable o : Object | D.cs:82:9:82:9 | [post] access to local variable d : DPartial [property PartialProp2] : Object | provenance | | +| D.cs:82:26:82:26 | access to local variable o : Object | D.cs:82:9:82:9 | [post] access to local variable d : DPartial [property PartialProp2] : Object | provenance | | +| D.cs:84:14:84:14 | access to local variable d : DPartial [property PartialProp1] : Object | D.cs:84:14:84:27 | access to property PartialProp1 | provenance | | +| D.cs:84:14:84:14 | access to local variable d : DPartial [property PartialProp1] : Object | D.cs:84:14:84:27 | access to property PartialProp1 | provenance | | +| D.cs:85:14:85:14 | access to local variable d : DPartial [property PartialProp2] : Object | D.cs:85:14:85:27 | access to property PartialProp2 | provenance | | +| D.cs:85:14:85:14 | access to local variable d : DPartial [property PartialProp2] : Object | D.cs:85:14:85:27 | access to property PartialProp2 | 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 +1765,28 @@ 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: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 | semmle.label | call to method Source : Object | +| D.cs:78:17:78:33 | call to method Source : Object | semmle.label | call to method Source : Object | +| D.cs:81:9:81:9 | [post] access to local variable d : DPartial [property PartialProp1] : Object | semmle.label | [post] access to local variable d : DPartial [property PartialProp1] : Object | +| D.cs:81:9:81:9 | [post] access to local variable d : DPartial [property PartialProp1] : Object | semmle.label | [post] access to local variable d : DPartial [property PartialProp1] : 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:82:9:82:9 | [post] access to local variable d : DPartial [property PartialProp2] : Object | semmle.label | [post] access to local variable d : DPartial [property PartialProp2] : Object | +| D.cs:82:9:82:9 | [post] access to local variable d : DPartial [property PartialProp2] : Object | semmle.label | [post] access to local variable d : DPartial [property PartialProp2] : Object | +| D.cs:82:9:82:9 | access to local variable d : DPartial [property PartialProp1] : Object | semmle.label | access to local variable d : DPartial [property PartialProp1] : Object | +| D.cs:82:9:82:9 | access to local variable d : DPartial [property PartialProp1] : Object | semmle.label | access to local variable d : DPartial [property PartialProp1] : Object | +| D.cs:82:26:82:26 | access to local variable o : Object | semmle.label | access to local variable o : Object | +| D.cs:82:26:82: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 [property PartialProp1] : Object | semmle.label | access to local variable d : DPartial [property PartialProp1] : Object | +| D.cs:84:14:84:14 | access to local variable d : DPartial [property PartialProp1] : Object | semmle.label | access to local variable d : DPartial [property PartialProp1] : 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 | +| D.cs:85:14:85:14 | access to local variable d : DPartial [property PartialProp2] : Object | semmle.label | access to local variable d : DPartial [property PartialProp2] : Object | +| D.cs:85:14:85:14 | access to local variable d : DPartial [property PartialProp2] : Object | semmle.label | access to local variable d : DPartial [property PartialProp2] : Object | +| D.cs:85:14:85:27 | access to property PartialProp2 | semmle.label | access to property PartialProp2 | +| D.cs:85:14:85:27 | access to property PartialProp2 | semmle.label | access to property PartialProp2 | | 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 | @@ -2633,6 +2675,7 @@ subpaths | J.cs:80:35:80:35 | access to local variable o : Object | J.cs:14:40:14:43 | prop : Object | J.cs:14:12:14:17 | this [Return] : Struct [property Prop] : Object | J.cs:80:18:80:36 | object creation of type Struct : Struct [property Prop] : Object | | J.cs:80:35:80:35 | access to local variable o : Object | J.cs:14:40:14:43 | prop : Object | J.cs:14:12:14:17 | this [Return] : Struct [property Prop] : Object | J.cs:80:18:80:36 | object creation of type Struct : Struct [property Prop] : Object | testFailures +| D.cs:85:14:85:27 | access to property PartialProp2 | Unexpected result: hasValueFlow=1 | #select | A.cs:7:14:7:16 | access to field c | A.cs:5:17:5:28 | call to method Source : C | A.cs:7:14:7:16 | access to field c | $@ | A.cs:5:17:5:28 | call to method Source : C | call to method Source : C | | A.cs:7:14:7:16 | access to field c | A.cs:5:17:5:28 | call to method Source : C | A.cs:7:14:7:16 | access to field c | $@ | A.cs:5:17:5:28 | call to method Source : C | call to method Source : C | @@ -2690,6 +2733,10 @@ testFailures | D.cs:46:14:46:31 | access to field trivialPropField | D.cs:43:32:43:48 | call to method Source : Object | D.cs:46:14:46:31 | access to field trivialPropField | $@ | D.cs:43:32:43:48 | call to method Source : Object | call to method Source : Object | | D.cs:47:14:47:26 | access to property ComplexProp | D.cs:43:32:43:48 | call to method Source : Object | D.cs:47:14:47:26 | access to property ComplexProp | $@ | D.cs:43:32:43:48 | call to method Source : Object | call to method Source : Object | | D.cs:47:14:47:26 | access to property ComplexProp | D.cs:43:32:43:48 | call to method Source : Object | D.cs:47:14:47:26 | access to property ComplexProp | $@ | D.cs:43:32:43:48 | call to method Source : Object | call to method Source : Object | +| D.cs:84:14:84:27 | access to property PartialProp1 | D.cs:78:17:78:33 | call to method Source : Object | D.cs:84:14:84:27 | access to property PartialProp1 | $@ | D.cs:78:17:78:33 | call to method Source : Object | call to method Source : Object | +| D.cs:84:14:84:27 | access to property PartialProp1 | D.cs:78:17:78:33 | call to method Source : Object | D.cs:84:14:84:27 | access to property PartialProp1 | $@ | D.cs:78:17:78:33 | call to method Source : Object | call to method Source : Object | +| D.cs:85:14:85:27 | access to property PartialProp2 | D.cs:78:17:78:33 | call to method Source : Object | D.cs:85:14:85:27 | access to property PartialProp2 | $@ | D.cs:78:17:78:33 | call to method Source : Object | call to method Source : Object | +| D.cs:85:14:85:27 | access to property PartialProp2 | D.cs:78:17:78:33 | call to method Source : Object | D.cs:85:14:85:27 | access to property PartialProp2 | $@ | D.cs:78:17:78:33 | call to method Source : Object | call to method Source : Object | | E.cs:24:14:24:20 | access to field Field | E.cs:22:17:22:33 | call to method Source : Object | E.cs:24:14:24:20 | access to field Field | $@ | E.cs:22:17:22:33 | call to method Source : Object | call to method Source : Object | | E.cs:24:14:24:20 | access to field Field | E.cs:22:17:22:33 | call to method Source : Object | E.cs:24:14:24:20 | access to field Field | $@ | E.cs:22:17:22:33 | call to method Source : Object | call to method Source : Object | | E.cs:57:14:57:26 | access to field RefField | E.cs:54:21:54:37 | call to method Source : Object | E.cs:57:14:57:26 | access to field RefField | $@ | E.cs:54:21:54:37 | call to method Source : Object | call to method Source : Object | From 568fd9c7482b6d7eb001fcdca389c24113bc051b Mon Sep 17 00:00:00 2001 From: Michael Nebel Date: Mon, 20 Jan 2025 14:05:35 +0100 Subject: [PATCH 07/12] C#: Add some partial tests for Properties and Indexers. --- .../test/library-tests/partial/PartialAccessors.expected | 8 ++++++++ csharp/ql/test/library-tests/partial/PartialAccessors.ql | 7 +++++++ .../test/library-tests/partial/PartialIndexers.expected | 2 ++ csharp/ql/test/library-tests/partial/PartialIndexers.ql | 7 +++++++ .../test/library-tests/partial/PartialProperties.expected | 2 ++ csharp/ql/test/library-tests/partial/PartialProperties.ql | 7 +++++++ 6 files changed, 33 insertions(+) create mode 100644 csharp/ql/test/library-tests/partial/PartialAccessors.expected create mode 100644 csharp/ql/test/library-tests/partial/PartialAccessors.ql create mode 100644 csharp/ql/test/library-tests/partial/PartialIndexers.expected create mode 100644 csharp/ql/test/library-tests/partial/PartialIndexers.ql create mode 100644 csharp/ql/test/library-tests/partial/PartialProperties.expected create mode 100644 csharp/ql/test/library-tests/partial/PartialProperties.ql diff --git a/csharp/ql/test/library-tests/partial/PartialAccessors.expected b/csharp/ql/test/library-tests/partial/PartialAccessors.expected new file mode 100644 index 000000000000..b06879bb0283 --- /dev/null +++ b/csharp/ql/test/library-tests/partial/PartialAccessors.expected @@ -0,0 +1,8 @@ +| Partial.cs:7:46:7:48 | get_PartialProperty1 | true | +| Partial.cs:7:51:7:53 | set_PartialProperty1 | true | +| Partial.cs:9:45:9:47 | get_Item | true | +| Partial.cs:9:50:9:52 | 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 | diff --git a/csharp/ql/test/library-tests/partial/PartialAccessors.ql b/csharp/ql/test/library-tests/partial/PartialAccessors.ql new file mode 100644 index 000000000000..c65a4459ae1b --- /dev/null +++ b/csharp/ql/test/library-tests/partial/PartialAccessors.ql @@ -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) diff --git a/csharp/ql/test/library-tests/partial/PartialIndexers.expected b/csharp/ql/test/library-tests/partial/PartialIndexers.expected new file mode 100644 index 000000000000..e047e4161ac9 --- /dev/null +++ b/csharp/ql/test/library-tests/partial/PartialIndexers.expected @@ -0,0 +1,2 @@ +| Partial.cs:9:27:9:30 | Item | true | +| Partial.cs:42:19:42:22 | Item | false | diff --git a/csharp/ql/test/library-tests/partial/PartialIndexers.ql b/csharp/ql/test/library-tests/partial/PartialIndexers.ql new file mode 100644 index 000000000000..9a42c4ac3731 --- /dev/null +++ b/csharp/ql/test/library-tests/partial/PartialIndexers.ql @@ -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) diff --git a/csharp/ql/test/library-tests/partial/PartialProperties.expected b/csharp/ql/test/library-tests/partial/PartialProperties.expected new file mode 100644 index 000000000000..77f1105497ab --- /dev/null +++ b/csharp/ql/test/library-tests/partial/PartialProperties.expected @@ -0,0 +1,2 @@ +| Partial.cs:7:27:7:42 | PartialProperty1 | true | +| Partial.cs:41:19:41:26 | Property | false | diff --git a/csharp/ql/test/library-tests/partial/PartialProperties.ql b/csharp/ql/test/library-tests/partial/PartialProperties.ql new file mode 100644 index 000000000000..aa4feb6f6433 --- /dev/null +++ b/csharp/ql/test/library-tests/partial/PartialProperties.ql @@ -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) From c481e82fdde9a090ef794b44ebf6e351e43c4670 Mon Sep 17 00:00:00 2001 From: Michael Nebel Date: Wed, 22 Jan 2025 09:52:58 +0100 Subject: [PATCH 08/12] C#: Add indexer data flow test. --- .../dataflow/indexers/IndexerFlow.ql | 12 +++++ .../dataflow/indexers/Indexers.cs | 48 +++++++++++++++++++ 2 files changed, 60 insertions(+) create mode 100644 csharp/ql/test/library-tests/dataflow/indexers/IndexerFlow.ql create mode 100644 csharp/ql/test/library-tests/dataflow/indexers/Indexers.cs diff --git a/csharp/ql/test/library-tests/dataflow/indexers/IndexerFlow.ql b/csharp/ql/test/library-tests/dataflow/indexers/IndexerFlow.ql new file mode 100644 index 000000000000..9ab95f59caf3 --- /dev/null +++ b/csharp/ql/test/library-tests/dataflow/indexers/IndexerFlow.ql @@ -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() diff --git a/csharp/ql/test/library-tests/dataflow/indexers/Indexers.cs b/csharp/ql/test/library-tests/dataflow/indexers/Indexers.cs new file mode 100644 index 000000000000..1f5786929db6 --- /dev/null +++ b/csharp/ql/test/library-tests/dataflow/indexers/Indexers.cs @@ -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(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(object source) => throw null; +} From 443a2a47b56868181d37068e441d948a0e864793 Mon Sep 17 00:00:00 2001 From: Michael Nebel Date: Wed, 22 Jan 2025 09:53:19 +0100 Subject: [PATCH 09/12] C#: Add indexer data flow test expected output file. --- .../library-tests/dataflow/indexers/IndexerFlow.expected | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 csharp/ql/test/library-tests/dataflow/indexers/IndexerFlow.expected diff --git a/csharp/ql/test/library-tests/dataflow/indexers/IndexerFlow.expected b/csharp/ql/test/library-tests/dataflow/indexers/IndexerFlow.expected new file mode 100644 index 000000000000..c28cf5dd9c95 --- /dev/null +++ b/csharp/ql/test/library-tests/dataflow/indexers/IndexerFlow.expected @@ -0,0 +1,7 @@ +models +edges +nodes +subpaths +testFailures +| Indexers.cs:38:22:38:40 | // ... | Missing result: hasValueFlow=1 | +#select From 0453ae8dbd3d1f9b4a350376ed917998f42db31a Mon Sep 17 00:00:00 2001 From: Michael Nebel Date: Mon, 20 Jan 2025 14:08:06 +0100 Subject: [PATCH 10/12] C#: Use property- and indexer implementation location and extract the accessor implementations instead of declarations. --- .../Semmle.Extraction.CSharp/Entities/Accessor.cs | 4 ++++ .../Semmle.Extraction.CSharp/Entities/Indexer.cs | 8 ++++---- .../Semmle.Extraction.CSharp/Entities/Property.cs | 12 ++++++++---- 3 files changed, 16 insertions(+), 8 deletions(-) diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Accessor.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Accessor.cs index 22d81bfceb8f..66e45387d876 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Accessor.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Accessor.cs @@ -30,6 +30,10 @@ protected Accessor(Context cx, IMethodSymbol init, IPropertySymbol property) 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); diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Indexer.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Indexer.cs index 06c44c3bed33..1235b120253c 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Indexer.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Indexer.cs @@ -22,16 +22,16 @@ public override void Populate(TextWriter trapFile) 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) diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Property.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Property.cs index ef00877c5cd0..f8845a667cc7 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Property.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Property.cs @@ -21,6 +21,10 @@ protected Property(Context cx, IPropertySymbol init) 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 @@ public override void Populate(TextWriter trapFile) 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 ? From fc03c367e90a8cbf4bd85618359c7e3ad33515a3 Mon Sep 17 00:00:00 2001 From: Michael Nebel Date: Mon, 20 Jan 2025 14:12:02 +0100 Subject: [PATCH 11/12] C#: Update expected test output. --- .../dataflow/fields/FieldFlow.expected | 75 +++++++++++-------- .../dataflow/indexers/IndexerFlow.expected | 65 +++++++++++++++- .../library-tests/dispatch/CallGraph.expected | 8 +- .../library-tests/partial/Partial1.expected | 12 +-- .../partial/PartialAccessors.expected | 8 +- .../partial/PartialIndexers.expected | 2 +- .../partial/PartialProperties.expected | 2 +- .../library-tests/partial/PrintAst.expected | 65 ++++++++++------ 8 files changed, 166 insertions(+), 71 deletions(-) diff --git a/csharp/ql/test/library-tests/dataflow/fields/FieldFlow.expected b/csharp/ql/test/library-tests/dataflow/fields/FieldFlow.expected index b0118c3f427a..ff9e6ab405e6 100644 --- a/csharp/ql/test/library-tests/dataflow/fields/FieldFlow.expected +++ b/csharp/ql/test/library-tests/dataflow/fields/FieldFlow.expected @@ -502,26 +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:13:78:13 | access to local variable o : Object | D.cs:82:26:82:26 | access to local variable o : Object | provenance | | -| D.cs:78:13:78:13 | access to local variable o : Object | D.cs:82:26:82:26 | access to local variable o : Object | provenance | | | D.cs:78:17:78:33 | call to method Source : 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 | 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 [property PartialProp1] : Object | D.cs:82:9:82:9 | access to local variable d : DPartial [property PartialProp1] : Object | provenance | | -| D.cs:81:9:81:9 | [post] access to local variable d : DPartial [property PartialProp1] : Object | D.cs:82:9:82:9 | access to local variable d : DPartial [property PartialProp1] : 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 [property PartialProp1] : 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 [property PartialProp1] : Object | provenance | | -| D.cs:82:9:82:9 | [post] access to local variable d : DPartial [property PartialProp2] : Object | D.cs:85:14:85:14 | access to local variable d : DPartial [property PartialProp2] : Object | provenance | | -| D.cs:82:9:82:9 | [post] access to local variable d : DPartial [property PartialProp2] : Object | D.cs:85:14:85:14 | access to local variable d : DPartial [property PartialProp2] : Object | provenance | | -| D.cs:82:9:82:9 | access to local variable d : DPartial [property PartialProp1] : Object | D.cs:84:14:84:14 | access to local variable d : DPartial [property PartialProp1] : Object | provenance | | -| D.cs:82:9:82:9 | access to local variable d : DPartial [property PartialProp1] : Object | D.cs:84:14:84:14 | access to local variable d : DPartial [property PartialProp1] : Object | provenance | | -| D.cs:82:26:82:26 | access to local variable o : Object | D.cs:82:9:82:9 | [post] access to local variable d : DPartial [property PartialProp2] : Object | provenance | | -| D.cs:82:26:82:26 | access to local variable o : Object | D.cs:82:9:82:9 | [post] access to local variable d : DPartial [property PartialProp2] : Object | provenance | | -| D.cs:84:14:84:14 | access to local variable d : DPartial [property PartialProp1] : Object | D.cs:84:14:84:27 | access to property PartialProp1 | provenance | | -| D.cs:84:14:84:14 | access to local variable d : DPartial [property PartialProp1] : Object | D.cs:84:14:84:27 | access to property PartialProp1 | provenance | | -| D.cs:85:14:85:14 | access to local variable d : DPartial [property PartialProp2] : Object | D.cs:85:14:85:27 | access to property PartialProp2 | provenance | | -| D.cs:85:14:85:14 | access to local variable d : DPartial [property PartialProp2] : Object | D.cs:85:14:85:27 | access to property PartialProp2 | 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 | | @@ -1765,28 +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 | semmle.label | call to method Source : Object | | D.cs:78:17:78:33 | call to method Source : Object | semmle.label | call to method Source : Object | -| D.cs:81:9:81:9 | [post] access to local variable d : DPartial [property PartialProp1] : Object | semmle.label | [post] access to local variable d : DPartial [property PartialProp1] : Object | -| D.cs:81:9:81:9 | [post] access to local variable d : DPartial [property PartialProp1] : Object | semmle.label | [post] access to local variable d : DPartial [property PartialProp1] : 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:82:9:82:9 | [post] access to local variable d : DPartial [property PartialProp2] : Object | semmle.label | [post] access to local variable d : DPartial [property PartialProp2] : Object | -| D.cs:82:9:82:9 | [post] access to local variable d : DPartial [property PartialProp2] : Object | semmle.label | [post] access to local variable d : DPartial [property PartialProp2] : Object | -| D.cs:82:9:82:9 | access to local variable d : DPartial [property PartialProp1] : Object | semmle.label | access to local variable d : DPartial [property PartialProp1] : Object | -| D.cs:82:9:82:9 | access to local variable d : DPartial [property PartialProp1] : Object | semmle.label | access to local variable d : DPartial [property PartialProp1] : Object | -| D.cs:82:26:82:26 | access to local variable o : Object | semmle.label | access to local variable o : Object | -| D.cs:82:26:82: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 [property PartialProp1] : Object | semmle.label | access to local variable d : DPartial [property PartialProp1] : Object | -| D.cs:84:14:84:14 | access to local variable d : DPartial [property PartialProp1] : Object | semmle.label | access to local variable d : DPartial [property PartialProp1] : 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 | -| D.cs:85:14:85:14 | access to local variable d : DPartial [property PartialProp2] : Object | semmle.label | access to local variable d : DPartial [property PartialProp2] : Object | -| D.cs:85:14:85:14 | access to local variable d : DPartial [property PartialProp2] : Object | semmle.label | access to local variable d : DPartial [property PartialProp2] : Object | -| D.cs:85:14:85:27 | access to property PartialProp2 | semmle.label | access to property PartialProp2 | -| D.cs:85:14:85:27 | access to property PartialProp2 | semmle.label | access to property PartialProp2 | | 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 | @@ -2624,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 | @@ -2675,7 +2687,6 @@ subpaths | J.cs:80:35:80:35 | access to local variable o : Object | J.cs:14:40:14:43 | prop : Object | J.cs:14:12:14:17 | this [Return] : Struct [property Prop] : Object | J.cs:80:18:80:36 | object creation of type Struct : Struct [property Prop] : Object | | J.cs:80:35:80:35 | access to local variable o : Object | J.cs:14:40:14:43 | prop : Object | J.cs:14:12:14:17 | this [Return] : Struct [property Prop] : Object | J.cs:80:18:80:36 | object creation of type Struct : Struct [property Prop] : Object | testFailures -| D.cs:85:14:85:27 | access to property PartialProp2 | Unexpected result: hasValueFlow=1 | #select | A.cs:7:14:7:16 | access to field c | A.cs:5:17:5:28 | call to method Source : C | A.cs:7:14:7:16 | access to field c | $@ | A.cs:5:17:5:28 | call to method Source : C | call to method Source : C | | A.cs:7:14:7:16 | access to field c | A.cs:5:17:5:28 | call to method Source : C | A.cs:7:14:7:16 | access to field c | $@ | A.cs:5:17:5:28 | call to method Source : C | call to method Source : C | @@ -2735,8 +2746,6 @@ testFailures | D.cs:47:14:47:26 | access to property ComplexProp | D.cs:43:32:43:48 | call to method Source : Object | D.cs:47:14:47:26 | access to property ComplexProp | $@ | D.cs:43:32:43:48 | call to method Source : Object | call to method Source : Object | | D.cs:84:14:84:27 | access to property PartialProp1 | D.cs:78:17:78:33 | call to method Source : Object | D.cs:84:14:84:27 | access to property PartialProp1 | $@ | D.cs:78:17:78:33 | call to method Source : Object | call to method Source : Object | | D.cs:84:14:84:27 | access to property PartialProp1 | D.cs:78:17:78:33 | call to method Source : Object | D.cs:84:14:84:27 | access to property PartialProp1 | $@ | D.cs:78:17:78:33 | call to method Source : Object | call to method Source : Object | -| D.cs:85:14:85:27 | access to property PartialProp2 | D.cs:78:17:78:33 | call to method Source : Object | D.cs:85:14:85:27 | access to property PartialProp2 | $@ | D.cs:78:17:78:33 | call to method Source : Object | call to method Source : Object | -| D.cs:85:14:85:27 | access to property PartialProp2 | D.cs:78:17:78:33 | call to method Source : Object | D.cs:85:14:85:27 | access to property PartialProp2 | $@ | D.cs:78:17:78:33 | call to method Source : Object | call to method Source : Object | | E.cs:24:14:24:20 | access to field Field | E.cs:22:17:22:33 | call to method Source : Object | E.cs:24:14:24:20 | access to field Field | $@ | E.cs:22:17:22:33 | call to method Source : Object | call to method Source : Object | | E.cs:24:14:24:20 | access to field Field | E.cs:22:17:22:33 | call to method Source : Object | E.cs:24:14:24:20 | access to field Field | $@ | E.cs:22:17:22:33 | call to method Source : Object | call to method Source : Object | | E.cs:57:14:57:26 | access to field RefField | E.cs:54:21:54:37 | call to method Source : Object | E.cs:57:14:57:26 | access to field RefField | $@ | E.cs:54:21:54:37 | call to method Source : Object | call to method Source : Object | diff --git a/csharp/ql/test/library-tests/dataflow/indexers/IndexerFlow.expected b/csharp/ql/test/library-tests/dataflow/indexers/IndexerFlow.expected index c28cf5dd9c95..b287d45a03e9 100644 --- a/csharp/ql/test/library-tests/dataflow/indexers/IndexerFlow.expected +++ b/csharp/ql/test/library-tests/dataflow/indexers/IndexerFlow.expected @@ -1,7 +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 | Indexers.cs:34:13:34:13 | access to local variable o : Object | provenance | | +| Indexers.cs:34:17:34:33 | call to method Source : 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 | semmle.label | call to method Source : Object | +| Indexers.cs:34:17:34:33 | call to method Source : Object | semmle.label | call to method Source : 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 -| Indexers.cs:38:22:38:40 | // ... | Missing result: hasValueFlow=1 | #select +| Indexers.cs:38:14:38:18 | access to indexer | Indexers.cs:34:17:34:33 | call to method Source : Object | Indexers.cs:38:14:38:18 | access to indexer | $@ | Indexers.cs:34:17:34:33 | call to method Source : Object | call to method Source : Object | +| Indexers.cs:38:14:38:18 | access to indexer | Indexers.cs:34:17:34:33 | call to method Source : Object | Indexers.cs:38:14:38:18 | access to indexer | $@ | Indexers.cs:34:17:34:33 | call to method Source : Object | call to method Source : Object | diff --git a/csharp/ql/test/library-tests/dispatch/CallGraph.expected b/csharp/ql/test/library-tests/dispatch/CallGraph.expected index 67710dc314f5..4eed880f0a3e 100644 --- a/csharp/ql/test/library-tests/dispatch/CallGraph.expected +++ b/csharp/ql/test/library-tests/dispatch/CallGraph.expected @@ -270,7 +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:695:42:695:44 | get_Property | -| ViableCallable.cs:707:17:707:20 | Run1 | ViableCallable.cs:695:47:695:49 | set_Property | -| ViableCallable.cs:707:17:707:20 | Run1 | ViableCallable.cs:697:49:697:51 | get_Item | -| ViableCallable.cs:707:17:707:20 | Run1 | ViableCallable.cs:697:54:697:56 | set_Item | +| 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 | diff --git a/csharp/ql/test/library-tests/partial/Partial1.expected b/csharp/ql/test/library-tests/partial/Partial1.expected index 7f888c73e35f..af7be1359143 100644 --- a/csharp/ql/test/library-tests/partial/Partial1.expected +++ b/csharp/ql/test/library-tests/partial/Partial1.expected @@ -1,12 +1,12 @@ | Partial.cs:1:15:1:26 | TwoPartClass | | Partial.cs:4:18:4:42 | PartialMethodWithoutBody1 | -| Partial.cs:7:27:7:42 | PartialProperty1 | -| Partial.cs:7:46:7:48 | get_PartialProperty1 | -| Partial.cs:7:51:7:53 | set_PartialProperty1 | -| Partial.cs:9:27:9:30 | Item | -| Partial.cs:9:45:9:47 | get_Item | -| Partial.cs:9:50:9:52 | set_Item | | 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 | diff --git a/csharp/ql/test/library-tests/partial/PartialAccessors.expected b/csharp/ql/test/library-tests/partial/PartialAccessors.expected index b06879bb0283..2c69ed620ae6 100644 --- a/csharp/ql/test/library-tests/partial/PartialAccessors.expected +++ b/csharp/ql/test/library-tests/partial/PartialAccessors.expected @@ -1,7 +1,7 @@ -| Partial.cs:7:46:7:48 | get_PartialProperty1 | true | -| Partial.cs:7:51:7:53 | set_PartialProperty1 | true | -| Partial.cs:9:45:9:47 | get_Item | true | -| Partial.cs:9:50:9:52 | set_Item | true | +| 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 | diff --git a/csharp/ql/test/library-tests/partial/PartialIndexers.expected b/csharp/ql/test/library-tests/partial/PartialIndexers.expected index e047e4161ac9..151ed5aad03a 100644 --- a/csharp/ql/test/library-tests/partial/PartialIndexers.expected +++ b/csharp/ql/test/library-tests/partial/PartialIndexers.expected @@ -1,2 +1,2 @@ -| Partial.cs:9:27:9:30 | Item | true | +| Partial.cs:25:27:25:30 | Item | true | | Partial.cs:42:19:42:22 | Item | false | diff --git a/csharp/ql/test/library-tests/partial/PartialProperties.expected b/csharp/ql/test/library-tests/partial/PartialProperties.expected index 77f1105497ab..8d2dfc01e74a 100644 --- a/csharp/ql/test/library-tests/partial/PartialProperties.expected +++ b/csharp/ql/test/library-tests/partial/PartialProperties.expected @@ -1,2 +1,2 @@ -| Partial.cs:7:27:7:42 | PartialProperty1 | true | +| Partial.cs:18:27:18:42 | PartialProperty1 | true | | Partial.cs:41:19:41:26 | Property | false | diff --git a/csharp/ql/test/library-tests/partial/PrintAst.expected b/csharp/ql/test/library-tests/partial/PrintAst.expected index 3ba40a50a78b..8d9da42fc11c 100644 --- a/csharp/ql/test/library-tests/partial/PrintAst.expected +++ b/csharp/ql/test/library-tests/partial/PrintAst.expected @@ -5,35 +5,58 @@ Partial.cs: # 5| 6: [Method] Method2 # 5| -1: [TypeMention] Void # 5| 4: [BlockStmt] {...} -# 7| 7: [Property] PartialProperty1 +# 14| 7: [Method] PartialMethodWithBody1 +# 3| -1: [TypeMention] Void +# 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 -# 7| 3: [Getter] get_PartialProperty1 -# 7| 4: [Setter] set_PartialProperty1 +# 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) -# 7| 0: [Parameter] value -# 9| 8: [Indexer] Item +# 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 -# 9| 3: [Getter] get_Item +# 25| -1: [TypeMention] int +# 27| 3: [Getter] get_Item #-----| 2: (Parameters) -# 9| 0: [Parameter] index -# 9| 4: [Setter] set_Item +# 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) -# 9| 0: [Parameter] index -# 9| 1: [Parameter] value -# 14| 9: [Method] PartialMethodWithBody1 -# 3| -1: [TypeMention] Void -# 14| 4: [BlockStmt] {...} -# 15| 10: [Method] Method3 -# 15| -1: [TypeMention] Void -# 15| 4: [BlockStmt] {...} -# 16| 11: [Field] _backingField -# 16| -1: [TypeMention] object -# 23| 12: [Field] _backingArray -# 23| -1: [TypeMention] Object[] -# 23| 1: [TypeMention] object +# 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 From 501f9859bd3634cf7dddfc12893ab5e2934eef12 Mon Sep 17 00:00:00 2001 From: Michael Nebel Date: Wed, 22 Jan 2025 13:38:08 +0100 Subject: [PATCH 12/12] C#: Add change note. --- csharp/ql/lib/change-notes/2025-01-22-partial-members.md | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 csharp/ql/lib/change-notes/2025-01-22-partial-members.md diff --git a/csharp/ql/lib/change-notes/2025-01-22-partial-members.md b/csharp/ql/lib/change-notes/2025-01-22-partial-members.md new file mode 100644 index 000000000000..d83e0365405e --- /dev/null +++ b/csharp/ql/lib/change-notes/2025-01-22-partial-members.md @@ -0,0 +1,4 @@ +--- +category: minorAnalysis +--- +* C# 13: Added support for partial properties and indexers.