mirror of
https://github.com/github/codeql.git
synced 2025-12-18 01:33:15 +01:00
JS: add two-prop version of loadStoreStep and infer pseudo properties
Initial step towards migrating CollectionFlowStep to PreCallGraphStep
This commit is contained in:
@@ -10,18 +10,12 @@ private import DataFlow::PseudoProperties
|
||||
|
||||
/**
|
||||
* A pseudo-property used in a data-flow/type-tracking step for collections.
|
||||
*
|
||||
* By extending `TypeTrackingPseudoProperty` the class enables the use of the collection related pseudo-properties in type-tracking predicates.
|
||||
*/
|
||||
private class PseudoProperty extends TypeTrackingPseudoProperty {
|
||||
private class PseudoProperty extends string {
|
||||
PseudoProperty() {
|
||||
this = [arrayLikeElement(), "1"] or // the "1" is required for the `ForOfStep`.
|
||||
this = any(CollectionDataFlow::MapSet step).getAPseudoProperty()
|
||||
}
|
||||
|
||||
override PseudoProperty getLoadStoreToProp() {
|
||||
exists(CollectionFlowStep step | step.loadStore(_, _, this, result))
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -214,13 +214,6 @@ module PromiseTypeTracking {
|
||||
result = PromiseTypeTracking::promiseStep(mid, summary)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* A class enabling the use of the `resolveField` as a pseudo-property in type-tracking predicates.
|
||||
*/
|
||||
private class ResolveFieldAsTypeTrackingProperty extends TypeTrackingPseudoProperty {
|
||||
ResolveFieldAsTypeTrackingProperty() { this = Promises::valueProp() }
|
||||
}
|
||||
}
|
||||
|
||||
private import semmle.javascript.dataflow.internal.PreCallGraphStep
|
||||
|
||||
@@ -358,6 +358,15 @@ class SharedTypeTrackingStep extends Unit {
|
||||
* 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() }
|
||||
|
||||
/**
|
||||
* Holds if type-tracking should step from the `loadProp` property of `pred` to the `storeProp` property in `succ`.
|
||||
*/
|
||||
predicate loadStoreStep(
|
||||
DataFlow::Node pred, DataFlow::SourceNode succ, string loadProp, string storeProp
|
||||
) {
|
||||
none()
|
||||
}
|
||||
}
|
||||
|
||||
/** Provides access to the steps contributed by subclasses of `SharedTypeTrackingStep`. */
|
||||
@@ -389,6 +398,15 @@ module SharedTypeTrackingStep {
|
||||
predicate loadStoreStep(DataFlow::Node pred, DataFlow::SourceNode succ, string prop) {
|
||||
any(SharedTypeTrackingStep s).loadStoreStep(pred, succ, prop)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if type-tracking should step from the `loadProp` property of `pred` to the `storeProp` property in `succ`.
|
||||
*/
|
||||
predicate loadStoreStep(
|
||||
DataFlow::Node pred, DataFlow::SourceNode succ, string loadProp, string storeProp
|
||||
) {
|
||||
any(SharedTypeTrackingStep s).loadStoreStep(pred, succ, loadProp, storeProp)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -40,6 +40,15 @@ class PreCallGraphStep extends Unit {
|
||||
* Holds if there is a step from the `prop` property of `pred` to the same property in `succ`.
|
||||
*/
|
||||
predicate loadStoreStep(DataFlow::Node pred, DataFlow::SourceNode succ, string prop) { none() }
|
||||
|
||||
/**
|
||||
* Holds if there is a step from the `loadProp` property of `pred` to the `storeProp` property in `succ`.
|
||||
*/
|
||||
predicate loadStoreStep(
|
||||
DataFlow::Node pred, DataFlow::SourceNode succ, string loadProp, string storeProp
|
||||
) {
|
||||
none()
|
||||
}
|
||||
}
|
||||
|
||||
module PreCallGraphStep {
|
||||
@@ -75,6 +84,15 @@ module PreCallGraphStep {
|
||||
predicate loadStoreStep(DataFlow::Node pred, DataFlow::SourceNode succ, string prop) {
|
||||
any(PreCallGraphStep s).loadStoreStep(pred, succ, prop)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if there is a step from the `loadProp` property of `pred` to the `storeProp` property in `succ`.
|
||||
*/
|
||||
predicate loadStoreStep(
|
||||
DataFlow::Node pred, DataFlow::SourceNode succ, string loadProp, string storeProp
|
||||
) {
|
||||
any(PreCallGraphStep s).loadStoreStep(pred, succ, loadProp, storeProp)
|
||||
}
|
||||
}
|
||||
|
||||
private class SharedFlowStepFromPreCallGraph extends DataFlow::SharedFlowStep {
|
||||
@@ -93,6 +111,12 @@ private class SharedFlowStepFromPreCallGraph extends DataFlow::SharedFlowStep {
|
||||
override predicate loadStoreStep(DataFlow::Node pred, DataFlow::Node succ, string prop) {
|
||||
PreCallGraphStep::loadStoreStep(pred, succ, prop)
|
||||
}
|
||||
|
||||
override predicate loadStoreStep(
|
||||
DataFlow::Node pred, DataFlow::Node succ, string loadProp, string storeProp
|
||||
) {
|
||||
PreCallGraphStep::loadStoreStep(pred, succ, loadProp, storeProp)
|
||||
}
|
||||
}
|
||||
|
||||
private class SharedTypeTrackingStepFromPreCallGraph extends DataFlow::SharedTypeTrackingStep {
|
||||
@@ -111,4 +135,10 @@ private class SharedTypeTrackingStepFromPreCallGraph extends DataFlow::SharedTyp
|
||||
override predicate loadStoreStep(DataFlow::Node pred, DataFlow::SourceNode succ, string prop) {
|
||||
PreCallGraphStep::loadStoreStep(pred, succ, prop)
|
||||
}
|
||||
|
||||
override predicate loadStoreStep(
|
||||
DataFlow::Node pred, DataFlow::SourceNode succ, string loadProp, string storeProp
|
||||
) {
|
||||
PreCallGraphStep::loadStoreStep(pred, succ, loadProp, storeProp)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,7 +10,13 @@ class PropertyName extends string {
|
||||
or
|
||||
exists(AccessPath::getAnAssignmentTo(_, this))
|
||||
or
|
||||
this instanceof TypeTrackingPseudoProperty
|
||||
SharedTypeTrackingStep::loadStep(_, _, this)
|
||||
or
|
||||
SharedTypeTrackingStep::storeStep(_, _, this)
|
||||
or
|
||||
SharedTypeTrackingStep::loadStoreStep(_, _, this, _)
|
||||
or
|
||||
SharedTypeTrackingStep::loadStoreStep(_, _, _, this)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,19 +24,6 @@ class OptionalPropertyName extends string {
|
||||
OptionalPropertyName() { this instanceof PropertyName or this = "" }
|
||||
}
|
||||
|
||||
/**
|
||||
* A pseudo-property that can be used in type-tracking.
|
||||
*/
|
||||
abstract class TypeTrackingPseudoProperty extends string {
|
||||
bindingset[this]
|
||||
TypeTrackingPseudoProperty() { any() }
|
||||
|
||||
/**
|
||||
* Gets a property name that `this` can be copied to in a `LoadStoreStep(this, result)`.
|
||||
*/
|
||||
string getLoadStoreToProp() { none() }
|
||||
}
|
||||
|
||||
/**
|
||||
* A description of a step on an inter-procedural data flow path.
|
||||
*/
|
||||
@@ -42,7 +35,7 @@ newtype TStepSummary =
|
||||
LoadStep(PropertyName prop) or
|
||||
CopyStep(PropertyName prop) or
|
||||
LoadStoreStep(PropertyName fromProp, PropertyName toProp) {
|
||||
exists(TypeTrackingPseudoProperty prop | fromProp = prop and toProp = prop.getLoadStoreToProp())
|
||||
SharedTypeTrackingStep::loadStoreStep(_, _, fromProp, toProp)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -121,6 +114,11 @@ module StepSummary {
|
||||
summary = CopyStep(prop)
|
||||
)
|
||||
or
|
||||
exists(string fromProp, string toProp |
|
||||
SharedTypeTrackingStep::loadStoreStep(pred, succ, fromProp, toProp) and
|
||||
summary = LoadStoreStep(fromProp, toProp)
|
||||
)
|
||||
or
|
||||
SharedTypeTrackingStep::step(pred, succ) and
|
||||
summary = LevelStep()
|
||||
or
|
||||
|
||||
@@ -708,8 +708,8 @@ module HTTP {
|
||||
override DataFlow::SourceNode getRouteHandler(DataFlow::SourceNode access) {
|
||||
result instanceof RouteHandlerCandidate and
|
||||
exists(
|
||||
DataFlow::Node input, TypeTrackingPseudoProperty key, CollectionFlowStep store,
|
||||
CollectionFlowStep load, DataFlow::Node storeTo, DataFlow::Node loadFrom
|
||||
DataFlow::Node input, string key, CollectionFlowStep store, CollectionFlowStep load,
|
||||
DataFlow::Node storeTo, DataFlow::Node loadFrom
|
||||
|
|
||||
this.flowsTo(storeTo) and
|
||||
store.store(input, storeTo, key) and
|
||||
|
||||
Reference in New Issue
Block a user