diff --git a/csharp/ql/src/utils/model-generator/CaptureDiscardedSummaryModels.ql b/csharp/ql/src/utils/model-generator/CaptureDiscardedSummaryModels.ql index 6276f9793dc..b9e0cc23987 100644 --- a/csharp/ql/src/utils/model-generator/CaptureDiscardedSummaryModels.ql +++ b/csharp/ql/src/utils/model-generator/CaptureDiscardedSummaryModels.ql @@ -4,10 +4,10 @@ * @id csharp/utils/model-generator/discarded-summary-models */ -private import semmle.code.csharp.dataflow.ExternalFlow -private import internal.CaptureModels -private import internal.CaptureSummaryFlow +import semmle.code.csharp.dataflow.ExternalFlow +import internal.CaptureModels +import internal.CaptureSummaryFlow -from TargetApi api, string flow +from DataFlowTargetApi api, string flow where flow = captureFlow(api) and hasSummary(api, false) select flow order by flow diff --git a/csharp/ql/src/utils/model-generator/CaptureNegativeSummaryModels.ql b/csharp/ql/src/utils/model-generator/CaptureNegativeSummaryModels.ql index 09202f423ea..0e26d3eee7f 100644 --- a/csharp/ql/src/utils/model-generator/CaptureNegativeSummaryModels.ql +++ b/csharp/ql/src/utils/model-generator/CaptureNegativeSummaryModels.ql @@ -6,10 +6,12 @@ * @tags model-generator */ -private import semmle.code.csharp.dataflow.ExternalFlow -private import internal.CaptureModels -private import internal.CaptureSummaryFlow +import semmle.code.csharp.dataflow.ExternalFlow +import internal.CaptureModels +import internal.CaptureSummaryFlow -from TargetApi api, string noflow -where noflow = captureNoFlow(api) and not hasSummary(api, false) +from DataFlowTargetApi api, string noflow +where + noflow = captureNoFlow(api) and + not hasSummary(api, false) select noflow order by noflow diff --git a/csharp/ql/src/utils/model-generator/CaptureSinkModels.ql b/csharp/ql/src/utils/model-generator/CaptureSinkModels.ql index 03eeeeda273..ea249016427 100644 --- a/csharp/ql/src/utils/model-generator/CaptureSinkModels.ql +++ b/csharp/ql/src/utils/model-generator/CaptureSinkModels.ql @@ -6,8 +6,8 @@ * @tags model-generator */ -private import internal.CaptureModels +import internal.CaptureModels -from TargetApi api, string sink +from DataFlowTargetApi api, string sink where sink = captureSink(api) select sink order by sink diff --git a/csharp/ql/src/utils/model-generator/CaptureSourceModels.ql b/csharp/ql/src/utils/model-generator/CaptureSourceModels.ql index f60682b2b6d..72ce31d4b61 100644 --- a/csharp/ql/src/utils/model-generator/CaptureSourceModels.ql +++ b/csharp/ql/src/utils/model-generator/CaptureSourceModels.ql @@ -6,8 +6,8 @@ * @tags model-generator */ -private import internal.CaptureModels +import internal.CaptureModels -from TargetApi api, string source +from DataFlowTargetApi api, string source where source = captureSource(api) select source order by source diff --git a/csharp/ql/src/utils/model-generator/CaptureSummaryModels.ql b/csharp/ql/src/utils/model-generator/CaptureSummaryModels.ql index f6c91335428..f308c57c89d 100644 --- a/csharp/ql/src/utils/model-generator/CaptureSummaryModels.ql +++ b/csharp/ql/src/utils/model-generator/CaptureSummaryModels.ql @@ -6,10 +6,10 @@ * @tags model-generator */ -private import semmle.code.csharp.dataflow.ExternalFlow -private import internal.CaptureModels -private import internal.CaptureSummaryFlow +import semmle.code.csharp.dataflow.ExternalFlow +import internal.CaptureModels +import internal.CaptureSummaryFlow -from TargetApi api, string flow +from DataFlowTargetApi api, string flow where flow = captureFlow(api) and not hasSummary(api, false) select flow order by flow diff --git a/csharp/ql/src/utils/model-generator/CaptureTypeBasedSummaryModels.ql b/csharp/ql/src/utils/model-generator/CaptureTypeBasedSummaryModels.ql new file mode 100644 index 00000000000..e3dcc9dc2f6 --- /dev/null +++ b/csharp/ql/src/utils/model-generator/CaptureTypeBasedSummaryModels.ql @@ -0,0 +1,14 @@ +/** + * @name Capture typed based summary models. + * @description Finds applicable summary models to be used by other queries. + * @kind diagnostic + * @id cs/utils/model-generator/summary-models-typed-based + * @tags model-generator + */ + +import semmle.code.csharp.dataflow.ExternalFlow +import internal.CaptureTypeBasedSummaryModels + +from TypeBasedFlowTargetApi api, string flow +where flow = captureFlow(api) +select flow order by flow diff --git a/csharp/ql/src/utils/model-generator/internal/CaptureModels.qll b/csharp/ql/src/utils/model-generator/internal/CaptureModels.qll index c6ebc854edb..82c6fbd1bbb 100644 --- a/csharp/ql/src/utils/model-generator/internal/CaptureModels.qll +++ b/csharp/ql/src/utils/model-generator/internal/CaptureModels.qll @@ -5,7 +5,9 @@ private import CaptureModelsSpecific -class TargetApi = TargetApiSpecific; +class DataFlowTargetApi extends TargetApiSpecific { + DataFlowTargetApi() { isRelevantForDataFlowModels(this) } +} /** * Holds if data can flow from `node1` to `node2` either via a read or a write of an intermediate field `f`. @@ -40,7 +42,7 @@ private predicate isRelevantContent(DataFlow::Content c) { * Gets the summary model for `api` with `input`, `output` and `kind`. */ bindingset[input, output, kind] -private string asSummaryModel(TargetApi api, string input, string output, string kind) { +private string asSummaryModel(TargetApiSpecific api, string input, string output, string kind) { result = asPartialModel(api) + input + ";" // + output + ";" // @@ -48,13 +50,15 @@ private string asSummaryModel(TargetApi api, string input, string output, string + "generated" } -string asNegativeSummaryModel(TargetApi api) { result = asPartialNegativeModel(api) + "generated" } +string asNegativeSummaryModel(TargetApiSpecific api) { + result = asPartialNegativeModel(api) + "generated" +} /** * Gets the value summary model for `api` with `input` and `output`. */ bindingset[input, output] -private string asValueModel(TargetApi api, string input, string output) { +string asValueModel(TargetApiSpecific api, string input, string output) { result = asSummaryModel(api, input, output, "value") } @@ -62,7 +66,7 @@ private string asValueModel(TargetApi api, string input, string output) { * Gets the taint summary model for `api` with `input` and `output`. */ bindingset[input, output] -private string asTaintModel(TargetApi api, string input, string output) { +private string asTaintModel(TargetApiSpecific api, string input, string output) { result = asSummaryModel(api, input, output, "taint") } @@ -70,7 +74,7 @@ private string asTaintModel(TargetApi api, string input, string output) { * Gets the sink model for `api` with `input` and `kind`. */ bindingset[input, kind] -private string asSinkModel(TargetApi api, string input, string kind) { +private string asSinkModel(TargetApiSpecific api, string input, string kind) { result = asPartialModel(api) + input + ";" // + kind + ";" // @@ -81,7 +85,7 @@ private string asSinkModel(TargetApi api, string input, string kind) { * Gets the source model for `api` with `output` and `kind`. */ bindingset[output, kind] -private string asSourceModel(TargetApi api, string output, string kind) { +private string asSourceModel(TargetApiSpecific api, string output, string kind) { result = asPartialModel(api) + output + ";" // + kind + ";" // @@ -91,7 +95,7 @@ private string asSourceModel(TargetApi api, string output, string kind) { /** * Gets the summary model of `api`, if it follows the `fluent` programming pattern (returns `this`). */ -string captureQualifierFlow(TargetApi api) { +string captureQualifierFlow(TargetApiSpecific api) { exists(DataFlowImplCommon::ReturnNodeExt ret | api = returnNodeEnclosingCallable(ret) and isOwnInstanceAccessNode(ret) @@ -140,7 +144,7 @@ private class ThroughFlowConfig extends TaintTracking::Configuration { override predicate isSource(DataFlow::Node source, DataFlow::FlowState state) { source instanceof DataFlow::ParameterNode and - source.getEnclosingCallable() instanceof TargetApi and + source.getEnclosingCallable() instanceof DataFlowTargetApi and state.(TaintRead).getStep() = 0 } @@ -184,7 +188,7 @@ private class ThroughFlowConfig extends TaintTracking::Configuration { /** * Gets the summary model(s) of `api`, if there is flow from parameters to return value or parameter. */ -string captureThroughFlow(TargetApi api) { +string captureThroughFlow(DataFlowTargetApi api) { exists( ThroughFlowConfig config, DataFlow::ParameterNode p, DataFlowImplCommon::ReturnNodeExt returnNodeExt, string input, string output @@ -211,7 +215,7 @@ private class FromSourceConfiguration extends TaintTracking::Configuration { override predicate isSource(DataFlow::Node source) { ExternalFlow::sourceNode(source, _) } override predicate isSink(DataFlow::Node sink) { - exists(TargetApi c | + exists(DataFlowTargetApi c | sink instanceof DataFlowImplCommon::ReturnNodeExt and sink.getEnclosingCallable() = c ) @@ -229,7 +233,7 @@ private class FromSourceConfiguration extends TaintTracking::Configuration { /** * Gets the source model(s) of `api`, if there is flow from an existing known source to the return of `api`. */ -string captureSource(TargetApi api) { +string captureSource(DataFlowTargetApi api) { exists(DataFlow::Node source, DataFlow::Node sink, FromSourceConfiguration config, string kind | config.hasFlow(source, sink) and ExternalFlow::sourceNode(source, kind) and @@ -259,7 +263,7 @@ private class PropagateToSinkConfiguration extends PropagateToSinkConfigurationS /** * Gets the sink model(s) of `api`, if there is flow from a parameter to an existing known sink. */ -string captureSink(TargetApi api) { +string captureSink(DataFlowTargetApi api) { exists(DataFlow::Node src, DataFlow::Node sink, PropagateToSinkConfiguration config, string kind | config.hasFlow(src, sink) and ExternalFlow::sinkNode(sink, kind) and diff --git a/csharp/ql/src/utils/model-generator/internal/CaptureModelsSpecific.qll b/csharp/ql/src/utils/model-generator/internal/CaptureModelsSpecific.qll index 57407dcc391..3b0a33336c0 100644 --- a/csharp/ql/src/utils/model-generator/internal/CaptureModelsSpecific.qll +++ b/csharp/ql/src/utils/model-generator/internal/CaptureModelsSpecific.qll @@ -36,10 +36,21 @@ private predicate isRelevantForModels(CS::Callable api) { api.getDeclaringType().getNamespace().getQualifiedName() != "" and not api instanceof CS::ConversionOperator and not api instanceof Util::MainMethod and - not isHigherOrder(api) and not api instanceof CS::Destructor } +/** + * Holds if it is relevant to generate models for `api` based on data flow analysis. + */ +predicate isRelevantForDataFlowModels(CS::Callable api) { + isRelevantForModels(api) and not isHigherOrder(api) +} + +/** + * Holds if it is relevant to generate models for `api` based on its type. + */ +predicate isRelevantForTypeBasedFlowModels = isRelevantForModels/1; + /** * A class of callables that are relevant generating summary, source and sinks models for. * @@ -49,8 +60,7 @@ private predicate isRelevantForModels(CS::Callable api) { class TargetApiSpecific extends DotNet::Callable { TargetApiSpecific() { this.fromSource() and - this.isUnboundDeclaration() and - isRelevantForModels(this) + this.isUnboundDeclaration() } } @@ -100,7 +110,7 @@ predicate isRelevantType(CS::Type t) { */ string qualifierString() { result = "Argument[this]" } -private string parameterAccess(CS::Parameter p) { +string parameterAccess(CS::Parameter p) { if Collections::isCollectionType(p.getType()) then result = "Argument[" + p.getPosition() + "].Element" else result = "Argument[" + p.getPosition() + "]" diff --git a/csharp/ql/src/utils/model-generator/internal/CaptureSummaryFlow.qll b/csharp/ql/src/utils/model-generator/internal/CaptureSummaryFlow.qll index 65a5181ee89..e06ea1a609a 100644 --- a/csharp/ql/src/utils/model-generator/internal/CaptureSummaryFlow.qll +++ b/csharp/ql/src/utils/model-generator/internal/CaptureSummaryFlow.qll @@ -75,7 +75,7 @@ private import CaptureModels * Captured Model: * ```Summaries;BasicFlow;false;AssignToArray;(System.Int32,System.Int32[]);Argument[0];Argument[1].Element;taint``` */ -string captureFlow(TargetApi api) { +string captureFlow(DataFlowTargetApi api) { result = captureQualifierFlow(api) or result = captureThroughFlow(api) } @@ -84,7 +84,7 @@ string captureFlow(TargetApi api) { * Gets the negative summary for `api`, if any. * A negative summary is generated, if there does not exist any positive flow. */ -string captureNoFlow(TargetApi api) { +string captureNoFlow(DataFlowTargetApi api) { not exists(captureFlow(api)) and result = asNegativeSummaryModel(api) } diff --git a/csharp/ql/src/utils/model-generator/internal/CaptureTypeBasedSummaryModels.qll b/csharp/ql/src/utils/model-generator/internal/CaptureTypeBasedSummaryModels.qll new file mode 100644 index 00000000000..02f00986c3c --- /dev/null +++ b/csharp/ql/src/utils/model-generator/internal/CaptureTypeBasedSummaryModels.qll @@ -0,0 +1,224 @@ +private import csharp +private import dotnet +private import semmle.code.csharp.frameworks.system.collections.Generic as GenericCollections +private import semmle.code.csharp.dataflow.internal.DataFlowPrivate +private import semmle.code.csharp.frameworks.system.linq.Expressions +private import CaptureModelsSpecific as Specific +private import CaptureModels + +/** + * Holds if `t` is a subtype (reflexive/transitive) of `IEnumerable`, where `T` = `tp`. + */ +private predicate genericCollectionType(ValueOrRefType t, TypeParameter tp) { + exists(ConstructedGeneric t2 | + t2 = t.getABaseType*() and + t2.getUnboundDeclaration() instanceof + GenericCollections::SystemCollectionsGenericIEnumerableTInterface and + tp = t2.getATypeArgument() + ) +} + +/** + * Holds if `tp` is a type parameter of the immediate type declaring `callable`. + */ +private predicate classTypeParameter(DotNet::Callable callable, TypeParameter tp) { + callable.getDeclaringType().(UnboundGeneric).getATypeParameter() = tp +} + +/** + * Holds if `tp` is type parameter of `callable` or the type declaring `callable`. + */ +private predicate localTypeParameter(DotNet::Callable callable, TypeParameter tp) { + classTypeParameter(callable, tp) or + callable.(UnboundGeneric).getATypeParameter() = tp +} + +/** + * Holds if `callable` has a parameter of type `tp` + * or collection parameterized over type `tp`. + */ +private predicate parameter(DotNet::Callable callable, string input, TypeParameter tp) { + exists(Parameter p | + input = Specific::parameterAccess(p) and + p = callable.getAParameter() and + ( + // Parameter of type tp + p.getType() = tp + or + // Parameter is a collection of type tp + genericCollectionType(p.getType(), tp) + ) + ) +} + +/** + * Gets the string representation of a synthetic field corresponding to `tp`. + */ +private string getSyntheticField(TypeParameter tp) { + result = ".SyntheticField[ArgType" + tp.getIndex() + "]" +} + +/** + * Gets a models as data string representation of, how a value of type `tp` + * can be read or stored implicitly in relation to `callable`. + */ +private string implicit(DotNet::Callable callable, TypeParameter tp) { + classTypeParameter(callable, tp) and + exists(string access | + if genericCollectionType(callable.getDeclaringType(), tp) + then access = ".Element" + else access = getSyntheticField(tp) + | + result = Specific::qualifierString() + access + ) +} + +/** + * Holds if `callable` has a delegate parameter `dt` at parameter position `position`. + */ +private predicate delegate(DotNet::Callable callable, DelegateType dt, int position) { + exists(Parameter p | + p = callable.getAParameter() and + dt = p.getType().(SystemLinqExpressions::DelegateExtType).getDelegateType() and + position = p.getPosition() + ) +} + +/** + * Gets models as data input/output access relative to the type parameter `tp` in the + * type `t` in the scope of `callable`. + * + * Note: This predicate has to be inlined as `callable` is not related to `return` or `tp` + * in every disjunction. + */ +bindingset[callable] +private string getAccess(DotNet::Callable callable, Type return, TypeParameter tp) { + return = tp and result = "" + or + genericCollectionType(return, tp) and result = ".Element" + or + not genericCollectionType(return, tp) and + ( + return.(ConstructedGeneric).getATypeArgument() = tp + or + callable.getDeclaringType() = return and return.(UnboundGeneric).getATypeParameter() = tp + ) and + result = getSyntheticField(tp) +} + +/** + * Holds if `input` is a models as data string representation of, how a value of type `tp` + * (or a generic parameterized over `tp`) can be generated by a delegate parameter of `callable`. + */ +private predicate delegateSource(DotNet::Callable callable, string input, TypeParameter tp) { + exists(DelegateType dt, int position, Type return, string access | + delegate(callable, dt, position) and + return = dt.getReturnType() and + access = getAccess(callable, return, tp) and + input = "Argument[" + position + "].ReturnValue" + access + ) +} + +/** + * Holds if `input` is a models as data string representation of, how a + * value of type `tp` (or a generic parameterized over `tp`) + * can be provided as input to `callable`. + * This includes + * (1) The implicit synthetic field(s) of the declaring type of `callable`. + * (2) The parameters of `callable`. + * (3) Any delegate parameters of `callable`. + */ +private predicate input(DotNet::Callable callable, string input, TypeParameter tp) { + input = implicit(callable, tp) + or + parameter(callable, input, tp) + or + delegateSource(callable, input, tp) +} + +/** + * Holds if `callable` returns a value of type `tp` (or a generic parameterized over `tp`) and `output` + * is a models as data string representation of, how data is routed to the return. + */ +private predicate returns(DotNet::Callable callable, TypeParameter tp, string output) { + exists(Type return, string access | return = callable.getReturnType() | + access = getAccess(callable, return, tp) and + output = "ReturnValue" + access + ) +} + +/** + * Holds if `callable` has a delegate parameter that accepts a value of type `tp` + * and `output` is the models as data string representation of, how data is routed to + * the delegate parameter. + */ +private predicate delegateSink(DotNet::Callable callable, TypeParameter tp, string output) { + exists(DelegateType dt, int position, Parameter p | + delegate(callable, dt, position) and + p = dt.getAParameter() and + p.getType() = tp and + output = "Argument[" + position + "]" + ".Parameter[" + p.getPosition() + "]" + ) +} + +/** + * Holds if `output` is a models as data string representation of, how values of type `tp` + * (or generics parameterized over `tp`) can be routed. + * This includes + * (1) The implicit synthetic field(s) of the declaring type of `callable`. + * (2) The return of `callable`. + * (3) Any delegate parameters of `callable`. + */ +private predicate output(DotNet::Callable callable, TypeParameter tp, string output) { + output = implicit(callable, tp) + or + returns(callable, tp, output) + or + delegateSink(callable, tp, output) +} + +/** + * A class of callables that are relevant generating summaries for based + * on the Theorems for Free approach. + */ +class TypeBasedFlowTargetApi extends Specific::TargetApiSpecific { + TypeBasedFlowTargetApi() { Specific::isRelevantForTypeBasedFlowModels(this) } + + /** + * Gets the string representation of all type based summaries for `this` + * inspired by the Theorems for Free approach. + * + * Examples could be (see C# psuedo code below) + * (1) `Get` returns a value of type `T`. We assume that the returned + * value was fetched from a (synthetic) field. + * (2) `Set` consumes a value of type `T`. We assume that the value is stored in + * a (synthetic) field. + * (3) `Apply` is assumed to apply the provided function to a value stored in + * a (synthetic) field and return the result. + * (4) `Apply` is assumed to apply the provided function to provided value + * and return the result. + * ```csharp + * public class MyGeneric { + * public void Set(T x) { ... } + * public T Get() { ... } + * public S Apply(Func f) { ... } + * public S2 Apply(S1 x, Func f) { ... } + * } + * ``` + */ + string getSummaries() { + exists(TypeParameter tp, string input, string output | + localTypeParameter(this, tp) and + input(this, input, tp) and + output(this, tp, output) and + input != output + | + result = asValueModel(this, input, output) + ) + } +} + +/** + * Returns the Theorems for Free inspired typed based summaries for `api`. + */ +string captureFlow(TypeBasedFlowTargetApi api) { result = api.getSummaries() } diff --git a/csharp/ql/test/utils/model-generator/CaptureNegativeSummaryModels.expected b/csharp/ql/test/utils/model-generator/dataflow/CaptureNegativeSummaryModels.expected similarity index 100% rename from csharp/ql/test/utils/model-generator/CaptureNegativeSummaryModels.expected rename to csharp/ql/test/utils/model-generator/dataflow/CaptureNegativeSummaryModels.expected diff --git a/csharp/ql/test/utils/model-generator/CaptureNegativeSummaryModels.qlref b/csharp/ql/test/utils/model-generator/dataflow/CaptureNegativeSummaryModels.qlref similarity index 100% rename from csharp/ql/test/utils/model-generator/CaptureNegativeSummaryModels.qlref rename to csharp/ql/test/utils/model-generator/dataflow/CaptureNegativeSummaryModels.qlref diff --git a/csharp/ql/test/utils/model-generator/CaptureSinkModels.expected b/csharp/ql/test/utils/model-generator/dataflow/CaptureSinkModels.expected similarity index 100% rename from csharp/ql/test/utils/model-generator/CaptureSinkModels.expected rename to csharp/ql/test/utils/model-generator/dataflow/CaptureSinkModels.expected diff --git a/csharp/ql/test/utils/model-generator/CaptureSinkModels.qlref b/csharp/ql/test/utils/model-generator/dataflow/CaptureSinkModels.qlref similarity index 100% rename from csharp/ql/test/utils/model-generator/CaptureSinkModels.qlref rename to csharp/ql/test/utils/model-generator/dataflow/CaptureSinkModels.qlref diff --git a/csharp/ql/test/utils/model-generator/CaptureSourceModels.expected b/csharp/ql/test/utils/model-generator/dataflow/CaptureSourceModels.expected similarity index 100% rename from csharp/ql/test/utils/model-generator/CaptureSourceModels.expected rename to csharp/ql/test/utils/model-generator/dataflow/CaptureSourceModels.expected diff --git a/csharp/ql/test/utils/model-generator/CaptureSourceModels.qlref b/csharp/ql/test/utils/model-generator/dataflow/CaptureSourceModels.qlref similarity index 100% rename from csharp/ql/test/utils/model-generator/CaptureSourceModels.qlref rename to csharp/ql/test/utils/model-generator/dataflow/CaptureSourceModels.qlref diff --git a/csharp/ql/test/utils/model-generator/CaptureSummaryModels.expected b/csharp/ql/test/utils/model-generator/dataflow/CaptureSummaryModels.expected similarity index 100% rename from csharp/ql/test/utils/model-generator/CaptureSummaryModels.expected rename to csharp/ql/test/utils/model-generator/dataflow/CaptureSummaryModels.expected diff --git a/csharp/ql/test/utils/model-generator/CaptureSummaryModels.qlref b/csharp/ql/test/utils/model-generator/dataflow/CaptureSummaryModels.qlref similarity index 100% rename from csharp/ql/test/utils/model-generator/CaptureSummaryModels.qlref rename to csharp/ql/test/utils/model-generator/dataflow/CaptureSummaryModels.qlref diff --git a/csharp/ql/test/utils/model-generator/NoSummaries.cs b/csharp/ql/test/utils/model-generator/dataflow/NoSummaries.cs similarity index 100% rename from csharp/ql/test/utils/model-generator/NoSummaries.cs rename to csharp/ql/test/utils/model-generator/dataflow/NoSummaries.cs diff --git a/csharp/ql/test/utils/model-generator/Sinks.cs b/csharp/ql/test/utils/model-generator/dataflow/Sinks.cs similarity index 100% rename from csharp/ql/test/utils/model-generator/Sinks.cs rename to csharp/ql/test/utils/model-generator/dataflow/Sinks.cs diff --git a/csharp/ql/test/utils/model-generator/Sources.cs b/csharp/ql/test/utils/model-generator/dataflow/Sources.cs similarity index 100% rename from csharp/ql/test/utils/model-generator/Sources.cs rename to csharp/ql/test/utils/model-generator/dataflow/Sources.cs diff --git a/csharp/ql/test/utils/model-generator/Summaries.cs b/csharp/ql/test/utils/model-generator/dataflow/Summaries.cs similarity index 99% rename from csharp/ql/test/utils/model-generator/Summaries.cs rename to csharp/ql/test/utils/model-generator/dataflow/Summaries.cs index 28e777700f2..3db83726765 100644 --- a/csharp/ql/test/utils/model-generator/Summaries.cs +++ b/csharp/ql/test/utils/model-generator/dataflow/Summaries.cs @@ -259,4 +259,4 @@ public class EqualsGetHashCodeNoFlow { return intTainted; } -} \ No newline at end of file +} diff --git a/csharp/ql/test/utils/model-generator/options b/csharp/ql/test/utils/model-generator/dataflow/options similarity index 52% rename from csharp/ql/test/utils/model-generator/options rename to csharp/ql/test/utils/model-generator/dataflow/options index a55169c6e97..ed33eca5326 100644 --- a/csharp/ql/test/utils/model-generator/options +++ b/csharp/ql/test/utils/model-generator/dataflow/options @@ -1,2 +1,2 @@ semmle-extractor-options: /r:System.Linq.dll /r:System.Collections.Specialized.dll -semmle-extractor-options: ${testdir}/../../resources/stubs/System.Web.cs +semmle-extractor-options: ${testdir}/../../../resources/stubs/System.Web.cs diff --git a/csharp/ql/test/utils/model-generator/typebasedflow/CaptureTypeBasedSummaryModels.expected b/csharp/ql/test/utils/model-generator/typebasedflow/CaptureTypeBasedSummaryModels.expected new file mode 100644 index 00000000000..6405ea3fab8 --- /dev/null +++ b/csharp/ql/test/utils/model-generator/typebasedflow/CaptureTypeBasedSummaryModels.expected @@ -0,0 +1,165 @@ +| Summaries;IGrouping<,>;true;get_Key;();;Argument[this].SyntheticField[ArgType0];ReturnValue;value;generated | +| Summaries;IOrderedEnumerable<>;true;CreateOrderedEnumerable<>;(System.Func,System.Collections.Generic.IComparer,System.Boolean);;Argument[this].Element;Argument[0].Parameter[0];value;generated | +| Summaries;IOrderedEnumerable<>;true;CreateOrderedEnumerable<>;(System.Func,System.Collections.Generic.IComparer,System.Boolean);;Argument[this].Element;ReturnValue.Element;value;generated | +| Summaries;SystemLinqEnumerable;false;Aggregate<,,>;(System.Collections.Generic.IEnumerable,TAccumulate,System.Func,System.Func);;Argument[0].Element;Argument[2].Parameter[1];value;generated | +| Summaries;SystemLinqEnumerable;false;Aggregate<,,>;(System.Collections.Generic.IEnumerable,TAccumulate,System.Func,System.Func);;Argument[1];Argument[2].Parameter[0];value;generated | +| Summaries;SystemLinqEnumerable;false;Aggregate<,,>;(System.Collections.Generic.IEnumerable,TAccumulate,System.Func,System.Func);;Argument[1];Argument[3].Parameter[0];value;generated | +| Summaries;SystemLinqEnumerable;false;Aggregate<,,>;(System.Collections.Generic.IEnumerable,TAccumulate,System.Func,System.Func);;Argument[2].ReturnValue;Argument[2].Parameter[0];value;generated | +| Summaries;SystemLinqEnumerable;false;Aggregate<,,>;(System.Collections.Generic.IEnumerable,TAccumulate,System.Func,System.Func);;Argument[2].ReturnValue;Argument[3].Parameter[0];value;generated | +| Summaries;SystemLinqEnumerable;false;Aggregate<,,>;(System.Collections.Generic.IEnumerable,TAccumulate,System.Func,System.Func);;Argument[3].ReturnValue;ReturnValue;value;generated | +| Summaries;SystemLinqEnumerable;false;Aggregate<,>;(System.Collections.Generic.IEnumerable,TAccumulate,System.Func);;Argument[0].Element;Argument[2].Parameter[1];value;generated | +| Summaries;SystemLinqEnumerable;false;Aggregate<,>;(System.Collections.Generic.IEnumerable,TAccumulate,System.Func);;Argument[1];Argument[2].Parameter[0];value;generated | +| Summaries;SystemLinqEnumerable;false;Aggregate<,>;(System.Collections.Generic.IEnumerable,TAccumulate,System.Func);;Argument[1];ReturnValue;value;generated | +| Summaries;SystemLinqEnumerable;false;Aggregate<,>;(System.Collections.Generic.IEnumerable,TAccumulate,System.Func);;Argument[2].ReturnValue;Argument[2].Parameter[0];value;generated | +| Summaries;SystemLinqEnumerable;false;Aggregate<,>;(System.Collections.Generic.IEnumerable,TAccumulate,System.Func);;Argument[2].ReturnValue;ReturnValue;value;generated | +| Summaries;SystemLinqEnumerable;false;Aggregate<>;(System.Collections.Generic.IEnumerable,System.Func);;Argument[0].Element;Argument[1].Parameter[0];value;generated | +| Summaries;SystemLinqEnumerable;false;Aggregate<>;(System.Collections.Generic.IEnumerable,System.Func);;Argument[0].Element;Argument[1].Parameter[1];value;generated | +| Summaries;SystemLinqEnumerable;false;Aggregate<>;(System.Collections.Generic.IEnumerable,System.Func);;Argument[0].Element;ReturnValue;value;generated | +| Summaries;SystemLinqEnumerable;false;Aggregate<>;(System.Collections.Generic.IEnumerable,System.Func);;Argument[1].ReturnValue;Argument[1].Parameter[0];value;generated | +| Summaries;SystemLinqEnumerable;false;Aggregate<>;(System.Collections.Generic.IEnumerable,System.Func);;Argument[1].ReturnValue;Argument[1].Parameter[1];value;generated | +| Summaries;SystemLinqEnumerable;false;Aggregate<>;(System.Collections.Generic.IEnumerable,System.Func);;Argument[1].ReturnValue;ReturnValue;value;generated | +| Summaries;SystemLinqEnumerable;false;All<>;(System.Collections.Generic.IEnumerable,System.Func);;Argument[0].Element;Argument[1].Parameter[0];value;generated | +| Summaries;SystemLinqEnumerable;false;Any<>;(System.Collections.Generic.IEnumerable,System.Func);;Argument[0].Element;Argument[1].Parameter[0];value;generated | +| Summaries;SystemLinqEnumerable;false;Append<>;(System.Collections.Generic.IEnumerable,TSource);;Argument[0].Element;ReturnValue.Element;value;generated | +| Summaries;SystemLinqEnumerable;false;Append<>;(System.Collections.Generic.IEnumerable,TSource);;Argument[1];ReturnValue.Element;value;generated | +| Summaries;SystemLinqEnumerable;false;AsEnumerable<>;(System.Collections.Generic.IEnumerable);;Argument[0].Element;ReturnValue.Element;value;generated | +| Summaries;SystemLinqEnumerable;false;Average<>;(System.Collections.Generic.IEnumerable,System.Func);;Argument[0].Element;Argument[1].Parameter[0];value;generated | +| Summaries;SystemLinqEnumerable;false;Concat<>;(System.Collections.Generic.IEnumerable,System.Collections.Generic.IEnumerable);;Argument[0].Element;ReturnValue.Element;value;generated | +| Summaries;SystemLinqEnumerable;false;Concat<>;(System.Collections.Generic.IEnumerable,System.Collections.Generic.IEnumerable);;Argument[1].Element;ReturnValue.Element;value;generated | +| Summaries;SystemLinqEnumerable;false;Count<>;(System.Collections.Generic.IEnumerable,System.Func);;Argument[0].Element;Argument[1].Parameter[0];value;generated | +| Summaries;SystemLinqEnumerable;false;DefaultIfEmpty<>;(System.Collections.Generic.IEnumerable);;Argument[0].Element;ReturnValue.Element;value;generated | +| Summaries;SystemLinqEnumerable;false;DefaultIfEmpty<>;(System.Collections.Generic.IEnumerable,TSource);;Argument[0].Element;ReturnValue.Element;value;generated | +| Summaries;SystemLinqEnumerable;false;DefaultIfEmpty<>;(System.Collections.Generic.IEnumerable,TSource);;Argument[1];ReturnValue.Element;value;generated | +| Summaries;SystemLinqEnumerable;false;Distinct<>;(System.Collections.Generic.IEnumerable);;Argument[0].Element;ReturnValue.Element;value;generated | +| Summaries;SystemLinqEnumerable;false;DistinctBy<,>;(System.Collections.Generic.IEnumerable,System.Func);;Argument[0].Element;Argument[1].Parameter[0];value;generated | +| Summaries;SystemLinqEnumerable;false;DistinctBy<,>;(System.Collections.Generic.IEnumerable,System.Func);;Argument[0].Element;ReturnValue.Element;value;generated | +| Summaries;SystemLinqEnumerable;false;ElementAt<>;(System.Collections.Generic.IEnumerable,System.Int32);;Argument[0].Element;ReturnValue;value;generated | +| Summaries;SystemLinqEnumerable;false;ElementAtOrDefault<>;(System.Collections.Generic.IEnumerable,System.Int32);;Argument[0].Element;ReturnValue;value;generated | +| Summaries;SystemLinqEnumerable;false;First<>;(System.Collections.Generic.IEnumerable);;Argument[0].Element;ReturnValue;value;generated | +| Summaries;SystemLinqEnumerable;false;First<>;(System.Collections.Generic.IEnumerable,System.Func);;Argument[0].Element;Argument[1].Parameter[0];value;generated | +| Summaries;SystemLinqEnumerable;false;First<>;(System.Collections.Generic.IEnumerable,System.Func);;Argument[0].Element;ReturnValue;value;generated | +| Summaries;SystemLinqEnumerable;false;FirstOrDefault<>;(System.Collections.Generic.IEnumerable);;Argument[0].Element;ReturnValue;value;generated | +| Summaries;SystemLinqEnumerable;false;FirstOrDefault<>;(System.Collections.Generic.IEnumerable,System.Func);;Argument[0].Element;Argument[1].Parameter[0];value;generated | +| Summaries;SystemLinqEnumerable;false;FirstOrDefault<>;(System.Collections.Generic.IEnumerable,System.Func);;Argument[0].Element;ReturnValue;value;generated | +| Summaries;SystemLinqEnumerable;false;FirstOrDefault<>;(System.Collections.Generic.IEnumerable,TSource);;Argument[0].Element;ReturnValue;value;generated | +| Summaries;SystemLinqEnumerable;false;FirstOrDefault<>;(System.Collections.Generic.IEnumerable,TSource);;Argument[1];ReturnValue;value;generated | +| Summaries;SystemLinqEnumerable;false;Intersect<>;(System.Collections.Generic.IEnumerable,System.Collections.Generic.IEnumerable);;Argument[0].Element;ReturnValue.Element;value;generated | +| Summaries;SystemLinqEnumerable;false;Intersect<>;(System.Collections.Generic.IEnumerable,System.Collections.Generic.IEnumerable);;Argument[1].Element;ReturnValue.Element;value;generated | +| Summaries;SystemLinqEnumerable;false;IntersectBy<,>;(System.Collections.Generic.IEnumerable,System.Collections.Generic.IEnumerable,System.Func);;Argument[0].Element;Argument[2].Parameter[0];value;generated | +| Summaries;SystemLinqEnumerable;false;IntersectBy<,>;(System.Collections.Generic.IEnumerable,System.Collections.Generic.IEnumerable,System.Func);;Argument[0].Element;ReturnValue.Element;value;generated | +| Summaries;SystemLinqEnumerable;false;Join<,,,>;(System.Collections.Generic.IEnumerable,System.Collections.Generic.IEnumerable,System.Func,System.Func,System.Func);;Argument[0].Element;Argument[2].Parameter[0];value;generated | +| Summaries;SystemLinqEnumerable;false;Join<,,,>;(System.Collections.Generic.IEnumerable,System.Collections.Generic.IEnumerable,System.Func,System.Func,System.Func);;Argument[0].Element;Argument[4].Parameter[0];value;generated | +| Summaries;SystemLinqEnumerable;false;Join<,,,>;(System.Collections.Generic.IEnumerable,System.Collections.Generic.IEnumerable,System.Func,System.Func,System.Func);;Argument[1].Element;Argument[3].Parameter[0];value;generated | +| Summaries;SystemLinqEnumerable;false;Join<,,,>;(System.Collections.Generic.IEnumerable,System.Collections.Generic.IEnumerable,System.Func,System.Func,System.Func);;Argument[1].Element;Argument[4].Parameter[1];value;generated | +| Summaries;SystemLinqEnumerable;false;Join<,,,>;(System.Collections.Generic.IEnumerable,System.Collections.Generic.IEnumerable,System.Func,System.Func,System.Func);;Argument[4].ReturnValue;ReturnValue.Element;value;generated | +| Summaries;SystemLinqEnumerable;false;Last<>;(System.Collections.Generic.IEnumerable);;Argument[0].Element;ReturnValue;value;generated | +| Summaries;SystemLinqEnumerable;false;Last<>;(System.Collections.Generic.IEnumerable,System.Func);;Argument[0].Element;Argument[1].Parameter[0];value;generated | +| Summaries;SystemLinqEnumerable;false;Last<>;(System.Collections.Generic.IEnumerable,System.Func);;Argument[0].Element;ReturnValue;value;generated | +| Summaries;SystemLinqEnumerable;false;LastOrDefault<>;(System.Collections.Generic.IEnumerable);;Argument[0].Element;ReturnValue;value;generated | +| Summaries;SystemLinqEnumerable;false;LastOrDefault<>;(System.Collections.Generic.IEnumerable,System.Func);;Argument[0].Element;Argument[1].Parameter[0];value;generated | +| Summaries;SystemLinqEnumerable;false;LastOrDefault<>;(System.Collections.Generic.IEnumerable,System.Func);;Argument[0].Element;ReturnValue;value;generated | +| Summaries;SystemLinqEnumerable;false;LastOrDefault<>;(System.Collections.Generic.IEnumerable,TSource);;Argument[0].Element;ReturnValue;value;generated | +| Summaries;SystemLinqEnumerable;false;LastOrDefault<>;(System.Collections.Generic.IEnumerable,TSource);;Argument[1];ReturnValue;value;generated | +| Summaries;SystemLinqEnumerable;false;LongCount<>;(System.Collections.Generic.IEnumerable,System.Func);;Argument[0].Element;Argument[1].Parameter[0];value;generated | +| Summaries;SystemLinqEnumerable;false;Max<,>;(System.Collections.Generic.IEnumerable,System.Func);;Argument[0].Element;Argument[1].Parameter[0];value;generated | +| Summaries;SystemLinqEnumerable;false;Max<,>;(System.Collections.Generic.IEnumerable,System.Func);;Argument[1].ReturnValue;ReturnValue;value;generated | +| Summaries;SystemLinqEnumerable;false;Max<>;(System.Collections.Generic.IEnumerable);;Argument[0].Element;ReturnValue;value;generated | +| Summaries;SystemLinqEnumerable;false;Max<>;(System.Collections.Generic.IEnumerable,System.Func);;Argument[0].Element;Argument[1].Parameter[0];value;generated | +| Summaries;SystemLinqEnumerable;false;MaxBy<,>;(System.Collections.Generic.IEnumerable,System.Func);;Argument[0].Element;Argument[1].Parameter[0];value;generated | +| Summaries;SystemLinqEnumerable;false;MaxBy<,>;(System.Collections.Generic.IEnumerable,System.Func);;Argument[0].Element;ReturnValue;value;generated | +| Summaries;SystemLinqEnumerable;false;Min<,>;(System.Collections.Generic.IEnumerable,System.Func);;Argument[0].Element;Argument[1].Parameter[0];value;generated | +| Summaries;SystemLinqEnumerable;false;Min<,>;(System.Collections.Generic.IEnumerable,System.Func);;Argument[1].ReturnValue;ReturnValue;value;generated | +| Summaries;SystemLinqEnumerable;false;Min<>;(System.Collections.Generic.IEnumerable);;Argument[0].Element;ReturnValue;value;generated | +| Summaries;SystemLinqEnumerable;false;MinBy<,>;(System.Collections.Generic.IEnumerable,System.Func);;Argument[0].Element;Argument[1].Parameter[0];value;generated | +| Summaries;SystemLinqEnumerable;false;MinBy<,>;(System.Collections.Generic.IEnumerable,System.Func);;Argument[0].Element;ReturnValue;value;generated | +| Summaries;SystemLinqEnumerable;false;OrderBy<,>;(System.Collections.Generic.IEnumerable,System.Func);;Argument[0].Element;Argument[1].Parameter[0];value;generated | +| Summaries;SystemLinqEnumerable;false;OrderBy<,>;(System.Collections.Generic.IEnumerable,System.Func);;Argument[0].Element;ReturnValue.Element;value;generated | +| Summaries;SystemLinqEnumerable;false;OrderByDescending<,>;(System.Collections.Generic.IEnumerable,System.Func);;Argument[0].Element;Argument[1].Parameter[0];value;generated | +| Summaries;SystemLinqEnumerable;false;OrderByDescending<,>;(System.Collections.Generic.IEnumerable,System.Func);;Argument[0].Element;ReturnValue.Element;value;generated | +| Summaries;SystemLinqEnumerable;false;Prepend<>;(System.Collections.Generic.IEnumerable,TSource);;Argument[0].Element;ReturnValue.Element;value;generated | +| Summaries;SystemLinqEnumerable;false;Prepend<>;(System.Collections.Generic.IEnumerable,TSource);;Argument[1];ReturnValue.Element;value;generated | +| Summaries;SystemLinqEnumerable;false;Repeat<>;(TResult,System.Int32);;Argument[0];ReturnValue.Element;value;generated | +| Summaries;SystemLinqEnumerable;false;Reverse<>;(System.Collections.Generic.IEnumerable);;Argument[0].Element;ReturnValue.Element;value;generated | +| Summaries;SystemLinqEnumerable;false;Select<,>;(System.Collections.Generic.IEnumerable,System.Func);;Argument[0].Element;Argument[1].Parameter[0];value;generated | +| Summaries;SystemLinqEnumerable;false;Select<,>;(System.Collections.Generic.IEnumerable,System.Func);;Argument[1].ReturnValue;ReturnValue.Element;value;generated | +| Summaries;SystemLinqEnumerable;false;SelectMany<,,>;(System.Collections.Generic.IEnumerable,System.Func>,System.Func);;Argument[0].Element;Argument[1].Parameter[0];value;generated | +| Summaries;SystemLinqEnumerable;false;SelectMany<,,>;(System.Collections.Generic.IEnumerable,System.Func>,System.Func);;Argument[0].Element;Argument[2].Parameter[0];value;generated | +| Summaries;SystemLinqEnumerable;false;SelectMany<,,>;(System.Collections.Generic.IEnumerable,System.Func>,System.Func);;Argument[1].ReturnValue.Element;Argument[2].Parameter[1];value;generated | +| Summaries;SystemLinqEnumerable;false;SelectMany<,,>;(System.Collections.Generic.IEnumerable,System.Func>,System.Func);;Argument[2].ReturnValue;ReturnValue.Element;value;generated | +| Summaries;SystemLinqEnumerable;false;SelectMany<,>;(System.Collections.Generic.IEnumerable,System.Func>);;Argument[0].Element;Argument[1].Parameter[0];value;generated | +| Summaries;SystemLinqEnumerable;false;SelectMany<,>;(System.Collections.Generic.IEnumerable,System.Func>);;Argument[1].ReturnValue.Element;ReturnValue.Element;value;generated | +| Summaries;SystemLinqEnumerable;false;Single<>;(System.Collections.Generic.IEnumerable);;Argument[0].Element;ReturnValue;value;generated | +| Summaries;SystemLinqEnumerable;false;Single<>;(System.Collections.Generic.IEnumerable,System.Func);;Argument[0].Element;Argument[1].Parameter[0];value;generated | +| Summaries;SystemLinqEnumerable;false;Single<>;(System.Collections.Generic.IEnumerable,System.Func);;Argument[0].Element;ReturnValue;value;generated | +| Summaries;SystemLinqEnumerable;false;SingleOrDefault<>;(System.Collections.Generic.IEnumerable);;Argument[0].Element;ReturnValue;value;generated | +| Summaries;SystemLinqEnumerable;false;SingleOrDefault<>;(System.Collections.Generic.IEnumerable,System.Func);;Argument[0].Element;Argument[1].Parameter[0];value;generated | +| Summaries;SystemLinqEnumerable;false;SingleOrDefault<>;(System.Collections.Generic.IEnumerable,System.Func);;Argument[0].Element;ReturnValue;value;generated | +| Summaries;SystemLinqEnumerable;false;SingleOrDefault<>;(System.Collections.Generic.IEnumerable,TSource);;Argument[0].Element;ReturnValue;value;generated | +| Summaries;SystemLinqEnumerable;false;SingleOrDefault<>;(System.Collections.Generic.IEnumerable,TSource);;Argument[1];ReturnValue;value;generated | +| Summaries;SystemLinqEnumerable;false;Skip<>;(System.Collections.Generic.IEnumerable,System.Int32);;Argument[0].Element;ReturnValue.Element;value;generated | +| Summaries;SystemLinqEnumerable;false;SkipLast<>;(System.Collections.Generic.IEnumerable,System.Int32);;Argument[0].Element;ReturnValue.Element;value;generated | +| Summaries;SystemLinqEnumerable;false;SkipWhile<>;(System.Collections.Generic.IEnumerable,System.Func);;Argument[0].Element;Argument[1].Parameter[0];value;generated | +| Summaries;SystemLinqEnumerable;false;SkipWhile<>;(System.Collections.Generic.IEnumerable,System.Func);;Argument[0].Element;ReturnValue.Element;value;generated | +| Summaries;SystemLinqEnumerable;false;Take<>;(System.Collections.Generic.IEnumerable,System.Int32);;Argument[0].Element;ReturnValue.Element;value;generated | +| Summaries;SystemLinqEnumerable;false;TakeLast<>;(System.Collections.Generic.IEnumerable,System.Int32);;Argument[0].Element;ReturnValue.Element;value;generated | +| Summaries;SystemLinqEnumerable;false;TakeWhile<>;(System.Collections.Generic.IEnumerable,System.Func);;Argument[0].Element;Argument[1].Parameter[0];value;generated | +| Summaries;SystemLinqEnumerable;false;TakeWhile<>;(System.Collections.Generic.IEnumerable,System.Func);;Argument[0].Element;ReturnValue.Element;value;generated | +| Summaries;SystemLinqEnumerable;false;ThenBy<,>;(Summaries.IOrderedEnumerable,System.Func);;Argument[0].Element;Argument[1].Parameter[0];value;generated | +| Summaries;SystemLinqEnumerable;false;ThenBy<,>;(Summaries.IOrderedEnumerable,System.Func);;Argument[0].Element;ReturnValue.Element;value;generated | +| Summaries;SystemLinqEnumerable;false;ThenByDescending<,>;(Summaries.IOrderedEnumerable,System.Func);;Argument[0].Element;Argument[1].Parameter[0];value;generated | +| Summaries;SystemLinqEnumerable;false;ThenByDescending<,>;(Summaries.IOrderedEnumerable,System.Func);;Argument[0].Element;ReturnValue.Element;value;generated | +| Summaries;SystemLinqEnumerable;false;ToHashSet<>;(System.Collections.Generic.IEnumerable);;Argument[0].Element;ReturnValue.Element;value;generated | +| Summaries;SystemLinqEnumerable;false;ToList<>;(System.Collections.Generic.IEnumerable);;Argument[0].Element;ReturnValue.Element;value;generated | +| Summaries;SystemLinqEnumerable;false;Union<>;(System.Collections.Generic.IEnumerable,System.Collections.Generic.IEnumerable);;Argument[0].Element;ReturnValue.Element;value;generated | +| Summaries;SystemLinqEnumerable;false;Union<>;(System.Collections.Generic.IEnumerable,System.Collections.Generic.IEnumerable);;Argument[1].Element;ReturnValue.Element;value;generated | +| Summaries;SystemLinqEnumerable;false;UnionBy<,>;(System.Collections.Generic.IEnumerable,System.Collections.Generic.IEnumerable,System.Func);;Argument[0].Element;Argument[2].Parameter[0];value;generated | +| Summaries;SystemLinqEnumerable;false;UnionBy<,>;(System.Collections.Generic.IEnumerable,System.Collections.Generic.IEnumerable,System.Func);;Argument[0].Element;ReturnValue.Element;value;generated | +| Summaries;SystemLinqEnumerable;false;UnionBy<,>;(System.Collections.Generic.IEnumerable,System.Collections.Generic.IEnumerable,System.Func);;Argument[1].Element;Argument[2].Parameter[0];value;generated | +| Summaries;SystemLinqEnumerable;false;UnionBy<,>;(System.Collections.Generic.IEnumerable,System.Collections.Generic.IEnumerable,System.Func);;Argument[1].Element;ReturnValue.Element;value;generated | +| Summaries;SystemLinqEnumerable;false;Where<>;(System.Collections.Generic.IEnumerable,System.Func);;Argument[0].Element;Argument[1].Parameter[0];value;generated | +| Summaries;SystemLinqEnumerable;false;Where<>;(System.Collections.Generic.IEnumerable,System.Func);;Argument[0].Element;ReturnValue.Element;value;generated | +| Summaries;SystemLinqEnumerable;false;Zip<,,>;(System.Collections.Generic.IEnumerable,System.Collections.Generic.IEnumerable,System.Func);;Argument[0].Element;Argument[2].Parameter[0];value;generated | +| Summaries;SystemLinqEnumerable;false;Zip<,,>;(System.Collections.Generic.IEnumerable,System.Collections.Generic.IEnumerable,System.Func);;Argument[1].Element;Argument[2].Parameter[1];value;generated | +| Summaries;SystemLinqEnumerable;false;Zip<,,>;(System.Collections.Generic.IEnumerable,System.Collections.Generic.IEnumerable,System.Func);;Argument[2].ReturnValue;ReturnValue.Element;value;generated | +| Summaries;TypeBasedCollection<>;false;Add;(T);;Argument[0];Argument[this].Element;value;generated | +| Summaries;TypeBasedCollection<>;false;AddMany;(System.Collections.Generic.IEnumerable);;Argument[0].Element;Argument[this].Element;value;generated | +| Summaries;TypeBasedCollection<>;false;First;();;Argument[this].Element;ReturnValue;value;generated | +| Summaries;TypeBasedCollection<>;false;GetEnumerator;();;Argument[this].Element;ReturnValue.SyntheticField[ArgType0];value;generated | +| Summaries;TypeBasedCollection<>;false;GetMany;();;Argument[this].Element;ReturnValue.Element;value;generated | +| Summaries;TypeBasedComplex<>;false;AddMany;(System.Collections.Generic.IEnumerable);;Argument[0].Element;Argument[this].SyntheticField[ArgType0];value;generated | +| Summaries;TypeBasedComplex<>;false;Apply;(System.Func);;Argument[this].SyntheticField[ArgType0];Argument[0].Parameter[0];value;generated | +| Summaries;TypeBasedComplex<>;false;Apply<,>;(T1,System.Func);;Argument[0];Argument[1].Parameter[0];value;generated | +| Summaries;TypeBasedComplex<>;false;Apply<,>;(T1,System.Func);;Argument[1].ReturnValue;ReturnValue;value;generated | +| Summaries;TypeBasedComplex<>;false;Apply<>;(System.Func);;Argument[0].ReturnValue;ReturnValue;value;generated | +| Summaries;TypeBasedComplex<>;false;Apply<>;(System.Func);;Argument[this].SyntheticField[ArgType0];Argument[0].Parameter[0];value;generated | +| Summaries;TypeBasedComplex<>;false;FlatMap;(System.Func>);;Argument[0].ReturnValue.Element;Argument[0].Parameter[0];value;generated | +| Summaries;TypeBasedComplex<>;false;FlatMap;(System.Func>);;Argument[0].ReturnValue.Element;Argument[this].SyntheticField[ArgType0];value;generated | +| Summaries;TypeBasedComplex<>;false;FlatMap;(System.Func>);;Argument[0].ReturnValue.Element;ReturnValue.SyntheticField[ArgType0];value;generated | +| Summaries;TypeBasedComplex<>;false;FlatMap;(System.Func>);;Argument[this].SyntheticField[ArgType0];Argument[0].Parameter[0];value;generated | +| Summaries;TypeBasedComplex<>;false;FlatMap;(System.Func>);;Argument[this].SyntheticField[ArgType0];ReturnValue.SyntheticField[ArgType0];value;generated | +| Summaries;TypeBasedComplex<>;false;FlatMap<>;(System.Func>);;Argument[0].ReturnValue.Element;ReturnValue.SyntheticField[ArgType0];value;generated | +| Summaries;TypeBasedComplex<>;false;FlatMap<>;(System.Func>);;Argument[this].SyntheticField[ArgType0];Argument[0].Parameter[0];value;generated | +| Summaries;TypeBasedComplex<>;false;GetMany;();;Argument[this].SyntheticField[ArgType0];ReturnValue.Element;value;generated | +| Summaries;TypeBasedComplex<>;false;Map<>;(System.Func);;Argument[0].ReturnValue;ReturnValue;value;generated | +| Summaries;TypeBasedComplex<>;false;Map<>;(System.Func);;Argument[this].SyntheticField[ArgType0];Argument[0].Parameter[0];value;generated | +| Summaries;TypeBasedComplex<>;false;MapComplex<>;(System.Func);;Argument[0].ReturnValue;ReturnValue.SyntheticField[ArgType0];value;generated | +| Summaries;TypeBasedComplex<>;false;MapComplex<>;(System.Func);;Argument[this].SyntheticField[ArgType0];Argument[0].Parameter[0];value;generated | +| Summaries;TypeBasedComplex<>;false;Return;(System.Func>);;Argument[0].ReturnValue.SyntheticField[ArgType0];Argument[0].Parameter[0];value;generated | +| Summaries;TypeBasedComplex<>;false;Return;(System.Func>);;Argument[0].ReturnValue.SyntheticField[ArgType0];Argument[this].SyntheticField[ArgType0];value;generated | +| Summaries;TypeBasedComplex<>;false;Return;(System.Func>);;Argument[0].ReturnValue.SyntheticField[ArgType0];ReturnValue.SyntheticField[ArgType0];value;generated | +| Summaries;TypeBasedComplex<>;false;Return;(System.Func>);;Argument[this].SyntheticField[ArgType0];Argument[0].Parameter[0];value;generated | +| Summaries;TypeBasedComplex<>;false;Return;(System.Func>);;Argument[this].SyntheticField[ArgType0];ReturnValue.SyntheticField[ArgType0];value;generated | +| Summaries;TypeBasedComplex<>;false;Set;(System.Int32,System.Func);;Argument[1].ReturnValue;Argument[this].SyntheticField[ArgType0];value;generated | +| Summaries;TypeBasedNoCollection<>;false;Get;();;Argument[this].SyntheticField[ArgType0];ReturnValue;value;generated | +| Summaries;TypeBasedNoCollection<>;false;Set;(T);;Argument[0];Argument[this].SyntheticField[ArgType0];value;generated | +| Summaries;TypeBasedSimple<>;false;Get;();;Argument[this].SyntheticField[ArgType0];ReturnValue;value;generated | +| Summaries;TypeBasedSimple<>;false;Get;(System.Object);;Argument[this].SyntheticField[ArgType0];ReturnValue;value;generated | +| Summaries;TypeBasedSimple<>;false;Id;(T);;Argument[0];Argument[this].SyntheticField[ArgType0];value;generated | +| Summaries;TypeBasedSimple<>;false;Id;(T);;Argument[0];ReturnValue;value;generated | +| Summaries;TypeBasedSimple<>;false;Id;(T);;Argument[this].SyntheticField[ArgType0];ReturnValue;value;generated | +| Summaries;TypeBasedSimple<>;false;Id<>;(S);;Argument[0];ReturnValue;value;generated | +| Summaries;TypeBasedSimple<>;false;Set;(System.Int32,T);;Argument[1];Argument[this].SyntheticField[ArgType0];value;generated | +| Summaries;TypeBasedSimple<>;false;Set;(T);;Argument[0];Argument[this].SyntheticField[ArgType0];value;generated | +| Summaries;TypeBasedSimple<>;false;TypeBasedSimple;(T);;Argument[0];Argument[this].SyntheticField[ArgType0];value;generated | +| Summaries;TypeBasedSimple<>;false;get_Prop;();;Argument[this].SyntheticField[ArgType0];ReturnValue;value;generated | +| Summaries;TypeBasedSimple<>;false;set_Prop;(T);;Argument[0];Argument[this].SyntheticField[ArgType0];value;generated | diff --git a/csharp/ql/test/utils/model-generator/typebasedflow/CaptureTypeBasedSummaryModels.qlref b/csharp/ql/test/utils/model-generator/typebasedflow/CaptureTypeBasedSummaryModels.qlref new file mode 100644 index 00000000000..99c0975a4c2 --- /dev/null +++ b/csharp/ql/test/utils/model-generator/typebasedflow/CaptureTypeBasedSummaryModels.qlref @@ -0,0 +1 @@ +utils/model-generator/CaptureTypeBasedSummaryModels.ql \ No newline at end of file diff --git a/csharp/ql/test/utils/model-generator/typebasedflow/TypeBasedSummaries.cs b/csharp/ql/test/utils/model-generator/typebasedflow/TypeBasedSummaries.cs new file mode 100644 index 00000000000..f87563b945d --- /dev/null +++ b/csharp/ql/test/utils/model-generator/typebasedflow/TypeBasedSummaries.cs @@ -0,0 +1,210 @@ +using System; +using System.Linq; +using System.Collections; +using System.Collections.Generic; + +namespace Summaries; + +public class TypeBasedSimple { + + public T Prop { + get { throw null; } + set { throw null; } + } + + public TypeBasedSimple(T t) { throw null; } + + public T Get() { throw null; } + + public T Get(object x) { throw null; } + + public T Id(T x) { throw null; } + + public S Id(S x) { throw null; } + + public void Set(T x) { throw null; } + + public void Set(int x, T y) { throw null; } + + public void Set(S x) { throw null; } // No summary as S is unrelated to T +} + +public class TypeBasedComplex { + + public void AddMany(IEnumerable xs) { throw null; } + + public int Apply(Func f) { throw null; } + + public S Apply(Func f) { throw null; } + + public T2 Apply(T1 x, Func f) { throw null; } + + public TypeBasedComplex FlatMap(Func> f) { throw null; } + + public TypeBasedComplex FlatMap(Func> f) { throw null; } + + public IList GetMany() { throw null; } + + public S Map(Func f) { throw null; } + + public TypeBasedComplex MapComplex(Func f) { throw null; } + + public TypeBasedComplex Return(Func> f) { throw null; } + + public void Set(int x, Func f) { throw null;} +} + +// It is assumed that this is a collection with elements of type T. +public class TypeBasedCollection : IEnumerable { + IEnumerator IEnumerable.GetEnumerator() { throw null; } + IEnumerator IEnumerable.GetEnumerator() { throw null; } + + public void Add(T x) { throw null; } + + public void AddMany(IEnumerable x) { throw null; } + + public T First() { throw null; } + + public ICollection GetMany() { throw null; } +} + +// It is assumed that this is NOT a collection with elements of type T. +public class TypeBasedNoCollection : IEnumerable { + IEnumerator IEnumerable.GetEnumerator() { throw null; } + + public T Get() { throw null; } + + public void Set(T x) { throw null; } +} + +/* + * Representative subset of Linq. + * + * Only methods that will get summaries generated correctly are commented in. + * The remaning methods and interfaces are commented out with a descriptive reason. + * In some cases we will not be able correctly generate a summary based purely on the + * type information. + */ +public static class SystemLinqEnumerable { + + public static TSource Aggregate(this IEnumerable source, Func func) { throw null; } + public static TAccumulate Aggregate(this IEnumerable source, TAccumulate seed, Func func) { throw null; } + public static TResult Aggregate(this IEnumerable source, TAccumulate seed, Func func, Func resultSelector) { throw null; } + public static bool All(this IEnumerable source, Func predicate) { throw null; } + public static bool Any(this IEnumerable source) { throw null; } + public static bool Any(this IEnumerable source, Func predicate) { throw null; } + public static IEnumerable Append(this IEnumerable source, TSource element) { throw null; } + public static IEnumerable AsEnumerable(this IEnumerable source) { throw null; } + public static decimal Average(this IEnumerable source, Func selector) { throw null; } + // Summary will not be derivables based on type information. + // public static IEnumerable Cast(this IEnumerable source) { throw null; } + public static IEnumerable Chunk(this IEnumerable source, int size) { throw null; } + public static IEnumerable Concat(this IEnumerable first, IEnumerable second) { throw null; } + public static bool Contains(this IEnumerable source, TSource value) { throw null; } + public static int Count(this IEnumerable source) { throw null; } + public static int Count(this IEnumerable source, Func predicate) { throw null; } + public static IEnumerable DefaultIfEmpty(this IEnumerable source) { throw null; } + public static IEnumerable DefaultIfEmpty(this IEnumerable source, TSource defaultValue) { throw null; } + public static IEnumerable DistinctBy(this IEnumerable source, Func keySelector) { throw null; } + public static IEnumerable Distinct(this IEnumerable source) { throw null; } + public static TSource? ElementAtOrDefault(this IEnumerable source, int index) { throw null; } + public static TSource ElementAt(this IEnumerable source, int index) { throw null; } + public static IEnumerable Empty() { throw null; } + // These summaries will not be derivable based on type information. + // public static IEnumerable ExceptBy(this IEnumerable first, IEnumerable second, Func keySelector) { throw null; } + // public static IEnumerable Except(this IEnumerable first, IEnumerable second) { throw null; } + public static TSource? FirstOrDefault(this IEnumerable source) { throw null; } + public static TSource FirstOrDefault(this IEnumerable source, TSource defaultValue) { throw null; } + public static TSource? FirstOrDefault(this IEnumerable source, Func predicate) { throw null; } + // Summary will not be correctly derivable based on type information. + // public static TSource FirstOrDefault(this IEnumerable source, Func predicate, TSource defaultValue) { throw null; } + public static TSource First(this IEnumerable source) { throw null; } + public static TSource First(this IEnumerable source, Func predicate) { throw null; } + // Missing summary for Argument[0].Element -> Argument[2].Parameter[1].Element and similar problem for GroupJoin (issue with generator) + // public static IEnumerable GroupBy(this IEnumerable source, Func keySelector, Func, TResult> resultSelector) { throw null; } + // public static IEnumerable GroupJoin(this IEnumerable outer, IEnumerable inner, Func outerKeySelector, Func innerKeySelector, Func, TResult> resultSelector) { throw null; } + public static IEnumerable IntersectBy(this IEnumerable first, IEnumerable second, Func keySelector) { throw null; } + public static IEnumerable Intersect(this IEnumerable first, IEnumerable second) { throw null; } + public static IEnumerable Join(this IEnumerable outer, IEnumerable inner, Func outerKeySelector, Func innerKeySelector, Func resultSelector) { throw null; } + public static TSource? LastOrDefault(this IEnumerable source) { throw null; } + public static TSource LastOrDefault(this IEnumerable source, TSource defaultValue) { throw null; } + public static TSource? LastOrDefault(this IEnumerable source, Func predicate) { throw null; } + // Summary will not be correctly derivable based on type information (same problem as for FirstOrDefault) + // public static TSource LastOrDefault(this IEnumerable source, Func predicate, TSource defaultValue) { throw null; } + public static TSource Last(this IEnumerable source) { throw null; } + public static TSource Last(this IEnumerable source, Func predicate) { throw null; } + public static long LongCount(this IEnumerable source, Func predicate) { throw null; } + public static TSource? MaxBy(this IEnumerable source, Func keySelector) { throw null; } + public static TSource? Max(this IEnumerable source) { throw null; } + public static decimal Max(this IEnumerable source, Func selector) { throw null; } + public static TResult? Max(this IEnumerable source, Func selector) { throw null; } + public static TSource? MinBy(this IEnumerable source, Func keySelector) { throw null; } + public static TSource? Min(this IEnumerable source) { throw null; } + public static TResult? Min(this IEnumerable source, Func selector) { throw null; } + // These summaries will not be derivable based on type information. + // public static IEnumerable OfType(this IEnumerable source) { throw null; } + public static IOrderedEnumerable OrderByDescending(this IEnumerable source, Func keySelector) { throw null; } + public static IOrderedEnumerable OrderBy(this IEnumerable source, Func keySelector) { throw null; } + public static IEnumerable Prepend(this IEnumerable source, TSource element) { throw null; } + public static IEnumerable Repeat(TResult element, int count) { throw null; } + public static IEnumerable Reverse(this IEnumerable source) { throw null; } + public static IEnumerable SelectMany(this IEnumerable source, Func> selector) { throw null; } + public static IEnumerable SelectMany(this IEnumerable source, Func> collectionSelector, Func resultSelector) { throw null; } + public static IEnumerable Select(this IEnumerable source, Func selector) { throw null; } + public static bool SequenceEqual(this IEnumerable first, IEnumerable second) { throw null; } + public static TSource? SingleOrDefault(this IEnumerable source) { throw null; } + public static TSource SingleOrDefault(this IEnumerable source, TSource defaultValue) { throw null; } + public static TSource? SingleOrDefault(this IEnumerable source, Func predicate) { throw null; } + // Summary will not be correctly derivable based on type information (same problem as for FirstOrDefault) + // public static TSource SingleOrDefault(this IEnumerable source, Func predicate, TSource defaultValue) { throw null; } + public static TSource Single(this IEnumerable source) { throw null; } + public static TSource Single(this IEnumerable source, Func predicate) { throw null; } + public static IEnumerable SkipLast(this IEnumerable source, int count) { throw null; } + public static IEnumerable SkipWhile(this IEnumerable source, Func predicate) { throw null; } + public static IEnumerable Skip(this IEnumerable source, int count) { throw null; } + public static IEnumerable TakeLast(this IEnumerable source, int count) { throw null; } + public static IEnumerable TakeWhile(this IEnumerable source, Func predicate) { throw null; } + public static IEnumerable Take(this IEnumerable source, int count) { throw null; } + public static IOrderedEnumerable ThenByDescending(this IOrderedEnumerable source, Func keySelector) { throw null; } + public static IOrderedEnumerable ThenBy(this IOrderedEnumerable source, Func keySelector) { throw null; } + // Missing summary for Argument[0].Element -> ReturnValue.Element (issue with generator) + // public static TSource[] ToArray(this IEnumerable source) { throw null; } + // Summaries related to dictionaries is not generated correctly as dictionaries are not identified as collections of keys and values (issue with generator). + // public static Dictionary ToDictionary(this IEnumerable source, Func keySelector) where TKey : notnull { throw null; } + // public static Dictionary ToDictionary(this IEnumerable source, Func keySelector, Func elementSelector) where TKey : notnull { throw null; } + public static HashSet ToHashSet(this IEnumerable source) { throw null; } + public static List ToList(this IEnumerable source) { throw null; } + // Type to complicated to be handled by the generator (issue with generator). + // public static ILookup ToLookup(this IEnumerable source, Func keySelector) { throw null; } + // public static ILookup ToLookup(this IEnumerable source, Func keySelector, Func elementSelector) { throw null; } + public static IEnumerable UnionBy(this IEnumerable first, IEnumerable second, Func keySelector) { throw null; } + public static IEnumerable Union(this IEnumerable first, IEnumerable second) { throw null; } + public static IEnumerable Where(this IEnumerable source, Func predicate) { throw null; } + // Type to complicated to be handled by the generator (issue with generator). + // public static IEnumerable<(TFirst First, TSecond Second)> Zip(this IEnumerable first, IEnumerable second) { throw null; } + // public static IEnumerable<(TFirst First, TSecond Second, TThird Third)> Zip(this IEnumerable first, IEnumerable second, IEnumerable third) { throw null; } + public static IEnumerable Zip(this IEnumerable first, IEnumerable second, Func resultSelector) { throw null; } +} + +public interface IGrouping : IEnumerable, IEnumerable { + TKey Key { get; } +} + +// public interface ILookup : IEnumerable>, IEnumerable { +// IEnumerable this[TKey key] { get; } +// bool Contains(TKey key); +// } + +public interface IOrderedEnumerable : IEnumerable, IEnumerable { + IOrderedEnumerable CreateOrderedEnumerable(Func keySelector, IComparer? comparer, bool descending); +} + +// public partial class Lookup : IEnumerable>, IEnumerable, ILookup{ +// internal Lookup() { } +// public int Count { get { throw null; } } +// public IEnumerable this[TKey key] { get { throw null; } } +// public IEnumerable ApplyResultSelector(Func, TResult> resultSelector) { throw null; } +// public bool Contains(TKey key) { throw null; } +// public IEnumerator> GetEnumerator() { throw null; } +// IEnumerator IEnumerable.GetEnumerator() { throw null; } +// } diff --git a/java/ql/src/utils/model-generator/CaptureNegativeSummaryModels.ql b/java/ql/src/utils/model-generator/CaptureNegativeSummaryModels.ql index 60bf8351de2..49ed16aa1dc 100644 --- a/java/ql/src/utils/model-generator/CaptureNegativeSummaryModels.ql +++ b/java/ql/src/utils/model-generator/CaptureNegativeSummaryModels.ql @@ -6,9 +6,9 @@ * @tags model-generator */ -private import internal.CaptureModels -private import internal.CaptureSummaryFlow +import internal.CaptureModels +import internal.CaptureSummaryFlow -from TargetApi api, string noflow +from DataFlowTargetApi api, string noflow where noflow = captureNoFlow(api) select noflow order by noflow diff --git a/java/ql/src/utils/model-generator/CaptureSinkModels.ql b/java/ql/src/utils/model-generator/CaptureSinkModels.ql index 405b9fab772..154c87928fc 100644 --- a/java/ql/src/utils/model-generator/CaptureSinkModels.ql +++ b/java/ql/src/utils/model-generator/CaptureSinkModels.ql @@ -6,8 +6,8 @@ * @tags model-generator */ -private import internal.CaptureModels +import internal.CaptureModels -from TargetApi api, string sink +from DataFlowTargetApi api, string sink where sink = captureSink(api) select sink order by sink diff --git a/java/ql/src/utils/model-generator/CaptureSourceModels.ql b/java/ql/src/utils/model-generator/CaptureSourceModels.ql index d37cf5e78fb..8c7de037a90 100644 --- a/java/ql/src/utils/model-generator/CaptureSourceModels.ql +++ b/java/ql/src/utils/model-generator/CaptureSourceModels.ql @@ -6,8 +6,8 @@ * @tags model-generator */ -private import internal.CaptureModels +import internal.CaptureModels -from TargetApi api, string source +from DataFlowTargetApi api, string source where source = captureSource(api) select source order by source diff --git a/java/ql/src/utils/model-generator/CaptureSummaryModels.ql b/java/ql/src/utils/model-generator/CaptureSummaryModels.ql index a4eaea9c4e8..981c6fe73fc 100644 --- a/java/ql/src/utils/model-generator/CaptureSummaryModels.ql +++ b/java/ql/src/utils/model-generator/CaptureSummaryModels.ql @@ -6,9 +6,9 @@ * @tags model-generator */ -private import internal.CaptureModels -private import internal.CaptureSummaryFlow +import internal.CaptureModels +import internal.CaptureSummaryFlow -from TargetApi api, string flow +from DataFlowTargetApi api, string flow where flow = captureFlow(api) select flow order by flow diff --git a/java/ql/src/utils/model-generator/internal/CaptureModels.qll b/java/ql/src/utils/model-generator/internal/CaptureModels.qll index c6ebc854edb..82c6fbd1bbb 100644 --- a/java/ql/src/utils/model-generator/internal/CaptureModels.qll +++ b/java/ql/src/utils/model-generator/internal/CaptureModels.qll @@ -5,7 +5,9 @@ private import CaptureModelsSpecific -class TargetApi = TargetApiSpecific; +class DataFlowTargetApi extends TargetApiSpecific { + DataFlowTargetApi() { isRelevantForDataFlowModels(this) } +} /** * Holds if data can flow from `node1` to `node2` either via a read or a write of an intermediate field `f`. @@ -40,7 +42,7 @@ private predicate isRelevantContent(DataFlow::Content c) { * Gets the summary model for `api` with `input`, `output` and `kind`. */ bindingset[input, output, kind] -private string asSummaryModel(TargetApi api, string input, string output, string kind) { +private string asSummaryModel(TargetApiSpecific api, string input, string output, string kind) { result = asPartialModel(api) + input + ";" // + output + ";" // @@ -48,13 +50,15 @@ private string asSummaryModel(TargetApi api, string input, string output, string + "generated" } -string asNegativeSummaryModel(TargetApi api) { result = asPartialNegativeModel(api) + "generated" } +string asNegativeSummaryModel(TargetApiSpecific api) { + result = asPartialNegativeModel(api) + "generated" +} /** * Gets the value summary model for `api` with `input` and `output`. */ bindingset[input, output] -private string asValueModel(TargetApi api, string input, string output) { +string asValueModel(TargetApiSpecific api, string input, string output) { result = asSummaryModel(api, input, output, "value") } @@ -62,7 +66,7 @@ private string asValueModel(TargetApi api, string input, string output) { * Gets the taint summary model for `api` with `input` and `output`. */ bindingset[input, output] -private string asTaintModel(TargetApi api, string input, string output) { +private string asTaintModel(TargetApiSpecific api, string input, string output) { result = asSummaryModel(api, input, output, "taint") } @@ -70,7 +74,7 @@ private string asTaintModel(TargetApi api, string input, string output) { * Gets the sink model for `api` with `input` and `kind`. */ bindingset[input, kind] -private string asSinkModel(TargetApi api, string input, string kind) { +private string asSinkModel(TargetApiSpecific api, string input, string kind) { result = asPartialModel(api) + input + ";" // + kind + ";" // @@ -81,7 +85,7 @@ private string asSinkModel(TargetApi api, string input, string kind) { * Gets the source model for `api` with `output` and `kind`. */ bindingset[output, kind] -private string asSourceModel(TargetApi api, string output, string kind) { +private string asSourceModel(TargetApiSpecific api, string output, string kind) { result = asPartialModel(api) + output + ";" // + kind + ";" // @@ -91,7 +95,7 @@ private string asSourceModel(TargetApi api, string output, string kind) { /** * Gets the summary model of `api`, if it follows the `fluent` programming pattern (returns `this`). */ -string captureQualifierFlow(TargetApi api) { +string captureQualifierFlow(TargetApiSpecific api) { exists(DataFlowImplCommon::ReturnNodeExt ret | api = returnNodeEnclosingCallable(ret) and isOwnInstanceAccessNode(ret) @@ -140,7 +144,7 @@ private class ThroughFlowConfig extends TaintTracking::Configuration { override predicate isSource(DataFlow::Node source, DataFlow::FlowState state) { source instanceof DataFlow::ParameterNode and - source.getEnclosingCallable() instanceof TargetApi and + source.getEnclosingCallable() instanceof DataFlowTargetApi and state.(TaintRead).getStep() = 0 } @@ -184,7 +188,7 @@ private class ThroughFlowConfig extends TaintTracking::Configuration { /** * Gets the summary model(s) of `api`, if there is flow from parameters to return value or parameter. */ -string captureThroughFlow(TargetApi api) { +string captureThroughFlow(DataFlowTargetApi api) { exists( ThroughFlowConfig config, DataFlow::ParameterNode p, DataFlowImplCommon::ReturnNodeExt returnNodeExt, string input, string output @@ -211,7 +215,7 @@ private class FromSourceConfiguration extends TaintTracking::Configuration { override predicate isSource(DataFlow::Node source) { ExternalFlow::sourceNode(source, _) } override predicate isSink(DataFlow::Node sink) { - exists(TargetApi c | + exists(DataFlowTargetApi c | sink instanceof DataFlowImplCommon::ReturnNodeExt and sink.getEnclosingCallable() = c ) @@ -229,7 +233,7 @@ private class FromSourceConfiguration extends TaintTracking::Configuration { /** * Gets the source model(s) of `api`, if there is flow from an existing known source to the return of `api`. */ -string captureSource(TargetApi api) { +string captureSource(DataFlowTargetApi api) { exists(DataFlow::Node source, DataFlow::Node sink, FromSourceConfiguration config, string kind | config.hasFlow(source, sink) and ExternalFlow::sourceNode(source, kind) and @@ -259,7 +263,7 @@ private class PropagateToSinkConfiguration extends PropagateToSinkConfigurationS /** * Gets the sink model(s) of `api`, if there is flow from a parameter to an existing known sink. */ -string captureSink(TargetApi api) { +string captureSink(DataFlowTargetApi api) { exists(DataFlow::Node src, DataFlow::Node sink, PropagateToSinkConfiguration config, string kind | config.hasFlow(src, sink) and ExternalFlow::sinkNode(sink, kind) and diff --git a/java/ql/src/utils/model-generator/internal/CaptureModelsSpecific.qll b/java/ql/src/utils/model-generator/internal/CaptureModelsSpecific.qll index bcdd90caac5..2e630ec5214 100644 --- a/java/ql/src/utils/model-generator/internal/CaptureModelsSpecific.qll +++ b/java/ql/src/utils/model-generator/internal/CaptureModelsSpecific.qll @@ -59,6 +59,11 @@ private predicate isRelevantForModels(J::Callable api) { not api instanceof J::StaticInitializer } +/** + * Holds if it is relevant to generate models for `api` based on data flow analysis. + */ +predicate isRelevantForDataFlowModels = isRelevantForModels/1; + /** * A class of Callables that are relevant for generating summary, source and sinks models for. * diff --git a/java/ql/src/utils/model-generator/internal/CaptureSummaryFlow.qll b/java/ql/src/utils/model-generator/internal/CaptureSummaryFlow.qll index 196b2189e94..dce9ce9cfef 100644 --- a/java/ql/src/utils/model-generator/internal/CaptureSummaryFlow.qll +++ b/java/ql/src/utils/model-generator/internal/CaptureSummaryFlow.qll @@ -67,7 +67,7 @@ private import CaptureModels * Captured Model: * ```p;Foo;true;addToList;;Argument[0];Argument[1];taint``` */ -string captureFlow(TargetApi api) { +string captureFlow(DataFlowTargetApi api) { result = captureQualifierFlow(api) or result = captureThroughFlow(api) } @@ -76,7 +76,7 @@ string captureFlow(TargetApi api) { * Gets the negative summary for `api`, if any. * A negative summary is generated, if there does not exist any positive flow. */ -string captureNoFlow(TargetApi api) { +string captureNoFlow(DataFlowTargetApi api) { not exists(captureFlow(api)) and result = asNegativeSummaryModel(api) } diff --git a/misc/scripts/models-as-data/generate_flow_model.py b/misc/scripts/models-as-data/generate_flow_model.py index 3a0583fb15b..bb46565ea3b 100644 --- a/misc/scripts/models-as-data/generate_flow_model.py +++ b/misc/scripts/models-as-data/generate_flow_model.py @@ -15,12 +15,13 @@ class Generator: self.generateSources = False self.generateSummaries = False self.generateNegativeSummaries = False + self.generateTypeBasedSummaries = False self.dryRun = False def printHelp(self): print(f"""Usage: -python3 GenerateFlowModel.py [] [--with-sinks] [--with-sources] [--with-summaries] [--dry-run] +python3 GenerateFlowModel.py [] [--with-sinks] [--with-sources] [--with-summaries] [--with-typebased-summaries] [--dry-run] This generates summary, source and sink models for the code in the database. The files will be placed in `{self.language}/ql/lib/semmle/code/{self.language}/frameworks/` where @@ -33,6 +34,7 @@ Which models are generated is controlled by the flags: --with-sources --with-summaries --with-negative-summaries + --with-typebased-summaries (Experimental - only for C#) If none of these flags are specified, all models are generated. --dry-run: Only run the queries, but don't write to file. @@ -62,6 +64,7 @@ Requirements: `codeql` should both appear on your path. self.codeQlRoot, f"{self.language}/ql/lib/semmle/code/{self.language}/frameworks/") self.frameworkTarget = os.path.join(self.generatedFrameworks, dirname, filename) self.negativeFrameworkTarget = os.path.join(self.generatedFrameworks, dirname, "Negative" + filename) + self.typeBasedFrameworkTarget = os.path.join(self.generatedFrameworks, dirname, "TypeBased" + filename) self.workDir = tempfile.mkdtemp() os.makedirs(self.generatedFrameworks, exist_ok=True) @@ -90,11 +93,15 @@ Requirements: `codeql` should both appear on your path. sys.argv.remove("--with-negative-summaries") generator.generateNegativeSummaries = True + if "--with-typebased-summaries" in sys.argv: + sys.argv.remove("--with-typebased-summaries") + generator.generateTypeBasedSummaries = True + if "--dry-run" in sys.argv: sys.argv.remove("--dry-run") generator.dryRun = True - if not generator.generateSinks and not generator.generateSources and not generator.generateSummaries and not generator.generateNegativeSummaries: + if not generator.generateSinks and not generator.generateSources and not generator.generateSummaries and not generator.generateNegativeSummaries and not generator.generateTypeBasedSummaries: generator.generateSinks = generator.generateSources = generator.generateSummaries = generator.generateNegativeSummaries = True if len(sys.argv) < 3 or len(sys.argv) > 4: @@ -207,7 +214,7 @@ private import semmle.code.{self.language}.dataflow.ExternalFlow negativeSummaryCsv = "" return f""" -/** +/** * THIS FILE IS AN AUTO-GENERATED MODELS AS DATA FILE. DO NOT EDIT. * Definitions of negative summaries in the {self.friendlyname} framework. */ @@ -219,6 +226,25 @@ private import semmle.code.{self.language}.dataflow.ExternalFlow """ + def makeTypeBasedContent(self): + if self.generateTypeBasedSummaries: + typeBasedSummaryRows = self.runQuery("type based summary models", "CaptureTypeBasedSummaryModels.ql") + typeBasedSummaryCsv = self.asCsvModel("SummaryModelCsv", "TypeBasedSummary", typeBasedSummaryRows) + else: + typeBasedSummaryCsv = "" + + return f""" +/** + * THIS FILE IS AN AUTO-GENERATED MODELS AS DATA FILE. DO NOT EDIT. + * Definitions of type based summaries in the {self.friendlyname} framework. + */ + +import {self.language} +private import semmle.code.{self.language}.dataflow.ExternalFlow + +{typeBasedSummaryCsv} + + """ def save(self, content, target): with open(target, "w") as targetQll: @@ -237,6 +263,7 @@ private import semmle.code.{self.language}.dataflow.ExternalFlow def run(self): content = self.makeContent() negativeContent = self.makeNegativeContent() + typeBasedContent = self.makeTypeBasedContent() if self.dryRun: print("CSV Models generated, but not written to file.") @@ -247,3 +274,6 @@ private import semmle.code.{self.language}.dataflow.ExternalFlow if self.generateNegativeSummaries: self.save(negativeContent, self.negativeFrameworkTarget) + + if self.generateTypeBasedSummaries: + self.save(typeBasedContent, self.typeBasedFrameworkTarget)