Merge branch 'main' into js/graph-export

This commit is contained in:
Asger F
2024-04-16 20:23:33 +02:00
1236 changed files with 37405 additions and 42510 deletions

View File

@@ -1,4 +1,4 @@
load("@rules_pkg//:mappings.bzl", "pkg_files")
load("@rules_pkg//pkg:mappings.bzl", "pkg_files")
package(default_visibility = ["//python:__pkg__"])

View File

@@ -31,8 +31,21 @@ abstract class SummarizedCallable extends LibraryCallable, Impl::Public::Summari
* DEPRECATED: Use `propagatesFlow` instead.
*/
deprecated predicate propagatesFlowExt(string input, string output, boolean preservesValue) {
this.propagatesFlow(input, output, preservesValue)
this.propagatesFlow(input, output, preservesValue, _)
}
override predicate propagatesFlow(
string input, string output, boolean preservesValue, string model
) {
this.propagatesFlow(input, output, preservesValue) and model = this
}
/**
* Holds if data may flow from `input` to `output` through this callable.
*
* `preservesValue` indicates whether this is a value-preserving step or a taint-step.
*/
predicate propagatesFlow(string input, string output, boolean preservesValue) { none() }
}
deprecated class RequiredSummaryComponentStack = Impl::Private::RequiredSummaryComponentStack;

View File

