mirror of
https://github.com/github/codeql.git
synced 2026-04-29 18:55:14 +02:00
Merge branch 'master' of github.com:github/codeql into SharedDataflow
to receive updates from data flow library
This commit is contained in:
@@ -1,3 +1,5 @@
|
||||
/** INTERNAL - Methods used by queries that test whether functions are invoked correctly. */
|
||||
|
||||
import python
|
||||
import Testing.Mox
|
||||
|
||||
@@ -71,36 +73,38 @@ private int positional_arg_count_for_call(Call call, Value callable) {
|
||||
)
|
||||
}
|
||||
|
||||
/** Gets the number of arguments in `call`. */
|
||||
int arg_count_objectapi(Call call) {
|
||||
result = count(call.getAnArg()) + varargs_length_objectapi(call) + count(call.getAKeyword())
|
||||
}
|
||||
|
||||
/** Gets the number of arguments in `call`. */
|
||||
int arg_count(Call call) {
|
||||
result = count(call.getAnArg()) + varargs_length(call) + count(call.getAKeyword())
|
||||
}
|
||||
|
||||
/* Gets a call corresponding to the given class or function*/
|
||||
/** Gets a call corresponding to the given class or function. */
|
||||
private ControlFlowNode get_a_call_objectapi(Object callable) {
|
||||
result = callable.(ClassObject).getACall()
|
||||
or
|
||||
result = callable.(FunctionObject).getACall()
|
||||
}
|
||||
|
||||
/* Gets a call corresponding to the given class or function*/
|
||||
/** Gets a call corresponding to the given class or function. */
|
||||
private ControlFlowNode get_a_call(Value callable) {
|
||||
result = callable.(ClassValue).getACall()
|
||||
or
|
||||
result = callable.(FunctionValue).getACall()
|
||||
}
|
||||
|
||||
/* Gets the function object corresponding to the given class or function*/
|
||||
/** Gets the function object corresponding to the given class or function. */
|
||||
FunctionObject get_function_or_initializer_objectapi(Object func_or_cls) {
|
||||
result = func_or_cls.(FunctionObject)
|
||||
or
|
||||
result = func_or_cls.(ClassObject).declaredAttribute("__init__")
|
||||
}
|
||||
|
||||
/* Gets the function object corresponding to the given class or function*/
|
||||
/** Gets the function object corresponding to the given class or function. */
|
||||
FunctionValue get_function_or_initializer(Value func_or_cls) {
|
||||
result = func_or_cls.(FunctionValue)
|
||||
or
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import python
|
||||
|
||||
/** A string constant that looks like it may be used in string formatting operations. */
|
||||
library class PossibleAdvancedFormatString extends StrConst {
|
||||
PossibleAdvancedFormatString() { this.getText().matches("%{%}%") }
|
||||
|
||||
@@ -51,6 +52,7 @@ library class PossibleAdvancedFormatString extends StrConst {
|
||||
predicate isExplicitlyNumbered() { exists(this.fieldId(_, _).toInt()) }
|
||||
}
|
||||
|
||||
/** Holds if the formatting string `fmt` contains a sequence of braces `{` of length `len`, beginning at index `index`. */
|
||||
predicate brace_sequence(PossibleAdvancedFormatString fmt, int index, int len) {
|
||||
exists(string text | text = fmt.getText() |
|
||||
text.charAt(index) = "{" and not text.charAt(index - 1) = "{" and len = 1
|
||||
@@ -61,10 +63,12 @@ predicate brace_sequence(PossibleAdvancedFormatString fmt, int index, int len) {
|
||||
)
|
||||
}
|
||||
|
||||
/** Holds if index `index` in the format string `fmt` contains an escaped brace `{`. */
|
||||
predicate escaped_brace(PossibleAdvancedFormatString fmt, int index) {
|
||||
exists(int len | brace_sequence(fmt, index, len) | len % 2 = 0)
|
||||
}
|
||||
|
||||
/** Holds if index `index` in the format string `fmt` contains a left brace `{` that acts as an escape character. */
|
||||
predicate escaping_brace(PossibleAdvancedFormatString fmt, int index) {
|
||||
escaped_brace(fmt, index + 1)
|
||||
}
|
||||
@@ -105,15 +109,18 @@ private predicate advanced_format_call(Call format_expr, PossibleAdvancedFormatS
|
||||
)
|
||||
}
|
||||
|
||||
/** A string constant that has the `format` method applied to it. */
|
||||
class AdvancedFormatString extends PossibleAdvancedFormatString {
|
||||
AdvancedFormatString() { advanced_format_call(_, this, _) }
|
||||
}
|
||||
|
||||
/** A string formatting operation that uses the `format` method. */
|
||||
class AdvancedFormattingCall extends Call {
|
||||
AdvancedFormattingCall() { advanced_format_call(this, _, _) }
|
||||
|
||||
/** Count of the arguments actually provided */
|
||||
int providedArgCount() { advanced_format_call(this, _, result) }
|
||||
|
||||
/** Gets a formatting string for this call. */
|
||||
AdvancedFormatString getAFormat() { advanced_format_call(this, result, _) }
|
||||
}
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
/** INTERNAL - Helper predicates for queries that inspect the comparison of objects using `is`. */
|
||||
|
||||
import python
|
||||
|
||||
/** Holds if the comparison `comp` uses `is` or `is not` (represented as `op`) to compare its `left` and `right` arguments. */
|
||||
predicate comparison_using_is(Compare comp, ControlFlowNode left, Cmpop op, ControlFlowNode right) {
|
||||
exists(CompareNode fcomp | fcomp = comp.getAFlowNode() |
|
||||
fcomp.operands(left, op, right) and
|
||||
@@ -7,6 +10,7 @@ predicate comparison_using_is(Compare comp, ControlFlowNode left, Cmpop op, Cont
|
||||
)
|
||||
}
|
||||
|
||||
/** Holds if the class `c` overrides the default notion of equality or comparison. */
|
||||
predicate overrides_eq_or_cmp(ClassValue c) {
|
||||
major_version() = 2 and c.hasAttribute("__eq__")
|
||||
or
|
||||
@@ -19,12 +23,14 @@ predicate overrides_eq_or_cmp(ClassValue c) {
|
||||
major_version() = 2 and c.hasAttribute("__cmp__")
|
||||
}
|
||||
|
||||
/** Holds if the class `cls` is likely to only have a single instance throughout the program. */
|
||||
predicate probablySingleton(ClassValue cls) {
|
||||
strictcount(Value inst | inst.getClass() = cls) = 1
|
||||
or
|
||||
cls = Value::named("None").getClass()
|
||||
}
|
||||
|
||||
/** Holds if using `is` to compare instances of the class `c` is likely to cause unexpected behavior. */
|
||||
predicate invalid_to_use_is_portably(ClassValue c) {
|
||||
overrides_eq_or_cmp(c) and
|
||||
// Exclude type/builtin-function/bool as it is legitimate to compare them using 'is' but they implement __eq__
|
||||
@@ -35,6 +41,7 @@ predicate invalid_to_use_is_portably(ClassValue c) {
|
||||
not probablySingleton(c)
|
||||
}
|
||||
|
||||
/** Holds if the control flow node `f` points to either `True`, `False`, or `None`. */
|
||||
predicate simple_constant(ControlFlowNode f) {
|
||||
exists(Value val | f.pointsTo(val) |
|
||||
val = Value::named("True") or val = Value::named("False") or val = Value::named("None")
|
||||
@@ -66,10 +73,12 @@ private predicate universally_interned_value(Expr e) {
|
||||
e.(StrConst).getText() = ""
|
||||
}
|
||||
|
||||
/** Holds if the expression `e` points to an interned constant in CPython. */
|
||||
predicate cpython_interned_constant(Expr e) {
|
||||
exists(Expr const | e.pointsTo(_, const) | cpython_interned_value(const))
|
||||
}
|
||||
|
||||
/** Holds if the expression `e` points to a value that can be reasonably expected to be interned across all implementations of Python. */
|
||||
predicate universally_interned_constant(Expr e) {
|
||||
exists(Expr const | e.pointsTo(_, const) | universally_interned_value(const))
|
||||
}
|
||||
@@ -92,6 +101,9 @@ private predicate comparison_one_type(Compare comp, Cmpop op, ClassValue cls) {
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if using `is` or `is not` as the operator `op` in the comparison `comp` would be invalid when applied to the class `cls`.
|
||||
*/
|
||||
predicate invalid_portable_is_comparison(Compare comp, Cmpop op, ClassValue cls) {
|
||||
// OK to use 'is' when defining '__eq__'
|
||||
not exists(Function eq | eq.getName() = "__eq__" or eq.getName() = "__ne__" |
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
/** Helper functions for queries that test redundant comparisons. */
|
||||
|
||||
import python
|
||||
|
||||
/** A comparison where the left and right hand sides appear to be identical. */
|
||||
class RedundantComparison extends Compare {
|
||||
RedundantComparison() {
|
||||
exists(Expr left, Expr right |
|
||||
@@ -8,6 +11,15 @@ class RedundantComparison extends Compare {
|
||||
)
|
||||
}
|
||||
|
||||
/** Holds if this comparison could be redundant due to a missing `self.`, for example
|
||||
* ```python
|
||||
* foo == foo
|
||||
* ```
|
||||
* instead of
|
||||
* ```python
|
||||
* self.foo == foo
|
||||
* ```
|
||||
*/
|
||||
predicate maybeMissingSelf() {
|
||||
exists(Name left |
|
||||
this.compares(left, _, _) and
|
||||
|
||||
@@ -175,6 +175,7 @@ class CommentedOutCodeLine extends Comment {
|
||||
class CommentedOutCodeBlock extends @py_comment {
|
||||
CommentedOutCodeBlock() { commented_out_code_block(this, _) }
|
||||
|
||||
/** Gets a textual representation of this element. */
|
||||
string toString() { result = "Commented out code" }
|
||||
|
||||
/** Whether this commented-out code block contains the comment c */
|
||||
@@ -191,10 +192,19 @@ class CommentedOutCodeBlock extends @py_comment {
|
||||
/** The length of this comment block (in comments) */
|
||||
int length() { result = count(Comment c | this.contains(c)) }
|
||||
|
||||
predicate hasLocationInfo(string filepath, int bl, int bc, int el, int ec) {
|
||||
this.(Comment).getLocation().hasLocationInfo(filepath, bl, bc, _, _) and
|
||||
/**
|
||||
* Holds if this element is at the specified location.
|
||||
* The location spans column `startcolumn` of line `startline` to
|
||||
* column `endcolumn` of line `endline` in file `filepath`.
|
||||
* For more information, see
|
||||
* [Locations](https://help.semmle.com/QL/learn-ql/ql/locations.html).
|
||||
*/
|
||||
predicate hasLocationInfo(
|
||||
string filepath, int startline, int startcolumn, int endline, int endcolumn
|
||||
) {
|
||||
this.(Comment).getLocation().hasLocationInfo(filepath, startline, startcolumn, _, _) and
|
||||
exists(Comment end | commented_out_code_block(this, end) |
|
||||
end.getLocation().hasLocationInfo(_, _, _, el, ec)
|
||||
end.getLocation().hasLocationInfo(_, _, _, endline, endcolumn)
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -15,9 +15,17 @@ import python
|
||||
* including the body (if any), as opposed to the location of its name only.
|
||||
*/
|
||||
class RangeFunction extends Function {
|
||||
predicate hasLocationInfo(string path, int sl, int sc, int el, int ec) {
|
||||
super.getLocation().hasLocationInfo(path, sl, sc, _, _) and
|
||||
this.getBody().getLastItem().getLocation().hasLocationInfo(path, _, _, el, ec)
|
||||
/**
|
||||
* Holds if this element is at the specified location.
|
||||
* The location spans column `startcolumn` of line `startline` to
|
||||
* column `endcolumn` of line `endline` in file `filepath`.
|
||||
* For more information, see
|
||||
* [Locations](https://help.semmle.com/QL/learn-ql/ql/locations.html).
|
||||
*/
|
||||
predicate hasLocationInfo(
|
||||
string filepath, int startline, int startcolumn, int endline, int endcolumn
|
||||
) { super.getLocation().hasLocationInfo(filepath, startline, startcolumn, _, _) and
|
||||
this.getBody().getLastItem().getLocation().hasLocationInfo(filepath, _, _, endline, endcolumn)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,8 +34,16 @@ class RangeFunction extends Function {
|
||||
* including the body (if any), as opposed to the location of its name only.
|
||||
*/
|
||||
class RangeClass extends Class {
|
||||
predicate hasLocationInfo(string path, int sl, int sc, int el, int ec) {
|
||||
super.getLocation().hasLocationInfo(path, sl, sc, _, _) and
|
||||
this.getBody().getLastItem().getLocation().hasLocationInfo(path, _, _, el, ec)
|
||||
/**
|
||||
* Holds if this element is at the specified location.
|
||||
* The location spans column `startcolumn` of line `startline` to
|
||||
* column `endcolumn` of line `endline` in file `filepath`.
|
||||
* For more information, see
|
||||
* [Locations](https://help.semmle.com/QL/learn-ql/ql/locations.html).
|
||||
*/
|
||||
predicate hasLocationInfo(
|
||||
string filepath, int startline, int startcolumn, int endline, int endcolumn
|
||||
) { super.getLocation().hasLocationInfo(filepath, startline, startcolumn, _, _) and
|
||||
this.getBody().getLastItem().getLocation().hasLocationInfo(filepath, _, _, endline, endcolumn)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
/** Contains predicates concerning when and where files are opened and closed. */
|
||||
|
||||
import python
|
||||
import semmle.python.GuardedControlFlow
|
||||
import semmle.python.pointsto.Filters
|
||||
@@ -113,12 +115,14 @@ predicate close_method_call(CallNode call, ControlFlowNode self) {
|
||||
call.getFunction().(AttrNode).getObject("close") = self
|
||||
}
|
||||
|
||||
/** Holds if `close` is a function that appears to close files that are passed to it as an argument. */
|
||||
predicate function_closes_file(FunctionValue close) {
|
||||
close = Value::named("os.close")
|
||||
or
|
||||
function_should_close_parameter(close.getScope())
|
||||
}
|
||||
|
||||
/** INTERNAL - Helper predicate for `function_closes_file` */
|
||||
predicate function_should_close_parameter(Function func) {
|
||||
exists(EssaDefinition def |
|
||||
closes_file(def) and
|
||||
@@ -126,6 +130,7 @@ predicate function_should_close_parameter(Function func) {
|
||||
)
|
||||
}
|
||||
|
||||
/** Holds if the function `f` opens a file, either directly or indirectly. */
|
||||
predicate function_opens_file(FunctionValue f) {
|
||||
f = Value::named("open")
|
||||
or
|
||||
@@ -140,6 +145,7 @@ predicate function_opens_file(FunctionValue f) {
|
||||
)
|
||||
}
|
||||
|
||||
/** Holds if the variable `v` refers to a file opened at `open` which is subsequently returned from a function. */
|
||||
predicate file_is_returned(EssaVariable v, ControlFlowNode open) {
|
||||
exists(NameNode n, Return ret |
|
||||
var_is_open(v, open) and
|
||||
|
||||
@@ -10,6 +10,7 @@ private newtype TDefinition =
|
||||
|
||||
/** A definition for the purposes of jump-to-definition. */
|
||||
class Definition extends TLocalDefinition {
|
||||
/** Gets a textual representation of this element. */
|
||||
string toString() { result = "Definition " + this.getAstNode().getLocation().toString() }
|
||||
|
||||
AstNode getAstNode() { this = TLocalDefinition(result) }
|
||||
@@ -467,8 +468,15 @@ Definition getUniqueDefinition(Expr use) {
|
||||
|
||||
/** Helper class to get suitable locations for attributes */
|
||||
class NiceLocationExpr extends @py_expr {
|
||||
/** Gets a textual representation of this element. */
|
||||
string toString() { result = this.(Expr).toString() }
|
||||
|
||||
/**
|
||||
* Holds if this element is at the specified location.
|
||||
* The location spans column `bc` of line `bl` to
|
||||
* column `ec` of line `el` in file `f`.
|
||||
* For more information, see
|
||||
* [Locations](https://help.semmle.com/QL/learn-ql/ql/locations.html).
|
||||
*/
|
||||
predicate hasLocationInfo(string f, int bl, int bc, int el, int ec) {
|
||||
/* Attribute location for x.y is that of 'y' so that url does not overlap with that of 'x' */
|
||||
exists(int abl, int abc | this.(Attribute).getLocation().hasLocationInfo(f, abl, abc, el, ec) |
|
||||
|
||||
18
python/ql/src/experimental/CWE-091/Xslt.qhelp
Normal file
18
python/ql/src/experimental/CWE-091/Xslt.qhelp
Normal file
@@ -0,0 +1,18 @@
|
||||
<!DOCTYPE qhelp SYSTEM "qhelp.dtd">
|
||||
<qhelp>
|
||||
<overview>
|
||||
<p>
|
||||
Processing an unvalidated XSL stylesheet can allow an attacker to change the structure and contents of the resultant XML, include arbitrary files from the file system, or execute arbitrary code.
|
||||
</p>
|
||||
</overview>
|
||||
<recommendation>
|
||||
<p>
|
||||
This vulnerability can be prevented by not allowing untrusted user input to be passed as an XSL stylesheet.
|
||||
If the application logic necessiates processing untrusted XSL stylesheets, the input should be properly filtered and sanitized before use.
|
||||
</p>
|
||||
</recommendation>
|
||||
<example>
|
||||
<p>In the example below, the XSL stylesheet is controlled by the user and hence leads to a vulnerability.</p>
|
||||
<sample src="xslt.py" />
|
||||
</example>
|
||||
</qhelp>
|
||||
35
python/ql/src/experimental/CWE-091/Xslt.ql
Normal file
35
python/ql/src/experimental/CWE-091/Xslt.ql
Normal file
@@ -0,0 +1,35 @@
|
||||
/**
|
||||
* @name XSLT query built from user-controlled sources
|
||||
* @description Building a XSLT query from user-controlled sources is vulnerable to insertion of
|
||||
* malicious XSLT code by the user.
|
||||
* @kind path-problem
|
||||
* @problem.severity error
|
||||
* @precision high
|
||||
* @id py/xslt-injection
|
||||
* @tags security
|
||||
* external/cwe/cwe-643
|
||||
*/
|
||||
|
||||
import python
|
||||
import semmle.python.security.Paths
|
||||
/* Sources */
|
||||
import semmle.python.web.HttpRequest
|
||||
/* Sinks */
|
||||
import experimental.semmle.python.security.injection.XSLT
|
||||
|
||||
class XSLTInjectionConfiguration extends TaintTracking::Configuration {
|
||||
XSLTInjectionConfiguration() { this = "XSLT injection configuration" }
|
||||
|
||||
override predicate isSource(TaintTracking::Source source) {
|
||||
source instanceof HttpRequestTaintSource
|
||||
}
|
||||
|
||||
override predicate isSink(TaintTracking::Sink sink) {
|
||||
sink instanceof XSLTInjection::XSLTInjectionSink
|
||||
}
|
||||
}
|
||||
|
||||
from XSLTInjectionConfiguration config, TaintedPathSource src, TaintedPathSink sink
|
||||
where config.hasFlowPath(src, sink)
|
||||
select sink.getSink(), src, sink, "This XSLT query depends on $@.", src.getSource(),
|
||||
"a user-provided value"
|
||||
14
python/ql/src/experimental/CWE-091/xslt.py
Normal file
14
python/ql/src/experimental/CWE-091/xslt.py
Normal file
@@ -0,0 +1,14 @@
|
||||
from lxml import etree
|
||||
from io import StringIO
|
||||
from flask import Flask, request
|
||||
|
||||
app = Flask(__name__)
|
||||
|
||||
|
||||
@app.route("/xslt")
|
||||
def bad():
|
||||
xsltQuery = request.args.get('xml', '')
|
||||
xslt_root = etree.XML(xsltQuery)
|
||||
f = StringIO('<foo><bar></bar></foo>')
|
||||
tree = etree.parse(f)
|
||||
result_tree = tree.xslt(xslt_root) # Not OK
|
||||
@@ -0,0 +1,115 @@
|
||||
/**
|
||||
* Provides class and predicates to track external data that
|
||||
* may represent malicious XSLT query objects.
|
||||
*
|
||||
* This module is intended to be imported into a taint-tracking query
|
||||
* to extend `TaintKind` and `TaintSink`.
|
||||
*/
|
||||
|
||||
import python
|
||||
import semmle.python.dataflow.TaintTracking
|
||||
import semmle.python.web.HttpRequest
|
||||
|
||||
/** Models XSLT Injection related classes and functions */
|
||||
module XSLTInjection {
|
||||
/** Returns a class value which refers to `lxml.etree` */
|
||||
Value etree() { result = Value::named("lxml.etree") }
|
||||
|
||||
/** A generic taint sink that is vulnerable to XSLT injection. */
|
||||
abstract class XSLTInjectionSink extends TaintSink { }
|
||||
|
||||
/**
|
||||
* A kind of "taint", representing an untrusted XML string
|
||||
*/
|
||||
private class ExternalXmlStringKind extends ExternalStringKind {
|
||||
ExternalXmlStringKind() { this = "etree.XML string" }
|
||||
|
||||
override TaintKind getTaintForFlowStep(ControlFlowNode fromnode, ControlFlowNode tonode) {
|
||||
etreeXML(fromnode, tonode) and result instanceof ExternalXmlKind
|
||||
or
|
||||
etreeFromStringList(fromnode, tonode) and result instanceof ExternalXmlKind
|
||||
or
|
||||
etreeFromString(fromnode, tonode) and result instanceof ExternalXmlKind
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A kind of "taint", representing a XML encoded string
|
||||
*/
|
||||
class ExternalXmlKind extends TaintKind {
|
||||
ExternalXmlKind() { this = "lxml etree xml" }
|
||||
}
|
||||
|
||||
private predicate etreeXML(ControlFlowNode fromnode, CallNode tonode) {
|
||||
// etree.XML("<xmlContent>")
|
||||
exists(CallNode call | call.getFunction().(AttrNode).getObject("XML").pointsTo(etree()) |
|
||||
call.getArg(0) = fromnode and
|
||||
call = tonode
|
||||
)
|
||||
}
|
||||
|
||||
private predicate etreeFromString(ControlFlowNode fromnode, CallNode tonode) {
|
||||
// etree.fromstring(text, parser=None)
|
||||
exists(CallNode call | call.getFunction().(AttrNode).getObject("fromstring").pointsTo(etree()) |
|
||||
call.getArg(0) = fromnode and
|
||||
call = tonode
|
||||
)
|
||||
}
|
||||
|
||||
private predicate etreeFromStringList(ControlFlowNode fromnode, CallNode tonode) {
|
||||
// etree.fromstringlist(strings, parser=None)
|
||||
exists(CallNode call |
|
||||
call.getFunction().(AttrNode).getObject("fromstringlist").pointsTo(etree())
|
||||
|
|
||||
call.getArg(0) = fromnode and
|
||||
call = tonode
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* A Sink representing an argument to the `etree.XSLT` call.
|
||||
*
|
||||
* from lxml import etree
|
||||
* root = etree.XML("<xmlContent>")
|
||||
* find_text = etree.XSLT("`sink`")
|
||||
*/
|
||||
private class EtreeXSLTArgument extends XSLTInjectionSink {
|
||||
override string toString() { result = "lxml.etree.XSLT" }
|
||||
|
||||
EtreeXSLTArgument() {
|
||||
exists(CallNode call | call.getFunction().(AttrNode).getObject("XSLT").pointsTo(etree()) |
|
||||
call.getArg(0) = this
|
||||
)
|
||||
}
|
||||
|
||||
override predicate sinks(TaintKind kind) { kind instanceof ExternalXmlKind }
|
||||
}
|
||||
|
||||
/**
|
||||
* A Sink representing an argument to the `XSLT` call to a parsed xml document.
|
||||
*
|
||||
* from lxml import etree
|
||||
* from io import StringIO
|
||||
* `sink` = etree.XML(xsltQuery)
|
||||
* tree = etree.parse(f)
|
||||
* result_tree = tree.xslt(`sink`)
|
||||
*/
|
||||
private class ParseXSLTArgument extends XSLTInjectionSink {
|
||||
override string toString() { result = "lxml.etree.parse.xslt" }
|
||||
|
||||
ParseXSLTArgument() {
|
||||
exists(
|
||||
CallNode parseCall, CallNode xsltCall, ControlFlowNode obj, Variable var, AssignStmt assign
|
||||
|
|
||||
parseCall.getFunction().(AttrNode).getObject("parse").pointsTo(etree()) and
|
||||
assign.getValue().(Call).getAFlowNode() = parseCall and
|
||||
xsltCall.getFunction().(AttrNode).getObject("xslt") = obj and
|
||||
var.getAUse() = obj and
|
||||
assign.getATarget() = var.getAStore() and
|
||||
xsltCall.getArg(0) = this
|
||||
)
|
||||
}
|
||||
|
||||
override predicate sinks(TaintKind kind) { kind instanceof ExternalXmlKind }
|
||||
}
|
||||
}
|
||||
17
python/ql/src/external/DefectFilter.qll
vendored
17
python/ql/src/external/DefectFilter.qll
vendored
@@ -26,7 +26,9 @@ class DefectResult extends int {
|
||||
|
||||
/** Gets the file in which this query result was reported. */
|
||||
File getFile() {
|
||||
exists(string path | defectResults(this, _, path, _, _, _, _, _) and result.getAbsolutePath() = path)
|
||||
exists(string path |
|
||||
defectResults(this, _, path, _, _, _, _, _) and result.getAbsolutePath() = path
|
||||
)
|
||||
}
|
||||
|
||||
/** Gets the file path in which this query result was reported. */
|
||||
@@ -47,8 +49,17 @@ class DefectResult extends int {
|
||||
/** Gets the message associated with this query result. */
|
||||
string getMessage() { defectResults(this, _, _, _, _, _, _, result) }
|
||||
|
||||
predicate hasLocationInfo(string path, int sl, int sc, int el, int ec) {
|
||||
defectResults(this, _, path, sl, sc, el, ec, _)
|
||||
/**
|
||||
* Holds if this element is at the specified location.
|
||||
* The location spans column `startcolumn` of line `startline` to
|
||||
* column `endcolumn` of line `endline` in file `filepath`.
|
||||
* For more information, see
|
||||
* [Locations](https://help.semmle.com/QL/learn-ql/ql/locations.html).
|
||||
*/
|
||||
predicate hasLocationInfo(
|
||||
string filepath, int startline, int startcolumn, int endline, int endcolumn
|
||||
) {
|
||||
defectResults(this, _, filepath, startline, startcolumn, endline, endcolumn, _)
|
||||
}
|
||||
|
||||
/** Gets the URL corresponding to the location of this query result. */
|
||||
|
||||
21
python/ql/src/external/ExternalArtifact.qll
vendored
21
python/ql/src/external/ExternalArtifact.qll
vendored
@@ -1,3 +1,7 @@
|
||||
/**
|
||||
* Provides classes for working with external data.
|
||||
*/
|
||||
|
||||
import python
|
||||
|
||||
class ExternalDefect extends @externalDefect {
|
||||
@@ -14,6 +18,7 @@ class ExternalDefect extends @externalDefect {
|
||||
|
||||
Location getLocation() { externalDefects(this, _, result, _, _) }
|
||||
|
||||
/** Gets a textual representation of this element. */
|
||||
string toString() { result = getQueryPath() + ": " + getLocation() + " - " + getMessage() }
|
||||
}
|
||||
|
||||
@@ -24,26 +29,42 @@ class ExternalMetric extends @externalMetric {
|
||||
|
||||
Location getLocation() { externalMetrics(this, _, result, _) }
|
||||
|
||||
/** Gets a textual representation of this element. */
|
||||
string toString() { result = getQueryPath() + ": " + getLocation() + " - " + getValue() }
|
||||
}
|
||||
|
||||
/**
|
||||
* An external data item.
|
||||
*/
|
||||
class ExternalData extends @externalDataElement {
|
||||
/** Gets the path of the file this data was loaded from. */
|
||||
string getDataPath() { externalData(this, result, _, _) }
|
||||
|
||||
/**
|
||||
* Gets the path of the file this data was loaded from, with its
|
||||
* extension replaced by `.ql`.
|
||||
*/
|
||||
string getQueryPath() { result = getDataPath().regexpReplaceAll("\\.[^.]*$", ".ql") }
|
||||
|
||||
/** Gets the number of fields in this data item. */
|
||||
int getNumFields() { result = 1 + max(int i | externalData(this, _, i, _) | i) }
|
||||
|
||||
/** Gets the value of the field at position `index` of this data item. */
|
||||
string getField(int index) { externalData(this, _, index, result) }
|
||||
|
||||
/** Gets the integer value of the field at position `index` of this data item. */
|
||||
int getFieldAsInt(int index) { result = getField(index).toInt() }
|
||||
|
||||
/** Gets the floating-point value of the field at position `index` of this data item. */
|
||||
float getFieldAsFloat(int index) { result = getField(index).toFloat() }
|
||||
|
||||
/** Gets the value of the field at position `index` of this data item, interpreted as a date. */
|
||||
date getFieldAsDate(int index) { result = getField(index).toDate() }
|
||||
|
||||
/** Gets a textual representation of this data item. */
|
||||
string toString() { result = getQueryPath() + ": " + buildTupleString(0) }
|
||||
|
||||
/** Gets a textual representation of this data item, starting with the field at position `start`. */
|
||||
private string buildTupleString(int start) {
|
||||
start = getNumFields() - 1 and result = getField(start)
|
||||
or
|
||||
|
||||
37
python/ql/src/external/Thrift.qll
vendored
37
python/ql/src/external/Thrift.qll
vendored
@@ -33,18 +33,27 @@ class ThriftElement extends ExternalData {
|
||||
|
||||
private int column() { result = this.getFieldAsInt(6) }
|
||||
|
||||
predicate hasLocationInfo(string fp, int bl, int bc, int el, int ec) {
|
||||
fp = this.getPath() and
|
||||
bl = this.line() and
|
||||
bc = this.column() and
|
||||
el = this.line() and
|
||||
ec = this.column() + this.getValue().length() - 1
|
||||
/**
|
||||
* Holds if this element is at the specified location.
|
||||
* The location spans column `startcolumn` of line `startline` to
|
||||
* column `endcolumn` of line `endline` in file `filepath`.
|
||||
* For more information, see
|
||||
* [Locations](https://help.semmle.com/QL/learn-ql/ql/locations.html).
|
||||
*/
|
||||
predicate hasLocationInfo(
|
||||
string filepath, int startline, int startcolumn, int endline, int endcolumn
|
||||
) {
|
||||
filepath = this.getPath() and
|
||||
startline = this.line() and
|
||||
startcolumn = this.column() and
|
||||
endline = this.line() and
|
||||
endcolumn = this.column() + this.getValue().length() - 1
|
||||
or
|
||||
exists(ThriftElement first, ThriftElement last |
|
||||
first = this.getChild(min(int l | exists(this.getChild(l)))) and
|
||||
last = this.getChild(max(int l | exists(this.getChild(l)))) and
|
||||
first.hasLocationInfo(fp, bl, bc, _, _) and
|
||||
last.hasLocationInfo(fp, _, _, el, ec)
|
||||
first.hasLocationInfo(filepath, startline, startcolumn, _, _) and
|
||||
last.hasLocationInfo(filepath, _, _, endline, endcolumn)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -62,11 +71,11 @@ abstract class ThriftNamedElement extends ThriftElement {
|
||||
not exists(this.getName()) and result = this.getKind() + " ???"
|
||||
}
|
||||
|
||||
override predicate hasLocationInfo(string fp, int bl, int bc, int el, int ec) {
|
||||
override predicate hasLocationInfo(string filepath, int startline, int startcolumn, int endline, int endcolumn) {
|
||||
exists(ThriftElement first |
|
||||
first = this.getChild(min(int l | exists(this.getChild(l)))) and
|
||||
first.hasLocationInfo(fp, bl, bc, _, _) and
|
||||
this.getNameElement().hasLocationInfo(fp, _, _, el, ec)
|
||||
first.hasLocationInfo(filepath, startline, startcolumn, _, _) and
|
||||
this.getNameElement().hasLocationInfo(filepath, _, _, endline, endcolumn)
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -142,9 +151,9 @@ class ThriftFunction extends ThriftNamedElement {
|
||||
|
||||
ThriftType getReturnType() { result = this.getChild(1).getChild(0) }
|
||||
|
||||
override predicate hasLocationInfo(string fp, int bl, int bc, int el, int ec) {
|
||||
this.getChild(1).hasLocationInfo(fp, bl, bc, _, _) and
|
||||
this.getChild(2).hasLocationInfo(fp, _, _, el, ec)
|
||||
override predicate hasLocationInfo(string filepath, int startline, int startcolumn, int endline, int endcolumn) {
|
||||
this.getChild(1).hasLocationInfo(filepath, startline, startcolumn, _, _) and
|
||||
this.getChild(2).hasLocationInfo(filepath, _, _, endline, endcolumn)
|
||||
}
|
||||
|
||||
ThriftService getService() { result.getAFunction() = this }
|
||||
|
||||
1
python/ql/src/external/VCS.qll
vendored
1
python/ql/src/external/VCS.qll
vendored
@@ -10,6 +10,7 @@ class Commit extends @svnentry {
|
||||
)
|
||||
}
|
||||
|
||||
/** Gets a textual representation of this element. */
|
||||
string toString() { result = this.getRevisionName() }
|
||||
|
||||
string getRevisionName() { svnentries(this, result, _, _, _) }
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/*
|
||||
/**
|
||||
* This library file is auto-generated by 'semmle/query_gen.py'.
|
||||
* WARNING: Any modifications to this file will be lost.
|
||||
* Relations can be changed by modifying master.py.
|
||||
@@ -6,14 +6,17 @@
|
||||
|
||||
import python
|
||||
|
||||
/** INTERNAL: See the class `Add` for further information. */
|
||||
library class Add_ extends @py_Add, Operator {
|
||||
override string toString() { result = "Add" }
|
||||
}
|
||||
|
||||
/** INTERNAL: See the class `And` for further information. */
|
||||
library class And_ extends @py_And, Boolop {
|
||||
override string toString() { result = "And" }
|
||||
}
|
||||
|
||||
/** INTERNAL: See the class `AnnAssign` for further information. */
|
||||
library class AnnAssign_ extends @py_AnnAssign, Stmt {
|
||||
/** Gets the value of this annotated assignment. */
|
||||
Expr getValue() { py_exprs(result, _, this, 1) }
|
||||
@@ -27,6 +30,7 @@ library class AnnAssign_ extends @py_AnnAssign, Stmt {
|
||||
override string toString() { result = "AnnAssign" }
|
||||
}
|
||||
|
||||
/** INTERNAL: See the class `Assert` for further information. */
|
||||
library class Assert_ extends @py_Assert, Stmt {
|
||||
/** Gets the value being tested of this assert statement. */
|
||||
Expr getTest() { py_exprs(result, _, this, 1) }
|
||||
@@ -37,6 +41,7 @@ library class Assert_ extends @py_Assert, Stmt {
|
||||
override string toString() { result = "Assert" }
|
||||
}
|
||||
|
||||
/** INTERNAL: See the class `Assign` for further information. */
|
||||
library class Assign_ extends @py_Assign, Stmt {
|
||||
/** Gets the value of this assignment statement. */
|
||||
Expr getValue() { py_exprs(result, _, this, 1) }
|
||||
@@ -53,6 +58,7 @@ library class Assign_ extends @py_Assign, Stmt {
|
||||
override string toString() { result = "Assign" }
|
||||
}
|
||||
|
||||
/** INTERNAL: See the class `AssignExpr` for further information. */
|
||||
library class AssignExpr_ extends @py_AssignExpr, Expr {
|
||||
/** Gets the value of this assignment expression. */
|
||||
Expr getValue() { py_exprs(result, _, this, 2) }
|
||||
@@ -63,6 +69,7 @@ library class AssignExpr_ extends @py_AssignExpr, Expr {
|
||||
override string toString() { result = "AssignExpr" }
|
||||
}
|
||||
|
||||
/** INTERNAL: See the class `Attribute` for further information. */
|
||||
library class Attribute_ extends @py_Attribute, Expr {
|
||||
/** Gets the object of this attribute expression. */
|
||||
Expr getValue() { py_exprs(result, _, this, 2) }
|
||||
@@ -76,6 +83,7 @@ library class Attribute_ extends @py_Attribute, Expr {
|
||||
override string toString() { result = "Attribute" }
|
||||
}
|
||||
|
||||
/** INTERNAL: See the class `AugAssign` for further information. */
|
||||
library class AugAssign_ extends @py_AugAssign, Stmt {
|
||||
/** Gets the operation of this augmented assignment statement. */
|
||||
BinaryExpr getOperation() { py_exprs(result, _, this, 1) }
|
||||
@@ -83,14 +91,17 @@ library class AugAssign_ extends @py_AugAssign, Stmt {
|
||||
override string toString() { result = "AugAssign" }
|
||||
}
|
||||
|
||||
/** INTERNAL: See the class `AugLoad` for further information. */
|
||||
library class AugLoad_ extends @py_AugLoad, ExprContext {
|
||||
override string toString() { result = "AugLoad" }
|
||||
}
|
||||
|
||||
/** INTERNAL: See the class `AugStore` for further information. */
|
||||
library class AugStore_ extends @py_AugStore, ExprContext {
|
||||
override string toString() { result = "AugStore" }
|
||||
}
|
||||
|
||||
/** INTERNAL: See the class `Await` for further information. */
|
||||
library class Await_ extends @py_Await, Expr {
|
||||
/** Gets the expression waited upon of this await expression. */
|
||||
Expr getValue() { py_exprs(result, _, this, 2) }
|
||||
@@ -98,6 +109,7 @@ library class Await_ extends @py_Await, Expr {
|
||||
override string toString() { result = "Await" }
|
||||
}
|
||||
|
||||
/** INTERNAL: See the class `BinaryExpr` for further information. */
|
||||
library class BinaryExpr_ extends @py_BinaryExpr, Expr {
|
||||
/** Gets the left sub-expression of this binary expression. */
|
||||
Expr getLeft() { py_exprs(result, _, this, 2) }
|
||||
@@ -113,18 +125,22 @@ library class BinaryExpr_ extends @py_BinaryExpr, Expr {
|
||||
override string toString() { result = "BinaryExpr" }
|
||||
}
|
||||
|
||||
/** INTERNAL: See the class `BitAnd` for further information. */
|
||||
library class BitAnd_ extends @py_BitAnd, Operator {
|
||||
override string toString() { result = "BitAnd" }
|
||||
}
|
||||
|
||||
/** INTERNAL: See the class `BitOr` for further information. */
|
||||
library class BitOr_ extends @py_BitOr, Operator {
|
||||
override string toString() { result = "BitOr" }
|
||||
}
|
||||
|
||||
/** INTERNAL: See the class `BitXor` for further information. */
|
||||
library class BitXor_ extends @py_BitXor, Operator {
|
||||
override string toString() { result = "BitXor" }
|
||||
}
|
||||
|
||||
/** INTERNAL: See the class `BoolExpr` for further information. */
|
||||
library class BoolExpr_ extends @py_BoolExpr, Expr {
|
||||
/** Gets the operator of this boolean expression. */
|
||||
Boolop getOp() { py_boolops(result, _, this) }
|
||||
@@ -141,10 +157,12 @@ library class BoolExpr_ extends @py_BoolExpr, Expr {
|
||||
override string toString() { result = "BoolExpr" }
|
||||
}
|
||||
|
||||
/** INTERNAL: See the class `Break` for further information. */
|
||||
library class Break_ extends @py_Break, Stmt {
|
||||
override string toString() { result = "Break" }
|
||||
}
|
||||
|
||||
/** INTERNAL: See the class `Bytes` for further information. */
|
||||
library class Bytes_ extends @py_Bytes, Expr {
|
||||
/** Gets the value of this bytes expression. */
|
||||
string getS() { py_bytes(result, this, 2) }
|
||||
@@ -168,10 +186,13 @@ library class Bytes_ extends @py_Bytes, Expr {
|
||||
override string toString() { result = "Bytes" }
|
||||
}
|
||||
|
||||
/** INTERNAL: See the class `BytesOrStr` for further information. */
|
||||
library class BytesOrStr_ extends @py_Bytes_or_Str {
|
||||
/** Gets a textual representation of this element. */
|
||||
string toString() { result = "BytesOrStr" }
|
||||
}
|
||||
|
||||
/** INTERNAL: See the class `Call` for further information. */
|
||||
library class Call_ extends @py_Call, Expr {
|
||||
/** Gets the callable of this call expression. */
|
||||
Expr getFunc() { py_exprs(result, _, this, 2) }
|
||||
@@ -197,6 +218,7 @@ library class Call_ extends @py_Call, Expr {
|
||||
override string toString() { result = "Call" }
|
||||
}
|
||||
|
||||
/** INTERNAL: See the class `Class` for further information. */
|
||||
library class Class_ extends @py_Class {
|
||||
/** Gets the name of this class. */
|
||||
string getName() { py_strs(result, this, 0) }
|
||||
@@ -212,9 +234,11 @@ library class Class_ extends @py_Class {
|
||||
|
||||
ClassExpr getParent() { py_Classes(this, result) }
|
||||
|
||||
/** Gets a textual representation of this element. */
|
||||
string toString() { result = "Class" }
|
||||
}
|
||||
|
||||
/** INTERNAL: See the class `ClassExpr` for further information. */
|
||||
library class ClassExpr_ extends @py_ClassExpr, Expr {
|
||||
/** Gets the name of this class definition. */
|
||||
string getName() { py_strs(result, this, 2) }
|
||||
@@ -243,6 +267,7 @@ library class ClassExpr_ extends @py_ClassExpr, Expr {
|
||||
override string toString() { result = "ClassExpr" }
|
||||
}
|
||||
|
||||
/** INTERNAL: See the class `Compare` for further information. */
|
||||
library class Compare_ extends @py_Compare, Expr {
|
||||
/** Gets the left sub-expression of this compare expression. */
|
||||
Expr getLeft() { py_exprs(result, _, this, 2) }
|
||||
@@ -268,14 +293,17 @@ library class Compare_ extends @py_Compare, Expr {
|
||||
override string toString() { result = "Compare" }
|
||||
}
|
||||
|
||||
/** INTERNAL: See the class `Continue` for further information. */
|
||||
library class Continue_ extends @py_Continue, Stmt {
|
||||
override string toString() { result = "Continue" }
|
||||
}
|
||||
|
||||
/** INTERNAL: See the class `Del` for further information. */
|
||||
library class Del_ extends @py_Del, ExprContext {
|
||||
override string toString() { result = "Del" }
|
||||
}
|
||||
|
||||
/** INTERNAL: See the class `Delete` for further information. */
|
||||
library class Delete_ extends @py_Delete, Stmt {
|
||||
/** Gets the targets of this delete statement. */
|
||||
ExprList getTargets() { py_expr_lists(result, this, 1) }
|
||||
@@ -289,6 +317,7 @@ library class Delete_ extends @py_Delete, Stmt {
|
||||
override string toString() { result = "Delete" }
|
||||
}
|
||||
|
||||
/** INTERNAL: See the class `Dict` for further information. */
|
||||
library class Dict_ extends @py_Dict, Expr {
|
||||
/** Gets the items of this dictionary expression. */
|
||||
DictItemList getItems() { py_dict_item_lists(result, this) }
|
||||
@@ -302,6 +331,7 @@ library class Dict_ extends @py_Dict, Expr {
|
||||
override string toString() { result = "Dict" }
|
||||
}
|
||||
|
||||
/** INTERNAL: See the class `DictComp` for further information. */
|
||||
library class DictComp_ extends @py_DictComp, Expr {
|
||||
/** Gets the implementation of this dictionary comprehension. */
|
||||
Function getFunction() { py_Functions(result, this) }
|
||||
@@ -312,6 +342,7 @@ library class DictComp_ extends @py_DictComp, Expr {
|
||||
override string toString() { result = "DictComp" }
|
||||
}
|
||||
|
||||
/** INTERNAL: See the class `DictUnpacking` for further information. */
|
||||
library class DictUnpacking_ extends @py_DictUnpacking, DictItem {
|
||||
/** Gets the location of this dictionary unpacking. */
|
||||
override Location getLocation() { py_locations(result, this) }
|
||||
@@ -322,18 +353,22 @@ library class DictUnpacking_ extends @py_DictUnpacking, DictItem {
|
||||
override string toString() { result = "DictUnpacking" }
|
||||
}
|
||||
|
||||
/** INTERNAL: See the class `Div` for further information. */
|
||||
library class Div_ extends @py_Div, Operator {
|
||||
override string toString() { result = "Div" }
|
||||
}
|
||||
|
||||
/** INTERNAL: See the class `Ellipsis` for further information. */
|
||||
library class Ellipsis_ extends @py_Ellipsis, Expr {
|
||||
override string toString() { result = "Ellipsis" }
|
||||
}
|
||||
|
||||
/** INTERNAL: See the class `Eq` for further information. */
|
||||
library class Eq_ extends @py_Eq, Cmpop {
|
||||
override string toString() { result = "Eq" }
|
||||
}
|
||||
|
||||
/** INTERNAL: See the class `ExceptStmt` for further information. */
|
||||
library class ExceptStmt_ extends @py_ExceptStmt, Stmt {
|
||||
/** Gets the type of this except block. */
|
||||
Expr getType() { py_exprs(result, _, this, 1) }
|
||||
@@ -353,6 +388,7 @@ library class ExceptStmt_ extends @py_ExceptStmt, Stmt {
|
||||
override string toString() { result = "ExceptStmt" }
|
||||
}
|
||||
|
||||
/** INTERNAL: See the class `Exec` for further information. */
|
||||
library class Exec_ extends @py_Exec, Stmt {
|
||||
/** Gets the body of this exec statement. */
|
||||
Expr getBody() { py_exprs(result, _, this, 1) }
|
||||
@@ -366,6 +402,7 @@ library class Exec_ extends @py_Exec, Stmt {
|
||||
override string toString() { result = "Exec" }
|
||||
}
|
||||
|
||||
/** INTERNAL: See the class `ExprStmt` for further information. */
|
||||
library class ExprStmt_ extends @py_Expr_stmt, Stmt {
|
||||
/** Gets the value of this expr statement. */
|
||||
Expr getValue() { py_exprs(result, _, this, 1) }
|
||||
@@ -373,6 +410,7 @@ library class ExprStmt_ extends @py_Expr_stmt, Stmt {
|
||||
override string toString() { result = "ExprStmt" }
|
||||
}
|
||||
|
||||
/** INTERNAL: See the class `Filter` for further information. */
|
||||
library class Filter_ extends @py_Filter, Expr {
|
||||
/** Gets the filtered value of this template filter expression. */
|
||||
Expr getValue() { py_exprs(result, _, this, 2) }
|
||||
@@ -383,10 +421,12 @@ library class Filter_ extends @py_Filter, Expr {
|
||||
override string toString() { result = "Filter" }
|
||||
}
|
||||
|
||||
/** INTERNAL: See the class `FloorDiv` for further information. */
|
||||
library class FloorDiv_ extends @py_FloorDiv, Operator {
|
||||
override string toString() { result = "FloorDiv" }
|
||||
}
|
||||
|
||||
/** INTERNAL: See the class `For` for further information. */
|
||||
library class For_ extends @py_For, Stmt {
|
||||
/** Gets the target of this for statement. */
|
||||
Expr getTarget() { py_exprs(result, _, this, 1) }
|
||||
@@ -418,6 +458,7 @@ library class For_ extends @py_For, Stmt {
|
||||
override string toString() { result = "For" }
|
||||
}
|
||||
|
||||
/** INTERNAL: See the class `FormattedValue` for further information. */
|
||||
library class FormattedValue_ extends @py_FormattedValue, Expr {
|
||||
/** Gets the expression to be formatted of this formatted value. */
|
||||
Expr getValue() { py_exprs(result, _, this, 2) }
|
||||
@@ -431,6 +472,7 @@ library class FormattedValue_ extends @py_FormattedValue, Expr {
|
||||
override string toString() { result = "FormattedValue" }
|
||||
}
|
||||
|
||||
/** INTERNAL: See the class `Function` for further information. */
|
||||
library class Function_ extends @py_Function {
|
||||
/** Gets the name of this function. */
|
||||
string getName() { py_strs(result, this, 0) }
|
||||
@@ -473,9 +515,11 @@ library class Function_ extends @py_Function {
|
||||
|
||||
FunctionParent getParent() { py_Functions(this, result) }
|
||||
|
||||
/** Gets a textual representation of this element. */
|
||||
string toString() { result = "Function" }
|
||||
}
|
||||
|
||||
/** INTERNAL: See the class `FunctionExpr` for further information. */
|
||||
library class FunctionExpr_ extends @py_FunctionExpr, Expr {
|
||||
/** Gets the name of this function definition. */
|
||||
string getName() { py_strs(result, this, 2) }
|
||||
@@ -492,10 +536,13 @@ library class FunctionExpr_ extends @py_FunctionExpr, Expr {
|
||||
override string toString() { result = "FunctionExpr" }
|
||||
}
|
||||
|
||||
/** INTERNAL: See the class `FunctionParent` for further information. */
|
||||
library class FunctionParent_ extends @py_Function_parent {
|
||||
/** Gets a textual representation of this element. */
|
||||
string toString() { result = "FunctionParent" }
|
||||
}
|
||||
|
||||
/** INTERNAL: See the class `GeneratorExp` for further information. */
|
||||
library class GeneratorExp_ extends @py_GeneratorExp, Expr {
|
||||
/** Gets the implementation of this generator expression. */
|
||||
Function getFunction() { py_Functions(result, this) }
|
||||
@@ -506,6 +553,7 @@ library class GeneratorExp_ extends @py_GeneratorExp, Expr {
|
||||
override string toString() { result = "GeneratorExp" }
|
||||
}
|
||||
|
||||
/** INTERNAL: See the class `Global` for further information. */
|
||||
library class Global_ extends @py_Global, Stmt {
|
||||
/** Gets the names of this global statement. */
|
||||
StringList getNames() { py_str_lists(result, this) }
|
||||
@@ -519,14 +567,17 @@ library class Global_ extends @py_Global, Stmt {
|
||||
override string toString() { result = "Global" }
|
||||
}
|
||||
|
||||
/** INTERNAL: See the class `Gt` for further information. */
|
||||
library class Gt_ extends @py_Gt, Cmpop {
|
||||
override string toString() { result = "Gt" }
|
||||
}
|
||||
|
||||
/** INTERNAL: See the class `GtE` for further information. */
|
||||
library class GtE_ extends @py_GtE, Cmpop {
|
||||
override string toString() { result = "GtE" }
|
||||
}
|
||||
|
||||
/** INTERNAL: See the class `If` for further information. */
|
||||
library class If_ extends @py_If, Stmt {
|
||||
/** Gets the test of this if statement. */
|
||||
Expr getTest() { py_exprs(result, _, this, 1) }
|
||||
@@ -552,6 +603,7 @@ library class If_ extends @py_If, Stmt {
|
||||
override string toString() { result = "If" }
|
||||
}
|
||||
|
||||
/** INTERNAL: See the class `IfExp` for further information. */
|
||||
library class IfExp_ extends @py_IfExp, Expr {
|
||||
/** Gets the test of this if expression. */
|
||||
Expr getTest() { py_exprs(result, _, this, 2) }
|
||||
@@ -565,6 +617,7 @@ library class IfExp_ extends @py_IfExp, Expr {
|
||||
override string toString() { result = "IfExp" }
|
||||
}
|
||||
|
||||
/** INTERNAL: See the class `Import` for further information. */
|
||||
library class Import_ extends @py_Import, Stmt {
|
||||
/** Gets the alias list of this import statement. */
|
||||
AliasList getNames() { py_alias_lists(result, this) }
|
||||
@@ -578,6 +631,7 @@ library class Import_ extends @py_Import, Stmt {
|
||||
override string toString() { result = "Import" }
|
||||
}
|
||||
|
||||
/** INTERNAL: See the class `ImportExpr` for further information. */
|
||||
library class ImportExpr_ extends @py_ImportExpr, Expr {
|
||||
/** Gets the level of this import expression. */
|
||||
int getLevel() { py_ints(result, this) }
|
||||
@@ -591,6 +645,7 @@ library class ImportExpr_ extends @py_ImportExpr, Expr {
|
||||
override string toString() { result = "ImportExpr" }
|
||||
}
|
||||
|
||||
/** INTERNAL: See the class `ImportStar` for further information. */
|
||||
library class ImportStar_ extends @py_ImportStar, Stmt {
|
||||
/** Gets the module of this import * statement. */
|
||||
Expr getModule() { py_exprs(result, _, this, 1) }
|
||||
@@ -598,6 +653,7 @@ library class ImportStar_ extends @py_ImportStar, Stmt {
|
||||
override string toString() { result = "ImportStar" }
|
||||
}
|
||||
|
||||
/** INTERNAL: See the class `ImportMember` for further information. */
|
||||
library class ImportMember_ extends @py_ImportMember, Expr {
|
||||
/** Gets the module of this from import. */
|
||||
Expr getModule() { py_exprs(result, _, this, 2) }
|
||||
@@ -608,22 +664,27 @@ library class ImportMember_ extends @py_ImportMember, Expr {
|
||||
override string toString() { result = "ImportMember" }
|
||||
}
|
||||
|
||||
/** INTERNAL: See the class `In` for further information. */
|
||||
library class In_ extends @py_In, Cmpop {
|
||||
override string toString() { result = "In" }
|
||||
}
|
||||
|
||||
/** INTERNAL: See the class `Invert` for further information. */
|
||||
library class Invert_ extends @py_Invert, Unaryop {
|
||||
override string toString() { result = "Invert" }
|
||||
}
|
||||
|
||||
/** INTERNAL: See the class `Is` for further information. */
|
||||
library class Is_ extends @py_Is, Cmpop {
|
||||
override string toString() { result = "Is" }
|
||||
}
|
||||
|
||||
/** INTERNAL: See the class `IsNot` for further information. */
|
||||
library class IsNot_ extends @py_IsNot, Cmpop {
|
||||
override string toString() { result = "IsNot" }
|
||||
}
|
||||
|
||||
/** INTERNAL: See the class `Fstring` for further information. */
|
||||
library class Fstring_ extends @py_Fstring, Expr {
|
||||
/** Gets the values of this formatted string literal. */
|
||||
ExprList getValues() { py_expr_lists(result, this, 2) }
|
||||
@@ -639,6 +700,7 @@ library class Fstring_ extends @py_Fstring, Expr {
|
||||
override string toString() { result = "Fstring" }
|
||||
}
|
||||
|
||||
/** INTERNAL: See the class `KeyValuePair` for further information. */
|
||||
library class KeyValuePair_ extends @py_KeyValuePair, DictItem {
|
||||
/** Gets the location of this key-value pair. */
|
||||
override Location getLocation() { py_locations(result, this) }
|
||||
@@ -652,10 +714,12 @@ library class KeyValuePair_ extends @py_KeyValuePair, DictItem {
|
||||
override string toString() { result = "KeyValuePair" }
|
||||
}
|
||||
|
||||
/** INTERNAL: See the class `LShift` for further information. */
|
||||
library class LShift_ extends @py_LShift, Operator {
|
||||
override string toString() { result = "LShift" }
|
||||
}
|
||||
|
||||
/** INTERNAL: See the class `Lambda` for further information. */
|
||||
library class Lambda_ extends @py_Lambda, Expr {
|
||||
/** Gets the arguments of this lambda expression. */
|
||||
Arguments getArgs() { py_arguments(result, this) }
|
||||
@@ -666,6 +730,7 @@ library class Lambda_ extends @py_Lambda, Expr {
|
||||
override string toString() { result = "Lambda" }
|
||||
}
|
||||
|
||||
/** INTERNAL: See the class `List` for further information. */
|
||||
library class List_ extends @py_List, Expr {
|
||||
/** Gets the element list of this list expression. */
|
||||
ExprList getElts() { py_expr_lists(result, this, 2) }
|
||||
@@ -682,6 +747,7 @@ library class List_ extends @py_List, Expr {
|
||||
override string toString() { result = "List" }
|
||||
}
|
||||
|
||||
/** INTERNAL: See the class `ListComp` for further information. */
|
||||
library class ListComp_ extends @py_ListComp, Expr {
|
||||
/** Gets the implementation of this list comprehension. */
|
||||
Function getFunction() { py_Functions(result, this) }
|
||||
@@ -704,26 +770,32 @@ library class ListComp_ extends @py_ListComp, Expr {
|
||||
override string toString() { result = "ListComp" }
|
||||
}
|
||||
|
||||
/** INTERNAL: See the class `Load` for further information. */
|
||||
library class Load_ extends @py_Load, ExprContext {
|
||||
override string toString() { result = "Load" }
|
||||
}
|
||||
|
||||
/** INTERNAL: See the class `Lt` for further information. */
|
||||
library class Lt_ extends @py_Lt, Cmpop {
|
||||
override string toString() { result = "Lt" }
|
||||
}
|
||||
|
||||
/** INTERNAL: See the class `LtE` for further information. */
|
||||
library class LtE_ extends @py_LtE, Cmpop {
|
||||
override string toString() { result = "LtE" }
|
||||
}
|
||||
|
||||
/** INTERNAL: See the class `MatMult` for further information. */
|
||||
library class MatMult_ extends @py_MatMult, Operator {
|
||||
override string toString() { result = "MatMult" }
|
||||
}
|
||||
|
||||
/** INTERNAL: See the class `Mod` for further information. */
|
||||
library class Mod_ extends @py_Mod, Operator {
|
||||
override string toString() { result = "Mod" }
|
||||
}
|
||||
|
||||
/** INTERNAL: See the class `Module` for further information. */
|
||||
library class Module_ extends @py_Module {
|
||||
/** Gets the name of this module. */
|
||||
string getName() { py_strs(result, this, 0) }
|
||||
@@ -743,13 +815,16 @@ library class Module_ extends @py_Module {
|
||||
/** Gets the kind of this module. */
|
||||
string getKind() { py_strs(result, this, 3) }
|
||||
|
||||
/** Gets a textual representation of this element. */
|
||||
string toString() { result = "Module" }
|
||||
}
|
||||
|
||||
/** INTERNAL: See the class `Mult` for further information. */
|
||||
library class Mult_ extends @py_Mult, Operator {
|
||||
override string toString() { result = "Mult" }
|
||||
}
|
||||
|
||||
/** INTERNAL: See the class `Name` for further information. */
|
||||
library class Name_ extends @py_Name, Expr {
|
||||
/** Gets the variable of this name expression. */
|
||||
Variable getVariable() { py_variables(result, this) }
|
||||
@@ -762,6 +837,7 @@ library class Name_ extends @py_Name, Expr {
|
||||
override string toString() { result = "Name" }
|
||||
}
|
||||
|
||||
/** INTERNAL: See the class `Nonlocal` for further information. */
|
||||
library class Nonlocal_ extends @py_Nonlocal, Stmt {
|
||||
/** Gets the names of this nonlocal statement. */
|
||||
StringList getNames() { py_str_lists(result, this) }
|
||||
@@ -775,18 +851,22 @@ library class Nonlocal_ extends @py_Nonlocal, Stmt {
|
||||
override string toString() { result = "Nonlocal" }
|
||||
}
|
||||
|
||||
/** INTERNAL: See the class `Not` for further information. */
|
||||
library class Not_ extends @py_Not, Unaryop {
|
||||
override string toString() { result = "Not" }
|
||||
}
|
||||
|
||||
/** INTERNAL: See the class `NotEq` for further information. */
|
||||
library class NotEq_ extends @py_NotEq, Cmpop {
|
||||
override string toString() { result = "NotEq" }
|
||||
}
|
||||
|
||||
/** INTERNAL: See the class `NotIn` for further information. */
|
||||
library class NotIn_ extends @py_NotIn, Cmpop {
|
||||
override string toString() { result = "NotIn" }
|
||||
}
|
||||
|
||||
/** INTERNAL: See the class `Num` for further information. */
|
||||
library class Num_ extends @py_Num, Expr {
|
||||
/** Gets the value of this numeric literal. */
|
||||
string getN() { py_numbers(result, this, 2) }
|
||||
@@ -797,18 +877,22 @@ library class Num_ extends @py_Num, Expr {
|
||||
override string toString() { result = "Num" }
|
||||
}
|
||||
|
||||
/** INTERNAL: See the class `Or` for further information. */
|
||||
library class Or_ extends @py_Or, Boolop {
|
||||
override string toString() { result = "Or" }
|
||||
}
|
||||
|
||||
/** INTERNAL: See the class `Param` for further information. */
|
||||
library class Param_ extends @py_Param, ExprContext {
|
||||
override string toString() { result = "Param" }
|
||||
}
|
||||
|
||||
/** INTERNAL: See the class `Pass` for further information. */
|
||||
library class Pass_ extends @py_Pass, Stmt {
|
||||
override string toString() { result = "Pass" }
|
||||
}
|
||||
|
||||
/** INTERNAL: See the class `PlaceHolder` for further information. */
|
||||
library class PlaceHolder_ extends @py_PlaceHolder, Expr {
|
||||
/** Gets the variable of this template place-holder expression. */
|
||||
Variable getVariable() { py_variables(result, this) }
|
||||
@@ -819,10 +903,12 @@ library class PlaceHolder_ extends @py_PlaceHolder, Expr {
|
||||
override string toString() { result = "PlaceHolder" }
|
||||
}
|
||||
|
||||
/** INTERNAL: See the class `Pow` for further information. */
|
||||
library class Pow_ extends @py_Pow, Operator {
|
||||
override string toString() { result = "Pow" }
|
||||
}
|
||||
|
||||
/** INTERNAL: See the class `Print` for further information. */
|
||||
library class Print_ extends @py_Print, Stmt {
|
||||
/** Gets the destination of this print statement. */
|
||||
Expr getDest() { py_exprs(result, _, this, 1) }
|
||||
@@ -842,10 +928,12 @@ library class Print_ extends @py_Print, Stmt {
|
||||
override string toString() { result = "Print" }
|
||||
}
|
||||
|
||||
/** INTERNAL: See the class `RShift` for further information. */
|
||||
library class RShift_ extends @py_RShift, Operator {
|
||||
override string toString() { result = "RShift" }
|
||||
}
|
||||
|
||||
/** INTERNAL: See the class `Raise` for further information. */
|
||||
library class Raise_ extends @py_Raise, Stmt {
|
||||
/** Gets the exception of this raise statement. */
|
||||
Expr getExc() { py_exprs(result, _, this, 1) }
|
||||
@@ -865,6 +953,7 @@ library class Raise_ extends @py_Raise, Stmt {
|
||||
override string toString() { result = "Raise" }
|
||||
}
|
||||
|
||||
/** INTERNAL: See the class `Repr` for further information. */
|
||||
library class Repr_ extends @py_Repr, Expr {
|
||||
/** Gets the value of this backtick expression. */
|
||||
Expr getValue() { py_exprs(result, _, this, 2) }
|
||||
@@ -872,6 +961,7 @@ library class Repr_ extends @py_Repr, Expr {
|
||||
override string toString() { result = "Repr" }
|
||||
}
|
||||
|
||||
/** INTERNAL: See the class `Return` for further information. */
|
||||
library class Return_ extends @py_Return, Stmt {
|
||||
/** Gets the value of this return statement. */
|
||||
Expr getValue() { py_exprs(result, _, this, 1) }
|
||||
@@ -879,6 +969,7 @@ library class Return_ extends @py_Return, Stmt {
|
||||
override string toString() { result = "Return" }
|
||||
}
|
||||
|
||||
/** INTERNAL: See the class `Set` for further information. */
|
||||
library class Set_ extends @py_Set, Expr {
|
||||
/** Gets the elements of this set expression. */
|
||||
ExprList getElts() { py_expr_lists(result, this, 2) }
|
||||
@@ -892,6 +983,7 @@ library class Set_ extends @py_Set, Expr {
|
||||
override string toString() { result = "Set" }
|
||||
}
|
||||
|
||||
/** INTERNAL: See the class `SetComp` for further information. */
|
||||
library class SetComp_ extends @py_SetComp, Expr {
|
||||
/** Gets the implementation of this set comprehension. */
|
||||
Function getFunction() { py_Functions(result, this) }
|
||||
@@ -902,6 +994,7 @@ library class SetComp_ extends @py_SetComp, Expr {
|
||||
override string toString() { result = "SetComp" }
|
||||
}
|
||||
|
||||
/** INTERNAL: See the class `Slice` for further information. */
|
||||
library class Slice_ extends @py_Slice, Expr {
|
||||
/** Gets the start of this slice. */
|
||||
Expr getStart() { py_exprs(result, _, this, 2) }
|
||||
@@ -915,6 +1008,7 @@ library class Slice_ extends @py_Slice, Expr {
|
||||
override string toString() { result = "Slice" }
|
||||
}
|
||||
|
||||
/** INTERNAL: See the class `SpecialOperation` for further information. */
|
||||
library class SpecialOperation_ extends @py_SpecialOperation, Expr {
|
||||
/** Gets the name of this special operation. */
|
||||
string getName() { py_strs(result, this, 2) }
|
||||
@@ -931,6 +1025,7 @@ library class SpecialOperation_ extends @py_SpecialOperation, Expr {
|
||||
override string toString() { result = "SpecialOperation" }
|
||||
}
|
||||
|
||||
/** INTERNAL: See the class `Starred` for further information. */
|
||||
library class Starred_ extends @py_Starred, Expr {
|
||||
/** Gets the value of this starred expression. */
|
||||
Expr getValue() { py_exprs(result, _, this, 2) }
|
||||
@@ -941,10 +1036,12 @@ library class Starred_ extends @py_Starred, Expr {
|
||||
override string toString() { result = "Starred" }
|
||||
}
|
||||
|
||||
/** INTERNAL: See the class `Store` for further information. */
|
||||
library class Store_ extends @py_Store, ExprContext {
|
||||
override string toString() { result = "Store" }
|
||||
}
|
||||
|
||||
/** INTERNAL: See the class `Str` for further information. */
|
||||
library class Str_ extends @py_Str, Expr {
|
||||
/** Gets the text of this string literal. */
|
||||
string getS() { py_strs(result, this, 2) }
|
||||
@@ -968,6 +1065,7 @@ library class Str_ extends @py_Str, Expr {
|
||||
override string toString() { result = "Str" }
|
||||
}
|
||||
|
||||
/** INTERNAL: See the class `StringPart` for further information. */
|
||||
library class StringPart_ extends @py_StringPart {
|
||||
/** Gets the text of this implicitly concatenated part. */
|
||||
string getText() { py_strs(result, this, 0) }
|
||||
@@ -977,9 +1075,11 @@ library class StringPart_ extends @py_StringPart {
|
||||
|
||||
StringPartList getParent() { py_StringParts(this, result, _) }
|
||||
|
||||
/** Gets a textual representation of this element. */
|
||||
string toString() { result = "StringPart" }
|
||||
}
|
||||
|
||||
/** INTERNAL: See the class `StringPartList` for further information. */
|
||||
library class StringPartList_ extends @py_StringPart_list {
|
||||
BytesOrStr getParent() { py_StringPart_lists(this, result) }
|
||||
|
||||
@@ -989,13 +1089,16 @@ library class StringPartList_ extends @py_StringPart_list {
|
||||
/** Gets the nth item of this implicitly concatenated part list */
|
||||
StringPart getItem(int index) { py_StringParts(result, this, index) }
|
||||
|
||||
/** Gets a textual representation of this element. */
|
||||
string toString() { result = "StringPartList" }
|
||||
}
|
||||
|
||||
/** INTERNAL: See the class `Sub` for further information. */
|
||||
library class Sub_ extends @py_Sub, Operator {
|
||||
override string toString() { result = "Sub" }
|
||||
}
|
||||
|
||||
/** INTERNAL: See the class `Subscript` for further information. */
|
||||
library class Subscript_ extends @py_Subscript, Expr {
|
||||
/** Gets the value of this subscript expression. */
|
||||
Expr getValue() { py_exprs(result, _, this, 2) }
|
||||
@@ -1009,6 +1112,7 @@ library class Subscript_ extends @py_Subscript, Expr {
|
||||
override string toString() { result = "Subscript" }
|
||||
}
|
||||
|
||||
/** INTERNAL: See the class `TemplateDottedNotation` for further information. */
|
||||
library class TemplateDottedNotation_ extends @py_TemplateDottedNotation, Expr {
|
||||
/** Gets the object of this template dotted notation expression. */
|
||||
Expr getValue() { py_exprs(result, _, this, 2) }
|
||||
@@ -1022,6 +1126,7 @@ library class TemplateDottedNotation_ extends @py_TemplateDottedNotation, Expr {
|
||||
override string toString() { result = "TemplateDottedNotation" }
|
||||
}
|
||||
|
||||
/** INTERNAL: See the class `TemplateWrite` for further information. */
|
||||
library class TemplateWrite_ extends @py_TemplateWrite, Stmt {
|
||||
/** Gets the value of this template write statement. */
|
||||
Expr getValue() { py_exprs(result, _, this, 1) }
|
||||
@@ -1029,6 +1134,7 @@ library class TemplateWrite_ extends @py_TemplateWrite, Stmt {
|
||||
override string toString() { result = "TemplateWrite" }
|
||||
}
|
||||
|
||||
/** INTERNAL: See the class `Try` for further information. */
|
||||
library class Try_ extends @py_Try, Stmt {
|
||||
/** Gets the body of this try statement. */
|
||||
StmtList getBody() { py_stmt_lists(result, this, 1) }
|
||||
@@ -1069,6 +1175,7 @@ library class Try_ extends @py_Try, Stmt {
|
||||
override string toString() { result = "Try" }
|
||||
}
|
||||
|
||||
/** INTERNAL: See the class `Tuple` for further information. */
|
||||
library class Tuple_ extends @py_Tuple, Expr {
|
||||
/** Gets the elements of this tuple expression. */
|
||||
ExprList getElts() { py_expr_lists(result, this, 2) }
|
||||
@@ -1087,14 +1194,17 @@ library class Tuple_ extends @py_Tuple, Expr {
|
||||
override string toString() { result = "Tuple" }
|
||||
}
|
||||
|
||||
/** INTERNAL: See the class `UAdd` for further information. */
|
||||
library class UAdd_ extends @py_UAdd, Unaryop {
|
||||
override string toString() { result = "UAdd" }
|
||||
}
|
||||
|
||||
/** INTERNAL: See the class `USub` for further information. */
|
||||
library class USub_ extends @py_USub, Unaryop {
|
||||
override string toString() { result = "USub" }
|
||||
}
|
||||
|
||||
/** INTERNAL: See the class `UnaryExpr` for further information. */
|
||||
library class UnaryExpr_ extends @py_UnaryExpr, Expr {
|
||||
/** Gets the operator of this unary expression. */
|
||||
Unaryop getOp() { py_unaryops(result, _, this) }
|
||||
@@ -1105,6 +1215,7 @@ library class UnaryExpr_ extends @py_UnaryExpr, Expr {
|
||||
override string toString() { result = "UnaryExpr" }
|
||||
}
|
||||
|
||||
/** INTERNAL: See the class `While` for further information. */
|
||||
library class While_ extends @py_While, Stmt {
|
||||
/** Gets the test of this while statement. */
|
||||
Expr getTest() { py_exprs(result, _, this, 1) }
|
||||
@@ -1130,6 +1241,7 @@ library class While_ extends @py_While, Stmt {
|
||||
override string toString() { result = "While" }
|
||||
}
|
||||
|
||||
/** INTERNAL: See the class `With` for further information. */
|
||||
library class With_ extends @py_With, Stmt {
|
||||
/** Gets the context manager of this with statement. */
|
||||
Expr getContextExpr() { py_exprs(result, _, this, 1) }
|
||||
@@ -1152,6 +1264,7 @@ library class With_ extends @py_With, Stmt {
|
||||
override string toString() { result = "With" }
|
||||
}
|
||||
|
||||
/** INTERNAL: See the class `Yield` for further information. */
|
||||
library class Yield_ extends @py_Yield, Expr {
|
||||
/** Gets the value of this yield expression. */
|
||||
Expr getValue() { py_exprs(result, _, this, 2) }
|
||||
@@ -1159,6 +1272,7 @@ library class Yield_ extends @py_Yield, Expr {
|
||||
override string toString() { result = "Yield" }
|
||||
}
|
||||
|
||||
/** INTERNAL: See the class `YieldFrom` for further information. */
|
||||
library class YieldFrom_ extends @py_YieldFrom, Expr {
|
||||
/** Gets the value of this yield-from expression. */
|
||||
Expr getValue() { py_exprs(result, _, this, 2) }
|
||||
@@ -1166,6 +1280,7 @@ library class YieldFrom_ extends @py_YieldFrom, Expr {
|
||||
override string toString() { result = "YieldFrom" }
|
||||
}
|
||||
|
||||
/** INTERNAL: See the class `Alias` for further information. */
|
||||
library class Alias_ extends @py_alias {
|
||||
/** Gets the value of this alias. */
|
||||
Expr getValue() { py_exprs(result, _, this, 0) }
|
||||
@@ -1175,9 +1290,11 @@ library class Alias_ extends @py_alias {
|
||||
|
||||
AliasList getParent() { py_aliases(this, result, _) }
|
||||
|
||||
/** Gets a textual representation of this element. */
|
||||
string toString() { result = "Alias" }
|
||||
}
|
||||
|
||||
/** INTERNAL: See the class `AliasList` for further information. */
|
||||
library class AliasList_ extends @py_alias_list {
|
||||
Import getParent() { py_alias_lists(this, result) }
|
||||
|
||||
@@ -1187,9 +1304,11 @@ library class AliasList_ extends @py_alias_list {
|
||||
/** Gets the nth item of this alias list */
|
||||
Alias getItem(int index) { py_aliases(result, this, index) }
|
||||
|
||||
/** Gets a textual representation of this element. */
|
||||
string toString() { result = "AliasList" }
|
||||
}
|
||||
|
||||
/** INTERNAL: See the class `Arguments` for further information. */
|
||||
library class Arguments_ extends @py_arguments {
|
||||
/** Gets the keyword default values of this parameters definition. */
|
||||
ExprList getKwDefaults() { py_expr_lists(result, this, 0) }
|
||||
@@ -1235,33 +1354,45 @@ library class Arguments_ extends @py_arguments {
|
||||
|
||||
ArgumentsParent getParent() { py_arguments(this, result) }
|
||||
|
||||
/** Gets a textual representation of this element. */
|
||||
string toString() { result = "Arguments" }
|
||||
}
|
||||
|
||||
/** INTERNAL: See the class `ArgumentsParent` for further information. */
|
||||
library class ArgumentsParent_ extends @py_arguments_parent {
|
||||
/** Gets a textual representation of this element. */
|
||||
string toString() { result = "ArgumentsParent" }
|
||||
}
|
||||
|
||||
/** INTERNAL: See the class `AstNode` for further information. */
|
||||
library class AstNode_ extends @py_ast_node {
|
||||
/** Gets a textual representation of this element. */
|
||||
string toString() { result = "AstNode" }
|
||||
}
|
||||
|
||||
/** INTERNAL: See the class `BoolParent` for further information. */
|
||||
library class BoolParent_ extends @py_bool_parent {
|
||||
/** Gets a textual representation of this element. */
|
||||
string toString() { result = "BoolParent" }
|
||||
}
|
||||
|
||||
/** INTERNAL: See the class `Boolop` for further information. */
|
||||
library class Boolop_ extends @py_boolop {
|
||||
BoolExpr getParent() { py_boolops(this, _, result) }
|
||||
|
||||
/** Gets a textual representation of this element. */
|
||||
string toString() { result = "Boolop" }
|
||||
}
|
||||
|
||||
/** INTERNAL: See the class `Cmpop` for further information. */
|
||||
library class Cmpop_ extends @py_cmpop {
|
||||
CmpopList getParent() { py_cmpops(this, _, result, _) }
|
||||
|
||||
/** Gets a textual representation of this element. */
|
||||
string toString() { result = "Cmpop" }
|
||||
}
|
||||
|
||||
/** INTERNAL: See the class `CmpopList` for further information. */
|
||||
library class CmpopList_ extends @py_cmpop_list {
|
||||
Compare getParent() { py_cmpop_lists(this, result) }
|
||||
|
||||
@@ -1271,9 +1402,11 @@ library class CmpopList_ extends @py_cmpop_list {
|
||||
/** Gets the nth item of this comparison operator list */
|
||||
Cmpop getItem(int index) { py_cmpops(result, _, this, index) }
|
||||
|
||||
/** Gets a textual representation of this element. */
|
||||
string toString() { result = "CmpopList" }
|
||||
}
|
||||
|
||||
/** INTERNAL: See the class `Comprehension` for further information. */
|
||||
library class Comprehension_ extends @py_comprehension {
|
||||
/** Gets the location of this comprehension. */
|
||||
Location getLocation() { py_locations(result, this) }
|
||||
@@ -1295,9 +1428,11 @@ library class Comprehension_ extends @py_comprehension {
|
||||
|
||||
ComprehensionList getParent() { py_comprehensions(this, result, _) }
|
||||
|
||||
/** Gets a textual representation of this element. */
|
||||
string toString() { result = "Comprehension" }
|
||||
}
|
||||
|
||||
/** INTERNAL: See the class `ComprehensionList` for further information. */
|
||||
library class ComprehensionList_ extends @py_comprehension_list {
|
||||
ListComp getParent() { py_comprehension_lists(this, result) }
|
||||
|
||||
@@ -1307,15 +1442,19 @@ library class ComprehensionList_ extends @py_comprehension_list {
|
||||
/** Gets the nth item of this comprehension list */
|
||||
Comprehension getItem(int index) { py_comprehensions(result, this, index) }
|
||||
|
||||
/** Gets a textual representation of this element. */
|
||||
string toString() { result = "ComprehensionList" }
|
||||
}
|
||||
|
||||
/** INTERNAL: See the class `DictItem` for further information. */
|
||||
library class DictItem_ extends @py_dict_item {
|
||||
DictItemList getParent() { py_dict_items(this, _, result, _) }
|
||||
|
||||
/** Gets a textual representation of this element. */
|
||||
string toString() { result = "DictItem" }
|
||||
}
|
||||
|
||||
/** INTERNAL: See the class `DictItemList` for further information. */
|
||||
library class DictItemList_ extends @py_dict_item_list {
|
||||
DictItemListParent getParent() { py_dict_item_lists(this, result) }
|
||||
|
||||
@@ -1325,13 +1464,17 @@ library class DictItemList_ extends @py_dict_item_list {
|
||||
/** Gets the nth item of this dict_item list */
|
||||
DictItem getItem(int index) { py_dict_items(result, _, this, index) }
|
||||
|
||||
/** Gets a textual representation of this element. */
|
||||
string toString() { result = "DictItemList" }
|
||||
}
|
||||
|
||||
/** INTERNAL: See the class `DictItemListParent` for further information. */
|
||||
library class DictItemListParent_ extends @py_dict_item_list_parent {
|
||||
/** Gets a textual representation of this element. */
|
||||
string toString() { result = "DictItemListParent" }
|
||||
}
|
||||
|
||||
/** INTERNAL: See the class `Expr` for further information. */
|
||||
library class Expr_ extends @py_expr {
|
||||
/** Gets the location of this expression. */
|
||||
Location getLocation() { py_locations(result, this) }
|
||||
@@ -1341,19 +1484,25 @@ library class Expr_ extends @py_expr {
|
||||
|
||||
ExprParent getParent() { py_exprs(this, _, result, _) }
|
||||
|
||||
/** Gets a textual representation of this element. */
|
||||
string toString() { result = "Expr" }
|
||||
}
|
||||
|
||||
/** INTERNAL: See the class `ExprContext` for further information. */
|
||||
library class ExprContext_ extends @py_expr_context {
|
||||
ExprContextParent getParent() { py_expr_contexts(this, _, result) }
|
||||
|
||||
/** Gets a textual representation of this element. */
|
||||
string toString() { result = "ExprContext" }
|
||||
}
|
||||
|
||||
/** INTERNAL: See the class `ExprContextParent` for further information. */
|
||||
library class ExprContextParent_ extends @py_expr_context_parent {
|
||||
/** Gets a textual representation of this element. */
|
||||
string toString() { result = "ExprContextParent" }
|
||||
}
|
||||
|
||||
/** INTERNAL: See the class `ExprList` for further information. */
|
||||
library class ExprList_ extends @py_expr_list {
|
||||
ExprListParent getParent() { py_expr_lists(this, result, _) }
|
||||
|
||||
@@ -1363,21 +1512,29 @@ library class ExprList_ extends @py_expr_list {
|
||||
/** Gets the nth item of this expression list */
|
||||
Expr getItem(int index) { py_exprs(result, _, this, index) }
|
||||
|
||||
/** Gets a textual representation of this element. */
|
||||
string toString() { result = "ExprList" }
|
||||
}
|
||||
|
||||
/** INTERNAL: See the class `ExprListParent` for further information. */
|
||||
library class ExprListParent_ extends @py_expr_list_parent {
|
||||
/** Gets a textual representation of this element. */
|
||||
string toString() { result = "ExprListParent" }
|
||||
}
|
||||
|
||||
/** INTERNAL: See the class `ExprOrStmt` for further information. */
|
||||
library class ExprOrStmt_ extends @py_expr_or_stmt {
|
||||
/** Gets a textual representation of this element. */
|
||||
string toString() { result = "ExprOrStmt" }
|
||||
}
|
||||
|
||||
/** INTERNAL: See the class `ExprParent` for further information. */
|
||||
library class ExprParent_ extends @py_expr_parent {
|
||||
/** Gets a textual representation of this element. */
|
||||
string toString() { result = "ExprParent" }
|
||||
}
|
||||
|
||||
/** INTERNAL: See the class `Keyword` for further information. */
|
||||
library class Keyword_ extends @py_keyword, DictItem {
|
||||
/** Gets the location of this keyword argument. */
|
||||
override Location getLocation() { py_locations(result, this) }
|
||||
@@ -1391,33 +1548,44 @@ library class Keyword_ extends @py_keyword, DictItem {
|
||||
override string toString() { result = "Keyword" }
|
||||
}
|
||||
|
||||
/** INTERNAL: See the class `LocationParent` for further information. */
|
||||
library class LocationParent_ extends @py_location_parent {
|
||||
/** Gets a textual representation of this element. */
|
||||
string toString() { result = "LocationParent" }
|
||||
}
|
||||
|
||||
/** INTERNAL: See the class `Operator` for further information. */
|
||||
library class Operator_ extends @py_operator {
|
||||
BinaryExpr getParent() { py_operators(this, _, result) }
|
||||
|
||||
/** Gets a textual representation of this element. */
|
||||
string toString() { result = "Operator" }
|
||||
}
|
||||
|
||||
/** INTERNAL: See the class `Parameter` for further information. */
|
||||
library class Parameter_ extends @py_parameter {
|
||||
/** Gets a textual representation of this element. */
|
||||
string toString() { result = "Parameter" }
|
||||
}
|
||||
|
||||
/** INTERNAL: See the class `Scope` for further information. */
|
||||
library class Scope_ extends @py_scope {
|
||||
/** Gets a textual representation of this element. */
|
||||
string toString() { result = "Scope" }
|
||||
}
|
||||
|
||||
/** INTERNAL: See the class `Stmt` for further information. */
|
||||
library class Stmt_ extends @py_stmt {
|
||||
/** Gets the location of this statement. */
|
||||
Location getLocation() { py_locations(result, this) }
|
||||
|
||||
StmtList getParent() { py_stmts(this, _, result, _) }
|
||||
|
||||
/** Gets a textual representation of this element. */
|
||||
string toString() { result = "Stmt" }
|
||||
}
|
||||
|
||||
/** INTERNAL: See the class `StmtList` for further information. */
|
||||
library class StmtList_ extends @py_stmt_list {
|
||||
StmtListParent getParent() { py_stmt_lists(this, result, _) }
|
||||
|
||||
@@ -1427,13 +1595,17 @@ library class StmtList_ extends @py_stmt_list {
|
||||
/** Gets the nth item of this statement list */
|
||||
Stmt getItem(int index) { py_stmts(result, _, this, index) }
|
||||
|
||||
/** Gets a textual representation of this element. */
|
||||
string toString() { result = "StmtList" }
|
||||
}
|
||||
|
||||
/** INTERNAL: See the class `StmtListParent` for further information. */
|
||||
library class StmtListParent_ extends @py_stmt_list_parent {
|
||||
/** Gets a textual representation of this element. */
|
||||
string toString() { result = "StmtListParent" }
|
||||
}
|
||||
|
||||
/** INTERNAL: See the class `StringList` for further information. */
|
||||
library class StringList_ extends @py_str_list {
|
||||
StrListParent getParent() { py_str_lists(this, result) }
|
||||
|
||||
@@ -1443,23 +1615,32 @@ library class StringList_ extends @py_str_list {
|
||||
/** Gets the nth item of this string list */
|
||||
string getItem(int index) { py_strs(result, this, index) }
|
||||
|
||||
/** Gets a textual representation of this element. */
|
||||
string toString() { result = "StringList" }
|
||||
}
|
||||
|
||||
/** INTERNAL: See the class `StrListParent` for further information. */
|
||||
library class StrListParent_ extends @py_str_list_parent {
|
||||
/** Gets a textual representation of this element. */
|
||||
string toString() { result = "StrListParent" }
|
||||
}
|
||||
|
||||
/** INTERNAL: See the class `StrParent` for further information. */
|
||||
library class StrParent_ extends @py_str_parent {
|
||||
/** Gets a textual representation of this element. */
|
||||
string toString() { result = "StrParent" }
|
||||
}
|
||||
|
||||
/** INTERNAL: See the class `Unaryop` for further information. */
|
||||
library class Unaryop_ extends @py_unaryop {
|
||||
UnaryExpr getParent() { py_unaryops(this, _, result) }
|
||||
|
||||
/** Gets a textual representation of this element. */
|
||||
string toString() { result = "Unaryop" }
|
||||
}
|
||||
|
||||
/** INTERNAL: See the class `VariableParent` for further information. */
|
||||
library class VariableParent_ extends @py_variable_parent {
|
||||
/** Gets a textual representation of this element. */
|
||||
string toString() { result = "VariableParent" }
|
||||
}
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
/**
|
||||
* Provides classes representing Python classes.
|
||||
*/
|
||||
|
||||
import python
|
||||
|
||||
/**
|
||||
@@ -37,6 +41,7 @@ class ClassExpr extends ClassExpr_ {
|
||||
result = this.getStarargs()
|
||||
}
|
||||
|
||||
/** Gets a call corresponding to a decorator of this class definition. */
|
||||
Call getADecoratorCall() {
|
||||
result.getArg(0) = this or
|
||||
result.getArg(0) = this.getADecoratorCall()
|
||||
@@ -114,9 +119,10 @@ class Class extends Class_, Scope, AstNode {
|
||||
/** Gets the name used to define this class */
|
||||
override string getName() { result = Class_.super.getName() }
|
||||
|
||||
/** Holds if this expression may have a side effect (as determined purely from its syntax). */
|
||||
predicate hasSideEffects() { any() }
|
||||
|
||||
/** Whether this is probably a mixin (has 'mixin' or similar in name or docstring) */
|
||||
/** Holds if this is probably a mixin (has 'mixin' or similar in name or docstring) */
|
||||
predicate isProbableMixin() {
|
||||
(
|
||||
this.getName().toLowerCase().matches("%mixin%")
|
||||
@@ -129,6 +135,7 @@ class Class extends Class_, Scope, AstNode {
|
||||
|
||||
override AstNode getAChildNode() { result = this.getAStmt() }
|
||||
|
||||
/** Gets a decorator of this class. */
|
||||
Expr getADecorator() { result = this.getParent().getADecorator() }
|
||||
|
||||
/** Gets the metaclass expression */
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
/**
|
||||
* Provides classes representing comments in Python.
|
||||
*/
|
||||
|
||||
import python
|
||||
|
||||
/** A source code comment */
|
||||
@@ -10,6 +14,7 @@ class Comment extends @py_comment {
|
||||
|
||||
Location getLocation() { py_comments(this, _, result) }
|
||||
|
||||
/** Gets a textual representation of this element. */
|
||||
string toString() { result = "Comment " + this.getText() }
|
||||
|
||||
/**
|
||||
@@ -51,22 +56,33 @@ class CommentBlock extends @py_comment {
|
||||
|
||||
private Comment last() { comment_block_part(this, result, this.length()) }
|
||||
|
||||
/** Gets a textual representation of this element. */
|
||||
string toString() { result = "Comment block" }
|
||||
|
||||
/** The length of this comment block (in comments) */
|
||||
int length() { result = max(int i | comment_block_part(this, _, i)) }
|
||||
|
||||
predicate hasLocationInfo(string filepath, int bl, int bc, int el, int ec) {
|
||||
this.(Comment).getLocation().hasLocationInfo(filepath, bl, bc, _, _) and
|
||||
exists(Comment end | end = this.last() | end.getLocation().hasLocationInfo(_, _, _, el, ec))
|
||||
/**
|
||||
* Holds if this element is at the specified location.
|
||||
* The location spans column `startcolumn` of line `startline` to
|
||||
* column `endcolumn` of line `endline` in file `filepath`.
|
||||
* For more information, see
|
||||
* [Locations](https://help.semmle.com/QL/learn-ql/ql/locations.html).
|
||||
*/
|
||||
predicate hasLocationInfo(
|
||||
string filepath, int startline, int startcolumn, int endline, int endcolumn
|
||||
) { this.(Comment).getLocation().hasLocationInfo(filepath, startline, startcolumn, _, _) and
|
||||
exists(Comment end | end = this.last() | end.getLocation().hasLocationInfo(_, _, _, endline, endcolumn))
|
||||
}
|
||||
|
||||
/** Holds if this comment block contains `c`. */
|
||||
predicate contains(Comment c) {
|
||||
comment_block_part(this, c, _)
|
||||
or
|
||||
this = c
|
||||
}
|
||||
|
||||
/** Gets a string representation of this comment block. */
|
||||
string getContents() {
|
||||
result =
|
||||
concat(Comment c, int i |
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
/**
|
||||
* Provides classes representing comparison operators.
|
||||
*/
|
||||
|
||||
import python
|
||||
|
||||
/** A class representing the six comparison operators, ==, !=, <, <=, > and >=. */
|
||||
@@ -34,6 +38,7 @@ class CompareOp extends int {
|
||||
this = ge() and result = le()
|
||||
}
|
||||
|
||||
/** Gets the textual representation of `this`. */
|
||||
string repr() {
|
||||
this = eq() and result = "=="
|
||||
or
|
||||
@@ -48,6 +53,7 @@ class CompareOp extends int {
|
||||
this = ge() and result = ">="
|
||||
}
|
||||
|
||||
/** Holds if `op` is the `Cmpop` corresponding to `this`. */
|
||||
predicate forOp(Cmpop op) {
|
||||
op instanceof Eq and this = eq()
|
||||
or
|
||||
@@ -70,16 +76,22 @@ class CompareOp extends int {
|
||||
}
|
||||
}
|
||||
|
||||
/** The `CompareOp` for "equals". */
|
||||
CompareOp eq() { result = 1 }
|
||||
|
||||
/** The `CompareOp` for "not equals". */
|
||||
CompareOp ne() { result = 2 }
|
||||
|
||||
/** The `CompareOp` for "less than". */
|
||||
CompareOp lt() { result = 3 }
|
||||
|
||||
/** The `CompareOp` for "less than or equal to". */
|
||||
CompareOp le() { result = 4 }
|
||||
|
||||
/** The `CompareOp` for "greater than". */
|
||||
CompareOp gt() { result = 5 }
|
||||
|
||||
/** The `CompareOp` for "greater than or equal to". */
|
||||
CompareOp ge() { result = 6 }
|
||||
|
||||
/* Workaround precision limits in floating point numbers */
|
||||
|
||||
@@ -7,6 +7,7 @@ class Expr extends Expr_, AstNode {
|
||||
/** Gets the scope of this expression */
|
||||
override Scope getScope() { py_scopes(this, result) }
|
||||
|
||||
/** Gets a textual representation of this element. */
|
||||
override string toString() { result = "Expression" }
|
||||
|
||||
/** Gets the module in which this expression occurs */
|
||||
|
||||
@@ -10,8 +10,21 @@ class File extends Container {
|
||||
/** DEPRECATED: Use `getAbsolutePath` instead. */
|
||||
deprecated string getFullName() { result = this.getAbsolutePath() }
|
||||
|
||||
predicate hasLocationInfo(string filepath, int bl, int bc, int el, int ec) {
|
||||
this.getAbsolutePath() = filepath and bl = 0 and bc = 0 and el = 0 and ec = 0
|
||||
/**
|
||||
* Holds if this element is at the specified location.
|
||||
* The location spans column `startcolumn` of line `startline` to
|
||||
* column `endcolumn` of line `endline` in file `filepath`.
|
||||
* For more information, see
|
||||
* [Locations](https://help.semmle.com/QL/learn-ql/ql/locations.html).
|
||||
*/
|
||||
predicate hasLocationInfo(
|
||||
string filepath, int startline, int startcolumn, int endline, int endcolumn
|
||||
) {
|
||||
this.getAbsolutePath() = filepath and
|
||||
startline = 0 and
|
||||
startcolumn = 0 and
|
||||
endline = 0 and
|
||||
endcolumn = 0
|
||||
}
|
||||
|
||||
/** Whether this file is a source code file. */
|
||||
@@ -79,8 +92,21 @@ class Folder extends Container {
|
||||
/** DEPRECATED: Use `getBaseName` instead. */
|
||||
deprecated string getSimple() { folders(this, _, result) }
|
||||
|
||||
predicate hasLocationInfo(string filepath, int bl, int bc, int el, int ec) {
|
||||
this.getAbsolutePath() = filepath and bl = 0 and bc = 0 and el = 0 and ec = 0
|
||||
/**
|
||||
* Holds if this element is at the specified location.
|
||||
* The location spans column `startcolumn` of line `startline` to
|
||||
* column `endcolumn` of line `endline` in file `filepath`.
|
||||
* For more information, see
|
||||
* [Locations](https://help.semmle.com/QL/learn-ql/ql/locations.html).
|
||||
*/
|
||||
predicate hasLocationInfo(
|
||||
string filepath, int startline, int startcolumn, int endline, int endcolumn
|
||||
) {
|
||||
this.getAbsolutePath() = filepath and
|
||||
startline = 0 and
|
||||
startcolumn = 0 and
|
||||
endline = 0 and
|
||||
endcolumn = 0
|
||||
}
|
||||
|
||||
override string getAbsolutePath() { folders(this, result, _) }
|
||||
@@ -367,30 +393,48 @@ class Location extends @location {
|
||||
locations_ast(this, _, _, _, _, result)
|
||||
}
|
||||
|
||||
/** Gets a textual representation of this element. */
|
||||
string toString() {
|
||||
result = this.getPath().getAbsolutePath() + ":" + this.getStartLine().toString()
|
||||
}
|
||||
|
||||
predicate hasLocationInfo(string filepath, int bl, int bc, int el, int ec) {
|
||||
exists(File f | f.getAbsolutePath() = filepath |
|
||||
locations_default(this, f, bl, bc, el, ec)
|
||||
/**
|
||||
* Holds if this element is at the specified location.
|
||||
* The location spans column `startcolumn` of line `startline` to
|
||||
* column `endcolumn` of line `endline` in file `filepath`.
|
||||
* For more information, see
|
||||
* [Locations](https://help.semmle.com/QL/learn-ql/ql/locations.html).
|
||||
*/
|
||||
predicate hasLocationInfo(
|
||||
string filepath, int startline, int startcolumn, int endline, int endcolumn
|
||||
) { exists(File f | f.getAbsolutePath() = filepath |
|
||||
locations_default(this, f, startline, startcolumn, endline, endcolumn)
|
||||
or
|
||||
exists(Module m | m.getFile() = f | locations_ast(this, m, bl, bc, el, ec))
|
||||
exists(Module m | m.getFile() = f | locations_ast(this, m, startline, startcolumn, endline, endcolumn))
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/** A non-empty line in the source code */
|
||||
class Line extends @py_line {
|
||||
predicate hasLocationInfo(string filepath, int bl, int bc, int el, int ec) {
|
||||
exists(Module m |
|
||||
/**
|
||||
* Holds if this element is at the specified location.
|
||||
* The location spans column `startcolumn` of line `startline` to
|
||||
* column `endcolumn` of line `endline` in file `filepath`.
|
||||
* For more information, see
|
||||
* [Locations](https://help.semmle.com/QL/learn-ql/ql/locations.html).
|
||||
*/
|
||||
predicate hasLocationInfo(
|
||||
string filepath, int startline, int startcolumn, int endline, int endcolumn
|
||||
) { exists(Module m |
|
||||
m.getFile().getAbsolutePath() = filepath and
|
||||
el = bl and
|
||||
bc = 1 and
|
||||
py_line_lengths(this, m, bl, ec)
|
||||
endline = startline and
|
||||
startcolumn = 1 and
|
||||
py_line_lengths(this, m, startline, endcolumn)
|
||||
)
|
||||
}
|
||||
|
||||
/** Gets a textual representation of this element. */
|
||||
string toString() {
|
||||
exists(Module m | py_line_lengths(this, m, _, _) |
|
||||
result = m.getFile().getShortName() + ":" + this.getLineNumber().toString()
|
||||
|
||||
@@ -139,6 +139,7 @@ class ControlFlowNode extends @py_flow_node {
|
||||
/** Gets the syntactic element corresponding to this flow node */
|
||||
AstNode getNode() { py_flow_bb_node(this, result, _, _) }
|
||||
|
||||
/** Gets a textual representation of this element. */
|
||||
string toString() {
|
||||
exists(Scope s | s.getEntryNode() = this | result = "Entry node for " + s.toString())
|
||||
or
|
||||
@@ -1014,6 +1015,7 @@ class BasicBlock extends @py_flow_node {
|
||||
/** Gets the nth node in this basic block */
|
||||
ControlFlowNode getNode(int n) { py_flow_bb_node(result, _, this, n) }
|
||||
|
||||
/** Gets a textual representation of this element. */
|
||||
string toString() { result = "BasicBlock" }
|
||||
|
||||
/** Whether this basic block strictly dominates the other */
|
||||
@@ -1079,9 +1081,17 @@ class BasicBlock extends @py_flow_node {
|
||||
this.getASuccessor().reachesExit()
|
||||
}
|
||||
|
||||
predicate hasLocationInfo(string file, int line, int col, int endl, int endc) {
|
||||
this.startLocationInfo(file, line, col) and
|
||||
this.endLocationInfo(endl, endc)
|
||||
/**
|
||||
* Holds if this element is at the specified location.
|
||||
* The location spans column `startcolumn` of line `startline` to
|
||||
* column `endcolumn` of line `endline` in file `filepath`.
|
||||
* For more information, see
|
||||
* [Locations](https://help.semmle.com/QL/learn-ql/ql/locations.html).
|
||||
*/
|
||||
predicate hasLocationInfo(
|
||||
string filepath, int startline, int startcolumn, int endline, int endcolumn
|
||||
) { this.startLocationInfo(filepath, startline, startcolumn) and
|
||||
this.endLocationInfo(endline, endcolumn)
|
||||
}
|
||||
|
||||
/** Gets a true successor to this basic block */
|
||||
|
||||
@@ -76,6 +76,7 @@ class SsaVariable extends @py_ssa_var {
|
||||
result = this.getAPhiInput().getAnUltimateDefinition()
|
||||
}
|
||||
|
||||
/** Gets a textual representation of this element. */
|
||||
string toString() { result = "SSA Variable " + this.getId() }
|
||||
|
||||
Location getLocation() { result = this.getDefinition().getLocation() }
|
||||
|
||||
@@ -90,8 +90,16 @@ class AugAssign extends AugAssign_ {
|
||||
/* syntax: Expr += Expr */
|
||||
override Expr getASubExpression() { result = this.getOperation() }
|
||||
|
||||
/**
|
||||
* Gets the target of this augmented assignment statement.
|
||||
* That is, the `a` in `a += b`.
|
||||
*/
|
||||
Expr getTarget() { result = this.getOperation().(BinaryExpr).getLeft() }
|
||||
|
||||
/**
|
||||
* Gets the value of this augmented assignment statement.
|
||||
* That is, the `b` in `a += b`.
|
||||
*/
|
||||
Expr getValue() { result = this.getOperation().(BinaryExpr).getRight() }
|
||||
|
||||
override Stmt getASubStatement() { none() }
|
||||
@@ -405,11 +413,13 @@ class TemplateWrite extends TemplateWrite_ {
|
||||
override Stmt getASubStatement() { none() }
|
||||
}
|
||||
|
||||
/** An asynchronous `for` statement, such as `async for varname in Expr: ...` */
|
||||
class AsyncFor extends For {
|
||||
/* syntax: async for varname in Expr: ... */
|
||||
AsyncFor() { this.isAsync() }
|
||||
}
|
||||
|
||||
/** An asynchronous `with` statement, such as `async with varname as Expr: ...` */
|
||||
class AsyncWith extends With {
|
||||
/* syntax: async with Expr as varname: ... */
|
||||
AsyncWith() { this.isAsync() }
|
||||
@@ -417,10 +427,11 @@ class AsyncWith extends With {
|
||||
|
||||
/** A list of statements */
|
||||
class StmtList extends StmtList_ {
|
||||
/** Whether this list of statements contains s */
|
||||
/** Holds if this list of statements contains the AST node `a` */
|
||||
predicate contains(AstNode a) {
|
||||
exists(Stmt item | item = this.getAnItem() | item = a or item.contains(a))
|
||||
}
|
||||
|
||||
/** Gets the last item in this list of statements, if any. */
|
||||
Stmt getLastItem() { result = this.getItem(max(int i | exists(this.getItem(i)))) }
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@ class Variable extends @py_variable {
|
||||
/** Gets the identifier (name) of this variable */
|
||||
string getId() { variable(this, _, result) }
|
||||
|
||||
/** Gets a textual representation of this element. */
|
||||
string toString() { result = "Variable " + this.getId() }
|
||||
|
||||
/** Gets an access (load or store) of this variable */
|
||||
|
||||
@@ -24,6 +24,7 @@ newtype TTaintTrackingContext =
|
||||
* Used to track taint through calls accurately and reasonably efficiently.
|
||||
*/
|
||||
class TaintTrackingContext extends TTaintTrackingContext {
|
||||
/** Gets a textual representation of this element. */
|
||||
string toString() {
|
||||
this = TNoParam() and result = ""
|
||||
or
|
||||
@@ -66,6 +67,7 @@ private newtype TAttributePath =
|
||||
* Used for tracking tainted attributes of objects.
|
||||
*/
|
||||
abstract class AttributePath extends TAttributePath {
|
||||
/** Gets a textual representation of this element. */
|
||||
abstract string toString();
|
||||
|
||||
abstract string extension();
|
||||
@@ -126,6 +128,7 @@ newtype TTaintTrackingNode =
|
||||
* Used for context-sensitive path-aware taint-tracking.
|
||||
*/
|
||||
class TaintTrackingNode extends TTaintTrackingNode {
|
||||
/** Gets a textual representation of this element. */
|
||||
string toString() {
|
||||
if this.getPath() instanceof NoAttribute
|
||||
then result = this.getTaintKind().repr()
|
||||
|
||||
@@ -355,6 +355,7 @@ abstract class Sanitizer extends string {
|
||||
* class to provide their own sources.
|
||||
*/
|
||||
abstract class TaintSource extends @py_flow_node {
|
||||
/** Gets a textual representation of this element. */
|
||||
string toString() { result = "Taint source" }
|
||||
|
||||
/**
|
||||
@@ -378,8 +379,16 @@ abstract class TaintSource extends @py_flow_node {
|
||||
|
||||
Location getLocation() { result = this.(ControlFlowNode).getLocation() }
|
||||
|
||||
predicate hasLocationInfo(string fp, int bl, int bc, int el, int ec) {
|
||||
this.getLocation().hasLocationInfo(fp, bl, bc, el, ec)
|
||||
/**
|
||||
* Holds if this element is at the specified location.
|
||||
* The location spans column `startcolumn` of line `startline` to
|
||||
* column `endcolumn` of line `endline` in file `filepath`.
|
||||
* For more information, see
|
||||
* [Locations](https://help.semmle.com/QL/learn-ql/ql/locations.html).
|
||||
*/
|
||||
predicate hasLocationInfo(
|
||||
string filepath, int startline, int startcolumn, int endline, int endcolumn
|
||||
) { this.getLocation().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
|
||||
}
|
||||
|
||||
/** Gets a TaintedNode for this taint source */
|
||||
@@ -470,6 +479,7 @@ private class SequenceExtends extends DataFlowExtension::DataFlowNode {
|
||||
* class to provide their own sink nodes.
|
||||
*/
|
||||
abstract class TaintSink extends @py_flow_node {
|
||||
/** Gets a textual representation of this element. */
|
||||
string toString() { result = "Taint sink" }
|
||||
|
||||
/**
|
||||
@@ -482,8 +492,16 @@ abstract class TaintSink extends @py_flow_node {
|
||||
|
||||
Location getLocation() { result = this.(ControlFlowNode).getLocation() }
|
||||
|
||||
predicate hasLocationInfo(string fp, int bl, int bc, int el, int ec) {
|
||||
this.getLocation().hasLocationInfo(fp, bl, bc, el, ec)
|
||||
/**
|
||||
* Holds if this element is at the specified location.
|
||||
* The location spans column `startcolumn` of line `startline` to
|
||||
* column `endcolumn` of line `endline` in file `filepath`.
|
||||
* For more information, see
|
||||
* [Locations](https://help.semmle.com/QL/learn-ql/ql/locations.html).
|
||||
*/
|
||||
predicate hasLocationInfo(
|
||||
string filepath, int startline, int startcolumn, int endline, int endcolumn
|
||||
) { this.getLocation().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -495,6 +513,7 @@ abstract class TaintSink extends @py_flow_node {
|
||||
module DataFlowExtension {
|
||||
/** A control flow node that modifies the basic data-flow. */
|
||||
abstract class DataFlowNode extends @py_flow_node {
|
||||
/** Gets a textual representation of this element. */
|
||||
string toString() { result = "Dataflow extension node" }
|
||||
|
||||
/**
|
||||
@@ -641,6 +660,7 @@ module DataFlow {
|
||||
|
||||
abstract EssaVariable asVariable();
|
||||
|
||||
/** Gets a textual representation of this element. */
|
||||
abstract string toString();
|
||||
|
||||
abstract Scope getScope();
|
||||
@@ -660,6 +680,7 @@ module DataFlow {
|
||||
|
||||
override EssaVariable asVariable() { none() }
|
||||
|
||||
/** Gets a textual representation of this element. */
|
||||
override string toString() { result = this.asAstNode().toString() }
|
||||
|
||||
override Scope getScope() { result = this.asCfgNode().getScope() }
|
||||
@@ -674,6 +695,7 @@ module DataFlow {
|
||||
|
||||
override EssaVariable asVariable() { this = TEssaNode(result) }
|
||||
|
||||
/** Gets a textual representation of this element. */
|
||||
override string toString() { result = this.asVariable().toString() }
|
||||
|
||||
override Scope getScope() { result = this.asVariable().getScope() }
|
||||
|
||||
@@ -29,6 +29,7 @@ abstract class SsaSourceVariable extends @py_variable {
|
||||
|
||||
abstract ControlFlowNode getScopeEntryDefinition();
|
||||
|
||||
/** Gets a textual representation of this element. */
|
||||
string toString() { result = "SsaSourceVariable " + this.getName() }
|
||||
|
||||
/** Gets a use of this variable, either explicit or implicit. */
|
||||
|
||||
@@ -24,6 +24,7 @@ class EssaVariable extends TEssaDefinition {
|
||||
/** Gets the name of this variable. */
|
||||
string getName() { result = this.getSourceVariable().getName() }
|
||||
|
||||
/** Gets a textual representation of this element. */
|
||||
string toString() { result = "SSA variable " + this.getName() }
|
||||
|
||||
/**
|
||||
@@ -131,6 +132,7 @@ private newtype TEssaDefinition =
|
||||
* and exactly one variable for each definition.
|
||||
*/
|
||||
abstract class EssaDefinition extends TEssaDefinition {
|
||||
/** Gets a textual representation of this element. */
|
||||
string toString() { result = "EssaDefinition" }
|
||||
|
||||
/** Gets the source variable for which this a definition, either explicit or implicit. */
|
||||
|
||||
@@ -36,6 +36,7 @@ class Value extends TObject {
|
||||
this != ObjectInternal::undefined()
|
||||
}
|
||||
|
||||
/** Gets a textual representation of this element. */
|
||||
string toString() { result = this.(ObjectInternal).toString() }
|
||||
|
||||
/** Gets a `ControlFlowNode` that refers to this object. */
|
||||
@@ -73,15 +74,28 @@ class Value extends TObject {
|
||||
*/
|
||||
predicate isBuiltin() { this.(ObjectInternal).isBuiltin() }
|
||||
|
||||
predicate hasLocationInfo(string filepath, int bl, int bc, int el, int ec) {
|
||||
this.(ObjectInternal).getOrigin().getLocation().hasLocationInfo(filepath, bl, bc, el, ec)
|
||||
/**
|
||||
* Holds if this element is at the specified location.
|
||||
* The location spans column `startcolumn` of line `startline` to
|
||||
* column `endcolumn` of line `endline` in file `filepath`.
|
||||
* For more information, see
|
||||
* [Locations](https://help.semmle.com/QL/learn-ql/ql/locations.html).
|
||||
*/
|
||||
predicate hasLocationInfo(
|
||||
string filepath, int startline, int startcolumn, int endline, int endcolumn
|
||||
) {
|
||||
this
|
||||
.(ObjectInternal)
|
||||
.getOrigin()
|
||||
.getLocation()
|
||||
.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
|
||||
or
|
||||
not exists(this.(ObjectInternal).getOrigin()) and
|
||||
filepath = "" and
|
||||
bl = 0 and
|
||||
bc = 0 and
|
||||
el = 0 and
|
||||
ec = 0
|
||||
startline = 0 and
|
||||
startcolumn = 0 and
|
||||
endline = 0 and
|
||||
endcolumn = 0
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -882,6 +896,7 @@ class PropertyValue extends Value {
|
||||
|
||||
/** A method-resolution-order sequence of classes */
|
||||
class MRO extends TClassList {
|
||||
/** Gets a textual representation of this element. */
|
||||
string toString() { result = this.(ClassList).toString() }
|
||||
|
||||
/** Gets the `n`th class in this MRO */
|
||||
|
||||
@@ -17,6 +17,7 @@ import semmle.python.objects.Sequences
|
||||
import semmle.python.objects.Descriptors
|
||||
|
||||
class ObjectInternal extends TObject {
|
||||
/** Gets a textual representation of this element. */
|
||||
abstract string toString();
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
/** Contains the internal algebraic datatype backing the various values tracked by the points-to implementation. */
|
||||
|
||||
import python
|
||||
private import semmle.python.types.Builtins
|
||||
private import semmle.python.objects.ObjectInternal
|
||||
@@ -10,19 +12,19 @@ private import semmle.python.pointsto.PointsToContext
|
||||
*/
|
||||
cached
|
||||
newtype TObject =
|
||||
/* Builtin class objects */
|
||||
/** Builtin class objects */
|
||||
TBuiltinClassObject(Builtin bltn) {
|
||||
bltn.isClass() and
|
||||
not bltn = Builtin::unknownType() and
|
||||
not bltn = Builtin::special("type")
|
||||
} or
|
||||
/* Builtin function objects (module members) */
|
||||
/** Builtin function objects (module members) */
|
||||
TBuiltinFunctionObject(Builtin bltn) { bltn.isFunction() } or
|
||||
/* Builtin method objects (class members) */
|
||||
/** Builtin method objects (class members) */
|
||||
TBuiltinMethodObject(Builtin bltn) { bltn.isMethod() } or
|
||||
/* Builtin module objects */
|
||||
/** Builtin module objects */
|
||||
TBuiltinModuleObject(Builtin bltn) { bltn.isModule() } or
|
||||
/* Other builtin objects from the interpreter */
|
||||
/** Other builtin objects from the interpreter */
|
||||
TBuiltinOpaqueObject(Builtin bltn) {
|
||||
not bltn.isClass() and
|
||||
not bltn.isFunction() and
|
||||
@@ -34,31 +36,31 @@ newtype TObject =
|
||||
not exists(bltn.strValue()) and
|
||||
not py_special_objects(bltn, _)
|
||||
} or
|
||||
/* Python function objects (including lambdas) */
|
||||
/** Python function objects (including lambdas) */
|
||||
TPythonFunctionObject(ControlFlowNode callable) { callable.getNode() instanceof CallableExpr } or
|
||||
/* Python class objects */
|
||||
/** Python class objects */
|
||||
TPythonClassObject(ControlFlowNode classexpr) { classexpr.getNode() instanceof ClassExpr } or
|
||||
/* Package objects */
|
||||
/** Package objects */
|
||||
TPackageObject(Folder f) { isPreferredModuleForName(f, _) } or
|
||||
/* Python module objects */
|
||||
/** Python module objects */
|
||||
TPythonModule(Module m) {
|
||||
not m.isPackage() and
|
||||
isPreferredModuleForName(m.getFile(), _) and
|
||||
not exists(SyntaxError se | se.getFile() = m.getFile())
|
||||
} or
|
||||
/* `True` */
|
||||
/** `True` */
|
||||
TTrue() or
|
||||
/* `False` */
|
||||
/** `False` */
|
||||
TFalse() or
|
||||
/* `None` */
|
||||
/** `None` */
|
||||
TNone() or
|
||||
/* Represents any value about which nothing useful is known */
|
||||
/** Represents any value about which nothing useful is known */
|
||||
TUnknown() or
|
||||
/* Represents any value known to be a class, but not known to be any specific class */
|
||||
/** Represents any value known to be a class, but not known to be any specific class */
|
||||
TUnknownClass() or
|
||||
/* Represents the absence of a value. Used by points-to for tracking undefined variables */
|
||||
/** Represents the absence of a value. Used by points-to for tracking undefined variables */
|
||||
TUndefined() or
|
||||
/* The integer `n` */
|
||||
/** The integer `n` */
|
||||
TInt(int n) {
|
||||
// Powers of 2 are used for flags
|
||||
is_power_2(n)
|
||||
@@ -76,9 +78,9 @@ newtype TObject =
|
||||
or
|
||||
n = any(Builtin b).intValue()
|
||||
} or
|
||||
/* The float `f` */
|
||||
/** The float `f` */
|
||||
TFloat(float f) { f = any(FloatLiteral num).getValue() } or
|
||||
/* The unicode string `s` */
|
||||
/** The unicode string `s` */
|
||||
TUnicode(string s) {
|
||||
// Any string explicitly mentioned in the source code.
|
||||
exists(StrConst str |
|
||||
@@ -94,7 +96,7 @@ newtype TObject =
|
||||
or
|
||||
s = "__main__"
|
||||
} or
|
||||
/* The byte string `s` */
|
||||
/** The byte string `s` */
|
||||
TBytes(string s) {
|
||||
// Any string explicitly mentioned in the source code.
|
||||
exists(StrConst str |
|
||||
@@ -110,74 +112,74 @@ newtype TObject =
|
||||
or
|
||||
s = "__main__"
|
||||
} or
|
||||
/* An instance of `cls`, instantiated at `instantiation` given the `context`. */
|
||||
/** An instance of `cls`, instantiated at `instantiation` given the `context`. */
|
||||
TSpecificInstance(ControlFlowNode instantiation, ClassObjectInternal cls, PointsToContext context) {
|
||||
PointsToInternal::pointsTo(instantiation.(CallNode).getFunction(), context, cls, _) and
|
||||
cls.isSpecial() = false
|
||||
or
|
||||
literal_instantiation(instantiation, cls, context)
|
||||
} or
|
||||
/* A non-specific instance `cls` which enters the scope at `def` given the callee `context`. */
|
||||
/** A non-specific instance `cls` which enters the scope at `def` given the callee `context`. */
|
||||
TSelfInstance(ParameterDefinition def, PointsToContext context, PythonClassObjectInternal cls) {
|
||||
self_parameter(def, context, cls)
|
||||
} or
|
||||
/* A bound method */
|
||||
/** A bound method */
|
||||
TBoundMethod(ObjectInternal self, CallableObjectInternal function) {
|
||||
any(ObjectInternal obj).binds(self, _, function) and
|
||||
function.isDescriptor() = true
|
||||
} or
|
||||
/* Represents any value whose class is known, but nothing else */
|
||||
/** Represents any value whose class is known, but nothing else */
|
||||
TUnknownInstance(BuiltinClassObjectInternal cls) {
|
||||
cls != ObjectInternal::superType() and
|
||||
cls != ObjectInternal::builtin("bool") and
|
||||
cls != ObjectInternal::noneType()
|
||||
} or
|
||||
/* Represents an instance of `super` */
|
||||
/** Represents an instance of `super` */
|
||||
TSuperInstance(ObjectInternal self, ClassObjectInternal startclass) {
|
||||
super_instantiation(_, self, startclass, _)
|
||||
} or
|
||||
/* Represents an instance of `classmethod` */
|
||||
/** Represents an instance of `classmethod` */
|
||||
TClassMethod(CallNode instantiation, CallableObjectInternal function) {
|
||||
class_method(instantiation, function, _)
|
||||
} or
|
||||
/* Represents an instance of `staticmethod` */
|
||||
/** Represents an instance of `staticmethod` */
|
||||
TStaticMethod(CallNode instantiation, CallableObjectInternal function) {
|
||||
static_method(instantiation, function, _)
|
||||
} or
|
||||
/* Represents a builtin tuple */
|
||||
/** Represents a builtin tuple */
|
||||
TBuiltinTuple(Builtin bltn) { bltn.getClass() = Builtin::special("tuple") } or
|
||||
/* Represents a tuple in the Python source */
|
||||
/** Represents a tuple in the Python source */
|
||||
TPythonTuple(TupleNode origin, PointsToContext context) {
|
||||
origin.isLoad() and
|
||||
context.appliesTo(origin)
|
||||
} or
|
||||
/* Varargs tuple */
|
||||
/** Varargs tuple */
|
||||
TVarargsTuple(CallNode call, PointsToContext context, int offset, int length) {
|
||||
InterProceduralPointsTo::varargs_tuple(call, context, _, _, offset, length)
|
||||
} or
|
||||
/* `type` */
|
||||
/** `type` */
|
||||
TType() or
|
||||
/* Represents an instance of `property` */
|
||||
/** Represents an instance of `property` */
|
||||
TProperty(CallNode call, Context ctx, CallableObjectInternal getter) {
|
||||
PointsToInternal::pointsTo(call.getFunction(), ctx, ObjectInternal::property(), _) and
|
||||
PointsToInternal::pointsTo(call.getArg(0), ctx, getter, _)
|
||||
} or
|
||||
/* Represents the `setter` or `deleter` method of a property object. */
|
||||
/** Represents the `setter` or `deleter` method of a property object. */
|
||||
TPropertySetterOrDeleter(PropertyInternal property, string method) {
|
||||
exists(AttrNode attr | PointsToInternal::pointsTo(attr.getObject(method), _, property, _)) and
|
||||
(method = "setter" or method = "deleter")
|
||||
} or
|
||||
/* Represents a dynamically created class */
|
||||
/** Represents a dynamically created class */
|
||||
TDynamicClass(CallNode instantiation, ClassObjectInternal metacls, PointsToContext context) {
|
||||
PointsToInternal::pointsTo(instantiation.getFunction(), context, metacls, _) and
|
||||
not count(instantiation.getAnArg()) = 1 and
|
||||
Types::getMro(metacls).contains(TType())
|
||||
} or
|
||||
/* Represents `sys.version_info`. Acts like a tuple with a range of values depending on the version being analysed. */
|
||||
/** Represents `sys.version_info`. Acts like a tuple with a range of values depending on the version being analysed. */
|
||||
TSysVersionInfo() or
|
||||
/* Represents a module that is inferred to perhaps exist, but is not present in the database. */
|
||||
/** Represents a module that is inferred to perhaps exist, but is not present in the database. */
|
||||
TAbsentModule(string name) { missing_imported_module(_, _, name) } or
|
||||
/* Represents an attribute of a module that is inferred to perhaps exist, but is not present in the database. */
|
||||
/** Represents an attribute of a module that is inferred to perhaps exist, but is not present in the database. */
|
||||
TAbsentModuleAttribute(AbsentModuleObjectInternal mod, string attrname) {
|
||||
(
|
||||
PointsToInternal::pointsTo(any(AttrNode attr).getObject(attrname), _, mod, _)
|
||||
@@ -189,9 +191,9 @@ newtype TObject =
|
||||
not common_module_name(modname + "." + attrname)
|
||||
)
|
||||
} or
|
||||
/* Opaque object representing the result of calling a decorator on a function that we don't understand */
|
||||
/** Opaque object representing the result of calling a decorator on a function that we don't understand */
|
||||
TDecoratedFunction(CallNode call) { call.isFunctionDecoratorCall() } or
|
||||
/* Represents a subscript operation applied to a type. For type-hint analysis */
|
||||
/** Represents a subscript operation applied to a type. For type-hint analysis */
|
||||
TSubscriptedType(ObjectInternal generic, ObjectInternal index) {
|
||||
isType(generic) and
|
||||
generic.isNotSubscriptedType() and
|
||||
@@ -199,6 +201,7 @@ newtype TObject =
|
||||
Expressions::subscriptPartsPointsTo(_, _, generic, index)
|
||||
}
|
||||
|
||||
/** Holds if the object `t` is a type. */
|
||||
predicate isType(ObjectInternal t) {
|
||||
t.isClass() = true
|
||||
or
|
||||
@@ -421,7 +424,7 @@ predicate missing_imported_module(ControlFlowNode imp, Context ctx, string name)
|
||||
)
|
||||
}
|
||||
|
||||
/*
|
||||
/**
|
||||
* Helper for missing modules to determine if name `x.y` is a module `x.y` or
|
||||
* an attribute `y` of module `x`. This list should be added to as required.
|
||||
*/
|
||||
@@ -444,6 +447,7 @@ library class ClassDecl extends @py_object {
|
||||
this.(ControlFlowNode).getNode() instanceof ClassExpr
|
||||
}
|
||||
|
||||
/** Gets a textual representation of this element. */
|
||||
string toString() { result = "ClassDecl" }
|
||||
|
||||
/** Gets the class scope for Python class declarations */
|
||||
|
||||
@@ -195,6 +195,7 @@ private newtype TIterationDefinition =
|
||||
* A definition of a variable in a for loop `for v in ...:`
|
||||
*/
|
||||
deprecated class IterationDefinition extends TIterationDefinition {
|
||||
/** Gets a textual representation of this element. */
|
||||
string toString() { result = "IterationDefinition" }
|
||||
|
||||
ControlFlowNode getSequence() { this = TIterationDefinition_(_, _, result) }
|
||||
|
||||
@@ -28,6 +28,7 @@ private newtype TTInvocation =
|
||||
* all calls made to a function for a given context.
|
||||
*/
|
||||
class FunctionInvocation extends TTInvocation {
|
||||
/** Gets a textual representation of this element. */
|
||||
string toString() { result = "Invocation" }
|
||||
|
||||
FunctionObject getFunction() { this = TInvocation(result, _) }
|
||||
|
||||
@@ -68,6 +68,7 @@ private ClassObjectInternal sole_base(ClassObjectInternal cls) {
|
||||
|
||||
/** A list of classes, used to represent the MRO of a class */
|
||||
class ClassList extends TClassList {
|
||||
/** Gets a textual representation of this element. */
|
||||
string toString() { result = "[" + this.contents() + "]" }
|
||||
|
||||
string contents() {
|
||||
@@ -243,6 +244,7 @@ private predicate required_list(ClassList head, ClassListList tail) {
|
||||
}
|
||||
|
||||
private class ClassListList extends TClassListList {
|
||||
/** Gets a textual representation of this element. */
|
||||
string toString() { result = "[" + this.contents() + "]" }
|
||||
|
||||
string contents() {
|
||||
|
||||
@@ -9,6 +9,7 @@ private import semmle.python.types.Extensions
|
||||
|
||||
/* Use this version for speed */
|
||||
library class CfgOrigin extends @py_object {
|
||||
/** Gets a textual representation of this element. */
|
||||
string toString() {
|
||||
/* Not to be displayed */
|
||||
result = "CfgOrigin"
|
||||
|
||||
@@ -129,6 +129,7 @@ module Context {
|
||||
* * All other contexts are call contexts and consist of a pair of call-site and caller context.
|
||||
*/
|
||||
class PointsToContext extends TPointsToContext {
|
||||
/** Gets a textual representation of this element. */
|
||||
cached
|
||||
string toString() {
|
||||
this = TMainContext() and result = "main"
|
||||
|
||||
@@ -17,6 +17,7 @@ class Builtin extends @py_cobject {
|
||||
)
|
||||
}
|
||||
|
||||
/** Gets a textual representation of this element. */
|
||||
string toString() {
|
||||
not this = undefinedVariable().asBuiltin() and
|
||||
not this = Builtin::unknown() and
|
||||
|
||||
@@ -64,20 +64,29 @@ class Object extends @py_object {
|
||||
|
||||
private predicate hasOrigin() { py_flow_bb_node(this, _, _, _) }
|
||||
|
||||
predicate hasLocationInfo(string filepath, int bl, int bc, int el, int ec) {
|
||||
this.hasOrigin() and this.getOrigin().getLocation().hasLocationInfo(filepath, bl, bc, el, ec)
|
||||
/**
|
||||
* Holds if this element is at the specified location.
|
||||
* The location spans column `startcolumn` of line `startline` to
|
||||
* column `endcolumn` of line `endline` in file `filepath`.
|
||||
* For more information, see
|
||||
* [Locations](https://help.semmle.com/QL/learn-ql/ql/locations.html).
|
||||
*/
|
||||
predicate hasLocationInfo(
|
||||
string filepath, int startline, int startcolumn, int endline, int endcolumn
|
||||
) { this.hasOrigin() and this.getOrigin().getLocation().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
|
||||
or
|
||||
not this.hasOrigin() and
|
||||
filepath = ":Compiled Code" and
|
||||
bl = 0 and
|
||||
bc = 0 and
|
||||
el = 0 and
|
||||
ec = 0
|
||||
startline = 0 and
|
||||
startcolumn = 0 and
|
||||
endline = 0 and
|
||||
endcolumn = 0
|
||||
}
|
||||
|
||||
/** INTERNAL -- Do not use */
|
||||
Builtin asBuiltin() { result = this }
|
||||
|
||||
/** Gets a textual representation of this element. */
|
||||
string toString() {
|
||||
not this = undefinedVariable() and
|
||||
not this = unknownValue() and
|
||||
|
||||
@@ -63,6 +63,7 @@ class UntrustedCookie extends TaintKind {
|
||||
}
|
||||
|
||||
abstract class CookieOperation extends @py_flow_node {
|
||||
/** Gets a textual representation of this element. */
|
||||
abstract string toString();
|
||||
|
||||
abstract ControlFlowNode getKey();
|
||||
|
||||
47
python/ql/test/experimental/CWE-091/Xslt.expected
Normal file
47
python/ql/test/experimental/CWE-091/Xslt.expected
Normal file
@@ -0,0 +1,47 @@
|
||||
edges
|
||||
| xslt.py:10:17:10:28 | dict of etree.XML string | xslt.py:10:17:10:43 | etree.XML string |
|
||||
| xslt.py:10:17:10:28 | dict of etree.XML string | xslt.py:10:17:10:43 | etree.XML string |
|
||||
| xslt.py:10:17:10:43 | etree.XML string | xslt.py:11:27:11:35 | etree.XML string |
|
||||
| xslt.py:10:17:10:43 | etree.XML string | xslt.py:11:27:11:35 | etree.XML string |
|
||||
| xslt.py:11:17:11:36 | lxml etree xml | xslt.py:14:29:14:37 | lxml etree xml |
|
||||
| xslt.py:11:17:11:36 | lxml etree xml | xslt.py:14:29:14:37 | lxml etree xml |
|
||||
| xslt.py:11:27:11:35 | etree.XML string | xslt.py:11:17:11:36 | lxml etree xml |
|
||||
| xslt.py:11:27:11:35 | etree.XML string | xslt.py:11:17:11:36 | lxml etree xml |
|
||||
| xsltInjection.py:10:17:10:28 | dict of etree.XML string | xsltInjection.py:10:17:10:43 | etree.XML string |
|
||||
| xsltInjection.py:10:17:10:28 | dict of etree.XML string | xsltInjection.py:10:17:10:43 | etree.XML string |
|
||||
| xsltInjection.py:10:17:10:43 | etree.XML string | xsltInjection.py:11:27:11:35 | etree.XML string |
|
||||
| xsltInjection.py:10:17:10:43 | etree.XML string | xsltInjection.py:11:27:11:35 | etree.XML string |
|
||||
| xsltInjection.py:11:17:11:36 | lxml etree xml | xsltInjection.py:12:28:12:36 | lxml etree xml |
|
||||
| xsltInjection.py:11:17:11:36 | lxml etree xml | xsltInjection.py:12:28:12:36 | lxml etree xml |
|
||||
| xsltInjection.py:11:27:11:35 | etree.XML string | xsltInjection.py:11:17:11:36 | lxml etree xml |
|
||||
| xsltInjection.py:11:27:11:35 | etree.XML string | xsltInjection.py:11:17:11:36 | lxml etree xml |
|
||||
| xsltInjection.py:17:17:17:28 | dict of etree.XML string | xsltInjection.py:17:17:17:43 | etree.XML string |
|
||||
| xsltInjection.py:17:17:17:28 | dict of etree.XML string | xsltInjection.py:17:17:17:43 | etree.XML string |
|
||||
| xsltInjection.py:17:17:17:43 | etree.XML string | xsltInjection.py:18:27:18:35 | etree.XML string |
|
||||
| xsltInjection.py:17:17:17:43 | etree.XML string | xsltInjection.py:18:27:18:35 | etree.XML string |
|
||||
| xsltInjection.py:18:17:18:36 | lxml etree xml | xsltInjection.py:21:29:21:37 | lxml etree xml |
|
||||
| xsltInjection.py:18:17:18:36 | lxml etree xml | xsltInjection.py:21:29:21:37 | lxml etree xml |
|
||||
| xsltInjection.py:18:27:18:35 | etree.XML string | xsltInjection.py:18:17:18:36 | lxml etree xml |
|
||||
| xsltInjection.py:18:27:18:35 | etree.XML string | xsltInjection.py:18:17:18:36 | lxml etree xml |
|
||||
| xsltInjection.py:26:17:26:28 | dict of etree.XML string | xsltInjection.py:26:17:26:43 | etree.XML string |
|
||||
| xsltInjection.py:26:17:26:28 | dict of etree.XML string | xsltInjection.py:26:17:26:43 | etree.XML string |
|
||||
| xsltInjection.py:26:17:26:43 | etree.XML string | xsltInjection.py:27:27:27:35 | etree.XML string |
|
||||
| xsltInjection.py:26:17:26:43 | etree.XML string | xsltInjection.py:27:27:27:35 | etree.XML string |
|
||||
| xsltInjection.py:27:17:27:36 | lxml etree xml | xsltInjection.py:31:24:31:32 | lxml etree xml |
|
||||
| xsltInjection.py:27:17:27:36 | lxml etree xml | xsltInjection.py:31:24:31:32 | lxml etree xml |
|
||||
| xsltInjection.py:27:27:27:35 | etree.XML string | xsltInjection.py:27:17:27:36 | lxml etree xml |
|
||||
| xsltInjection.py:27:27:27:35 | etree.XML string | xsltInjection.py:27:17:27:36 | lxml etree xml |
|
||||
| xsltInjection.py:35:17:35:28 | dict of etree.XML string | xsltInjection.py:35:17:35:43 | etree.XML string |
|
||||
| xsltInjection.py:35:17:35:28 | dict of etree.XML string | xsltInjection.py:35:17:35:43 | etree.XML string |
|
||||
| xsltInjection.py:35:17:35:43 | etree.XML string | xsltInjection.py:36:34:36:42 | etree.XML string |
|
||||
| xsltInjection.py:35:17:35:43 | etree.XML string | xsltInjection.py:36:34:36:42 | etree.XML string |
|
||||
| xsltInjection.py:36:17:36:43 | lxml etree xml | xsltInjection.py:40:24:40:32 | lxml etree xml |
|
||||
| xsltInjection.py:36:17:36:43 | lxml etree xml | xsltInjection.py:40:24:40:32 | lxml etree xml |
|
||||
| xsltInjection.py:36:34:36:42 | etree.XML string | xsltInjection.py:36:17:36:43 | lxml etree xml |
|
||||
| xsltInjection.py:36:34:36:42 | etree.XML string | xsltInjection.py:36:17:36:43 | lxml etree xml |
|
||||
#select
|
||||
| xslt.py:14:29:14:37 | xslt_root | xslt.py:10:17:10:28 | dict of etree.XML string | xslt.py:14:29:14:37 | lxml etree xml | This XSLT query depends on $@. | xslt.py:10:17:10:28 | Attribute | a user-provided value |
|
||||
| xsltInjection.py:12:28:12:36 | xslt_root | xsltInjection.py:10:17:10:28 | dict of etree.XML string | xsltInjection.py:12:28:12:36 | lxml etree xml | This XSLT query depends on $@. | xsltInjection.py:10:17:10:28 | Attribute | a user-provided value |
|
||||
| xsltInjection.py:21:29:21:37 | xslt_root | xsltInjection.py:17:17:17:28 | dict of etree.XML string | xsltInjection.py:21:29:21:37 | lxml etree xml | This XSLT query depends on $@. | xsltInjection.py:17:17:17:28 | Attribute | a user-provided value |
|
||||
| xsltInjection.py:31:24:31:32 | xslt_root | xsltInjection.py:26:17:26:28 | dict of etree.XML string | xsltInjection.py:31:24:31:32 | lxml etree xml | This XSLT query depends on $@. | xsltInjection.py:26:17:26:28 | Attribute | a user-provided value |
|
||||
| xsltInjection.py:40:24:40:32 | xslt_root | xsltInjection.py:35:17:35:28 | dict of etree.XML string | xsltInjection.py:40:24:40:32 | lxml etree xml | This XSLT query depends on $@. | xsltInjection.py:35:17:35:28 | Attribute | a user-provided value |
|
||||
1
python/ql/test/experimental/CWE-091/Xslt.qlref
Normal file
1
python/ql/test/experimental/CWE-091/Xslt.qlref
Normal file
@@ -0,0 +1 @@
|
||||
experimental/CWE-643/Xslt.ql
|
||||
12
python/ql/test/experimental/CWE-091/XsltSinks.expected
Normal file
12
python/ql/test/experimental/CWE-091/XsltSinks.expected
Normal file
@@ -0,0 +1,12 @@
|
||||
| xslt.py:14:29:14:37 | lxml.etree.parse.xslt | lxml etree xml |
|
||||
| xsltInjection.py:12:28:12:36 | lxml.etree.XSLT | lxml etree xml |
|
||||
| xsltInjection.py:21:29:21:37 | lxml.etree.parse.xslt | lxml etree xml |
|
||||
| xsltInjection.py:31:24:31:32 | lxml.etree.parse.xslt | lxml etree xml |
|
||||
| xsltInjection.py:40:24:40:32 | lxml.etree.parse.xslt | lxml etree xml |
|
||||
| xsltInjection.py:50:24:50:32 | lxml.etree.parse.xslt | lxml etree xml |
|
||||
| xsltInjection.py:60:24:60:32 | lxml.etree.parse.xslt | lxml etree xml |
|
||||
| xsltInjection.py:69:24:69:32 | lxml.etree.parse.xslt | lxml etree xml |
|
||||
| xsltInjection.py:79:24:79:32 | lxml.etree.parse.xslt | lxml etree xml |
|
||||
| xsltSinks.py:17:28:17:36 | lxml.etree.XSLT | lxml etree xml |
|
||||
| xsltSinks.py:30:29:30:37 | lxml.etree.parse.xslt | lxml etree xml |
|
||||
| xsltSinks.py:44:24:44:32 | lxml.etree.parse.xslt | lxml etree xml |
|
||||
6
python/ql/test/experimental/CWE-091/XsltSinks.ql
Normal file
6
python/ql/test/experimental/CWE-091/XsltSinks.ql
Normal file
@@ -0,0 +1,6 @@
|
||||
import python
|
||||
import experimental.semmle.python.security.injection.XSLT
|
||||
|
||||
from XSLTInjection::XSLTInjectionSink sink, TaintKind kind
|
||||
where sink.sinks(kind)
|
||||
select sink, kind
|
||||
1
python/ql/test/experimental/CWE-091/options
Normal file
1
python/ql/test/experimental/CWE-091/options
Normal file
@@ -0,0 +1 @@
|
||||
semmle-extractor-options: -p ../../query-tests/Security/lib/ --max-import-depth=3
|
||||
14
python/ql/test/experimental/CWE-091/xslt.py
Normal file
14
python/ql/test/experimental/CWE-091/xslt.py
Normal file
@@ -0,0 +1,14 @@
|
||||
from lxml import etree
|
||||
from io import StringIO
|
||||
from flask import Flask, request
|
||||
|
||||
app = Flask(__name__)
|
||||
|
||||
|
||||
@app.route("/xslt")
|
||||
def bad():
|
||||
xsltQuery = request.args.get('xml', '')
|
||||
xslt_root = etree.XML(xsltQuery)
|
||||
f = StringIO('<foo><bar></bar></foo>')
|
||||
tree = etree.parse(f)
|
||||
result_tree = tree.xslt(xslt_root) # Not OK
|
||||
79
python/ql/test/experimental/CWE-091/xsltInjection.py
Normal file
79
python/ql/test/experimental/CWE-091/xsltInjection.py
Normal file
@@ -0,0 +1,79 @@
|
||||
from lxml import etree
|
||||
from io import StringIO
|
||||
from flask import Flask, request
|
||||
|
||||
app = Flask(__name__)
|
||||
|
||||
|
||||
@app.route("/xslt1")
|
||||
def a():
|
||||
xsltQuery = request.args.get('xml', '')
|
||||
xslt_root = etree.XML(xsltQuery)
|
||||
transform = etree.XSLT(xslt_root) # Not OK
|
||||
|
||||
|
||||
@app.route("/xslt2")
|
||||
def b():
|
||||
xsltQuery = request.args.get('xml', '')
|
||||
xslt_root = etree.XML(xsltQuery)
|
||||
f = StringIO('<foo><bar></bar></foo>')
|
||||
tree = etree.parse(f)
|
||||
result_tree = tree.xslt(xslt_root) # Not OK
|
||||
|
||||
|
||||
@app.route("/xslt3")
|
||||
def c():
|
||||
xsltQuery = request.args.get('xml', '')
|
||||
xslt_root = etree.XML(xsltQuery)
|
||||
|
||||
f = StringIO('<foo><bar></bar></foo>')
|
||||
tree = etree.parse(f)
|
||||
result = tree.xslt(xslt_root, a="'A'") # Not OK
|
||||
|
||||
@app.route("/xslt4")
|
||||
def d():
|
||||
xsltQuery = request.args.get('xml', '')
|
||||
xslt_root = etree.fromstring(xsltQuery)
|
||||
|
||||
f = StringIO('<foo><bar></bar></foo>')
|
||||
tree = etree.parse(f)
|
||||
result = tree.xslt(xslt_root, a="'A'") # Not OK
|
||||
|
||||
@app.route("/xslt5")
|
||||
def e():
|
||||
xsltQuery = request.args.get('xml', '')
|
||||
xsltStrings = [xsltQuery,"asd","random"]
|
||||
xslt_root = etree.fromstringlist(xsltStrings)
|
||||
|
||||
f = StringIO('<foo><bar></bar></foo>')
|
||||
tree = etree.parse(f)
|
||||
result = tree.xslt(xslt_root, a="'A'") # Not OK
|
||||
|
||||
|
||||
@app.route("/xslt6")
|
||||
def f():
|
||||
xsltQuery = '<non><remote><query></query></remote></non>'
|
||||
xslt_root = etree.XML(xsltQuery)
|
||||
|
||||
f = StringIO('<foo><bar></bar></foo>')
|
||||
tree = etree.parse(f)
|
||||
result = tree.xslt(xslt_root, a="'A'") # OK
|
||||
|
||||
@app.route("/xslt7")
|
||||
def g():
|
||||
xsltQuery = '<non><remote><query></query></remote></non>'
|
||||
xslt_root = etree.fromstring(xsltQuery)
|
||||
|
||||
f = StringIO('<foo><bar></bar></foo>')
|
||||
tree = etree.parse(f)
|
||||
result = tree.xslt(xslt_root, a="'A'") # OK
|
||||
|
||||
@app.route("/xslt8")
|
||||
def h():
|
||||
xsltQuery = '<non><remote><query></query></remote></non>'
|
||||
xsltStrings = [xsltQuery,"asd","random"]
|
||||
xslt_root = etree.fromstringlist(xsltStrings)
|
||||
|
||||
f = StringIO('<foo><bar></bar></foo>')
|
||||
tree = etree.parse(f)
|
||||
result = tree.xslt(xslt_root, a="'A'") # OK
|
||||
56
python/ql/test/experimental/CWE-091/xsltSinks.py
Normal file
56
python/ql/test/experimental/CWE-091/xsltSinks.py
Normal file
@@ -0,0 +1,56 @@
|
||||
from lxml import etree
|
||||
from io import StringIO
|
||||
|
||||
from django.urls import path
|
||||
from django.http import HttpResponse
|
||||
from django.template import Template, Context, Engine, engines
|
||||
|
||||
|
||||
def a(request):
|
||||
xslt_root = etree.XML('''\
|
||||
<xsl:stylesheet version="1.0"
|
||||
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
|
||||
<xsl:template match="/">
|
||||
<foo><xsl:value-of select="/a/b/text()" /></foo>
|
||||
</xsl:template>
|
||||
</xsl:stylesheet>''')
|
||||
transform = etree.XSLT(xslt_root)
|
||||
|
||||
|
||||
def b(request):
|
||||
xslt_root = etree.XML('''\
|
||||
<xsl:stylesheet version="1.0"
|
||||
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
|
||||
<xsl:template match="/">
|
||||
<foo><xsl:value-of select="/a/b/text()" /></foo>
|
||||
</xsl:template>
|
||||
</xsl:stylesheet>''')
|
||||
f = StringIO('<foo><bar></bar></foo>')
|
||||
tree = etree.parse(f)
|
||||
result_tree = tree.xslt(xslt_root)
|
||||
|
||||
|
||||
def c(request):
|
||||
xslt_root = etree.XML('''\
|
||||
<xsl:stylesheet version="1.0"
|
||||
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
|
||||
<xsl:template match="/">
|
||||
<foo><xsl:value-of select="/a/b/text()" /></foo>
|
||||
</xsl:template>
|
||||
</xsl:stylesheet>''')
|
||||
|
||||
f = StringIO('<foo><bar></bar></foo>')
|
||||
tree = etree.parse(f)
|
||||
result = tree.xslt(xslt_root, a="'A'")
|
||||
|
||||
|
||||
urlpatterns = [
|
||||
path('a', a),
|
||||
path('b', b),
|
||||
path('c', c)
|
||||
]
|
||||
|
||||
if __name__ == "__main__":
|
||||
a(None)
|
||||
b(None)
|
||||
c(None)
|
||||
Reference in New Issue
Block a user