C#: Only use generated flow summaries in case no handwritten summary exists.

This commit is contained in:
Michael Nebel
2022-03-31 14:28:33 +02:00
parent 4d953da480
commit f8b094ac1f
2 changed files with 29 additions and 17 deletions

View File

@@ -806,10 +806,10 @@ module Private {
module External {
/** Holds if `spec` is a relevant external specification. */
private predicate relevantSpec(string spec) {
summaryElement(_, spec, _, _) or
summaryElement(_, _, spec, _) or
sourceElement(_, spec, _) or
sinkElement(_, spec, _)
summaryElement(_, spec, _, _, _) or
summaryElement(_, _, spec, _, _) or
sourceElement(_, spec, _, _) or
sinkElement(_, spec, _, _)
}
private class AccessPathRange extends AccessPath::Range {
@@ -875,13 +875,20 @@ module Private {
}
private class SummarizedCallableExternal extends SummarizedCallable {
SummarizedCallableExternal() { summaryElement(this, _, _, _) }
SummarizedCallableExternal() { summaryElement(this, _, _, _, _) }
private predicate relevantSummaryElement(AccessPath inSpec, AccessPath outSpec, string kind) {
summaryElement(this, inSpec, outSpec, kind, false)
or
summaryElement(this, inSpec, outSpec, kind, true) and
not summaryElement(this, inSpec, outSpec, kind, false)
}
override predicate propagatesFlow(
SummaryComponentStack input, SummaryComponentStack output, boolean preservesValue
) {
exists(AccessPath inSpec, AccessPath outSpec, string kind |
summaryElement(this, inSpec, outSpec, kind) and
this.relevantSummaryElement(inSpec, outSpec, kind) and
interpretSpec(inSpec, input) and
interpretSpec(outSpec, output)
|
@@ -910,7 +917,7 @@ module Private {
private predicate sourceElementRef(InterpretNode ref, AccessPath output, string kind) {
exists(SourceOrSinkElement e |
sourceElement(e, output, kind) and
sourceElement(e, output, kind, _) and
if outputNeedsReference(output.getToken(0))
then e = ref.getCallTarget()
else e = ref.asElement()
@@ -919,7 +926,7 @@ module Private {
private predicate sinkElementRef(InterpretNode ref, AccessPath input, string kind) {
exists(SourceOrSinkElement e |
sinkElement(e, input, kind) and
sinkElement(e, input, kind, _) and
if inputNeedsReference(input.getToken(0))
then e = ref.getCallTarget()
else e = ref.asElement()

View File

@@ -85,39 +85,44 @@ DataFlowType getCallbackReturnType(DataFlowType t, ReturnKind rk) {
/**
* Holds if an external flow summary exists for `c` with input specification
* `input`, output specification `output`, and kind `kind`.
* `input`, output specification `output`, kind `kind`, and a flag `generated`
* stating whether the summary is autogenerated or not.
*/
predicate summaryElement(DataFlowCallable c, string input, string output, string kind) {
predicate summaryElement(
DataFlowCallable c, string input, string output, string kind, boolean generated
) {
exists(
string namespace, string type, boolean subtypes, string name, string signature, string ext
|
summaryModel(namespace, type, subtypes, name, signature, ext, input, output, kind, _) and
summaryModel(namespace, type, subtypes, name, signature, ext, input, output, kind, generated) and
c = interpretElement(namespace, type, subtypes, name, signature, ext)
)
}
/**
* Holds if an external source specification exists for `e` with output specification
* `output` and kind `kind`.
* `output`, kind `kind`, and a flag `generated` stating whether the summary is
* autogenerated or not.
*/
predicate sourceElement(Element e, string output, string kind) {
predicate sourceElement(Element e, string output, string kind, boolean generated) {
exists(
string namespace, string type, boolean subtypes, string name, string signature, string ext
|
sourceModel(namespace, type, subtypes, name, signature, ext, output, kind, _) and
sourceModel(namespace, type, subtypes, name, signature, ext, output, kind, generated) and
e = interpretElement(namespace, type, subtypes, name, signature, ext)
)
}
/**
* Holds if an external sink specification exists for `n` with input specification
* `input` and kind `kind`.
* `input`, kind `kind` and a flag `generated` stating whether the summary is
* autogenerated or not..
*/
predicate sinkElement(Element e, string input, string kind) {
predicate sinkElement(Element e, string input, string kind, boolean generated) {
exists(
string namespace, string type, boolean subtypes, string name, string signature, string ext
|
sinkModel(namespace, type, subtypes, name, signature, ext, input, kind, _) and
sinkModel(namespace, type, subtypes, name, signature, ext, input, kind, generated) and
e = interpretElement(namespace, type, subtypes, name, signature, ext)
)
}