mirror of
https://github.com/github/codeql.git
synced 2025-12-17 01:03:14 +01:00
JS: Adapt to changes in shared code
This commit is contained in:
@@ -469,7 +469,6 @@
|
|||||||
"csharp/ql/lib/semmle/code/csharp/dataflow/internal/AccessPathSyntax.qll",
|
"csharp/ql/lib/semmle/code/csharp/dataflow/internal/AccessPathSyntax.qll",
|
||||||
"go/ql/lib/semmle/go/dataflow/internal/AccessPathSyntax.qll",
|
"go/ql/lib/semmle/go/dataflow/internal/AccessPathSyntax.qll",
|
||||||
"java/ql/lib/semmle/code/java/dataflow/internal/AccessPathSyntax.qll",
|
"java/ql/lib/semmle/code/java/dataflow/internal/AccessPathSyntax.qll",
|
||||||
"javascript/ql/lib/semmle/javascript/frameworks/data/internal/AccessPathSyntax.qll",
|
|
||||||
"python/ql/lib/semmle/python/dataflow/new/internal/AccessPathSyntax.qll",
|
"python/ql/lib/semmle/python/dataflow/new/internal/AccessPathSyntax.qll",
|
||||||
"swift/ql/lib/codeql/swift/dataflow/internal/AccessPathSyntax.qll"
|
"swift/ql/lib/codeql/swift/dataflow/internal/AccessPathSyntax.qll"
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ extractor: javascript
|
|||||||
library: true
|
library: true
|
||||||
upgrades: upgrades
|
upgrades: upgrades
|
||||||
dependencies:
|
dependencies:
|
||||||
|
codeql/dataflow: ${workspace}
|
||||||
codeql/mad: ${workspace}
|
codeql/mad: ${workspace}
|
||||||
codeql/regex: ${workspace}
|
codeql/regex: ${workspace}
|
||||||
codeql/tutorial: ${workspace}
|
codeql/tutorial: ${workspace}
|
||||||
|
|||||||
@@ -1,182 +0,0 @@
|
|||||||
/**
|
|
||||||
* Module for parsing access paths from MaD models, both the identifying access path used
|
|
||||||
* by dynamic languages, and the input/output specifications for summary steps.
|
|
||||||
*
|
|
||||||
* This file is used by the shared data flow library and by the JavaScript libraries
|
|
||||||
* (which does not use the shared data flow libraries).
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Convenience-predicate for extracting two capture groups at once.
|
|
||||||
*/
|
|
||||||
bindingset[input, regexp]
|
|
||||||
private predicate regexpCaptureTwo(string input, string regexp, string capture1, string capture2) {
|
|
||||||
capture1 = input.regexpCapture(regexp, 1) and
|
|
||||||
capture2 = input.regexpCapture(regexp, 2)
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Companion module to the `AccessPath` class. */
|
|
||||||
module AccessPath {
|
|
||||||
/** A string that should be parsed as an access path. */
|
|
||||||
abstract class Range extends string {
|
|
||||||
bindingset[this]
|
|
||||||
Range() { any() }
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Parses an integer constant `n` or interval `n1..n2` (inclusive) and gets the value
|
|
||||||
* of the constant or any value contained in the interval.
|
|
||||||
*/
|
|
||||||
bindingset[arg]
|
|
||||||
int parseInt(string arg) {
|
|
||||||
result = arg.toInt()
|
|
||||||
or
|
|
||||||
// Match "n1..n2"
|
|
||||||
exists(string lo, string hi |
|
|
||||||
regexpCaptureTwo(arg, "(-?\\d+)\\.\\.(-?\\d+)", lo, hi) and
|
|
||||||
result = [lo.toInt() .. hi.toInt()]
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Parses a lower-bounded interval `n..` and gets the lower bound.
|
|
||||||
*/
|
|
||||||
bindingset[arg]
|
|
||||||
int parseLowerBound(string arg) { result = arg.regexpCapture("(-?\\d+)\\.\\.", 1).toInt() }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Parses an integer constant or interval (bounded or unbounded) that explicitly
|
|
||||||
* references the arity, such as `N-1` or `N-3..N-1`.
|
|
||||||
*
|
|
||||||
* Note that expressions of form `N-x` will never resolve to a negative index,
|
|
||||||
* even if `N` is zero (it will have no result in that case).
|
|
||||||
*/
|
|
||||||
bindingset[arg, arity]
|
|
||||||
private int parseIntWithExplicitArity(string arg, int arity) {
|
|
||||||
result >= 0 and // do not allow N-1 to resolve to a negative index
|
|
||||||
exists(string lo |
|
|
||||||
// N-x
|
|
||||||
lo = arg.regexpCapture("N-(\\d+)", 1) and
|
|
||||||
result = arity - lo.toInt()
|
|
||||||
or
|
|
||||||
// N-x..
|
|
||||||
lo = arg.regexpCapture("N-(\\d+)\\.\\.", 1) and
|
|
||||||
result = [arity - lo.toInt(), arity - 1]
|
|
||||||
)
|
|
||||||
or
|
|
||||||
exists(string lo, string hi |
|
|
||||||
// x..N-y
|
|
||||||
regexpCaptureTwo(arg, "(-?\\d+)\\.\\.N-(\\d+)", lo, hi) and
|
|
||||||
result = [lo.toInt() .. arity - hi.toInt()]
|
|
||||||
or
|
|
||||||
// N-x..N-y
|
|
||||||
regexpCaptureTwo(arg, "N-(\\d+)\\.\\.N-(\\d+)", lo, hi) and
|
|
||||||
result = [arity - lo.toInt() .. arity - hi.toInt()] and
|
|
||||||
result >= 0
|
|
||||||
or
|
|
||||||
// N-x..y
|
|
||||||
regexpCaptureTwo(arg, "N-(\\d+)\\.\\.(\\d+)", lo, hi) and
|
|
||||||
result = [arity - lo.toInt() .. hi.toInt()] and
|
|
||||||
result >= 0
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Parses an integer constant or interval (bounded or unbounded) and gets any
|
|
||||||
* of the integers contained within (of which there may be infinitely many).
|
|
||||||
*
|
|
||||||
* Has no result for arguments involving an explicit arity, such as `N-1`.
|
|
||||||
*/
|
|
||||||
bindingset[arg, result]
|
|
||||||
int parseIntUnbounded(string arg) {
|
|
||||||
result = parseInt(arg)
|
|
||||||
or
|
|
||||||
result >= parseLowerBound(arg)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Parses an integer constant or interval (bounded or unbounded) that
|
|
||||||
* may reference the arity of a call, such as `N-1` or `N-3..N-1`.
|
|
||||||
*
|
|
||||||
* Note that expressions of form `N-x` will never resolve to a negative index,
|
|
||||||
* even if `N` is zero (it will have no result in that case).
|
|
||||||
*/
|
|
||||||
bindingset[arg, arity]
|
|
||||||
int parseIntWithArity(string arg, int arity) {
|
|
||||||
result = parseInt(arg)
|
|
||||||
or
|
|
||||||
result in [parseLowerBound(arg) .. arity - 1]
|
|
||||||
or
|
|
||||||
result = parseIntWithExplicitArity(arg, arity)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Gets the `n`th token on the access path as a string. */
|
|
||||||
private string getRawToken(AccessPath path, int n) {
|
|
||||||
// Avoid splitting by '.' since tokens may contain dots, e.g. `Field[foo.Bar.x]`.
|
|
||||||
// Instead use regexpFind to match valid tokens, and supplement with a final length
|
|
||||||
// check (in `AccessPath.hasSyntaxError`) to ensure all characters were included in a token.
|
|
||||||
result = path.regexpFind("\\w+(?:\\[[^\\]]*\\])?(?=\\.|$)", n, _)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A string that occurs as an access path (either identifying or input/output spec)
|
|
||||||
* which might be relevant for this database.
|
|
||||||
*/
|
|
||||||
class AccessPath extends string instanceof AccessPath::Range {
|
|
||||||
/** Holds if this string is not a syntactically valid access path. */
|
|
||||||
predicate hasSyntaxError() {
|
|
||||||
// If the lengths match, all characters must haven been included in a token
|
|
||||||
// or seen by the `.` lookahead pattern.
|
|
||||||
this != "" and
|
|
||||||
not this.length() = sum(int n | | getRawToken(this, n).length() + 1) - 1
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Gets the `n`th token on the access path (if there are no syntax errors). */
|
|
||||||
AccessPathToken getToken(int n) {
|
|
||||||
result = getRawToken(this, n) and
|
|
||||||
not this.hasSyntaxError()
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Gets the number of tokens on the path (if there are no syntax errors). */
|
|
||||||
int getNumToken() {
|
|
||||||
result = count(int n | exists(getRawToken(this, n))) and
|
|
||||||
not this.hasSyntaxError()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* An access part token such as `Argument[1]` or `ReturnValue`, appearing in one or more access paths.
|
|
||||||
*/
|
|
||||||
class AccessPathToken extends string {
|
|
||||||
AccessPathToken() { this = getRawToken(_, _) }
|
|
||||||
|
|
||||||
private string getPart(int part) {
|
|
||||||
result = this.regexpCapture("([^\\[]+)(?:\\[([^\\]]*)\\])?", part)
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Gets the name of the token, such as `Member` from `Member[x]` */
|
|
||||||
string getName() { result = this.getPart(1) }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the argument list, such as `1,2` from `Member[1,2]`,
|
|
||||||
* or has no result if there are no arguments.
|
|
||||||
*/
|
|
||||||
string getArgumentList() { result = this.getPart(2) }
|
|
||||||
|
|
||||||
/** Gets the `n`th argument to this token, such as `x` or `y` from `Member[x,y]`. */
|
|
||||||
string getArgument(int n) { result = this.getArgumentList().splitAt(",", n).trim() }
|
|
||||||
|
|
||||||
/** Gets the `n`th argument to this `name` token, such as `x` or `y` from `Member[x,y]`. */
|
|
||||||
pragma[nomagic]
|
|
||||||
string getArgument(string name, int n) { name = this.getName() and result = this.getArgument(n) }
|
|
||||||
|
|
||||||
/** Gets an argument to this token, such as `x` or `y` from `Member[x,y]`. */
|
|
||||||
string getAnArgument() { result = this.getArgument(_) }
|
|
||||||
|
|
||||||
/** Gets an argument to this `name` token, such as `x` or `y` from `Member[x,y]`. */
|
|
||||||
string getAnArgument(string name) { result = this.getArgument(name, _) }
|
|
||||||
|
|
||||||
/** Gets the number of arguments to this token, such as 2 for `Member[x,y]` or zero for `ReturnValue`. */
|
|
||||||
int getNumArgument() { result = count(int n | exists(this.getArgument(n))) }
|
|
||||||
}
|
|
||||||
@@ -70,8 +70,8 @@ private module API = Specific::API;
|
|||||||
|
|
||||||
private module DataFlow = Specific::DataFlow;
|
private module DataFlow = Specific::DataFlow;
|
||||||
|
|
||||||
private import Specific::AccessPathSyntax
|
|
||||||
private import ApiGraphModelsExtensions as Extensions
|
private import ApiGraphModelsExtensions as Extensions
|
||||||
|
import codeql.dataflow.internal.AccessPathSyntax
|
||||||
|
|
||||||
/** Module containing hooks for providing input data to be interpreted as a model. */
|
/** Module containing hooks for providing input data to be interpreted as a model. */
|
||||||
module ModelInput {
|
module ModelInput {
|
||||||
@@ -327,29 +327,29 @@ predicate isRelevantFullPath(string type, string path) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** A string from a CSV row that should be parsed as an access path. */
|
/** A string from a CSV row that should be parsed as an access path. */
|
||||||
private class AccessPathRange extends AccessPath::Range {
|
private predicate accessPathRange(string s) {
|
||||||
AccessPathRange() {
|
isRelevantFullPath(_, s)
|
||||||
isRelevantFullPath(_, this)
|
or
|
||||||
or
|
exists(string type | isRelevantType(type) |
|
||||||
exists(string type | isRelevantType(type) |
|
summaryModel(type, _, s, _, _) or
|
||||||
summaryModel(type, _, this, _, _) or
|
summaryModel(type, _, _, s, _)
|
||||||
summaryModel(type, _, _, this, _)
|
)
|
||||||
)
|
or
|
||||||
or
|
typeVariableModel(_, s)
|
||||||
typeVariableModel(_, this)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
import AccessPath<accessPathRange/1>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets a successor of `node` in the API graph.
|
* Gets a successor of `node` in the API graph.
|
||||||
*/
|
*/
|
||||||
bindingset[token]
|
bindingset[token]
|
||||||
API::Node getSuccessorFromNode(API::Node node, AccessPathToken token) {
|
API::Node getSuccessorFromNode(API::Node node, AccessPathTokenBase token) {
|
||||||
// API graphs use the same label for arguments and parameters. An edge originating from a
|
// API graphs use the same label for arguments and parameters. An edge originating from a
|
||||||
// use-node represents an argument, and an edge originating from a def-node represents a parameter.
|
// use-node represents an argument, and an edge originating from a def-node represents a parameter.
|
||||||
// We just map both to the same thing.
|
// We just map both to the same thing.
|
||||||
token.getName() = ["Argument", "Parameter"] and
|
token.getName() = ["Argument", "Parameter"] and
|
||||||
result = node.getParameter(AccessPath::parseIntUnbounded(token.getAnArgument()))
|
result = node.getParameter(parseIntUnbounded(token.getAnArgument()))
|
||||||
or
|
or
|
||||||
token.getName() = "ReturnValue" and
|
token.getName() = "ReturnValue" and
|
||||||
result = node.getReturn()
|
result = node.getReturn()
|
||||||
@@ -362,11 +362,9 @@ API::Node getSuccessorFromNode(API::Node node, AccessPathToken token) {
|
|||||||
* Gets an API-graph successor for the given invocation.
|
* Gets an API-graph successor for the given invocation.
|
||||||
*/
|
*/
|
||||||
bindingset[token]
|
bindingset[token]
|
||||||
API::Node getSuccessorFromInvoke(Specific::InvokeNode invoke, AccessPathToken token) {
|
API::Node getSuccessorFromInvoke(Specific::InvokeNode invoke, AccessPathTokenBase token) {
|
||||||
token.getName() = "Argument" and
|
token.getName() = "Argument" and
|
||||||
result =
|
result = invoke.getParameter(parseIntWithArity(token.getAnArgument(), invoke.getNumArgument()))
|
||||||
invoke
|
|
||||||
.getParameter(AccessPath::parseIntWithArity(token.getAnArgument(), invoke.getNumArgument()))
|
|
||||||
or
|
or
|
||||||
token.getName() = "ReturnValue" and
|
token.getName() = "ReturnValue" and
|
||||||
result = invoke.getReturn()
|
result = invoke.getReturn()
|
||||||
@@ -378,10 +376,12 @@ API::Node getSuccessorFromInvoke(Specific::InvokeNode invoke, AccessPathToken to
|
|||||||
/**
|
/**
|
||||||
* Holds if `invoke` invokes a call-site filter given by `token`.
|
* Holds if `invoke` invokes a call-site filter given by `token`.
|
||||||
*/
|
*/
|
||||||
pragma[inline]
|
bindingset[token]
|
||||||
private predicate invocationMatchesCallSiteFilter(Specific::InvokeNode invoke, AccessPathToken token) {
|
private predicate invocationMatchesCallSiteFilter(
|
||||||
|
Specific::InvokeNode invoke, AccessPathTokenBase token
|
||||||
|
) {
|
||||||
token.getName() = "WithArity" and
|
token.getName() = "WithArity" and
|
||||||
invoke.getNumArgument() = AccessPath::parseIntUnbounded(token.getAnArgument())
|
invoke.getNumArgument() = parseIntUnbounded(token.getAnArgument())
|
||||||
or
|
or
|
||||||
Specific::invocationMatchesExtraCallSiteFilter(invoke, token)
|
Specific::invocationMatchesExtraCallSiteFilter(invoke, token)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,14 +4,13 @@
|
|||||||
* It must export the following members:
|
* It must export the following members:
|
||||||
* ```ql
|
* ```ql
|
||||||
* class Unit // a unit type
|
* class Unit // a unit type
|
||||||
* module AccessPathSyntax // a re-export of the AccessPathSyntax module
|
|
||||||
* class InvokeNode // a type representing an invocation connected to the API graph
|
* class InvokeNode // a type representing an invocation connected to the API graph
|
||||||
* module API // the API graph module
|
* module API // the API graph module
|
||||||
* predicate isPackageUsed(string package)
|
* predicate isPackageUsed(string package)
|
||||||
* API::Node getExtraNodeFromPath(string package, string type, string path, int n)
|
* API::Node getExtraNodeFromPath(string package, string type, string path, int n)
|
||||||
* API::Node getExtraSuccessorFromNode(API::Node node, AccessPathToken token)
|
* API::Node getExtraSuccessorFromNode(API::Node node, AccessPathTokenBase token)
|
||||||
* API::Node getExtraSuccessorFromInvoke(InvokeNode node, AccessPathToken token)
|
* API::Node getExtraSuccessorFromInvoke(InvokeNode node, AccessPathTokenBase token)
|
||||||
* predicate invocationMatchesExtraCallSiteFilter(InvokeNode invoke, AccessPathToken token)
|
* predicate invocationMatchesExtraCallSiteFilter(InvokeNode invoke, AccessPathTokenBase token)
|
||||||
* InvokeNode getAnInvocationOf(API::Node node)
|
* InvokeNode getAnInvocationOf(API::Node node)
|
||||||
* predicate isExtraValidTokenNameInIdentifyingAccessPath(string name)
|
* predicate isExtraValidTokenNameInIdentifyingAccessPath(string name)
|
||||||
* predicate isExtraValidNoArgumentTokenInIdentifyingAccessPath(string name)
|
* predicate isExtraValidNoArgumentTokenInIdentifyingAccessPath(string name)
|
||||||
@@ -25,9 +24,7 @@ private import ApiGraphModels
|
|||||||
// Re-export libraries needed by ApiGraphModels.qll
|
// Re-export libraries needed by ApiGraphModels.qll
|
||||||
module API = JS::API;
|
module API = JS::API;
|
||||||
|
|
||||||
import semmle.javascript.frameworks.data.internal.AccessPathSyntax as AccessPathSyntax
|
|
||||||
import JS::DataFlow as DataFlow
|
import JS::DataFlow as DataFlow
|
||||||
private import AccessPathSyntax
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Holds if `rawType` represents the JavaScript type `qualifiedName` from the given NPM `package`.
|
* Holds if `rawType` represents the JavaScript type `qualifiedName` from the given NPM `package`.
|
||||||
@@ -137,7 +134,7 @@ API::Node getExtraNodeFromType(string type) {
|
|||||||
* Gets a JavaScript-specific API graph successor of `node` reachable by resolving `token`.
|
* Gets a JavaScript-specific API graph successor of `node` reachable by resolving `token`.
|
||||||
*/
|
*/
|
||||||
bindingset[token]
|
bindingset[token]
|
||||||
API::Node getExtraSuccessorFromNode(API::Node node, AccessPathToken token) {
|
API::Node getExtraSuccessorFromNode(API::Node node, AccessPathTokenBase token) {
|
||||||
token.getName() = "Member" and
|
token.getName() = "Member" and
|
||||||
result = node.getMember(token.getAnArgument())
|
result = node.getMember(token.getAnArgument())
|
||||||
or
|
or
|
||||||
@@ -183,7 +180,7 @@ API::Node getExtraSuccessorFromNode(API::Node node, AccessPathToken token) {
|
|||||||
* Gets a JavaScript-specific API graph successor of `node` reachable by resolving `token`.
|
* Gets a JavaScript-specific API graph successor of `node` reachable by resolving `token`.
|
||||||
*/
|
*/
|
||||||
bindingset[token]
|
bindingset[token]
|
||||||
API::Node getExtraSuccessorFromInvoke(API::InvokeNode node, AccessPathToken token) {
|
API::Node getExtraSuccessorFromInvoke(API::InvokeNode node, AccessPathTokenBase token) {
|
||||||
token.getName() = "Instance" and
|
token.getName() = "Instance" and
|
||||||
result = node.getInstance()
|
result = node.getInstance()
|
||||||
or
|
or
|
||||||
@@ -233,7 +230,7 @@ API::Node getAFuzzySuccessor(API::Node node) {
|
|||||||
* Holds if `invoke` matches the JS-specific call site filter in `token`.
|
* Holds if `invoke` matches the JS-specific call site filter in `token`.
|
||||||
*/
|
*/
|
||||||
bindingset[token]
|
bindingset[token]
|
||||||
predicate invocationMatchesExtraCallSiteFilter(API::InvokeNode invoke, AccessPathToken token) {
|
predicate invocationMatchesExtraCallSiteFilter(API::InvokeNode invoke, AccessPathTokenBase token) {
|
||||||
token.getName() = "NewCall" and
|
token.getName() = "NewCall" and
|
||||||
invoke instanceof API::NewNode
|
invoke instanceof API::NewNode
|
||||||
or
|
or
|
||||||
@@ -246,9 +243,8 @@ predicate invocationMatchesExtraCallSiteFilter(API::InvokeNode invoke, AccessPat
|
|||||||
operand = token.getAnArgument() and
|
operand = token.getAnArgument() and
|
||||||
argIndex = operand.splitAt("=", 0) and
|
argIndex = operand.splitAt("=", 0) and
|
||||||
stringValue = operand.splitAt("=", 1) and
|
stringValue = operand.splitAt("=", 1) and
|
||||||
invoke
|
invoke.getArgument(parseIntWithArity(argIndex, invoke.getNumArgument())).getStringValue() =
|
||||||
.getArgument(AccessPath::parseIntWithArity(argIndex, invoke.getNumArgument()))
|
stringValue
|
||||||
.getStringValue() = stringValue
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -338,7 +334,7 @@ predicate isExtraValidTokenArgumentInIdentifyingAccessPath(string name, string a
|
|||||||
or
|
or
|
||||||
name = "WithStringArgument" and
|
name = "WithStringArgument" and
|
||||||
exists(argument.indexOf("=")) and
|
exists(argument.indexOf("=")) and
|
||||||
exists(AccessPath::parseIntWithArity(argument.splitAt("=", 0), 10))
|
exists(parseIntWithArity(argument.splitAt("=", 0), 10))
|
||||||
}
|
}
|
||||||
|
|
||||||
module ModelOutputSpecific {
|
module ModelOutputSpecific {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import javascript
|
import javascript
|
||||||
import testUtilities.ConsistencyChecking
|
import testUtilities.ConsistencyChecking
|
||||||
import semmle.javascript.frameworks.data.internal.AccessPathSyntax as AccessPathSyntax
|
import semmle.javascript.frameworks.data.internal.ApiGraphModels as ApiGraphModels
|
||||||
|
|
||||||
class Steps extends ModelInput::SummaryModelCsv {
|
class Steps extends ModelInput::SummaryModelCsv {
|
||||||
override predicate row(string row) {
|
override predicate row(string row) {
|
||||||
@@ -126,6 +126,6 @@ class SyntaxErrorTest extends ModelInput::SinkModelCsv {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
query predicate syntaxErrors(AccessPathSyntax::AccessPath path) { path.hasSyntaxError() }
|
query predicate syntaxErrors(ApiGraphModels::AccessPath path) { path.hasSyntaxError() }
|
||||||
|
|
||||||
query predicate warning = ModelOutput::getAWarning/0;
|
query predicate warning = ModelOutput::getAWarning/0;
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
import javascript
|
import javascript
|
||||||
import semmle.javascript.frameworks.data.internal.AccessPathSyntax as AccessPathSyntax
|
|
||||||
import semmle.javascript.frameworks.data.internal.ApiGraphModels as ApiGraphModels
|
import semmle.javascript.frameworks.data.internal.ApiGraphModels as ApiGraphModels
|
||||||
|
|
||||||
private class InvalidTypeModel extends ModelInput::TypeModelCsv {
|
private class InvalidTypeModel extends ModelInput::TypeModelCsv {
|
||||||
|
|||||||
Reference in New Issue
Block a user