Data flow: Add aliases for removing DataFlow prefixes

This commit is contained in:
Tom Hvitved
2025-02-05 10:11:46 +01:00
parent bcec7ee234
commit 0f52fe92cf
5 changed files with 487 additions and 592 deletions

View File

@@ -4,19 +4,19 @@ import semmle.code.csharp.dataflow.internal.DataFlowDispatch
query predicate delegateCall(DelegateLikeCall dc, Callable c) { c = dc.getARuntimeTarget() } query predicate delegateCall(DelegateLikeCall dc, Callable c) { c = dc.getARuntimeTarget() }
private class LocatableDataFlowCallOption extends DataFlowCallOption { private class LocatableCallOption extends CallOption {
Location getLocation() { Location getLocation() {
this = TDataFlowCallNone() and this = TCallNone() and
result instanceof EmptyLocation result instanceof EmptyLocation
or or
exists(DataFlowCall call | exists(DataFlowCall call |
this = TDataFlowCallSome(call) and this = TCallSome(call) and
result = call.getLocation() result = call.getLocation()
) )
} }
} }
private class LocatableDataFlowCall extends TDataFlowCall { private class LocatableCall extends TDataFlowCall {
string toString() { result = this.(DataFlowCall).toString() } string toString() { result = this.(DataFlowCall).toString() }
Location getLocation() { Location getLocation() {
@@ -28,7 +28,7 @@ private class LocatableDataFlowCall extends TDataFlowCall {
} }
query predicate viableLambda( query predicate viableLambda(
LocatableDataFlowCall call, LocatableDataFlowCallOption lastCall, DataFlowCallable target LocatableCall call, LocatableCallOption lastCall, DataFlowCallable target
) { ) {
target = viableCallableLambda(call, lastCall) target = viableCallableLambda(call, lastCall)
} }

View File

@@ -4,13 +4,13 @@ import semmle.code.csharp.dataflow.internal.DataFlowDispatch
query predicate fptrCall(FunctionPointerCall dc, Callable c) { c = dc.getARuntimeTarget() } query predicate fptrCall(FunctionPointerCall dc, Callable c) { c = dc.getARuntimeTarget() }
private class LocatableDataFlowCallOption extends DataFlowCallOption { private class LocatableDataFlowCallOption extends CallOption {
Location getLocation() { Location getLocation() {
this = TDataFlowCallNone() and this = TCallNone() and
result instanceof EmptyLocation result instanceof EmptyLocation
or or
exists(DataFlowCall call | exists(DataFlowCall call |
this = TDataFlowCallSome(call) and this = TCallSome(call) and
result = call.getLocation() result = call.getLocation()
) )
} }

View File

@@ -17,6 +17,7 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
private import MakeImplStage1<Location, Lang> private import MakeImplStage1<Location, Lang>
private import DataFlowImplCommon::MakeImplCommon<Location, Lang> private import DataFlowImplCommon::MakeImplCommon<Location, Lang>
private import DataFlowImplCommonPublic private import DataFlowImplCommonPublic
private import Aliases
/** /**
* An input configuration for data flow using flow state. This signature equals * An input configuration for data flow using flow state. This signature equals
@@ -236,7 +237,7 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
} }
pragma[nomagic] pragma[nomagic]
private predicate allowsFieldFlowThrough(DataFlowCall call, DataFlowCallable c) { private predicate allowsFieldFlowThrough(Call call, Callable c) {
Stage1::callEdgeReturn(call, c, _, _, _, true) Stage1::callEdgeReturn(call, c, _, _, _, true)
} }
@@ -249,30 +250,25 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
predicate revFlow(Nd node, Ap ap); predicate revFlow(Nd node, Ap ap);
predicate callMayFlowThroughRev(DataFlowCall call); predicate callMayFlowThroughRev(Call call);
predicate parameterMayFlowThrough(ParamNd p, boolean emptyAp); predicate parameterMayFlowThrough(ParamNd p, boolean emptyAp);
predicate returnMayFlowThrough(RetNd ret, ReturnKindExt kind); predicate returnMayFlowThrough(RetNd ret, ReturnKindExt kind);
predicate storeStepCand( predicate storeStepCand(Nd node1, Content c, Nd node2, Type contentType, Type containerType);
Nd node1, Content c, Nd node2, DataFlowType contentType, DataFlowType containerType
);
predicate readStepCand(Nd n1, Content c, Nd n2); predicate readStepCand(Nd n1, Content c, Nd n2);
predicate callEdgeArgParam( predicate callEdgeArgParam(Call call, Callable c, ArgNd arg, ParamNd p, boolean emptyAp);
DataFlowCall call, DataFlowCallable c, ArgNd arg, ParamNd p, boolean emptyAp
);
predicate callEdgeReturn( predicate callEdgeReturn(
DataFlowCall call, DataFlowCallable c, RetNd ret, ReturnKindExt kind, Nd out, Call call, Callable c, RetNd ret, ReturnKindExt kind, Nd out, boolean allowsFieldFlow
boolean allowsFieldFlow
); );
predicate relevantCallEdgeIn(DataFlowCall call, DataFlowCallable c); predicate relevantCallEdgeIn(Call call, Callable c);
predicate relevantCallEdgeOut(DataFlowCall call, DataFlowCallable c); predicate relevantCallEdgeOut(Call call, Callable c);
} }
private module MkStage<StageSig PrevStage> { private module MkStage<StageSig PrevStage> {
@@ -292,7 +288,7 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
bindingset[result, ap] bindingset[result, ap]
ApApprox getApprox(Ap ap); ApApprox getApprox(Ap ap);
Typ getTyp(DataFlowType t); Typ getTyp(Type t);
bindingset[c, tail] bindingset[c, tail]
Ap apCons(Content c, Ap tail); Ap apCons(Content c, Ap tail);
@@ -321,7 +317,7 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
class CcCall extends Cc; class CcCall extends Cc;
// TODO: member predicate on CcCall // TODO: member predicate on CcCall
predicate matchesCall(CcCall cc, DataFlowCall call); predicate matchesCall(CcCall cc, Call call);
class CcNoCall extends Cc; class CcNoCall extends Cc;
@@ -343,20 +339,20 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
class LocalCc; class LocalCc;
DataFlowCallable viableImplCallContextReduced(DataFlowCall call, CcCall ctx); Callable viableImplCallContextReduced(Call call, CcCall ctx);
bindingset[call, ctx] bindingset[call, ctx]
predicate viableImplNotCallContextReduced(DataFlowCall call, Cc ctx); predicate viableImplNotCallContextReduced(Call call, Cc ctx);
bindingset[call, c] bindingset[call, c]
CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c); CcCall getCallContextCall(Call call, Callable c);
DataFlowCall viableImplCallContextReducedReverse(DataFlowCallable c, CcNoCall ctx); Call viableImplCallContextReducedReverse(Callable c, CcNoCall ctx);
predicate viableImplNotCallContextReducedReverse(CcNoCall ctx); predicate viableImplNotCallContextReducedReverse(CcNoCall ctx);
bindingset[call, c] bindingset[call, c]
CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call); CcNoCall getCallContextReturn(Callable c, Call call);
bindingset[cc] bindingset[cc]
LocalCc getLocalCc(Cc cc); LocalCc getLocalCc(Cc cc);
@@ -398,13 +394,11 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
/* Begin: Stage logic. */ /* Begin: Stage logic. */
pragma[nomagic] pragma[nomagic]
private Typ getNodeTyp(Nd node) { private Typ getNodeTyp(Nd node) {
PrevStage::revFlow(node) and result = getTyp(node.getDataFlowType()) PrevStage::revFlow(node) and result = getTyp(node.getType())
} }
pragma[nomagic] pragma[nomagic]
private predicate flowThroughOutOfCall( private predicate flowThroughOutOfCall(Call call, RetNd ret, Nd out, boolean allowsFieldFlow) {
DataFlowCall call, RetNd ret, Nd out, boolean allowsFieldFlow
) {
exists(ReturnKindExt kind | exists(ReturnKindExt kind |
PrevStage::callEdgeReturn(call, _, ret, kind, out, allowsFieldFlow) and PrevStage::callEdgeReturn(call, _, ret, kind, out, allowsFieldFlow) and
PrevStage::callMayFlowThroughRev(call) and PrevStage::callMayFlowThroughRev(call) and
@@ -413,8 +407,8 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
} }
pragma[nomagic] pragma[nomagic]
private predicate compatibleContainer0(ApHeadContent apc, DataFlowType containerType) { private predicate compatibleContainer0(ApHeadContent apc, Type containerType) {
exists(DataFlowType containerType0, Content c | exists(Type containerType0, Content c |
PrevStage::storeStepCand(_, c, _, _, containerType0) and PrevStage::storeStepCand(_, c, _, _, containerType0) and
not topTypeContent(apc) and not topTypeContent(apc) and
compatibleTypesCached(containerType0, containerType) and compatibleTypesCached(containerType0, containerType) and
@@ -424,7 +418,7 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
pragma[nomagic] pragma[nomagic]
private predicate topTypeContent(ApHeadContent apc) { private predicate topTypeContent(ApHeadContent apc) {
exists(DataFlowType containerType0, Content c | exists(Type containerType0, Content c |
PrevStage::storeStepCand(_, c, _, _, containerType0) and PrevStage::storeStepCand(_, c, _, _, containerType0) and
isTopType(containerType0) and isTopType(containerType0) and
apc = projectToHeadContent(c) apc = projectToHeadContent(c)
@@ -433,7 +427,7 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
bindingset[apc, containerType] bindingset[apc, containerType]
pragma[inline_late] pragma[inline_late]
private predicate compatibleContainer(ApHeadContent apc, DataFlowType containerType) { private predicate compatibleContainer(ApHeadContent apc, Type containerType) {
compatibleContainer0(apc, containerType) compatibleContainer0(apc, containerType)
} }
@@ -462,7 +456,7 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
if node instanceof CastingNd if node instanceof CastingNd
then then
ap instanceof ApNil or ap instanceof ApNil or
compatibleContainer(getHeadContent(ap), node.getDataFlowType()) or compatibleContainer(getHeadContent(ap), node.getType()) or
topTypeContent(getHeadContent(ap)) topTypeContent(getHeadContent(ap))
else any() else any()
) )
@@ -528,7 +522,7 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
apa = getApprox(ap) apa = getApprox(ap)
or or
// flow through a callable // flow through a callable
exists(DataFlowCall call, RetNd ret, boolean allowsFieldFlow | exists(Call call, RetNd ret, boolean allowsFieldFlow |
fwdFlowThrough(call, cc, summaryCtx, t, ap, stored, ret) and fwdFlowThrough(call, cc, summaryCtx, t, ap, stored, ret) and
flowThroughOutOfCall(call, ret, node, allowsFieldFlow) and flowThroughOutOfCall(call, ret, node, allowsFieldFlow) and
apa = getApprox(ap) and apa = getApprox(ap) and
@@ -600,7 +594,7 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
Nd node1, Typ t1, Ap ap1, TypOption stored1, Content c, Typ t2, TypOption stored2, Nd node1, Typ t1, Ap ap1, TypOption stored1, Content c, Typ t2, TypOption stored2,
Nd node2, Cc cc, SummaryCtx summaryCtx Nd node2, Cc cc, SummaryCtx summaryCtx
) { ) {
exists(DataFlowType contentType, DataFlowType containerType | exists(Type contentType, Type containerType |
fwdFlow(node1, cc, summaryCtx, t1, ap1, stored1) and fwdFlow(node1, cc, summaryCtx, t1, ap1, stored1) and
PrevStage::storeStepCand(node1, c, node2, contentType, containerType) and PrevStage::storeStepCand(node1, c, node2, contentType, containerType) and
t2 = getTyp(containerType) and t2 = getTyp(containerType) and
@@ -690,7 +684,7 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
private module FwdFlowIn<flowThroughSig/0 flowThrough> { private module FwdFlowIn<flowThroughSig/0 flowThrough> {
pragma[nomagic] pragma[nomagic]
private predicate callEdgeArgParamRestricted( private predicate callEdgeArgParamRestricted(
DataFlowCall call, DataFlowCallable c, ArgNd arg, ParamNd p, boolean emptyAp Call call, Callable c, ArgNd arg, ParamNd p, boolean emptyAp
) { ) {
PrevStage::callEdgeArgParam(call, c, arg, p, emptyAp) and PrevStage::callEdgeArgParam(call, c, arg, p, emptyAp) and
if if
@@ -706,26 +700,20 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
} }
pragma[nomagic] pragma[nomagic]
private DataFlowCallable viableImplCallContextReducedRestricted( private Callable viableImplCallContextReducedRestricted(Call call, CcCall ctx) {
DataFlowCall call, CcCall ctx
) {
result = viableImplCallContextReduced(call, ctx) and result = viableImplCallContextReduced(call, ctx) and
callEdgeArgParamRestricted(call, result, _, _, _) callEdgeArgParamRestricted(call, result, _, _, _)
} }
bindingset[call, ctx] bindingset[call, ctx]
pragma[inline_late] pragma[inline_late]
private DataFlowCallable viableImplCallContextReducedInlineLate( private Callable viableImplCallContextReducedInlineLate(Call call, CcCall ctx) {
DataFlowCall call, CcCall ctx
) {
result = viableImplCallContextReducedRestricted(call, ctx) result = viableImplCallContextReducedRestricted(call, ctx)
} }
bindingset[arg, ctx] bindingset[arg, ctx]
pragma[inline_late] pragma[inline_late]
private DataFlowCallable viableImplCallContextReducedInlineLate( private Callable viableImplCallContextReducedInlineLate(Call call, ArgNd arg, CcCall ctx) {
DataFlowCall call, ArgNd arg, CcCall ctx
) {
callEdgeArgParamRestricted(call, _, arg, _, _) and callEdgeArgParamRestricted(call, _, arg, _, _) and
instanceofCcCall(ctx) and instanceofCcCall(ctx) and
result = viableImplCallContextReducedInlineLate(call, ctx) result = viableImplCallContextReducedInlineLate(call, ctx)
@@ -734,23 +722,21 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
bindingset[call] bindingset[call]
pragma[inline_late] pragma[inline_late]
private predicate callEdgeArgParamRestrictedInlineLate( private predicate callEdgeArgParamRestrictedInlineLate(
DataFlowCall call, DataFlowCallable c, ArgNd arg, ParamNd p, boolean emptyAp Call call, Callable c, ArgNd arg, ParamNd p, boolean emptyAp
) { ) {
callEdgeArgParamRestricted(call, c, arg, p, emptyAp) callEdgeArgParamRestricted(call, c, arg, p, emptyAp)
} }
bindingset[call, ctx] bindingset[call, ctx]
pragma[inline_late] pragma[inline_late]
private predicate viableImplNotCallContextReducedInlineLate(DataFlowCall call, Cc ctx) { private predicate viableImplNotCallContextReducedInlineLate(Call call, Cc ctx) {
instanceofCc(ctx) and instanceofCc(ctx) and
viableImplNotCallContextReduced(call, ctx) viableImplNotCallContextReduced(call, ctx)
} }
bindingset[arg, outercc] bindingset[arg, outercc]
pragma[inline_late] pragma[inline_late]
private predicate viableImplArgNotCallContextReduced( private predicate viableImplArgNotCallContextReduced(Call call, ArgNd arg, Cc outercc) {
DataFlowCall call, ArgNd arg, Cc outercc
) {
callEdgeArgParamRestricted(call, _, arg, _, _) and callEdgeArgParamRestricted(call, _, arg, _, _) and
instanceofCc(outercc) and instanceofCc(outercc) and
viableImplNotCallContextReducedInlineLate(call, outercc) viableImplNotCallContextReducedInlineLate(call, outercc)
@@ -758,8 +744,8 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
pragma[inline] pragma[inline]
private predicate fwdFlowInCand( private predicate fwdFlowInCand(
DataFlowCall call, ArgNd arg, Cc outercc, DataFlowCallable inner, ParamNd p, Call call, ArgNd arg, Cc outercc, Callable inner, ParamNd p, SummaryCtx summaryCtx,
SummaryCtx summaryCtx, Typ t, Ap ap, boolean emptyAp, TypOption stored, boolean cc Typ t, Ap ap, boolean emptyAp, TypOption stored, boolean cc
) { ) {
fwdFlowIntoArg(arg, outercc, summaryCtx, t, ap, emptyAp, stored, cc) and fwdFlowIntoArg(arg, outercc, summaryCtx, t, ap, emptyAp, stored, cc) and
( (
@@ -772,8 +758,8 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
pragma[inline] pragma[inline]
private predicate fwdFlowInCandTypeFlowDisabled( private predicate fwdFlowInCandTypeFlowDisabled(
DataFlowCall call, ArgNd arg, Cc outercc, DataFlowCallable inner, ParamNd p, Call call, ArgNd arg, Cc outercc, Callable inner, ParamNd p, SummaryCtx summaryCtx,
SummaryCtx summaryCtx, Typ t, Ap ap, TypOption stored, boolean cc Typ t, Ap ap, TypOption stored, boolean cc
) { ) {
not enableTypeFlow() and not enableTypeFlow() and
fwdFlowInCand(call, arg, outercc, inner, p, summaryCtx, t, ap, _, stored, cc) fwdFlowInCand(call, arg, outercc, inner, p, summaryCtx, t, ap, _, stored, cc)
@@ -781,8 +767,7 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
pragma[nomagic] pragma[nomagic]
private predicate fwdFlowInCandTypeFlowEnabled( private predicate fwdFlowInCandTypeFlowEnabled(
DataFlowCall call, ArgNd arg, Cc outercc, DataFlowCallable inner, ParamNd p, Call call, ArgNd arg, Cc outercc, Callable inner, ParamNd p, boolean emptyAp, boolean cc
boolean emptyAp, boolean cc
) { ) {
enableTypeFlow() and enableTypeFlow() and
fwdFlowInCand(call, arg, outercc, inner, p, _, _, _, emptyAp, _, cc) fwdFlowInCand(call, arg, outercc, inner, p, _, _, _, emptyAp, _, cc)
@@ -790,7 +775,7 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
pragma[nomagic] pragma[nomagic]
private predicate fwdFlowInValidEdgeTypeFlowDisabled( private predicate fwdFlowInValidEdgeTypeFlowDisabled(
DataFlowCall call, DataFlowCallable inner, CcCall innercc, boolean cc Call call, Callable inner, CcCall innercc, boolean cc
) { ) {
not enableTypeFlow() and not enableTypeFlow() and
FwdTypeFlow::typeFlowValidEdgeIn(call, inner, cc) and FwdTypeFlow::typeFlowValidEdgeIn(call, inner, cc) and
@@ -799,8 +784,8 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
pragma[nomagic] pragma[nomagic]
private predicate fwdFlowInValidEdgeTypeFlowEnabled( private predicate fwdFlowInValidEdgeTypeFlowEnabled(
DataFlowCall call, ArgNd arg, Cc outercc, DataFlowCallable inner, ParamNd p, Call call, ArgNd arg, Cc outercc, Callable inner, ParamNd p, CcCall innercc,
CcCall innercc, boolean emptyAp, boolean cc boolean emptyAp, boolean cc
) { ) {
fwdFlowInCandTypeFlowEnabled(call, arg, outercc, inner, p, emptyAp, cc) and fwdFlowInCandTypeFlowEnabled(call, arg, outercc, inner, p, emptyAp, cc) and
FwdTypeFlow::typeFlowValidEdgeIn(call, inner, cc) and FwdTypeFlow::typeFlowValidEdgeIn(call, inner, cc) and
@@ -809,8 +794,8 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
pragma[inline] pragma[inline]
predicate fwdFlowIn( predicate fwdFlowIn(
DataFlowCall call, ArgNd arg, DataFlowCallable inner, ParamNd p, Cc outercc, Call call, ArgNd arg, Callable inner, ParamNd p, Cc outercc, CcCall innercc,
CcCall innercc, SummaryCtx summaryCtx, Typ t, Ap ap, TypOption stored, boolean cc SummaryCtx summaryCtx, Typ t, Ap ap, TypOption stored, boolean cc
) { ) {
// type flow disabled: linear recursion // type flow disabled: linear recursion
fwdFlowInCandTypeFlowDisabled(call, arg, outercc, inner, p, summaryCtx, t, ap, stored, fwdFlowInCandTypeFlowDisabled(call, arg, outercc, inner, p, summaryCtx, t, ap, stored,
@@ -848,25 +833,21 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
} }
pragma[nomagic] pragma[nomagic]
private DataFlowCall viableImplCallContextReducedReverseRestricted( private Call viableImplCallContextReducedReverseRestricted(Callable c, CcNoCall ctx) {
DataFlowCallable c, CcNoCall ctx
) {
result = viableImplCallContextReducedReverse(c, ctx) and result = viableImplCallContextReducedReverse(c, ctx) and
PrevStage::callEdgeReturn(result, c, _, _, _, _) PrevStage::callEdgeReturn(result, c, _, _, _, _)
} }
bindingset[c, ctx] bindingset[c, ctx]
pragma[inline_late] pragma[inline_late]
private DataFlowCall viableImplCallContextReducedReverseInlineLate( private Call viableImplCallContextReducedReverseInlineLate(Callable c, CcNoCall ctx) {
DataFlowCallable c, CcNoCall ctx
) {
result = viableImplCallContextReducedReverseRestricted(c, ctx) result = viableImplCallContextReducedReverseRestricted(c, ctx)
} }
bindingset[call] bindingset[call]
pragma[inline_late] pragma[inline_late]
private predicate flowOutOfCallInlineLate( private predicate flowOutOfCallInlineLate(
DataFlowCall call, DataFlowCallable c, RetNd ret, Nd out, boolean allowsFieldFlow Call call, Callable c, RetNd ret, Nd out, boolean allowsFieldFlow
) { ) {
PrevStage::callEdgeReturn(call, c, ret, _, out, allowsFieldFlow) PrevStage::callEdgeReturn(call, c, ret, _, out, allowsFieldFlow)
} }
@@ -875,8 +856,7 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
pragma[inline_late] pragma[inline_late]
pragma[noopt] pragma[noopt]
private predicate flowOutOfCallNotCallContextReduced( private predicate flowOutOfCallNotCallContextReduced(
DataFlowCall call, DataFlowCallable c, RetNd ret, Nd out, boolean allowsFieldFlow, Call call, Callable c, RetNd ret, Nd out, boolean allowsFieldFlow, CcNoCall innercc
CcNoCall innercc
) { ) {
viableImplNotCallContextReducedReverse(innercc) and viableImplNotCallContextReducedReverse(innercc) and
PrevStage::callEdgeReturn(call, c, ret, _, out, allowsFieldFlow) PrevStage::callEdgeReturn(call, c, ret, _, out, allowsFieldFlow)
@@ -892,8 +872,7 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
pragma[nomagic] pragma[nomagic]
private predicate fwdFlowOutCand( private predicate fwdFlowOutCand(
DataFlowCall call, RetNd ret, CcNoCall innercc, DataFlowCallable inner, Nd out, Call call, RetNd ret, CcNoCall innercc, Callable inner, Nd out, boolean allowsFieldFlow
boolean allowsFieldFlow
) { ) {
fwdFlowIntoRet(ret, innercc, _, _, _, _) and fwdFlowIntoRet(ret, innercc, _, _, _, _) and
inner = ret.getEnclosingCallable() and inner = ret.getEnclosingCallable() and
@@ -907,8 +886,8 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
pragma[nomagic] pragma[nomagic]
private predicate fwdFlowOutValidEdge( private predicate fwdFlowOutValidEdge(
DataFlowCall call, RetNd ret, CcNoCall innercc, DataFlowCallable inner, Nd out, Call call, RetNd ret, CcNoCall innercc, Callable inner, Nd out, CcNoCall outercc,
CcNoCall outercc, boolean allowsFieldFlow boolean allowsFieldFlow
) { ) {
fwdFlowOutCand(call, ret, innercc, inner, out, allowsFieldFlow) and fwdFlowOutCand(call, ret, innercc, inner, out, allowsFieldFlow) and
FwdTypeFlow::typeFlowValidEdgeOut(call, inner) and FwdTypeFlow::typeFlowValidEdgeOut(call, inner) and
@@ -917,8 +896,8 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
pragma[inline] pragma[inline]
private predicate fwdFlowOut( private predicate fwdFlowOut(
DataFlowCall call, DataFlowCallable inner, Nd out, CcNoCall outercc, Call call, Callable inner, Nd out, CcNoCall outercc, SummaryCtx summaryCtx, Typ t, Ap ap,
SummaryCtx summaryCtx, Typ t, Ap ap, TypOption stored TypOption stored
) { ) {
exists(RetNd ret, CcNoCall innercc, boolean allowsFieldFlow | exists(RetNd ret, CcNoCall innercc, boolean allowsFieldFlow |
fwdFlowIntoRet(ret, innercc, summaryCtx, t, ap, stored) and fwdFlowIntoRet(ret, innercc, summaryCtx, t, ap, stored) and
@@ -936,8 +915,8 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
pragma[nomagic] pragma[nomagic]
private predicate dataFlowTakenCallEdgeIn0( private predicate dataFlowTakenCallEdgeIn0(
DataFlowCall call, DataFlowCallable c, ParamNd p, CcCall innercc, Typ t, Ap ap, Call call, Callable c, ParamNd p, CcCall innercc, Typ t, Ap ap, TypOption stored,
TypOption stored, boolean cc boolean cc
) { ) {
FwdFlowInNoThrough::fwdFlowIn(call, _, c, p, _, innercc, _, t, ap, stored, cc) FwdFlowInNoThrough::fwdFlowIn(call, _, c, p, _, innercc, _, t, ap, stored, cc)
or or
@@ -951,7 +930,7 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
} }
pragma[nomagic] pragma[nomagic]
predicate dataFlowTakenCallEdgeIn(DataFlowCall call, DataFlowCallable c, boolean cc) { predicate dataFlowTakenCallEdgeIn(Call call, Callable c, boolean cc) {
exists(ParamNd p, CcCall innercc, Typ t, Ap ap, TypOption stored | exists(ParamNd p, CcCall innercc, Typ t, Ap ap, TypOption stored |
dataFlowTakenCallEdgeIn0(call, c, p, innercc, t, ap, stored, cc) and dataFlowTakenCallEdgeIn0(call, c, p, innercc, t, ap, stored, cc) and
fwdFlow1Param(p, innercc, t, ap, stored) fwdFlow1Param(p, innercc, t, ap, stored)
@@ -960,7 +939,7 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
pragma[nomagic] pragma[nomagic]
private predicate dataFlowTakenCallEdgeOut0( private predicate dataFlowTakenCallEdgeOut0(
DataFlowCall call, DataFlowCallable c, Nd node, Cc cc, Typ t, Ap ap, TypOption stored Call call, Callable c, Nd node, Cc cc, Typ t, Ap ap, TypOption stored
) { ) {
fwdFlowOut(call, c, node, cc, _, t, ap, stored) fwdFlowOut(call, c, node, cc, _, t, ap, stored)
} }
@@ -972,14 +951,14 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
} }
pragma[nomagic] pragma[nomagic]
predicate dataFlowTakenCallEdgeOut(DataFlowCall call, DataFlowCallable c) { predicate dataFlowTakenCallEdgeOut(Call call, Callable c) {
exists(Nd node, Cc cc, Typ t, Ap ap, TypOption stored | exists(Nd node, Cc cc, Typ t, Ap ap, TypOption stored |
dataFlowTakenCallEdgeOut0(call, c, node, cc, t, ap, stored) and dataFlowTakenCallEdgeOut0(call, c, node, cc, t, ap, stored) and
fwdFlow1Out(node, cc, t, ap, stored) fwdFlow1Out(node, cc, t, ap, stored)
) )
} }
predicate dataFlowNonCallEntry(DataFlowCallable c, boolean cc) { predicate dataFlowNonCallEntry(Callable c, boolean cc) {
exists(Nd node | exists(Nd node |
sourceNode(node) and sourceNode(node) and
(if hasSourceCallCtx() then cc = true else cc = false) and (if hasSourceCallCtx() then cc = true else cc = false) and
@@ -998,7 +977,7 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
private module FwdTypeFlow = TypeFlow<FwdTypeFlowInput>; private module FwdTypeFlow = TypeFlow<FwdTypeFlowInput>;
private predicate flowIntoCallTaken( private predicate flowIntoCallTaken(
DataFlowCall call, DataFlowCallable c, ArgNd arg, ParamNd p, boolean emptyAp Call call, Callable c, ArgNd arg, ParamNd p, boolean emptyAp
) { ) {
PrevStage::callEdgeArgParam(call, c, arg, p, emptyAp) and PrevStage::callEdgeArgParam(call, c, arg, p, emptyAp) and
FwdTypeFlowInput::dataFlowTakenCallEdgeIn(call, c, _) FwdTypeFlowInput::dataFlowTakenCallEdgeIn(call, c, _)
@@ -1021,7 +1000,7 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
pragma[inline] pragma[inline]
private predicate fwdFlowThrough0( private predicate fwdFlowThrough0(
DataFlowCall call, ArgNd arg, Cc cc, CcCall ccc, SummaryCtx summaryCtx, Typ t, Ap ap, Call call, ArgNd arg, Cc cc, CcCall ccc, SummaryCtx summaryCtx, Typ t, Ap ap,
TypOption stored, RetNd ret, SummaryCtxSome innerSummaryCtx TypOption stored, RetNd ret, SummaryCtxSome innerSummaryCtx
) { ) {
fwdFlowRetFromArg(ret, ccc, innerSummaryCtx, t, ap, stored) and fwdFlowRetFromArg(ret, ccc, innerSummaryCtx, t, ap, stored) and
@@ -1030,15 +1009,15 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
pragma[nomagic] pragma[nomagic]
private predicate fwdFlowThrough( private predicate fwdFlowThrough(
DataFlowCall call, Cc cc, SummaryCtx summaryCtx, Typ t, Ap ap, TypOption stored, RetNd ret Call call, Cc cc, SummaryCtx summaryCtx, Typ t, Ap ap, TypOption stored, RetNd ret
) { ) {
fwdFlowThrough0(call, _, cc, _, summaryCtx, t, ap, stored, ret, _) fwdFlowThrough0(call, _, cc, _, summaryCtx, t, ap, stored, ret, _)
} }
pragma[nomagic] pragma[nomagic]
private predicate fwdFlowIsEntered0( private predicate fwdFlowIsEntered0(
DataFlowCall call, ArgNd arg, Cc cc, CcCall innerCc, SummaryCtx summaryCtx, ParamNd p, Call call, ArgNd arg, Cc cc, CcCall innerCc, SummaryCtx summaryCtx, ParamNd p, Typ t,
Typ t, Ap ap, TypOption stored Ap ap, TypOption stored
) { ) {
FwdFlowInThrough::fwdFlowIn(call, arg, _, p, cc, innerCc, summaryCtx, t, ap, stored, _) FwdFlowInThrough::fwdFlowIn(call, arg, _, p, cc, innerCc, summaryCtx, t, ap, stored, _)
} }
@@ -1049,7 +1028,7 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
*/ */
pragma[nomagic] pragma[nomagic]
private predicate fwdFlowIsEntered( private predicate fwdFlowIsEntered(
DataFlowCall call, ArgNd arg, Cc cc, CcCall innerCc, SummaryCtx summaryCtx, Call call, ArgNd arg, Cc cc, CcCall innerCc, SummaryCtx summaryCtx,
SummaryCtxSome innerSummaryCtx SummaryCtxSome innerSummaryCtx
) { ) {
exists(ParamNd p, Typ t, Ap ap, TypOption stored | exists(ParamNd p, Typ t, Ap ap, TypOption stored |
@@ -1071,7 +1050,7 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
pragma[nomagic] pragma[nomagic]
private predicate returnFlowsThrough0( private predicate returnFlowsThrough0(
DataFlowCall call, CcCall ccc, Ap ap, RetNd ret, SummaryCtxSome innerSummaryCtx Call call, CcCall ccc, Ap ap, RetNd ret, SummaryCtxSome innerSummaryCtx
) { ) {
fwdFlowThrough0(call, _, _, ccc, _, _, ap, _, ret, innerSummaryCtx) fwdFlowThrough0(call, _, _, ccc, _, _, ap, _, ret, innerSummaryCtx)
} }
@@ -1081,7 +1060,7 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
RetNd ret, ReturnPosition pos, CcCall ccc, ParamNd p, Typ argT, Ap argAp, RetNd ret, ReturnPosition pos, CcCall ccc, ParamNd p, Typ argT, Ap argAp,
TypOption argStored, Ap ap TypOption argStored, Ap ap
) { ) {
exists(DataFlowCall call, boolean allowsFieldFlow | exists(Call call, boolean allowsFieldFlow |
returnFlowsThrough0(call, ccc, ap, ret, TSummaryCtxSome(p, argT, argAp, argStored)) and returnFlowsThrough0(call, ccc, ap, ret, TSummaryCtxSome(p, argT, argAp, argStored)) and
flowThroughOutOfCall(call, ret, _, allowsFieldFlow) and flowThroughOutOfCall(call, ret, _, allowsFieldFlow) and
pos = ret.getReturnPosition() and pos = ret.getReturnPosition() and
@@ -1090,7 +1069,7 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
} }
pragma[nomagic] pragma[nomagic]
private predicate flowThroughIntoCall(DataFlowCall call, ArgNd arg, ParamNd p, Ap argAp) { private predicate flowThroughIntoCall(Call call, ArgNd arg, ParamNd p, Ap argAp) {
exists(Typ argT, TypOption argStored | exists(Typ argT, TypOption argStored |
returnFlowsThrough(_, _, _, pragma[only_bind_into](p), pragma[only_bind_into](argT), returnFlowsThrough(_, _, _, pragma[only_bind_into](p), pragma[only_bind_into](argT),
pragma[only_bind_into](argAp), pragma[only_bind_into](argStored), _) and pragma[only_bind_into](argAp), pragma[only_bind_into](argStored), _) and
@@ -1101,16 +1080,14 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
} }
pragma[nomagic] pragma[nomagic]
private predicate flowIntoCallAp( private predicate flowIntoCallAp(Call call, Callable c, ArgNd arg, ParamNd p, Ap ap) {
DataFlowCall call, DataFlowCallable c, ArgNd arg, ParamNd p, Ap ap
) {
flowIntoCallTaken(call, c, arg, p, isNil(ap)) and flowIntoCallTaken(call, c, arg, p, isNil(ap)) and
fwdFlow(arg, _, _, _, ap, _) fwdFlow(arg, _, _, _, ap, _)
} }
pragma[nomagic] pragma[nomagic]
private predicate flowOutOfCallAp( private predicate flowOutOfCallAp(
DataFlowCall call, DataFlowCallable c, RetNd ret, ReturnPosition pos, Nd out, Ap ap, Call call, Callable c, RetNd ret, ReturnPosition pos, Nd out, Ap ap,
boolean allowsFieldFlow boolean allowsFieldFlow
) { ) {
PrevStage::callEdgeReturn(call, c, ret, _, out, allowsFieldFlow) and PrevStage::callEdgeReturn(call, c, ret, _, out, allowsFieldFlow) and
@@ -1183,7 +1160,7 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
returnAp = apNone() returnAp = apNone()
or or
// flow through a callable // flow through a callable
exists(DataFlowCall call, ParamNd p | exists(Call call, ParamNd p |
revFlowThrough(call, returnCtx, p, returnAp, ap) and revFlowThrough(call, returnCtx, p, returnAp, ap) and
flowThroughIntoCall(call, node, p, ap) flowThroughIntoCall(call, node, p, ap)
) )
@@ -1238,16 +1215,14 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
private module RevTypeFlowInput implements TypeFlowInput { private module RevTypeFlowInput implements TypeFlowInput {
predicate enableTypeFlow = Param::enableTypeFlow/0; predicate enableTypeFlow = Param::enableTypeFlow/0;
predicate relevantCallEdgeIn(DataFlowCall call, DataFlowCallable c) { predicate relevantCallEdgeIn(Call call, Callable c) {
flowOutOfCallAp(call, c, _, _, _, _, _) flowOutOfCallAp(call, c, _, _, _, _, _)
} }
predicate relevantCallEdgeOut(DataFlowCall call, DataFlowCallable c) { predicate relevantCallEdgeOut(Call call, Callable c) { flowIntoCallAp(call, c, _, _, _) }
flowIntoCallAp(call, c, _, _, _)
}
pragma[nomagic] pragma[nomagic]
predicate dataFlowTakenCallEdgeIn(DataFlowCall call, DataFlowCallable c, boolean cc) { predicate dataFlowTakenCallEdgeIn(Call call, Callable c, boolean cc) {
exists(RetNd ret | exists(RetNd ret |
revFlowOut(call, ret, _, _, cc, _, _) and revFlowOut(call, ret, _, _, cc, _, _) and
c = ret.getEnclosingCallable() c = ret.getEnclosingCallable()
@@ -1255,11 +1230,9 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
} }
pragma[nomagic] pragma[nomagic]
predicate dataFlowTakenCallEdgeOut(DataFlowCall call, DataFlowCallable c) { predicate dataFlowTakenCallEdgeOut(Call call, Callable c) { revFlowIn(call, c, _, _) }
revFlowIn(call, c, _, _)
}
predicate dataFlowNonCallEntry(DataFlowCallable c, boolean cc) { predicate dataFlowNonCallEntry(Callable c, boolean cc) {
exists(Nd node, ApNil nil | exists(Nd node, ApNil nil |
fwdFlow(node, _, _, _, nil, _) and fwdFlow(node, _, _, _, nil, _) and
sinkNode(node) and sinkNode(node) and
@@ -1278,24 +1251,22 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
private module RevTypeFlow = TypeFlow<RevTypeFlowInput>; private module RevTypeFlow = TypeFlow<RevTypeFlowInput>;
pragma[nomagic] pragma[nomagic]
private predicate flowIntoCallApValid( private predicate flowIntoCallApValid(Call call, Callable c, ArgNd arg, ParamNd p, Ap ap) {
DataFlowCall call, DataFlowCallable c, ArgNd arg, ParamNd p, Ap ap
) {
flowIntoCallAp(call, c, arg, p, ap) and flowIntoCallAp(call, c, arg, p, ap) and
RevTypeFlow::typeFlowValidEdgeOut(call, c) RevTypeFlow::typeFlowValidEdgeOut(call, c)
} }
pragma[nomagic] pragma[nomagic]
private predicate flowOutOfCallApValid( private predicate flowOutOfCallApValid(
DataFlowCall call, RetNd ret, ReturnPosition pos, Nd out, Ap ap, boolean cc Call call, RetNd ret, ReturnPosition pos, Nd out, Ap ap, boolean cc
) { ) {
exists(DataFlowCallable c | exists(Callable c |
flowOutOfCallAp(call, c, ret, pos, out, ap, _) and flowOutOfCallAp(call, c, ret, pos, out, ap, _) and
RevTypeFlow::typeFlowValidEdgeIn(call, c, cc) RevTypeFlow::typeFlowValidEdgeIn(call, c, cc)
) )
} }
private predicate revFlowIn(DataFlowCall call, DataFlowCallable c, ArgNd arg, Ap ap) { private predicate revFlowIn(Call call, Callable c, ArgNd arg, Ap ap) {
exists(ParamNd p | exists(ParamNd p |
revFlow(p, TReturnCtxNone(), _, ap) and revFlow(p, TReturnCtxNone(), _, ap) and
flowIntoCallApValid(call, c, arg, p, ap) flowIntoCallApValid(call, c, arg, p, ap)
@@ -1304,7 +1275,7 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
pragma[nomagic] pragma[nomagic]
private predicate revFlowOut( private predicate revFlowOut(
DataFlowCall call, RetNd ret, ReturnPosition pos, ReturnCtx returnCtx, boolean cc, Call call, RetNd ret, ReturnPosition pos, ReturnCtx returnCtx, boolean cc,
ApOption returnAp, Ap ap ApOption returnAp, Ap ap
) { ) {
exists(Nd out | exists(Nd out |
@@ -1324,7 +1295,7 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
pragma[nomagic] pragma[nomagic]
private predicate revFlowThrough( private predicate revFlowThrough(
DataFlowCall call, ReturnCtx returnCtx, ParamNd p, ApOption returnAp, Ap ap Call call, ReturnCtx returnCtx, ParamNd p, ApOption returnAp, Ap ap
) { ) {
exists(ReturnPosition pos, Ap innerReturnAp | exists(ReturnPosition pos, Ap innerReturnAp |
revFlowParamToReturn(p, pos, innerReturnAp, ap) and revFlowParamToReturn(p, pos, innerReturnAp, ap) and
@@ -1339,7 +1310,7 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
*/ */
pragma[nomagic] pragma[nomagic]
private predicate revFlowIsReturned( private predicate revFlowIsReturned(
DataFlowCall call, ReturnCtx returnCtx, ApOption returnAp, ReturnPosition pos, Ap ap Call call, ReturnCtx returnCtx, ApOption returnAp, ReturnPosition pos, Ap ap
) { ) {
exists(RetNd ret, CcCall ccc | exists(RetNd ret, CcCall ccc |
revFlowOut(call, ret, pos, returnCtx, _, returnAp, ap) and revFlowOut(call, ret, pos, returnCtx, _, returnAp, ap) and
@@ -1349,9 +1320,7 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
} }
pragma[nomagic] pragma[nomagic]
predicate storeStepCand( predicate storeStepCand(Nd node1, Content c, Nd node2, Type contentType, Type containerType) {
Nd node1, Content c, Nd node2, DataFlowType contentType, DataFlowType containerType
) {
exists(Ap ap2, Ap ap1 | exists(Ap ap2, Ap ap1 |
PrevStage::storeStepCand(node1, c, node2, contentType, containerType) and PrevStage::storeStepCand(node1, c, node2, contentType, containerType) and
revFlowStore(ap2, c, ap1, node1, node2, _, _) and revFlowStore(ap2, c, ap1, node1, node2, _, _) and
@@ -1449,7 +1418,7 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
pragma[nomagic] pragma[nomagic]
private predicate revFlowThroughArg( private predicate revFlowThroughArg(
DataFlowCall call, ArgNd arg, ReturnCtx returnCtx, ApOption returnAp, Ap ap Call call, ArgNd arg, ReturnCtx returnCtx, ApOption returnAp, Ap ap
) { ) {
exists(ParamNd p | exists(ParamNd p |
revFlowThrough(call, returnCtx, p, returnAp, ap) and revFlowThrough(call, returnCtx, p, returnAp, ap) and
@@ -1458,16 +1427,14 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
} }
pragma[nomagic] pragma[nomagic]
predicate callMayFlowThroughRev(DataFlowCall call) { predicate callMayFlowThroughRev(Call call) {
exists(ArgNd arg, ReturnCtx returnCtx, ApOption returnAp, Ap ap | exists(ArgNd arg, ReturnCtx returnCtx, ApOption returnAp, Ap ap |
revFlow(arg, returnCtx, returnAp, ap) and revFlow(arg, returnCtx, returnAp, ap) and
revFlowThroughArg(call, arg, returnCtx, returnAp, ap) revFlowThroughArg(call, arg, returnCtx, returnAp, ap)
) )
} }
predicate callEdgeArgParam( predicate callEdgeArgParam(Call call, Callable c, ArgNd arg, ParamNd p, boolean emptyAp) {
DataFlowCall call, DataFlowCallable c, ArgNd arg, ParamNd p, boolean emptyAp
) {
exists(Ap ap | exists(Ap ap |
flowIntoCallAp(call, c, arg, p, ap) and flowIntoCallAp(call, c, arg, p, ap) and
revFlow(arg, pragma[only_bind_into](ap)) and revFlow(arg, pragma[only_bind_into](ap)) and
@@ -1481,8 +1448,7 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
} }
predicate callEdgeReturn( predicate callEdgeReturn(
DataFlowCall call, DataFlowCallable c, RetNd ret, ReturnKindExt kind, Nd out, Call call, Callable c, RetNd ret, ReturnKindExt kind, Nd out, boolean allowsFieldFlow
boolean allowsFieldFlow
) { ) {
exists(ReturnPosition pos, Ap ap | exists(ReturnPosition pos, Ap ap |
flowOutOfCallAp(call, c, ret, pos, out, ap, allowsFieldFlow) and flowOutOfCallAp(call, c, ret, pos, out, ap, allowsFieldFlow) and
@@ -1493,18 +1459,13 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
) )
} }
predicate relevantCallEdgeIn(DataFlowCall call, DataFlowCallable c) { predicate relevantCallEdgeIn(Call call, Callable c) { callEdgeArgParam(call, c, _, _, _) }
callEdgeArgParam(call, c, _, _, _)
}
predicate relevantCallEdgeOut(DataFlowCall call, DataFlowCallable c) { predicate relevantCallEdgeOut(Call call, Callable c) { callEdgeReturn(call, c, _, _, _, _) }
callEdgeReturn(call, c, _, _, _, _)
}
/** Holds if `node1` can step to `node2` in one or more local steps. */ /** Holds if `node1` can step to `node2` in one or more local steps. */
signature predicate localStepSig( signature predicate localStepSig(
Nd node1, Nd node2, boolean preservesValue, DataFlowType t, LocalCallContext lcc, Nd node1, Nd node2, boolean preservesValue, Type t, LocalCallContext lcc, string label
string label
); );
/** /**
@@ -1532,7 +1493,7 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
} }
private predicate additionalLocalStateStep( private predicate additionalLocalStateStep(
Nd node1, Nd node2, DataFlowType t, LocalCallContext lcc, string label Nd node1, Nd node2, Type t, LocalCallContext lcc, string label
) { ) {
exists(ApNil nil | exists(ApNil nil |
revFlow(node1, pragma[only_bind_into](nil)) and revFlow(node1, pragma[only_bind_into](nil)) and
@@ -1615,10 +1576,9 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
*/ */
pragma[nomagic] pragma[nomagic]
private predicate localFlowStepPlus( private predicate localFlowStepPlus(
Nd node1, Nd node2, boolean preservesValue, DataFlowType t, LocalCallContext cc, Nd node1, Nd node2, boolean preservesValue, Type t, LocalCallContext cc, string label
string label
) { ) {
exists(Nd mid, boolean preservesValue2, DataFlowType t2, string label2, Ap ap | exists(Nd mid, boolean preservesValue2, Type t2, string label2, Ap ap |
localStepInput(mid, node2, preservesValue2, t2, cc, label2) and localStepInput(mid, node2, preservesValue2, t2, cc, label2) and
not isStateStep(mid, node2) and not isStateStep(mid, node2) and
revFlow(node2, pragma[only_bind_into](ap)) and revFlow(node2, pragma[only_bind_into](ap)) and
@@ -1631,7 +1591,7 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
t = t2 and t = t2 and
node1 != node2 node1 != node2
or or
exists(boolean preservesValue1, DataFlowType t1, string label1 | exists(boolean preservesValue1, Type t1, string label1 |
localFlowStepPlus(node1, mid, preservesValue1, t1, cc, label1) and localFlowStepPlus(node1, mid, preservesValue1, t1, cc, label1) and
not mid instanceof FlowCheckNode and not mid instanceof FlowCheckNode and
preservesValue = preservesValue2.booleanAnd(preservesValue1) and preservesValue = preservesValue2.booleanAnd(preservesValue1) and
@@ -1647,8 +1607,8 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
*/ */
pragma[nomagic] pragma[nomagic]
predicate localFlowBigStep( predicate localFlowBigStep(
Nd node1, Nd node2, boolean preservesValue, DataFlowType t, Nd node1, Nd node2, boolean preservesValue, Type t, LocalCallContext callContext,
LocalCallContext callContext, string label string label
) { ) {
exists(Ap ap | exists(Ap ap |
localFlowStepPlus(node1, node2, preservesValue, t, callContext, label) and localFlowStepPlus(node1, node2, preservesValue, t, callContext, label) and
@@ -1672,8 +1632,8 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
*/ */
pragma[nomagic] pragma[nomagic]
predicate localFlowBigStepTc( predicate localFlowBigStepTc(
Nd node1, Nd node2, boolean preservesValue, DataFlowType t, Nd node1, Nd node2, boolean preservesValue, Type t, LocalCallContext callContext,
LocalCallContext callContext, string label string label
) { ) {
exists(Ap ap | exists(Ap ap |
localFlowEntry(node1, pragma[only_bind_into](ap)) and localFlowEntry(node1, pragma[only_bind_into](ap)) and
@@ -2005,7 +1965,7 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
pragma[nomagic] pragma[nomagic]
private predicate fwdFlowThroughStep0( private predicate fwdFlowThroughStep0(
DataFlowCall call, ArgNd arg, Cc cc, CcCall ccc, SummaryCtx summaryCtx, Typ t, Ap ap, Call call, ArgNd arg, Cc cc, CcCall ccc, SummaryCtx summaryCtx, Typ t, Ap ap,
TypOption stored, RetNd ret, SummaryCtxSome innerSummaryCtx TypOption stored, RetNd ret, SummaryCtxSome innerSummaryCtx
) { ) {
fwdFlowThrough0(call, arg, cc, ccc, summaryCtx, t, ap, stored, ret, innerSummaryCtx) fwdFlowThrough0(call, arg, cc, ccc, summaryCtx, t, ap, stored, ret, innerSummaryCtx)
@@ -2030,7 +1990,7 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
pragma[nomagic] pragma[nomagic]
private predicate fwdFlowThroughStep1( private predicate fwdFlowThroughStep1(
PathNodeImpl pn1, PathNodeImpl pn2, PathNodeImpl pn3, DataFlowCall call, Cc cc, PathNodeImpl pn1, PathNodeImpl pn2, PathNodeImpl pn3, Call call, Cc cc,
SummaryCtx summaryCtx, Typ t, Ap ap, TypOption stored, RetNd ret SummaryCtx summaryCtx, Typ t, Ap ap, TypOption stored, RetNd ret
) { ) {
exists( exists(
@@ -2053,7 +2013,7 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
PathNodeImpl pn1, PathNodeImpl pn2, PathNodeImpl pn3, Nd node, Cc cc, PathNodeImpl pn1, PathNodeImpl pn2, PathNodeImpl pn3, Nd node, Cc cc,
SummaryCtx summaryCtx, Typ t, Ap ap, TypOption stored SummaryCtx summaryCtx, Typ t, Ap ap, TypOption stored
) { ) {
exists(DataFlowCall call, RetNd ret, boolean allowsFieldFlow | exists(Call call, RetNd ret, boolean allowsFieldFlow |
fwdFlowThroughStep1(pn1, pn2, pn3, call, cc, summaryCtx, t, ap, stored, ret) and fwdFlowThroughStep1(pn1, pn2, pn3, call, cc, summaryCtx, t, ap, stored, ret) and
flowThroughOutOfCall(call, ret, node, allowsFieldFlow) and flowThroughOutOfCall(call, ret, node, allowsFieldFlow) and
if allowsFieldFlow = false then ap instanceof ApNil else any() if allowsFieldFlow = false then ap instanceof ApNil else any()
@@ -2464,7 +2424,7 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
fwdFlow(n, cc, summaryCtx, t, ap, stored) fwdFlow(n, cc, summaryCtx, t, ap, stored)
) and ) and
calledges = calledges =
count(DataFlowCall call, DataFlowCallable c | count(Call call, Callable c |
FwdTypeFlowInput::dataFlowTakenCallEdgeIn(call, c, _) or FwdTypeFlowInput::dataFlowTakenCallEdgeIn(call, c, _) or
FwdTypeFlowInput::dataFlowTakenCallEdgeOut(call, c) FwdTypeFlowInput::dataFlowTakenCallEdgeOut(call, c)
) and ) and
@@ -2480,7 +2440,7 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
revFlow(n, returnCtx, retAp, ap) revFlow(n, returnCtx, retAp, ap)
) and ) and
calledges = calledges =
count(DataFlowCall call, DataFlowCallable c | count(Call call, Callable c |
RevTypeFlowInput::dataFlowTakenCallEdgeIn(call, c, _) or RevTypeFlowInput::dataFlowTakenCallEdgeIn(call, c, _) or
RevTypeFlowInput::dataFlowTakenCallEdgeOut(call, c) RevTypeFlowInput::dataFlowTakenCallEdgeOut(call, c)
) and ) and
@@ -2498,7 +2458,7 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
} }
/** Holds if the call context may be `call`. */ /** Holds if the call context may be `call`. */
predicate matchesCall(CcCall cc, DataFlowCall call) { any() } predicate matchesCall(CcCall cc, Call call) { any() }
class CcNoCall extends Cc { class CcNoCall extends Cc {
CcNoCall() { this = false } CcNoCall() { this = false }
@@ -2519,20 +2479,20 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
bindingset[cc] bindingset[cc]
LocalCc getLocalCc(Cc cc) { any() } LocalCc getLocalCc(Cc cc) { any() }
DataFlowCallable viableImplCallContextReduced(DataFlowCall call, CcCall ctx) { none() } Callable viableImplCallContextReduced(Call call, CcCall ctx) { none() }
bindingset[call, ctx] bindingset[call, ctx]
predicate viableImplNotCallContextReduced(DataFlowCall call, Cc ctx) { any() } predicate viableImplNotCallContextReduced(Call call, Cc ctx) { any() }
bindingset[call, c] bindingset[call, c]
CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c) { any() } CcCall getCallContextCall(Call call, Callable c) { any() }
DataFlowCall viableImplCallContextReducedReverse(DataFlowCallable c, CcNoCall ctx) { none() } Call viableImplCallContextReducedReverse(Callable c, CcNoCall ctx) { none() }
predicate viableImplNotCallContextReducedReverse(CcNoCall ctx) { any() } predicate viableImplNotCallContextReducedReverse(CcNoCall ctx) { any() }
bindingset[call, c] bindingset[call, c]
CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call) { any() } CcNoCall getCallContextReturn(Callable c, Call call) { any() }
} }
private module S1 implements StageSig { private module S1 implements StageSig {
@@ -2553,7 +2513,7 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
bindingset[result, ap] bindingset[result, ap]
PrevStage::Ap getApprox(Ap ap) { any() } PrevStage::Ap getApprox(Ap ap) { any() }
Typ getTyp(DataFlowType t) { any() } Typ getTyp(Type t) { any() }
bindingset[c, tail] bindingset[c, tail]
Ap apCons(Content c, Ap tail) { Ap apCons(Content c, Ap tail) {
@@ -2629,7 +2589,7 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
PrevStage::Ap getApprox(Ap ap) { result = ap.toBoolNonEmpty() } PrevStage::Ap getApprox(Ap ap) { result = ap.toBoolNonEmpty() }
Typ getTyp(DataFlowType t) { any() } Typ getTyp(Type t) { any() }
bindingset[c, tail] bindingset[c, tail]
Ap apCons(Content c, Ap tail) { result.getAHead() = c and exists(tail) } Ap apCons(Content c, Ap tail) { result.getAHead() = c and exists(tail) }
@@ -2663,8 +2623,7 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
import NoLocalCallContext import NoLocalCallContext
additional predicate localFlowBigStep( additional predicate localFlowBigStep(
Nd node1, Nd node2, boolean preservesValue, DataFlowType t, LocalCallContext lcc, Nd node1, Nd node2, boolean preservesValue, Type t, LocalCallContext lcc, string label
string label
) { ) {
PrevStage::LocalFlowBigStep<localStep1/6>::localFlowBigStep(node1, node2, preservesValue, t, PrevStage::LocalFlowBigStep<localStep1/6>::localFlowBigStep(node1, node2, preservesValue, t,
lcc, label) lcc, label)
@@ -2708,10 +2667,10 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
private module Stage3 = MkStage<Stage2>::Stage<Stage3Param>; private module Stage3 = MkStage<Stage2>::Stage<Stage3Param>;
bindingset[node, t0] bindingset[node, t0]
private predicate strengthenType(Nd node, DataFlowType t0, DataFlowType t) { private predicate strengthenType(Nd node, Type t0, Type t) {
if node instanceof CastingNd if node instanceof CastingNd
then then
exists(DataFlowType nt | nt = node.getDataFlowType() | exists(Type nt | nt = node.getType() |
if typeStrongerThanFilter(nt, t0) if typeStrongerThanFilter(nt, t0)
then t = nt then t = nt
else ( else (
@@ -2732,7 +2691,7 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
PrevStage::Ap getApprox(Ap ap) { result = ap.toApprox() } PrevStage::Ap getApprox(Ap ap) { result = ap.toApprox() }
Typ getTyp(DataFlowType t) { any() } Typ getTyp(Type t) { any() }
bindingset[c, tail] bindingset[c, tail]
Ap apCons(Content c, Ap tail) { result.getHead() = c and exists(tail) } Ap apCons(Content c, Ap tail) { result.getHead() = c and exists(tail) }
@@ -2994,7 +2953,7 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
private module Stage5Param implements MkStage<Stage4>::StageParam { private module Stage5Param implements MkStage<Stage4>::StageParam {
private module PrevStage = Stage4; private module PrevStage = Stage4;
class Typ = DataFlowType; class Typ = Type;
class Ap = AccessPathApprox; class Ap = AccessPathApprox;
@@ -3003,7 +2962,7 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
pragma[nomagic] pragma[nomagic]
PrevStage::Ap getApprox(Ap ap) { result = ap.getFront() } PrevStage::Ap getApprox(Ap ap) { result = ap.getFront() }
Typ getTyp(DataFlowType t) { result = t } Typ getTyp(Type t) { result = t }
bindingset[c, tail] bindingset[c, tail]
Ap apCons(Content c, Ap tail) { result.isCons(c, tail) } Ap apCons(Content c, Ap tail) { result.isCons(c, tail) }
@@ -3184,7 +3143,7 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
private module Stage6Param implements MkStage<Stage5>::StageParam { private module Stage6Param implements MkStage<Stage5>::StageParam {
private module PrevStage = Stage5; private module PrevStage = Stage5;
class Typ = DataFlowType; class Typ = Type;
class Ap = AccessPath; class Ap = AccessPath;
@@ -3193,7 +3152,7 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
pragma[nomagic] pragma[nomagic]
PrevStage::Ap getApprox(Ap ap) { result = ap.getApprox() } PrevStage::Ap getApprox(Ap ap) { result = ap.getApprox() }
Typ getTyp(DataFlowType t) { result = t } Typ getTyp(Type t) { result = t }
bindingset[c, tail] bindingset[c, tail]
pragma[inline_late] pragma[inline_late]
@@ -3428,7 +3387,7 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
/** /**
* Holds if data can flow from some source to `sink`. * Holds if data can flow from some source to `sink`.
*/ */
predicate flowToExpr(DataFlowExpr sink) { flowTo(exprNode(sink)) } predicate flowToExpr(Expr sink) { flowTo(exprNode(sink)) }
/** /**
* INTERNAL: Only for debugging. * INTERNAL: Only for debugging.

View File

@@ -16,6 +16,7 @@ module MakeImplStage1<LocationSig Location, InputSig<Location> Lang> {
private import MakeImpl<Location, Lang> as Impl private import MakeImpl<Location, Lang> as Impl
private import DataFlowImplCommon::MakeImplCommon<Location, Lang> private import DataFlowImplCommon::MakeImplCommon<Location, Lang>
private import DataFlowImplCommonPublic private import DataFlowImplCommonPublic
private import Aliases
bindingset[this] bindingset[this]
signature class FlowStateSig; signature class FlowStateSig;
@@ -33,9 +34,9 @@ module MakeImplStage1<LocationSig Location, InputSig<Location> Lang> {
Location getLocation(); Location getLocation();
DataFlowType getDataFlowType(); Type getType();
DataFlowCallable getEnclosingCallable(); Callable getEnclosingCallable();
} }
class ArgNd extends Nd; class ArgNd extends Nd;
@@ -68,7 +69,7 @@ module MakeImplStage1<LocationSig Location, InputSig<Location> Lang> {
predicate additionalJumpStep(Nd node1, Nd node2, string model); predicate additionalJumpStep(Nd node1, Nd node2, string model);
predicate localStep1( predicate localStep1(
Nd node1, Nd node2, boolean preservesValue, DataFlowType t, LocalCallContext lcc, string label Nd node1, Nd node2, boolean preservesValue, Type t, LocalCallContext lcc, string label
); );
predicate isStateStep(Nd node1, Nd node2); predicate isStateStep(Nd node1, Nd node2);
@@ -90,30 +91,25 @@ module MakeImplStage1<LocationSig Location, InputSig<Location> Lang> {
predicate revFlow(Nd node, Ap ap); predicate revFlow(Nd node, Ap ap);
predicate callMayFlowThroughRev(DataFlowCall call); predicate callMayFlowThroughRev(Call call);
predicate parameterMayFlowThrough(ParamNd p, boolean emptyAp); predicate parameterMayFlowThrough(ParamNd p, boolean emptyAp);
predicate returnMayFlowThrough(RetNd ret, ReturnKindExt kind); predicate returnMayFlowThrough(RetNd ret, ReturnKindExt kind);
predicate storeStepCand( predicate storeStepCand(Nd node1, Content c, Nd node2, Type contentType, Type containerType);
Nd node1, Content c, Nd node2, DataFlowType contentType, DataFlowType containerType
);
predicate readStepCand(Nd n1, Content c, Nd n2); predicate readStepCand(Nd n1, Content c, Nd n2);
predicate callEdgeArgParam( predicate callEdgeArgParam(Call call, Callable c, ArgNd arg, ParamNd p, boolean emptyAp);
DataFlowCall call, DataFlowCallable c, ArgNd arg, ParamNd p, boolean emptyAp
);
predicate callEdgeReturn( predicate callEdgeReturn(
DataFlowCall call, DataFlowCallable c, RetNd ret, ReturnKindExt kind, Nd out, Call call, Callable c, RetNd ret, ReturnKindExt kind, Nd out, boolean allowsFieldFlow
boolean allowsFieldFlow
); );
predicate relevantCallEdgeIn(DataFlowCall call, DataFlowCallable c); predicate relevantCallEdgeIn(Call call, Callable c);
predicate relevantCallEdgeOut(DataFlowCall call, DataFlowCallable c); predicate relevantCallEdgeOut(Call call, Callable c);
// end StageSig // end StageSig
predicate revFlowIsReadAndStored(Content c); predicate revFlowIsReadAndStored(Content c);
@@ -416,7 +412,7 @@ module MakeImplStage1<LocationSig Location, InputSig<Location> Lang> {
pragma[nomagic] pragma[nomagic]
private predicate storeUnrestricted( private predicate storeUnrestricted(
NodeEx node1, Content c, NodeEx node2, DataFlowType contentType, DataFlowType containerType NodeEx node1, Content c, NodeEx node2, Type contentType, Type containerType
) { ) {
storeEx(node1, c, node2, contentType, containerType) and storeEx(node1, c, node2, contentType, containerType) and
stepFilter(node1, node2) stepFilter(node1, node2)
@@ -427,7 +423,7 @@ module MakeImplStage1<LocationSig Location, InputSig<Location> Lang> {
pragma[nomagic] pragma[nomagic]
private predicate store( private predicate store(
NodeEx node1, Content c, NodeEx node2, DataFlowType contentType, DataFlowType containerType NodeEx node1, Content c, NodeEx node2, Type contentType, Type containerType
) { ) {
storeUnrestricted(node1, c, node2, contentType, containerType) and storeUnrestricted(node1, c, node2, contentType, containerType) and
hasReadStep(c) hasReadStep(c)
@@ -504,7 +500,7 @@ module MakeImplStage1<LocationSig Location, InputSig<Location> Lang> {
cc = false cc = false
or or
// flow through a callable // flow through a callable
exists(DataFlowCall call, ReturnKindExtOption kind, ReturnKindExtOption disallowReturnKind | exists(Call call, ReturnKindExtOption kind, ReturnKindExtOption disallowReturnKind |
fwdFlowOutFromArg(call, kind, node) and fwdFlowOutFromArg(call, kind, node) and
fwdFlowIsEntered(call, disallowReturnKind, cc) and fwdFlowIsEntered(call, disallowReturnKind, cc) and
kind != disallowReturnKind kind != disallowReturnKind
@@ -513,7 +509,7 @@ module MakeImplStage1<LocationSig Location, InputSig<Location> Lang> {
// inline to reduce the number of iterations // inline to reduce the number of iterations
pragma[inline] pragma[inline]
private predicate fwdFlowIn(DataFlowCall call, NodeEx arg, Cc cc, ParamNodeEx p) { private predicate fwdFlowIn(Call call, NodeEx arg, Cc cc, ParamNodeEx p) {
// call context cannot help reduce virtual dispatch // call context cannot help reduce virtual dispatch
fwdFlow(arg, cc) and fwdFlow(arg, cc) and
viableParamArgEx(call, p, arg) and viableParamArgEx(call, p, arg) and
@@ -526,7 +522,7 @@ module MakeImplStage1<LocationSig Location, InputSig<Location> Lang> {
) )
or or
// call context may help reduce virtual dispatch // call context may help reduce virtual dispatch
exists(DataFlowCallable target | exists(Callable target |
fwdFlowInReducedViableImplInSomeCallContext(call, arg, p, target) and fwdFlowInReducedViableImplInSomeCallContext(call, arg, p, target) and
target = viableImplInSomeFwdFlowCallContextExt(call) and target = viableImplInSomeFwdFlowCallContextExt(call) and
cc = true cc = true
@@ -550,9 +546,7 @@ module MakeImplStage1<LocationSig Location, InputSig<Location> Lang> {
* Holds if an argument to `call` is reached in the flow covered by `fwdFlow`. * Holds if an argument to `call` is reached in the flow covered by `fwdFlow`.
*/ */
pragma[nomagic] pragma[nomagic]
private predicate fwdFlowIsEntered( private predicate fwdFlowIsEntered(Call call, ReturnKindExtOption disallowReturnKind, Cc cc) {
DataFlowCall call, ReturnKindExtOption disallowReturnKind, Cc cc
) {
exists(ParamNodeEx p | exists(ParamNodeEx p |
fwdFlowIn(call, _, cc, p) and fwdFlowIn(call, _, cc, p) and
disallowReturnKind = getDisallowedReturnKind(p) disallowReturnKind = getDisallowedReturnKind(p)
@@ -561,7 +555,7 @@ module MakeImplStage1<LocationSig Location, InputSig<Location> Lang> {
pragma[nomagic] pragma[nomagic]
private predicate fwdFlowInReducedViableImplInSomeCallContext( private predicate fwdFlowInReducedViableImplInSomeCallContext(
DataFlowCall call, NodeEx arg, ParamNodeEx p, DataFlowCallable target Call call, NodeEx arg, ParamNodeEx p, Callable target
) { ) {
fwdFlow(arg, true) and fwdFlow(arg, true) and
viableParamArgEx(call, p, arg) and viableParamArgEx(call, p, arg) and
@@ -576,8 +570,8 @@ module MakeImplStage1<LocationSig Location, InputSig<Location> Lang> {
* and to `ctx`s that are reachable in `fwdFlow`. * and to `ctx`s that are reachable in `fwdFlow`.
*/ */
pragma[nomagic] pragma[nomagic]
private DataFlowCallable viableImplInSomeFwdFlowCallContextExt(DataFlowCall call) { private Callable viableImplInSomeFwdFlowCallContextExt(Call call) {
exists(DataFlowCall ctx | exists(Call ctx |
fwdFlowIsEntered(ctx, _, _) and fwdFlowIsEntered(ctx, _, _) and
result = viableImplInCallContextExt(call, ctx) result = viableImplInCallContextExt(call, ctx)
) )
@@ -626,7 +620,7 @@ module MakeImplStage1<LocationSig Location, InputSig<Location> Lang> {
// inline to reduce the number of iterations // inline to reduce the number of iterations
pragma[inline] pragma[inline]
private predicate fwdFlowOut(DataFlowCall call, ReturnKindExt kind, NodeEx out, Cc cc) { private predicate fwdFlowOut(Call call, ReturnKindExt kind, NodeEx out, Cc cc) {
exists(ReturnPosition pos | exists(ReturnPosition pos |
fwdFlowReturnPosition(pos, cc) and fwdFlowReturnPosition(pos, cc) and
viableReturnPosOutEx(call, pos, out) and viableReturnPosOutEx(call, pos, out) and
@@ -636,7 +630,7 @@ module MakeImplStage1<LocationSig Location, InputSig<Location> Lang> {
} }
pragma[nomagic] pragma[nomagic]
private predicate fwdFlowOutFromArg(DataFlowCall call, ReturnKindExtOption kind, NodeEx out) { private predicate fwdFlowOutFromArg(Call call, ReturnKindExtOption kind, NodeEx out) {
fwdFlowOut(call, kind.asSome(), out, true) fwdFlowOut(call, kind.asSome(), out, true)
} }
@@ -722,7 +716,7 @@ module MakeImplStage1<LocationSig Location, InputSig<Location> Lang> {
) )
or or
// flow through a callable // flow through a callable
exists(DataFlowCall call, ReturnKindExtOption kind, ReturnKindExtOption disallowReturnKind | exists(Call call, ReturnKindExtOption kind, ReturnKindExtOption disallowReturnKind |
revFlowIsReturned(call, kind, toReturn) and revFlowIsReturned(call, kind, toReturn) and
revFlowInToReturn(call, disallowReturnKind, node) and revFlowInToReturn(call, disallowReturnKind, node) and
kind != disallowReturnKind kind != disallowReturnKind
@@ -762,7 +756,7 @@ module MakeImplStage1<LocationSig Location, InputSig<Location> Lang> {
} }
pragma[nomagic] pragma[nomagic]
predicate viableReturnPosOutNodeCandFwd1(DataFlowCall call, ReturnPosition pos, NodeEx out) { predicate viableReturnPosOutNodeCandFwd1(Call call, ReturnPosition pos, NodeEx out) {
fwdFlowReturnPosition(pos, _) and fwdFlowReturnPosition(pos, _) and
viableReturnPosOutEx(call, pos, out) viableReturnPosOutEx(call, pos, out)
} }
@@ -776,20 +770,20 @@ module MakeImplStage1<LocationSig Location, InputSig<Location> Lang> {
} }
pragma[nomagic] pragma[nomagic]
predicate viableParamArgNodeCandFwd1(DataFlowCall call, ParamNodeEx p, ArgNodeEx arg) { predicate viableParamArgNodeCandFwd1(Call call, ParamNodeEx p, ArgNodeEx arg) {
fwdFlowIn(call, arg, _, p) fwdFlowIn(call, arg, _, p)
} }
// inline to reduce the number of iterations // inline to reduce the number of iterations
pragma[inline] pragma[inline]
private predicate revFlowIn(DataFlowCall call, ParamNodeEx p, ArgNodeEx arg, boolean toReturn) { private predicate revFlowIn(Call call, ParamNodeEx p, ArgNodeEx arg, boolean toReturn) {
revFlow(p, toReturn) and revFlow(p, toReturn) and
viableParamArgNodeCandFwd1(call, p, arg) viableParamArgNodeCandFwd1(call, p, arg)
} }
pragma[nomagic] pragma[nomagic]
private predicate revFlowInToReturn( private predicate revFlowInToReturn(
DataFlowCall call, ReturnKindExtOption disallowReturnKind, ArgNodeEx arg Call call, ReturnKindExtOption disallowReturnKind, ArgNodeEx arg
) { ) {
exists(ParamNodeEx p | exists(ParamNodeEx p |
revFlowIn(call, p, arg, true) and revFlowIn(call, p, arg, true) and
@@ -803,9 +797,7 @@ module MakeImplStage1<LocationSig Location, InputSig<Location> Lang> {
* reaching an argument of `call`. * reaching an argument of `call`.
*/ */
pragma[nomagic] pragma[nomagic]
private predicate revFlowIsReturned( private predicate revFlowIsReturned(Call call, ReturnKindExtOption kind, boolean toReturn) {
DataFlowCall call, ReturnKindExtOption kind, boolean toReturn
) {
exists(NodeEx out | exists(NodeEx out |
revFlow(out, toReturn) and revFlow(out, toReturn) and
fwdFlowOutFromArg(call, kind, out) fwdFlowOutFromArg(call, kind, out)
@@ -840,7 +832,7 @@ module MakeImplStage1<LocationSig Location, InputSig<Location> Lang> {
pragma[nomagic] pragma[nomagic]
predicate storeStepCand( predicate storeStepCand(
NodeEx node1, Content c, NodeEx node2, DataFlowType contentType, DataFlowType containerType NodeEx node1, Content c, NodeEx node2, Type contentType, Type containerType
) { ) {
revFlowIsReadAndStored(c) and revFlowIsReadAndStored(c) and
revFlow(node2) and revFlow(node2) and
@@ -866,7 +858,7 @@ module MakeImplStage1<LocationSig Location, InputSig<Location> Lang> {
/** Holds if flow may return from `callable`. */ /** Holds if flow may return from `callable`. */
pragma[nomagic] pragma[nomagic]
private predicate returnFlowCallableNodeCand(DataFlowCallable callable, ReturnKindExt kind) { private predicate returnFlowCallableNodeCand(Callable callable, ReturnKindExt kind) {
exists(RetNodeEx ret | exists(RetNodeEx ret |
throughFlowNodeCand(ret) and throughFlowNodeCand(ret) and
callable = ret.getEnclosingCallable() and callable = ret.getEnclosingCallable() and
@@ -880,7 +872,7 @@ module MakeImplStage1<LocationSig Location, InputSig<Location> Lang> {
*/ */
pragma[nomagic] pragma[nomagic]
predicate parameterMayFlowThrough(ParamNodeEx p, boolean emptyAp) { predicate parameterMayFlowThrough(ParamNodeEx p, boolean emptyAp) {
exists(DataFlowCallable c, ReturnKindExt kind | exists(Callable c, ReturnKindExt kind |
throughFlowNodeCand(p) and throughFlowNodeCand(p) and
returnFlowCallableNodeCand(c, kind) and returnFlowCallableNodeCand(c, kind) and
p.getEnclosingCallable() = c and p.getEnclosingCallable() = c and
@@ -896,7 +888,7 @@ module MakeImplStage1<LocationSig Location, InputSig<Location> Lang> {
} }
pragma[nomagic] pragma[nomagic]
predicate callMayFlowThroughRev(DataFlowCall call) { predicate callMayFlowThroughRev(Call call) {
exists( exists(
ArgNodeEx arg, ReturnKindExtOption kind, ReturnKindExtOption disallowReturnKind, ArgNodeEx arg, ReturnKindExtOption kind, ReturnKindExtOption disallowReturnKind,
boolean toReturn boolean toReturn
@@ -909,7 +901,7 @@ module MakeImplStage1<LocationSig Location, InputSig<Location> Lang> {
} }
predicate callEdgeArgParam( predicate callEdgeArgParam(
DataFlowCall call, DataFlowCallable c, ArgNodeEx arg, ParamNodeEx p, boolean emptyAp Call call, Callable c, ArgNodeEx arg, ParamNodeEx p, boolean emptyAp
) { ) {
exists(boolean allowsFieldFlow | exists(boolean allowsFieldFlow |
flowIntoCallNodeCand1(call, arg, p, allowsFieldFlow) and flowIntoCallNodeCand1(call, arg, p, allowsFieldFlow) and
@@ -923,7 +915,7 @@ module MakeImplStage1<LocationSig Location, InputSig<Location> Lang> {
} }
predicate callEdgeReturn( predicate callEdgeReturn(
DataFlowCall call, DataFlowCallable c, RetNodeEx ret, ReturnKindExt kind, NodeEx out, Call call, Callable c, RetNodeEx ret, ReturnKindExt kind, NodeEx out,
boolean allowsFieldFlow boolean allowsFieldFlow
) { ) {
flowOutOfCallNodeCand1(call, ret, kind, out, allowsFieldFlow) and flowOutOfCallNodeCand1(call, ret, kind, out, allowsFieldFlow) and
@@ -948,7 +940,7 @@ module MakeImplStage1<LocationSig Location, InputSig<Location> Lang> {
states = count(FlowState state | revFlowState(state)) and states = count(FlowState state | revFlowState(state)) and
tuples = count(NodeEx n, boolean b | revFlow(n, b)) and tuples = count(NodeEx n, boolean b | revFlow(n, b)) and
calledges = calledges =
count(DataFlowCall call, DataFlowCallable c | count(Call call, Callable c |
callEdgeArgParam(call, c, _, _, _) or callEdgeArgParam(call, c, _, _, _) or
callEdgeReturn(call, c, _, _, _, _) callEdgeReturn(call, c, _, _, _, _)
) )
@@ -980,11 +972,11 @@ module MakeImplStage1<LocationSig Location, InputSig<Location> Lang> {
predicate callMayFlowThroughRev = Stage1::callMayFlowThroughRev/1; predicate callMayFlowThroughRev = Stage1::callMayFlowThroughRev/1;
predicate relevantCallEdgeIn(DataFlowCall call, DataFlowCallable c) { predicate relevantCallEdgeIn(Call call, Callable c) {
Stage1::callEdgeArgParam(call, c, _, _, _) Stage1::callEdgeArgParam(call, c, _, _, _)
} }
predicate relevantCallEdgeOut(DataFlowCall call, DataFlowCallable c) { predicate relevantCallEdgeOut(Call call, Callable c) {
Stage1::callEdgeReturn(call, c, _, _, _, _) Stage1::callEdgeReturn(call, c, _, _, _, _)
} }
@@ -993,19 +985,18 @@ module MakeImplStage1<LocationSig Location, InputSig<Location> Lang> {
pragma[nomagic] pragma[nomagic]
private predicate localStepNodeCand1( private predicate localStepNodeCand1(
NodeEx node1, NodeEx node2, boolean preservesValue, DataFlowType t, LocalCallContext lcc, NodeEx node1, NodeEx node2, boolean preservesValue, Type t, LocalCallContext lcc, string label
string label
) { ) {
Stage1::revFlow(node1) and Stage1::revFlow(node1) and
Stage1::revFlow(node2) and Stage1::revFlow(node2) and
( (
preservesValue = true and preservesValue = true and
localFlowStepEx(node1, node2, label) and localFlowStepEx(node1, node2, label) and
t = node1.getDataFlowType() t = node1.getType()
or or
preservesValue = false and preservesValue = false and
additionalLocalFlowStep(node1, node2, label) and additionalLocalFlowStep(node1, node2, label) and
t = node2.getDataFlowType() t = node2.getType()
) and ) and
lcc.relevantFor(node1.getEnclosingCallable()) and lcc.relevantFor(node1.getEnclosingCallable()) and
not isUnreachableInCall1(node1, lcc) and not isUnreachableInCall1(node1, lcc) and
@@ -1014,20 +1005,20 @@ module MakeImplStage1<LocationSig Location, InputSig<Location> Lang> {
pragma[nomagic] pragma[nomagic]
private predicate localStateStepNodeCand1( private predicate localStateStepNodeCand1(
NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, DataFlowType t, NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, Type t, LocalCallContext lcc,
LocalCallContext lcc, string label string label
) { ) {
Stage1::revFlow(node1) and Stage1::revFlow(node1) and
Stage1::revFlow(node2) and Stage1::revFlow(node2) and
additionalLocalStateStep(node1, state1, node2, state2, label) and additionalLocalStateStep(node1, state1, node2, state2, label) and
t = node2.getDataFlowType() and t = node2.getType() and
lcc.relevantFor(node1.getEnclosingCallable()) and lcc.relevantFor(node1.getEnclosingCallable()) and
not isUnreachableInCall1(node1, lcc) and not isUnreachableInCall1(node1, lcc) and
not isUnreachableInCall1(node2, lcc) not isUnreachableInCall1(node2, lcc)
} }
pragma[nomagic] pragma[nomagic]
private predicate viableReturnPosOutNodeCand1(DataFlowCall call, ReturnPosition pos, NodeEx out) { private predicate viableReturnPosOutNodeCand1(Call call, ReturnPosition pos, NodeEx out) {
Stage1::revFlow(out) and Stage1::revFlow(out) and
Stage1::viableReturnPosOutNodeCandFwd1(call, pos, out) Stage1::viableReturnPosOutNodeCandFwd1(call, pos, out)
} }
@@ -1039,7 +1030,7 @@ module MakeImplStage1<LocationSig Location, InputSig<Location> Lang> {
*/ */
pragma[nomagic] pragma[nomagic]
private predicate flowOutOfCallNodeCand1( private predicate flowOutOfCallNodeCand1(
DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, NodeEx out Call call, RetNodeEx ret, ReturnKindExt kind, NodeEx out
) { ) {
exists(ReturnPosition pos | exists(ReturnPosition pos |
viableReturnPosOutNodeCand1(call, pos, out) and viableReturnPosOutNodeCand1(call, pos, out) and
@@ -1052,7 +1043,7 @@ module MakeImplStage1<LocationSig Location, InputSig<Location> Lang> {
} }
pragma[nomagic] pragma[nomagic]
private predicate viableParamArgNodeCand1(DataFlowCall call, ParamNodeEx p, ArgNodeEx arg) { private predicate viableParamArgNodeCand1(Call call, ParamNodeEx p, ArgNodeEx arg) {
Stage1::viableParamArgNodeCandFwd1(call, p, arg) and Stage1::viableParamArgNodeCandFwd1(call, p, arg) and
Stage1::revFlow(arg) Stage1::revFlow(arg)
} }
@@ -1062,7 +1053,7 @@ module MakeImplStage1<LocationSig Location, InputSig<Location> Lang> {
* path from a source to a sink. * path from a source to a sink.
*/ */
pragma[nomagic] pragma[nomagic]
private predicate flowIntoCallNodeCand1(DataFlowCall call, ArgNodeEx arg, ParamNodeEx p) { private predicate flowIntoCallNodeCand1(Call call, ArgNodeEx arg, ParamNodeEx p) {
viableParamArgNodeCand1(call, p, arg) and viableParamArgNodeCand1(call, p, arg) and
Stage1::revFlow(p) and Stage1::revFlow(p) and
not outBarrier(arg) and not outBarrier(arg) and
@@ -1081,9 +1072,7 @@ module MakeImplStage1<LocationSig Location, InputSig<Location> Lang> {
} }
pragma[nomagic] pragma[nomagic]
private predicate returnCallEdge1( private predicate returnCallEdge1(Callable c, SndLevelScopeOption scope, Call call, NodeEx out) {
DataFlowCallable c, SndLevelScopeOption scope, DataFlowCall call, NodeEx out
) {
exists(RetNodeEx ret | exists(RetNodeEx ret |
flowOutOfCallNodeCand1(call, ret, _, out) and flowOutOfCallNodeCand1(call, ret, _, out) and
c = ret.getEnclosingCallable() c = ret.getEnclosingCallable()
@@ -1094,37 +1083,35 @@ module MakeImplStage1<LocationSig Location, InputSig<Location> Lang> {
) )
} }
private int simpleDispatchFanoutOnReturn(DataFlowCall call, NodeEx out) { private int simpleDispatchFanoutOnReturn(Call call, NodeEx out) {
result = result =
strictcount(DataFlowCallable c, SndLevelScopeOption scope | strictcount(Callable c, SndLevelScopeOption scope | returnCallEdge1(c, scope, call, out))
returnCallEdge1(c, scope, call, out)
)
} }
pragma[nomagic] pragma[nomagic]
private predicate returnCallEdgeInCtx1( private predicate returnCallEdgeInCtx1(
DataFlowCallable c, SndLevelScopeOption scope, DataFlowCall call, NodeEx out, DataFlowCall ctx Callable c, SndLevelScopeOption scope, Call call, NodeEx out, Call ctx
) { ) {
returnCallEdge1(c, scope, call, out) and returnCallEdge1(c, scope, call, out) and
c = viableImplInCallContextExt(call, ctx) c = viableImplInCallContextExt(call, ctx)
} }
private int ctxDispatchFanoutOnReturn(NodeEx out, DataFlowCall ctx) { private int ctxDispatchFanoutOnReturn(NodeEx out, Call ctx) {
exists(DataFlowCall call, DataFlowCallable c | exists(Call call, Callable c |
simpleDispatchFanoutOnReturn(call, out) > 1 and simpleDispatchFanoutOnReturn(call, out) > 1 and
not Stage1::revFlow(out, false) and not Stage1::revFlow(out, false) and
call.getEnclosingCallable() = c and call.getEnclosingCallable() = c and
returnCallEdge1(c, _, ctx, _) and returnCallEdge1(c, _, ctx, _) and
mayBenefitFromCallContextExt(call, _) and mayBenefitFromCallContextExt(call, _) and
result = result =
count(DataFlowCallable tgt, SndLevelScopeOption scope | count(Callable tgt, SndLevelScopeOption scope |
returnCallEdgeInCtx1(tgt, scope, call, out, ctx) returnCallEdgeInCtx1(tgt, scope, call, out, ctx)
) )
) )
} }
private int ctxDispatchFanoutOnReturn(NodeEx out) { private int ctxDispatchFanoutOnReturn(NodeEx out) {
result = max(DataFlowCall ctx | | ctxDispatchFanoutOnReturn(out, ctx)) result = max(Call ctx | | ctxDispatchFanoutOnReturn(out, ctx))
} }
private int dispatchFanoutOnReturn(NodeEx out) { private int dispatchFanoutOnReturn(NodeEx out) {
@@ -1142,7 +1129,7 @@ module MakeImplStage1<LocationSig Location, InputSig<Location> Lang> {
pragma[nomagic] pragma[nomagic]
private int branch(ArgNodeEx n1) { private int branch(ArgNodeEx n1) {
result = result =
strictcount(DataFlowCallable c | strictcount(Callable c |
exists(NodeEx n | exists(NodeEx n |
flowIntoCallNodeCand1(_, n1, n) and flowIntoCallNodeCand1(_, n1, n) and
c = n.getEnclosingCallable() c = n.getEnclosingCallable()
@@ -1158,7 +1145,7 @@ module MakeImplStage1<LocationSig Location, InputSig<Location> Lang> {
pragma[nomagic] pragma[nomagic]
private int join(ParamNodeEx n2) { private int join(ParamNodeEx n2) {
result = result =
strictcount(DataFlowCallable c | strictcount(Callable c |
exists(NodeEx n | exists(NodeEx n |
flowIntoCallNodeCand1(_, n, n2) and flowIntoCallNodeCand1(_, n, n2) and
c = n.getEnclosingCallable() c = n.getEnclosingCallable()
@@ -1175,7 +1162,7 @@ module MakeImplStage1<LocationSig Location, InputSig<Location> Lang> {
*/ */
pragma[nomagic] pragma[nomagic]
private predicate flowOutOfCallNodeCand1( private predicate flowOutOfCallNodeCand1(
DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, NodeEx out, boolean allowsFieldFlow Call call, RetNodeEx ret, ReturnKindExt kind, NodeEx out, boolean allowsFieldFlow
) { ) {
flowOutOfCallNodeCand1(call, ret, kind, out) and flowOutOfCallNodeCand1(call, ret, kind, out) and
exists(int j | exists(int j |
@@ -1196,7 +1183,7 @@ module MakeImplStage1<LocationSig Location, InputSig<Location> Lang> {
*/ */
pragma[nomagic] pragma[nomagic]
private predicate flowIntoCallNodeCand1( private predicate flowIntoCallNodeCand1(
DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow Call call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow
) { ) {
flowIntoCallNodeCand1(call, arg, p) and flowIntoCallNodeCand1(call, arg, p) and
exists(int b, int j | exists(int b, int j |
@@ -1298,9 +1285,9 @@ module MakeImplStage1<LocationSig Location, InputSig<Location> Lang> {
Location getLocation() { result = node.getLocation() } Location getLocation() { result = node.getLocation() }
DataFlowType getDataFlowType() { result = node.getDataFlowType() } Type getType() { result = node.getType() }
DataFlowCallable getEnclosingCallable() { result = node.getEnclosingCallable() } Callable getEnclosingCallable() { result = node.getEnclosingCallable() }
} }
class ArgNd extends Nd { class ArgNd extends Nd {
@@ -1361,9 +1348,7 @@ module MakeImplStage1<LocationSig Location, InputSig<Location> Lang> {
private Nd mkNodeState(NodeEx node, FlowState state) { result = TNodeState(node, state) } private Nd mkNodeState(NodeEx node, FlowState state) { result = TNodeState(node, state) }
pragma[nomagic] pragma[nomagic]
predicate storeStepCand( predicate storeStepCand(Nd node1, Content c, Nd node2, Type contentType, Type containerType) {
Nd node1, Content c, Nd node2, DataFlowType contentType, DataFlowType containerType
) {
exists(NodeEx n1, NodeEx n2, FlowState s | exists(NodeEx n1, NodeEx n2, FlowState s |
Stage1::storeStepCand(n1, c, n2, contentType, containerType) and Stage1::storeStepCand(n1, c, n2, contentType, containerType) and
node1 = mkNodeState(n1, s) and node1 = mkNodeState(n1, s) and
@@ -1384,9 +1369,7 @@ module MakeImplStage1<LocationSig Location, InputSig<Location> Lang> {
) )
} }
predicate callEdgeArgParam( predicate callEdgeArgParam(Call call, Callable c, ArgNd arg, ParamNd p, boolean emptyAp) {
DataFlowCall call, DataFlowCallable c, ArgNd arg, ParamNd p, boolean emptyAp
) {
exists(ArgNodeEx arg0, ParamNodeEx p0, FlowState s | exists(ArgNodeEx arg0, ParamNodeEx p0, FlowState s |
Stage1::callEdgeArgParam(call, c, arg0, p0, emptyAp) and Stage1::callEdgeArgParam(call, c, arg0, p0, emptyAp) and
arg = mkNodeState(arg0, s) and arg = mkNodeState(arg0, s) and
@@ -1397,8 +1380,7 @@ module MakeImplStage1<LocationSig Location, InputSig<Location> Lang> {
} }
predicate callEdgeReturn( predicate callEdgeReturn(
DataFlowCall call, DataFlowCallable c, RetNd ret, ReturnKindExt kind, Nd out, Call call, Callable c, RetNd ret, ReturnKindExt kind, Nd out, boolean allowsFieldFlow
boolean allowsFieldFlow
) { ) {
exists(RetNodeEx ret0, NodeEx out0, FlowState s | exists(RetNodeEx ret0, NodeEx out0, FlowState s |
Stage1::callEdgeReturn(call, c, ret0, kind, out0, allowsFieldFlow) and Stage1::callEdgeReturn(call, c, ret0, kind, out0, allowsFieldFlow) and
@@ -1460,8 +1442,7 @@ module MakeImplStage1<LocationSig Location, InputSig<Location> Lang> {
pragma[nomagic] pragma[nomagic]
predicate localStep1( predicate localStep1(
Nd node1, Nd node2, boolean preservesValue, DataFlowType t, LocalCallContext lcc, Nd node1, Nd node2, boolean preservesValue, Type t, LocalCallContext lcc, string label
string label
) { ) {
exists(NodeEx n1, NodeEx n2, FlowState s | exists(NodeEx n1, NodeEx n2, FlowState s |
localStepNodeCand1(n1, n2, preservesValue, t, lcc, label) and localStepNodeCand1(n1, n2, preservesValue, t, lcc, label) and
@@ -1522,7 +1503,7 @@ module MakeImplStage1<LocationSig Location, InputSig<Location> Lang> {
predicate callContextNone = CachedCallContextSensitivity::ccNone/0; predicate callContextNone = CachedCallContextSensitivity::ccNone/0;
private predicate callableStep(DataFlowCallable c1, DataFlowCallable c2) { private predicate callableStep(Callable c1, Callable c2) {
exists(NodeEx node1, NodeEx node2 | exists(NodeEx node1, NodeEx node2 |
jumpStepEx1(node1, node2) jumpStepEx1(node1, node2)
or or
@@ -1542,23 +1523,23 @@ module MakeImplStage1<LocationSig Location, InputSig<Location> Lang> {
) )
} }
private predicate interestingCallableSrc(DataFlowCallable c) { private predicate interestingCallableSrc(Callable c) {
exists(Node n | isRelevantSource(n, _) and c = getNodeEnclosingCallable(n)) exists(Node n | isRelevantSource(n, _) and c = getNodeEnclosingCallable(n))
or or
exists(DataFlowCallable mid | interestingCallableSrc(mid) and callableStep(mid, c)) exists(Callable mid | interestingCallableSrc(mid) and callableStep(mid, c))
} }
private predicate interestingCallableSink(DataFlowCallable c) { private predicate interestingCallableSink(Callable c) {
exists(Node n | c = getNodeEnclosingCallable(n) | exists(Node n | c = getNodeEnclosingCallable(n) |
isRelevantSink(n, _) or isRelevantSink(n, _) or
isRelevantSink(n) isRelevantSink(n)
) )
or or
exists(DataFlowCallable mid | interestingCallableSink(mid) and callableStep(c, mid)) exists(Callable mid | interestingCallableSink(mid) and callableStep(c, mid))
} }
private newtype TCallableExt = private newtype TCallableExt =
TCallable(DataFlowCallable c) { TCallable(Callable c) {
interestingCallableSrc(c) or interestingCallableSrc(c) or
interestingCallableSink(c) interestingCallableSink(c)
} or } or
@@ -1570,7 +1551,7 @@ module MakeImplStage1<LocationSig Location, InputSig<Location> Lang> {
private predicate callableExtSink(TCallableSink sink) { any() } private predicate callableExtSink(TCallableSink sink) { any() }
private predicate callableExtStepFwd(TCallableExt ce1, TCallableExt ce2) { private predicate callableExtStepFwd(TCallableExt ce1, TCallableExt ce2) {
exists(DataFlowCallable c1, DataFlowCallable c2 | exists(Callable c1, Callable c2 |
callableStep(c1, c2) and callableStep(c1, c2) and
ce1 = TCallable(c1) and ce1 = TCallable(c1) and
ce2 = TCallable(c2) ce2 = TCallable(c2)
@@ -1601,9 +1582,9 @@ module MakeImplStage1<LocationSig Location, InputSig<Location> Lang> {
private int distSinkExt(TCallableExt c) = private int distSinkExt(TCallableExt c) =
shortestDistances(callableExtSink/1, callableExtStepRev/2)(_, c, result) shortestDistances(callableExtSink/1, callableExtStepRev/2)(_, c, result)
private int distSrc(DataFlowCallable c) { result = distSrcExt(TCallable(c)) - 1 } private int distSrc(Callable c) { result = distSrcExt(TCallable(c)) - 1 }
private int distSink(DataFlowCallable c) { result = distSinkExt(TCallable(c)) - 1 } private int distSink(Callable c) { result = distSinkExt(TCallable(c)) - 1 }
private newtype TPartialAccessPath = private newtype TPartialAccessPath =
TPartialNil() or TPartialNil() or
@@ -1667,7 +1648,7 @@ module MakeImplStage1<LocationSig Location, InputSig<Location> Lang> {
private newtype TSummaryCtx3 = private newtype TSummaryCtx3 =
TSummaryCtx3None() or TSummaryCtx3None() or
TSummaryCtx3Some(DataFlowType t) TSummaryCtx3Some(Type t)
private newtype TSummaryCtx4 = private newtype TSummaryCtx4 =
TSummaryCtx4None() or TSummaryCtx4None() or
@@ -1688,7 +1669,7 @@ module MakeImplStage1<LocationSig Location, InputSig<Location> Lang> {
private newtype TPartialPathNode = private newtype TPartialPathNode =
TPartialPathNodeFwd( TPartialPathNodeFwd(
NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2,
TSummaryCtx3 sc3, TSummaryCtx4 sc4, DataFlowType t, PartialAccessPath ap TSummaryCtx3 sc3, TSummaryCtx4 sc4, Type t, PartialAccessPath ap
) { ) {
flagFwd() and flagFwd() and
sourceNode(node, state) and sourceNode(node, state) and
@@ -1697,7 +1678,7 @@ module MakeImplStage1<LocationSig Location, InputSig<Location> Lang> {
sc2 = TSummaryCtx2None() and sc2 = TSummaryCtx2None() and
sc3 = TSummaryCtx3None() and sc3 = TSummaryCtx3None() and
sc4 = TSummaryCtx4None() and sc4 = TSummaryCtx4None() and
t = node.getDataFlowType() and t = node.getType() and
ap = TPartialNil() and ap = TPartialNil() and
exists(explorationLimit()) exists(explorationLimit())
or or
@@ -1732,16 +1713,16 @@ module MakeImplStage1<LocationSig Location, InputSig<Location> Lang> {
pragma[nomagic] pragma[nomagic]
private predicate partialPathStep( private predicate partialPathStep(
PartialPathNodeFwd mid, NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1, PartialPathNodeFwd mid, NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1,
TSummaryCtx2 sc2, TSummaryCtx3 sc3, TSummaryCtx4 sc4, DataFlowType t, PartialAccessPath ap TSummaryCtx2 sc2, TSummaryCtx3 sc3, TSummaryCtx4 sc4, Type t, PartialAccessPath ap
) { ) {
partialPathStep1(mid, node, state, cc, sc1, sc2, sc3, sc4, _, t, ap) partialPathStep1(mid, node, state, cc, sc1, sc2, sc3, sc4, _, t, ap)
} }
bindingset[node, t0] bindingset[node, t0]
private predicate strengthenType(NodeEx node, DataFlowType t0, DataFlowType t) { private predicate strengthenType(NodeEx node, Type t0, Type t) {
if node instanceof CastingNodeEx if node instanceof CastingNodeEx
then then
exists(DataFlowType nt | nt = node.getDataFlowType() | exists(Type nt | nt = node.getType() |
if typeStrongerThanFilter(nt, t0) if typeStrongerThanFilter(nt, t0)
then t = nt then t = nt
else ( else (
@@ -1754,8 +1735,7 @@ module MakeImplStage1<LocationSig Location, InputSig<Location> Lang> {
pragma[nomagic] pragma[nomagic]
private predicate partialPathStep1( private predicate partialPathStep1(
PartialPathNodeFwd mid, NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1, PartialPathNodeFwd mid, NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1,
TSummaryCtx2 sc2, TSummaryCtx3 sc3, TSummaryCtx4 sc4, DataFlowType t0, DataFlowType t, TSummaryCtx2 sc2, TSummaryCtx3 sc3, TSummaryCtx4 sc4, Type t0, Type t, PartialAccessPath ap
PartialAccessPath ap
) { ) {
exists(boolean isStoreStep | exists(boolean isStoreStep |
partialPathStep0(mid, node, state, cc, sc1, sc2, sc3, sc4, t0, ap, isStoreStep) and partialPathStep0(mid, node, state, cc, sc1, sc2, sc3, sc4, t0, ap, isStoreStep) and
@@ -1774,9 +1754,7 @@ module MakeImplStage1<LocationSig Location, InputSig<Location> Lang> {
} }
pragma[nomagic] pragma[nomagic]
private predicate partialPathTypeStrengthen( private predicate partialPathTypeStrengthen(Type t0, PartialAccessPath ap, Type t) {
DataFlowType t0, PartialAccessPath ap, DataFlowType t
) {
partialPathStep1(_, _, _, _, _, _, _, _, t0, t, ap) and t0 != t partialPathStep1(_, _, _, _, _, _, _, _, t0, t, ap) and t0 != t
} }
@@ -1885,7 +1863,7 @@ module MakeImplStage1<LocationSig Location, InputSig<Location> Lang> {
TSummaryCtx2 sc2; TSummaryCtx2 sc2;
TSummaryCtx3 sc3; TSummaryCtx3 sc3;
TSummaryCtx4 sc4; TSummaryCtx4 sc4;
DataFlowType t; Type t;
PartialAccessPath ap; PartialAccessPath ap;
PartialPathNodeFwd() { PartialPathNodeFwd() {
@@ -1906,7 +1884,7 @@ module MakeImplStage1<LocationSig Location, InputSig<Location> Lang> {
TSummaryCtx4 getSummaryCtx4() { result = sc4 } TSummaryCtx4 getSummaryCtx4() { result = sc4 }
DataFlowType getType() { result = t } Type getType() { result = t }
PartialAccessPath getAp() { result = ap } PartialAccessPath getAp() { result = ap }
@@ -1968,7 +1946,7 @@ module MakeImplStage1<LocationSig Location, InputSig<Location> Lang> {
pragma[nomagic] pragma[nomagic]
private predicate partialPathStep0( private predicate partialPathStep0(
PartialPathNodeFwd mid, NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1, PartialPathNodeFwd mid, NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1,
TSummaryCtx2 sc2, TSummaryCtx3 sc3, TSummaryCtx4 sc4, DataFlowType t, PartialAccessPath ap, TSummaryCtx2 sc2, TSummaryCtx3 sc3, TSummaryCtx4 sc4, Type t, PartialAccessPath ap,
boolean isStoreStep boolean isStoreStep
) { ) {
not isUnreachableInCall1(node, not isUnreachableInCall1(node,
@@ -1992,7 +1970,7 @@ module MakeImplStage1<LocationSig Location, InputSig<Location> Lang> {
sc3 = mid.getSummaryCtx3() and sc3 = mid.getSummaryCtx3() and
sc4 = mid.getSummaryCtx4() and sc4 = mid.getSummaryCtx4() and
mid.getAp() instanceof PartialAccessPathNil and mid.getAp() instanceof PartialAccessPathNil and
t = node.getDataFlowType() and t = node.getType() and
ap = TPartialNil() ap = TPartialNil()
or or
additionalLocalStateStep(mid.getNodeEx(), mid.getState(), node, state, _) and additionalLocalStateStep(mid.getNodeEx(), mid.getState(), node, state, _) and
@@ -2002,7 +1980,7 @@ module MakeImplStage1<LocationSig Location, InputSig<Location> Lang> {
sc3 = mid.getSummaryCtx3() and sc3 = mid.getSummaryCtx3() and
sc4 = mid.getSummaryCtx4() and sc4 = mid.getSummaryCtx4() and
mid.getAp() instanceof PartialAccessPathNil and mid.getAp() instanceof PartialAccessPathNil and
t = node.getDataFlowType() and t = node.getType() and
ap = TPartialNil() ap = TPartialNil()
) and ) and
isStoreStep = false isStoreStep = false
@@ -2026,7 +2004,7 @@ module MakeImplStage1<LocationSig Location, InputSig<Location> Lang> {
sc3 = TSummaryCtx3None() and sc3 = TSummaryCtx3None() and
sc4 = TSummaryCtx4None() and sc4 = TSummaryCtx4None() and
mid.getAp() instanceof PartialAccessPathNil and mid.getAp() instanceof PartialAccessPathNil and
t = node.getDataFlowType() and t = node.getType() and
ap = TPartialNil() and ap = TPartialNil() and
isStoreStep = false isStoreStep = false
or or
@@ -2037,7 +2015,7 @@ module MakeImplStage1<LocationSig Location, InputSig<Location> Lang> {
sc3 = TSummaryCtx3None() and sc3 = TSummaryCtx3None() and
sc4 = TSummaryCtx4None() and sc4 = TSummaryCtx4None() and
mid.getAp() instanceof PartialAccessPathNil and mid.getAp() instanceof PartialAccessPathNil and
t = node.getDataFlowType() and t = node.getType() and
ap = TPartialNil() and ap = TPartialNil() and
isStoreStep = false isStoreStep = false
or or
@@ -2050,7 +2028,7 @@ module MakeImplStage1<LocationSig Location, InputSig<Location> Lang> {
sc4 = mid.getSummaryCtx4() and sc4 = mid.getSummaryCtx4() and
isStoreStep = true isStoreStep = true
or or
exists(DataFlowType t0, PartialAccessPath ap0, Content c | exists(Type t0, PartialAccessPath ap0, Content c |
partialPathReadStep(mid, t0, ap0, c, node, cc) and partialPathReadStep(mid, t0, ap0, c, node, cc) and
state = mid.getState() and state = mid.getState() and
sc1 = mid.getSummaryCtx1() and sc1 = mid.getSummaryCtx1() and
@@ -2084,10 +2062,10 @@ module MakeImplStage1<LocationSig Location, InputSig<Location> Lang> {
pragma[inline] pragma[inline]
private predicate partialPathStoreStep( private predicate partialPathStoreStep(
PartialPathNodeFwd mid, DataFlowType t1, PartialAccessPath ap1, Content c, NodeEx node, PartialPathNodeFwd mid, Type t1, PartialAccessPath ap1, Content c, NodeEx node, Type t2,
DataFlowType t2, PartialAccessPath ap2 PartialAccessPath ap2
) { ) {
exists(NodeEx midNode, DataFlowType contentType | exists(NodeEx midNode, Type contentType |
midNode = mid.getNodeEx() and midNode = mid.getNodeEx() and
t1 = mid.getType() and t1 = mid.getType() and
ap1 = mid.getAp() and ap1 = mid.getAp() and
@@ -2100,11 +2078,11 @@ module MakeImplStage1<LocationSig Location, InputSig<Location> Lang> {
pragma[nomagic] pragma[nomagic]
private predicate apConsFwd( private predicate apConsFwd(
DataFlowType t1, PartialAccessPath ap1, Content c, DataFlowType t2, PartialAccessPath ap2 Type t1, PartialAccessPath ap1, Content c, Type t2, PartialAccessPath ap2
) { ) {
partialPathStoreStep(_, t1, ap1, c, _, t2, ap2) partialPathStoreStep(_, t1, ap1, c, _, t2, ap2)
or or
exists(DataFlowType t0 | exists(Type t0 |
partialPathTypeStrengthen(t0, ap2, t2) and partialPathTypeStrengthen(t0, ap2, t2) and
apConsFwd(t1, ap1, c, t0, ap2) apConsFwd(t1, ap1, c, t0, ap2)
) )
@@ -2112,8 +2090,7 @@ module MakeImplStage1<LocationSig Location, InputSig<Location> Lang> {
pragma[nomagic] pragma[nomagic]
private predicate partialPathReadStep( private predicate partialPathReadStep(
PartialPathNodeFwd mid, DataFlowType t, PartialAccessPath ap, Content c, NodeEx node, PartialPathNodeFwd mid, Type t, PartialAccessPath ap, Content c, NodeEx node, CallContext cc
CallContext cc
) { ) {
exists(NodeEx midNode | exists(NodeEx midNode |
midNode = mid.getNodeEx() and midNode = mid.getNodeEx() and
@@ -2126,8 +2103,8 @@ module MakeImplStage1<LocationSig Location, InputSig<Location> Lang> {
} }
private predicate partialPathOutOfCallable0( private predicate partialPathOutOfCallable0(
PartialPathNodeFwd mid, ReturnPosition pos, FlowState state, CallContext innercc, PartialPathNodeFwd mid, ReturnPosition pos, FlowState state, CallContext innercc, Type t,
DataFlowType t, PartialAccessPath ap PartialAccessPath ap
) { ) {
pos = mid.getNodeEx().(RetNodeEx).getReturnPosition() and pos = mid.getNodeEx().(RetNodeEx).getReturnPosition() and
state = mid.getState() and state = mid.getState() and
@@ -2139,10 +2116,10 @@ module MakeImplStage1<LocationSig Location, InputSig<Location> Lang> {
pragma[nomagic] pragma[nomagic]
private predicate partialPathOutOfCallable1( private predicate partialPathOutOfCallable1(
PartialPathNodeFwd mid, DataFlowCall call, ReturnKindExt kind, FlowState state, PartialPathNodeFwd mid, Call call, ReturnKindExt kind, FlowState state, CallContext cc,
CallContext cc, DataFlowType t, PartialAccessPath ap Type t, PartialAccessPath ap
) { ) {
exists(ReturnPosition pos, DataFlowCallable c, CallContext innercc | exists(ReturnPosition pos, Callable c, CallContext innercc |
partialPathOutOfCallable0(mid, pos, state, innercc, t, ap) and partialPathOutOfCallable0(mid, pos, state, innercc, t, ap) and
c = pos.getCallable() and c = pos.getCallable() and
kind = pos.getKind() and kind = pos.getKind() and
@@ -2152,10 +2129,10 @@ module MakeImplStage1<LocationSig Location, InputSig<Location> Lang> {
} }
private predicate partialPathOutOfCallable( private predicate partialPathOutOfCallable(
PartialPathNodeFwd mid, NodeEx out, FlowState state, CallContext cc, DataFlowType t, PartialPathNodeFwd mid, NodeEx out, FlowState state, CallContext cc, Type t,
PartialAccessPath ap PartialAccessPath ap
) { ) {
exists(ReturnKindExt kind, DataFlowCall call | exists(ReturnKindExt kind, Call call |
partialPathOutOfCallable1(mid, call, kind, state, cc, t, ap) and partialPathOutOfCallable1(mid, call, kind, state, cc, t, ap) and
out = kind.getAnOutNodeEx(call) out = kind.getAnOutNodeEx(call)
) )
@@ -2163,8 +2140,8 @@ module MakeImplStage1<LocationSig Location, InputSig<Location> Lang> {
pragma[noinline] pragma[noinline]
private predicate partialPathIntoArg( private predicate partialPathIntoArg(
PartialPathNodeFwd mid, ParameterPosition ppos, FlowState state, CallContext cc, PartialPathNodeFwd mid, ParameterPosition ppos, FlowState state, CallContext cc, Call call,
DataFlowCall call, DataFlowType t, PartialAccessPath ap Type t, PartialAccessPath ap
) { ) {
exists(ArgNode arg, ArgumentPosition apos | exists(ArgNode arg, ArgumentPosition apos |
arg = mid.getNodeEx().asNode() and arg = mid.getNodeEx().asNode() and
@@ -2179,8 +2156,8 @@ module MakeImplStage1<LocationSig Location, InputSig<Location> Lang> {
pragma[nomagic] pragma[nomagic]
private predicate partialPathIntoCallable0( private predicate partialPathIntoCallable0(
PartialPathNodeFwd mid, DataFlowCallable callable, ParameterPosition pos, FlowState state, PartialPathNodeFwd mid, Callable callable, ParameterPosition pos, FlowState state,
CallContext outercc, DataFlowCall call, DataFlowType t, PartialAccessPath ap CallContext outercc, Call call, Type t, PartialAccessPath ap
) { ) {
partialPathIntoArg(mid, pos, state, outercc, call, t, ap) and partialPathIntoArg(mid, pos, state, outercc, call, t, ap) and
callable = CachedCallContextSensitivity::resolveCall(call, outercc) callable = CachedCallContextSensitivity::resolveCall(call, outercc)
@@ -2189,9 +2166,9 @@ module MakeImplStage1<LocationSig Location, InputSig<Location> Lang> {
private predicate partialPathIntoCallable( private predicate partialPathIntoCallable(
PartialPathNodeFwd mid, ParamNodeEx p, FlowState state, CallContext outercc, PartialPathNodeFwd mid, ParamNodeEx p, FlowState state, CallContext outercc,
CallContextCall innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, TSummaryCtx3 sc3, CallContextCall innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, TSummaryCtx3 sc3,
TSummaryCtx4 sc4, DataFlowCall call, DataFlowType t, PartialAccessPath ap TSummaryCtx4 sc4, Call call, Type t, PartialAccessPath ap
) { ) {
exists(ParameterPosition pos, DataFlowCallable callable | exists(ParameterPosition pos, Callable callable |
partialPathIntoCallable0(mid, callable, pos, state, outercc, call, t, ap) and partialPathIntoCallable0(mid, callable, pos, state, outercc, call, t, ap) and
p.isParameterOf(callable, pos) and p.isParameterOf(callable, pos) and
sc1 = TSummaryCtx1Param(p) and sc1 = TSummaryCtx1Param(p) and
@@ -2206,7 +2183,7 @@ module MakeImplStage1<LocationSig Location, InputSig<Location> Lang> {
pragma[nomagic] pragma[nomagic]
private predicate paramFlowsThroughInPartialPath( private predicate paramFlowsThroughInPartialPath(
ReturnKindExt kind, FlowState state, CallContextCall cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, ReturnKindExt kind, FlowState state, CallContextCall cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2,
TSummaryCtx3 sc3, TSummaryCtx4 sc4, DataFlowType t, PartialAccessPath ap TSummaryCtx3 sc3, TSummaryCtx4 sc4, Type t, PartialAccessPath ap
) { ) {
exists(PartialPathNodeFwd mid, RetNodeEx ret | exists(PartialPathNodeFwd mid, RetNodeEx ret |
mid.getNodeEx() = ret and mid.getNodeEx() = ret and
@@ -2224,8 +2201,8 @@ module MakeImplStage1<LocationSig Location, InputSig<Location> Lang> {
pragma[noinline] pragma[noinline]
private predicate partialPathThroughCallable0( private predicate partialPathThroughCallable0(
DataFlowCall call, PartialPathNodeFwd mid, ReturnKindExt kind, FlowState state, Call call, PartialPathNodeFwd mid, ReturnKindExt kind, FlowState state, CallContext cc,
CallContext cc, DataFlowType t, PartialAccessPath ap Type t, PartialAccessPath ap
) { ) {
exists( exists(
CallContext innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, TSummaryCtx3 sc3, CallContext innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, TSummaryCtx3 sc3,
@@ -2237,10 +2214,10 @@ module MakeImplStage1<LocationSig Location, InputSig<Location> Lang> {
} }
private predicate partialPathThroughCallable( private predicate partialPathThroughCallable(
PartialPathNodeFwd mid, NodeEx out, FlowState state, CallContext cc, DataFlowType t, PartialPathNodeFwd mid, NodeEx out, FlowState state, CallContext cc, Type t,
PartialAccessPath ap PartialAccessPath ap
) { ) {
exists(DataFlowCall call, ReturnKindExt kind | exists(Call call, ReturnKindExt kind |
partialPathThroughCallable0(call, mid, kind, state, cc, t, ap) and partialPathThroughCallable0(call, mid, kind, state, cc, t, ap) and
out = kind.getAnOutNodeEx(call) out = kind.getAnOutNodeEx(call)
) )
@@ -2411,7 +2388,7 @@ module MakeImplStage1<LocationSig Location, InputSig<Location> Lang> {
pragma[nomagic] pragma[nomagic]
private predicate revPartialPathIntoReturn( private predicate revPartialPathIntoReturn(
PartialPathNodeRev mid, ReturnPosition pos, FlowState state, TRevSummaryCtx1Some sc1, PartialPathNodeRev mid, ReturnPosition pos, FlowState state, TRevSummaryCtx1Some sc1,
TRevSummaryCtx2Some sc2, TRevSummaryCtx3Some sc3, DataFlowCall call, PartialAccessPath ap TRevSummaryCtx2Some sc2, TRevSummaryCtx3Some sc3, Call call, PartialAccessPath ap
) { ) {
exists(NodeEx out | exists(NodeEx out |
mid.getNodeEx() = out and mid.getNodeEx() = out and
@@ -2443,7 +2420,7 @@ module MakeImplStage1<LocationSig Location, InputSig<Location> Lang> {
pragma[nomagic] pragma[nomagic]
private predicate revPartialPathThroughCallable0( private predicate revPartialPathThroughCallable0(
DataFlowCall call, PartialPathNodeRev mid, ArgumentPosition pos, FlowState state, Call call, PartialPathNodeRev mid, ArgumentPosition pos, FlowState state,
PartialAccessPath ap PartialAccessPath ap
) { ) {
exists(TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, TRevSummaryCtx3Some sc3 | exists(TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, TRevSummaryCtx3Some sc3 |
@@ -2456,7 +2433,7 @@ module MakeImplStage1<LocationSig Location, InputSig<Location> Lang> {
private predicate revPartialPathThroughCallable( private predicate revPartialPathThroughCallable(
PartialPathNodeRev mid, ArgNodeEx node, FlowState state, PartialAccessPath ap PartialPathNodeRev mid, ArgNodeEx node, FlowState state, PartialAccessPath ap
) { ) {
exists(DataFlowCall call, ArgumentPosition pos | exists(Call call, ArgumentPosition pos |
revPartialPathThroughCallable0(call, mid, pos, state, ap) and revPartialPathThroughCallable0(call, mid, pos, state, ap) and
node.argumentOf(call, pos) node.argumentOf(call, pos)
) )