mirror of
https://github.com/github/codeql.git
synced 2026-03-01 13:23:49 +01:00
Merge pull request #3762 from hvitved/dataflow/clear-contents
Data flow: Model field clearing
This commit is contained in:
@@ -1051,6 +1051,17 @@ private predicate flowIntoCallNodeCand2(
|
||||
}
|
||||
|
||||
private module LocalFlowBigStep {
|
||||
/**
|
||||
* A node where some checking is required, and hence the big-step relation
|
||||
* is not allowed to step over.
|
||||
*/
|
||||
private class FlowCheckNode extends Node {
|
||||
FlowCheckNode() {
|
||||
this instanceof CastNode or
|
||||
clearsContent(this, _)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `node` can be the first node in a maximal subsequence of local
|
||||
* flow steps in a dataflow path.
|
||||
@@ -1065,7 +1076,7 @@ private module LocalFlowBigStep {
|
||||
node instanceof OutNodeExt or
|
||||
store(_, _, node, _) or
|
||||
read(_, _, node) or
|
||||
node instanceof CastNode
|
||||
node instanceof FlowCheckNode
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1083,7 +1094,7 @@ private module LocalFlowBigStep {
|
||||
read(node, _, next)
|
||||
)
|
||||
or
|
||||
node instanceof CastNode
|
||||
node instanceof FlowCheckNode
|
||||
or
|
||||
config.isSink(node)
|
||||
}
|
||||
@@ -1127,14 +1138,14 @@ private module LocalFlowBigStep {
|
||||
exists(Node mid |
|
||||
localFlowStepPlus(node1, mid, preservesValue, t, config, cc) and
|
||||
localFlowStepNodeCand1(mid, node2, config) and
|
||||
not mid instanceof CastNode and
|
||||
not mid instanceof FlowCheckNode and
|
||||
nodeCand2(node2, unbind(config))
|
||||
)
|
||||
or
|
||||
exists(Node mid |
|
||||
localFlowStepPlus(node1, mid, _, _, config, cc) and
|
||||
additionalLocalFlowStepNodeCand2(mid, node2, config) and
|
||||
not mid instanceof CastNode and
|
||||
not mid instanceof FlowCheckNode and
|
||||
preservesValue = false and
|
||||
t = getErasedNodeTypeBound(node2) and
|
||||
nodeCand2(node2, unbind(config))
|
||||
@@ -1190,6 +1201,7 @@ private predicate flowCandFwd(
|
||||
Configuration config
|
||||
) {
|
||||
flowCandFwd0(node, fromArg, argApf, apf, config) and
|
||||
not apf.isClearedAt(node) and
|
||||
if node instanceof CastingNode
|
||||
then compatibleTypes(getErasedNodeTypeBound(node), apf.getType())
|
||||
else any()
|
||||
|
||||
@@ -1051,6 +1051,17 @@ private predicate flowIntoCallNodeCand2(
|
||||
}
|
||||
|
||||
private module LocalFlowBigStep {
|
||||
/**
|
||||
* A node where some checking is required, and hence the big-step relation
|
||||
* is not allowed to step over.
|
||||
*/
|
||||
private class FlowCheckNode extends Node {
|
||||
FlowCheckNode() {
|
||||
this instanceof CastNode or
|
||||
clearsContent(this, _)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `node` can be the first node in a maximal subsequence of local
|
||||
* flow steps in a dataflow path.
|
||||
@@ -1065,7 +1076,7 @@ private module LocalFlowBigStep {
|
||||
node instanceof OutNodeExt or
|
||||
store(_, _, node, _) or
|
||||
read(_, _, node) or
|
||||
node instanceof CastNode
|
||||
node instanceof FlowCheckNode
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1083,7 +1094,7 @@ private module LocalFlowBigStep {
|
||||
read(node, _, next)
|
||||
)
|
||||
or
|
||||
node instanceof CastNode
|
||||
node instanceof FlowCheckNode
|
||||
or
|
||||
config.isSink(node)
|
||||
}
|
||||
@@ -1127,14 +1138,14 @@ private module LocalFlowBigStep {
|
||||
exists(Node mid |
|
||||
localFlowStepPlus(node1, mid, preservesValue, t, config, cc) and
|
||||
localFlowStepNodeCand1(mid, node2, config) and
|
||||
not mid instanceof CastNode and
|
||||
not mid instanceof FlowCheckNode and
|
||||
nodeCand2(node2, unbind(config))
|
||||
)
|
||||
or
|
||||
exists(Node mid |
|
||||
localFlowStepPlus(node1, mid, _, _, config, cc) and
|
||||
additionalLocalFlowStepNodeCand2(mid, node2, config) and
|
||||
not mid instanceof CastNode and
|
||||
not mid instanceof FlowCheckNode and
|
||||
preservesValue = false and
|
||||
t = getErasedNodeTypeBound(node2) and
|
||||
nodeCand2(node2, unbind(config))
|
||||
@@ -1190,6 +1201,7 @@ private predicate flowCandFwd(
|
||||
Configuration config
|
||||
) {
|
||||
flowCandFwd0(node, fromArg, argApf, apf, config) and
|
||||
not apf.isClearedAt(node) and
|
||||
if node instanceof CastingNode
|
||||
then compatibleTypes(getErasedNodeTypeBound(node), apf.getType())
|
||||
else any()
|
||||
|
||||
@@ -1051,6 +1051,17 @@ private predicate flowIntoCallNodeCand2(
|
||||
}
|
||||
|
||||
private module LocalFlowBigStep {
|
||||
/**
|
||||
* A node where some checking is required, and hence the big-step relation
|
||||
* is not allowed to step over.
|
||||
*/
|
||||
private class FlowCheckNode extends Node {
|
||||
FlowCheckNode() {
|
||||
this instanceof CastNode or
|
||||
clearsContent(this, _)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `node` can be the first node in a maximal subsequence of local
|
||||
* flow steps in a dataflow path.
|
||||
@@ -1065,7 +1076,7 @@ private module LocalFlowBigStep {
|
||||
node instanceof OutNodeExt or
|
||||
store(_, _, node, _) or
|
||||
read(_, _, node) or
|
||||
node instanceof CastNode
|
||||
node instanceof FlowCheckNode
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1083,7 +1094,7 @@ private module LocalFlowBigStep {
|
||||
read(node, _, next)
|
||||
)
|
||||
or
|
||||
node instanceof CastNode
|
||||
node instanceof FlowCheckNode
|
||||
or
|
||||
config.isSink(node)
|
||||
}
|
||||
@@ -1127,14 +1138,14 @@ private module LocalFlowBigStep {
|
||||
exists(Node mid |
|
||||
localFlowStepPlus(node1, mid, preservesValue, t, config, cc) and
|
||||
localFlowStepNodeCand1(mid, node2, config) and
|
||||
not mid instanceof CastNode and
|
||||
not mid instanceof FlowCheckNode and
|
||||
nodeCand2(node2, unbind(config))
|
||||
)
|
||||
or
|
||||
exists(Node mid |
|
||||
localFlowStepPlus(node1, mid, _, _, config, cc) and
|
||||
additionalLocalFlowStepNodeCand2(mid, node2, config) and
|
||||
not mid instanceof CastNode and
|
||||
not mid instanceof FlowCheckNode and
|
||||
preservesValue = false and
|
||||
t = getErasedNodeTypeBound(node2) and
|
||||
nodeCand2(node2, unbind(config))
|
||||
@@ -1190,6 +1201,7 @@ private predicate flowCandFwd(
|
||||
Configuration config
|
||||
) {
|
||||
flowCandFwd0(node, fromArg, argApf, apf, config) and
|
||||
not apf.isClearedAt(node) and
|
||||
if node instanceof CastingNode
|
||||
then compatibleTypes(getErasedNodeTypeBound(node), apf.getType())
|
||||
else any()
|
||||
|
||||
@@ -1051,6 +1051,17 @@ private predicate flowIntoCallNodeCand2(
|
||||
}
|
||||
|
||||
private module LocalFlowBigStep {
|
||||
/**
|
||||
* A node where some checking is required, and hence the big-step relation
|
||||
* is not allowed to step over.
|
||||
*/
|
||||
private class FlowCheckNode extends Node {
|
||||
FlowCheckNode() {
|
||||
this instanceof CastNode or
|
||||
clearsContent(this, _)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `node` can be the first node in a maximal subsequence of local
|
||||
* flow steps in a dataflow path.
|
||||
@@ -1065,7 +1076,7 @@ private module LocalFlowBigStep {
|
||||
node instanceof OutNodeExt or
|
||||
store(_, _, node, _) or
|
||||
read(_, _, node) or
|
||||
node instanceof CastNode
|
||||
node instanceof FlowCheckNode
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1083,7 +1094,7 @@ private module LocalFlowBigStep {
|
||||
read(node, _, next)
|
||||
)
|
||||
or
|
||||
node instanceof CastNode
|
||||
node instanceof FlowCheckNode
|
||||
or
|
||||
config.isSink(node)
|
||||
}
|
||||
@@ -1127,14 +1138,14 @@ private module LocalFlowBigStep {
|
||||
exists(Node mid |
|
||||
localFlowStepPlus(node1, mid, preservesValue, t, config, cc) and
|
||||
localFlowStepNodeCand1(mid, node2, config) and
|
||||
not mid instanceof CastNode and
|
||||
not mid instanceof FlowCheckNode and
|
||||
nodeCand2(node2, unbind(config))
|
||||
)
|
||||
or
|
||||
exists(Node mid |
|
||||
localFlowStepPlus(node1, mid, _, _, config, cc) and
|
||||
additionalLocalFlowStepNodeCand2(mid, node2, config) and
|
||||
not mid instanceof CastNode and
|
||||
not mid instanceof FlowCheckNode and
|
||||
preservesValue = false and
|
||||
t = getErasedNodeTypeBound(node2) and
|
||||
nodeCand2(node2, unbind(config))
|
||||
@@ -1190,6 +1201,7 @@ private predicate flowCandFwd(
|
||||
Configuration config
|
||||
) {
|
||||
flowCandFwd0(node, fromArg, argApf, apf, config) and
|
||||
not apf.isClearedAt(node) and
|
||||
if node instanceof CastingNode
|
||||
then compatibleTypes(getErasedNodeTypeBound(node), apf.getType())
|
||||
else any()
|
||||
|
||||
@@ -1051,6 +1051,17 @@ private predicate flowIntoCallNodeCand2(
|
||||
}
|
||||
|
||||
private module LocalFlowBigStep {
|
||||
/**
|
||||
* A node where some checking is required, and hence the big-step relation
|
||||
* is not allowed to step over.
|
||||
*/
|
||||
private class FlowCheckNode extends Node {
|
||||
FlowCheckNode() {
|
||||
this instanceof CastNode or
|
||||
clearsContent(this, _)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `node` can be the first node in a maximal subsequence of local
|
||||
* flow steps in a dataflow path.
|
||||
@@ -1065,7 +1076,7 @@ private module LocalFlowBigStep {
|
||||
node instanceof OutNodeExt or
|
||||
store(_, _, node, _) or
|
||||
read(_, _, node) or
|
||||
node instanceof CastNode
|
||||
node instanceof FlowCheckNode
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1083,7 +1094,7 @@ private module LocalFlowBigStep {
|
||||
read(node, _, next)
|
||||
)
|
||||
or
|
||||
node instanceof CastNode
|
||||
node instanceof FlowCheckNode
|
||||
or
|
||||
config.isSink(node)
|
||||
}
|
||||
@@ -1127,14 +1138,14 @@ private module LocalFlowBigStep {
|
||||
exists(Node mid |
|
||||
localFlowStepPlus(node1, mid, preservesValue, t, config, cc) and
|
||||
localFlowStepNodeCand1(mid, node2, config) and
|
||||
not mid instanceof CastNode and
|
||||
not mid instanceof FlowCheckNode and
|
||||
nodeCand2(node2, unbind(config))
|
||||
)
|
||||
or
|
||||
exists(Node mid |
|
||||
localFlowStepPlus(node1, mid, _, _, config, cc) and
|
||||
additionalLocalFlowStepNodeCand2(mid, node2, config) and
|
||||
not mid instanceof CastNode and
|
||||
not mid instanceof FlowCheckNode and
|
||||
preservesValue = false and
|
||||
t = getErasedNodeTypeBound(node2) and
|
||||
nodeCand2(node2, unbind(config))
|
||||
@@ -1190,6 +1201,7 @@ private predicate flowCandFwd(
|
||||
Configuration config
|
||||
) {
|
||||
flowCandFwd0(node, fromArg, argApf, apf, config) and
|
||||
not apf.isClearedAt(node) and
|
||||
if node instanceof CastingNode
|
||||
then compatibleTypes(getErasedNodeTypeBound(node), apf.getType())
|
||||
else any()
|
||||
|
||||
@@ -754,6 +754,13 @@ abstract class AccessPathFront extends TAccessPathFront {
|
||||
abstract boolean toBoolNonEmpty();
|
||||
|
||||
predicate headUsesContent(TypedContent tc) { this = TFrontHead(tc) }
|
||||
|
||||
predicate isClearedAt(Node n) {
|
||||
exists(TypedContent tc |
|
||||
this.headUsesContent(tc) and
|
||||
clearsContent(n, tc.getContent())
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
class AccessPathFrontNil extends AccessPathFront, TFrontNil {
|
||||
|
||||
@@ -195,6 +195,15 @@ predicate readStep(Node node1, Content f, Node node2) {
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if values stored inside content `c` are cleared at node `n`. For example,
|
||||
* any value stored inside `f` is cleared at the pre-update node associated with `x`
|
||||
* in `x.f = newValue`.
|
||||
*/
|
||||
predicate clearsContent(Node n, Content c) {
|
||||
n = any(PostUpdateNode pun | storeStep(_, c, pun)).getPreUpdateNode()
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a representative (boxed) type for `t` for the purpose of pruning
|
||||
* possible flow. A single type is used for all numeric types to account for
|
||||
|
||||
Reference in New Issue
Block a user