Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions javascript/ql/src/semmle/javascript/PackageExports.qll
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,14 @@
*/

import javascript
private import semmle.javascript.internal.CachedStages

/**
* Gets a parameter that is a library input to a top-level package.
*/
cached
DataFlow::ParameterNode getALibraryInputParameter() {
Stages::Taint::ref() and
exists(int bound, DataFlow::FunctionNode func |
func = getAValueExportedByPackage().getABoundFunctionValue(bound) and
result = func.getParameter(any(int arg | arg >= bound))
Expand Down
4 changes: 4 additions & 0 deletions javascript/ql/src/semmle/javascript/dataflow/DataFlow.qll
Original file line number Diff line number Diff line change
Expand Up @@ -255,7 +255,9 @@ module DataFlow {
* Holds if this node is annotated with the given named type,
* or is declared as a subtype thereof, or is a union or intersection containing such a type.
*/
cached
predicate hasUnderlyingType(string globalName) {
Stages::TypeTracking::ref() and
getType().hasUnderlyingType(globalName)
or
getFallbackTypeAnnotation().getAnUnderlyingType().hasQualifiedName(globalName)
Expand All @@ -265,7 +267,9 @@ module DataFlow {
* Holds if this node is annotated with the given named type,
* or is declared as a subtype thereof, or is a union or intersection containing such a type.
*/
cached
predicate hasUnderlyingType(string moduleName, string typeName) {
Stages::TypeTracking::ref() and
getType().hasUnderlyingType(moduleName, typeName)
or
getFallbackTypeAnnotation().getAnUnderlyingType().hasQualifiedName(moduleName, typeName)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,49 +53,11 @@ private module Cached {
predicate step(DataFlow::SourceNode pred, DataFlow::SourceNode succ, StepSummary summary) {
exists(DataFlow::Node mid | pred.flowsTo(mid) | StepSummary::smallstep(mid, succ, summary))
}
}

import Cached::Public

class OptionalPropertyName extends string {
OptionalPropertyName() { this instanceof PropertyName or this = "" }
}

/**
* INTERNAL: Use `TypeTracker` or `TypeBackTracker` instead.
*
* A description of a step on an inter-procedural data flow path.
*/
class StepSummary extends TStepSummary {
/** Gets a textual representation of this step summary. */
string toString() {
this instanceof LevelStep and result = "level"
or
this instanceof CallStep and result = "call"
or
this instanceof ReturnStep and result = "return"
or
exists(string prop | this = StoreStep(prop) | result = "store " + prop)
or
exists(string prop | this = LoadStep(prop) | result = "load " + prop)
or
exists(string prop | this = CopyStep(prop) | result = "copy " + prop)
or
exists(string fromProp, string toProp | this = LoadStoreStep(fromProp, toProp) |
result = "load " + fromProp + " and store to " + toProp
)
}
}

module StepSummary {
/**
* INTERNAL: Use `SourceNode.track()` or `SourceNode.backtrack()` instead.
*/
predicate step = Cached::step/3;

/**
* INTERNAL: Use `TypeBackTracker.smallstep()` instead.
*/
cached
predicate smallstep(DataFlow::Node pred, DataFlow::Node succ, StepSummary summary) {
// Flow through properties of objects
propertyFlowStep(pred, succ) and
Expand Down Expand Up @@ -194,3 +156,47 @@ module StepSummary {
)
}
}

import Cached::Public

class OptionalPropertyName extends string {
OptionalPropertyName() { this instanceof PropertyName or this = "" }
}

/**
* INTERNAL: Use `TypeTracker` or `TypeBackTracker` instead.
*
* A description of a step on an inter-procedural data flow path.
*/
class StepSummary extends TStepSummary {
/** Gets a textual representation of this step summary. */
string toString() {
this instanceof LevelStep and result = "level"
or
this instanceof CallStep and result = "call"
or
this instanceof ReturnStep and result = "return"
or
exists(string prop | this = StoreStep(prop) | result = "store " + prop)
or
exists(string prop | this = LoadStep(prop) | result = "load " + prop)
or
exists(string prop | this = CopyStep(prop) | result = "copy " + prop)
or
exists(string fromProp, string toProp | this = LoadStoreStep(fromProp, toProp) |
result = "load " + fromProp + " and store to " + toProp
)
}
}

module StepSummary {
/**
* INTERNAL: Use `SourceNode.track()` or `SourceNode.backtrack()` instead.
*/
predicate step = Cached::step/3;

/**
* INTERNAL: Use `TypeBackTracker.smallstep()` instead.
*/
predicate smallstep = Cached::smallstep/3;
}
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,10 @@ module Stages {
exists(any(DataFlow::TypeBackTracker t).prepend(_))
or
DataFlow::functionForwardingStep(_, _)
or
any(DataFlow::Node node).hasUnderlyingType(_)
or
any(DataFlow::Node node).hasUnderlyingType(_, _)
}
}

Expand Down Expand Up @@ -232,6 +236,8 @@ module Stages {
*/
cached
module Taint {
private import semmle.javascript.PackageExports as Exports

/**
* Always holds.
* Ensures that a predicate is evaluated as part of the Taint stage.
Expand All @@ -250,6 +256,8 @@ module Stages {
TaintTracking::heapStep(_, _)
or
exists(RemoteFlowSource r)
or
exists(Exports::getALibraryInputParameter())
}
}
}