@@ -263,9 +263,10 @@ deprecated private module Config implements FullStateConfigSig {
predicate isBarrierOut(Node node, FlowState state) { none() }
predicate isAdditionalFlowStep(Node node1, Node node2) {
predicate isAdditionalFlowStep(Node node1, Node node2, string model) {
singleConfiguration() and
any(Configuration config).isAdditionalFlowStep(node1, node2)
any(Configuration config).isAdditionalFlowStep(node1, node2) and
model = ""
}
predicate isAdditionalFlowStep(Node node1, FlowState state1, Node node2, FlowState state2) {

View File

@@ -263,9 +263,10 @@ deprecated private module Config implements FullStateConfigSig {
predicate isBarrierOut(Node node, FlowState state) { none() }
predicate isAdditionalFlowStep(Node node1, Node node2) {
predicate isAdditionalFlowStep(Node node1, Node node2, string model) {
singleConfiguration() and
any(Configuration config).isAdditionalFlowStep(node1, node2)
any(Configuration config).isAdditionalFlowStep(node1, node2) and
model = ""
}
predicate isAdditionalFlowStep(Node node1, FlowState state1, Node node2, FlowState state2) {

View File

@@ -263,9 +263,10 @@ deprecated private module Config implements FullStateConfigSig {
predicate isBarrierOut(Node node, FlowState state) { none() }
predicate isAdditionalFlowStep(Node node1, Node node2) {
predicate isAdditionalFlowStep(Node node1, Node node2, string model) {
singleConfiguration() and
any(Configuration config).isAdditionalFlowStep(node1, node2)
any(Configuration config).isAdditionalFlowStep(node1, node2) and
model = ""
}
predicate isAdditionalFlowStep(Node node1, FlowState state1, Node node2, FlowState state2) {

View File

@@ -263,9 +263,10 @@ deprecated private module Config implements FullStateConfigSig {
predicate isBarrierOut(Node node, FlowState state) { none() }
predicate isAdditionalFlowStep(Node node1, Node node2) {
predicate isAdditionalFlowStep(Node node1, Node node2, string model) {
singleConfiguration() and
any(Configuration config).isAdditionalFlowStep(node1, node2)
any(Configuration config).isAdditionalFlowStep(node1, node2) and
model = ""
}
predicate isAdditionalFlowStep(Node node1, FlowState state1, Node node2, FlowState state2) {

View File

@@ -3,6 +3,7 @@ private import DataFlowPublic
private import semmle.python.essa.SsaCompute
private import semmle.python.dataflow.new.internal.ImportResolution
private import FlowSummaryImpl as FlowSummaryImpl
private import semmle.python.frameworks.data.ModelsAsData
// Since we allow extra data-flow steps from modeled frameworks, we import these
// up-front, to ensure these are included. This provides a more seamless experience from
// a user point of view, since they don't need to know they need to import a specific
@@ -471,12 +472,12 @@ import StepRelationTransformations
*
* It includes flow steps from flow summaries.
*/
predicate simpleLocalFlowStep(Node nodeFrom, Node nodeTo) {
simpleLocalFlowStepForTypetracking(nodeFrom, nodeTo)
predicate simpleLocalFlowStep(Node nodeFrom, Node nodeTo, string model) {
simpleLocalFlowStepForTypetracking(nodeFrom, nodeTo) and model = ""
or
summaryLocalStep(nodeFrom, nodeTo)
summaryLocalStep(nodeFrom, nodeTo, model)
or
variableCaptureLocalFlowStep(nodeFrom, nodeTo)
variableCaptureLocalFlowStep(nodeFrom, nodeTo) and model = ""
}
/**
@@ -490,9 +491,9 @@ predicate simpleLocalFlowStepForTypetracking(Node nodeFrom, Node nodeTo) {
LocalFlow::localFlowStep(nodeFrom, nodeTo)
}
private predicate summaryLocalStep(Node nodeFrom, Node nodeTo) {
private predicate summaryLocalStep(Node nodeFrom, Node nodeTo, string model) {
FlowSummaryImpl::Private::Steps::summaryLocalStep(nodeFrom.(FlowSummaryNode).getSummaryNode(),
nodeTo.(FlowSummaryNode).getSummaryNode(), true)
nodeTo.(FlowSummaryNode).getSummaryNode(), true, model)
}
predicate variableCaptureLocalFlowStep(Node nodeFrom, Node nodeTo) {
@@ -1078,6 +1079,14 @@ predicate lambdaCall(DataFlowCall call, LambdaCallKind kind, Node receiver) {
/** Extra data-flow steps needed for lambda flow analysis. */
predicate additionalLambdaFlowStep(Node nodeFrom, Node nodeTo, boolean preservesValue) { none() }
predicate knownSourceModel(Node source, string model) {
source = ModelOutput::getASourceNode(_, model).asSource()
}
predicate knownSinkModel(Node sink, string model) {
sink = ModelOutput::getASinkNode(_, model).asSink()
}
/**
* Holds if flow is allowed to pass from parameter `p` and back to itself as a
* side-effect, resulting in a summary from `p` to itself.

View File

@@ -642,7 +642,9 @@ newtype TContent =
or
//
// 2) summaries in data-extension files
exists(string input, string output | ModelOutput::relevantSummaryModel(_, _, input, output, _) |
exists(string input, string output |
ModelOutput::relevantSummaryModel(_, _, input, output, _, _)
|
attr = [input, output].regexpFind("(?<=(^|\\.)Attribute\\[)[^\\]]+(?=\\])", _, _).trim()
)
} or

View File

@@ -12,7 +12,7 @@ private import FlowSummaryImpl as FlowSummaryImpl
* (intra-procedural) step.
*/
predicate localFlowStep(Node nodeFrom, Node nodeTo) {
simpleLocalFlowStep(nodeFrom, nodeTo)
simpleLocalFlowStep(nodeFrom, nodeTo, _)
or
// Simple flow through library code is included in the exposed local
// step relation, even though flow is technically inter-procedural.

View File

@@ -242,7 +242,7 @@ private module Cached {
*/
pragma[nomagic]
private predicate localSourceFlowStep(Node nodeFrom, Node nodeTo) {
simpleLocalFlowStep(nodeFrom, nodeTo) and
simpleLocalFlowStep(nodeFrom, nodeTo, _) and
not nodeTo = any(ModuleVariableNode v).getARead()
}

View File

@@ -24,10 +24,11 @@ private module Cached {
* global taint flow configurations.
*/
cached
predicate defaultAdditionalTaintStep(DataFlow::Node nodeFrom, DataFlow::Node nodeTo) {
localAdditionalTaintStep(nodeFrom, nodeTo)
predicate defaultAdditionalTaintStep(DataFlow::Node nodeFrom, DataFlow::Node nodeTo, string model) {
localAdditionalTaintStep(nodeFrom, nodeTo, model)
or
any(AdditionalTaintStep a).step(nodeFrom, nodeTo)
any(AdditionalTaintStep a).step(nodeFrom, nodeTo) and
model = "AdditionalTaintStep"
}
/**
@@ -36,30 +37,34 @@ private module Cached {
* different objects.
*/
cached
predicate localAdditionalTaintStep(DataFlow::Node nodeFrom, DataFlow::Node nodeTo) {
concatStep(nodeFrom, nodeTo)
or
subscriptStep(nodeFrom, nodeTo)
or
stringManipulation(nodeFrom, nodeTo)
or
containerStep(nodeFrom, nodeTo)
or
copyStep(nodeFrom, nodeTo)
or
DataFlowPrivate::forReadStep(nodeFrom, _, nodeTo)
or
DataFlowPrivate::iterableUnpackingReadStep(nodeFrom, _, nodeTo)
or
DataFlowPrivate::iterableUnpackingStoreStep(nodeFrom, _, nodeTo)
or
awaitStep(nodeFrom, nodeTo)
or
asyncWithStep(nodeFrom, nodeTo)
predicate localAdditionalTaintStep(DataFlow::Node nodeFrom, DataFlow::Node nodeTo, string model) {
(
concatStep(nodeFrom, nodeTo)
or
subscriptStep(nodeFrom, nodeTo)
or
stringManipulation(nodeFrom, nodeTo)
or
containerStep(nodeFrom, nodeTo)
or
copyStep(nodeFrom, nodeTo)
or
DataFlowPrivate::forReadStep(nodeFrom, _, nodeTo)
or
DataFlowPrivate::iterableUnpackingReadStep(nodeFrom, _, nodeTo)
or
DataFlowPrivate::iterableUnpackingStoreStep(nodeFrom, _, nodeTo)
or
awaitStep(nodeFrom, nodeTo)
or
asyncWithStep(nodeFrom, nodeTo)
) and
model = ""
or
FlowSummaryImpl::Private::Steps::summaryLocalStep(nodeFrom
.(DataFlowPrivate::FlowSummaryNode)
.getSummaryNode(), nodeTo.(DataFlowPrivate::FlowSummaryNode).getSummaryNode(), false)
.getSummaryNode(), nodeTo.(DataFlowPrivate::FlowSummaryNode).getSummaryNode(), false,
model)
}
}

View File

@@ -34,7 +34,7 @@ predicate localTaintStep(DataFlow::Node nodeFrom, DataFlow::Node nodeTo) {
// Ordinary data flow
DataFlow::localFlowStep(nodeFrom, nodeTo)
or
localAdditionalTaintStep(nodeFrom, nodeTo)
localAdditionalTaintStep(nodeFrom, nodeTo, _)
}
/**

View File

@@ -24,7 +24,15 @@ private module SummaryTypeTrackerInput implements SummaryTypeTracker::Input {
ContentFilter getFilterFromWithContentStep(Content content) { none() }
// Callables
class SummarizedCallable = FlowSummaryImpl::Private::SummarizedCallableImpl;
class SummarizedCallable instanceof FlowSummaryImpl::Private::SummarizedCallableImpl {
string toString() { result = super.toString() }
predicate propagatesFlow(
SummaryComponentStack input, SummaryComponentStack output, boolean preservesValue
) {
super.propagatesFlow(input, output, preservesValue, _)
}
}
// Summaries and their stacks
class SummaryComponent = FlowSummaryImpl::Private::SummaryComponent;

View File

@@ -127,7 +127,7 @@ abstract deprecated class Configuration extends DataFlow::Configuration {
final override predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) {
this.isAdditionalTaintStep(node1, node2) or
defaultAdditionalTaintStep(node1, node2)
defaultAdditionalTaintStep(node1, node2, _)
}
/**

View File

@@ -127,7 +127,7 @@ abstract deprecated class Configuration extends DataFlow::Configuration {
final override predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) {
this.isAdditionalTaintStep(node1, node2) or
defaultAdditionalTaintStep(node1, node2)
defaultAdditionalTaintStep(node1, node2, _)
}
/**

View File

@@ -127,7 +127,7 @@ abstract deprecated class Configuration extends DataFlow::Configuration {
final override predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) {
this.isAdditionalTaintStep(node1, node2) or
defaultAdditionalTaintStep(node1, node2)
defaultAdditionalTaintStep(node1, node2, _)
}
/**

View File

@@ -127,7 +127,7 @@ abstract deprecated class Configuration extends DataFlow::Configuration {
final override predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) {
this.isAdditionalTaintStep(node1, node2) or
defaultAdditionalTaintStep(node1, node2)
defaultAdditionalTaintStep(node1, node2, _)
}
/**

View File

@@ -0,0 +1,29 @@
extensions:
- addsTo:
pack: codeql/python-all
extensible: sinkModel
data:
# `Connection`s and `ConnectionPool`s provide some methods that execute SQL.
- ['asyncpg.~Connection', 'Member[copy_from_query,execute,fetch,fetchrow,fetchval].Argument[0,query:]', 'sql-injection']
- ['asyncpg.~Connection', 'Member[executemany].Argument[0,command:]', 'sql-injection']
# A model of `Connection` and `ConnectionPool`, which provide some methods that access the file system.
- ['asyncpg.~Connection', 'Member[copy_from_query,copy_from_table].Argument[output:]', 'path-injection']
- ['asyncpg.~Connection', 'Member[copy_to_table].Argument[source:]', 'path-injection']
# the `PreparedStatement` class in `asyncpg`.
- ['asyncpg.Connection', 'Member[prepare].Argument[0,query:]', 'sql-injection']
- addsTo:
pack: codeql/python-all
extensible: typeModel
data:
# a `ConnectionPool` that is created when the result of `asyncpg.create_pool()` is awaited.
- ['asyncpg.Connection', 'asyncpg.ConnectionPool', 'Member[acquire].ReturnValue.Awaited']
# a `Connection` that is created when
# * - the result of `asyncpg.connect()` is awaited.
# * - the result of calling `acquire` on a `ConnectionPool` is awaited.
- ['asyncpg.Connection', 'asyncpg', 'Member[connect].ReturnValue.Awaited']
- ['asyncpg.Connection', 'asyncpg', 'Member[connection].Member[connect].ReturnValue.Awaited']
- ['asyncpg.ConnectionPool', 'asyncpg', 'Member[create_pool].ReturnValue.Awaited']
# Creating an internal `~Connection` type that contains both `Connection` and `ConnectionPool`.
- ['asyncpg.~Connection', 'asyncpg.Connection', '']
- ['asyncpg.~Connection', 'asyncpg.ConnectionPool', '']

View File

@@ -11,43 +11,6 @@ private import semmle.python.frameworks.data.ModelsAsData
/** Provides models for the `asyncpg` PyPI package. */
private module Asyncpg {
class AsyncpgModel extends ModelInput::TypeModelCsv {
override predicate row(string row) {
// type1;type2;path
row =
[
// a `ConnectionPool` that is created when the result of `asyncpg.create_pool()` is awaited.
"asyncpg.ConnectionPool;asyncpg;Member[create_pool].ReturnValue.Awaited",
// a `Connection` that is created when
// * - the result of `asyncpg.connect()` is awaited.
// * - the result of calling `acquire` on a `ConnectionPool` is awaited.
"asyncpg.Connection;asyncpg;Member[connect].ReturnValue.Awaited",
"asyncpg.Connection;asyncpg;Member[connection].Member[connect].ReturnValue.Awaited",
"asyncpg.Connection;asyncpg.ConnectionPool;Member[acquire].ReturnValue.Awaited",
// Creating an internal `~Connection` type that contains both `Connection` and `ConnectionPool`.
"asyncpg.~Connection;asyncpg.Connection;", //
"asyncpg.~Connection;asyncpg.ConnectionPool;"
]
}
}
class AsyncpgSink extends ModelInput::SinkModelCsv {
// type;path;kind
override predicate row(string row) {
row =
[
// `Connection`s and `ConnectionPool`s provide some methods that execute SQL.
"asyncpg.~Connection;Member[copy_from_query,execute,fetch,fetchrow,fetchval].Argument[0,query:];sql-injection",
"asyncpg.~Connection;Member[executemany].Argument[0,command:];sql-injection",
// A model of `Connection` and `ConnectionPool`, which provide some methods that access the file system.
"asyncpg.~Connection;Member[copy_from_query,copy_from_table].Argument[output:];path-injection",
"asyncpg.~Connection;Member[copy_to_table].Argument[source:];path-injection",
// the `PreparedStatement` class in `asyncpg`.
"asyncpg.Connection;Member[prepare].Argument[0,query:];sql-injection",
]
}
}
/**
* Provides models of the `Cursor` class in `asyncpg`.
* `Cursor`s are created

View File

@@ -22,7 +22,7 @@ private import semmle.python.dataflow.new.FlowSummary
/**
* A remote flow source originating from a CSV source row.
*/
private class RemoteFlowSourceFromCsv extends RemoteFlowSource {
private class RemoteFlowSourceFromCsv extends RemoteFlowSource::Range {
RemoteFlowSourceFromCsv() { this = ModelOutput::getASourceNode("remote").asSource() }
override string getSourceType() { result = "Remote flow (from model)" }
@@ -33,7 +33,7 @@ private class SummarizedCallableFromModel extends SummarizedCallable {
string path;
SummarizedCallableFromModel() {
ModelOutput::relevantSummaryModel(type, path, _, _, _) and
ModelOutput::relevantSummaryModel(type, path, _, _, _, _) and
this = type + ";" + path
}
@@ -46,8 +46,10 @@ private class SummarizedCallableFromModel extends SummarizedCallable {
)
}
override predicate propagatesFlow(string input, string output, boolean preservesValue) {
exists(string kind | ModelOutput::relevantSummaryModel(type, path, input, output, kind) |
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

View File

@@ -1,17 +1,17 @@
/**
* INTERNAL use only. This is an experimental API subject to change without notice.
*
* Provides classes and predicates for dealing with flow models specified in CSV format.
* Provides classes and predicates for dealing with flow models specified in extensible predicates.
*
* The CSV specification has the following columns:
* The extensible predicates have the following columns:
* - Sources:
* `type; path; kind`
* `type, path, kind`
* - Sinks:
* `type; path; kind`
* `type, path, kind`
* - Summaries:
* `type; path; input; output; kind`
* `type, path, input, output, kind`
* - Types:
* `type1; type2; path`
* `type1, type2, path`
*
* The interpretation of a row is similar to API-graphs with a left-to-right
* reading.
@@ -76,11 +76,13 @@ private import codeql.dataflow.internal.AccessPathSyntax
/** Module containing hooks for providing input data to be interpreted as a model. */
module ModelInput {
/**
* DEPRECATED: Use the extensible predicate `sourceModel` instead.
*
* A unit class for adding additional source model rows.
*
* Extend this class to add additional source definitions.
*/
class SourceModelCsv extends Unit {
deprecated class SourceModelCsv extends Unit {
/**
* Holds if `row` specifies a source definition.
*
@@ -93,15 +95,17 @@ module ModelInput {
*
* The kind `remote` represents a general remote flow source.
*/
abstract predicate row(string row);
abstract deprecated predicate row(string row);
}
/**
* A unit class for adding additional sink model rows.
*
* Extend this class to add additional sink definitions.
*
* DEPRECATED: Use the extensible predicate `sinkModel` instead.
*/
class SinkModelCsv extends Unit {
deprecated class SinkModelCsv extends Unit {
/**
* Holds if `row` specifies a sink definition.
*
@@ -112,15 +116,17 @@ module ModelInput {
* indicates that the value at `(type, path)` should be seen as a sink
* of the given `kind`.
*/
abstract predicate row(string row);
abstract deprecated predicate row(string row);
}
/**
* A unit class for adding additional summary model rows.
*
* Extend this class to add additional flow summary definitions.
*
* DEPRECATED: Use the extensible predicate `summaryModel` instead.
*/
class SummaryModelCsv extends Unit {
deprecated class SummaryModelCsv extends Unit {
/**
* Holds if `row` specifies a summary definition.
*
@@ -134,15 +140,18 @@ module ModelInput {
* `kind` should be either `value` or `taint`, for value-preserving or taint-preserving steps,
* respectively.
*/
abstract predicate row(string row);
abstract deprecated predicate row(string row);
}
/**
* A unit class for adding additional type model rows.
*
* Extend this class to add additional type definitions.
*
* DEPRECATED: Use the extensible predicate `typeModel` or the class
* `TypeModel` instead.
*/
class TypeModelCsv extends Unit {
deprecated class TypeModelCsv extends Unit {
/**
* Holds if `row` specifies a type definition.
*
@@ -152,7 +161,7 @@ module ModelInput {
* ```
* indicates that `(type2, path)` should be seen as an instance of `type1`.
*/
abstract predicate row(string row);
abstract deprecated predicate row(string row);
}
/**
@@ -186,8 +195,10 @@ module ModelInput {
/**
* A unit class for adding additional type variable model rows.
*
* DEPRECATED: Use the extensible predicate `typeVariableModel` instead.
*/
class TypeVariableModelCsv extends Unit {
deprecated class TypeVariableModelCsv extends Unit {
/**
* Holds if `row` specifies a path through a type variable.
*
@@ -197,7 +208,7 @@ module ModelInput {
* ```
* means `path` can be substituted for a token `TypeVar[name]`.
*/
abstract predicate row(string row);
abstract deprecated predicate row(string row);
}
}
@@ -216,57 +227,121 @@ abstract class TestAllModels extends Unit { }
* does not preserve empty trailing substrings.
*/
bindingset[result]
private string inversePad(string s) { s = result + ";dummy" }
deprecated private string inversePad(string s) { s = result + ";dummy" }
private predicate sourceModel(string row) { any(SourceModelCsv s).row(inversePad(row)) }
deprecated private predicate sourceModel(string row) { any(SourceModelCsv s).row(inversePad(row)) }
private predicate sinkModel(string row) { any(SinkModelCsv s).row(inversePad(row)) }
deprecated private predicate sinkModel(string row) { any(SinkModelCsv s).row(inversePad(row)) }
private predicate summaryModel(string row) { any(SummaryModelCsv s).row(inversePad(row)) }
deprecated private predicate summaryModel(string row) {
any(SummaryModelCsv s).row(inversePad(row))
}
private predicate typeModel(string row) { any(TypeModelCsv s).row(inversePad(row)) }
deprecated private predicate typeModel(string row) { any(TypeModelCsv s).row(inversePad(row)) }
private predicate typeVariableModel(string row) { any(TypeVariableModelCsv s).row(inversePad(row)) }
deprecated private predicate typeVariableModel(string row) {
any(TypeVariableModelCsv s).row(inversePad(row))
}
private class DeprecationAdapter extends Unit {
abstract predicate sourceModel(string type, string path, string kind);
abstract predicate sinkModel(string type, string path, string kind);
abstract predicate summaryModel(string type, string path, string input, string output, string kind);
abstract predicate typeModel(string type1, string type2, string path);
abstract predicate typeVariableModel(string name, string path);
}
private class DeprecationAdapterImpl extends DeprecationAdapter {
deprecated override predicate sourceModel(string type, string path, string kind) {
exists(string row |
sourceModel(row) and
row.splitAt(";", 0) = type and
row.splitAt(";", 1) = path and
row.splitAt(";", 2) = kind
)
}
deprecated override predicate sinkModel(string type, string path, string kind) {
exists(string row |
sinkModel(row) and
row.splitAt(";", 0) = type and
row.splitAt(";", 1) = path and
row.splitAt(";", 2) = kind
)
}
deprecated override predicate summaryModel(
string type, string path, string input, string output, string kind
) {
exists(string row |
summaryModel(row) and
row.splitAt(";", 0) = type and
row.splitAt(";", 1) = path and
row.splitAt(";", 2) = input and
row.splitAt(";", 3) = output and
row.splitAt(";", 4) = kind
)
}
deprecated override predicate typeModel(string type1, string type2, string path) {
exists(string row |
typeModel(row) and
row.splitAt(";", 0) = type1 and
row.splitAt(";", 1) = type2 and
row.splitAt(";", 2) = path
)
}
deprecated override predicate typeVariableModel(string name, string path) {
exists(string row |
typeVariableModel(row) and
row.splitAt(";", 0) = name and
row.splitAt(";", 1) = path
)
}
}
/** Holds if a source model exists for the given parameters. */
predicate sourceModel(string type, string path, string kind) {
exists(string row |
sourceModel(row) and
row.splitAt(";", 0) = type and
row.splitAt(";", 1) = path and
row.splitAt(";", 2) = kind
)
predicate sourceModel(string type, string path, string kind, string model) {
any(DeprecationAdapter a).sourceModel(type, path, kind) and
model = "SourceModelCsv"
or
Extensions::sourceModel(type, path, kind)
exists(QlBuiltins::ExtensionId madId |
Extensions::sourceModel(type, path, kind, madId) and
model = "MaD:" + madId.toString()
)
}
/** Holds if a sink model exists for the given parameters. */
private predicate sinkModel(string type, string path, string kind) {
exists(string row |
sinkModel(row) and
row.splitAt(";", 0) = type and
row.splitAt(";", 1) = path and
row.splitAt(";", 2) = kind
)
private predicate sinkModel(string type, string path, string kind, string model) {
any(DeprecationAdapter a).sinkModel(type, path, kind) and
model = "SinkModelCsv"
or
Extensions::sinkModel(type, path, kind)
exists(QlBuiltins::ExtensionId madId |
Extensions::sinkModel(type, path, kind, madId) and
model = "MaD:" + madId.toString()
)
}
/** Holds if a summary model `row` exists for the given parameters. */
private predicate summaryModel(string type, string path, string input, string output, string kind) {
exists(string row |
summaryModel(row) and
row.splitAt(";", 0) = type and
row.splitAt(";", 1) = path and
row.splitAt(";", 2) = input and
row.splitAt(";", 3) = output and
row.splitAt(";", 4) = kind
)
private predicate summaryModel(
string type, string path, string input, string output, string kind, string model
) {
any(DeprecationAdapter a).summaryModel(type, path, input, output, kind) and
model = "SummaryModelCsv"
or
Extensions::summaryModel(type, path, input, output, kind)
exists(QlBuiltins::ExtensionId madId |
Extensions::summaryModel(type, path, input, output, kind, madId) and
model = "MaD:" + madId.toString()
)
}
/** Holds if a type model exists for the given parameters. */
<<<<<<< HEAD
predicate typeModel(string type1, string type2, string path) {
exists(string row |
typeModel(row) and
@@ -274,29 +349,29 @@ predicate typeModel(string type1, string type2, string path) {
row.splitAt(";", 1) = type2 and
row.splitAt(";", 2) = path
)
=======
private predicate typeModel(string type1, string type2, string path) {
any(DeprecationAdapter a).typeModel(type1, type2, path)
>>>>>>> main
or
Extensions::typeModel(type1, type2, path)
}
/** Holds if a type variable model exists for the given parameters. */
private predicate typeVariableModel(string name, string path) {
exists(string row |
typeVariableModel(row) and
row.splitAt(";", 0) = name and
row.splitAt(";", 1) = path
)
any(DeprecationAdapter a).typeVariableModel(name, path)
or
Extensions::typeVariableModel(name, path)
}
/**
* Holds if CSV rows involving `type` might be relevant for the analysis of this database.
* Holds if rows involving `type` might be relevant for the analysis of this database.
*/
predicate isRelevantType(string type) {
(
sourceModel(type, _, _) or
sinkModel(type, _, _) or
summaryModel(type, _, _, _, _) or
sourceModel(type, _, _, _) or
sinkModel(type, _, _, _) or
summaryModel(type, _, _, _, _, _) or
typeModel(_, type, _)
) and
(
@@ -313,26 +388,26 @@ predicate isRelevantType(string type) {
}
/**
* Holds if `type,path` is used in some CSV row.
* Holds if `type,path` is used in some row.
*/
pragma[nomagic]
predicate isRelevantFullPath(string type, string path) {
isRelevantType(type) and
(
sourceModel(type, path, _) or
sinkModel(type, path, _) or
summaryModel(type, path, _, _, _) or
sourceModel(type, path, _, _) or
sinkModel(type, path, _, _) or
summaryModel(type, path, _, _, _, _) or
typeModel(_, type, path)
)
}
/** A string from a CSV row that should be parsed as an access path. */
/** A string from a row that should be parsed as an access path. */
private predicate accessPathRange(string s) {
isRelevantFullPath(_, s)
or
exists(string type | isRelevantType(type) |
summaryModel(type, _, s, _, _) or
summaryModel(type, _, _, s, _)
summaryModel(type, _, s, _, _, _) or
summaryModel(type, _, _, s, _, _)
)
or
typeVariableModel(_, s)
@@ -543,7 +618,7 @@ private API::Node getNodeFromPath(string type, AccessPath path) {
pragma[nomagic]
private predicate typeStepModel(string type, AccessPath basePath, AccessPath output) {
summaryModel(type, basePath, "", output, "type")
summaryModel(type, basePath, "", output, "type", _)
}
pragma[nomagic]
@@ -618,36 +693,36 @@ module ModelOutput {
cached
private module Cached {
/**
* Holds if a CSV source model contributed `source` with the given `kind`.
* Holds if a source model contributed `source` with the given `kind`.
*/
cached
API::Node getASourceNode(string kind) {
API::Node getASourceNode(string kind, string model) {
exists(string type, string path |
sourceModel(type, path, kind) and
sourceModel(type, path, kind, model) and
result = getNodeFromPath(type, path)
)
}
/**
* Holds if a CSV sink model contributed `sink` with the given `kind`.
* Holds if a sink model contributed `sink` with the given `kind`.
*/
cached
API::Node getASinkNode(string kind) {
API::Node getASinkNode(string kind, string model) {
exists(string type, string path |
sinkModel(type, path, kind) and
sinkModel(type, path, kind, model) and
result = getNodeFromPath(type, path)
)
}
/**
* Holds if a relevant CSV summary exists for these parameters.
* Holds if a relevant summary exists for these parameters.
*/
cached
predicate relevantSummaryModel(
string type, string path, string input, string output, string kind
string type, string path, string input, string output, string kind, string model
) {
isRelevantType(type) and
summaryModel(type, path, input, output, kind)
summaryModel(type, path, input, output, kind, model)
}
/**
@@ -655,7 +730,7 @@ module ModelOutput {
*/
cached
predicate resolvedSummaryBase(string type, string path, Specific::InvokeNode baseNode) {
summaryModel(type, path, _, _, _) and
summaryModel(type, path, _, _, _, _) and
baseNode = getInvocationFromPath(type, path)
}
@@ -664,13 +739,13 @@ module ModelOutput {
*/
cached
predicate resolvedSummaryRefBase(string type, string path, API::Node baseNode) {
summaryModel(type, path, _, _, _) and
summaryModel(type, path, _, _, _, _) and
baseNode = getNodeFromPath(type, path)
}
/**
* Holds if `node` is seen as an instance of `type` due to a type definition
* contributed by a CSV model.
* contributed by a model.
*/
cached
API::Node getATypeNode(string type) { result = getNodeFromType(type) }
@@ -680,12 +755,22 @@ module ModelOutput {
import Specific::ModelOutputSpecific
private import codeql.mad.ModelValidation as SharedModelVal
/**
* Holds if a CSV source model contributed `source` with the given `kind`.
*/
API::Node getASourceNode(string kind) { result = getASourceNode(kind, _) }
/**
* Holds if a CSV sink model contributed `sink` with the given `kind`.
*/
API::Node getASinkNode(string kind) { result = getASinkNode(kind, _) }
private module KindValConfig implements SharedModelVal::KindValidationConfigSig {
predicate summaryKind(string kind) { summaryModel(_, _, _, _, kind) }
predicate summaryKind(string kind) { summaryModel(_, _, _, _, kind, _) }
predicate sinkKind(string kind) { sinkModel(_, _, kind) }
predicate sinkKind(string kind) { sinkModel(_, _, kind, _) }
predicate sourceKind(string kind) { sourceModel(_, _, kind) }
predicate sourceKind(string kind) { sourceModel(_, _, kind, _) }
}
private module KindVal = SharedModelVal::KindValidation<KindValConfig>;
@@ -694,25 +779,6 @@ module ModelOutput {
* Gets an error message relating to an invalid CSV row in a model.
*/
string getAWarning() {
// Check number of columns
exists(string row, string kind, int expectedArity, int actualArity |
any(SourceModelCsv csv).row(row) and kind = "source" and expectedArity = 3
or
any(SinkModelCsv csv).row(row) and kind = "sink" and expectedArity = 3
or
any(SummaryModelCsv csv).row(row) and kind = "summary" and expectedArity = 5
or
any(TypeModelCsv csv).row(row) and kind = "type" and expectedArity = 3
or
any(TypeVariableModelCsv csv).row(row) and kind = "type-variable" and expectedArity = 2
|
actualArity = count(row.indexOf(";")) + 1 and
actualArity != expectedArity and
result =
"CSV " + kind + " row should have " + expectedArity + " columns but has " + actualArity +
": " + row
)
or
// Check names and arguments of access path tokens
exists(AccessPath path, AccessPathToken token |
(isRelevantFullPath(_, path) or typeVariableModel(_, path)) and

View File

@@ -8,13 +8,15 @@
*
* The kind `remote` represents a general remote flow source.
*/
extensible predicate sourceModel(string type, string path, string kind);
extensible predicate sourceModel(
string type, string path, string kind, QlBuiltins::ExtensionId madId
);
/**
* Holds if the value at `(type, path)` should be seen as a sink
* of the given `kind`.
*/
extensible predicate sinkModel(string type, string path, string kind);
extensible predicate sinkModel(string type, string path, string kind, QlBuiltins::ExtensionId madId);
/**
* Holds if in calls to `(type, path)`, the value referred to by `input`
@@ -23,7 +25,9 @@ extensible predicate sinkModel(string type, string path, string kind);
* `kind` should be either `value` or `taint`, for value-preserving or taint-preserving steps,
* respectively.
*/
extensible predicate summaryModel(string type, string path, string input, string output, string kind);
extensible predicate summaryModel(
string type, string path, string input, string output, string kind, QlBuiltins::ExtensionId madId
);
/**
* Holds if calls to `(type, path)` should be considered neutral. The meaning of this depends on the `kind`.

View File

@@ -138,7 +138,7 @@ predicate invocationMatchesExtraCallSiteFilter(API::CallNode invoke, AccessPathT
pragma[nomagic]
private predicate relevantInputOutputPath(API::CallNode base, AccessPath inputOrOutput) {
exists(string type, string input, string output, string path |
ModelOutput::relevantSummaryModel(type, path, input, output, _) and
ModelOutput::relevantSummaryModel(type, path, input, output, _, _) and
ModelOutput::resolvedSummaryBase(type, path, base) and
inputOrOutput = [input, output]
)
@@ -170,7 +170,7 @@ private API::Node getNodeFromInputOutputPath(API::CallNode baseNode, AccessPath
*/
predicate summaryStep(API::Node pred, API::Node succ, string kind) {
exists(string type, string path, API::CallNode base, AccessPath input, AccessPath output |
ModelOutput::relevantSummaryModel(type, path, input, output, kind) and
ModelOutput::relevantSummaryModel(type, path, input, output, kind, _) and // TODO???
ModelOutput::resolvedSummaryBase(type, path, base) and
pred = getNodeFromInputOutputPath(base, input) and
succ = getNodeFromInputOutputPath(base, output)

View File

@@ -157,12 +157,12 @@ class ExternalApiDataNode extends DataFlow::Node {
ExternalApiDataNode() {
exists(InterestingExternalApiCall call | this = call.getArgument(_)) and
// Not already modeled as a taint step
not TaintTrackingPrivate::defaultAdditionalTaintStep(this, _) and
not TaintTrackingPrivate::defaultAdditionalTaintStep(this, _, _) and
// for `list.append(x)`, we have a additional taint step from x -> [post] list.
// Since we have modeled this explicitly, I don't see any cases where we would want to report this.
not exists(DataFlow::PostUpdateNode post |
post.getPreUpdateNode() = this and
TaintTrackingPrivate::defaultAdditionalTaintStep(_, post)
TaintTrackingPrivate::defaultAdditionalTaintStep(_, post, _)
)
}
}

View File

@@ -0,0 +1 @@
| 2 |

View File

@@ -0,0 +1,3 @@
import python
select count(Ellipsis e)

View File

@@ -0,0 +1,6 @@
a = {}
a[...] = 1
b = a[
...]
print(b)

View File

@@ -0,0 +1,23 @@
| test.py | 0 | Entry node for Module test | 1 | ControlFlowNode for FunctionExpr | normal |
| test.py | 1 | ControlFlowNode for FunctionExpr | 1 | ControlFlowNode for f | normal |
| test.py | 1 | ControlFlowNode for f | 0 | Exit node for Module test | normal |
| test.py | 1 | ControlFlowNode for x | 2 | ControlFlowNode for exec | normal |
| test.py | 1 | Entry node for Function f | 1 | ControlFlowNode for x | normal |
| test.py | 2 | ControlFlowNode for Str | 2 | ControlFlowNode for exec() | normal |
| test.py | 2 | ControlFlowNode for exec | 2 | ControlFlowNode for Str | normal |
| test.py | 2 | ControlFlowNode for exec() | 3 | ControlFlowNode for x | normal |
| test.py | 3 | ControlFlowNode for Return | 1 | Exit node for Function f | normal |
| test.py | 3 | ControlFlowNode for x | 3 | ControlFlowNode for Return | normal |
| unicode.py | 0 | Entry node for Module unicode | 1 | ControlFlowNode for ImportExpr | normal |
| unicode.py | 1 | ControlFlowNode for ImportExpr | 1 | ControlFlowNode for ImportMember | normal |
| unicode.py | 1 | ControlFlowNode for ImportMember | 1 | ControlFlowNode for unicode_literals | normal |
| unicode.py | 1 | ControlFlowNode for unicode_literals | 3 | ControlFlowNode for FunctionExpr | normal |
| unicode.py | 3 | ControlFlowNode for FunctionExpr | 3 | ControlFlowNode for f | normal |
| unicode.py | 3 | ControlFlowNode for f | 0 | Exit node for Module unicode | normal |
| unicode.py | 3 | ControlFlowNode for x | 4 | ControlFlowNode for exec | normal |
| unicode.py | 3 | Entry node for Function f | 3 | ControlFlowNode for x | normal |
| unicode.py | 4 | ControlFlowNode for Str | 4 | ControlFlowNode for exec() | normal |
| unicode.py | 4 | ControlFlowNode for exec | 4 | ControlFlowNode for Str | normal |
| unicode.py | 4 | ControlFlowNode for exec() | 5 | ControlFlowNode for x | normal |
| unicode.py | 5 | ControlFlowNode for Return | 3 | Exit node for Function f | normal |
| unicode.py | 5 | ControlFlowNode for x | 5 | ControlFlowNode for Return | normal |

View File

@@ -0,0 +1,14 @@
import python
from ControlFlowNode p, ControlFlowNode s, string kind, string filename
where
p.getASuccessor() = s and
(
p.getAnExceptionalSuccessor() = s and kind = "exception"
or
not p.getAnExceptionalSuccessor() = s and kind = "normal"
) and
filename = p.getLocation().getFile().getShortName() and
not filename = "__future__.py"
select filename, p.getLocation().getStartLine(), p.toString(), s.getLocation().getStartLine(),
s.toString(), kind

View File

@@ -0,0 +1,3 @@
def f(x):
exec("raise thing")
return x

View File

@@ -0,0 +1,5 @@
from __future__ import unicode_literals
def f(x):
exec("raise thing")
return x

View File

@@ -0,0 +1,2 @@
semmle-extractor-options: -R . -p . --filter exclude:**/src_archive/**

View File

@@ -0,0 +1,4 @@
| folder/module.py |
| package |
| package/__init__.py |
| package/module.py |

View File

@@ -0,0 +1,5 @@
import python
from Container f
where exists(Module m | m.getPath() = f)
select f.toString()

View File

@@ -0,0 +1 @@
semmle-extractor-options: --lang=2 --max-import-depth=1

View File

@@ -0,0 +1,4 @@
| Module package |
| Module package.__init__ |
| Module sys |
| Module test |

View File

@@ -0,0 +1 @@
import package

View File

@@ -0,0 +1,6 @@
import python
from ModuleObject m
/* Exclude the builtins module as it has a different name under 2 and 3. */
where not m = theBuiltinModuleObject()
select m.toString()

View File

@@ -0,0 +1,6 @@
| test.py:3:1:3:11 | Str | \u0111\u0142e\u00b6\u014b\u00b6\u0142\u014b |
| test.py:3:15:3:19 | Str | hi |
| test.py:3:23:3:27 | Str | \n |
| test.py:4:1:4:11 | Str | \u0111\u0142e\u00b6\u014b\u00b6\u0142\u014b |
| test.py:4:15:4:19 | Str | hi |
| test.py:4:23:4:27 | Str | \n |

View File

@@ -0,0 +1,4 @@
import python
from StrConst s
select s, s.getText()

View File

@@ -0,0 +1 @@
automatic_locations: true

View File

@@ -0,0 +1,4 @@
#coding=utf8
b"đłe¶ŋ¶łŋ" + b"hi" + b"\n"
u"đłe¶ŋ¶łŋ" + u"hi" + u"\n"

View File

@@ -0,0 +1,7 @@
| int 0 | 0 |
| int 1 | 1 |
| int 2 | 2 |
| int 123745 | 123745 |
| int 268435455 | 268435455 |
| int 17216961135462248174 | 17216961135462248174 |
| int 100000000000000000000000000000000000000000000 | 100000000000000000000000000000000000000000000 |

View File

@@ -0,0 +1,16 @@
/**
* Much of the QL library handling integral values assumes that
* equivalence of the DB entities implies equivalence of the
* Python object and vice-versa.
* In Python 2, 1L == 1, which can cause problems, so we
* normalise all longs to ints.
*/
import python
from NumericObject n
where
exists(IntegerLiteral i | i.getLiteralObject() = n |
i.getEnclosingModule().getFile().getShortName() = "test.py"
)
select n.toString(), n.repr()

View File

@@ -0,0 +1,23 @@
#ints
0
0L
1
1L
2
2L
123745
123745L
0xfffffff
0xfffffffL
#Avoid values between 32 and 64 bits, as long is 32 bits on windows and 64 bits on 64 bit linux machines.
#longs
0xeeeeeeeeeeeeeeee
0xeeeeeeeeeeeeeeeeL
100000000000000000000000000000000000000000000
100000000000000000000000000000000000000000000L

View File

@@ -0,0 +1 @@
| 1 |

View File

@@ -0,0 +1,4 @@
import python
where exists(theSysModuleObject())
select 1

View File

@@ -0,0 +1 @@
import cStringIO

View File

@@ -0,0 +1 @@
| test.py:1:1:1:6 | Compare |

View File

@@ -0,0 +1 @@
1 <> 2

View File

@@ -0,0 +1,3 @@
import python
select any(Compare o)

View File

@@ -0,0 +1 @@
automatic_locations: true

View File

@@ -0,0 +1 @@
| Module test | test |

View File

@@ -0,0 +1,4 @@
import python
from Module m
select m.toString(), m.getName()

View File

@@ -0,0 +1 @@
| Syntax Error |

View File

@@ -0,0 +1,4 @@
import python
from SyntaxError s
select s.toString()

View File

@@ -0,0 +1,2 @@
Not python at all :(

View File

@@ -0,0 +1,35 @@
| Call | 2 | 17 | 2 | 28 |
| DictComp | 2 | 1 | 2 | 29 |
| ExprStmt | 2 | 1 | 2 | 29 |
| ExprStmt | 2 | 2 | 2 | 4 |
| ExprStmt | 3 | 1 | 3 | 14 |
| ExprStmt | 4 | 1 | 4 | 16 |
| ExprStmt | 4 | 3 | 4 | 3 |
| FastLocalsFunction | 2 | 1 | 2 | 29 |
| FastLocalsFunction | 4 | 1 | 4 | 16 |
| For | 2 | 1 | 2 | 29 |
| For | 4 | 1 | 4 | 16 |
| FunctionMetrics | 2 | 1 | 2 | 29 |
| FunctionMetrics | 4 | 1 | 4 | 16 |
| IntegerLiteral | 3 | 3 | 3 | 3 |
| IntegerLiteral | 3 | 6 | 3 | 6 |
| IntegerLiteral | 3 | 9 | 3 | 9 |
| IntegerLiteral | 3 | 12 | 3 | 12 |
| ModuleMetrics | 0 | 0 | 0 | 0 |
| Name | 2 | 1 | 2 | 29 |
| Name | 2 | 2 | 2 | 2 |
| Name | 2 | 4 | 2 | 4 |
| Name | 2 | 10 | 2 | 10 |
| Name | 2 | 12 | 2 | 12 |
| Name | 2 | 17 | 2 | 25 |
| Name | 2 | 27 | 2 | 27 |
| Name | 4 | 1 | 4 | 16 |
| Name | 4 | 3 | 4 | 3 |
| Name | 4 | 9 | 4 | 9 |
| Name | 4 | 14 | 4 | 14 |
| Set | 3 | 1 | 3 | 14 |
| SetComp | 4 | 1 | 4 | 16 |
| Tuple | 2 | 2 | 2 | 4 |
| Tuple | 2 | 10 | 2 | 12 |
| Yield | 2 | 2 | 2 | 4 |
| Yield | 4 | 3 | 4 | 3 |

View File

@@ -0,0 +1,5 @@
import python
from AstNode ast, Location l
where ast.getLocation() = l
select ast.getAQlClass(), l.getStartLine(), l.getStartColumn(), l.getEndLine(), l.getEndColumn()

View File

@@ -0,0 +1,5 @@
{k:v for k,v in enumerate(y)}
{ 1, 2, 3, 4 }
{ i for i in y }

View File

@@ -0,0 +1 @@
| Script \u0ca8\u0ca8\u0ccd\u0ca8_\u0cb8\u0ccd\u0c95\u0ccd\u0cb0\u0cbf\u0caa\u0ccd\u0c9f\u0ccd.py |

View File

@@ -0,0 +1,4 @@
import python
from Module m
select m.toString()

View File

@@ -0,0 +1,9 @@
# -*- coding: utf-8 -*-
import sys
from dbgimporter import import_and_enable_debugger
import_and_enable_debugger()
def ಏನದರ_ಮ():
print('ಏನೋ ಮಾಡಿದೆ'.encode(sys.stdout.encoding, errors='replace'))
ಏನದರ_ಮ()

View File

@@ -0,0 +1,8 @@
| 1 | AnnAssign | x | int | IntegerLiteral |
| 2 | AnnAssign | y | Thing | something() |
| 3 | AnnAssign | z | Any | ---- |
| 4 | AnnAssign | Attribute | complex | ---- |
| 5 | AnnAssign | Attribute | not_simple | None |
| 8 | AnnAssign | a | int | IntegerLiteral |
| 9 | AnnAssign | b | Thing | something() |
| 10 | AnnAssign | c | Any | ---- |

View File

@@ -0,0 +1,9 @@
import python
from AnnAssign a, string value
where
value = a.getValue().toString()
or
not exists(a.getValue()) and value = "----"
select a.getLocation().getStartLine(), a.toString(), a.getTarget().toString(),
a.getAnnotation().toString(), value

View File

@@ -0,0 +1,38 @@
| 0 | 0 | 0 | 0 | Module test |
| 1 | 1 | 1 | 1 | x |
| 1 | 1 | 1 | 10 | AnnAssign |
| 1 | 4 | 1 | 6 | int |
| 1 | 10 | 1 | 10 | IntegerLiteral |
| 2 | 1 | 2 | 1 | y |
| 2 | 1 | 2 | 22 | AnnAssign |
| 2 | 4 | 2 | 8 | Thing |
| 2 | 12 | 2 | 20 | something |
| 2 | 12 | 2 | 22 | something() |
| 3 | 1 | 3 | 1 | z |
| 3 | 1 | 3 | 6 | AnnAssign |
| 3 | 4 | 3 | 6 | Any |
| 4 | 1 | 4 | 1 | a |
| 4 | 1 | 4 | 3 | Attribute |
| 4 | 1 | 4 | 13 | AnnAssign |
| 4 | 7 | 4 | 13 | complex |
| 5 | 1 | 5 | 1 | c |
| 5 | 1 | 5 | 3 | Attribute |
| 5 | 1 | 5 | 23 | AnnAssign |
| 5 | 7 | 5 | 16 | not_simple |
| 5 | 20 | 5 | 23 | None |
| 7 | 1 | 7 | 8 | Function f |
| 7 | 1 | 7 | 8 | FunctionDef |
| 7 | 1 | 7 | 8 | FunctionExpr |
| 7 | 5 | 7 | 5 | f |
| 8 | 5 | 8 | 5 | a |
| 8 | 5 | 8 | 14 | AnnAssign |
| 8 | 8 | 8 | 10 | int |
| 8 | 14 | 8 | 14 | IntegerLiteral |
| 9 | 5 | 9 | 5 | b |
| 9 | 5 | 9 | 26 | AnnAssign |
| 9 | 8 | 9 | 12 | Thing |
| 9 | 16 | 9 | 24 | something |
| 9 | 16 | 9 | 26 | something() |
| 10 | 5 | 10 | 5 | c |
| 10 | 5 | 10 | 10 | AnnAssign |
| 10 | 8 | 10 | 10 | Any |

View File

@@ -0,0 +1,5 @@
import python
from AstNode a, Location l
where l = a.getLocation()
select l.getStartLine(), l.getStartColumn(), l.getEndLine(), l.getEndColumn(), a.toString()

View File

@@ -0,0 +1,34 @@
| 0 | Module test | 1 | IntegerLiteral |
| 1 | AnnAssign | 2 | something |
| 1 | IntegerLiteral | 1 | x |
| 1 | int | 1 | AnnAssign |
| 1 | x | 1 | int |
| 2 | AnnAssign | 3 | z |
| 2 | Thing | 2 | AnnAssign |
| 2 | something | 2 | something() |
| 2 | something() | 2 | y |
| 2 | y | 2 | Thing |
| 3 | AnnAssign | 4 | a |
| 3 | Any | 3 | AnnAssign |
| 3 | z | 3 | Any |
| 4 | AnnAssign | 5 | None |
| 4 | Attribute | 4 | complex |
| 4 | a | 4 | Attribute |
| 4 | complex | 4 | AnnAssign |
| 5 | AnnAssign | 7 | FunctionExpr |
| 5 | Attribute | 5 | not_simple |
| 5 | None | 5 | c |
| 5 | c | 5 | Attribute |
| 5 | not_simple | 5 | AnnAssign |
| 7 | Function f | 8 | IntegerLiteral |
| 7 | FunctionExpr | 7 | f |
| 7 | f | 0 | Module test |
| 8 | AnnAssign | 9 | something |
| 8 | IntegerLiteral | 8 | a |
| 8 | a | 8 | AnnAssign |
| 9 | AnnAssign | 10 | c |
| 9 | b | 9 | AnnAssign |
| 9 | something | 9 | something() |
| 9 | something() | 9 | b |
| 10 | AnnAssign | 7 | Function f |
| 10 | c | 10 | AnnAssign |

View File

@@ -0,0 +1,6 @@
import python
from ControlFlowNode p, ControlFlowNode s
where p.getASuccessor() = s
select p.getLocation().getStartLine(), p.getNode().toString(), s.getLocation().getStartLine(),
s.getNode().toString()

View File

@@ -0,0 +1,10 @@
x: int = 0
y: Thing = something()
z: Any
a.x : complex
c.y : not_simple = None
def f():
a: int = 0
b: Thing = something()
c: Any

View File

@@ -0,0 +1 @@
| 3 | For |

View File

@@ -0,0 +1,4 @@
import python
from AsyncFor a
select a.getLocation().getStartLine(), a.toString()

View File

@@ -0,0 +1 @@
| 4 | With |

View File

@@ -0,0 +1,4 @@
import python
from AsyncWith aw
select aw.getLocation().getStartLine(), aw.toString()

View File

@@ -0,0 +1 @@
| 6 | Await |

View File

@@ -0,0 +1,4 @@
import python
from Await a
select a.getLocation().getStartLine(), a.toString()

View File

@@ -0,0 +1,8 @@
async def foo():
async for x in y:
async with a as b:
pass
await z

View File

@@ -0,0 +1,9 @@
| 7 | For | normal |
| 14 | For | async |
| 15 | For | normal |
| 16 | For | async |
| 17 | For | normal |
| 22 | For | normal |
| 23 | For | normal |
| 24 | For | normal |
| 25 | For | normal |

View File

@@ -0,0 +1,8 @@
import python
from For f, string kind
where
f instanceof AsyncFor and kind = "async"
or
not f instanceof AsyncFor and kind = "normal"
select f.getLocation().getStartLine(), f.toString(), kind

View File

@@ -0,0 +1,3 @@
| 9 | Await |
| 15 | Await |
| 17 | Await |

View File

@@ -0,0 +1,4 @@
import python
from Await a
select a.getLocation().getStartLine(), a.toString()

View File

@@ -0,0 +1,159 @@
| 0 | 0 | 0 | 0 | Module test |
| 5 | 7 | 5 | 28 | Function ticker |
| 5 | 7 | 5 | 28 | FunctionDef |
| 5 | 7 | 5 | 28 | FunctionExpr |
| 5 | 11 | 5 | 16 | ticker |
| 5 | 18 | 5 | 22 | delay |
| 5 | 25 | 5 | 26 | to |
| 6 | 5 | 6 | 61 | ExprStmt |
| 6 | 5 | 6 | 61 | Str |
| 7 | 5 | 7 | 23 | For |
| 7 | 9 | 7 | 9 | i |
| 7 | 14 | 7 | 18 | range |
| 7 | 14 | 7 | 22 | range() |
| 7 | 20 | 7 | 21 | to |
| 8 | 9 | 8 | 15 | ExprStmt |
| 8 | 9 | 8 | 15 | Yield |
| 8 | 15 | 8 | 15 | i |
| 9 | 9 | 9 | 34 | Await |
| 9 | 9 | 9 | 34 | ExprStmt |
| 9 | 15 | 9 | 21 | asyncio |
| 9 | 15 | 9 | 27 | Attribute |
| 9 | 15 | 9 | 34 | Attribute() |
| 9 | 29 | 9 | 33 | delay |
| 13 | 7 | 13 | 14 | Function f |
| 13 | 7 | 13 | 14 | FunctionDef |
| 13 | 7 | 13 | 14 | FunctionExpr |
| 13 | 11 | 13 | 11 | f |
| 14 | 5 | 14 | 5 | a |
| 14 | 5 | 14 | 43 | AssignStmt |
| 14 | 9 | 14 | 43 | .0 |
| 14 | 9 | 14 | 43 | For |
| 14 | 9 | 14 | 43 | Function listcomp |
| 14 | 9 | 14 | 43 | ListComp |
| 14 | 10 | 14 | 10 | ExprStmt |
| 14 | 10 | 14 | 10 | Yield |
| 14 | 10 | 14 | 10 | i |
| 14 | 22 | 14 | 22 | i |
| 14 | 27 | 14 | 31 | aiter |
| 14 | 27 | 14 | 33 | aiter() |
| 14 | 38 | 14 | 38 | i |
| 14 | 38 | 14 | 42 | BinaryExpr |
| 14 | 38 | 14 | 42 | If |
| 14 | 42 | 14 | 42 | IntegerLiteral |
| 15 | 5 | 15 | 5 | b |
| 15 | 5 | 15 | 59 | AssignStmt |
| 15 | 9 | 15 | 59 | .0 |
| 15 | 9 | 15 | 59 | For |
| 15 | 9 | 15 | 59 | Function listcomp |
| 15 | 9 | 15 | 59 | ListComp |
| 15 | 10 | 15 | 20 | Await |
| 15 | 10 | 15 | 20 | ExprStmt |
| 15 | 10 | 15 | 20 | Yield |
| 15 | 16 | 15 | 18 | fun |
| 15 | 16 | 15 | 20 | fun() |
| 15 | 26 | 15 | 28 | fun |
| 15 | 33 | 15 | 37 | funcs |
| 15 | 42 | 15 | 58 | Await |
| 15 | 42 | 15 | 58 | If |
| 15 | 48 | 15 | 56 | condition |
| 15 | 48 | 15 | 58 | condition() |
| 16 | 5 | 16 | 5 | c |
| 16 | 5 | 16 | 43 | AssignStmt |
| 16 | 9 | 16 | 43 | .0 |
| 16 | 9 | 16 | 43 | For |
| 16 | 9 | 16 | 43 | Function setcomp |
| 16 | 9 | 16 | 43 | SetComp |
| 16 | 10 | 16 | 10 | ExprStmt |
| 16 | 10 | 16 | 10 | Yield |
| 16 | 10 | 16 | 10 | i |
| 16 | 22 | 16 | 22 | i |
| 16 | 27 | 16 | 31 | aiter |
| 16 | 27 | 16 | 33 | aiter() |
| 16 | 38 | 16 | 38 | i |
| 16 | 38 | 16 | 42 | BinaryExpr |
| 16 | 38 | 16 | 42 | If |
| 16 | 42 | 16 | 42 | IntegerLiteral |
| 17 | 5 | 17 | 5 | d |
| 17 | 5 | 17 | 59 | AssignStmt |
| 17 | 9 | 17 | 59 | .0 |
| 17 | 9 | 17 | 59 | For |
| 17 | 9 | 17 | 59 | Function setcomp |
| 17 | 9 | 17 | 59 | SetComp |
| 17 | 10 | 17 | 20 | Await |
| 17 | 10 | 17 | 20 | ExprStmt |
| 17 | 10 | 17 | 20 | Yield |
| 17 | 16 | 17 | 18 | fun |
| 17 | 16 | 17 | 20 | fun() |
| 17 | 26 | 17 | 28 | fun |
| 17 | 33 | 17 | 37 | funcs |
| 17 | 42 | 17 | 58 | Await |
| 17 | 42 | 17 | 58 | If |
| 17 | 48 | 17 | 56 | condition |
| 17 | 48 | 17 | 58 | condition() |
| 21 | 1 | 21 | 8 | Function g |
| 21 | 1 | 21 | 8 | FunctionDef |
| 21 | 1 | 21 | 8 | FunctionExpr |
| 21 | 5 | 21 | 5 | g |
| 22 | 5 | 22 | 5 | a |
| 22 | 5 | 22 | 36 | AssignStmt |
| 22 | 9 | 22 | 36 | .0 |
| 22 | 9 | 22 | 36 | For |
| 22 | 9 | 22 | 36 | Function listcomp |
| 22 | 9 | 22 | 36 | ListComp |
| 22 | 10 | 22 | 10 | ExprStmt |
| 22 | 10 | 22 | 10 | Yield |
| 22 | 10 | 22 | 10 | i |
| 22 | 16 | 22 | 16 | i |
| 22 | 21 | 22 | 24 | iter |
| 22 | 21 | 22 | 26 | iter() |
| 22 | 31 | 22 | 31 | i |
| 22 | 31 | 22 | 35 | BinaryExpr |
| 22 | 31 | 22 | 35 | If |
| 22 | 35 | 22 | 35 | IntegerLiteral |
| 23 | 5 | 23 | 5 | b |
| 23 | 5 | 23 | 47 | AssignStmt |
| 23 | 9 | 23 | 47 | .0 |
| 23 | 9 | 23 | 47 | For |
| 23 | 9 | 23 | 47 | Function listcomp |
| 23 | 9 | 23 | 47 | ListComp |
| 23 | 10 | 23 | 12 | fun |
| 23 | 10 | 23 | 14 | ExprStmt |
| 23 | 10 | 23 | 14 | Yield |
| 23 | 10 | 23 | 14 | fun() |
| 23 | 20 | 23 | 22 | fun |
| 23 | 27 | 23 | 31 | funcs |
| 23 | 36 | 23 | 44 | condition |
| 23 | 36 | 23 | 46 | If |
| 23 | 36 | 23 | 46 | condition() |
| 24 | 5 | 24 | 5 | c |
| 24 | 5 | 24 | 36 | AssignStmt |
| 24 | 9 | 24 | 36 | .0 |
| 24 | 9 | 24 | 36 | For |
| 24 | 9 | 24 | 36 | Function setcomp |
| 24 | 9 | 24 | 36 | SetComp |
| 24 | 10 | 24 | 10 | ExprStmt |
| 24 | 10 | 24 | 10 | Yield |
| 24 | 10 | 24 | 10 | i |
| 24 | 16 | 24 | 16 | i |
| 24 | 21 | 24 | 24 | iter |
| 24 | 21 | 24 | 26 | iter() |
| 24 | 31 | 24 | 31 | i |
| 24 | 31 | 24 | 35 | BinaryExpr |
| 24 | 31 | 24 | 35 | If |
| 24 | 35 | 24 | 35 | IntegerLiteral |
| 25 | 5 | 25 | 5 | d |
| 25 | 5 | 25 | 47 | AssignStmt |
| 25 | 9 | 25 | 47 | .0 |
| 25 | 9 | 25 | 47 | For |
| 25 | 9 | 25 | 47 | Function setcomp |
| 25 | 9 | 25 | 47 | SetComp |
| 25 | 10 | 25 | 12 | fun |
| 25 | 10 | 25 | 14 | ExprStmt |
| 25 | 10 | 25 | 14 | Yield |
| 25 | 10 | 25 | 14 | fun() |
| 25 | 20 | 25 | 22 | fun |
| 25 | 27 | 25 | 31 | funcs |
| 25 | 36 | 25 | 44 | condition |
| 25 | 36 | 25 | 46 | If |
| 25 | 36 | 25 | 46 | condition() |

View File

@@ -0,0 +1,5 @@
import python
from AstNode a, Location l
where l = a.getLocation()
select l.getStartLine(), l.getStartColumn(), l.getEndLine(), l.getEndColumn(), a.toString()

View File

@@ -0,0 +1,32 @@
| 5 | Function ticker | 5 | delay |
| 5 | delay | 5 | to |
| 5 | to | 6 | Str |
| 6 | Str | 7 | range |
| 7 | For | 5 | Function ticker |
| 7 | For | 7 | i |
| 7 | i | 8 | i |
| 7 | range | 7 | to |
| 7 | range() | 7 | For |
| 7 | to | 7 | range() |
| 8 | Yield | 9 | asyncio |
| 8 | i | 8 | Yield |
| 9 | Attribute | 9 | delay |
| 9 | Attribute() | 9 | Await |
| 9 | Await | 7 | For |
| 9 | asyncio | 9 | Attribute |
| 9 | delay | 9 | Attribute() |
| 13 | Function f | 14 | aiter |
| 14 | ListComp | 14 | a |
| 14 | a | 15 | funcs |
| 14 | aiter | 14 | aiter() |
| 14 | aiter() | 14 | ListComp |
| 15 | ListComp | 15 | b |
| 15 | b | 16 | aiter |
| 15 | funcs | 15 | ListComp |
| 16 | SetComp | 16 | c |
| 16 | aiter | 16 | aiter() |
| 16 | aiter() | 16 | SetComp |
| 16 | c | 17 | funcs |
| 17 | SetComp | 17 | d |
| 17 | d | 13 | Function f |
| 17 | funcs | 17 | SetComp |

View File

@@ -0,0 +1,6 @@
import python
from ControlFlowNode p, ControlFlowNode s
where p.getASuccessor() = s and p.getScope().(Function).isAsync()
select p.getLocation().getStartLine(), p.getNode().toString(), s.getLocation().getStartLine(),
s.getNode().toString()

View File

@@ -0,0 +1,26 @@
#PEP 525
async def ticker(delay, to):
"""Yield numbers from 0 to *to* every *delay* seconds."""
for i in range(to):
yield i
await asyncio.sleep(delay)
#PEP 530
async def f():
a = [i async for i in aiter() if i % 2]
b = [await fun() for fun in funcs if await condition()]
c = {i async for i in aiter() if i % 2}
d = {await fun() for fun in funcs if await condition()}
# Not async versions
def g():
a = [i for i in iter() if i % 2]
b = [fun() for fun in funcs if condition()]
c = {i for i in iter() if i % 2}
d = {fun() for fun in funcs if condition()}

View File

@@ -0,0 +1,3 @@
@foo[0].bar
def baz():
pass

View File

@@ -0,0 +1,3 @@
import python
select any(SyntaxError s)

View File

@@ -0,0 +1,75 @@
| 2 | Fstring | 0 | Str |
| 2 | Fstring | 1 | world |
| 2 | Fstring | 2 | Str |
| 3 | Fstring | 0 | Str |
| 3 | Fstring | 1 | one |
| 3 | Fstring | 2 | Str |
| 3 | Fstring | 3 | two |
| 3 | Fstring | 4 | Str |
| 3 | Fstring | 5 | three |
| 3 | Fstring | 6 | Str |
| 4 | Fstring | 0 | Str |
| 4 | Fstring | 1 | cruel |
| 4 | Fstring | 2 | Str |
| 5 | Fstring | 0 | Str |
| 5 | Fstring | 1 | thing |
| 5 | Fstring | 2 | Str |
| 6 | Fstring | 0 | Str |
| 6 | Fstring | 1 | x |
| 6 | Fstring | 2 | Str |
| 8 | Fstring | 0 | Str |
| 8 | Fstring | 1 | name |
| 8 | Fstring | 2 | Str |
| 8 | Fstring | 3 | BinaryExpr |
| 8 | Fstring | 4 | Str |
| 8 | Fstring | 5 | anniversary |
| 8 | Fstring | 6 | Str |
| 13 | Fstring | 0 | Str |
| 13 | Fstring | 1 | world |
| 13 | Fstring | 2 | Str |
| 16 | Fstring | 0 | Str |
| 16 | Fstring | 1 | Tuple |
| 16 | Fstring | 2 | Str |
| 16 | Fstring | 3 | Tuple |
| 16 | Fstring | 4 | Str |
| 19 | Fstring | 0 | Str |
| 19 | Fstring | 1 | Tuple |
| 19 | Fstring | 2 | Str |
| 19 | Fstring | 3 | Tuple |
| 19 | Fstring | 4 | Str |
| 32 | Fstring | 0 | Str |
| 32 | Fstring | 1 | IntegerLiteral |
| 32 | Fstring | 2 | Str |
| 34 | Fstring | 0 | Str |
| 34 | Fstring | 1 | IntegerLiteral |
| 34 | Fstring | 2 | Str |
| 36 | Fstring | 0 | Str |
| 36 | Fstring | 1 | IntegerLiteral |
| 36 | Fstring | 2 | Str |
| 38 | Fstring | 0 | Str |
| 38 | Fstring | 1 | IntegerLiteral |
| 38 | Fstring | 2 | Str |
| 53 | Fstring | 0 | Str |
| 53 | Fstring | 1 | degrees |
| 53 | Fstring | 2 | Str |
| 56 | Fstring | 0 | Str |
| 56 | Fstring | 1 | IntegerLiteral |
| 56 | Fstring | 2 | Str |
| 59 | Fstring | 0 | Str |
| 59 | Fstring | 1 | IntegerLiteral |
| 59 | Fstring | 2 | Str |
| 62 | Fstring | 0 | Str |
| 62 | Fstring | 1 | IntegerLiteral |
| 62 | Fstring | 2 | Str |
| 67 | Fstring | 0 | Str |
| 67 | Fstring | 1 | IntegerLiteral |
| 67 | Fstring | 2 | Str |
| 70 | Fstring | 0 | Str |
| 70 | Fstring | 1 | IntegerLiteral |
| 70 | Fstring | 2 | Str |
| 75 | Fstring | 0 | Str |
| 75 | Fstring | 1 | IntegerLiteral |
| 75 | Fstring | 2 | Str |
| 78 | Fstring | 0 | Str |
| 78 | Fstring | 1 | IntegerLiteral |
| 78 | Fstring | 2 | Str |

View File

@@ -0,0 +1,7 @@
import python
from Fstring str, int n, Expr e
where
e = str.getValue(n) and
not exists(FormattedValue v | v.getFormatSpec() = str)
select str.getLocation().getStartLine(), str.toString(), n, e.toString()

View File

@@ -0,0 +1,11 @@
| 2 | FormattedValue | | world | s |
| 3 | FormattedValue | #06x | one | |
| 3 | FormattedValue | ++++ | three | s |
| 3 | FormattedValue | format | two | |
| 4 | FormattedValue | | cruel | |
| 5 | FormattedValue | | thing | a |
| 6 | FormattedValue | | x | r |
| 8 | FormattedValue | | BinaryExpr | |
| 8 | FormattedValue | | name | |
| 8 | FormattedValue | %A, %B %d, %Y | anniversary | |
| 13 | FormattedValue | | world | s |

Some files were not shown because too many files have changed in this diff Show More