From 0d343c5ce10971a3207cad5e7e2ac37fa401898c Mon Sep 17 00:00:00 2001 From: Michael Nebel Date: Mon, 2 Sep 2024 11:10:46 +0200 Subject: [PATCH 1/3] C#: Add external flow tests for synthetic fields. --- .../dataflow/external-models/ExternalFlow.cs | 38 +++++++++++++++++++ .../external-models/ExternalFlow.expected | 8 ++++ .../external-models/ExternalFlow.ext.yml | 7 ++++ 3 files changed, 53 insertions(+) diff --git a/csharp/ql/test/library-tests/dataflow/external-models/ExternalFlow.cs b/csharp/ql/test/library-tests/dataflow/external-models/ExternalFlow.cs index 1090b61a8845..aa26a5d43056 100644 --- a/csharp/ql/test/library-tests/dataflow/external-models/ExternalFlow.cs +++ b/csharp/ql/test/library-tests/dataflow/external-models/ExternalFlow.cs @@ -291,4 +291,42 @@ void M2() static void Sink(object o) { } } + + // Test synthetic fields + public class K { + + public object MyField; + + public void SetMySyntheticField(object o) => throw null; + + public object GetMySyntheticField() => throw null; + + public void SetMyNestedSyntheticField(object o) => throw null; + + public object GetMyNestedSyntheticField() => throw null; + + public void SetMyFieldOnSyntheticField(object o) => throw null; + + public object GetMyFieldOnSyntheticField() => throw null; + + public void M1() { + var o = new object(); + SetMySyntheticField(o); + Sink(GetMySyntheticField()); + } + + public void M2() { + var o = new object(); + SetMyNestedSyntheticField(o); + Sink(GetMyNestedSyntheticField()); + } + + public void M3() { + var o = new object(); + SetMyFieldOnSyntheticField(o); + Sink(GetMyFieldOnSyntheticField()); + } + + static void Sink(object o) { } + } } diff --git a/csharp/ql/test/library-tests/dataflow/external-models/ExternalFlow.expected b/csharp/ql/test/library-tests/dataflow/external-models/ExternalFlow.expected index cad976516b3d..10695e0c53e1 100644 --- a/csharp/ql/test/library-tests/dataflow/external-models/ExternalFlow.expected +++ b/csharp/ql/test/library-tests/dataflow/external-models/ExternalFlow.expected @@ -243,6 +243,14 @@ nodes subpaths | ExternalFlow.cs:84:29:84:32 | access to local variable objs : null [element] : Object | ExternalFlow.cs:84:35:84:35 | o : Object | ExternalFlow.cs:84:40:84:40 | access to parameter o : Object | ExternalFlow.cs:84:25:84:41 | call to method Map : T[] [element] : Object | invalidModelRow +| Unrecognized input specification "SyntheticField[My.Qltest.K.MySyntheticField1]" in summary model. | +| Unrecognized input specification "SyntheticField[My.Qltest.K.MySyntheticField2]" in summary model. | +| Unrecognized input specification "SyntheticField[My.Qltest.K.MySyntheticField]" in summary model. | +| Unrecognized input specification "SyntheticField[MySyntheticField1.MyNestedSyntheticField]" in summary model. | +| Unrecognized output specification "SyntheticField[My.Qltest.K.MySyntheticField1]" in summary model. | +| Unrecognized output specification "SyntheticField[My.Qltest.K.MySyntheticField2]" in summary model. | +| Unrecognized output specification "SyntheticField[My.Qltest.K.MySyntheticField]" in summary model. | +| Unrecognized output specification "SyntheticField[MySyntheticField1.MyNestedSyntheticField]" in summary model. | #select | ExternalFlow.cs:10:18:10:33 | call to method StepArgRes | ExternalFlow.cs:9:27:9:38 | object creation of type Object : Object | ExternalFlow.cs:10:18:10:33 | call to method StepArgRes | $@ | ExternalFlow.cs:9:27:9:38 | object creation of type Object : Object | object creation of type Object : Object | | ExternalFlow.cs:18:18:18:24 | access to local variable argOut1 | ExternalFlow.cs:15:29:15:40 | object creation of type Object : Object | ExternalFlow.cs:18:18:18:24 | access to local variable argOut1 | $@ | ExternalFlow.cs:15:29:15:40 | object creation of type Object : Object | object creation of type Object : Object | diff --git a/csharp/ql/test/library-tests/dataflow/external-models/ExternalFlow.ext.yml b/csharp/ql/test/library-tests/dataflow/external-models/ExternalFlow.ext.yml index 6c877d061619..f2cf9972a73d 100644 --- a/csharp/ql/test/library-tests/dataflow/external-models/ExternalFlow.ext.yml +++ b/csharp/ql/test/library-tests/dataflow/external-models/ExternalFlow.ext.yml @@ -37,6 +37,13 @@ extensions: - ["My.Qltest", "J", false, "SetProp1", "(System.Object)", "", "Argument[0]", "Argument[this]", "value", "manual"] - ["My.Qltest", "J", false, "get_Prop2", "()", "", "Argument[this]", "ReturnValue", "value", "df-generated"] - ["My.Qltest", "J", false, "SetProp2", "(System.Object)", "", "Argument[0]", "Argument[this]", "value", "manual"] + - ["My.Qltest", "K", false, "SetMySyntheticField", "(System.Object)", "", "Argument[0]", "Argument[this].SyntheticField[My.Qltest.K.MySyntheticField]", "value", "manual"] + - ["My.Qltest", "K", false, "GetMySyntheticField", "()", "", "Argument[this].SyntheticField[My.Qltest.K.MySyntheticField]", "ReturnValue", "value", "manual"] + - ["My.Qltest", "K", false, "SetMyNestedSyntheticField", "(System.Object)", "", "Argument[0]", "Argument[this].SyntheticField[My.Qltest.K.MySyntheticField1].SyntheticField[MySyntheticField1.MyNestedSyntheticField]", "value", "manual"] + - ["My.Qltest", "K", false, "GetMyNestedSyntheticField", "()", "", "Argument[this].SyntheticField[My.Qltest.K.MySyntheticField1].SyntheticField[MySyntheticField1.MyNestedSyntheticField]", "ReturnValue", "value", "manual"] + - ["My.Qltest", "K", false, "SetMyFieldOnSyntheticField", "(System.Object)", "", "Argument[0]", "Argument[this].SyntheticField[My.Qltest.K.MySyntheticField2].Field[My.Qltest.K.MyField]", "value", "manual"] + - ["My.Qltest", "K", false, "GetMyFieldOnSyntheticField", "()", "", "Argument[this].SyntheticField[My.Qltest.K.MySyntheticField2].Field[My.Qltest.K.MyField]", "ReturnValue", "value", "manual"] + - addsTo: pack: codeql/csharp-all extensible: neutralModel From 6e81d7455875471607a09d63e65fd10946583683 Mon Sep 17 00:00:00 2001 From: Michael Nebel Date: Mon, 2 Sep 2024 11:07:11 +0200 Subject: [PATCH 2/3] C#: Add support for synthetic fields in MaD for C#. --- .../code/csharp/dataflow/internal/DataFlowPrivate.qll | 1 + .../code/csharp/dataflow/internal/ExternalFlow.qll | 11 +++++++++++ 2 files changed, 12 insertions(+) diff --git a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowPrivate.qll b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowPrivate.qll index 7253d0581a57..1394f238de7f 100644 --- a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowPrivate.qll +++ b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowPrivate.qll @@ -3075,6 +3075,7 @@ ContentApprox getContentApprox(Content c) { * ensuring that they are visible to the taint tracking / data flow library. */ private module SyntheticFields { + private import semmle.code.csharp.dataflow.internal.ExternalFlow private import semmle.code.csharp.frameworks.system.threading.Tasks private import semmle.code.csharp.frameworks.system.runtime.CompilerServices } diff --git a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/ExternalFlow.qll b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/ExternalFlow.qll index f1c299c2f252..c2d3da0607aa 100644 --- a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/ExternalFlow.qll +++ b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/ExternalFlow.qll @@ -431,6 +431,17 @@ Declaration interpretElement( ) } +private predicate parseSynthField(AccessPathToken c, string name) { + c.getName() = "SyntheticField" and name = c.getAnArgument() +} + +/** + * An adapter class for adding synthetic fields from MaD. + */ +private class SyntheticFieldAdapter extends SyntheticField { + SyntheticFieldAdapter() { parseSynthField(_, this) } +} + cached private module Cached { /** From 4f4c7bfbb9524d32e3c5952df6712067f686fc18 Mon Sep 17 00:00:00 2001 From: Michael Nebel Date: Mon, 2 Sep 2024 11:11:55 +0200 Subject: [PATCH 3/3] C#: Update expected test output. --- .../external-models/ExternalFlow.expected | 50 ++++++++++++++++--- 1 file changed, 42 insertions(+), 8 deletions(-) diff --git a/csharp/ql/test/library-tests/dataflow/external-models/ExternalFlow.expected b/csharp/ql/test/library-tests/dataflow/external-models/ExternalFlow.expected index 10695e0c53e1..0b80a70fbade 100644 --- a/csharp/ql/test/library-tests/dataflow/external-models/ExternalFlow.expected +++ b/csharp/ql/test/library-tests/dataflow/external-models/ExternalFlow.expected @@ -24,6 +24,12 @@ models | 23 | Summary: My.Qltest; I; false; GetFirst; (My.Qltest.MyInlineArray); ; Argument[0].Element; ReturnValue; value; manual | | 24 | Summary: My.Qltest; J; false; get_Prop1; (); ; Argument[this]; ReturnValue; value; manual | | 25 | Summary: My.Qltest; J; false; SetProp1; (System.Object); ; Argument[0]; Argument[this]; value; manual | +| 26 | Summary: My.Qltest; K; false; SetMySyntheticField; (System.Object); ; Argument[0]; Argument[this].SyntheticField[My.Qltest.K.MySyntheticField]; value; manual | +| 27 | Summary: My.Qltest; K; false; GetMySyntheticField; (); ; Argument[this].SyntheticField[My.Qltest.K.MySyntheticField]; ReturnValue; value; manual | +| 28 | Summary: My.Qltest; K; false; SetMyNestedSyntheticField; (System.Object); ; Argument[0]; Argument[this].SyntheticField[My.Qltest.K.MySyntheticField1].SyntheticField[MySyntheticField1.MyNestedSyntheticField]; value; manual | +| 29 | Summary: My.Qltest; K; false; GetMyNestedSyntheticField; (); ; Argument[this].SyntheticField[My.Qltest.K.MySyntheticField1].SyntheticField[MySyntheticField1.MyNestedSyntheticField]; ReturnValue; value; manual | +| 30 | Summary: My.Qltest; K; false; SetMyFieldOnSyntheticField; (System.Object); ; Argument[0]; Argument[this].SyntheticField[My.Qltest.K.MySyntheticField2].Field[My.Qltest.K.MyField]; value; manual | +| 31 | Summary: My.Qltest; K; false; GetMyFieldOnSyntheticField; (); ; Argument[this].SyntheticField[My.Qltest.K.MySyntheticField2].Field[My.Qltest.K.MyField]; ReturnValue; value; manual | edges | ExternalFlow.cs:9:20:9:23 | access to local variable arg1 : Object | ExternalFlow.cs:10:29:10:32 | access to local variable arg1 : Object | provenance | | | ExternalFlow.cs:9:27:9:38 | object creation of type Object : Object | ExternalFlow.cs:9:20:9:23 | access to local variable arg1 : Object | provenance | | @@ -121,6 +127,21 @@ edges | ExternalFlow.cs:279:13:279:23 | [post] this access : J | ExternalFlow.cs:281:18:281:21 | this access : J | provenance | | | ExternalFlow.cs:279:22:279:22 | access to local variable j : Object | ExternalFlow.cs:279:13:279:23 | [post] this access : J | provenance | MaD:25 | | ExternalFlow.cs:281:18:281:21 | this access : J | ExternalFlow.cs:281:18:281:27 | access to property Prop1 | provenance | MaD:24 | +| ExternalFlow.cs:313:17:313:17 | access to local variable o : Object | ExternalFlow.cs:314:33:314:33 | access to local variable o : Object | provenance | | +| ExternalFlow.cs:313:21:313:32 | object creation of type Object : Object | ExternalFlow.cs:313:17:313:17 | access to local variable o : Object | provenance | | +| ExternalFlow.cs:314:13:314:34 | [post] this access : K [synthetic My.Qltest.K.MySyntheticField] : Object | ExternalFlow.cs:315:18:315:38 | this access : K [synthetic My.Qltest.K.MySyntheticField] : Object | provenance | | +| ExternalFlow.cs:314:33:314:33 | access to local variable o : Object | ExternalFlow.cs:314:13:314:34 | [post] this access : K [synthetic My.Qltest.K.MySyntheticField] : Object | provenance | MaD:26 | +| ExternalFlow.cs:315:18:315:38 | this access : K [synthetic My.Qltest.K.MySyntheticField] : Object | ExternalFlow.cs:315:18:315:38 | call to method GetMySyntheticField | provenance | MaD:27 | +| ExternalFlow.cs:319:17:319:17 | access to local variable o : Object | ExternalFlow.cs:320:39:320:39 | access to local variable o : Object | provenance | | +| ExternalFlow.cs:319:21:319:32 | object creation of type Object : Object | ExternalFlow.cs:319:17:319:17 | access to local variable o : Object | provenance | | +| ExternalFlow.cs:320:13:320:40 | [post] this access : K [synthetic My.Qltest.K.MySyntheticField1, synthetic MySyntheticField1.MyNestedSyntheticField] : Object | ExternalFlow.cs:321:18:321:44 | this access : K [synthetic My.Qltest.K.MySyntheticField1, synthetic MySyntheticField1.MyNestedSyntheticField] : Object | provenance | | +| ExternalFlow.cs:320:39:320:39 | access to local variable o : Object | ExternalFlow.cs:320:13:320:40 | [post] this access : K [synthetic My.Qltest.K.MySyntheticField1, synthetic MySyntheticField1.MyNestedSyntheticField] : Object | provenance | MaD:28 | +| ExternalFlow.cs:321:18:321:44 | this access : K [synthetic My.Qltest.K.MySyntheticField1, synthetic MySyntheticField1.MyNestedSyntheticField] : Object | ExternalFlow.cs:321:18:321:44 | call to method GetMyNestedSyntheticField | provenance | MaD:29 | +| ExternalFlow.cs:325:17:325:17 | access to local variable o : Object | ExternalFlow.cs:326:40:326:40 | access to local variable o : Object | provenance | | +| ExternalFlow.cs:325:21:325:32 | object creation of type Object : Object | ExternalFlow.cs:325:17:325:17 | access to local variable o : Object | provenance | | +| ExternalFlow.cs:326:13:326:41 | [post] this access : K [synthetic My.Qltest.K.MySyntheticField2, field MyField] : Object | ExternalFlow.cs:327:18:327:45 | this access : K [synthetic My.Qltest.K.MySyntheticField2, field MyField] : Object | provenance | | +| ExternalFlow.cs:326:40:326:40 | access to local variable o : Object | ExternalFlow.cs:326:13:326:41 | [post] this access : K [synthetic My.Qltest.K.MySyntheticField2, field MyField] : Object | provenance | MaD:30 | +| ExternalFlow.cs:327:18:327:45 | this access : K [synthetic My.Qltest.K.MySyntheticField2, field MyField] : Object | ExternalFlow.cs:327:18:327:45 | call to method GetMyFieldOnSyntheticField | provenance | MaD:31 | nodes | ExternalFlow.cs:9:20:9:23 | access to local variable arg1 : Object | semmle.label | access to local variable arg1 : Object | | ExternalFlow.cs:9:27:9:38 | object creation of type Object : Object | semmle.label | object creation of type Object : Object | @@ -240,17 +261,27 @@ nodes | ExternalFlow.cs:279:22:279:22 | access to local variable j : Object | semmle.label | access to local variable j : Object | | ExternalFlow.cs:281:18:281:21 | this access : J | semmle.label | this access : J | | ExternalFlow.cs:281:18:281:27 | access to property Prop1 | semmle.label | access to property Prop1 | +| ExternalFlow.cs:313:17:313:17 | access to local variable o : Object | semmle.label | access to local variable o : Object | +| ExternalFlow.cs:313:21:313:32 | object creation of type Object : Object | semmle.label | object creation of type Object : Object | +| ExternalFlow.cs:314:13:314:34 | [post] this access : K [synthetic My.Qltest.K.MySyntheticField] : Object | semmle.label | [post] this access : K [synthetic My.Qltest.K.MySyntheticField] : Object | +| ExternalFlow.cs:314:33:314:33 | access to local variable o : Object | semmle.label | access to local variable o : Object | +| ExternalFlow.cs:315:18:315:38 | call to method GetMySyntheticField | semmle.label | call to method GetMySyntheticField | +| ExternalFlow.cs:315:18:315:38 | this access : K [synthetic My.Qltest.K.MySyntheticField] : Object | semmle.label | this access : K [synthetic My.Qltest.K.MySyntheticField] : Object | +| ExternalFlow.cs:319:17:319:17 | access to local variable o : Object | semmle.label | access to local variable o : Object | +| ExternalFlow.cs:319:21:319:32 | object creation of type Object : Object | semmle.label | object creation of type Object : Object | +| ExternalFlow.cs:320:13:320:40 | [post] this access : K [synthetic My.Qltest.K.MySyntheticField1, synthetic MySyntheticField1.MyNestedSyntheticField] : Object | semmle.label | [post] this access : K [synthetic My.Qltest.K.MySyntheticField1, synthetic MySyntheticField1.MyNestedSyntheticField] : Object | +| ExternalFlow.cs:320:39:320:39 | access to local variable o : Object | semmle.label | access to local variable o : Object | +| ExternalFlow.cs:321:18:321:44 | call to method GetMyNestedSyntheticField | semmle.label | call to method GetMyNestedSyntheticField | +| ExternalFlow.cs:321:18:321:44 | this access : K [synthetic My.Qltest.K.MySyntheticField1, synthetic MySyntheticField1.MyNestedSyntheticField] : Object | semmle.label | this access : K [synthetic My.Qltest.K.MySyntheticField1, synthetic MySyntheticField1.MyNestedSyntheticField] : Object | +| ExternalFlow.cs:325:17:325:17 | access to local variable o : Object | semmle.label | access to local variable o : Object | +| ExternalFlow.cs:325:21:325:32 | object creation of type Object : Object | semmle.label | object creation of type Object : Object | +| ExternalFlow.cs:326:13:326:41 | [post] this access : K [synthetic My.Qltest.K.MySyntheticField2, field MyField] : Object | semmle.label | [post] this access : K [synthetic My.Qltest.K.MySyntheticField2, field MyField] : Object | +| ExternalFlow.cs:326:40:326:40 | access to local variable o : Object | semmle.label | access to local variable o : Object | +| ExternalFlow.cs:327:18:327:45 | call to method GetMyFieldOnSyntheticField | semmle.label | call to method GetMyFieldOnSyntheticField | +| ExternalFlow.cs:327:18:327:45 | this access : K [synthetic My.Qltest.K.MySyntheticField2, field MyField] : Object | semmle.label | this access : K [synthetic My.Qltest.K.MySyntheticField2, field MyField] : Object | subpaths | ExternalFlow.cs:84:29:84:32 | access to local variable objs : null [element] : Object | ExternalFlow.cs:84:35:84:35 | o : Object | ExternalFlow.cs:84:40:84:40 | access to parameter o : Object | ExternalFlow.cs:84:25:84:41 | call to method Map : T[] [element] : Object | invalidModelRow -| Unrecognized input specification "SyntheticField[My.Qltest.K.MySyntheticField1]" in summary model. | -| Unrecognized input specification "SyntheticField[My.Qltest.K.MySyntheticField2]" in summary model. | -| Unrecognized input specification "SyntheticField[My.Qltest.K.MySyntheticField]" in summary model. | -| Unrecognized input specification "SyntheticField[MySyntheticField1.MyNestedSyntheticField]" in summary model. | -| Unrecognized output specification "SyntheticField[My.Qltest.K.MySyntheticField1]" in summary model. | -| Unrecognized output specification "SyntheticField[My.Qltest.K.MySyntheticField2]" in summary model. | -| Unrecognized output specification "SyntheticField[My.Qltest.K.MySyntheticField]" in summary model. | -| Unrecognized output specification "SyntheticField[MySyntheticField1.MyNestedSyntheticField]" in summary model. | #select | ExternalFlow.cs:10:18:10:33 | call to method StepArgRes | ExternalFlow.cs:9:27:9:38 | object creation of type Object : Object | ExternalFlow.cs:10:18:10:33 | call to method StepArgRes | $@ | ExternalFlow.cs:9:27:9:38 | object creation of type Object : Object | object creation of type Object : Object | | ExternalFlow.cs:18:18:18:24 | access to local variable argOut1 | ExternalFlow.cs:15:29:15:40 | object creation of type Object : Object | ExternalFlow.cs:18:18:18:24 | access to local variable argOut1 | $@ | ExternalFlow.cs:15:29:15:40 | object creation of type Object : Object | object creation of type Object : Object | @@ -277,3 +308,6 @@ invalidModelRow | ExternalFlow.cs:240:18:240:18 | access to local variable o | ExternalFlow.cs:238:21:238:28 | object creation of type HC : HC | ExternalFlow.cs:240:18:240:18 | access to local variable o | $@ | ExternalFlow.cs:238:21:238:28 | object creation of type HC : HC | object creation of type HC : HC | | ExternalFlow.cs:258:18:258:18 | access to local variable b | ExternalFlow.cs:256:20:256:31 | object creation of type Object : Object | ExternalFlow.cs:258:18:258:18 | access to local variable b | $@ | ExternalFlow.cs:256:20:256:31 | object creation of type Object : Object | object creation of type Object : Object | | ExternalFlow.cs:281:18:281:27 | access to property Prop1 | ExternalFlow.cs:278:21:278:32 | object creation of type Object : Object | ExternalFlow.cs:281:18:281:27 | access to property Prop1 | $@ | ExternalFlow.cs:278:21:278:32 | object creation of type Object : Object | object creation of type Object : Object | +| ExternalFlow.cs:315:18:315:38 | call to method GetMySyntheticField | ExternalFlow.cs:313:21:313:32 | object creation of type Object : Object | ExternalFlow.cs:315:18:315:38 | call to method GetMySyntheticField | $@ | ExternalFlow.cs:313:21:313:32 | object creation of type Object : Object | object creation of type Object : Object | +| ExternalFlow.cs:321:18:321:44 | call to method GetMyNestedSyntheticField | ExternalFlow.cs:319:21:319:32 | object creation of type Object : Object | ExternalFlow.cs:321:18:321:44 | call to method GetMyNestedSyntheticField | $@ | ExternalFlow.cs:319:21:319:32 | object creation of type Object : Object | object creation of type Object : Object | +| ExternalFlow.cs:327:18:327:45 | call to method GetMyFieldOnSyntheticField | ExternalFlow.cs:325:21:325:32 | object creation of type Object : Object | ExternalFlow.cs:327:18:327:45 | call to method GetMyFieldOnSyntheticField | $@ | ExternalFlow.cs:325:21:325:32 | object creation of type Object : Object | object creation of type Object : Object |