mirror of
https://github.com/github/codeql.git
synced 2025-12-16 16:53:25 +01:00
Data flow: Cache TNodeEx
This commit is contained in:
@@ -546,7 +546,7 @@ module ProductFlow {
|
|||||||
Flow1::PathGraph::edges(pred1, succ1, _, _) and
|
Flow1::PathGraph::edges(pred1, succ1, _, _) and
|
||||||
exists(ReturnKindExt returnKind |
|
exists(ReturnKindExt returnKind |
|
||||||
succ1.getNode() = returnKind.getAnOutNode(call) and
|
succ1.getNode() = returnKind.getAnOutNode(call) and
|
||||||
paramReturnNode(_, pred1.asParameterReturnNode(), _, returnKind)
|
returnKind = getParamReturnPosition(_, pred1.asParameterReturnNode()).getKind()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -574,7 +574,7 @@ module ProductFlow {
|
|||||||
Flow2::PathGraph::edges(pred2, succ2, _, _) and
|
Flow2::PathGraph::edges(pred2, succ2, _, _) and
|
||||||
exists(ReturnKindExt returnKind |
|
exists(ReturnKindExt returnKind |
|
||||||
succ2.getNode() = returnKind.getAnOutNode(call) and
|
succ2.getNode() = returnKind.getAnOutNode(call) and
|
||||||
paramReturnNode(_, pred2.asParameterReturnNode(), _, returnKind)
|
returnKind = getParamReturnPosition(_, pred2.asParameterReturnNode()).getKind()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -164,94 +164,19 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
|
|||||||
module Impl<FullStateConfigSig Config> {
|
module Impl<FullStateConfigSig Config> {
|
||||||
private class FlowState = Config::FlowState;
|
private class FlowState = Config::FlowState;
|
||||||
|
|
||||||
private newtype TNodeEx =
|
private class NodeEx extends NodeExImpl {
|
||||||
TNodeNormal(Node n) or
|
NodeEx() {
|
||||||
TNodeImplicitRead(Node n) { Config::allowImplicitRead(n, _) } or
|
Config::allowImplicitRead(any(Node n | this.isImplicitReadNode(n)), _)
|
||||||
TParamReturnNode(ParameterNode p, SndLevelScopeOption scope) {
|
|
||||||
paramReturnNode(_, p, scope, _)
|
|
||||||
}
|
|
||||||
|
|
||||||
private class NodeEx extends TNodeEx {
|
|
||||||
string toString() {
|
|
||||||
result = this.asNode().toString()
|
|
||||||
or
|
or
|
||||||
exists(Node n | this.isImplicitReadNode(n) | result = n.toString() + " [Ext]")
|
not this.isImplicitReadNode(_)
|
||||||
or
|
|
||||||
result = this.asParamReturnNode().toString() + " [Return]"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Node asNode() { this = TNodeNormal(result) }
|
|
||||||
|
|
||||||
/** Gets the corresponding Node if this is a normal node or its post-implicit read node. */
|
|
||||||
Node asNodeOrImplicitRead() { this = TNodeNormal(result) or this = TNodeImplicitRead(result) }
|
|
||||||
|
|
||||||
predicate isImplicitReadNode(Node n) { this = TNodeImplicitRead(n) }
|
|
||||||
|
|
||||||
ParameterNode asParamReturnNode() { this = TParamReturnNode(result, _) }
|
|
||||||
|
|
||||||
Node projectToNode() {
|
|
||||||
this = TNodeNormal(result) or
|
|
||||||
this = TNodeImplicitRead(result) or
|
|
||||||
this = TParamReturnNode(result, _)
|
|
||||||
}
|
|
||||||
|
|
||||||
pragma[nomagic]
|
|
||||||
private DataFlowCallable getEnclosingCallable0() {
|
|
||||||
nodeEnclosingCallable(this.projectToNode(), result)
|
|
||||||
}
|
|
||||||
|
|
||||||
pragma[inline]
|
|
||||||
DataFlowCallable getEnclosingCallable() {
|
|
||||||
pragma[only_bind_out](this).getEnclosingCallable0() = pragma[only_bind_into](result)
|
|
||||||
}
|
|
||||||
|
|
||||||
pragma[nomagic]
|
|
||||||
private DataFlowType getDataFlowType0() {
|
|
||||||
nodeDataFlowType(this.asNode(), result)
|
|
||||||
or
|
|
||||||
nodeDataFlowType(this.asParamReturnNode(), result)
|
|
||||||
}
|
|
||||||
|
|
||||||
pragma[inline]
|
|
||||||
DataFlowType getDataFlowType() {
|
|
||||||
pragma[only_bind_out](this).getDataFlowType0() = pragma[only_bind_into](result)
|
|
||||||
}
|
|
||||||
|
|
||||||
Location getLocation() { result = this.projectToNode().getLocation() }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private class ArgNodeEx extends NodeEx {
|
private class ArgNodeEx extends NodeEx, ArgNodeExImpl { }
|
||||||
ArgNodeEx() { this.asNode() instanceof ArgNode }
|
|
||||||
|
|
||||||
DataFlowCall getCall() { this.asNode().(ArgNode).argumentOf(result, _) }
|
private class ParamNodeEx extends NodeEx, ParamNodeExImpl { }
|
||||||
}
|
|
||||||
|
|
||||||
private class ParamNodeEx extends NodeEx {
|
private class RetNodeEx extends NodeEx, RetNodeExImpl { }
|
||||||
ParamNodeEx() { this.asNode() instanceof ParamNode }
|
|
||||||
|
|
||||||
predicate isParameterOf(DataFlowCallable c, ParameterPosition pos) {
|
|
||||||
this.asNode().(ParamNode).isParameterOf(c, pos)
|
|
||||||
}
|
|
||||||
|
|
||||||
ParameterPosition getPosition() { this.isParameterOf(_, result) }
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A node from which flow can return to the caller. This is either a regular
|
|
||||||
* `ReturnNode` or a synthesized node for flow out via a parameter.
|
|
||||||
*/
|
|
||||||
private class RetNodeEx extends NodeEx {
|
|
||||||
private ReturnPosition pos;
|
|
||||||
|
|
||||||
RetNodeEx() {
|
|
||||||
pos = getValueReturnPosition(this.asNode()) or
|
|
||||||
pos = getParamReturnPosition(_, this.asParamReturnNode())
|
|
||||||
}
|
|
||||||
|
|
||||||
ReturnPosition getReturnPosition() { result = pos }
|
|
||||||
|
|
||||||
ReturnKindExt getKind() { result = pos.getKind() }
|
|
||||||
}
|
|
||||||
|
|
||||||
private module SourceSinkFiltering {
|
private module SourceSinkFiltering {
|
||||||
private import codeql.util.AlertFiltering
|
private import codeql.util.AlertFiltering
|
||||||
@@ -428,20 +353,8 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
|
|||||||
* Holds if data can flow in one local step from `node1` to `node2`.
|
* Holds if data can flow in one local step from `node1` to `node2`.
|
||||||
*/
|
*/
|
||||||
private predicate localFlowStepEx(NodeEx node1, NodeEx node2, string model) {
|
private predicate localFlowStepEx(NodeEx node1, NodeEx node2, string model) {
|
||||||
exists(Node n1, Node n2 |
|
localFlowStepExImpl(node1, node2, model) and
|
||||||
node1.asNode() = n1 and
|
stepFilter(node1, node2)
|
||||||
node2.asNode() = n2 and
|
|
||||||
simpleLocalFlowStepExt(pragma[only_bind_into](n1), pragma[only_bind_into](n2), model) and
|
|
||||||
stepFilter(node1, node2)
|
|
||||||
)
|
|
||||||
or
|
|
||||||
exists(Node n1, Node n2, SndLevelScopeOption scope |
|
|
||||||
node1.asNode() = n1 and
|
|
||||||
node2 = TParamReturnNode(n2, scope) and
|
|
||||||
paramReturnNode(pragma[only_bind_into](n1), pragma[only_bind_into](n2),
|
|
||||||
pragma[only_bind_into](scope), _) and
|
|
||||||
model = ""
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -850,6 +850,85 @@ module MakeImplCommon<LocationSig Location, InputSig<Location> Lang> {
|
|||||||
|
|
||||||
class SndLevelScopeOption = SndLevelScopeOption::Option;
|
class SndLevelScopeOption = SndLevelScopeOption::Option;
|
||||||
|
|
||||||
|
final class NodeExImpl extends TNodeEx {
|
||||||
|
string toString() {
|
||||||
|
result = this.asNode().toString()
|
||||||
|
or
|
||||||
|
exists(Node n | this.isImplicitReadNode(n) | result = n.toString() + " [Ext]")
|
||||||
|
or
|
||||||
|
result = this.asParamReturnNode().toString() + " [Return]"
|
||||||
|
}
|
||||||
|
|
||||||
|
Node asNode() { this = TNodeNormal(result) }
|
||||||
|
|
||||||
|
/** Gets the corresponding Node if this is a normal node or its post-implicit read node. */
|
||||||
|
Node asNodeOrImplicitRead() { this = TNodeNormal(result) or this = TNodeImplicitRead(result) }
|
||||||
|
|
||||||
|
predicate isImplicitReadNode(Node n) { this = TNodeImplicitRead(n) }
|
||||||
|
|
||||||
|
ParameterNode asParamReturnNode() { this = TParamReturnNode(result, _) }
|
||||||
|
|
||||||
|
Node projectToNode() {
|
||||||
|
this = TNodeNormal(result) or
|
||||||
|
this = TNodeImplicitRead(result) or
|
||||||
|
this = TParamReturnNode(result, _)
|
||||||
|
}
|
||||||
|
|
||||||
|
pragma[nomagic]
|
||||||
|
private DataFlowCallable getEnclosingCallable0() {
|
||||||
|
nodeEnclosingCallable(this.projectToNode(), result)
|
||||||
|
}
|
||||||
|
|
||||||
|
pragma[inline]
|
||||||
|
DataFlowCallable getEnclosingCallable() {
|
||||||
|
pragma[only_bind_out](this).getEnclosingCallable0() = pragma[only_bind_into](result)
|
||||||
|
}
|
||||||
|
|
||||||
|
pragma[nomagic]
|
||||||
|
private DataFlowType getDataFlowType0() {
|
||||||
|
nodeDataFlowType(this.asNode(), result)
|
||||||
|
or
|
||||||
|
nodeDataFlowType(this.asParamReturnNode(), result)
|
||||||
|
}
|
||||||
|
|
||||||
|
pragma[inline]
|
||||||
|
DataFlowType getDataFlowType() {
|
||||||
|
pragma[only_bind_out](this).getDataFlowType0() = pragma[only_bind_into](result)
|
||||||
|
}
|
||||||
|
|
||||||
|
Location getLocation() { result = this.projectToNode().getLocation() }
|
||||||
|
}
|
||||||
|
|
||||||
|
final class ArgNodeExImpl extends NodeExImpl {
|
||||||
|
ArgNodeExImpl() { this.asNode() instanceof ArgNode }
|
||||||
|
|
||||||
|
DataFlowCall getCall() { this.asNode().(ArgNode).argumentOf(result, _) }
|
||||||
|
}
|
||||||
|
|
||||||
|
final class ParamNodeExImpl extends NodeExImpl {
|
||||||
|
ParamNodeExImpl() { this.asNode() instanceof ParamNode }
|
||||||
|
|
||||||
|
predicate isParameterOf(DataFlowCallable c, ParameterPosition pos) {
|
||||||
|
this.asNode().(ParamNode).isParameterOf(c, pos)
|
||||||
|
}
|
||||||
|
|
||||||
|
ParameterPosition getPosition() { this.isParameterOf(_, result) }
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A node from which flow can return to the caller. This is either a regular
|
||||||
|
* `ReturnNode` or a synthesized node for flow out via a parameter.
|
||||||
|
*/
|
||||||
|
final class RetNodeExImpl extends NodeExImpl {
|
||||||
|
private ReturnPosition pos;
|
||||||
|
|
||||||
|
RetNodeExImpl() { pos = getReturnPositionEx(this) }
|
||||||
|
|
||||||
|
ReturnPosition getReturnPosition() { result = pos }
|
||||||
|
|
||||||
|
ReturnKindExt getKind() { result = pos.getKind() }
|
||||||
|
}
|
||||||
|
|
||||||
cached
|
cached
|
||||||
private module Cached {
|
private module Cached {
|
||||||
/**
|
/**
|
||||||
@@ -927,11 +1006,8 @@ module MakeImplCommon<LocationSig Location, InputSig<Location> Lang> {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
cached
|
pragma[nomagic]
|
||||||
predicate valueReturnNode(ReturnNode n, ReturnKindExt k) { k = TValueReturn(n.getKind()) }
|
private predicate paramReturnNode(
|
||||||
|
|
||||||
cached
|
|
||||||
predicate paramReturnNode(
|
|
||||||
PostUpdateNode n, ParamNode p, SndLevelScopeOption scope, ReturnKindExt k
|
PostUpdateNode n, ParamNode p, SndLevelScopeOption scope, ReturnKindExt k
|
||||||
) {
|
) {
|
||||||
exists(ParameterPosition pos |
|
exists(ParameterPosition pos |
|
||||||
@@ -1541,6 +1617,20 @@ module MakeImplCommon<LocationSig Location, InputSig<Location> Lang> {
|
|||||||
|
|
||||||
class UnreachableSetOption = UnreachableSetOption::Option;
|
class UnreachableSetOption = UnreachableSetOption::Option;
|
||||||
|
|
||||||
|
pragma[nomagic]
|
||||||
|
private predicate hasValueReturnKindIn(ReturnNode ret, ReturnKindExt kind, DataFlowCallable c) {
|
||||||
|
c = getNodeEnclosingCallable(ret) and
|
||||||
|
kind = TValueReturn(ret.getKind())
|
||||||
|
}
|
||||||
|
|
||||||
|
pragma[nomagic]
|
||||||
|
private predicate hasParamReturnKindIn(
|
||||||
|
PostUpdateNode n, ParamNode p, ReturnKindExt kind, DataFlowCallable c
|
||||||
|
) {
|
||||||
|
c = getNodeEnclosingCallable(n) and
|
||||||
|
paramReturnNode(n, p, _, kind)
|
||||||
|
}
|
||||||
|
|
||||||
cached
|
cached
|
||||||
newtype TReturnPosition =
|
newtype TReturnPosition =
|
||||||
TReturnPosition0(DataFlowCallable c, ReturnKindExt kind) {
|
TReturnPosition0(DataFlowCallable c, ReturnKindExt kind) {
|
||||||
@@ -1549,6 +1639,22 @@ module MakeImplCommon<LocationSig Location, InputSig<Location> Lang> {
|
|||||||
hasParamReturnKindIn(_, _, kind, c)
|
hasParamReturnKindIn(_, _, kind, c)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cached
|
||||||
|
ReturnPosition getValueReturnPosition(ReturnNode ret) {
|
||||||
|
exists(ReturnKindExt kind, DataFlowCallable c |
|
||||||
|
hasValueReturnKindIn(ret, kind, c) and
|
||||||
|
result = TReturnPosition0(c, kind)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
cached
|
||||||
|
ReturnPosition getParamReturnPosition(PostUpdateNode n, ParamNode p) {
|
||||||
|
exists(ReturnKindExt kind, DataFlowCallable c |
|
||||||
|
hasParamReturnKindIn(n, p, kind, c) and
|
||||||
|
result = TReturnPosition0(c, kind)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
cached
|
cached
|
||||||
newtype TLocalFlowCallContext =
|
newtype TLocalFlowCallContext =
|
||||||
TAnyLocalCall() or
|
TAnyLocalCall() or
|
||||||
@@ -1594,6 +1700,44 @@ module MakeImplCommon<LocationSig Location, InputSig<Location> Lang> {
|
|||||||
newtype TApproxAccessPathFrontOption =
|
newtype TApproxAccessPathFrontOption =
|
||||||
TApproxAccessPathFrontNone() or
|
TApproxAccessPathFrontNone() or
|
||||||
TApproxAccessPathFrontSome(ApproxAccessPathFront apf)
|
TApproxAccessPathFrontSome(ApproxAccessPathFront apf)
|
||||||
|
|
||||||
|
cached
|
||||||
|
newtype TNodeEx =
|
||||||
|
TNodeNormal(Node n) or
|
||||||
|
TNodeImplicitRead(Node n) or // will be restricted to nodes with actual implicit reads in `DataFlowImpl.qll`
|
||||||
|
TParamReturnNode(ParameterNode p, SndLevelScopeOption scope) {
|
||||||
|
paramReturnNode(_, p, scope, _)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Holds if data can flow in one local step from `node1` to `node2`.
|
||||||
|
*/
|
||||||
|
cached
|
||||||
|
predicate localFlowStepExImpl(NodeExImpl node1, NodeExImpl node2, string model) {
|
||||||
|
exists(Node n1, Node n2 |
|
||||||
|
node1.asNode() = n1 and
|
||||||
|
node2.asNode() = n2 and
|
||||||
|
simpleLocalFlowStepExt(pragma[only_bind_into](n1), pragma[only_bind_into](n2), model)
|
||||||
|
)
|
||||||
|
or
|
||||||
|
exists(Node n1, Node n2, SndLevelScopeOption scope |
|
||||||
|
node1.asNode() = n1 and
|
||||||
|
node2 = TParamReturnNode(n2, scope) and
|
||||||
|
paramReturnNode(pragma[only_bind_into](n1), pragma[only_bind_into](n2),
|
||||||
|
pragma[only_bind_into](scope), _) and
|
||||||
|
model = ""
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
cached
|
||||||
|
ReturnPosition getReturnPositionEx(NodeExImpl ret) {
|
||||||
|
result = getValueReturnPosition(ret.asNode())
|
||||||
|
or
|
||||||
|
exists(ParamNode p |
|
||||||
|
ret = TParamReturnNode(p, _) and
|
||||||
|
result = getParamReturnPosition(_, p)
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bindingset[call, tgt]
|
bindingset[call, tgt]
|
||||||
@@ -2177,36 +2321,6 @@ module MakeImplCommon<LocationSig Location, InputSig<Location> Lang> {
|
|||||||
nodeDataFlowType(pragma[only_bind_out](n), pragma[only_bind_into](result))
|
nodeDataFlowType(pragma[only_bind_out](n), pragma[only_bind_into](result))
|
||||||
}
|
}
|
||||||
|
|
||||||
pragma[nomagic]
|
|
||||||
private predicate hasValueReturnKindIn(ReturnNode ret, ReturnKindExt kind, DataFlowCallable c) {
|
|
||||||
c = getNodeEnclosingCallable(ret) and
|
|
||||||
valueReturnNode(ret, kind)
|
|
||||||
}
|
|
||||||
|
|
||||||
pragma[nomagic]
|
|
||||||
private predicate hasParamReturnKindIn(
|
|
||||||
PostUpdateNode n, ParamNode p, ReturnKindExt kind, DataFlowCallable c
|
|
||||||
) {
|
|
||||||
c = getNodeEnclosingCallable(n) and
|
|
||||||
paramReturnNode(n, p, _, kind)
|
|
||||||
}
|
|
||||||
|
|
||||||
pragma[nomagic]
|
|
||||||
ReturnPosition getValueReturnPosition(ReturnNode ret) {
|
|
||||||
exists(ReturnKindExt kind, DataFlowCallable c |
|
|
||||||
hasValueReturnKindIn(ret, kind, c) and
|
|
||||||
result = TReturnPosition0(c, kind)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
pragma[nomagic]
|
|
||||||
ReturnPosition getParamReturnPosition(PostUpdateNode n, ParamNode p) {
|
|
||||||
exists(ReturnKindExt kind, DataFlowCallable c |
|
|
||||||
hasParamReturnKindIn(n, p, kind, c) and
|
|
||||||
result = TReturnPosition0(c, kind)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
/** An optional Boolean value. */
|
/** An optional Boolean value. */
|
||||||
class BooleanOption extends TBooleanOption {
|
class BooleanOption extends TBooleanOption {
|
||||||
string toString() {
|
string toString() {
|
||||||
|
|||||||
@@ -1775,7 +1775,7 @@ module Make<
|
|||||||
exists(ReturnNode ret, ValueReturnKind kind |
|
exists(ReturnNode ret, ValueReturnKind kind |
|
||||||
c = "ReturnValue" and
|
c = "ReturnValue" and
|
||||||
ret = node.asNode() and
|
ret = node.asNode() and
|
||||||
valueReturnNode(ret, kind) and
|
kind.getKind() = ret.getKind() and
|
||||||
kind.getKind() = getStandardReturnValueKind() and
|
kind.getKind() = getStandardReturnValueKind() and
|
||||||
mid.asCallable() = getNodeEnclosingCallable(ret)
|
mid.asCallable() = getNodeEnclosingCallable(ret)
|
||||||
)
|
)
|
||||||
|
|||||||
Reference in New Issue
Block a user