mirror of
https://github.com/github/codeql.git
synced 2025-12-16 16:53:25 +01:00
Merge pull request #20739 from github/tausbn/python-remove-top-level-points-to-imports
Python: Hide points-to imports in `python.qll`
This commit is contained in:
@@ -7,6 +7,7 @@
|
||||
*/
|
||||
|
||||
import python
|
||||
private import LegacyPointsTo
|
||||
|
||||
from Value len, CallNode call
|
||||
where len.getName() = "len" and len.getACall() = call
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
*/
|
||||
|
||||
import python
|
||||
private import LegacyPointsTo
|
||||
|
||||
from ClassObject sub, ClassObject base
|
||||
where
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
*/
|
||||
|
||||
import python
|
||||
private import LegacyPointsTo
|
||||
|
||||
from AstNode call, PythonFunctionValue method
|
||||
where
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
*/
|
||||
|
||||
import python
|
||||
private import LegacyPointsTo
|
||||
|
||||
from FunctionObject m, FunctionObject n
|
||||
where m != n and m.getACallee() = n and n.getACallee() = m
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
*/
|
||||
|
||||
import python
|
||||
private import LegacyPointsTo
|
||||
|
||||
from FunctionObject override, FunctionObject base
|
||||
where
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
*/
|
||||
|
||||
import python
|
||||
private import LegacyPointsTo
|
||||
|
||||
from PythonFunctionValue f
|
||||
where f.getACall().getScope() = f.getScope()
|
||||
|
||||
@@ -20,8 +20,21 @@
|
||||
*/
|
||||
|
||||
private import python
|
||||
private import semmle.python.pointsto.PointsTo
|
||||
private import semmle.python.objects.Modules
|
||||
import semmle.python.pointsto.Base
|
||||
import semmle.python.pointsto.Context
|
||||
import semmle.python.pointsto.PointsTo
|
||||
import semmle.python.pointsto.PointsToContext
|
||||
import semmle.python.objects.ObjectAPI
|
||||
import semmle.python.objects.ObjectInternal
|
||||
import semmle.python.types.Object
|
||||
import semmle.python.types.ClassObject
|
||||
import semmle.python.types.FunctionObject
|
||||
import semmle.python.types.ModuleObject
|
||||
import semmle.python.types.Exceptions
|
||||
import semmle.python.types.Properties
|
||||
import semmle.python.types.Descriptors
|
||||
import semmle.python.SelfAttribute
|
||||
import semmle.python.Metrics
|
||||
|
||||
/**
|
||||
* An extension of `ControlFlowNode` that provides points-to predicates.
|
||||
@@ -93,6 +106,24 @@ class ControlFlowNodeWithPointsTo extends ControlFlowNode {
|
||||
// for that variable.
|
||||
exists(SsaVariable v | v.getAUse() = this | varHasCompletePointsToSet(v))
|
||||
}
|
||||
|
||||
/** Whether it is unlikely that this ControlFlowNode can be reached */
|
||||
predicate unlikelyReachable() {
|
||||
not start_bb_likely_reachable(this.getBasicBlock())
|
||||
or
|
||||
exists(BasicBlock b |
|
||||
start_bb_likely_reachable(b) and
|
||||
not end_bb_likely_reachable(b) and
|
||||
// If there is an unlikely successor edge earlier in the BB
|
||||
// than this node, then this node must be unreachable.
|
||||
exists(ControlFlowNode p, int i, int j |
|
||||
p.(RaisingNode).unlikelySuccessor(_) and
|
||||
p = b.getNode(i) and
|
||||
this = b.getNode(j) and
|
||||
i < j
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -121,6 +152,45 @@ private predicate varHasCompletePointsToSet(SsaVariable var) {
|
||||
)
|
||||
}
|
||||
|
||||
private predicate start_bb_likely_reachable(BasicBlock b) {
|
||||
exists(Scope s | s.getEntryNode() = b.getNode(_))
|
||||
or
|
||||
exists(BasicBlock pred |
|
||||
pred = b.getAPredecessor() and
|
||||
end_bb_likely_reachable(pred) and
|
||||
not pred.getLastNode().(RaisingNode).unlikelySuccessor(b)
|
||||
)
|
||||
}
|
||||
|
||||
private predicate end_bb_likely_reachable(BasicBlock b) {
|
||||
start_bb_likely_reachable(b) and
|
||||
not exists(ControlFlowNode p, ControlFlowNode s |
|
||||
p.(RaisingNode).unlikelySuccessor(s) and
|
||||
p = b.getNode(_) and
|
||||
s = b.getNode(_) and
|
||||
not p = b.getLastNode()
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* An extension of `BasicBlock` that provides points-to related methods.
|
||||
*/
|
||||
class BasicBlockWithPointsTo extends BasicBlock {
|
||||
/**
|
||||
* Whether (as inferred by type inference) it is highly unlikely (or impossible) for control to flow from this to succ.
|
||||
*/
|
||||
predicate unlikelySuccessor(BasicBlockWithPointsTo succ) {
|
||||
this.getLastNode().(RaisingNode).unlikelySuccessor(succ.firstNode())
|
||||
or
|
||||
not end_bb_likely_reachable(this) and succ = this.getASuccessor()
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether (as inferred by type inference) this basic block is likely to be reachable.
|
||||
*/
|
||||
predicate likelyReachable() { start_bb_likely_reachable(this) }
|
||||
}
|
||||
|
||||
/**
|
||||
* An extension of `Expr` that provides points-to predicates.
|
||||
*/
|
||||
@@ -208,3 +278,155 @@ class ModuleWithPointsTo extends Module {
|
||||
|
||||
override string getAQlClass() { none() }
|
||||
}
|
||||
|
||||
/**
|
||||
* An extension of `Function` that provides points-to related methods.
|
||||
*/
|
||||
class FunctionWithPointsTo extends Function {
|
||||
/** Gets the FunctionObject corresponding to this function */
|
||||
FunctionObject getFunctionObject() { result.getOrigin() = this.getDefinition() }
|
||||
|
||||
override string getAQlClass() { none() }
|
||||
}
|
||||
|
||||
/**
|
||||
* An extension of `Class` that provides points-to related methods.
|
||||
*/
|
||||
class ClassWithPointsTo extends Class {
|
||||
/** Gets the ClassObject corresponding to this class */
|
||||
ClassObject getClassObject() { result.getOrigin() = this.getParent() }
|
||||
|
||||
override string getAQlClass() { none() }
|
||||
}
|
||||
|
||||
/** Gets the `Object` corresponding to the immutable literal `l`. */
|
||||
Object getLiteralObject(ImmutableLiteral l) {
|
||||
l instanceof IntegerLiteral and
|
||||
(
|
||||
py_cobjecttypes(result, theIntType()) and py_cobjectnames(result, l.(Num).getN())
|
||||
or
|
||||
py_cobjecttypes(result, theLongType()) and py_cobjectnames(result, l.(Num).getN())
|
||||
)
|
||||
or
|
||||
l instanceof FloatLiteral and
|
||||
py_cobjecttypes(result, theFloatType()) and
|
||||
py_cobjectnames(result, l.(Num).getN())
|
||||
or
|
||||
l instanceof ImaginaryLiteral and
|
||||
py_cobjecttypes(result, theComplexType()) and
|
||||
py_cobjectnames(result, l.(Num).getN())
|
||||
or
|
||||
l instanceof NegativeIntegerLiteral and
|
||||
(
|
||||
(py_cobjecttypes(result, theIntType()) or py_cobjecttypes(result, theLongType())) and
|
||||
py_cobjectnames(result, "-" + l.(UnaryExpr).getOperand().(IntegerLiteral).getN())
|
||||
)
|
||||
or
|
||||
l instanceof Bytes and
|
||||
py_cobjecttypes(result, theBytesType()) and
|
||||
py_cobjectnames(result, l.(Bytes).quotedString())
|
||||
or
|
||||
l instanceof Unicode and
|
||||
py_cobjecttypes(result, theUnicodeType()) and
|
||||
py_cobjectnames(result, l.(Unicode).quotedString())
|
||||
or
|
||||
l instanceof True and
|
||||
name_consts(l, "True") and
|
||||
result = theTrueObject()
|
||||
or
|
||||
l instanceof False and
|
||||
name_consts(l, "False") and
|
||||
result = theFalseObject()
|
||||
or
|
||||
l instanceof None and
|
||||
name_consts(l, "None") and
|
||||
result = theNoneObject()
|
||||
}
|
||||
|
||||
private predicate gettext_installed() {
|
||||
// Good enough (and fast) approximation
|
||||
exists(Module m | m.getName() = "gettext")
|
||||
}
|
||||
|
||||
private predicate builtin_constant(string name) {
|
||||
exists(Object::builtin(name))
|
||||
or
|
||||
name = "WindowsError"
|
||||
or
|
||||
name = "_" and gettext_installed()
|
||||
}
|
||||
|
||||
/** Whether this name is (almost) always defined, ie. it is a builtin or VM defined name */
|
||||
predicate globallyDefinedName(string name) { builtin_constant(name) or auto_name(name) }
|
||||
|
||||
private predicate auto_name(string name) {
|
||||
name = "__file__" or name = "__builtins__" or name = "__name__"
|
||||
}
|
||||
|
||||
/** An extension of `SsaVariable` that provides points-to related methods. */
|
||||
class SsaVariableWithPointsTo extends SsaVariable {
|
||||
/** Gets an argument of the phi function defining this variable, pruned of unlikely edges. */
|
||||
SsaVariable getAPrunedPhiInput() {
|
||||
result = this.getAPhiInput() and
|
||||
exists(BasicBlock incoming | incoming = this.getPredecessorBlockForPhiArgument(result) |
|
||||
not incoming.getLastNode().(RaisingNode).unlikelySuccessor(this.getDefinition())
|
||||
)
|
||||
}
|
||||
|
||||
/** Gets the incoming edges for a Phi node, pruned of unlikely edges. */
|
||||
private BasicBlockWithPointsTo getAPrunedPredecessorBlockForPhi() {
|
||||
result = this.getAPredecessorBlockForPhi() and
|
||||
not result.unlikelySuccessor(this.getDefinition().getBasicBlock())
|
||||
}
|
||||
|
||||
private predicate implicitlyDefined() {
|
||||
not exists(this.getDefinition()) and
|
||||
not py_ssa_phi(this, _) and
|
||||
exists(GlobalVariable var | this.getVariable() = var |
|
||||
globallyDefinedName(var.getId())
|
||||
or
|
||||
var.getId() = "__path__" and var.getScope().(Module).isPackageInit()
|
||||
)
|
||||
}
|
||||
|
||||
/** Whether this variable may be undefined */
|
||||
predicate maybeUndefined() {
|
||||
not exists(this.getDefinition()) and not py_ssa_phi(this, _) and not this.implicitlyDefined()
|
||||
or
|
||||
this.getDefinition().isDelete()
|
||||
or
|
||||
exists(SsaVariableWithPointsTo var | var = this.getAPrunedPhiInput() | var.maybeUndefined())
|
||||
or
|
||||
/*
|
||||
* For phi-nodes, there must be a corresponding phi-input for each control-flow
|
||||
* predecessor. Otherwise, the variable will be undefined on that incoming edge.
|
||||
* WARNING: the same phi-input may cover multiple predecessors, so this check
|
||||
* cannot be done by counting.
|
||||
*/
|
||||
|
||||
exists(BasicBlock incoming |
|
||||
reaches_end(incoming) and
|
||||
incoming = this.getAPrunedPredecessorBlockForPhi() and
|
||||
not this.getAPhiInput().getDefinition().getBasicBlock().dominates(incoming)
|
||||
)
|
||||
}
|
||||
|
||||
override string getAQlClass() { none() }
|
||||
}
|
||||
|
||||
private predicate reaches_end(BasicBlock b) {
|
||||
not exits_early(b) and
|
||||
(
|
||||
/* Entry point */
|
||||
not exists(BasicBlock prev | prev.getASuccessor() = b)
|
||||
or
|
||||
exists(BasicBlock prev | prev.getASuccessor() = b | reaches_end(prev))
|
||||
)
|
||||
}
|
||||
|
||||
private predicate exits_early(BasicBlock b) {
|
||||
exists(FunctionObject f |
|
||||
f.neverReturns() and
|
||||
f.getACall().getBasicBlock() = b
|
||||
)
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
import python
|
||||
private import LegacyPointsTo
|
||||
import semmle.python.pointsto.PointsTo
|
||||
private import semmle.python.types.ImportTime
|
||||
import IDEContextual
|
||||
|
||||
private newtype TDefinition =
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
---
|
||||
category: breaking
|
||||
---
|
||||
|
||||
* All modules that depend on the points-to analysis have now been removed from the top level `python.qll` module. To access the points-to functionality, import the new `LegacyPointsTo` module. This also means that some predicates have been removed from various classes, for instance `Function.getFunctionObject()`. To access these predicates, import the `LegacyPointsTo` module and use the `FunctionWithPointsTo` class instead. Most cases follow this pattern, but there are a few exceptions:
|
||||
* The `getLiteralObject` method on `ImmutableLiteral` subclasses has been replaced with a predicate `getLiteralObject(ImmutableLiteral l)` in the `LegacyPointsTo` module.
|
||||
* The `getMetrics` method on `Function`, `Class`, and `Module` has been removed. To access metrics, import `LegacyPointsTo` and use the classes `FunctionMetrics`, etc. instead.
|
||||
@@ -14,27 +14,27 @@ import semmle.python.Patterns
|
||||
import semmle.python.Keywords
|
||||
import semmle.python.Comprehensions
|
||||
import semmle.python.Flow
|
||||
import semmle.python.Metrics
|
||||
private import semmle.python.Metrics
|
||||
import semmle.python.Constants
|
||||
import semmle.python.Scope
|
||||
import semmle.python.Comment
|
||||
import semmle.python.GuardedControlFlow
|
||||
import semmle.python.types.ImportTime
|
||||
import semmle.python.types.Object
|
||||
import semmle.python.types.ClassObject
|
||||
import semmle.python.types.FunctionObject
|
||||
import semmle.python.types.ModuleObject
|
||||
import semmle.python.types.Version
|
||||
import semmle.python.types.Descriptors
|
||||
private import semmle.python.types.ImportTime
|
||||
private import semmle.python.types.Object
|
||||
private import semmle.python.types.ClassObject
|
||||
private import semmle.python.types.FunctionObject
|
||||
private import semmle.python.types.ModuleObject
|
||||
private import semmle.python.types.Version
|
||||
private import semmle.python.types.Descriptors
|
||||
import semmle.python.SSA
|
||||
import semmle.python.SelfAttribute
|
||||
import semmle.python.types.Properties
|
||||
private import semmle.python.SelfAttribute
|
||||
private import semmle.python.types.Properties
|
||||
import semmle.python.xml.XML
|
||||
import semmle.python.essa.Essa
|
||||
import semmle.python.pointsto.Base
|
||||
import semmle.python.pointsto.Context
|
||||
import semmle.python.pointsto.CallGraph
|
||||
import semmle.python.objects.ObjectAPI
|
||||
private import semmle.python.pointsto.Base
|
||||
private import semmle.python.pointsto.Context
|
||||
private import semmle.python.pointsto.CallGraph
|
||||
private import semmle.python.objects.ObjectAPI
|
||||
import semmle.python.Unit
|
||||
import site
|
||||
private import semmle.python.Overlay
|
||||
|
||||
@@ -141,18 +141,12 @@ class Class extends Class_, Scope, AstNode {
|
||||
/** Gets the metaclass expression */
|
||||
Expr getMetaClass() { result = this.getParent().getMetaClass() }
|
||||
|
||||
/** Gets the ClassObject corresponding to this class */
|
||||
ClassObject getClassObject() { result.getOrigin() = this.getParent() }
|
||||
|
||||
/** Gets the nth base of this class definition. */
|
||||
Expr getBase(int index) { result = this.getParent().getBase(index) }
|
||||
|
||||
/** Gets a base of this class definition. */
|
||||
Expr getABase() { result = this.getParent().getABase() }
|
||||
|
||||
/** Gets the metrics for this class */
|
||||
ClassMetrics getMetrics() { result = this }
|
||||
|
||||
/**
|
||||
* Gets the qualified name for this class.
|
||||
* Should return the same name as the `__qualname__` attribute on classes in Python 3.
|
||||
|
||||
@@ -240,17 +240,12 @@ class Bytes extends StringLiteral {
|
||||
/* syntax: b"hello" */
|
||||
Bytes() { not this.isUnicode() }
|
||||
|
||||
override Object getLiteralObject() {
|
||||
py_cobjecttypes(result, theBytesType()) and
|
||||
py_cobjectnames(result, this.quotedString())
|
||||
}
|
||||
|
||||
/**
|
||||
* The extractor puts quotes into the name of each string (to prevent "0" clashing with 0).
|
||||
* The following predicate help us match up a string/byte literals in the source
|
||||
* which the equivalent object.
|
||||
*/
|
||||
private string quotedString() {
|
||||
string quotedString() {
|
||||
exists(string b_unquoted | b_unquoted = this.getS() | result = "b'" + b_unquoted + "'")
|
||||
}
|
||||
}
|
||||
@@ -266,8 +261,6 @@ class Ellipsis extends Ellipsis_ {
|
||||
* Consists of string (both unicode and byte) literals and numeric literals.
|
||||
*/
|
||||
abstract class ImmutableLiteral extends Expr {
|
||||
abstract Object getLiteralObject();
|
||||
|
||||
abstract boolean booleanValue();
|
||||
}
|
||||
|
||||
@@ -292,12 +285,6 @@ class IntegerLiteral extends Num {
|
||||
|
||||
override string toString() { result = "IntegerLiteral" }
|
||||
|
||||
override Object getLiteralObject() {
|
||||
py_cobjecttypes(result, theIntType()) and py_cobjectnames(result, this.getN())
|
||||
or
|
||||
py_cobjecttypes(result, theLongType()) and py_cobjectnames(result, this.getN())
|
||||
}
|
||||
|
||||
override boolean booleanValue() {
|
||||
this.getValue() = 0 and result = false
|
||||
or
|
||||
@@ -317,10 +304,6 @@ class FloatLiteral extends Num {
|
||||
|
||||
override string toString() { result = "FloatLiteral" }
|
||||
|
||||
override Object getLiteralObject() {
|
||||
py_cobjecttypes(result, theFloatType()) and py_cobjectnames(result, this.getN())
|
||||
}
|
||||
|
||||
override boolean booleanValue() {
|
||||
this.getValue() = 0.0 and result = false
|
||||
or
|
||||
@@ -343,10 +326,6 @@ class ImaginaryLiteral extends Num {
|
||||
|
||||
override string toString() { result = "ImaginaryLiteral" }
|
||||
|
||||
override Object getLiteralObject() {
|
||||
py_cobjecttypes(result, theComplexType()) and py_cobjectnames(result, this.getN())
|
||||
}
|
||||
|
||||
override boolean booleanValue() {
|
||||
this.getValue() = 0.0 and result = false
|
||||
or
|
||||
@@ -365,11 +344,6 @@ class NegativeIntegerLiteral extends ImmutableLiteral, UnaryExpr {
|
||||
|
||||
override boolean booleanValue() { result = this.getOperand().(IntegerLiteral).booleanValue() }
|
||||
|
||||
override Object getLiteralObject() {
|
||||
(py_cobjecttypes(result, theIntType()) or py_cobjecttypes(result, theLongType())) and
|
||||
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
|
||||
@@ -385,11 +359,6 @@ class Unicode extends StringLiteral {
|
||||
/* syntax: "hello" */
|
||||
Unicode() { this.isUnicode() }
|
||||
|
||||
override Object getLiteralObject() {
|
||||
py_cobjecttypes(result, theUnicodeType()) and
|
||||
py_cobjectnames(result, this.quotedString())
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the quoted representation fo this string.
|
||||
*
|
||||
@@ -593,12 +562,11 @@ class StringLiteral extends Str_, ImmutableLiteral {
|
||||
this.getText() != "" and result = true
|
||||
}
|
||||
|
||||
override Object getLiteralObject() { none() }
|
||||
|
||||
override string toString() { result = "StringLiteral" }
|
||||
}
|
||||
|
||||
private predicate name_consts(Name_ n, string id) {
|
||||
/** Holds if `n` is a named constant (`True`, `False`, or `None`) with name `id`. */
|
||||
predicate name_consts(Name_ n, string id) {
|
||||
exists(Variable v | py_variables(v, n) and id = v.getId() |
|
||||
id = "True" or id = "False" or id = "None"
|
||||
)
|
||||
@@ -627,8 +595,6 @@ class True extends BooleanLiteral {
|
||||
/* syntax: True */
|
||||
True() { name_consts(this, "True") }
|
||||
|
||||
override Object getLiteralObject() { name_consts(this, "True") and result = theTrueObject() }
|
||||
|
||||
override boolean booleanValue() { result = true }
|
||||
}
|
||||
|
||||
@@ -637,8 +603,6 @@ class False extends BooleanLiteral {
|
||||
/* syntax: False */
|
||||
False() { name_consts(this, "False") }
|
||||
|
||||
override Object getLiteralObject() { name_consts(this, "False") and result = theFalseObject() }
|
||||
|
||||
override boolean booleanValue() { result = false }
|
||||
}
|
||||
|
||||
@@ -647,8 +611,6 @@ class None extends NameConstant {
|
||||
/* syntax: None */
|
||||
None() { name_consts(this, "None") }
|
||||
|
||||
override Object getLiteralObject() { name_consts(this, "None") and result = theNoneObject() }
|
||||
|
||||
override boolean booleanValue() { result = false }
|
||||
}
|
||||
|
||||
|
||||
@@ -190,24 +190,6 @@ class ControlFlowNode extends @py_flow_node {
|
||||
/** Whether this node is a normal (non-exceptional) exit */
|
||||
predicate isNormalExit() { py_scope_flow(this, _, 0) or py_scope_flow(this, _, 2) }
|
||||
|
||||
/** Whether it is unlikely that this ControlFlowNode can be reached */
|
||||
predicate unlikelyReachable() {
|
||||
not start_bb_likely_reachable(this.getBasicBlock())
|
||||
or
|
||||
exists(BasicBlock b |
|
||||
start_bb_likely_reachable(b) and
|
||||
not end_bb_likely_reachable(b) and
|
||||
// If there is an unlikely successor edge earlier in the BB
|
||||
// than this node, then this node must be unreachable.
|
||||
exists(ControlFlowNode p, int i, int j |
|
||||
p.(RaisingNode).unlikelySuccessor(_) and
|
||||
p = b.getNode(i) and
|
||||
this = b.getNode(j) and
|
||||
i < j
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
/** Whether this strictly dominates other. */
|
||||
pragma[inline]
|
||||
predicate strictlyDominates(ControlFlowNode other) {
|
||||
@@ -901,6 +883,58 @@ class StarredNode extends ControlFlowNode {
|
||||
ControlFlowNode getValue() { toAst(result) = toAst(this).(Starred).getValue() }
|
||||
}
|
||||
|
||||
/** The ControlFlowNode for an 'except' statement. */
|
||||
class ExceptFlowNode extends ControlFlowNode {
|
||||
ExceptFlowNode() { this.getNode() instanceof ExceptStmt }
|
||||
|
||||
/**
|
||||
* Gets the type handled by this exception handler.
|
||||
* `ExceptionType` in `except ExceptionType as e:`
|
||||
*/
|
||||
ControlFlowNode getType() {
|
||||
exists(ExceptStmt ex |
|
||||
this.getBasicBlock().dominates(result.getBasicBlock()) and
|
||||
ex = this.getNode() and
|
||||
result = ex.getType().getAFlowNode()
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the name assigned to the handled exception, if any.
|
||||
* `e` in `except ExceptionType as e:`
|
||||
*/
|
||||
ControlFlowNode getName() {
|
||||
exists(ExceptStmt ex |
|
||||
this.getBasicBlock().dominates(result.getBasicBlock()) and
|
||||
ex = this.getNode() and
|
||||
result = ex.getName().getAFlowNode()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/** The ControlFlowNode for an 'except*' statement. */
|
||||
class ExceptGroupFlowNode extends ControlFlowNode {
|
||||
ExceptGroupFlowNode() { this.getNode() instanceof ExceptGroupStmt }
|
||||
|
||||
/**
|
||||
* Gets the type handled by this exception handler.
|
||||
* `ExceptionType` in `except* ExceptionType as e:`
|
||||
*/
|
||||
ControlFlowNode getType() {
|
||||
this.getBasicBlock().dominates(result.getBasicBlock()) and
|
||||
result = this.getNode().(ExceptGroupStmt).getType().getAFlowNode()
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the name assigned to the handled exception, if any.
|
||||
* `e` in `except* ExceptionType as e:`
|
||||
*/
|
||||
ControlFlowNode getName() {
|
||||
this.getBasicBlock().dominates(result.getBasicBlock()) and
|
||||
result = this.getNode().(ExceptGroupStmt).getName().getAFlowNode()
|
||||
}
|
||||
}
|
||||
|
||||
private module Scopes {
|
||||
private predicate fast_local(NameNode n) {
|
||||
exists(FastLocalVariable v |
|
||||
@@ -1004,7 +1038,8 @@ class BasicBlock extends @py_flow_node {
|
||||
)
|
||||
}
|
||||
|
||||
private ControlFlowNode firstNode() { result = this }
|
||||
/** Gets the first node in this basic block */
|
||||
ControlFlowNode firstNode() { result = this }
|
||||
|
||||
/** Gets the last node in this basic block */
|
||||
ControlFlowNode getLastNode() {
|
||||
@@ -1093,15 +1128,6 @@ class BasicBlock extends @py_flow_node {
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether (as inferred by type inference) it is highly unlikely (or impossible) for control to flow from this to succ.
|
||||
*/
|
||||
predicate unlikelySuccessor(BasicBlock succ) {
|
||||
this.getLastNode().(RaisingNode).unlikelySuccessor(succ.firstNode())
|
||||
or
|
||||
not end_bb_likely_reachable(this) and succ = this.getASuccessor()
|
||||
}
|
||||
|
||||
/** Holds if this basic block strictly reaches the other. Is the start of other reachable from the end of this. */
|
||||
cached
|
||||
predicate strictlyReaches(BasicBlock other) {
|
||||
@@ -1112,11 +1138,6 @@ class BasicBlock extends @py_flow_node {
|
||||
/** Holds if this basic block reaches the other. Is the start of other reachable from the end of this. */
|
||||
predicate reaches(BasicBlock other) { this = other or this.strictlyReaches(other) }
|
||||
|
||||
/**
|
||||
* Whether (as inferred by type inference) this basic block is likely to be reachable.
|
||||
*/
|
||||
predicate likelyReachable() { start_bb_likely_reachable(this) }
|
||||
|
||||
/**
|
||||
* Gets the `ConditionBlock`, if any, that controls this block and
|
||||
* does not control any other `ConditionBlock`s that control this block.
|
||||
@@ -1144,26 +1165,6 @@ class BasicBlock extends @py_flow_node {
|
||||
}
|
||||
}
|
||||
|
||||
private predicate start_bb_likely_reachable(BasicBlock b) {
|
||||
exists(Scope s | s.getEntryNode() = b.getNode(_))
|
||||
or
|
||||
exists(BasicBlock pred |
|
||||
pred = b.getAPredecessor() and
|
||||
end_bb_likely_reachable(pred) and
|
||||
not pred.getLastNode().(RaisingNode).unlikelySuccessor(b)
|
||||
)
|
||||
}
|
||||
|
||||
private predicate end_bb_likely_reachable(BasicBlock b) {
|
||||
start_bb_likely_reachable(b) and
|
||||
not exists(ControlFlowNode p, ControlFlowNode s |
|
||||
p.(RaisingNode).unlikelySuccessor(s) and
|
||||
p = b.getNode(_) and
|
||||
s = b.getNode(_) and
|
||||
not p = b.getLastNode()
|
||||
)
|
||||
}
|
||||
|
||||
private class ControlFlowNodeAlias = ControlFlowNode;
|
||||
|
||||
final private class FinalBasicBlock = BasicBlock;
|
||||
|
||||
@@ -84,12 +84,6 @@ class Function extends Function_, Scope, AstNode {
|
||||
/** Gets the name used to define this function */
|
||||
override string getName() { result = Function_.super.getName() }
|
||||
|
||||
/** Gets the metrics for this function */
|
||||
FunctionMetrics getMetrics() { result = this }
|
||||
|
||||
/** Gets the FunctionObject corresponding to this function */
|
||||
FunctionObject getFunctionObject() { result.getOrigin() = this.getDefinition() }
|
||||
|
||||
/**
|
||||
* Whether this function is a procedure, that is, it has no explicit return statement and always returns None.
|
||||
* Note that generator and async functions are not procedures as they return generators and coroutines respectively.
|
||||
|
||||
@@ -29,9 +29,9 @@ class FunctionMetrics extends Function {
|
||||
*/
|
||||
int getCyclomaticComplexity() {
|
||||
exists(int e, int n |
|
||||
n = count(BasicBlock b | b = this.getABasicBlock() and b.likelyReachable()) and
|
||||
n = count(BasicBlockWithPointsTo b | b = this.getABasicBlock() and b.likelyReachable()) and
|
||||
e =
|
||||
count(BasicBlock b1, BasicBlock b2 |
|
||||
count(BasicBlockWithPointsTo b1, BasicBlockWithPointsTo b2 |
|
||||
b1 = this.getABasicBlock() and
|
||||
b1.likelyReachable() and
|
||||
b2 = this.getABasicBlock() and
|
||||
|
||||
@@ -86,9 +86,6 @@ class Module extends Module_, Scope, AstNode {
|
||||
result = this.getName().regexpReplaceAll("\\.[^.]*$", "")
|
||||
}
|
||||
|
||||
/** Gets the metrics for this module */
|
||||
ModuleMetrics getMetrics() { result = this }
|
||||
|
||||
string getAnImportedModuleName() {
|
||||
exists(Import i | i.getEnclosingModule() = this | result = i.getAnImportedModuleName())
|
||||
or
|
||||
|
||||
@@ -61,14 +61,6 @@ class SsaVariable extends @py_ssa_var {
|
||||
)
|
||||
}
|
||||
|
||||
/** Gets an argument of the phi function defining this variable, pruned of unlikely edges. */
|
||||
SsaVariable getAPrunedPhiInput() {
|
||||
result = this.getAPhiInput() and
|
||||
exists(BasicBlock incoming | incoming = this.getPredecessorBlockForPhiArgument(result) |
|
||||
not incoming.getLastNode().(RaisingNode).unlikelySuccessor(this.getDefinition())
|
||||
)
|
||||
}
|
||||
|
||||
/** Gets a variable that ultimately defines this variable and is not itself defined by another variable */
|
||||
SsaVariable getAnUltimateDefinition() {
|
||||
result = this and not exists(this.getAPhiInput())
|
||||
@@ -85,17 +77,11 @@ class SsaVariable extends @py_ssa_var {
|
||||
string getId() { result = this.getVariable().getId() }
|
||||
|
||||
/** Gets the incoming edges for a Phi node. */
|
||||
private BasicBlock getAPredecessorBlockForPhi() {
|
||||
BasicBlock getAPredecessorBlockForPhi() {
|
||||
exists(this.getAPhiInput()) and
|
||||
result.getASuccessor() = this.getDefinition().getBasicBlock()
|
||||
}
|
||||
|
||||
/** Gets the incoming edges for a Phi node, pruned of unlikely edges. */
|
||||
private BasicBlock getAPrunedPredecessorBlockForPhi() {
|
||||
result = this.getAPredecessorBlockForPhi() and
|
||||
not result.unlikelySuccessor(this.getDefinition().getBasicBlock())
|
||||
}
|
||||
|
||||
/** Whether it is possible to reach a use of this variable without passing a definition */
|
||||
predicate reachableWithoutDefinition() {
|
||||
not exists(this.getDefinition()) and not py_ssa_phi(this, _)
|
||||
@@ -115,38 +101,6 @@ class SsaVariable extends @py_ssa_var {
|
||||
)
|
||||
}
|
||||
|
||||
/** Whether this variable may be undefined */
|
||||
predicate maybeUndefined() {
|
||||
not exists(this.getDefinition()) and not py_ssa_phi(this, _) and not this.implicitlyDefined()
|
||||
or
|
||||
this.getDefinition().isDelete()
|
||||
or
|
||||
exists(SsaVariable var | var = this.getAPrunedPhiInput() | var.maybeUndefined())
|
||||
or
|
||||
/*
|
||||
* For phi-nodes, there must be a corresponding phi-input for each control-flow
|
||||
* predecessor. Otherwise, the variable will be undefined on that incoming edge.
|
||||
* WARNING: the same phi-input may cover multiple predecessors, so this check
|
||||
* cannot be done by counting.
|
||||
*/
|
||||
|
||||
exists(BasicBlock incoming |
|
||||
reaches_end(incoming) and
|
||||
incoming = this.getAPrunedPredecessorBlockForPhi() and
|
||||
not this.getAPhiInput().getDefinition().getBasicBlock().dominates(incoming)
|
||||
)
|
||||
}
|
||||
|
||||
private predicate implicitlyDefined() {
|
||||
not exists(this.getDefinition()) and
|
||||
not py_ssa_phi(this, _) and
|
||||
exists(GlobalVariable var | this.getVariable() = var |
|
||||
globallyDefinedName(var.getId())
|
||||
or
|
||||
var.getId() = "__path__" and var.getScope().(Module).isPackageInit()
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the global variable that is accessed if this local is undefined.
|
||||
* Only applies to local variables in class scopes.
|
||||
@@ -173,43 +127,6 @@ class SsaVariable extends @py_ssa_var {
|
||||
}
|
||||
}
|
||||
|
||||
private predicate reaches_end(BasicBlock b) {
|
||||
not exits_early(b) and
|
||||
(
|
||||
/* Entry point */
|
||||
not exists(BasicBlock prev | prev.getASuccessor() = b)
|
||||
or
|
||||
exists(BasicBlock prev | prev.getASuccessor() = b | reaches_end(prev))
|
||||
)
|
||||
}
|
||||
|
||||
private predicate exits_early(BasicBlock b) {
|
||||
exists(FunctionObject f |
|
||||
f.neverReturns() and
|
||||
f.getACall().getBasicBlock() = b
|
||||
)
|
||||
}
|
||||
|
||||
private predicate gettext_installed() {
|
||||
// Good enough (and fast) approximation
|
||||
exists(Module m | m.getName() = "gettext")
|
||||
}
|
||||
|
||||
private predicate builtin_constant(string name) {
|
||||
exists(Object::builtin(name))
|
||||
or
|
||||
name = "WindowsError"
|
||||
or
|
||||
name = "_" and gettext_installed()
|
||||
}
|
||||
|
||||
private predicate auto_name(string name) {
|
||||
name = "__file__" or name = "__builtins__" or name = "__name__"
|
||||
}
|
||||
|
||||
/** Whether this name is (almost) always defined, ie. it is a builtin or VM defined name */
|
||||
predicate globallyDefinedName(string name) { builtin_constant(name) or auto_name(name) }
|
||||
|
||||
/** An SSA variable that is backed by a global variable */
|
||||
class GlobalSsaVariable extends EssaVariable {
|
||||
GlobalSsaVariable() { this.getSourceVariable() instanceof GlobalVariable }
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
|
||||
import python
|
||||
private import semmle.python.pointsto.Filters
|
||||
private import LegacyPointsTo
|
||||
|
||||
/**
|
||||
* An attribute access where the left hand side of the attribute expression
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
/** This module provides an API for attribute reads and writes. */
|
||||
|
||||
private import python
|
||||
import DataFlowUtil
|
||||
import DataFlowPublic
|
||||
private import DataFlowPrivate
|
||||
private import semmle.python.types.Builtins
|
||||
private import semmle.python.dataflow.new.internal.Builtins
|
||||
|
||||
/**
|
||||
* A data flow node that reads or writes an attribute of an object.
|
||||
@@ -134,8 +135,12 @@ private class BuiltInCallNode extends CallNode {
|
||||
|
||||
BuiltInCallNode() {
|
||||
// TODO disallow instances where the name of the built-in may refer to an in-scope variable of that name.
|
||||
exists(NameNode id | this.getFunction() = id and id.getId() = name and id.isGlobal()) and
|
||||
name = any(Builtin b).getName()
|
||||
exists(NameNode id |
|
||||
name = Builtins::getBuiltinName() and
|
||||
this.getFunction() = id and
|
||||
id.getId() = name and
|
||||
id.isGlobal()
|
||||
)
|
||||
}
|
||||
|
||||
/** Gets the name of the built-in function that is called at this `CallNode` */
|
||||
|
||||
@@ -9,6 +9,7 @@ private import semmle.python.dataflow.new.DataFlow
|
||||
private import semmle.python.dataflow.new.internal.ImportStar
|
||||
private import semmle.python.dataflow.new.TypeTracking
|
||||
private import semmle.python.dataflow.new.internal.DataFlowPrivate
|
||||
private import semmle.python.essa.SsaDefinitions
|
||||
|
||||
/**
|
||||
* Python modules and the way imports are resolved are... complicated. Here's a crash course in how
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import python
|
||||
import semmle.python.dataflow.TaintTracking
|
||||
private import semmle.python.objects.ObjectInternal
|
||||
private import LegacyPointsTo
|
||||
private import semmle.python.dataflow.Implementation
|
||||
|
||||
module TaintTracking {
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import python
|
||||
private import LegacyPointsTo
|
||||
import semmle.python.dataflow.TaintTracking
|
||||
|
||||
class OpenFile extends TaintKind {
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import python
|
||||
private import LegacyPointsTo
|
||||
import semmle.python.dataflow.TaintTracking
|
||||
private import semmle.python.objects.ObjectInternal
|
||||
private import semmle.python.pointsto.Filters as Filters
|
||||
import semmle.python.dataflow.Legacy
|
||||
|
||||
@@ -257,7 +256,7 @@ class TaintTrackingImplementation extends string instanceof TaintTracking::Confi
|
||||
TaintKind kind, string edgeLabel
|
||||
) {
|
||||
this.unprunedStep(src, node, context, path, kind, edgeLabel) and
|
||||
node.getBasicBlock().likelyReachable() and
|
||||
node.getBasicBlock().(BasicBlockWithPointsTo).likelyReachable() and
|
||||
not super.isBarrier(node) and
|
||||
(
|
||||
not path = TNoAttribute()
|
||||
@@ -685,7 +684,9 @@ private class EssaTaintTracking extends string instanceof TaintTracking::Configu
|
||||
TaintTrackingNode src, PhiFunction defn, TaintTrackingContext context, AttributePath path,
|
||||
TaintKind kind
|
||||
) {
|
||||
exists(DataFlow::Node srcnode, BasicBlock pred, EssaVariable predvar, DataFlow::Node phi |
|
||||
exists(
|
||||
DataFlow::Node srcnode, BasicBlockWithPointsTo pred, EssaVariable predvar, DataFlow::Node phi
|
||||
|
|
||||
src = TTaintTrackingNode_(srcnode, context, path, kind, this) and
|
||||
defn = phi.asVariable().getDefinition() and
|
||||
predvar = defn.getInput(pred) and
|
||||
|
||||
@@ -9,9 +9,7 @@
|
||||
*/
|
||||
|
||||
import python
|
||||
private import semmle.python.pointsto.PointsTo
|
||||
private import semmle.python.pointsto.PointsToContext
|
||||
private import semmle.python.objects.ObjectInternal
|
||||
private import LegacyPointsTo
|
||||
|
||||
/** A state that should be tracked. */
|
||||
abstract class TrackableState extends string {
|
||||
|
||||
@@ -89,7 +89,6 @@
|
||||
import python
|
||||
private import LegacyPointsTo
|
||||
private import semmle.python.pointsto.Filters as Filters
|
||||
private import semmle.python.objects.ObjectInternal
|
||||
private import semmle.python.dataflow.Implementation
|
||||
import semmle.python.dataflow.Configuration
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import semmle.python.dependencies.Dependencies
|
||||
private import LegacyPointsTo
|
||||
|
||||
/**
|
||||
* A library describing an abstract mechanism for representing dependency categories.
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import python
|
||||
import semmle.python.dependencies.Dependencies
|
||||
import semmle.python.dependencies.DependencyKind
|
||||
private import LegacyPointsTo
|
||||
|
||||
/**
|
||||
* Combine the source-file and package into a single string:
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import python
|
||||
|
||||
/*
|
||||
* Classification of variables. These should be non-overlapping and complete.
|
||||
*
|
||||
@@ -12,6 +11,9 @@ import python
|
||||
* Escaping globals -- Global variables that have definitions and at least one of those definitions is in another scope.
|
||||
*/
|
||||
|
||||
private import semmle.python.types.ImportTime
|
||||
private import semmle.python.essa.SsaDefinitions
|
||||
|
||||
/** A source language variable, to be converted into a set of SSA variables. */
|
||||
abstract class SsaSourceVariable extends @py_variable {
|
||||
SsaSourceVariable() {
|
||||
@@ -274,6 +276,17 @@ class ModuleVariable extends SsaSourceVariable instanceof GlobalVariable {
|
||||
override CallNode redefinedAtCallSite() { none() }
|
||||
}
|
||||
|
||||
/** Holds if `f` is an import of the form `from .[...] import ...` and the enclosing scope is an __init__ module */
|
||||
private predicate import_from_dot_in_init(ImportExprNode f) {
|
||||
f.getScope() = any(Module m).getInitModule() and
|
||||
(
|
||||
f.getNode().getLevel() = 1 and
|
||||
not exists(f.getNode().getName())
|
||||
or
|
||||
f.getNode().getImportedModuleName() = f.getEnclosingModule().getPackage().getName()
|
||||
)
|
||||
}
|
||||
|
||||
class NonEscapingGlobalVariable extends ModuleVariable {
|
||||
NonEscapingGlobalVariable() {
|
||||
this instanceof GlobalVariable and
|
||||
|
||||
@@ -6,6 +6,7 @@ import python
|
||||
private import SsaCompute
|
||||
import semmle.python.essa.Definitions
|
||||
private import semmle.python.internal.CachedStages
|
||||
private import semmle.python.essa.SsaDefinitions
|
||||
|
||||
/** An (enhanced) SSA variable derived from `SsaSourceVariable`. */
|
||||
class EssaVariable extends TEssaDefinition {
|
||||
|
||||
@@ -6,6 +6,13 @@
|
||||
import python
|
||||
private import semmle.python.internal.CachedStages
|
||||
|
||||
/** Hold if `expr` is a test (a branch) and `use` is within that test */
|
||||
predicate test_contains(ControlFlowNode expr, ControlFlowNode use) {
|
||||
expr.getNode() instanceof Expr and
|
||||
expr.isBranch() and
|
||||
expr.getAChild*() = use
|
||||
}
|
||||
|
||||
cached
|
||||
module SsaSource {
|
||||
/** Holds if `v` is used as the receiver in a method call. */
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/** Utilities for handling the zope libraries */
|
||||
|
||||
import python
|
||||
private import semmle.python.pointsto.PointsTo
|
||||
private import LegacyPointsTo
|
||||
|
||||
/** A method that belongs to a sub-class of `zope.interface.Interface` */
|
||||
class ZopeInterfaceMethodValue extends PythonFunctionValue {
|
||||
|
||||
@@ -5,6 +5,7 @@ private import semmle.python.pointsto.PointsTo
|
||||
private import semmle.python.pointsto.MRO
|
||||
private import semmle.python.pointsto.PointsToContext
|
||||
private import semmle.python.types.Builtins
|
||||
private import semmle.python.objects.ObjectAPI
|
||||
|
||||
/**
|
||||
* A constant.
|
||||
|
||||
@@ -5,6 +5,7 @@ private import semmle.python.pointsto.PointsTo
|
||||
private import semmle.python.pointsto.PointsToContext
|
||||
private import semmle.python.pointsto.MRO
|
||||
private import semmle.python.types.Builtins
|
||||
private import semmle.python.pointsto.Context
|
||||
|
||||
/** A property object. */
|
||||
class PropertyInternal extends ObjectInternal, TProperty {
|
||||
|
||||
@@ -5,6 +5,8 @@ private import semmle.python.pointsto.PointsTo
|
||||
private import semmle.python.pointsto.MRO
|
||||
private import semmle.python.pointsto.PointsToContext
|
||||
private import semmle.python.types.Builtins
|
||||
private import semmle.python.pointsto.Context
|
||||
private import semmle.python.pointsto.Base
|
||||
|
||||
/** A class representing instances */
|
||||
abstract class InstanceObject extends ObjectInternal {
|
||||
|
||||
@@ -5,6 +5,7 @@ private import semmle.python.pointsto.PointsTo
|
||||
private import semmle.python.pointsto.MRO
|
||||
private import semmle.python.pointsto.PointsToContext
|
||||
private import semmle.python.types.Builtins
|
||||
private import semmle.python.types.ImportTime
|
||||
|
||||
/** A class representing modules */
|
||||
abstract class ModuleObjectInternal extends ObjectInternal {
|
||||
|
||||
@@ -6,9 +6,6 @@
|
||||
import python
|
||||
private import LegacyPointsTo
|
||||
private import TObject
|
||||
private import semmle.python.objects.ObjectInternal
|
||||
private import semmle.python.pointsto.PointsTo
|
||||
private import semmle.python.pointsto.PointsToContext
|
||||
private import semmle.python.pointsto.MRO
|
||||
private import semmle.python.types.Builtins
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@ private import semmle.python.objects.ObjectInternal
|
||||
private import semmle.python.pointsto.PointsTo
|
||||
private import semmle.python.pointsto.PointsToContext
|
||||
private import semmle.python.internal.CachedStages
|
||||
private import semmle.python.pointsto.Context
|
||||
|
||||
/**
|
||||
* Internal type backing `ObjectInternal` and `Value`
|
||||
|
||||
@@ -12,6 +12,8 @@ import python
|
||||
import semmle.python.essa.SsaDefinitions
|
||||
private import semmle.python.types.Builtins
|
||||
private import semmle.python.internal.CachedStages
|
||||
private import semmle.python.types.Object
|
||||
private import semmle.python.types.ClassObject
|
||||
|
||||
/*
|
||||
* The following predicates exist in order to provide
|
||||
@@ -42,24 +44,6 @@ private predicate class_defines_name(Class cls, string name) {
|
||||
exists(SsaVariable var | name = var.getId() and var.getAUse() = cls.getANormalExit())
|
||||
}
|
||||
|
||||
/** Hold if `expr` is a test (a branch) and `use` is within that test */
|
||||
predicate test_contains(ControlFlowNode expr, ControlFlowNode use) {
|
||||
expr.getNode() instanceof Expr and
|
||||
expr.isBranch() and
|
||||
expr.getAChild*() = use
|
||||
}
|
||||
|
||||
/** Holds if `f` is an import of the form `from .[...] import ...` and the enclosing scope is an __init__ module */
|
||||
predicate import_from_dot_in_init(ImportExprNode f) {
|
||||
f.getScope() = any(Module m).getInitModule() and
|
||||
(
|
||||
f.getNode().getLevel() = 1 and
|
||||
not exists(f.getNode().getName())
|
||||
or
|
||||
f.getNode().getImportedModuleName() = f.getEnclosingModule().getPackage().getName()
|
||||
)
|
||||
}
|
||||
|
||||
/** Gets the pseudo-object representing the value referred to by an undefined variable */
|
||||
Object undefinedVariable() { py_special_objects(result, "_semmle_undefined_value") }
|
||||
|
||||
|
||||
@@ -11,6 +11,8 @@
|
||||
|
||||
import python
|
||||
private import semmle.python.pointsto.PointsToContext
|
||||
private import semmle.python.types.FunctionObject
|
||||
private import semmle.python.pointsto.Context
|
||||
|
||||
private newtype TTInvocation =
|
||||
TInvocation(FunctionObject f, Context c) {
|
||||
|
||||
@@ -6,7 +6,13 @@ private import semmle.python.pointsto.PointsToContext
|
||||
private import semmle.python.pointsto.MRO
|
||||
private import semmle.python.types.Builtins
|
||||
private import semmle.python.types.Extensions
|
||||
private import semmle.python.pointsto.Context
|
||||
private import semmle.python.internal.CachedStages
|
||||
private import semmle.python.types.Object
|
||||
private import semmle.python.types.FunctionObject
|
||||
private import semmle.python.types.ClassObject
|
||||
private import semmle.python.pointsto.Base
|
||||
private import semmle.python.types.ImportTime
|
||||
|
||||
/* Use this version for speed */
|
||||
class CfgOrigin extends @py_object {
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
import python
|
||||
private import semmle.python.pointsto.PointsTo
|
||||
private import semmle.python.objects.ObjectInternal
|
||||
private import semmle.python.types.ImportTime
|
||||
private import semmle.python.types.Version
|
||||
|
||||
/*
|
||||
* A note on 'cost'. Cost doesn't represent the cost to compute,
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import python
|
||||
private import LegacyPointsTo
|
||||
|
||||
class Builtin extends @py_cobject {
|
||||
Builtin() {
|
||||
|
||||
@@ -6,6 +6,7 @@ private import semmle.python.pointsto.PointsTo
|
||||
private import semmle.python.pointsto.MRO
|
||||
private import semmle.python.types.Builtins
|
||||
private import semmle.python.objects.ObjectInternal
|
||||
private import semmle.python.types.ImportTime
|
||||
|
||||
/**
|
||||
* A class whose instances represents Python classes.
|
||||
@@ -88,7 +89,7 @@ class ClassObject extends Object {
|
||||
}
|
||||
|
||||
/** Gets the scope associated with this class, if it is not a builtin class */
|
||||
Class getPyClass() { result.getClassObject() = this }
|
||||
ClassWithPointsTo getPyClass() { result.getClassObject() = this }
|
||||
|
||||
/** Returns an attribute declared on this class (not on a super-class) */
|
||||
Object declaredAttribute(string name) {
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
import python
|
||||
private import semmle.python.objects.ObjectInternal
|
||||
private import semmle.python.types.Object
|
||||
private import semmle.python.types.FunctionObject
|
||||
private import semmle.python.pointsto.Context
|
||||
|
||||
/** A class method object. Either a decorated function or an explicit call to classmethod(f) */
|
||||
class ClassMethodObject extends Object {
|
||||
|
||||
@@ -80,7 +80,7 @@ class RaisingNode extends ControlFlowNode {
|
||||
or
|
||||
this.getNode() instanceof Print and result = theIOErrorType()
|
||||
or
|
||||
exists(ExceptFlowNode except |
|
||||
exists(ExceptFlowNodeWithPointsTo except |
|
||||
except = this.getAnExceptionalSuccessor() and
|
||||
except.handles_objectapi(result) and
|
||||
result = this.innateException_objectapi()
|
||||
@@ -107,7 +107,7 @@ class RaisingNode extends ControlFlowNode {
|
||||
or
|
||||
this.getNode() instanceof Print and result = ClassValue::ioError()
|
||||
or
|
||||
exists(ExceptFlowNode except |
|
||||
exists(ExceptFlowNodeWithPointsTo except |
|
||||
except = this.getAnExceptionalSuccessor() and
|
||||
except.handles(result) and
|
||||
result = this.innateException()
|
||||
@@ -200,8 +200,8 @@ class RaisingNode extends ControlFlowNode {
|
||||
succ = this.getAnExceptionalSuccessor() and
|
||||
(
|
||||
/* An 'except' that handles raised and there is no more previous handler */
|
||||
succ.(ExceptFlowNode).handles_objectapi(raised) and
|
||||
not exists(ExceptFlowNode other, StmtList s, int i, int j |
|
||||
succ.(ExceptFlowNodeWithPointsTo).handles_objectapi(raised) and
|
||||
not exists(ExceptFlowNodeWithPointsTo other, StmtList s, int i, int j |
|
||||
not other = succ and
|
||||
other.handles_objectapi(raised) and
|
||||
s.getItem(i) = succ.getNode() and
|
||||
@@ -211,7 +211,7 @@ class RaisingNode extends ControlFlowNode {
|
||||
)
|
||||
or
|
||||
/* Any successor that is not an 'except', provided that 'raised' is not handled by a different successor. */
|
||||
not this.getAnExceptionalSuccessor().(ExceptFlowNode).handles_objectapi(raised) and
|
||||
not this.getAnExceptionalSuccessor().(ExceptFlowNodeWithPointsTo).handles_objectapi(raised) and
|
||||
not succ instanceof ExceptFlowNode
|
||||
)
|
||||
}
|
||||
@@ -223,8 +223,8 @@ class RaisingNode extends ControlFlowNode {
|
||||
succ = this.getAnExceptionalSuccessor() and
|
||||
(
|
||||
/* An 'except' that handles raised and there is no more previous handler */
|
||||
succ.(ExceptFlowNode).handles(raised) and
|
||||
not exists(ExceptFlowNode other, StmtList s, int i, int j |
|
||||
succ.(ExceptFlowNodeWithPointsTo).handles(raised) and
|
||||
not exists(ExceptFlowNodeWithPointsTo other, StmtList s, int i, int j |
|
||||
not other = succ and
|
||||
other.handles(raised) and
|
||||
s.getItem(i) = succ.getNode() and
|
||||
@@ -234,7 +234,7 @@ class RaisingNode extends ControlFlowNode {
|
||||
)
|
||||
or
|
||||
/* Any successor that is not an 'except', provided that 'raised' is not handled by a different successor. */
|
||||
not this.getAnExceptionalSuccessor().(ExceptFlowNode).handles(raised) and
|
||||
not this.getAnExceptionalSuccessor().(ExceptFlowNodeWithPointsTo).handles(raised) and
|
||||
not succ instanceof ExceptFlowNode
|
||||
)
|
||||
}
|
||||
@@ -248,7 +248,7 @@ class RaisingNode extends ControlFlowNode {
|
||||
raised.isLegalExceptionType() and
|
||||
raised = this.getARaisedType_objectapi() and
|
||||
this.isExceptionalExit(s) and
|
||||
not this.getAnExceptionalSuccessor().(ExceptFlowNode).handles_objectapi(raised)
|
||||
not this.getAnExceptionalSuccessor().(ExceptFlowNodeWithPointsTo).handles_objectapi(raised)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -260,7 +260,7 @@ class RaisingNode extends ControlFlowNode {
|
||||
raised.isLegalExceptionType() and
|
||||
raised = this.getARaisedType() and
|
||||
this.isExceptionalExit(s) and
|
||||
not this.getAnExceptionalSuccessor().(ExceptFlowNode).handles(raised)
|
||||
not this.getAnExceptionalSuccessor().(ExceptFlowNodeWithPointsTo).handles(raised)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -368,36 +368,10 @@ predicate scope_raises_unknown(Scope s) {
|
||||
)
|
||||
}
|
||||
|
||||
/** The ControlFlowNode for an 'except' statement. */
|
||||
class ExceptFlowNode extends ControlFlowNode {
|
||||
ExceptFlowNode() { this.getNode() instanceof ExceptStmt }
|
||||
|
||||
/**
|
||||
* Gets the type handled by this exception handler.
|
||||
* `ExceptionType` in `except ExceptionType as e:`
|
||||
*/
|
||||
ControlFlowNodeWithPointsTo getType() {
|
||||
exists(ExceptStmt ex |
|
||||
this.getBasicBlock().dominates(result.getBasicBlock()) and
|
||||
ex = this.getNode() and
|
||||
result = ex.getType().getAFlowNode()
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the name assigned to the handled exception, if any.
|
||||
* `e` in `except ExceptionType as e:`
|
||||
*/
|
||||
ControlFlowNode getName() {
|
||||
exists(ExceptStmt ex |
|
||||
this.getBasicBlock().dominates(result.getBasicBlock()) and
|
||||
ex = this.getNode() and
|
||||
result = ex.getName().getAFlowNode()
|
||||
)
|
||||
}
|
||||
|
||||
/** An extension of `ExceptFlowNode` that provides points-to related methods. */
|
||||
class ExceptFlowNodeWithPointsTo extends ExceptFlowNode {
|
||||
private predicate handledObject_objectapi(Object obj, ClassObject cls, ControlFlowNode origin) {
|
||||
this.getType().refersTo(obj, cls, origin)
|
||||
this.getType().(ControlFlowNodeWithPointsTo).refersTo(obj, cls, origin)
|
||||
or
|
||||
exists(Object tup | this.handledObject_objectapi(tup, theTupleType(), _) |
|
||||
element_from_tuple_objectapi(tup).refersTo(obj, cls, origin)
|
||||
@@ -407,7 +381,7 @@ class ExceptFlowNode extends ControlFlowNode {
|
||||
private predicate handledObject(Value val, ClassValue cls, ControlFlowNode origin) {
|
||||
val.getClass() = cls and
|
||||
(
|
||||
this.getType().pointsTo(val, origin)
|
||||
this.getType().(ControlFlowNodeWithPointsTo).pointsTo(val, origin)
|
||||
or
|
||||
exists(TupleValue tup | this.handledObject(tup, ClassValue::tuple(), _) |
|
||||
val = tup.getItem(_) and origin = val.getOrigin()
|
||||
@@ -452,29 +426,6 @@ class ExceptFlowNode extends ControlFlowNode {
|
||||
}
|
||||
}
|
||||
|
||||
/** The ControlFlowNode for an 'except*' statement. */
|
||||
class ExceptGroupFlowNode extends ControlFlowNode {
|
||||
ExceptGroupFlowNode() { this.getNode() instanceof ExceptGroupStmt }
|
||||
|
||||
/**
|
||||
* Gets the type handled by this exception handler.
|
||||
* `ExceptionType` in `except* ExceptionType as e:`
|
||||
*/
|
||||
ControlFlowNode getType() {
|
||||
this.getBasicBlock().dominates(result.getBasicBlock()) and
|
||||
result = this.getNode().(ExceptGroupStmt).getType().getAFlowNode()
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the name assigned to the handled exception, if any.
|
||||
* `e` in `except* ExceptionType as e:`
|
||||
*/
|
||||
ControlFlowNode getName() {
|
||||
this.getBasicBlock().dominates(result.getBasicBlock()) and
|
||||
result = this.getNode().(ExceptGroupStmt).getName().getAFlowNode()
|
||||
}
|
||||
}
|
||||
|
||||
private ControlFlowNodeWithPointsTo element_from_tuple_objectapi(Object tuple) {
|
||||
exists(Tuple t | t = tuple.getOrigin() and result = t.getAnElt().getAFlowNode())
|
||||
}
|
||||
|
||||
@@ -15,7 +15,8 @@ private import semmle.python.pointsto.PointsTo
|
||||
private import semmle.python.pointsto.PointsToContext
|
||||
private import semmle.python.objects.TObject
|
||||
/* Make ObjectInternal visible to save extra imports in user code */
|
||||
import semmle.python.objects.ObjectInternal
|
||||
private import semmle.python.objects.ObjectInternal
|
||||
private import semmle.python.pointsto.Context
|
||||
|
||||
abstract class PointsToExtension extends @py_flow_node {
|
||||
string toString() { result = "PointsToExtension with missing toString" }
|
||||
|
||||
@@ -1,10 +1,7 @@
|
||||
import python
|
||||
private import LegacyPointsTo
|
||||
import semmle.python.types.Exceptions
|
||||
private import semmle.python.pointsto.PointsTo
|
||||
private import semmle.python.objects.Callables
|
||||
private import semmle.python.libraries.Zope
|
||||
private import semmle.python.objects.ObjectInternal
|
||||
private import semmle.python.types.Builtins
|
||||
|
||||
/** A function object, whether written in Python or builtin */
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import python
|
||||
private import semmle.python.types.ModuleObject
|
||||
|
||||
private predicate is_normal_module(ModuleObject m) {
|
||||
m instanceof BuiltinModuleObject
|
||||
|
||||
@@ -2,6 +2,9 @@ import python
|
||||
private import semmle.python.pointsto.PointsTo
|
||||
private import semmle.python.objects.ObjectInternal
|
||||
private import semmle.python.types.ModuleKind
|
||||
private import semmle.python.types.Object
|
||||
private import semmle.python.types.ClassObject
|
||||
private import semmle.python.objects.ObjectAPI
|
||||
|
||||
abstract class ModuleObject extends Object {
|
||||
ModuleValue theModule() {
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import python
|
||||
private import LegacyPointsTo
|
||||
private import semmle.python.objects.ObjectInternal
|
||||
private import semmle.python.types.Builtins
|
||||
private import semmle.python.internal.CachedStages
|
||||
|
||||
|
||||
@@ -1,8 +1,5 @@
|
||||
import python
|
||||
private import LegacyPointsTo
|
||||
private import semmle.python.types.Object
|
||||
private import semmle.python.types.ClassObject
|
||||
private import semmle.python.types.FunctionObject
|
||||
|
||||
predicate string_attribute_all(ControlFlowNodeWithPointsTo n, string attr) {
|
||||
(n.getNode() instanceof Unicode or n.getNode() instanceof Bytes) and
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import python
|
||||
private import semmle.python.pointsto.PointsTo
|
||||
private import LegacyPointsTo
|
||||
|
||||
/** A helper class for UndefinedClassAttribute.ql and MaybeUndefinedClassAttribute.ql */
|
||||
class CheckClass extends ClassObject {
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
*/
|
||||
|
||||
import python
|
||||
private import LegacyPointsTo
|
||||
|
||||
predicate does_nothing(PyFunctionObject f) {
|
||||
not exists(Stmt s | s.getScope() = f.getFunction() |
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
|
||||
import python
|
||||
import Equality
|
||||
private import LegacyPointsTo
|
||||
|
||||
predicate class_stores_to_attribute(ClassValue cls, SelfAttributeStore store, string name) {
|
||||
exists(FunctionValue f |
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
*/
|
||||
|
||||
import python
|
||||
private import LegacyPointsTo
|
||||
|
||||
ClassObject left_base(ClassObject type, ClassObject base) {
|
||||
exists(int i | i > 0 and type.getBaseType(i) = base and result = type.getBaseType(i - 1))
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
|
||||
import python
|
||||
import ClassAttributes
|
||||
private import LegacyPointsTo
|
||||
|
||||
predicate guarded_by_other_attribute(SelfAttributeRead a, CheckClass c) {
|
||||
c.sometimesDefines(a.getName()) and
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
*/
|
||||
|
||||
import python
|
||||
private import LegacyPointsTo
|
||||
|
||||
predicate mutates_descriptor(ClassObject cls, SelfAttributeStore s) {
|
||||
cls.isDescriptorType() and
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
*/
|
||||
|
||||
import python
|
||||
private import LegacyPointsTo
|
||||
|
||||
class InitCallStmt extends ExprStmt {
|
||||
InitCallStmt() {
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
*/
|
||||
|
||||
import python
|
||||
private import LegacyPointsTo
|
||||
|
||||
from PropertyObject prop, ClassObject cls
|
||||
where cls.declaredAttribute(_) = prop and not cls.failedInference() and not cls.isNewStyle()
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
*/
|
||||
|
||||
import python
|
||||
private import LegacyPointsTo
|
||||
|
||||
from ClassValue c
|
||||
where not c.isBuiltin() and not c.isContextManager() and exists(c.declaredAttribute("__del__"))
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
*/
|
||||
|
||||
import python
|
||||
private import LegacyPointsTo
|
||||
|
||||
from ClassObject c
|
||||
where not c.isNewStyle() and c.declaresAttribute("__slots__") and not c.failedInference()
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
*/
|
||||
|
||||
import python
|
||||
private import LegacyPointsTo
|
||||
|
||||
predicate uses_of_super_in_old_style_class(Call s) {
|
||||
exists(Function f, ClassObject c |
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
|
||||
import python
|
||||
import ClassAttributes
|
||||
private import LegacyPointsTo
|
||||
|
||||
predicate undefined_class_attribute(SelfAttributeRead a, CheckClass c, int line, string name) {
|
||||
name = a.getName() and
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
*/
|
||||
|
||||
import python
|
||||
private import LegacyPointsTo
|
||||
|
||||
predicate fewer_than_two_public_methods(Class cls, int methods) {
|
||||
(methods = 0 or methods = 1) and
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
import python
|
||||
import Expressions.CallArgs
|
||||
private import LegacyPointsTo
|
||||
|
||||
from Call call, ClassValue cls, string name, FunctionValue init
|
||||
where
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
|
||||
import python
|
||||
import Expressions.CallArgs
|
||||
private import LegacyPointsTo
|
||||
|
||||
from Call call, ClassValue cls, string too, string should, int limit, FunctionValue init
|
||||
where
|
||||
|
||||
@@ -12,8 +12,9 @@
|
||||
*/
|
||||
|
||||
import python
|
||||
private import LegacyPointsTo
|
||||
|
||||
from ExceptFlowNode ex, Value t, ClassValue c, ControlFlowNode origin, string what
|
||||
from ExceptFlowNodeWithPointsTo ex, Value t, ClassValue c, ControlFlowNode origin, string what
|
||||
where
|
||||
ex.handledException(t, c, origin) and
|
||||
(
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
import python
|
||||
import Raising
|
||||
import Exceptions.NotImplemented
|
||||
private import LegacyPointsTo
|
||||
|
||||
from Raise r, ClassValue t
|
||||
where
|
||||
|
||||
@@ -13,7 +13,6 @@
|
||||
|
||||
import python
|
||||
private import LegacyPointsTo
|
||||
import semmle.python.pointsto.PointsTo
|
||||
|
||||
predicate rhs_in_expr(ControlFlowNode rhs, Compare cmp) {
|
||||
exists(Cmpop op, int i | cmp.getOp(i) = op and cmp.getComparator(i) = rhs.getNode() |
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
|
||||
import python
|
||||
private import LegacyPointsTo
|
||||
private import semmle.python.objects.ObjectInternal
|
||||
|
||||
/** 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) {
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
|
||||
import python
|
||||
import IsComparisons
|
||||
private import LegacyPointsTo
|
||||
|
||||
from Compare comp, Cmpop op, ClassValue c
|
||||
where
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
/** Helper functions for queries that test redundant comparisons. */
|
||||
|
||||
import python
|
||||
private import LegacyPointsTo
|
||||
|
||||
/** A comparison where the left and right hand sides appear to be identical. */
|
||||
class RedundantComparison extends Compare {
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
import python
|
||||
import Expressions.CallArgs
|
||||
private import LegacyPointsTo
|
||||
|
||||
from Call call, FunctionObject func, string name
|
||||
where
|
||||
|
||||
@@ -15,7 +15,6 @@
|
||||
|
||||
import python
|
||||
import LegacyPointsTo
|
||||
import semmle.python.objects.ObjectInternal
|
||||
import semmle.python.strings
|
||||
|
||||
predicate string_format(BinaryExpr operation, StringLiteral str, Value args, AstNode origin) {
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
*/
|
||||
|
||||
import python
|
||||
private import LegacyPointsTo
|
||||
import CallArgs
|
||||
|
||||
from Call call, FunctionValue func, string too, string should, int limit
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
*/
|
||||
|
||||
import python
|
||||
private import LegacyPointsTo
|
||||
|
||||
predicate explicitly_returns_non_none(Function func) {
|
||||
exists(Return return |
|
||||
@@ -21,7 +22,7 @@ predicate explicitly_returns_non_none(Function func) {
|
||||
}
|
||||
|
||||
predicate has_implicit_return(Function func) {
|
||||
exists(ControlFlowNode fallthru |
|
||||
exists(ControlFlowNodeWithPointsTo fallthru |
|
||||
fallthru = func.getFallthroughNode() and not fallthru.unlikelyReachable()
|
||||
)
|
||||
or
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
*/
|
||||
|
||||
import python
|
||||
private import LegacyPointsTo
|
||||
|
||||
predicate slice_method_name(string name) {
|
||||
name = "__getslice__" or name = "__setslice__" or name = "__delslice__"
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
|
||||
import python
|
||||
import Expressions.CallArgs
|
||||
private import LegacyPointsTo
|
||||
|
||||
from Call call, FunctionValue func, FunctionValue overridden, string problem
|
||||
where
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
|
||||
import python
|
||||
import Expressions.CallArgs
|
||||
private import LegacyPointsTo
|
||||
|
||||
from Call call, FunctionValue func, FunctionValue overriding, string problem
|
||||
where
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
*/
|
||||
|
||||
import python
|
||||
private import LegacyPointsTo
|
||||
|
||||
from ClassValue iterable, FunctionValue iter, ClassValue iterator
|
||||
where
|
||||
|
||||
@@ -12,11 +12,12 @@
|
||||
*/
|
||||
|
||||
import python
|
||||
private import LegacyPointsTo
|
||||
|
||||
from FunctionValue method
|
||||
where
|
||||
exists(ClassValue c |
|
||||
c.declaredAttribute("__del__") = method and
|
||||
method.getScope().getMetrics().getCyclomaticComplexity() > 3
|
||||
method.getScope().(FunctionMetrics).getCyclomaticComplexity() > 3
|
||||
)
|
||||
select method, "Overly complex '__del__' method."
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
*/
|
||||
|
||||
import python
|
||||
import semmle.python.objects.Callables
|
||||
private import LegacyPointsTo
|
||||
|
||||
predicate meaningful_return_value(Expr val) {
|
||||
val instanceof Name
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import python
|
||||
private import LegacyPointsTo
|
||||
private import semmle.python.types.ImportTime
|
||||
|
||||
predicate is_import_time(Stmt s) { not s.getScope+() instanceof Function }
|
||||
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
|
||||
import python
|
||||
import Cyclic
|
||||
private import LegacyPointsTo
|
||||
|
||||
from ModuleValue m1, ModuleValue m2, Stmt imp
|
||||
where
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
*/
|
||||
|
||||
import python
|
||||
private import LegacyPointsTo
|
||||
|
||||
predicate modules_imports_itself(ImportingStmt i, ModuleValue m) {
|
||||
i.getEnclosingModule() = m.getScope() and
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
|
||||
import python
|
||||
import Cyclic
|
||||
private import LegacyPointsTo
|
||||
|
||||
// This is a potentially crashing bug if
|
||||
// 1. the imports in the whole cycle are lexically outside a def (and so executed at import time)
|
||||
|
||||
@@ -13,6 +13,8 @@
|
||||
*/
|
||||
|
||||
import python
|
||||
private import LegacyPointsTo
|
||||
private import semmle.python.types.ImportTime
|
||||
|
||||
predicate import_star(ImportStar imp, ModuleValue exporter) {
|
||||
exporter.importedAs(imp.getImportedModuleName())
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
*/
|
||||
|
||||
import python
|
||||
private import LegacyPointsTo
|
||||
|
||||
from Function f
|
||||
select f, f.getMetrics().getNumberOfLinesOfCode() as n order by n desc
|
||||
from FunctionMetrics f
|
||||
select f, f.getNumberOfLinesOfCode() as n order by n desc
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
*/
|
||||
|
||||
import python
|
||||
private import LegacyPointsTo
|
||||
|
||||
from ClassMetrics cls
|
||||
select cls, cls.getAfferentCoupling() as n order by n desc
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
*/
|
||||
|
||||
import python
|
||||
private import LegacyPointsTo
|
||||
|
||||
from ClassMetrics cls
|
||||
select cls, cls.getEfferentCoupling() as n order by n desc
|
||||
|
||||
@@ -12,8 +12,10 @@
|
||||
*/
|
||||
|
||||
import python
|
||||
private import LegacyPointsTo
|
||||
|
||||
from Module m, ModuleMetrics mm
|
||||
where mm = m.getMetrics() and mm.getNumberOfLines() > 0
|
||||
select m, 100.0 * (mm.getNumberOfLinesOfComments().(float) / mm.getNumberOfLines().(float)) as ratio
|
||||
from ModuleMetrics mm
|
||||
where mm.getNumberOfLines() > 0
|
||||
select mm,
|
||||
100.0 * (mm.getNumberOfLinesOfComments().(float) / mm.getNumberOfLines().(float)) as ratio
|
||||
order by ratio desc
|
||||
|
||||
@@ -13,7 +13,8 @@
|
||||
*/
|
||||
|
||||
import python
|
||||
private import LegacyPointsTo
|
||||
|
||||
from Function func, int complexity
|
||||
where complexity = func.getMetrics().getCyclomaticComplexity()
|
||||
from FunctionMetrics func, int complexity
|
||||
where complexity = func.getCyclomaticComplexity()
|
||||
select func, complexity order by complexity desc
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
|
||||
import python
|
||||
import semmle.python.dependencies.TechInventory
|
||||
private import LegacyPointsTo
|
||||
|
||||
/*
|
||||
* This query creates the source links for the ExternalDependencies.ql query.
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
*/
|
||||
|
||||
import python
|
||||
private import LegacyPointsTo
|
||||
|
||||
from ModuleValue m, int n
|
||||
where n = count(ModuleValue imp | imp = m.getAnImportedModule())
|
||||
|
||||
@@ -11,9 +11,10 @@
|
||||
*/
|
||||
|
||||
import python
|
||||
private import LegacyPointsTo
|
||||
|
||||
from Module m, ModuleMetrics mm
|
||||
where mm = m.getMetrics() and mm.getNumberOfLines() > 0
|
||||
select m,
|
||||
from ModuleMetrics mm
|
||||
where mm.getNumberOfLines() > 0
|
||||
select mm,
|
||||
100.0 * (mm.getNumberOfLinesOfDocStrings().(float) / mm.getNumberOfLines().(float)) as ratio
|
||||
order by ratio desc
|
||||
|
||||
@@ -9,7 +9,8 @@
|
||||
*/
|
||||
|
||||
import python
|
||||
private import LegacyPointsTo
|
||||
|
||||
from Module m, int n
|
||||
where n = m.getMetrics().getNumberOfLines()
|
||||
from ModuleMetrics m, int n
|
||||
where n = m.getNumberOfLines()
|
||||
select m, n order by n desc
|
||||
|
||||
@@ -11,7 +11,8 @@
|
||||
*/
|
||||
|
||||
import python
|
||||
private import LegacyPointsTo
|
||||
|
||||
from Module m, int n
|
||||
where n = m.getMetrics().getNumberOfLinesOfCode()
|
||||
from ModuleMetrics m, int n
|
||||
where n = m.getNumberOfLinesOfCode()
|
||||
select m, n order by n desc
|
||||
|
||||
@@ -10,8 +10,8 @@
|
||||
*/
|
||||
|
||||
import python
|
||||
private import LegacyPointsTo
|
||||
|
||||
from Module m, int n
|
||||
where
|
||||
n = m.getMetrics().getNumberOfLinesOfComments() + m.getMetrics().getNumberOfLinesOfDocStrings()
|
||||
from ModuleMetrics m, int n
|
||||
where n = m.getNumberOfLinesOfComments() + m.getNumberOfLinesOfDocStrings()
|
||||
select m, n order by n desc
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
*/
|
||||
|
||||
import python
|
||||
private import LegacyPointsTo
|
||||
|
||||
from FunctionMetrics func
|
||||
select func, func.getNumberOfCalls() as n order by n desc
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
*/
|
||||
|
||||
import python
|
||||
private import LegacyPointsTo
|
||||
|
||||
from FunctionMetrics func
|
||||
select func, func.getStatementNestingDepth() as n order by n desc
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user