Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 13 additions & 31 deletions cpp/ql/lib/semmle/code/cpp/dataflow/ExternalFlow.qll
Original file line number Diff line number Diff line change
Expand Up @@ -1058,40 +1058,22 @@ private predicate interpretSummary(

// adapter class for converting Mad summaries to `SummarizedCallable`s
private class SummarizedCallableAdapter extends SummarizedCallable {
SummarizedCallableAdapter() { interpretSummary(this, _, _, _, _, _) }
string input_;
string output_;
string kind;
Provenance p_;
string model_;

private predicate relevantSummaryElementManual(
string input, string output, string kind, string model
) {
exists(Provenance provenance |
interpretSummary(this, input, output, kind, provenance, model) and
provenance.isManual()
)
}

private predicate relevantSummaryElementGenerated(
string input, string output, string kind, string model
) {
exists(Provenance provenance |
interpretSummary(this, input, output, kind, provenance, model) and
provenance.isGenerated()
)
}
SummarizedCallableAdapter() { interpretSummary(this, input_, output_, kind, p_, model_) }

override predicate propagatesFlow(
string input, string output, boolean preservesValue, string model
string input, string output, boolean preservesValue, Provenance p, boolean isExact, string model
) {
exists(string kind |
this.relevantSummaryElementManual(input, output, kind, model)
or
not this.relevantSummaryElementManual(_, _, _, _) and
this.relevantSummaryElementGenerated(input, output, kind, model)
|
if kind = "value" then preservesValue = true else preservesValue = false
)
}

override predicate hasProvenance(Provenance provenance) {
interpretSummary(this, _, _, _, provenance, _)
input = input_ and
output = output_ and
(if kind = "value" then preservesValue = true else preservesValue = false) and
p = p_ and
isExact = true and
model = model_
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -1144,7 +1144,7 @@ private newtype TDataFlowCall =
}

private predicate summarizedCallableIsManual(SummarizedCallable sc) {
sc.asSummarizedCallable().applyManualModel()
sc.asSummarizedCallable().hasManualModel()
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -310,7 +310,7 @@ private module SummaryModelGeneratorInput implements SummaryModelGeneratorInputS
}

private predicate hasManualSummaryModel(Callable api) {
api = any(FlowSummaryImpl::Public::SummarizedCallable sc | sc.applyManualModel()) or
api = any(FlowSummaryImpl::Public::SummarizedCallable sc | sc.hasManualModel()) or
api = any(FlowSummaryImpl::Public::NeutralSummaryCallable sc | sc.hasManualModel())
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -371,24 +371,9 @@ class NonDelegateDataFlowCall extends DataFlowCall, TNonDelegateCall {
/** Gets the underlying call. */
DispatchCall getDispatchCall() { result = dc }

pragma[nomagic]
private predicate hasSourceTarget() { dc.getAStaticTarget().fromSource() }

pragma[nomagic]
private FlowSummary::SummarizedCallable getASummarizedCallableTarget() {
// Only use summarized callables with generated summaries in case
// we are not able to dispatch to a source declaration.
exists(boolean static |
result = this.getATarget(static) and
not (
result.applyGeneratedModel() and
this.hasSourceTarget()
)
|
static = false
or
static = true and not result instanceof RuntimeCallable
)
result = this.getATarget(_)
}

pragma[nomagic]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -848,7 +848,7 @@ private predicate fieldOrPropertyStore(Expr e, ContentSet c, Expr src, Expr q, b
FlowSummaryImpl::Private::SummarizedCallableImpl sc,
FlowSummaryImpl::Private::SummaryComponentStack input, ContentSet readSet
|
sc.propagatesFlow(input, _, _, _) and
sc.propagatesFlow(input, _, _, _, _, _) and
input.contains(FlowSummaryImpl::Private::SummaryComponent::content(readSet)) and
c.getAStoreContent() = readSet.getAReadContent()
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -349,20 +349,23 @@ private Declaration interpretExt(Declaration d, ExtPath ext) {
/** Gets the source/sink/summary/neutral element corresponding to the supplied parameters. */
pragma[nomagic]
Declaration interpretElement(
string namespace, string type, boolean subtypes, string name, string signature, string ext
string namespace, string type, boolean subtypes, string name, string signature, string ext,
boolean isExact
) {
elementSpec(namespace, type, subtypes, name, signature, ext) and
exists(Declaration base, Declaration d |
base = interpretBaseDeclaration(namespace, type, name, signature) and
(
d = base
d = base and
isExact = true
or
subtypes = true and
(
d.(UnboundCallable).overridesOrImplementsUnbound(base)
or
d = base.(UnboundValueOrRefType).getASubTypeUnbound+()
)
) and
isExact = false
)
|
result = interpretExt(d, ext)
Expand Down Expand Up @@ -500,71 +503,47 @@ string getSignature(UnboundCallable c) {
}

private predicate interpretSummary(
UnboundCallable c, string input, string output, string kind, string provenance, string model
UnboundCallable c, string input, string output, string kind, string provenance, boolean isExact,
string model
) {
exists(
string namespace, string type, boolean subtypes, string name, string signature, string ext
|
summaryModel(namespace, type, subtypes, name, signature, ext, input, output, kind, provenance,
model) and
c = interpretElement(namespace, type, subtypes, name, signature, ext)
c = interpretElement(namespace, type, subtypes, name, signature, ext, isExact)
)
}

predicate interpretNeutral(UnboundCallable c, string kind, string provenance) {
predicate interpretNeutral(UnboundCallable c, string kind, string provenance, boolean isExact) {
exists(string namespace, string type, string name, string signature |
Extensions::neutralModel(namespace, type, name, signature, kind, provenance) and
c = interpretElement(namespace, type, true, name, signature, "")
c = interpretElement(namespace, type, true, name, signature, "", isExact)
)
}

// adapter class for converting Mad summaries to `SummarizedCallable`s
private class SummarizedCallableAdapter extends SummarizedCallable {
SummarizedCallableAdapter() {
exists(Provenance provenance | interpretSummary(this, _, _, _, provenance, _) |
not this.fromSource()
or
this.fromSource() and provenance.isManual()
)
}

private predicate relevantSummaryElementManual(
string input, string output, string kind, string model
) {
exists(Provenance provenance |
interpretSummary(this, input, output, kind, provenance, model) and
provenance.isManual()
)
}
string input_;
string output_;
string kind;
Provenance p_;
boolean isExact_;
string model_;

private predicate relevantSummaryElementGenerated(
string input, string output, string kind, string model
) {
exists(Provenance provenance |
interpretSummary(this, input, output, kind, provenance, model) and
provenance.isGenerated()
) and
not exists(Provenance provenance |
interpretNeutral(this, "summary", provenance) and
provenance.isManual()
)
SummarizedCallableAdapter() {
interpretSummary(this, input_, output_, kind, p_, isExact_, model_)
}

override predicate propagatesFlow(
string input, string output, boolean preservesValue, string model
string input, string output, boolean preservesValue, Provenance p, boolean isExact, string model
) {
exists(string kind |
this.relevantSummaryElementManual(input, output, kind, model)
or
not this.relevantSummaryElementManual(_, _, _, _) and
this.relevantSummaryElementGenerated(input, output, kind, model)
|
if kind = "value" then preservesValue = true else preservesValue = false
)
}

override predicate hasProvenance(Provenance provenance) {
interpretSummary(this, _, _, _, provenance, _)
input = input_ and
output = output_ and
(if kind = "value" then preservesValue = true else preservesValue = false) and
p = p_ and
isExact = isExact_ and
model = model_
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,14 @@ module Input implements InputSig<Location, DataFlowImplSpecific::CsharpDataFlow>

class SummarizedCallableBase = UnboundCallable;

predicate allowGeneratedSummary(SummarizedCallableBase c) { not c.fromSource() }

class SourceBase = Void;

class SinkBase = Void;

predicate neutralElement(SummarizedCallableBase c, string kind, string provenance, boolean isExact) {
interpretNeutral(c, kind, provenance) and
interpretNeutral(c, kind, provenance, _) and
// isExact is not needed for C#.
isExact = false
}
Expand Down Expand Up @@ -216,7 +218,7 @@ module SourceSinkInterpretationInput implements
string namespace, string type, boolean subtypes, string name, string signature, string ext
|
sourceModel(namespace, type, subtypes, name, signature, ext, output, kind, provenance, model) and
e = interpretElement(namespace, type, subtypes, name, signature, ext)
e = interpretElement(namespace, type, subtypes, name, signature, ext, _)
)
}

Expand All @@ -227,7 +229,7 @@ module SourceSinkInterpretationInput implements
string namespace, string type, boolean subtypes, string name, string signature, string ext
|
sinkModel(namespace, type, subtypes, name, signature, ext, input, kind, provenance, model) and
e = interpretElement(namespace, type, subtypes, name, signature, ext)
e = interpretElement(namespace, type, subtypes, name, signature, ext, _)
)
}

Expand Down Expand Up @@ -437,13 +439,14 @@ private class SummarizedCallableWithCallback extends Public::SummarizedCallable
SummarizedCallableWithCallback() { mayInvokeCallback(this, pos) }

override predicate propagatesFlow(
string input, string output, boolean preservesValue, string model
string input, string output, boolean preservesValue, Public::Provenance provenance,
boolean isExact, string model
) {
input = "Argument[" + pos + "]" and
output = "Argument[" + pos + "].Parameter[delegate-self]" and
preservesValue = true and
provenance = "hq-generated" and
isExact = true and
model = "heuristic-callback"
}

override predicate hasProvenance(Public::Provenance provenance) { provenance = "hq-generated" }
}
31 changes: 17 additions & 14 deletions csharp/ql/lib/semmle/code/csharp/frameworks/EntityFramework.qll
Original file line number Diff line number Diff line change
Expand Up @@ -92,22 +92,17 @@ module EntityFramework {
abstract class EFSummarizedCallable extends SummarizedCallableImpl {
bindingset[this]
EFSummarizedCallable() { any() }

override predicate hasProvenance(Provenance provenance) { provenance = "manual" }
}

// see `SummarizedCallableImpl` qldoc
private class EFSummarizedCallableAdapter extends SummarizedCallable instanceof EFSummarizedCallable
{
override predicate propagatesFlow(
string input, string output, boolean preservesValue, string model
string input, string output, boolean preservesValue, Provenance provenance, boolean isExact,
string model
) {
none()
}

override predicate hasProvenance(Provenance provenance) {
EFSummarizedCallable.super.hasProvenance(provenance)
}
}

/** The class ``Microsoft.EntityFrameworkCore.DbQuery`1`` or ``System.Data.Entity.DbQuery`1``. */
Expand Down Expand Up @@ -177,11 +172,13 @@ module EntityFramework {

override predicate propagatesFlow(
SummaryComponentStack input, SummaryComponentStack output, boolean preservesValue,
string model
Provenance p, boolean isExact, string model
) {
input = SummaryComponentStack::argument(0) and
output = SummaryComponentStack::return() and
preservesValue = false and
p = "manual" and
isExact = true and
model = "RawSqlStringConstructorSummarizedCallable"
}
}
Expand All @@ -193,11 +190,13 @@ module EntityFramework {

override predicate propagatesFlow(
SummaryComponentStack input, SummaryComponentStack output, boolean preservesValue,
string model
Provenance p, boolean isExact, string model
) {
input = SummaryComponentStack::argument(0) and
output = SummaryComponentStack::return() and
preservesValue = false and
p = "manual" and
isExact = true and
model = "RawSqlStringConversionSummarizedCallable"
}
}
Expand Down Expand Up @@ -459,18 +458,20 @@ module EntityFramework {
}

private class DbContextClassSetPropertySynthetic extends EFSummarizedCallable {
private DbContextClassSetProperty p;
private DbContextClassSetProperty prop;

DbContextClassSetPropertySynthetic() { this = p.getGetter() }
DbContextClassSetPropertySynthetic() { this = prop.getGetter() }

override predicate propagatesFlow(
SummaryComponentStack input, SummaryComponentStack output, boolean preservesValue,
string model
Provenance p, boolean isExact, string model
) {
exists(string name, DbContextClass c |
preservesValue = true and
name = c.getSyntheticName(output, _, p) and
name = c.getSyntheticName(output, _, prop) and
input = SummaryComponentStack::syntheticGlobal(name) and
p = "manual" and
isExact = true and
model = "DbContextClassSetPropertySynthetic"
)
}
Expand All @@ -483,13 +484,15 @@ module EntityFramework {

override predicate propagatesFlow(
SummaryComponentStack input, SummaryComponentStack output, boolean preservesValue,
string model
Provenance p, boolean isExact, string model
) {
exists(string name, Property mapped |
preservesValue = true and
c.input(input, mapped) and
name = c.getSyntheticNameProj(mapped) and
output = SummaryComponentStack::syntheticGlobal(name) and
p = "manual" and
isExact = true and
model = "DbContextSaveChanges"
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -230,7 +230,7 @@ module SummaryModelGeneratorInput implements SummaryModelGeneratorInputSig {
}

private predicate hasManualSummaryModel(Callable api) {
api = any(FlowSummaryImpl::Public::SummarizedCallable sc | sc.applyManualModel()) or
api = any(FlowSummaryImpl::Public::SummarizedCallable sc | sc.hasManualModel()) or
api = any(FlowSummaryImpl::Public::NeutralSummaryCallable sc | sc.hasManualModel())
}

Expand Down
Loading
Loading