Skip to content

Commit f8b094a

Browse files
committed
C#: Only use generated flow summaries in case no handwritten summary exists.
1 parent 4d953da commit f8b094a

File tree

2 files changed

+29
-17
lines changed

2 files changed

+29
-17
lines changed

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

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -806,10 +806,10 @@ module Private {
806806
module External {
807807
/** Holds if `spec` is a relevant external specification. */
808808
private predicate relevantSpec(string spec) {
809-
summaryElement(_, spec, _, _) or
810-
summaryElement(_, _, spec, _) or
811-
sourceElement(_, spec, _) or
812-
sinkElement(_, spec, _)
809+
summaryElement(_, spec, _, _, _) or
810+
summaryElement(_, _, spec, _, _) or
811+
sourceElement(_, spec, _, _) or
812+
sinkElement(_, spec, _, _)
813813
}
814814

815815
private class AccessPathRange extends AccessPath::Range {
@@ -875,13 +875,20 @@ module Private {
875875
}
876876

877877
private class SummarizedCallableExternal extends SummarizedCallable {
878-
SummarizedCallableExternal() { summaryElement(this, _, _, _) }
878+
SummarizedCallableExternal() { summaryElement(this, _, _, _, _) }
879+
880+
private predicate relevantSummaryElement(AccessPath inSpec, AccessPath outSpec, string kind) {
881+
summaryElement(this, inSpec, outSpec, kind, false)
882+
or
883+
summaryElement(this, inSpec, outSpec, kind, true) and
884+
not summaryElement(this, inSpec, outSpec, kind, false)
885+
}
879886

880887
override predicate propagatesFlow(
881888
SummaryComponentStack input, SummaryComponentStack output, boolean preservesValue
882889
) {
883890
exists(AccessPath inSpec, AccessPath outSpec, string kind |
884-
summaryElement(this, inSpec, outSpec, kind) and
891+
this.relevantSummaryElement(inSpec, outSpec, kind) and
885892
interpretSpec(inSpec, input) and
886893
interpretSpec(outSpec, output)
887894
|
@@ -910,7 +917,7 @@ module Private {
910917

911918
private predicate sourceElementRef(InterpretNode ref, AccessPath output, string kind) {
912919
exists(SourceOrSinkElement e |
913-
sourceElement(e, output, kind) and
920+
sourceElement(e, output, kind, _) and
914921
if outputNeedsReference(output.getToken(0))
915922
then e = ref.getCallTarget()
916923
else e = ref.asElement()
@@ -919,7 +926,7 @@ module Private {
919926

920927
private predicate sinkElementRef(InterpretNode ref, AccessPath input, string kind) {
921928
exists(SourceOrSinkElement e |
922-
sinkElement(e, input, kind) and
929+
sinkElement(e, input, kind, _) and
923930
if inputNeedsReference(input.getToken(0))
924931
then e = ref.getCallTarget()
925932
else e = ref.asElement()

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

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -85,39 +85,44 @@ DataFlowType getCallbackReturnType(DataFlowType t, ReturnKind rk) {
8585

8686
/**
8787
* Holds if an external flow summary exists for `c` with input specification
88-
* `input`, output specification `output`, and kind `kind`.
88+
* `input`, output specification `output`, kind `kind`, and a flag `generated`
89+
* stating whether the summary is autogenerated or not.
8990
*/
90-
predicate summaryElement(DataFlowCallable c, string input, string output, string kind) {
91+
predicate summaryElement(
92+
DataFlowCallable c, string input, string output, string kind, boolean generated
93+
) {
9194
exists(
9295
string namespace, string type, boolean subtypes, string name, string signature, string ext
9396
|
94-
summaryModel(namespace, type, subtypes, name, signature, ext, input, output, kind, _) and
97+
summaryModel(namespace, type, subtypes, name, signature, ext, input, output, kind, generated) and
9598
c = interpretElement(namespace, type, subtypes, name, signature, ext)
9699
)
97100
}
98101

99102
/**
100103
* Holds if an external source specification exists for `e` with output specification
101-
* `output` and kind `kind`.
104+
* `output`, kind `kind`, and a flag `generated` stating whether the summary is
105+
* autogenerated or not.
102106
*/
103-
predicate sourceElement(Element e, string output, string kind) {
107+
predicate sourceElement(Element e, string output, string kind, boolean generated) {
104108
exists(
105109
string namespace, string type, boolean subtypes, string name, string signature, string ext
106110
|
107-
sourceModel(namespace, type, subtypes, name, signature, ext, output, kind, _) and
111+
sourceModel(namespace, type, subtypes, name, signature, ext, output, kind, generated) and
108112
e = interpretElement(namespace, type, subtypes, name, signature, ext)
109113
)
110114
}
111115

112116
/**
113117
* Holds if an external sink specification exists for `n` with input specification
114-
* `input` and kind `kind`.
118+
* `input`, kind `kind` and a flag `generated` stating whether the summary is
119+
* autogenerated or not..
115120
*/
116-
predicate sinkElement(Element e, string input, string kind) {
121+
predicate sinkElement(Element e, string input, string kind, boolean generated) {
117122
exists(
118123
string namespace, string type, boolean subtypes, string name, string signature, string ext
119124
|
120-
sinkModel(namespace, type, subtypes, name, signature, ext, input, kind, _) and
125+
sinkModel(namespace, type, subtypes, name, signature, ext, input, kind, generated) and
121126
e = interpretElement(namespace, type, subtypes, name, signature, ext)
122127
)
123128
}

0 commit comments

Comments
 (0)