mirror of
https://github.com/github/codeql.git
synced 2025-12-21 19:26:31 +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.
|
||||
*/
|
||||
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.
|
||||
* 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, "")
|
||||
or
|
||||
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. */
|
||||
@@ -373,6 +379,26 @@ class SharedTypeTrackingStep extends Unit {
|
||||
) {
|
||||
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`. */
|
||||
@@ -413,6 +439,15 @@ module SharedTypeTrackingStep {
|
||||
) {
|
||||
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
|
||||
LoadStoreStep(PropertyName fromProp, PropertyName toProp) {
|
||||
SharedTypeTrackingStep::loadStoreStep(_, _, fromProp, toProp)
|
||||
}
|
||||
} or
|
||||
WithoutPropStep(PropertySet props) { SharedTypeTrackingStep::withoutPropStep(_, _, props) }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -110,6 +111,11 @@ private module Cached {
|
||||
summary = CopyStep(prop)
|
||||
)
|
||||
or
|
||||
exists(PropertySet props |
|
||||
SharedTypeTrackingStep::withoutPropStep(pred, succ, props) and
|
||||
summary = WithoutPropStep(props)
|
||||
)
|
||||
or
|
||||
exists(string fromProp, string toProp |
|
||||
SharedTypeTrackingStep::loadStoreStep(pred, succ, fromProp, toProp) and
|
||||
summary = LoadStoreStep(fromProp, toProp)
|
||||
@@ -194,6 +200,8 @@ class StepSummary extends TStepSummary {
|
||||
or
|
||||
exists(string prop | this = CopyStep(prop) | result = "copy " + prop)
|
||||
or
|
||||
exists(string prop | this = WithoutPropStep(prop) | result = "without " + prop)
|
||||
or
|
||||
exists(string fromProp, string toProp | this = LoadStoreStep(fromProp, toProp) |
|
||||
result = "load " + fromProp + " and store to " + toProp
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user