Python: Remove typePreservingStep

This requires a bit of explanation, so strap in.

Firstly, because we use `LocalSourceNode`s as the start and end points
of our `StepSummary::step` relation, there's no need to include
`simpleLocalFlowStep` (via `typePreservingStep`) in `smallstep`. Indeed,
since the successor node for a `step` is a `LocalSourceNode`, and local
sources never have incoming flow, this is entirely futile -- we can find
values for `mid` and `nodeTo` that satisfy the body of `step`, but
`nodeTo` will never be a `LocalSourceNode`.

With this in mind, we can simplify `smallstep` to only refer to
`jumpStep`.

This then brings the other uses of `typePreservingStep` into question.
The only other place we use this predicate is in the `TypeTracker` and
`TypeBackTracker` `smallstep` predicates. Note, however, that here we
no longer need `jumpStep` to be part of `typeTrackingStep` (as it is
already accounted for in `StepSummary::smallstep`) so we can simplify
to `simpleLocalFlowStep`. At this point, `typePreservingStep` is unused.

Finally, because of the way `smallstep` is used in `step` (inside
`StepSummary`), `nodeTo` must always be a `LocalSourceNode`, so I have
propagated this restriction to `smallstep` as well. We can always lift
this restriction later, but for now it seems like it's likely to cause
fewer surprises to have made this explicit.
This commit is contained in:
Taus
2021-04-21 11:12:06 +00:00
committed by GitHub
parent 7cdf439b83
commit 9e95f6e7c1
2 changed files with 8 additions and 10 deletions

View File

@@ -71,8 +71,8 @@ module StepSummary {
* Unlike `StepSummary::step`, this predicate does not compress
* type-preserving steps.
*/
predicate smallstep(Node nodeFrom, Node nodeTo, StepSummary summary) {
typePreservingStep(nodeFrom, nodeTo) and
predicate smallstep(Node nodeFrom, LocalSourceNode nodeTo, StepSummary summary) {
jumpStep(nodeFrom, nodeTo) and
summary = LevelStep()
or
callStep(nodeFrom, nodeTo) and summary = CallStep()
@@ -225,7 +225,7 @@ class TypeTracker extends TTypeTracker {
* heap and/or inter-procedural step from `nodeFrom` to `nodeTo`.
*/
pragma[inline]
TypeTracker step(LocalSourceNode nodeFrom, Node nodeTo) {
TypeTracker step(LocalSourceNode nodeFrom, LocalSourceNode nodeTo) {
exists(StepSummary summary |
StepSummary::step(nodeFrom, nodeTo, summary) and
result = this.append(summary)
@@ -263,7 +263,7 @@ class TypeTracker extends TTypeTracker {
result = this.append(summary)
)
or
typePreservingStep(nodeFrom, nodeTo) and
simpleLocalFlowStep(nodeFrom, nodeTo) and
result = this
}
}
@@ -406,7 +406,7 @@ class TypeBackTracker extends TTypeBackTracker {
this = result.prepend(summary)
)
or
typePreservingStep(nodeFrom, nodeTo) and
simpleLocalFlowStep(nodeFrom, nodeTo) and
this = result
}
}

View File

@@ -6,11 +6,9 @@ class Node = DataFlowPublic::Node;
class LocalSourceNode = DataFlowPublic::LocalSourceNode;
/** Holds if it's reasonable to expect the data flow step from `nodeFrom` to `nodeTo` to preserve types. */
predicate typePreservingStep(Node nodeFrom, Node nodeTo) {
DataFlowPrivate::simpleLocalFlowStep(nodeFrom, nodeTo) or
DataFlowPrivate::jumpStep(nodeFrom, nodeTo)
}
predicate simpleLocalFlowStep = DataFlowPrivate::simpleLocalFlowStep/2;
predicate jumpStep = DataFlowPrivate::jumpStep/2;
/**
* Gets the name of a possible piece of content. For Python, this is currently only attribute names,