Merge pull request #3088 from tausbn/python-prepare-autoformatting

Python: Prepare for autoformatting.
This commit is contained in:
Rasmus Wriedt Larsen
2020-03-18 17:48:46 +01:00
committed by GitHub
33 changed files with 194 additions and 193 deletions

View File

@@ -22,8 +22,8 @@ predicate multiple_calls_to_superclass_method(ClassObject self, FunctionObject m
multiple_invocation_paths(top, i1, i2, multi) and multiple_invocation_paths(top, i1, i2, multi) and
top.runtime(self.declaredAttribute(name)) and top.runtime(self.declaredAttribute(name)) and
self.getASuperType().declaredAttribute(name) = multi | self.getASuperType().declaredAttribute(name) = multi |
/* Only called twice if called from different functions, // Only called twice if called from different functions,
* or if one call-site can reach the other */ // or if one call-site can reach the other.
i1.getCall().getScope() != i2.getCall().getScope() i1.getCall().getScope() != i2.getCall().getScope()
or or
i1.getCall().strictlyReaches(i2.getCall()) i1.getCall().strictlyReaches(i2.getCall())

View File

@@ -139,10 +139,9 @@ predicate too_few_args_objectapi(Call call, Object callable, int limit) {
arg_count_objectapi(call) < limit and arg_count_objectapi(call) < limit and
exists(FunctionObject func | func = get_function_or_initializer_objectapi(callable) | exists(FunctionObject func | func = get_function_or_initializer_objectapi(callable) |
call = func.getAFunctionCall().getNode() and limit = func.minParameters() and call = func.getAFunctionCall().getNode() and limit = func.minParameters() and
/* The combination of misuse of `mox.Mox().StubOutWithMock()` // The combination of misuse of `mox.Mox().StubOutWithMock()`
* and a bug in mox's implementation of methods results in having to // and a bug in mox's implementation of methods results in having to
* pass 1 too few arguments to the mocked function. // pass 1 too few arguments to the mocked function.
*/
not (useOfMoxInModule(call.getEnclosingModule()) and func.isNormalMethod()) not (useOfMoxInModule(call.getEnclosingModule()) and func.isNormalMethod())
or or
call = func.getAMethodCall().getNode() and limit = func.minParameters() - 1 call = func.getAMethodCall().getNode() and limit = func.minParameters() - 1
@@ -160,10 +159,9 @@ predicate too_few_args(Call call, Value callable, int limit) {
arg_count(call) < limit and arg_count(call) < limit and
exists(FunctionValue func | func = get_function_or_initializer(callable) | exists(FunctionValue func | func = get_function_or_initializer(callable) |
call = func.getACall().getNode() and limit = func.minParameters() and call = func.getACall().getNode() and limit = func.minParameters() and
/* The combination of misuse of `mox.Mox().StubOutWithMock()` // The combination of misuse of `mox.Mox().StubOutWithMock()`
* and a bug in mox's implementation of methods results in having to // and a bug in mox's implementation of methods results in having to
* pass 1 too few arguments to the mocked function. // pass 1 too few arguments to the mocked function.
*/
not (useOfMoxInModule(call.getEnclosingModule()) and func.isNormalMethod()) not (useOfMoxInModule(call.getEnclosingModule()) and func.isNormalMethod())
or or
call = func.getACall().getNode() and limit = func.minParameters() - 1 call = func.getACall().getNode() and limit = func.minParameters() - 1

View File

@@ -1,7 +1,6 @@
import python import python
/** Whether `mox` or `.StubOutWithMock()` is used in thin module `m`. /** Whether `mox` or `.StubOutWithMock()` is used in thin module `m`. */
*/
predicate useOfMoxInModule(Module m) { predicate useOfMoxInModule(Module m) {
exists(ModuleObject mox | exists(ModuleObject mox |
mox.getName() = "mox" or mox.getName() = "mox3.mox" | mox.getName() = "mox" or mox.getName() = "mox3.mox" |

View File

@@ -48,8 +48,7 @@ class Symbol extends TSymbol {
) )
} }
/** Finds the `AstNode` that this `Symbol` refers to. /** Finds the `AstNode` that this `Symbol` refers to. */
*/
AstNode find() { AstNode find() {
this = TModule(result) this = TModule(result)
or or
@@ -91,8 +90,7 @@ class Symbol extends TSymbol {
) )
} }
/** Gets the `Symbol` that is the named member of this `Symbol`. /** Gets the `Symbol` that is the named member of this `Symbol`. */
*/
Symbol getMember(string name) { Symbol getMember(string name) {
result = TMember(this, name) result = TMember(this, name)
} }

View File

@@ -10,8 +10,7 @@ private newtype TDefinition =
a instanceof Expr or a instanceof Stmt or a instanceof Module a instanceof Expr or a instanceof Stmt or a instanceof Module
} }
/** A definition for the purposes of jump-to-definition. /** A definition for the purposes of jump-to-definition. */
*/
class Definition extends TLocalDefinition { class Definition extends TLocalDefinition {
@@ -159,8 +158,7 @@ private predicate delete_defn(DeletionDefinition def, Definition defn) {
none() none()
} }
/* Implicit "defn" of the names of submodules at the start of an `__init__.py` file. /* Implicit "defn" of the names of submodules at the start of an `__init__.py` file. */
*/
private predicate implicit_submodule_defn(ImplicitSubModuleDefinition def, Definition defn) { private predicate implicit_submodule_defn(ImplicitSubModuleDefinition def, Definition defn) {
exists(PackageObject package, ModuleObject mod | exists(PackageObject package, ModuleObject mod |
package.getInitModule().getModule() = def.getDefiningNode().getScope() and package.getInitModule().getModule() = def.getDefiningNode().getScope() and
@@ -170,7 +168,9 @@ private predicate implicit_submodule_defn(ImplicitSubModuleDefinition def, Defin
} }
/* Helper for scope_entry_value_transfer(...). Transfer of values from the callsite to the callee, for enclosing variables, but not arguments/parameters */ /* Helper for scope_entry_value_transfer(...).
* Transfer of values from the callsite to the callee, for enclosing variables, but not arguments/parameters
*/
private predicate scope_entry_value_transfer_at_callsite(EssaVariable pred_var, ScopeEntryDefinition succ_def) { private predicate scope_entry_value_transfer_at_callsite(EssaVariable pred_var, ScopeEntryDefinition succ_def) {
exists(CallNode callsite, FunctionObject f | exists(CallNode callsite, FunctionObject f |
f.getACall() = callsite and f.getACall() = callsite and
@@ -469,8 +469,8 @@ class NiceLocationExpr extends @py_expr {
or or
this.(Name).getLocation().hasLocationInfo(f, bl, bc, el, ec) this.(Name).getLocation().hasLocationInfo(f, bl, bc, el, ec)
or or
/* Show xxx for `xxx` in `from xxx import y` or // Show xxx for `xxx` in `from xxx import y` or
* for `import xxx` or for `import xxx as yyy`. */ // for `import xxx` or for `import xxx as yyy`.
this.(ImportExpr).getLocation().hasLocationInfo(f, bl, bc, el, ec) this.(ImportExpr).getLocation().hasLocationInfo(f, bl, bc, el, ec)
or or
/* Show y for `y` in `from xxx import y` */ /* Show y for `y` in `from xxx import y` */

View File

@@ -1,8 +1,7 @@
import python import python
/* A class representing the six comparison operators, ==, !=, <, <=, > and >=. /** A class representing the six comparison operators, ==, !=, <, <=, > and >=. */
* */
class CompareOp extends int { class CompareOp extends int {
CompareOp() { CompareOp() {

View File

@@ -356,7 +356,7 @@ class Repr extends Repr_ {
/* Constants */ /* Constants */
/** A bytes constant, such as `b'ascii'`. Note that unadorned string constants such as /** A bytes constant, such as `b'ascii'`. Note that unadorned string constants such as
`"hello"` are treated as Bytes for Python2, but Unicode for Python3. */ * `"hello"` are treated as Bytes for Python2, but Unicode for Python3. */
class Bytes extends StrConst { class Bytes extends StrConst {
/* syntax: b"hello" */ /* syntax: b"hello" */
@@ -395,8 +395,7 @@ class Ellipsis extends Ellipsis_ {
} }
/** Immutable literal expressions (except tuples). /** Immutable literal expressions (except tuples).
* Consists of string (both unicode and byte) literals * Consists of string (both unicode and byte) literals and numeric literals.
* and numeric literals.
*/ */
abstract class ImmutableLiteral extends Expr { abstract class ImmutableLiteral extends Expr {
@@ -433,8 +432,10 @@ class IntegerLiteral extends Num {
not this instanceof FloatLiteral and not this instanceof ImaginaryLiteral not this instanceof FloatLiteral and not this instanceof ImaginaryLiteral
} }
/** Gets the (integer) value of this constant. Will not return a result if the value does not fit into /**
a 32 bit signed value */ * Gets the (integer) value of this constant. Will not return a result if the value does not fit into
* a 32 bit signed value
*/
int getValue() { int getValue() {
result = this.getN().toInt() result = this.getN().toInt()
} }
@@ -540,8 +541,10 @@ class NegativeIntegerLiteral extends ImmutableLiteral, UnaryExpr {
py_cobjectnames(result, "-" + this.getOperand().(IntegerLiteral).getN()) py_cobjectnames(result, "-" + this.getOperand().(IntegerLiteral).getN())
} }
/** Gets the (integer) value of this constant. Will not return a result if the value does not fit into /**
a 32 bit signed value */ * Gets the (integer) value of this constant. Will not return a result if the value does not fit into
* a 32 bit signed value
*/
int getValue() { int getValue() {
result = -(this.getOperand().(IntegerLiteral).getValue()) result = -(this.getOperand().(IntegerLiteral).getValue())
} }
@@ -549,7 +552,8 @@ class NegativeIntegerLiteral extends ImmutableLiteral, UnaryExpr {
} }
/** A unicode string expression, such as `u"\u20ac"`. Note that unadorned string constants such as /** A unicode string expression, such as `u"\u20ac"`. Note that unadorned string constants such as
"hello" are treated as Bytes for Python2, but Unicode for Python3. */ * "hello" are treated as Bytes for Python2, but Unicode for Python3.
*/
class Unicode extends StrConst { class Unicode extends StrConst {
/* syntax: "hello" */ /* syntax: "hello" */

View File

@@ -129,8 +129,10 @@ class Folder extends Container {
} }
/** A container is an abstract representation of a file system object that can /**
hold elements of interest. */ * A container is an abstract representation of a file system object that can
* hold elements of interest.
*/
abstract class Container extends @container { abstract class Container extends @container {
Container getParent() { Container getParent() {
@@ -473,8 +475,10 @@ class Line extends @py_line {
} }
/** A syntax error. Note that if there is a syntax error in a module, /**
much information about that module will be lost */ * A syntax error. Note that if there is a syntax error in a module,
* much information about that module will be lost
*/
class SyntaxError extends Location { class SyntaxError extends Location {
SyntaxError() { SyntaxError() {
@@ -492,8 +496,10 @@ class SyntaxError extends Location {
} }
/** An encoding error. Note that if there is an encoding error in a module, /**
much information about that module will be lost */ * An encoding error. Note that if there is an encoding error in a module,
* much information about that module will be lost
*/
class EncodingError extends SyntaxError { class EncodingError extends SyntaxError {
EncodingError() { EncodingError() {

View File

@@ -235,7 +235,8 @@ class ControlFlowNode extends @py_flow_node {
PointsTo::pointsTo(this, context, value, origin) PointsTo::pointsTo(this, context, value, origin)
} }
/** Gets what this flow node might "refer-to". Performs a combination of localized (intra-procedural) points-to /**
* Gets what this flow node might "refer-to". Performs a combination of localized (intra-procedural) points-to
* analysis and global module-level analysis. This points-to analysis favours precision over recall. It is highly * analysis and global module-level analysis. This points-to analysis favours precision over recall. It is highly
* precise, but may not provide information for a significant number of flow-nodes. * precise, but may not provide information for a significant number of flow-nodes.
* If the class is unimportant then use `refersTo(value)` or `refersTo(value, origin)` instead. * If the class is unimportant then use `refersTo(value)` or `refersTo(value, origin)` instead.
@@ -245,8 +246,7 @@ class ControlFlowNode extends @py_flow_node {
this.refersTo(_, obj, cls, origin) this.refersTo(_, obj, cls, origin)
} }
/** Gets what this expression might "refer-to" in the given `context`. /** Gets what this expression might "refer-to" in the given `context`. */
*/
pragma [nomagic] pragma [nomagic]
predicate refersTo(Context context, Object obj, ClassObject cls, ControlFlowNode origin) { predicate refersTo(Context context, Object obj, ClassObject cls, ControlFlowNode origin) {
not obj = unknownValue() and not obj = unknownValue() and
@@ -329,8 +329,8 @@ class ControlFlowNode extends @py_flow_node {
exists(BasicBlock b | exists(BasicBlock b |
start_bb_likely_reachable(b) and start_bb_likely_reachable(b) and
not end_bb_likely_reachable(b) and not end_bb_likely_reachable(b) and
/* If there is an unlikely successor edge earlier in the BB // If there is an unlikely successor edge earlier in the BB
* than this node, then this node must be unreachable */ // than this node, then this node must be unreachable.
exists(ControlFlowNode p, int i, int j | exists(ControlFlowNode p, int i, int j |
p.(RaisingNode).unlikelySuccessor(_) and p.(RaisingNode).unlikelySuccessor(_) and
p = b.getNode(i) and p = b.getNode(i) and
@@ -531,7 +531,7 @@ class AttrNode extends ControlFlowNode {
} }
/** Gets the flow node corresponding to the object of the attribute expression corresponding to this flow node, /** Gets the flow node corresponding to the object of the attribute expression corresponding to this flow node,
with the matching name */ * with the matching name */
ControlFlowNode getObject(string name) { ControlFlowNode getObject(string name) {
exists(Attribute a | exists(Attribute a |
this.getNode() = a and a.getObject() = result.getNode() and this.getNode() = a and a.getObject() = result.getNode() and
@@ -555,7 +555,7 @@ class ImportMemberNode extends ControlFlowNode {
} }
/** Gets the flow node corresponding to the module in the import-member expression corresponding to this flow node, /** Gets the flow node corresponding to the module in the import-member expression corresponding to this flow node,
with the matching name*/ * with the matching name */
ControlFlowNode getModule(string name) { ControlFlowNode getModule(string name) {
exists(ImportMember i | exists(ImportMember i |
this.getNode() = i and i.getModule() = result.getNode() | this.getNode() = i and i.getModule() = result.getNode() |

View File

@@ -1,7 +1,9 @@
import python import python
/** A function, independent of defaults and binding. /**
It is the syntactic entity that is compiled to a code object. */ * A function, independent of defaults and binding.
* It is the syntactic entity that is compiled to a code object.
*/
class Function extends Function_, Scope, AstNode { class Function extends Function_, Scope, AstNode {
/** The expression defining this function */ /** The expression defining this function */
@@ -33,8 +35,10 @@ class Function extends Function_, Scope, AstNode {
name != "__init__") name != "__init__")
} }
/** Whether this function is a generator function, /**
that is whether it contains a yield or yield-from expression */ * Whether this function is a generator function,
* that is whether it contains a yield or yield-from expression
*/
predicate isGenerator() { predicate isGenerator() {
exists(Yield y | y.getScope() = this) exists(Yield y | y.getScope() = this)
or or

View File

@@ -9,37 +9,38 @@ class ConditionBlock extends BasicBlock {
/** Basic blocks controlled by this condition, i.e. those BBs for which the condition is testIsTrue */ /** Basic blocks controlled by this condition, i.e. those BBs for which the condition is testIsTrue */
predicate controls(BasicBlock controlled, boolean testIsTrue) { predicate controls(BasicBlock controlled, boolean testIsTrue) {
/* For this block to control the block 'controlled' with 'testIsTrue' the following must be true: /*
Execution must have passed through the test i.e. 'this' must strictly dominate 'controlled'. * For this block to control the block 'controlled' with 'testIsTrue' the following must be true:
Execution must have passed through the 'testIsTrue' edge leaving 'this'. * Execution must have passed through the test i.e. 'this' must strictly dominate 'controlled'.
* Execution must have passed through the 'testIsTrue' edge leaving 'this'.
Although "passed through the true edge" implies that this.getATrueSuccessor() dominates 'controlled', *
the reverse is not true, as flow may have passed through another edge to get to this.getATrueSuccessor() * Although "passed through the true edge" implies that this.getATrueSuccessor() dominates 'controlled',
so we need to assert that this.getATrueSuccessor() dominates 'controlled' *and* that * the reverse is not true, as flow may have passed through another edge to get to this.getATrueSuccessor()
all predecessors of this.getATrueSuccessor() are either this or dominated by this.getATrueSuccessor(). * so we need to assert that this.getATrueSuccessor() dominates 'controlled' *and* that
* all predecessors of this.getATrueSuccessor() are either this or dominated by this.getATrueSuccessor().
For example, in the following python snippet: *
<code> * For example, in the following python snippet:
if x: * <code>
controlled * if x:
false_successor * controlled
uncontrolled * false_successor
</code> * uncontrolled
false_successor dominates uncontrolled, but not all of its predecessors are this (if x) * </code>
or dominated by itself. Whereas in the following code: * false_successor dominates uncontrolled, but not all of its predecessors are this (if x)
<code> * or dominated by itself. Whereas in the following code:
if x: * <code>
while controlled: * if x:
also_controlled * while controlled:
false_successor * also_controlled
uncontrolled * false_successor
</code> * uncontrolled
the block 'while controlled' is controlled because all of its predecessors are this (if x) * </code>
or (in the case of 'also_controlled') dominated by itself. * the block 'while controlled' is controlled because all of its predecessors are this (if x)
* or (in the case of 'also_controlled') dominated by itself.
The additional constraint on the predecessors of the test successor implies *
that `this` strictly dominates `controlled` so that isn't necessary to check * The additional constraint on the predecessors of the test successor implies
directly. * that `this` strictly dominates `controlled` so that isn't necessary to check
* directly.
*/ */
exists(BasicBlock succ | exists(BasicBlock succ |
testIsTrue = true and succ = this.getATrueSuccessor() testIsTrue = true and succ = this.getATrueSuccessor()

View File

@@ -2,7 +2,7 @@ import python
private import semmle.python.types.Builtins private import semmle.python.types.Builtins
/** An alias in an import statement, the `mod as name` part of `import mod as name`. May be artificial; /** An alias in an import statement, the `mod as name` part of `import mod as name`. May be artificial;
`import x` is transformed into `import x as x` */ * `import x` is transformed into `import x as x` */
class Alias extends Alias_ { class Alias extends Alias_ {
Location getLocation() { Location getLocation() {
@@ -38,7 +38,7 @@ class ImportExpr extends ImportExpr_ {
} }
/** The language specifies level as -1 if relative imports are to be tried first, 0 for absolute imports, /** The language specifies level as -1 if relative imports are to be tried first, 0 for absolute imports,
and level > 0 for explicit relative imports. */ * and level > 0 for explicit relative imports. */
override int getLevel() { override int getLevel() {
exists(int l | l = super.getLevel() | exists(int l | l = super.getLevel() |
l > 0 and result = l l > 0 and result = l

View File

@@ -4,7 +4,7 @@ import python
class FunctionMetrics extends Function { class FunctionMetrics extends Function {
/** Gets the total number of lines (including blank lines) /** Gets the total number of lines (including blank lines)
from the definition to the end of the function */ * from the definition to the end of the function */
int getNumberOfLines() { int getNumberOfLines() {
py_alllines(this, result) py_alllines(this, result)
} }
@@ -53,8 +53,8 @@ class FunctionMetrics extends Function {
} }
/** Dependency of Callables /** Dependency of Callables
One callable "this" depends on another callable "result" * One callable "this" depends on another callable "result"
if "this" makes some call to a method that may end up being "result". * if "this" makes some call to a method that may end up being "result".
*/ */
FunctionMetrics getADependency() { FunctionMetrics getADependency() {
result != this and result != this and
@@ -78,16 +78,16 @@ class FunctionMetrics extends Function {
} }
/** Afferent Coupling /** Afferent Coupling
the number of callables that depend on this method. * the number of callables that depend on this method.
This is sometimes called the "fan-in" of a method. * This is sometimes called the "fan-in" of a method.
*/ */
int getAfferentCoupling() { int getAfferentCoupling() {
result = count(FunctionMetrics m | m.getADependency() = this ) result = count(FunctionMetrics m | m.getADependency() = this )
} }
/** Efferent Coupling /** Efferent Coupling
the number of methods that this method depends on * the number of methods that this method depends on
This is sometimes called the "fan-out" of a method. * This is sometimes called the "fan-out" of a method.
*/ */
int getEfferentCoupling() { int getEfferentCoupling() {
result = count(FunctionMetrics m | this.getADependency() = m) result = count(FunctionMetrics m | this.getADependency() = m)
@@ -112,7 +112,7 @@ class FunctionMetrics extends Function {
class ClassMetrics extends Class { class ClassMetrics extends Class {
/** Gets the total number of lines (including blank lines) /** Gets the total number of lines (including blank lines)
from the definition to the end of the class */ * from the definition to the end of the class */
int getNumberOfLines() { int getNumberOfLines() {
py_alllines(this, result) py_alllines(this, result)
} }
@@ -172,19 +172,18 @@ class ClassMetrics extends Class {
/* -------- CHIDAMBER AND KEMERER LACK OF COHESION IN METHODS ------------ */ /* -------- CHIDAMBER AND KEMERER LACK OF COHESION IN METHODS ------------ */
/* The aim of this metric is to try and determine whether a class /* The aim of this metric is to try and determine whether a class
represents one abstraction (good) or multiple abstractions (bad). * represents one abstraction (good) or multiple abstractions (bad).
If a class represents multiple abstractions, it should be split * If a class represents multiple abstractions, it should be split
up into multiple classes. * up into multiple classes.
*
In the Chidamber and Kemerer method, this is measured as follows: * In the Chidamber and Kemerer method, this is measured as follows:
n1 = number of pairs of distinct methods in a class that do *not* * n1 = number of pairs of distinct methods in a class that do *not*
have at least one commonly accessed field * have at least one commonly accessed field
n2 = number of pairs of distinct methods in a class that do * n2 = number of pairs of distinct methods in a class that do
have at least one commonly accessed field * have at least one commonly accessed field
lcom = ((n1 - n2)/2 max 0) * lcom = ((n1 - n2)/2 max 0)
*
We divide by 2 because each pair (m1,m2) is counted twice in n1 and n2. * We divide by 2 because each pair (m1,m2) is counted twice in n1 and n2.
*/ */
/** should function f be excluded from the cohesion computation? */ /** should function f be excluded from the cohesion computation? */

View File

@@ -41,10 +41,9 @@ class SelfAttributeRead extends SelfAttribute {
SelfAttributeRead() { SelfAttributeRead() {
this.getCtx() instanceof Load and this.getCtx() instanceof Load and
/* Be stricter for loads. // Be stricter for loads.
* We want to generous as to what is defined (ie stores), // We want to generous as to what is defined (i.e. stores),
* but strict as to what needs to be defined (ie loads). // but strict as to what needs to be defined (i.e. loads).
*/
exists(ClassObject cls, FunctionObject func | exists(ClassObject cls, FunctionObject func |
cls.declaredAttribute(_) = func | cls.declaredAttribute(_) = func |
func.getFunction() = this.getScope() and func.getFunction() = this.getScope() and

View File

@@ -471,8 +471,7 @@ class EssaNodeDefinition extends EssaDefinition, TEssaNodeDefinition {
} }
/** A definition of an ESSA variable that takes another ESSA variable as an input. /** A definition of an ESSA variable that takes another ESSA variable as an input. */
*/
class EssaNodeRefinement extends EssaDefinition, TEssaNodeRefinement { class EssaNodeRefinement extends EssaDefinition, TEssaNodeRefinement {
override string toString() { override string toString() {

View File

@@ -232,8 +232,7 @@ class BuiltinFunctionObjectInternal extends CallableObjectInternal, TBuiltinFunc
Builtin getReturnType() { Builtin getReturnType() {
exists(Builtin func | exists(Builtin func |
func = this.getBuiltin() | func = this.getBuiltin() |
/* Enumerate the types of a few builtin functions, that the CPython analysis misses. /* Enumerate the types of a few builtin functions, that the CPython analysis misses. */
*/
func = Builtin::builtin("hex") and result = Builtin::special("str") func = Builtin::builtin("hex") and result = Builtin::special("str")
or or
func = Builtin::builtin("oct") and result = Builtin::special("str") func = Builtin::builtin("oct") and result = Builtin::special("str")
@@ -294,8 +293,7 @@ class BuiltinFunctionObjectInternal extends CallableObjectInternal, TBuiltinFunc
} }
/** Class representing methods of built-in classes (otherwise known as method-descriptors) such as `list.append`. /** Class representing methods of built-in classes (otherwise known as method-descriptors) such as `list.append`. */
*/
class BuiltinMethodObjectInternal extends CallableObjectInternal, TBuiltinMethodObject { class BuiltinMethodObjectInternal extends CallableObjectInternal, TBuiltinMethodObject {
override Builtin getBuiltin() { override Builtin getBuiltin() {

View File

@@ -542,13 +542,13 @@ class ClassValue extends Value {
} }
/** Holds if this class is a new style class. /** Holds if this class is a new style class.
A new style class is one that implicitly or explicitly inherits from `object`. */ * A new style class is one that implicitly or explicitly inherits from `object`. */
predicate isNewStyle() { predicate isNewStyle() {
Types::isNewStyle(this) Types::isNewStyle(this)
} }
/** Holds if this class is an old style class. /** Holds if this class is an old style class.
An old style class is one that does not inherit from `object`. */ * An old style class is one that does not inherit from `object`. */
predicate isOldStyle() { predicate isOldStyle() {
Types::isOldStyle(this) Types::isOldStyle(this)
} }
@@ -742,7 +742,7 @@ class TupleValue extends SequenceValue {
} }
/** A class representing strings, either present in the source as a literal, or /** A class representing strings, either present in the source as a literal, or
in a builtin as a value. */ * in a builtin as a value. */
class StringValue extends Value { class StringValue extends Value {
StringValue() { StringValue() {
@@ -918,7 +918,7 @@ module ClassValue {
} }
/** Get the `ClassValue` for the `str` class. This is `bytes` in Python 2, /** Get the `ClassValue` for the `str` class. This is `bytes` in Python 2,
and `str` in Python 3. */ * and `str` in Python 3. */
ClassValue str() { ClassValue str() {
if major_version() = 2 then if major_version() = 2 then
result = bytes() result = bytes()

View File

@@ -1,4 +1,4 @@
/** /*
* *
* ## Points-to analysis for Python * ## Points-to analysis for Python
* *

View File

@@ -3,8 +3,7 @@ private import Common
import semmle.python.security.TaintTracking import semmle.python.security.TaintTracking
/** An extensible kind of taint representing any kind of string. /** An extensible kind of taint representing any kind of string. */
*/
abstract class StringKind extends TaintKind { abstract class StringKind extends TaintKind {
bindingset[this] bindingset[this]

View File

@@ -73,13 +73,13 @@ class ClassObject extends Object {
} }
/** Whether this class is a new style class. /** Whether this class is a new style class.
A new style class is one that implicitly or explicitly inherits from `object`. */ * A new style class is one that implicitly or explicitly inherits from `object`. */
predicate isNewStyle() { predicate isNewStyle() {
Types::isNewStyle(theClass()) Types::isNewStyle(theClass())
} }
/** Whether this class is an old style class. /** Whether this class is an old style class.
An old style class is one that does not inherit from `object`. */ * An old style class is one that does not inherit from `object`. */
predicate isOldStyle() { predicate isOldStyle() {
Types::isOldStyle(theClass()) Types::isOldStyle(theClass())
} }
@@ -112,7 +112,7 @@ class ClassObject extends Object {
} }
/** Returns an attribute as it would be when looked up at runtime on this class. /** Returns an attribute as it would be when looked up at runtime on this class.
Will include attributes of super-classes */ * Will include attributes of super-classes */
Object lookupAttribute(string name) { Object lookupAttribute(string name) {
exists(ObjectInternal val | exists(ObjectInternal val |
theClass().lookup(name, val, _) and theClass().lookup(name, val, _) and
@@ -155,7 +155,7 @@ class ClassObject extends Object {
} }
/** Whether it is impossible to know all the attributes of this class. Usually because it is /** Whether it is impossible to know all the attributes of this class. Usually because it is
impossible to calculate the full class hierarchy or because some attribute is too dynamic. */ * impossible to calculate the full class hierarchy or because some attribute is too dynamic. */
predicate unknowableAttributes() { predicate unknowableAttributes() {
/* True for a class with undeterminable superclasses, unanalysable metaclasses, or other confusions */ /* True for a class with undeterminable superclasses, unanalysable metaclasses, or other confusions */
this.failedInference() this.failedInference()

View File

@@ -35,7 +35,7 @@ class RaisingNode extends ControlFlowNode {
} }
/** Gets the type of an exception that may be raised /** Gets the type of an exception that may be raised
at this control flow node */ * at this control flow node */
ClassObject getARaisedType() { ClassObject getARaisedType() {
result = this.localRaisedType() result = this.localRaisedType()
or or
@@ -118,8 +118,7 @@ class RaisingNode extends ControlFlowNode {
) )
} }
/** Whether (as inferred by type inference) it is highly unlikely (or impossible) for control to flow from this to succ. /** Whether (as inferred by type inference) it is highly unlikely (or impossible) for control to flow from this to succ. */
*/
predicate unlikelySuccessor(ControlFlowNode succ) { predicate unlikelySuccessor(ControlFlowNode succ) {
succ = this.getAnExceptionalSuccessor() and succ = this.getAnExceptionalSuccessor() and
not this.viableExceptionEdge(succ, _) and not this.viableExceptionEdge(succ, _) and

View File

@@ -70,21 +70,20 @@ abstract class FunctionObject extends Object {
} }
/** Gets the `ControlFlowNode` that will be passed as the nth argument to `this` when called at `call`. /** Gets the `ControlFlowNode` that will be passed as the nth argument to `this` when called at `call`.
This predicate will correctly handle `x.y()`, treating `x` as the zeroth argument. * This predicate will correctly handle `x.y()`, treating `x` as the zeroth argument.
*/ */
ControlFlowNode getArgumentForCall(CallNode call, int n) { ControlFlowNode getArgumentForCall(CallNode call, int n) {
result = theCallable().getArgumentForCall(call, n) result = theCallable().getArgumentForCall(call, n)
} }
/** Gets the `ControlFlowNode` that will be passed as the named argument to `this` when called at `call`. /** Gets the `ControlFlowNode` that will be passed as the named argument to `this` when called at `call`.
This predicate will correctly handle `x.y()`, treating `x` as the self argument. * This predicate will correctly handle `x.y()`, treating `x` as the self argument.
*/ */
ControlFlowNode getNamedArgumentForCall(CallNode call, string name) { ControlFlowNode getNamedArgumentForCall(CallNode call, string name) {
result = theCallable().getNamedArgumentForCall(call, name) result = theCallable().getNamedArgumentForCall(call, name)
} }
/** Whether this function never returns. This is an approximation. /** Whether this function never returns. This is an approximation. */
*/
predicate neverReturns() { predicate neverReturns() {
theCallable().neverReturns() theCallable().neverReturns()
} }

View File

@@ -79,7 +79,7 @@ abstract class ModuleObject extends Object {
} }
/** Whether this module "exports" `name`. That is, whether using `import *` on this module /** Whether this module "exports" `name`. That is, whether using `import *` on this module
will result in `name` being added to the namespace. */ * will result in `name` being added to the namespace. */
predicate exports(string name) { predicate exports(string name) {
theModule().exports(name) theModule().exports(name)
} }

View File

@@ -44,8 +44,8 @@ class Object extends @py_object {
this = unknownValue() and result = theUnknownType() this = unknownValue() and result = theUnknownType()
} }
/** Whether this a builtin object. A builtin object is one defined by the implementation, /** Whether this is a builtin object. A builtin object is one defined by the implementation,
such as the integer 4 or by a native extension, such as a NumPy array class. */ * such as the integer 4 or by a native extension, such as a NumPy array class. */
predicate isBuiltin() { predicate isBuiltin() {
exists(this.asBuiltin()) exists(this.asBuiltin())
} }