JS: AdditionalTypeTrackingStep -> SharedTypeTrackingStep

This commit is contained in:
Asger Feldthaus
2021-03-17 12:13:28 +00:00
parent b8049f19e2
commit 3a2f87f0a7
3 changed files with 99 additions and 29 deletions

View File

@@ -9,6 +9,7 @@
private import javascript
private import internal.FlowSteps
private import internal.StepSummary
private import internal.Unit
private import semmle.javascript.internal.CachedStages
private newtype TTypeTracker = MkTypeTracker(Boolean hasCall, OptionalPropertyName prop)
@@ -330,14 +331,14 @@ module TypeBackTracker {
/**
* A data flow edge that should be followed by type tracking.
*
* Unlike `AdditionalFlowStep`, this type of edge does not affect
* Unlike `SharedFlowStep`, this type of edge does not affect
* the local data flow graph, and is not used by data-flow configurations.
*
* Note: For performance reasons, all subclasses of this class should be part
* of the standard library. For query-specific steps, consider including the
* custom steps in the type-tracking predicate itself.
*/
abstract class AdditionalTypeTrackingStep extends DataFlow::Node {
class SharedTypeTrackingStep extends Unit {
/**
* Holds if type-tracking should step from `pred` to `succ`.
*/
@@ -358,3 +359,89 @@ abstract class AdditionalTypeTrackingStep extends DataFlow::Node {
*/
predicate loadStoreStep(DataFlow::Node pred, DataFlow::SourceNode succ, string prop) { none() }
}
/** Provides access to the steps contributed by subclasses of `SharedTypeTrackingStep`. */
module SharedTypeTrackingStep {
/**
* Holds if type-tracking should step from `pred` to `succ`.
*/
predicate step(DataFlow::Node pred, DataFlow::Node succ) {
any(SharedTypeTrackingStep s).step(pred, succ)
}
/**
* Holds if type-tracking should step from `pred` into the `prop` property of `succ`.
*/
predicate storeStep(DataFlow::Node pred, DataFlow::SourceNode succ, string prop) {
any(SharedTypeTrackingStep s).storeStep(pred, succ, prop)
}
/**
* Holds if type-tracking should step from the `prop` property of `pred` to `succ`.
*/
predicate loadStep(DataFlow::Node pred, DataFlow::Node succ, string prop) {
any(SharedTypeTrackingStep s).loadStep(pred, succ, prop)
}
/**
* Holds if type-tracking should step from the `prop` property of `pred` to the same property in `succ`.
*/
predicate loadStoreStep(DataFlow::Node pred, DataFlow::SourceNode succ, string prop) {
any(SharedTypeTrackingStep s).loadStoreStep(pred, succ, prop)
}
}
/**
* DEPRECATED. Use `SharedTypeTrackingStep` instead.
*
* A data flow edge that should be followed by type tracking.
*
* Unlike `AdditionalFlowStep`, this type of edge does not affect
* the local data flow graph, and is not used by data-flow configurations.
*
* Note: For performance reasons, all subclasses of this class should be part
* of the standard library. For query-specific steps, consider including the
* custom steps in the type-tracking predicate itself.
*/
deprecated class AdditionalTypeTrackingStep = LegacyTypeTrackingStep;
// Internal version of AdditionalTypeTrackingStep that we can reference without deprecation warnings.
abstract private class LegacyTypeTrackingStep extends DataFlow::Node {
/**
* Holds if type-tracking should step from `pred` to `succ`.
*/
predicate step(DataFlow::Node pred, DataFlow::Node succ) { none() }
/**
* Holds if type-tracking should step from `pred` into the `prop` property of `succ`.
*/
predicate storeStep(DataFlow::Node pred, DataFlow::SourceNode succ, string prop) { none() }
/**
* Holds if type-tracking should step from the `prop` property of `pred` to `succ`.
*/
predicate loadStep(DataFlow::Node pred, DataFlow::Node succ, string prop) { none() }
/**
* Holds if type-tracking should step from the `prop` property of `pred` to the same property in `succ`.
*/
predicate loadStoreStep(DataFlow::Node pred, DataFlow::SourceNode succ, string prop) { none() }
}
private class LegacyStepAsSharedTypeTrackingStep extends SharedTypeTrackingStep {
override predicate step(DataFlow::Node pred, DataFlow::Node succ) {
any(LegacyTypeTrackingStep s).step(pred, succ)
}
override predicate storeStep(DataFlow::Node pred, DataFlow::SourceNode succ, string prop) {
any(LegacyTypeTrackingStep s).storeStep(pred, succ, prop)
}
override predicate loadStep(DataFlow::Node pred, DataFlow::Node succ, string prop) {
any(LegacyTypeTrackingStep s).loadStep(pred, succ, prop)
}
override predicate loadStoreStep(DataFlow::Node pred, DataFlow::SourceNode succ, string prop) {
any(LegacyTypeTrackingStep s).loadStoreStep(pred, succ, prop)
}
}

View File

@@ -16,7 +16,7 @@ private class Unit extends TUnit {
* Internal extension point for adding flow edges prior to call graph construction
* and type tracking.
*
* Steps added here will be added to both `AdditionalFlowStep` and `AdditionalTypeTrackingStep`.
* Steps added here will be added to both `SharedFlowStep` and `SharedTypeTrackingStep`.
*
* Contributing steps that rely on type tracking will lead to negative recursion.
*/
@@ -77,18 +77,6 @@ module PreCallGraphStep {
}
}
private class NodeWithPreCallGraphStep extends DataFlow::Node {
NodeWithPreCallGraphStep() {
PreCallGraphStep::step(this, _)
or
PreCallGraphStep::storeStep(this, _, _)
or
PreCallGraphStep::loadStep(this, _, _)
or
PreCallGraphStep::loadStoreStep(this, _, _)
}
}
private class SharedFlowStepFromPreCallGraph extends DataFlow::SharedFlowStep {
override predicate step(DataFlow::Node pred, DataFlow::Node succ) {
PreCallGraphStep::step(pred, succ)
@@ -107,25 +95,20 @@ private class SharedFlowStepFromPreCallGraph extends DataFlow::SharedFlowStep {
}
}
private class AdditionalTypeTrackingStepFromPreCallGraph extends NodeWithPreCallGraphStep,
DataFlow::AdditionalTypeTrackingStep {
private class SharedTypeTrackingStepFromPreCallGraph extends DataFlow::SharedTypeTrackingStep {
override predicate step(DataFlow::Node pred, DataFlow::Node succ) {
pred = this and
PreCallGraphStep::step(this, succ)
PreCallGraphStep::step(pred, succ)
}
override predicate storeStep(DataFlow::Node pred, DataFlow::SourceNode succ, string prop) {
pred = this and
PreCallGraphStep::storeStep(this, succ, prop)
PreCallGraphStep::storeStep(pred, succ, prop)
}
override predicate loadStep(DataFlow::Node pred, DataFlow::Node succ, string prop) {
pred = this and
PreCallGraphStep::loadStep(this, succ, prop)
PreCallGraphStep::loadStep(pred, succ, prop)
}
override predicate loadStoreStep(DataFlow::Node pred, DataFlow::SourceNode succ, string prop) {
pred = this and
PreCallGraphStep::loadStoreStep(this, succ, prop)
PreCallGraphStep::loadStoreStep(pred, succ, prop)
}
}

View File

@@ -111,17 +111,17 @@ module StepSummary {
basicLoadStep(pred, succ, prop) and
summary = LoadStep(prop)
or
any(AdditionalTypeTrackingStep st).storeStep(pred, succ, prop) and
SharedTypeTrackingStep::storeStep(pred, succ, prop) and
summary = StoreStep(prop)
or
any(AdditionalTypeTrackingStep st).loadStep(pred, succ, prop) and
SharedTypeTrackingStep::loadStep(pred, succ, prop) and
summary = LoadStep(prop)
or
any(AdditionalTypeTrackingStep st).loadStoreStep(pred, succ, prop) and
SharedTypeTrackingStep::loadStoreStep(pred, succ, prop) and
summary = CopyStep(prop)
)
or
any(AdditionalTypeTrackingStep st).step(pred, succ) and
SharedTypeTrackingStep::step(pred, succ) and
summary = LevelStep()
or
// Store to global access path