Skip to content

Commit 6f4311d

Browse files
committed
C#: Include type parameters when printing MaD rows with generics
1 parent 4ae35d1 commit 6f4311d

File tree

13 files changed

+12117
-12109
lines changed

13 files changed

+12117
-12109
lines changed

csharp/ql/lib/semmle/code/csharp/commons/QualifiedName.qll

Lines changed: 20 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -160,30 +160,30 @@ module QualifiedName<QualifiedNameInputSig Input> {
160160
}
161161

162162
/**
163-
* Holds if member `m` has name `name` and is defined in type `type`
163+
* Holds if declaration `d` has name `name` and is defined in type `type`
164164
* with namespace `namespace`.
165165
*/
166-
predicate hasQualifiedName(Member m, string namespace, string type, string name) {
167-
m =
168-
any(ConstructedMethod cm |
169-
hasQualifiedName(cm.getDeclaringType(), namespace, type) and
170-
name = cm.getUndecoratedName() + "<" + getTypeArgumentsQualifiedNames(cm) + ">"
171-
)
172-
or
173-
m =
174-
any(UnboundGenericMethod ugm |
175-
hasQualifiedName(ugm.getDeclaringType(), namespace, type) and
176-
name = ugm.getUndecoratedName() + Input::getUnboundGenericSuffix(ugm)
177-
)
178-
or
179-
not m instanceof ConstructedMethod and
180-
not m instanceof UnboundGenericMethod and
181-
hasQualifiedName(m.getDeclaringType(), namespace, type) and
166+
predicate hasQualifiedName(Declaration d, string namespace, string type, string name) {
167+
hasQualifiedName(d.getDeclaringType(), namespace, type) and
182168
(
183-
name = m.(Operator).getFunctionName()
169+
d =
170+
any(ConstructedMethod cm |
171+
name = cm.getUndecoratedName() + "<" + getTypeArgumentsQualifiedNames(cm) + ">"
172+
)
184173
or
185-
not m instanceof Operator and
186-
name = m.getName()
174+
d =
175+
any(UnboundGenericMethod ugm |
176+
name = ugm.getUndecoratedName() + Input::getUnboundGenericSuffix(ugm)
177+
)
178+
or
179+
not d instanceof ConstructedMethod and
180+
not d instanceof UnboundGenericMethod and
181+
(
182+
name = d.(Operator).getFunctionName()
183+
or
184+
not d instanceof Operator and
185+
name = d.getName()
186+
)
187187
)
188188
}
189189
}

csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowPrivate.qll

