mirror of
https://github.com/github/codeql.git
synced 2026-05-02 04:05:14 +02:00
JS: Make separate type for back-tracking types
This commit is contained in:
@@ -160,19 +160,24 @@ class SourceNode extends DataFlow::Node {
|
||||
*
|
||||
* See `TypeTracker` for more details about how to use this.
|
||||
*/
|
||||
DataFlow::SourceNode track(TypeTracker src, TypeTracker dst) {
|
||||
DataFlow::SourceNode track(TypeTracker t2, TypeTracker t) {
|
||||
exists(StepSummary summary |
|
||||
StepSummary::step(this, result, summary) and
|
||||
dst = StepSummary::append(src, summary)
|
||||
t = StepSummary::append(t2, summary)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a node that may flow into this one using one heap and/or interprocedural step.
|
||||
*
|
||||
* See `TypeTracker` for more details about how to use this.
|
||||
* See `TypeBackTracker` for more details about how to use this.
|
||||
*/
|
||||
DataFlow::SourceNode backtrack(TypeTracker src, TypeTracker dst) { this = result.track(src, dst) }
|
||||
DataFlow::SourceNode backtrack(TypeBackTracker t2, TypeBackTracker t) {
|
||||
exists(StepSummary summary |
|
||||
StepSummary::step(result, this, summary) and
|
||||
t = StepSummary::prepend(summary, t2)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
module SourceNode {
|
||||
|
||||
@@ -118,6 +118,16 @@ module StepSummary {
|
||||
not (type.hasCall() = true and summary.hasReturn() = true) and
|
||||
result.hasCall() = type.hasCall().booleanOr(summary.hasCall())
|
||||
}
|
||||
|
||||
/**
|
||||
* INTERNAL. Do not use.
|
||||
*
|
||||
* Prepends a step summary before a backwards type-tracking summary.
|
||||
*/
|
||||
TypeBackTracker prepend(StepSummary summary, TypeBackTracker type) {
|
||||
not (type.hasReturn() = true and summary.hasCall() = true) and
|
||||
result.hasReturn() = type.hasReturn().booleanOr(summary.hasReturn())
|
||||
}
|
||||
}
|
||||
|
||||
private newtype TTypeTracker = MkTypeTracker(boolean hasCall) {
|
||||
@@ -147,9 +157,8 @@ private newtype TTypeTracker = MkTypeTracker(boolean hasCall) {
|
||||
* DataFlow::SourceNode myType() { result = myType(_) }
|
||||
* ```
|
||||
*
|
||||
* This class can also be used to track values backwards, which can be useful for tracking
|
||||
* the type of a callback. To do so, use the example above except with `.track`
|
||||
* replaced with `.backtrack`.
|
||||
* To track values backwards, which can be useful for tracking
|
||||
* the type of a callback, use the `TypeBackTracker` class instead.
|
||||
*/
|
||||
class TypeTracker extends TTypeTracker {
|
||||
Boolean hasCall;
|
||||
@@ -178,3 +187,60 @@ class TypeTracker extends TTypeTracker {
|
||||
result = hasCall
|
||||
}
|
||||
}
|
||||
|
||||
private newtype TTypeBackTracker = MkTypeBackTracker(boolean hasReturn) {
|
||||
hasReturn = true or hasReturn = false
|
||||
}
|
||||
|
||||
/**
|
||||
* Summary of the steps needed to back-track a use of a value to a given dataflow node.
|
||||
*
|
||||
* This can be used to track callbacks that are passed to a certian API call, and are
|
||||
* therefore expected to called with a certain type of value.
|
||||
*
|
||||
* Note that type back-tracking does not provide a source/sink relation, that is,
|
||||
* it may determine that a node will be used in an API call somwwhere, but it won't
|
||||
* determine exactly where that use was, or the path that led to the use.
|
||||
*
|
||||
* It is recommended that all uses of this type is written on the following form,
|
||||
* for back-tracking some callback type `myCallback`:
|
||||
* ```
|
||||
* DataFlow::SourceNode myCallback(DataFlow::TypeBackTracker t) {
|
||||
* t.start() and
|
||||
* result = (< some API call >).getParameter(< n >).getALocalSource()
|
||||
* or
|
||||
* exists (DataFlow::TypeTracker t2 |
|
||||
* result = myCallback(t2).backtrack(t2, t)
|
||||
* )
|
||||
* }
|
||||
*
|
||||
* DataFlow::SourceNode myCallback() { result = myCallback(_) }
|
||||
* ```
|
||||
*/
|
||||
class TypeBackTracker extends TTypeBackTracker {
|
||||
Boolean hasReturn;
|
||||
|
||||
TypeBackTracker() { this = MkTypeBackTracker(hasReturn) }
|
||||
|
||||
string toString() {
|
||||
hasReturn = true and result = "type back-tracker with return steps"
|
||||
or
|
||||
hasReturn = false and result = "type back-tracker without return steps"
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if this is the starting point of type tracking.
|
||||
*/
|
||||
predicate start() {
|
||||
hasReturn = false
|
||||
}
|
||||
|
||||
/**
|
||||
* INTERNAL. DO NOT USE.
|
||||
*
|
||||
* Holds if this type has been back-tracked into a call through return edge.
|
||||
*/
|
||||
boolean hasReturn() {
|
||||
result = hasReturn
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user