mirror of
https://github.com/github/codeql.git
synced 2026-05-02 04:05:14 +02:00
JavaScript: Switch from path summaries to step summaries for type tracking.
This is sufficient since we are not doing summarisation.
This commit is contained in:
@@ -10,81 +10,60 @@ import javascript
|
||||
private import internal.FlowSteps
|
||||
|
||||
/**
|
||||
* A pair of booleans, indicating whether a path goes through a return and/or a call.
|
||||
*
|
||||
* Identical to `TPathSummary` except without flow labels.
|
||||
* A description of a step on an inter-procedural data flow path.
|
||||
*/
|
||||
private newtype TStepSummary = MkStepSummary(Boolean hasReturn, Boolean hasCall)
|
||||
private newtype TStepSummary =
|
||||
LevelStep() or
|
||||
CallStep() or
|
||||
ReturnStep()
|
||||
|
||||
/**
|
||||
* INTERNAL: Use `TypeTracker` or `TypeBackTracker` instead.
|
||||
*
|
||||
* Summary of the steps needed to track a value to a given dataflow node.
|
||||
* A description of a step on an inter-procedural data flow path.
|
||||
*/
|
||||
class StepSummary extends TStepSummary {
|
||||
Boolean hasReturn;
|
||||
/** Indicates whether the step represented by this summary is a return. */
|
||||
boolean hasReturn() { if this instanceof ReturnStep then result = true else result = false }
|
||||
|
||||
Boolean hasCall;
|
||||
/** Indicates whether the step represented by this summary is a call. */
|
||||
boolean hasCall() { if this instanceof CallStep then result = true else result = false }
|
||||
|
||||
StepSummary() { this = MkStepSummary(hasReturn, hasCall) }
|
||||
|
||||
/** Indicates whether the path represented by this summary contains any return steps. */
|
||||
boolean hasReturn() { result = hasReturn }
|
||||
|
||||
/** Indicates whether the path represented by this summary contains any call steps. */
|
||||
boolean hasCall() { result = hasCall }
|
||||
|
||||
/** Gets a textual representation of this path summary. */
|
||||
/** Gets a textual representation of this step summary. */
|
||||
string toString() {
|
||||
exists(string withReturn, string withCall |
|
||||
(if hasReturn = true then withReturn = "with" else withReturn = "without") and
|
||||
(if hasCall = true then withCall = "with" else withCall = "without")
|
||||
|
|
||||
result = "path " + withReturn + " return steps and " + withCall + " call steps"
|
||||
)
|
||||
this instanceof LevelStep and result = "level"
|
||||
or
|
||||
this instanceof CallStep and result = "call"
|
||||
or
|
||||
this instanceof ReturnStep and result = "return"
|
||||
}
|
||||
}
|
||||
|
||||
module StepSummary {
|
||||
/**
|
||||
* Gets a summary describing a path without any calls or returns.
|
||||
*/
|
||||
StepSummary level() { result = MkStepSummary(false, false) }
|
||||
|
||||
/**
|
||||
* Gets a summary describing a path with one or more calls, but no returns.
|
||||
*/
|
||||
StepSummary call() { result = MkStepSummary(false, true) }
|
||||
|
||||
/**
|
||||
* Gets a summary describing a path with one or more returns, but no calls.
|
||||
*/
|
||||
StepSummary return() { result = MkStepSummary(true, false) }
|
||||
|
||||
/**
|
||||
* INTERNAL: Use `SourceNode.track()` or `SourceNode.backtrack()` instead.
|
||||
*/
|
||||
predicate step(DataFlow::SourceNode pred, DataFlow::SourceNode succ, StepSummary summary) {
|
||||
exists (DataFlow::Node predNode | pred.flowsTo(predNode) |
|
||||
exists(DataFlow::Node predNode | pred.flowsTo(predNode) |
|
||||
// Flow through properties of objects
|
||||
propertyFlowStep(predNode, succ) and
|
||||
summary = level()
|
||||
summary = LevelStep()
|
||||
or
|
||||
// Flow through global variables
|
||||
globalFlowStep(predNode, succ) and
|
||||
summary = level()
|
||||
summary = LevelStep()
|
||||
or
|
||||
// Flow into function
|
||||
callStep(predNode, succ) and
|
||||
summary = call()
|
||||
summary = CallStep()
|
||||
or
|
||||
// Flow out of function
|
||||
returnStep(predNode, succ) and
|
||||
summary = return()
|
||||
summary = ReturnStep()
|
||||
or
|
||||
// Flow through an instance field between members of the same class
|
||||
DataFlow::localFieldStep(predNode, succ) and
|
||||
summary = level()
|
||||
summary = LevelStep()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -153,18 +132,14 @@ class TypeTracker extends TTypeTracker {
|
||||
/**
|
||||
* Holds if this is the starting point of type tracking.
|
||||
*/
|
||||
predicate start() {
|
||||
hasCall = false
|
||||
}
|
||||
predicate start() { hasCall = false }
|
||||
|
||||
/**
|
||||
* INTERNAL. DO NOT USE.
|
||||
*
|
||||
* Holds if this type has been tracked into a call.
|
||||
*/
|
||||
boolean hasCall() {
|
||||
result = hasCall
|
||||
}
|
||||
boolean hasCall() { result = hasCall }
|
||||
}
|
||||
|
||||
private newtype TTypeBackTracker = MkTypeBackTracker(Boolean hasReturn)
|
||||
@@ -210,16 +185,12 @@ class TypeBackTracker extends TTypeBackTracker {
|
||||
/**
|
||||
* Holds if this is the starting point of type tracking.
|
||||
*/
|
||||
predicate start() {
|
||||
hasReturn = false
|
||||
}
|
||||
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
|
||||
}
|
||||
boolean hasReturn() { result = hasReturn }
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ apiObject
|
||||
connection
|
||||
| type tracker with call steps | tst.js:6:15:6:18 | conn |
|
||||
| type tracker with call steps | tst.js:10:5:10:19 | this.connection |
|
||||
| type tracker with call steps with property connection | tst.js:6:14:6:13 | this |
|
||||
| type tracker without call steps | tst.js:15:10:15:49 | api.cha ... ction() |
|
||||
| type tracker without call steps | tst.js:18:7:18:21 | getConnection() |
|
||||
| type tracker without call steps | tst.js:30:9:30:23 | getConnection() |
|
||||
|
||||
Reference in New Issue
Block a user