Skip to content

Commit 0a0ec18

Browse files
authoredMar 27, 2025··
Merge pull request #19114 from michaelnebel/csharp/modelgenparammodifiers
C#: Correct printing of returns via out/ref parameters in model generation.
2 parents 3fbfc41 + 8bda7ce commit 0a0ec18

File tree

3 files changed

+56
-1
lines changed

3 files changed

+56
-1
lines changed
 

‎csharp/ql/src/utils/modelgenerator/internal/CaptureModels.qll

+4
Original file line numberDiff line numberDiff line change
@@ -233,6 +233,10 @@ module ModelGeneratorInput implements ModelGeneratorInputSig<Location, CsharpDat
233233
result = ParamReturnNodeAsOutput<parameterContentAccess/1>::paramReturnNodeAsOutput(c, pos)
234234
}
235235

236+
ParameterPosition getReturnKindParamPosition(ReturnKind kind) {
237+
kind.(OutRefReturnKind).getPosition() = result.getPosition()
238+
}
239+
236240
Callable returnNodeEnclosingCallable(DataFlow::Node ret) {
237241
result = DataFlowImplCommon::getNodeEnclosingCallable(ret).asCallable(_)
238242
}

‎csharp/ql/test/utils/modelgenerator/dataflow/Summaries.cs

+37
Original file line numberDiff line numberDiff line change
@@ -1034,3 +1034,40 @@ public override object GetValue()
10341034
}
10351035
}
10361036
}
1037+
1038+
public class ParameterModifiers
1039+
{
1040+
// contentbased-summary=Models;ParameterModifiers;false;Copy;(System.Object,System.Object);;Argument[0];Argument[1];value;dfc-generated
1041+
// summary=Models;ParameterModifiers;false;Copy;(System.Object,System.Object);;Argument[0];Argument[1];taint;df-generated
1042+
public void Copy(object key, out object value)
1043+
{
1044+
value = key;
1045+
}
1046+
1047+
// contentbased-summary=Models;ParameterModifiers;false;CopyToRef;(System.Object,System.Object);;Argument[0];Argument[1];value;dfc-generated
1048+
// summary=Models;ParameterModifiers;false;CopyToRef;(System.Object,System.Object);;Argument[0];Argument[1];taint;df-generated
1049+
public void CopyToRef(object key, ref object value)
1050+
{
1051+
value = key;
1052+
}
1053+
1054+
// No summaries as we disregard flow from a parameter to itself.
1055+
// neutral=Models;ParameterModifiers;RefParamFlowToSelf;(System.Object,System.Boolean);summary;df-generated
1056+
public void RefParamFlowToSelf(ref object value, bool b)
1057+
{
1058+
value = b ? value : null;
1059+
}
1060+
1061+
// neutral=Models;ParameterModifiers;RefParamUse;(System.Object);summary;df-generated
1062+
public void RefParamUse(ref object value)
1063+
{
1064+
var b = value is null;
1065+
}
1066+
1067+
// contentbased-summary=Models;ParameterModifiers;false;InReturn;(System.Object);;Argument[0];ReturnValue;value;dfc-generated
1068+
// summary=Models;ParameterModifiers;false;InReturn;(System.Object);;Argument[0];ReturnValue;taint;df-generated
1069+
public object InReturn(in object v)
1070+
{
1071+
return v;
1072+
}
1073+
}

‎shared/mad/codeql/mad/modelgenerator/internal/ModelGeneratorImpl.qll

+15-1
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,11 @@ signature module ModelGeneratorInputSig<LocationSig Location, InputSig<Location>
221221
*/
222222
string printContent(Lang::ContentSet c);
223223

224+
/**
225+
* Gets the parameter position of the return kind, if any.
226+
*/
227+
default Lang::ParameterPosition getReturnKindParamPosition(Lang::ReturnKind node) { none() }
228+
224229
/**
225230
* Holds if it is irrelevant to generate models for `api` based on data flow analysis.
226231
*
@@ -301,6 +306,14 @@ module MakeModelGenerator<
301306
* Gets the kind of the return node.
302307
*/
303308
DataFlow::ReturnKindExt getKind() { result = kind }
309+
310+
/**
311+
* Gets the parameter position of the return node, if any.
312+
*/
313+
DataFlow::ParameterPosition getPosition() {
314+
result = this.getKind().(DataFlow::ParamUpdateReturnKind).getPosition() or
315+
result = getReturnKindParamPosition(this.getKind().(DataFlow::ValueReturnKind).getKind())
316+
}
304317
}
305318

306319
bindingset[c]
@@ -309,10 +322,11 @@ module MakeModelGenerator<
309322
private module PrintReturnNodeExt<printCallableParamSig/2 printCallableParam> {
310323
string getOutput(ReturnNodeExt node) {
311324
node.getKind() instanceof DataFlow::ValueReturnKind and
325+
not exists(node.getPosition()) and
312326
result = "ReturnValue"
313327
or
314328
exists(DataFlow::ParameterPosition pos |
315-
pos = node.getKind().(DataFlow::ParamUpdateReturnKind).getPosition() and
329+
pos = node.getPosition() and
316330
result = printCallableParam(returnNodeEnclosingCallable(node), pos)
317331
)
318332
}

0 commit comments

Comments
 (0)