Lines changed: 0 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -2488,68 +2488,3 @@ abstract class SyntheticField extends string {
24882488
* Holds if the the content `c` is a container.
24892489
*/
24902490
predicate containerContent(DataFlow::Content c) { c instanceof DataFlow::ElementContent }
2491-
2492-
/** Gets the string representation of the parameters of `c`. */
2493-
string parameterQualifiedTypeNamesToString(DotNet::Callable c) {
2494-
result =
2495-
concat(Parameter p, int i |
2496-
p = c.getParameter(i)
2497-
|
2498-
p.getType().getQualifiedName(), "," order by i
2499-
)
2500-
}
2501-
2502-
/**
2503-
* A module containing predicates related to generating MaD models.
2504-
*/
2505-
module Csv {
2506-
/** Holds if the summary should apply for all overrides of `c`. */
2507-
predicate isBaseCallableOrPrototype(DotNet::Callable c) {
2508-
c.getDeclaringType() instanceof Interface
2509-
or
2510-
exists(Modifiable m | m = [c.(Modifiable), c.(Accessor).getDeclaration()] |
2511-
m.isAbstract()
2512-
or
2513-
c.getDeclaringType().(Modifiable).isAbstract() and m.(Virtualizable).isVirtual()
2514-
)
2515-
}
2516-
2517-
/** Gets a string representing whether the summary should apply for all overrides of `c`. */
2518-
private string getCallableOverride(DotNet::Callable c) {
2519-
if isBaseCallableOrPrototype(c) then result = "true" else result = "false"
2520-
}
2521-
2522-
private predicate partialModel(
2523-
DotNet::Callable c, string namespace, string type, string name, string parameters
2524-
) {
2525-
c.getDeclaringType().hasQualifiedName(namespace, type) and
2526-
c.hasQualifiedName(_, name) and
2527-
parameters = "(" + parameterQualifiedTypeNamesToString(c) + ")"
2528-
}
2529-
2530-
/** Computes the first 6 columns for positive CSV rows of `c`. */
2531-
string asPartialModel(DotNet::Callable c) {
2532-
exists(string namespace, string type, string name, string parameters |
2533-
partialModel(c, namespace, type, name, parameters) and
2534-
result =
2535-
namespace + ";" //
2536-
+ type + ";" //
2537-
+ getCallableOverride(c) + ";" //
2538-
+ name + ";" //
2539-
+ parameters + ";" //
2540-
+ /* ext + */ ";" //
2541-
)
2542-
}
2543-
2544-
/** Computes the first 4 columns for neutral CSV rows of `c`. */
2545-
string asPartialNeutralModel(DotNet::Callable c) {
2546-
exists(string namespace, string type, string name, string parameters |
2547-
partialModel(c, namespace, type, name, parameters) and
2548-
result =
2549-
namespace + ";" //
2550-
+ type + ";" //
2551-
+ name + ";" //
2552-
+ parameters + ";" //
2553-
)
2554-
}
2555-
}

csharp/ql/lib/semmle/code/csharp/dataflow/internal/ExternalFlow.qll

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,7 @@ private import DataFlowPublic
9595
private import FlowSummaryImpl::Public
9696
private import FlowSummaryImpl::Private::External
9797
private import FlowSummaryImplSpecific
98+
private import semmle.code.csharp.commons.QualifiedName
9899
private import codeql.mad.ModelValidation as SharedModelVal
99100

100101
private predicate relevantNamespace(string namespace) {
@@ -449,3 +450,76 @@ private module Cached {
449450
}
450451

451452
import Cached
453+
454+
/** Holds if the summary should apply for all overrides of `c`. */
455+
predicate isBaseCallableOrPrototype(UnboundCallable c) {
456+
c.getDeclaringType() instanceof Interface
457+
or
458+
exists(Modifiable m | m = [c.(Modifiable), c.(Accessor).getDeclaration()] |
459+
m.isAbstract()
460+
or
461+
c.getDeclaringType().(Modifiable).isAbstract() and m.(Virtualizable).isVirtual()
462+
)
463+
}
464+
465+
/** Gets a string representing whether the summary should apply for all overrides of `c`. */
466+
private string getCallableOverride(UnboundCallable c) {
467+
if isBaseCallableOrPrototype(c) then result = "true" else result = "false"
468+
}
469+
470+
private module QualifiedNameInput implements QualifiedNameInputSig {
471+
string getUnboundGenericSuffix(UnboundGeneric ug) {
472+
result =
473+
"<" + strictconcat(int i, string s | s = ug.getTypeParameter(i).getName() | s, "," order by i)
474+
+ ">"
475+
}
476+
}
477+
478+
private module QN = QualifiedName<QualifiedNameInput>;
479+
480+
pragma[nomagic]
481+
private string parameterQualifiedType(Parameter p) {
482+
exists(string qualifier, string name |
483+
QN::hasQualifiedName(p.getType(), qualifier, name) and
484+
result = getQualifiedName(qualifier, name)
485+
)
486+
}
487+
488+
/** Gets the string representation of the parameters of `c`. */
489+
string parameterQualifiedTypeNamesToString(Callable c) {
490+
result =
491+
concat(int i, string s | s = parameterQualifiedType(c.getParameter(i)) | s, "," order by i)
492+
}
493+
494+
private predicate partialModel(
495+
UnboundCallable c, string namespace, string type, string name, string parameters
496+
) {
497+
QN::hasQualifiedName(c, namespace, type, name) and
498+
parameters = "(" + parameterQualifiedTypeNamesToString(c) + ")"
499+
}
500+
501+
/** Computes the first 6 columns for positive CSV rows of `c`. */
502+
string asPartialModel(UnboundCallable c) {
503+
exists(string namespace, string type, string name, string parameters |
504+
partialModel(c, namespace, type, name, parameters) and
505+
result =
506+
namespace + ";" //
507+
+ type + ";" //
508+
+ getCallableOverride(c) + ";" //
509+
+ name + ";" //
510+
+ parameters + ";" //
511+
+ /* ext + */ ";" //
512+
)
513+
}
514+
515+
/** Computes the first 4 columns for neutral CSV rows of `c`. */
516+
string asPartialNeutralModel(UnboundCallable c) {
517+
exists(string namespace, string type, string name, string parameters |
518+
partialModel(c, namespace, type, name, parameters) and
519+
result =
520+
namespace + ";" //
521+
+ type + ";" //
522+
+ name + ";" //
523+
+ parameters + ";" //
524+
)
525+
}

csharp/ql/src/utils/modeleditor/ModelEditor.qll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@
22

33
private import csharp
44
private import semmle.code.csharp.dataflow.FlowSummary
5-
private import semmle.code.csharp.dataflow.internal.DataFlowPrivate
65
private import semmle.code.csharp.dataflow.internal.FlowSummaryImpl as FlowSummaryImpl
6+
private import semmle.code.csharp.dataflow.internal.ExternalFlow
77
private import semmle.code.csharp.frameworks.Test
88
private import Telemetry.TestLibrary
99

csharp/ql/src/utils/modelgenerator/internal/CaptureModelsSpecific.qll

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -65,9 +65,9 @@ class TargetApiSpecific extends DotNet::Callable {
6565
}
6666
}
6767

68-
predicate asPartialModel = DataFlowPrivate::Csv::asPartialModel/1;
68+
predicate asPartialModel = ExternalFlow::asPartialModel/1;
6969

70-
predicate asPartialNeutralModel = DataFlowPrivate::Csv::asPartialNeutralModel/1;
70+
predicate asPartialNeutralModel = ExternalFlow::asPartialNeutralModel/1;
7171

7272
/**
7373
* Holds if `t` is a type that is generally used for bulk data in collection types.

0 commit comments

Comments
 (0)