diff --git a/csharp/ql/src/utils/modelgenerator/internal/CaptureModels.qll b/csharp/ql/src/utils/modelgenerator/internal/CaptureModels.qll index 108c3f84d2c2..125204d7c5bd 100644 --- a/csharp/ql/src/utils/modelgenerator/internal/CaptureModels.qll +++ b/csharp/ql/src/utils/modelgenerator/internal/CaptureModels.qll @@ -233,6 +233,10 @@ module ModelGeneratorInput implements ModelGeneratorInputSig::paramReturnNodeAsOutput(c, pos) } + ParameterPosition getReturnKindParamPosition(ReturnKind kind) { + kind.(OutRefReturnKind).getPosition() = result.getPosition() + } + Callable returnNodeEnclosingCallable(DataFlow::Node ret) { result = DataFlowImplCommon::getNodeEnclosingCallable(ret).asCallable(_) } diff --git a/csharp/ql/test/utils/modelgenerator/dataflow/Summaries.cs b/csharp/ql/test/utils/modelgenerator/dataflow/Summaries.cs index 2d8bbc8912bc..7a6f16f383e5 100644 --- a/csharp/ql/test/utils/modelgenerator/dataflow/Summaries.cs +++ b/csharp/ql/test/utils/modelgenerator/dataflow/Summaries.cs @@ -1034,3 +1034,40 @@ public override object GetValue() } } } + +public class ParameterModifiers +{ + // contentbased-summary=Models;ParameterModifiers;false;Copy;(System.Object,System.Object);;Argument[0];Argument[1];value;dfc-generated + // summary=Models;ParameterModifiers;false;Copy;(System.Object,System.Object);;Argument[0];Argument[1];taint;df-generated + public void Copy(object key, out object value) + { + value = key; + } + + // contentbased-summary=Models;ParameterModifiers;false;CopyToRef;(System.Object,System.Object);;Argument[0];Argument[1];value;dfc-generated + // summary=Models;ParameterModifiers;false;CopyToRef;(System.Object,System.Object);;Argument[0];Argument[1];taint;df-generated + public void CopyToRef(object key, ref object value) + { + value = key; + } + + // No summaries as we disregard flow from a parameter to itself. + // neutral=Models;ParameterModifiers;RefParamFlowToSelf;(System.Object,System.Boolean);summary;df-generated + public void RefParamFlowToSelf(ref object value, bool b) + { + value = b ? value : null; + } + + // neutral=Models;ParameterModifiers;RefParamUse;(System.Object);summary;df-generated + public void RefParamUse(ref object value) + { + var b = value is null; + } + + // contentbased-summary=Models;ParameterModifiers;false;InReturn;(System.Object);;Argument[0];ReturnValue;value;dfc-generated + // summary=Models;ParameterModifiers;false;InReturn;(System.Object);;Argument[0];ReturnValue;taint;df-generated + public object InReturn(in object v) + { + return v; + } +} diff --git a/shared/mad/codeql/mad/modelgenerator/internal/ModelGeneratorImpl.qll b/shared/mad/codeql/mad/modelgenerator/internal/ModelGeneratorImpl.qll index 64b5b0c3b1f9..0678d07e7f47 100644 --- a/shared/mad/codeql/mad/modelgenerator/internal/ModelGeneratorImpl.qll +++ b/shared/mad/codeql/mad/modelgenerator/internal/ModelGeneratorImpl.qll @@ -221,6 +221,11 @@ signature module ModelGeneratorInputSig */ string printContent(Lang::ContentSet c); + /** + * Gets the parameter position of the return kind, if any. + */ + default Lang::ParameterPosition getReturnKindParamPosition(Lang::ReturnKind node) { none() } + /** * Holds if it is irrelevant to generate models for `api` based on data flow analysis. * @@ -301,6 +306,14 @@ module MakeModelGenerator< * Gets the kind of the return node. */ DataFlow::ReturnKindExt getKind() { result = kind } + + /** + * Gets the parameter position of the return node, if any. + */ + DataFlow::ParameterPosition getPosition() { + result = this.getKind().(DataFlow::ParamUpdateReturnKind).getPosition() or + result = getReturnKindParamPosition(this.getKind().(DataFlow::ValueReturnKind).getKind()) + } } bindingset[c] @@ -309,10 +322,11 @@ module MakeModelGenerator< private module PrintReturnNodeExt { string getOutput(ReturnNodeExt node) { node.getKind() instanceof DataFlow::ValueReturnKind and + not exists(node.getPosition()) and result = "ReturnValue" or exists(DataFlow::ParameterPosition pos | - pos = node.getKind().(DataFlow::ParamUpdateReturnKind).getPosition() and + pos = node.getPosition() and result = printCallableParam(returnNodeEnclosingCallable(node), pos) ) }