mirror of
https://github.com/github/codeql.git
synced 2026-04-22 15:25:18 +02:00
JS: Generate summaries from summaryModel, and only generate steps as a fallback
This commit is contained in:
@@ -264,3 +264,7 @@ module Stage {
|
||||
cached
|
||||
predicate backref() { optionalStep(_, _, _) }
|
||||
}
|
||||
|
||||
predicate unsupportedCallable = Private::unsupportedCallable/1;
|
||||
|
||||
predicate unsupportedCallable = Private::unsupportedCallable/4;
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
private import javascript
|
||||
private import internal.ApiGraphModels as Shared
|
||||
private import internal.ApiGraphModelsSpecific as Specific
|
||||
private import semmle.javascript.dataflow.internal.FlowSummaryPrivate
|
||||
private import semmle.javascript.endpoints.EndpointNaming as EndpointNaming
|
||||
import Shared::ModelInput as ModelInput
|
||||
import Shared::ModelOutput as ModelOutput
|
||||
@@ -45,12 +46,50 @@ private class ThreatModelSourceFromDataExtension extends ThreatModelSource::Rang
|
||||
}
|
||||
}
|
||||
|
||||
private class SummarizedCallableFromModel extends DataFlow::SummarizedCallable {
|
||||
string type;
|
||||
string path;
|
||||
|
||||
SummarizedCallableFromModel() {
|
||||
ModelOutput::relevantSummaryModel(type, path, _, _, _, _) and
|
||||
this = type + ";" + path
|
||||
}
|
||||
|
||||
override DataFlow::InvokeNode getACall() { ModelOutput::resolvedSummaryBase(type, path, result) }
|
||||
|
||||
override predicate propagatesFlow(
|
||||
string input, string output, boolean preservesValue, string model
|
||||
) {
|
||||
exists(string kind | ModelOutput::relevantSummaryModel(type, path, input, output, kind, model) |
|
||||
kind = "value" and
|
||||
preservesValue = true
|
||||
or
|
||||
kind = "taint" and
|
||||
preservesValue = false
|
||||
)
|
||||
}
|
||||
|
||||
predicate hasTypeAndPath(string type_, string path_) { type = type_ and path = path_ }
|
||||
|
||||
predicate isUnsupportedByFlowSummaries() { unsupportedCallable(this) }
|
||||
}
|
||||
|
||||
private predicate shouldInduceStepsFromSummary(string type, string path) {
|
||||
exists(SummarizedCallableFromModel callable |
|
||||
callable.isUnsupportedByFlowSummaries() and
|
||||
callable.hasTypeAndPath(type, path)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `path` is an input or output spec for a summary with the given `base` node.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
private predicate relevantInputOutputPath(API::InvokeNode base, AccessPath inputOrOutput) {
|
||||
exists(string type, string input, string output, string path |
|
||||
// If the summary for 'callable' could not be handled as a flow summary, we need to evaluate
|
||||
// its inputs and outputs to a set of nodes, so we can generate steps instead.
|
||||
shouldInduceStepsFromSummary(type, path) and
|
||||
ModelOutput::resolvedSummaryBase(type, path, base) and
|
||||
ModelOutput::relevantSummaryModel(type, path, input, output, _, _) and
|
||||
inputOrOutput = [input, output]
|
||||
@@ -81,6 +120,7 @@ private API::Node getNodeFromInputOutputPath(API::InvokeNode baseNode, AccessPat
|
||||
|
||||
private predicate summaryStep(API::Node pred, API::Node succ, string kind) {
|
||||
exists(string type, string path, API::InvokeNode base, AccessPath input, AccessPath output |
|
||||
shouldInduceStepsFromSummary(type, path) and
|
||||
ModelOutput::relevantSummaryModel(type, path, input, output, kind, _) and
|
||||
ModelOutput::resolvedSummaryBase(type, path, base) and
|
||||
pred = getNodeFromInputOutputPath(base, input) and
|
||||
|
||||
@@ -39,7 +39,7 @@ function strToStr() {
|
||||
}
|
||||
|
||||
function strToArray() {
|
||||
sink(s.chop(source("s1"), 3)); // $ MISSING: hasTaintFlow=s1
|
||||
sink(s.chop(source("s1"), 3)); // $ hasTaintFlow=s1
|
||||
sink(s.chars(source("s2"))[0]); // $ hasTaintFlow=s2
|
||||
sink(s.words(source("s3"))[0]); // $ hasTaintFlow=s3
|
||||
sink(s.lines(source("s7"))[0]); // $ hasTaintFlow=s7
|
||||
@@ -97,7 +97,7 @@ function multiSource() {
|
||||
|
||||
function chaining() {
|
||||
sink(s(source("s1"))
|
||||
.slugify().capitalize().decapitalize().clean().cleanDiacritics()
|
||||
.slugify().capitalize().decapitalize().clean().cleanDiacritics()
|
||||
.swapCase().escapeHTML().unescapeHTML().wrap().dedent()
|
||||
.reverse().pred().succ().titleize().camelize().classify()
|
||||
.underscored().dasherize().humanize().trim().ltrim().rtrim()
|
||||
@@ -119,8 +119,8 @@ function chaining() {
|
||||
.q(source("s17")).ljust(10, source("s18"))
|
||||
.rjust(10, source("s19"))); // $ hasTaintFlow=s16 hasTaintFlow=s17 hasTaintFlow=s18 hasTaintFlow=s19
|
||||
|
||||
sink(s(source("s20")).tap(function(value) {
|
||||
return value + source("s21");
|
||||
sink(s(source("s20")).tap(function(value) {
|
||||
return value + source("s21");
|
||||
}).value()); // $ hasTaintFlow=s20 hasTaintFlow=s21
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user