mirror of
https://github.com/github/codeql.git
synced 2025-12-21 11:16:30 +01:00
JS: Add withoutPropStep and model 'await' steps with it
This commit is contained in:
@@ -189,6 +189,13 @@ module Promises {
|
|||||||
* Gets the pseudo-field used to describe rejected values in a promise.
|
* Gets the pseudo-field used to describe rejected values in a promise.
|
||||||
*/
|
*/
|
||||||
string errorProp() { result = "$PromiseRejectField$" }
|
string errorProp() { result = "$PromiseRejectField$" }
|
||||||
|
|
||||||
|
/** A property set containing the pseudo-properites of a promise object. */
|
||||||
|
class PromiseProps extends DataFlow::PropertySet {
|
||||||
|
PromiseProps() { this = "PromiseProps" }
|
||||||
|
|
||||||
|
override string getAProperty() { result = [valueProp(), errorProp()] }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -274,6 +281,24 @@ private class PromiseStep extends PreCallGraphStep {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A step from `p -> await p` for the case where `p` is not a promise.
|
||||||
|
*
|
||||||
|
* In this case, `await p` just returns `p` itself. We block flow of the promise-related
|
||||||
|
* pseudo properties through this edge.
|
||||||
|
*/
|
||||||
|
private class RawAwaitStep extends DataFlow::SharedTypeTrackingStep {
|
||||||
|
override predicate withoutPropStep(
|
||||||
|
DataFlow::Node pred, DataFlow::Node succ, DataFlow::PropertySet props
|
||||||
|
) {
|
||||||
|
exists(AwaitExpr await |
|
||||||
|
pred = await.getOperand().flow() and
|
||||||
|
succ = await.flow() and
|
||||||
|
props instanceof Promises::PromiseProps
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This module defines how data-flow propagates into and out of a Promise.
|
* This module defines how data-flow propagates into and out of a Promise.
|
||||||
* The data-flow is based on pseudo-properties rather than tainting the Promise object (which is what `PromiseTaintStep` does).
|
* The data-flow is based on pseudo-properties rather than tainting the Promise object (which is what `PromiseTaintStep` does).
|
||||||
|
|||||||
@@ -70,6 +70,12 @@ class TypeTracker extends TTypeTracker {
|
|||||||
step = LoadStep(prop) and result = MkTypeTracker(hasCall, "")
|
step = LoadStep(prop) and result = MkTypeTracker(hasCall, "")
|
||||||
or
|
or
|
||||||
exists(string p | step = StoreStep(p) and prop = "" and result = MkTypeTracker(hasCall, p))
|
exists(string p | step = StoreStep(p) and prop = "" and result = MkTypeTracker(hasCall, p))
|
||||||
|
or
|
||||||
|
exists(PropertySet props |
|
||||||
|
step = WithoutPropStep(props) and
|
||||||
|
not prop = props.getAProperty() and
|
||||||
|
result = this
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Gets a textual representation of this summary. */
|
/** Gets a textual representation of this summary. */
|
||||||
@@ -373,6 +379,26 @@ class SharedTypeTrackingStep extends Unit {
|
|||||||
) {
|
) {
|
||||||
none()
|
none()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Holds if type-tracking should step from `pred` to `succ` but block flow of `props` through here.
|
||||||
|
*
|
||||||
|
* This can be seen as taking a copy of the value in `pred` but without the properties in `props`.
|
||||||
|
*/
|
||||||
|
predicate withoutPropStep(DataFlow::Node pred, DataFlow::Node succ, PropertySet props) { none() }
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A representative for a set of property names.
|
||||||
|
*
|
||||||
|
* Currently this is used to denote a set of properties in `withoutPropStep`.
|
||||||
|
*/
|
||||||
|
abstract class PropertySet extends string {
|
||||||
|
bindingset[this]
|
||||||
|
PropertySet() { any() }
|
||||||
|
|
||||||
|
/** Gets a property contained in this property set. */
|
||||||
|
abstract string getAProperty();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Provides access to the steps contributed by subclasses of `SharedTypeTrackingStep`. */
|
/** Provides access to the steps contributed by subclasses of `SharedTypeTrackingStep`. */
|
||||||
@@ -413,6 +439,15 @@ module SharedTypeTrackingStep {
|
|||||||
) {
|
) {
|
||||||
any(SharedTypeTrackingStep s).loadStoreStep(pred, succ, loadProp, storeProp)
|
any(SharedTypeTrackingStep s).loadStoreStep(pred, succ, loadProp, storeProp)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Holds if type-tracking should step from `pred` to `succ` but block flow of `prop` through here.
|
||||||
|
*
|
||||||
|
* This can be seen as taking a copy of the value in `pred` but without the properties in `props`.
|
||||||
|
*/
|
||||||
|
predicate withoutPropStep(DataFlow::Node pred, DataFlow::Node succ, PropertySet props) {
|
||||||
|
any(SharedTypeTrackingStep s).withoutPropStep(pred, succ, props)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -45,7 +45,8 @@ private module Cached {
|
|||||||
CopyStep(PropertyName prop) or
|
CopyStep(PropertyName prop) or
|
||||||
LoadStoreStep(PropertyName fromProp, PropertyName toProp) {
|
LoadStoreStep(PropertyName fromProp, PropertyName toProp) {
|
||||||
SharedTypeTrackingStep::loadStoreStep(_, _, fromProp, toProp)
|
SharedTypeTrackingStep::loadStoreStep(_, _, fromProp, toProp)
|
||||||
}
|
} or
|
||||||
|
WithoutPropStep(PropertySet props) { SharedTypeTrackingStep::withoutPropStep(_, _, props) }
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -110,6 +111,11 @@ private module Cached {
|
|||||||
summary = CopyStep(prop)
|
summary = CopyStep(prop)
|
||||||
)
|
)
|
||||||
or
|
or
|
||||||
|
exists(PropertySet props |
|
||||||
|
SharedTypeTrackingStep::withoutPropStep(pred, succ, props) and
|
||||||
|
summary = WithoutPropStep(props)
|
||||||
|
)
|
||||||
|
or
|
||||||
exists(string fromProp, string toProp |
|
exists(string fromProp, string toProp |
|
||||||
SharedTypeTrackingStep::loadStoreStep(pred, succ, fromProp, toProp) and
|
SharedTypeTrackingStep::loadStoreStep(pred, succ, fromProp, toProp) and
|
||||||
summary = LoadStoreStep(fromProp, toProp)
|
summary = LoadStoreStep(fromProp, toProp)
|
||||||
@@ -194,6 +200,8 @@ class StepSummary extends TStepSummary {
|
|||||||
or
|
or
|
||||||
exists(string prop | this = CopyStep(prop) | result = "copy " + prop)
|
exists(string prop | this = CopyStep(prop) | result = "copy " + prop)
|
||||||
or
|
or
|
||||||
|
exists(string prop | this = WithoutPropStep(prop) | result = "without " + prop)
|
||||||
|
or
|
||||||
exists(string fromProp, string toProp | this = LoadStoreStep(fromProp, toProp) |
|
exists(string fromProp, string toProp | this = LoadStoreStep(fromProp, toProp) |
|
||||||
result = "load " + fromProp + " and store to " + toProp
|
result = "load " + fromProp + " and store to " + toProp
|
||||||
)
|
)
|
||||||
|
|||||||
Reference in New Issue
Block a user