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:
Taus
2025-12-05 14:24:41 +01:00
committed by GitHub
284 changed files with 690 additions and 430 deletions

View File

@@ -7,6 +7,7 @@
*/ */
import python import python
private import LegacyPointsTo
from Value len, CallNode call from Value len, CallNode call
where len.getName() = "len" and len.getACall() = call where len.getName() = "len" and len.getACall() = call

View File

@@ -11,6 +11,7 @@
*/ */
import python import python
private import LegacyPointsTo
from ClassObject sub, ClassObject base from ClassObject sub, ClassObject base
where where

View File

@@ -7,6 +7,7 @@
*/ */
import python import python
private import LegacyPointsTo
from AstNode call, PythonFunctionValue method from AstNode call, PythonFunctionValue method
where where

View File

@@ -7,6 +7,7 @@
*/ */
import python import python
private import LegacyPointsTo
from FunctionObject m, FunctionObject n from FunctionObject m, FunctionObject n
where m != n and m.getACallee() = n and n.getACallee() = m where m != n and m.getACallee() = n and n.getACallee() = m

View File

@@ -7,6 +7,7 @@
*/ */
import python import python
private import LegacyPointsTo
from FunctionObject override, FunctionObject base from FunctionObject override, FunctionObject base
where where

View File

@@ -7,6 +7,7 @@
*/ */
import python import python
private import LegacyPointsTo
from PythonFunctionValue f from PythonFunctionValue f
where f.getACall().getScope() = f.getScope() where f.getACall().getScope() = f.getScope()

View File

@@ -20,8 +20,21 @@
*/ */
private import python private import python
private import semmle.python.pointsto.PointsTo import semmle.python.pointsto.Base
private import semmle.python.objects.Modules 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. * An extension of `ControlFlowNode` that provides points-to predicates.
@@ -93,6 +106,24 @@ class ControlFlowNodeWithPointsTo extends ControlFlowNode {
// for that variable. // for that variable.
exists(SsaVariable v | v.getAUse() = this | varHasCompletePointsToSet(v)) 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. * An extension of `Expr` that provides points-to predicates.
*/ */
@@ -208,3 +278,155 @@ class ModuleWithPointsTo extends Module {
override string getAQlClass() { none() } 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
)
}

View File

@@ -4,7 +4,7 @@
import python import python
private import LegacyPointsTo private import LegacyPointsTo
import semmle.python.pointsto.PointsTo private import semmle.python.types.ImportTime
import IDEContextual import IDEContextual
private newtype TDefinition = private newtype TDefinition =

View File

@@ -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.

View File

@@ -14,27 +14,27 @@ import semmle.python.Patterns
import semmle.python.Keywords import semmle.python.Keywords
import semmle.python.Comprehensions import semmle.python.Comprehensions
import semmle.python.Flow import semmle.python.Flow
import semmle.python.Metrics private import semmle.python.Metrics
import semmle.python.Constants import semmle.python.Constants
import semmle.python.Scope import semmle.python.Scope
import semmle.python.Comment import semmle.python.Comment
import semmle.python.GuardedControlFlow import semmle.python.GuardedControlFlow
import semmle.python.types.ImportTime private import semmle.python.types.ImportTime
import semmle.python.types.Object private import semmle.python.types.Object
import semmle.python.types.ClassObject private import semmle.python.types.ClassObject
import semmle.python.types.FunctionObject private import semmle.python.types.FunctionObject
import semmle.python.types.ModuleObject private import semmle.python.types.ModuleObject
import semmle.python.types.Version private import semmle.python.types.Version
import semmle.python.types.Descriptors private import semmle.python.types.Descriptors
import semmle.python.SSA import semmle.python.SSA
import semmle.python.SelfAttribute private import semmle.python.SelfAttribute
import semmle.python.types.Properties private import semmle.python.types.Properties
import semmle.python.xml.XML import semmle.python.xml.XML
import semmle.python.essa.Essa import semmle.python.essa.Essa
import semmle.python.pointsto.Base private import semmle.python.pointsto.Base
import semmle.python.pointsto.Context private import semmle.python.pointsto.Context
import semmle.python.pointsto.CallGraph private import semmle.python.pointsto.CallGraph
import semmle.python.objects.ObjectAPI private import semmle.python.objects.ObjectAPI
import semmle.python.Unit import semmle.python.Unit
import site import site
private import semmle.python.Overlay private import semmle.python.Overlay

View File

@@ -141,18 +141,12 @@ class Class extends Class_, Scope, AstNode {
/** Gets the metaclass expression */ /** Gets the metaclass expression */
Expr getMetaClass() { result = this.getParent().getMetaClass() } 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. */ /** Gets the nth base of this class definition. */
Expr getBase(int index) { result = this.getParent().getBase(index) } Expr getBase(int index) { result = this.getParent().getBase(index) }
/** Gets a base of this class definition. */ /** Gets a base of this class definition. */
Expr getABase() { result = this.getParent().getABase() } Expr getABase() { result = this.getParent().getABase() }
/** Gets the metrics for this class */
ClassMetrics getMetrics() { result = this }
/** /**
* Gets the qualified name for this class. * Gets the qualified name for this class.
* Should return the same name as the `__qualname__` attribute on classes in Python 3. * Should return the same name as the `__qualname__` attribute on classes in Python 3.

View File

@@ -240,17 +240,12 @@ class Bytes extends StringLiteral {
/* syntax: b"hello" */ /* syntax: b"hello" */
Bytes() { not this.isUnicode() } 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 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 * The following predicate help us match up a string/byte literals in the source
* which the equivalent object. * which the equivalent object.
*/ */
private string quotedString() { string quotedString() {
exists(string b_unquoted | b_unquoted = this.getS() | result = "b'" + b_unquoted + "'") 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. * Consists of string (both unicode and byte) literals and numeric literals.
*/ */
abstract class ImmutableLiteral extends Expr { abstract class ImmutableLiteral extends Expr {
abstract Object getLiteralObject();
abstract boolean booleanValue(); abstract boolean booleanValue();
} }
@@ -292,12 +285,6 @@ class IntegerLiteral extends Num {
override string toString() { result = "IntegerLiteral" } 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() { override boolean booleanValue() {
this.getValue() = 0 and result = false this.getValue() = 0 and result = false
or or
@@ -317,10 +304,6 @@ class FloatLiteral extends Num {
override string toString() { result = "FloatLiteral" } override string toString() { result = "FloatLiteral" }
override Object getLiteralObject() {
py_cobjecttypes(result, theFloatType()) and py_cobjectnames(result, this.getN())
}
override boolean booleanValue() { override boolean booleanValue() {
this.getValue() = 0.0 and result = false this.getValue() = 0.0 and result = false
or or
@@ -343,10 +326,6 @@ class ImaginaryLiteral extends Num {
override string toString() { result = "ImaginaryLiteral" } override string toString() { result = "ImaginaryLiteral" }
override Object getLiteralObject() {
py_cobjecttypes(result, theComplexType()) and py_cobjectnames(result, this.getN())
}
override boolean booleanValue() { override boolean booleanValue() {
this.getValue() = 0.0 and result = false this.getValue() = 0.0 and result = false
or or
@@ -365,11 +344,6 @@ class NegativeIntegerLiteral extends ImmutableLiteral, UnaryExpr {
override boolean booleanValue() { result = this.getOperand().(IntegerLiteral).booleanValue() } 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 * Gets the (integer) value of this constant. Will not return a result if the value does not fit into
* a 32 bit signed value * a 32 bit signed value
@@ -385,11 +359,6 @@ class Unicode extends StringLiteral {
/* syntax: "hello" */ /* syntax: "hello" */
Unicode() { this.isUnicode() } Unicode() { this.isUnicode() }
override Object getLiteralObject() {
py_cobjecttypes(result, theUnicodeType()) and
py_cobjectnames(result, this.quotedString())
}
/** /**
* Gets the quoted representation fo this string. * Gets the quoted representation fo this string.
* *
@@ -593,12 +562,11 @@ class StringLiteral extends Str_, ImmutableLiteral {
this.getText() != "" and result = true this.getText() != "" and result = true
} }
override Object getLiteralObject() { none() }
override string toString() { result = "StringLiteral" } 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() | exists(Variable v | py_variables(v, n) and id = v.getId() |
id = "True" or id = "False" or id = "None" id = "True" or id = "False" or id = "None"
) )
@@ -627,8 +595,6 @@ class True extends BooleanLiteral {
/* syntax: True */ /* syntax: True */
True() { name_consts(this, "True") } True() { name_consts(this, "True") }
override Object getLiteralObject() { name_consts(this, "True") and result = theTrueObject() }
override boolean booleanValue() { result = true } override boolean booleanValue() { result = true }
} }
@@ -637,8 +603,6 @@ class False extends BooleanLiteral {
/* syntax: False */ /* syntax: False */
False() { name_consts(this, "False") } False() { name_consts(this, "False") }
override Object getLiteralObject() { name_consts(this, "False") and result = theFalseObject() }
override boolean booleanValue() { result = false } override boolean booleanValue() { result = false }
} }
@@ -647,8 +611,6 @@ class None extends NameConstant {
/* syntax: None */ /* syntax: None */
None() { name_consts(this, "None") } None() { name_consts(this, "None") }
override Object getLiteralObject() { name_consts(this, "None") and result = theNoneObject() }
override boolean booleanValue() { result = false } override boolean booleanValue() { result = false }
} }

View File

@@ -190,24 +190,6 @@ class ControlFlowNode extends @py_flow_node {
/** Whether this node is a normal (non-exceptional) exit */ /** Whether this node is a normal (non-exceptional) exit */
predicate isNormalExit() { py_scope_flow(this, _, 0) or py_scope_flow(this, _, 2) } 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. */ /** Whether this strictly dominates other. */
pragma[inline] pragma[inline]
predicate strictlyDominates(ControlFlowNode other) { predicate strictlyDominates(ControlFlowNode other) {
@@ -901,6 +883,58 @@ class StarredNode extends ControlFlowNode {
ControlFlowNode getValue() { toAst(result) = toAst(this).(Starred).getValue() } 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 module Scopes {
private predicate fast_local(NameNode n) { private predicate fast_local(NameNode n) {
exists(FastLocalVariable v | 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 */ /** Gets the last node in this basic block */
ControlFlowNode getLastNode() { 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. */ /** Holds if this basic block strictly reaches the other. Is the start of other reachable from the end of this. */
cached cached
predicate strictlyReaches(BasicBlock other) { 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. */ /** 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) } 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 * Gets the `ConditionBlock`, if any, that controls this block and
* does not control any other `ConditionBlock`s that control this block. * 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; private class ControlFlowNodeAlias = ControlFlowNode;
final private class FinalBasicBlock = BasicBlock; final private class FinalBasicBlock = BasicBlock;

View File

@@ -84,12 +84,6 @@ class Function extends Function_, Scope, AstNode {
/** Gets the name used to define this function */ /** Gets the name used to define this function */
override string getName() { result = Function_.super.getName() } 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. * 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. * Note that generator and async functions are not procedures as they return generators and coroutines respectively.

View File

@@ -29,9 +29,9 @@ class FunctionMetrics extends Function {
*/ */
int getCyclomaticComplexity() { int getCyclomaticComplexity() {
exists(int e, int n | 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 = e =
count(BasicBlock b1, BasicBlock b2 | count(BasicBlockWithPointsTo b1, BasicBlockWithPointsTo b2 |
b1 = this.getABasicBlock() and b1 = this.getABasicBlock() and
b1.likelyReachable() and b1.likelyReachable() and
b2 = this.getABasicBlock() and b2 = this.getABasicBlock() and

View File

@@ -86,9 +86,6 @@ class Module extends Module_, Scope, AstNode {
result = this.getName().regexpReplaceAll("\\.[^.]*$", "") result = this.getName().regexpReplaceAll("\\.[^.]*$", "")
} }
/** Gets the metrics for this module */
ModuleMetrics getMetrics() { result = this }
string getAnImportedModuleName() { string getAnImportedModuleName() {
exists(Import i | i.getEnclosingModule() = this | result = i.getAnImportedModuleName()) exists(Import i | i.getEnclosingModule() = this | result = i.getAnImportedModuleName())
or or

View File

@@ -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 */ /** Gets a variable that ultimately defines this variable and is not itself defined by another variable */
SsaVariable getAnUltimateDefinition() { SsaVariable getAnUltimateDefinition() {
result = this and not exists(this.getAPhiInput()) result = this and not exists(this.getAPhiInput())
@@ -85,17 +77,11 @@ class SsaVariable extends @py_ssa_var {
string getId() { result = this.getVariable().getId() } string getId() { result = this.getVariable().getId() }
/** Gets the incoming edges for a Phi node. */ /** Gets the incoming edges for a Phi node. */
private BasicBlock getAPredecessorBlockForPhi() { BasicBlock getAPredecessorBlockForPhi() {
exists(this.getAPhiInput()) and exists(this.getAPhiInput()) and
result.getASuccessor() = this.getDefinition().getBasicBlock() 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 */ /** Whether it is possible to reach a use of this variable without passing a definition */
predicate reachableWithoutDefinition() { predicate reachableWithoutDefinition() {
not exists(this.getDefinition()) and not py_ssa_phi(this, _) 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. * Gets the global variable that is accessed if this local is undefined.
* Only applies to local variables in class scopes. * 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 */ /** An SSA variable that is backed by a global variable */
class GlobalSsaVariable extends EssaVariable { class GlobalSsaVariable extends EssaVariable {
GlobalSsaVariable() { this.getSourceVariable() instanceof GlobalVariable } GlobalSsaVariable() { this.getSourceVariable() instanceof GlobalVariable }

View File

@@ -5,6 +5,7 @@
import python import python
private import semmle.python.pointsto.Filters private import semmle.python.pointsto.Filters
private import LegacyPointsTo
/** /**
* An attribute access where the left hand side of the attribute expression * An attribute access where the left hand side of the attribute expression

View File

@@ -1,9 +1,10 @@
/** This module provides an API for attribute reads and writes. */ /** This module provides an API for attribute reads and writes. */
private import python
import DataFlowUtil import DataFlowUtil
import DataFlowPublic import DataFlowPublic
private import DataFlowPrivate 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. * A data flow node that reads or writes an attribute of an object.
@@ -134,8 +135,12 @@ private class BuiltInCallNode extends CallNode {
BuiltInCallNode() { BuiltInCallNode() {
// TODO disallow instances where the name of the built-in may refer to an in-scope variable of that name. // 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 exists(NameNode id |
name = any(Builtin b).getName() 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` */ /** Gets the name of the built-in function that is called at this `CallNode` */

View File

@@ -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.internal.ImportStar
private import semmle.python.dataflow.new.TypeTracking private import semmle.python.dataflow.new.TypeTracking
private import semmle.python.dataflow.new.internal.DataFlowPrivate 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 * Python modules and the way imports are resolved are... complicated. Here's a crash course in how

View File

@@ -1,6 +1,6 @@
import python import python
import semmle.python.dataflow.TaintTracking import semmle.python.dataflow.TaintTracking
private import semmle.python.objects.ObjectInternal private import LegacyPointsTo
private import semmle.python.dataflow.Implementation private import semmle.python.dataflow.Implementation
module TaintTracking { module TaintTracking {

View File

@@ -1,4 +1,5 @@
import python import python
private import LegacyPointsTo
import semmle.python.dataflow.TaintTracking import semmle.python.dataflow.TaintTracking
class OpenFile extends TaintKind { class OpenFile extends TaintKind {

View File

@@ -1,7 +1,6 @@
import python import python
private import LegacyPointsTo private import LegacyPointsTo
import semmle.python.dataflow.TaintTracking import semmle.python.dataflow.TaintTracking
private import semmle.python.objects.ObjectInternal
private import semmle.python.pointsto.Filters as Filters private import semmle.python.pointsto.Filters as Filters
import semmle.python.dataflow.Legacy import semmle.python.dataflow.Legacy
@@ -257,7 +256,7 @@ class TaintTrackingImplementation extends string instanceof TaintTracking::Confi
TaintKind kind, string edgeLabel TaintKind kind, string edgeLabel
) { ) {
this.unprunedStep(src, node, context, path, kind, edgeLabel) and this.unprunedStep(src, node, context, path, kind, edgeLabel) and
node.getBasicBlock().likelyReachable() and node.getBasicBlock().(BasicBlockWithPointsTo).likelyReachable() and
not super.isBarrier(node) and not super.isBarrier(node) and
( (
not path = TNoAttribute() not path = TNoAttribute()
@@ -685,7 +684,9 @@ private class EssaTaintTracking extends string instanceof TaintTracking::Configu
TaintTrackingNode src, PhiFunction defn, TaintTrackingContext context, AttributePath path, TaintTrackingNode src, PhiFunction defn, TaintTrackingContext context, AttributePath path,
TaintKind kind 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 src = TTaintTrackingNode_(srcnode, context, path, kind, this) and
defn = phi.asVariable().getDefinition() and defn = phi.asVariable().getDefinition() and
predvar = defn.getInput(pred) and predvar = defn.getInput(pred) and

View File

@@ -9,9 +9,7 @@
*/ */
import python import python
private import semmle.python.pointsto.PointsTo private import LegacyPointsTo
private import semmle.python.pointsto.PointsToContext
private import semmle.python.objects.ObjectInternal
/** A state that should be tracked. */ /** A state that should be tracked. */
abstract class TrackableState extends string { abstract class TrackableState extends string {

View File

@@ -89,7 +89,6 @@
import python import python
private import LegacyPointsTo private import LegacyPointsTo
private import semmle.python.pointsto.Filters as Filters private import semmle.python.pointsto.Filters as Filters
private import semmle.python.objects.ObjectInternal
private import semmle.python.dataflow.Implementation private import semmle.python.dataflow.Implementation
import semmle.python.dataflow.Configuration import semmle.python.dataflow.Configuration

View File

@@ -1,4 +1,5 @@
import semmle.python.dependencies.Dependencies import semmle.python.dependencies.Dependencies
private import LegacyPointsTo
/** /**
* A library describing an abstract mechanism for representing dependency categories. * A library describing an abstract mechanism for representing dependency categories.

View File

@@ -1,6 +1,7 @@
import python import python
import semmle.python.dependencies.Dependencies import semmle.python.dependencies.Dependencies
import semmle.python.dependencies.DependencyKind import semmle.python.dependencies.DependencyKind
private import LegacyPointsTo
/** /**
* Combine the source-file and package into a single string: * Combine the source-file and package into a single string:

View File

@@ -1,5 +1,4 @@
import python import python
/* /*
* Classification of variables. These should be non-overlapping and complete. * 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. * 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. */ /** A source language variable, to be converted into a set of SSA variables. */
abstract class SsaSourceVariable extends @py_variable { abstract class SsaSourceVariable extends @py_variable {
SsaSourceVariable() { SsaSourceVariable() {
@@ -274,6 +276,17 @@ class ModuleVariable extends SsaSourceVariable instanceof GlobalVariable {
override CallNode redefinedAtCallSite() { none() } 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 { class NonEscapingGlobalVariable extends ModuleVariable {
NonEscapingGlobalVariable() { NonEscapingGlobalVariable() {
this instanceof GlobalVariable and this instanceof GlobalVariable and

View File

@@ -6,6 +6,7 @@ import python
private import SsaCompute private import SsaCompute
import semmle.python.essa.Definitions import semmle.python.essa.Definitions
private import semmle.python.internal.CachedStages private import semmle.python.internal.CachedStages
private import semmle.python.essa.SsaDefinitions
/** An (enhanced) SSA variable derived from `SsaSourceVariable`. */ /** An (enhanced) SSA variable derived from `SsaSourceVariable`. */
class EssaVariable extends TEssaDefinition { class EssaVariable extends TEssaDefinition {

View File

@@ -6,6 +6,13 @@
import python import python
private import semmle.python.internal.CachedStages 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 cached
module SsaSource { module SsaSource {
/** Holds if `v` is used as the receiver in a method call. */ /** Holds if `v` is used as the receiver in a method call. */

View File

@@ -1,7 +1,7 @@
/** Utilities for handling the zope libraries */ /** Utilities for handling the zope libraries */
import python import python
private import semmle.python.pointsto.PointsTo private import LegacyPointsTo
/** A method that belongs to a sub-class of `zope.interface.Interface` */ /** A method that belongs to a sub-class of `zope.interface.Interface` */
class ZopeInterfaceMethodValue extends PythonFunctionValue { class ZopeInterfaceMethodValue extends PythonFunctionValue {

View File

@@ -5,6 +5,7 @@ private import semmle.python.pointsto.PointsTo
private import semmle.python.pointsto.MRO private import semmle.python.pointsto.MRO
private import semmle.python.pointsto.PointsToContext private import semmle.python.pointsto.PointsToContext
private import semmle.python.types.Builtins private import semmle.python.types.Builtins
private import semmle.python.objects.ObjectAPI
/** /**
* A constant. * A constant.

View File

@@ -5,6 +5,7 @@ private import semmle.python.pointsto.PointsTo
private import semmle.python.pointsto.PointsToContext private import semmle.python.pointsto.PointsToContext
private import semmle.python.pointsto.MRO private import semmle.python.pointsto.MRO
private import semmle.python.types.Builtins private import semmle.python.types.Builtins
private import semmle.python.pointsto.Context
/** A property object. */ /** A property object. */
class PropertyInternal extends ObjectInternal, TProperty { class PropertyInternal extends ObjectInternal, TProperty {

View File

@@ -5,6 +5,8 @@ private import semmle.python.pointsto.PointsTo
private import semmle.python.pointsto.MRO private import semmle.python.pointsto.MRO
private import semmle.python.pointsto.PointsToContext private import semmle.python.pointsto.PointsToContext
private import semmle.python.types.Builtins private import semmle.python.types.Builtins
private import semmle.python.pointsto.Context
private import semmle.python.pointsto.Base
/** A class representing instances */ /** A class representing instances */
abstract class InstanceObject extends ObjectInternal { abstract class InstanceObject extends ObjectInternal {

View File

@@ -5,6 +5,7 @@ private import semmle.python.pointsto.PointsTo
private import semmle.python.pointsto.MRO private import semmle.python.pointsto.MRO
private import semmle.python.pointsto.PointsToContext private import semmle.python.pointsto.PointsToContext
private import semmle.python.types.Builtins private import semmle.python.types.Builtins
private import semmle.python.types.ImportTime
/** A class representing modules */ /** A class representing modules */
abstract class ModuleObjectInternal extends ObjectInternal { abstract class ModuleObjectInternal extends ObjectInternal {

View File

@@ -6,9 +6,6 @@
import python import python
private import LegacyPointsTo private import LegacyPointsTo
private import TObject 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.pointsto.MRO
private import semmle.python.types.Builtins private import semmle.python.types.Builtins

View File

@@ -6,6 +6,7 @@ private import semmle.python.objects.ObjectInternal
private import semmle.python.pointsto.PointsTo private import semmle.python.pointsto.PointsTo
private import semmle.python.pointsto.PointsToContext private import semmle.python.pointsto.PointsToContext
private import semmle.python.internal.CachedStages private import semmle.python.internal.CachedStages
private import semmle.python.pointsto.Context
/** /**
* Internal type backing `ObjectInternal` and `Value` * Internal type backing `ObjectInternal` and `Value`

View File

@@ -12,6 +12,8 @@ import python
import semmle.python.essa.SsaDefinitions import semmle.python.essa.SsaDefinitions
private import semmle.python.types.Builtins private import semmle.python.types.Builtins
private import semmle.python.internal.CachedStages 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 * 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()) 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 */ /** Gets the pseudo-object representing the value referred to by an undefined variable */
Object undefinedVariable() { py_special_objects(result, "_semmle_undefined_value") } Object undefinedVariable() { py_special_objects(result, "_semmle_undefined_value") }

View File

@@ -11,6 +11,8 @@
import python import python
private import semmle.python.pointsto.PointsToContext private import semmle.python.pointsto.PointsToContext
private import semmle.python.types.FunctionObject
private import semmle.python.pointsto.Context
private newtype TTInvocation = private newtype TTInvocation =
TInvocation(FunctionObject f, Context c) { TInvocation(FunctionObject f, Context c) {

View File

@@ -6,7 +6,13 @@ private import semmle.python.pointsto.PointsToContext
private import semmle.python.pointsto.MRO private import semmle.python.pointsto.MRO
private import semmle.python.types.Builtins private import semmle.python.types.Builtins
private import semmle.python.types.Extensions private import semmle.python.types.Extensions
private import semmle.python.pointsto.Context
private import semmle.python.internal.CachedStages 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 */ /* Use this version for speed */
class CfgOrigin extends @py_object { class CfgOrigin extends @py_object {

View File

@@ -1,6 +1,8 @@
import python import python
private import semmle.python.pointsto.PointsTo private import semmle.python.pointsto.PointsTo
private import semmle.python.objects.ObjectInternal 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, * A note on 'cost'. Cost doesn't represent the cost to compute,

View File

@@ -1,4 +1,5 @@
import python import python
private import LegacyPointsTo
class Builtin extends @py_cobject { class Builtin extends @py_cobject {
Builtin() { Builtin() {

View File

@@ -6,6 +6,7 @@ private import semmle.python.pointsto.PointsTo
private import semmle.python.pointsto.MRO private import semmle.python.pointsto.MRO
private import semmle.python.types.Builtins private import semmle.python.types.Builtins
private import semmle.python.objects.ObjectInternal private import semmle.python.objects.ObjectInternal
private import semmle.python.types.ImportTime
/** /**
* A class whose instances represents Python classes. * 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 */ /** 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) */ /** Returns an attribute declared on this class (not on a super-class) */
Object declaredAttribute(string name) { Object declaredAttribute(string name) {

View File

@@ -1,5 +1,8 @@
import python import python
private import semmle.python.objects.ObjectInternal 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) */ /** A class method object. Either a decorated function or an explicit call to classmethod(f) */
class ClassMethodObject extends Object { class ClassMethodObject extends Object {

View File

@@ -80,7 +80,7 @@ class RaisingNode extends ControlFlowNode {
or or
this.getNode() instanceof Print and result = theIOErrorType() this.getNode() instanceof Print and result = theIOErrorType()
or or
exists(ExceptFlowNode except | exists(ExceptFlowNodeWithPointsTo except |
except = this.getAnExceptionalSuccessor() and except = this.getAnExceptionalSuccessor() and
except.handles_objectapi(result) and except.handles_objectapi(result) and
result = this.innateException_objectapi() result = this.innateException_objectapi()
@@ -107,7 +107,7 @@ class RaisingNode extends ControlFlowNode {
or or
this.getNode() instanceof Print and result = ClassValue::ioError() this.getNode() instanceof Print and result = ClassValue::ioError()
or or
exists(ExceptFlowNode except | exists(ExceptFlowNodeWithPointsTo except |
except = this.getAnExceptionalSuccessor() and except = this.getAnExceptionalSuccessor() and
except.handles(result) and except.handles(result) and
result = this.innateException() result = this.innateException()
@@ -200,8 +200,8 @@ class RaisingNode extends ControlFlowNode {
succ = this.getAnExceptionalSuccessor() and succ = this.getAnExceptionalSuccessor() and
( (
/* An 'except' that handles raised and there is no more previous handler */ /* An 'except' that handles raised and there is no more previous handler */
succ.(ExceptFlowNode).handles_objectapi(raised) and succ.(ExceptFlowNodeWithPointsTo).handles_objectapi(raised) and
not exists(ExceptFlowNode other, StmtList s, int i, int j | not exists(ExceptFlowNodeWithPointsTo other, StmtList s, int i, int j |
not other = succ and not other = succ and
other.handles_objectapi(raised) and other.handles_objectapi(raised) and
s.getItem(i) = succ.getNode() and s.getItem(i) = succ.getNode() and
@@ -211,7 +211,7 @@ class RaisingNode extends ControlFlowNode {
) )
or or
/* Any successor that is not an 'except', provided that 'raised' is not handled by a different successor. */ /* 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 not succ instanceof ExceptFlowNode
) )
} }
@@ -223,8 +223,8 @@ class RaisingNode extends ControlFlowNode {
succ = this.getAnExceptionalSuccessor() and succ = this.getAnExceptionalSuccessor() and
( (
/* An 'except' that handles raised and there is no more previous handler */ /* An 'except' that handles raised and there is no more previous handler */
succ.(ExceptFlowNode).handles(raised) and succ.(ExceptFlowNodeWithPointsTo).handles(raised) and
not exists(ExceptFlowNode other, StmtList s, int i, int j | not exists(ExceptFlowNodeWithPointsTo other, StmtList s, int i, int j |
not other = succ and not other = succ and
other.handles(raised) and other.handles(raised) and
s.getItem(i) = succ.getNode() and s.getItem(i) = succ.getNode() and
@@ -234,7 +234,7 @@ class RaisingNode extends ControlFlowNode {
) )
or or
/* Any successor that is not an 'except', provided that 'raised' is not handled by a different successor. */ /* 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 not succ instanceof ExceptFlowNode
) )
} }
@@ -248,7 +248,7 @@ class RaisingNode extends ControlFlowNode {
raised.isLegalExceptionType() and raised.isLegalExceptionType() and
raised = this.getARaisedType_objectapi() and raised = this.getARaisedType_objectapi() and
this.isExceptionalExit(s) 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.isLegalExceptionType() and
raised = this.getARaisedType() and raised = this.getARaisedType() and
this.isExceptionalExit(s) 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. */ /** An extension of `ExceptFlowNode` that provides points-to related methods. */
class ExceptFlowNode extends ControlFlowNode { class ExceptFlowNodeWithPointsTo extends ExceptFlowNode {
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()
)
}
private predicate handledObject_objectapi(Object obj, ClassObject cls, ControlFlowNode origin) { private predicate handledObject_objectapi(Object obj, ClassObject cls, ControlFlowNode origin) {
this.getType().refersTo(obj, cls, origin) this.getType().(ControlFlowNodeWithPointsTo).refersTo(obj, cls, origin)
or or
exists(Object tup | this.handledObject_objectapi(tup, theTupleType(), _) | exists(Object tup | this.handledObject_objectapi(tup, theTupleType(), _) |
element_from_tuple_objectapi(tup).refersTo(obj, cls, origin) 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) { private predicate handledObject(Value val, ClassValue cls, ControlFlowNode origin) {
val.getClass() = cls and val.getClass() = cls and
( (
this.getType().pointsTo(val, origin) this.getType().(ControlFlowNodeWithPointsTo).pointsTo(val, origin)
or or
exists(TupleValue tup | this.handledObject(tup, ClassValue::tuple(), _) | exists(TupleValue tup | this.handledObject(tup, ClassValue::tuple(), _) |
val = tup.getItem(_) and origin = val.getOrigin() 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) { private ControlFlowNodeWithPointsTo element_from_tuple_objectapi(Object tuple) {
exists(Tuple t | t = tuple.getOrigin() and result = t.getAnElt().getAFlowNode()) exists(Tuple t | t = tuple.getOrigin() and result = t.getAnElt().getAFlowNode())
} }

View File

@@ -15,7 +15,8 @@ private import semmle.python.pointsto.PointsTo
private import semmle.python.pointsto.PointsToContext private import semmle.python.pointsto.PointsToContext
private import semmle.python.objects.TObject private import semmle.python.objects.TObject
/* Make ObjectInternal visible to save extra imports in user code */ /* 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 { abstract class PointsToExtension extends @py_flow_node {
string toString() { result = "PointsToExtension with missing toString" } string toString() { result = "PointsToExtension with missing toString" }

View File

@@ -1,10 +1,7 @@
import python import python
private import LegacyPointsTo private import LegacyPointsTo
import semmle.python.types.Exceptions
private import semmle.python.pointsto.PointsTo
private import semmle.python.objects.Callables private import semmle.python.objects.Callables
private import semmle.python.libraries.Zope private import semmle.python.libraries.Zope
private import semmle.python.objects.ObjectInternal
private import semmle.python.types.Builtins private import semmle.python.types.Builtins
/** A function object, whether written in Python or builtin */ /** A function object, whether written in Python or builtin */

View File

@@ -1,4 +1,5 @@
import python import python
private import semmle.python.types.ModuleObject
private predicate is_normal_module(ModuleObject m) { private predicate is_normal_module(ModuleObject m) {
m instanceof BuiltinModuleObject m instanceof BuiltinModuleObject

View File

@@ -2,6 +2,9 @@ import python
private import semmle.python.pointsto.PointsTo private import semmle.python.pointsto.PointsTo
private import semmle.python.objects.ObjectInternal private import semmle.python.objects.ObjectInternal
private import semmle.python.types.ModuleKind 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 { abstract class ModuleObject extends Object {
ModuleValue theModule() { ModuleValue theModule() {

View File

@@ -1,6 +1,5 @@
import python import python
private import LegacyPointsTo private import LegacyPointsTo
private import semmle.python.objects.ObjectInternal
private import semmle.python.types.Builtins private import semmle.python.types.Builtins
private import semmle.python.internal.CachedStages private import semmle.python.internal.CachedStages

View File

@@ -1,8 +1,5 @@
import python import python
private import LegacyPointsTo 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) { predicate string_attribute_all(ControlFlowNodeWithPointsTo n, string attr) {
(n.getNode() instanceof Unicode or n.getNode() instanceof Bytes) and (n.getNode() instanceof Unicode or n.getNode() instanceof Bytes) and

View File

@@ -1,5 +1,5 @@
import python import python
private import semmle.python.pointsto.PointsTo private import LegacyPointsTo
/** A helper class for UndefinedClassAttribute.ql and MaybeUndefinedClassAttribute.ql */ /** A helper class for UndefinedClassAttribute.ql and MaybeUndefinedClassAttribute.ql */
class CheckClass extends ClassObject { class CheckClass extends ClassObject {

View File

@@ -12,6 +12,7 @@
*/ */
import python import python
private import LegacyPointsTo
predicate does_nothing(PyFunctionObject f) { predicate does_nothing(PyFunctionObject f) {
not exists(Stmt s | s.getScope() = f.getFunction() | not exists(Stmt s | s.getScope() = f.getFunction() |

View File

@@ -13,6 +13,7 @@
import python import python
import Equality import Equality
private import LegacyPointsTo
predicate class_stores_to_attribute(ClassValue cls, SelfAttributeStore store, string name) { predicate class_stores_to_attribute(ClassValue cls, SelfAttributeStore store, string name) {
exists(FunctionValue f | exists(FunctionValue f |

View File

@@ -12,6 +12,7 @@
*/ */
import python import python
private import LegacyPointsTo
ClassObject left_base(ClassObject type, ClassObject base) { ClassObject left_base(ClassObject type, ClassObject base) {
exists(int i | i > 0 and type.getBaseType(i) = base and result = type.getBaseType(i - 1)) exists(int i | i > 0 and type.getBaseType(i) = base and result = type.getBaseType(i - 1))

View File

@@ -12,6 +12,7 @@
import python import python
import ClassAttributes import ClassAttributes
private import LegacyPointsTo
predicate guarded_by_other_attribute(SelfAttributeRead a, CheckClass c) { predicate guarded_by_other_attribute(SelfAttributeRead a, CheckClass c) {
c.sometimesDefines(a.getName()) and c.sometimesDefines(a.getName()) and

View File

@@ -12,6 +12,7 @@
*/ */
import python import python
private import LegacyPointsTo
predicate mutates_descriptor(ClassObject cls, SelfAttributeStore s) { predicate mutates_descriptor(ClassObject cls, SelfAttributeStore s) {
cls.isDescriptorType() and cls.isDescriptorType() and

View File

@@ -12,6 +12,7 @@
*/ */
import python import python
private import LegacyPointsTo
class InitCallStmt extends ExprStmt { class InitCallStmt extends ExprStmt {
InitCallStmt() { InitCallStmt() {

View File

@@ -11,6 +11,7 @@
*/ */
import python import python
private import LegacyPointsTo
from PropertyObject prop, ClassObject cls from PropertyObject prop, ClassObject cls
where cls.declaredAttribute(_) = prop and not cls.failedInference() and not cls.isNewStyle() where cls.declaredAttribute(_) = prop and not cls.failedInference() and not cls.isNewStyle()

View File

@@ -14,6 +14,7 @@
*/ */
import python import python
private import LegacyPointsTo
from ClassValue c from ClassValue c
where not c.isBuiltin() and not c.isContextManager() and exists(c.declaredAttribute("__del__")) where not c.isBuiltin() and not c.isContextManager() and exists(c.declaredAttribute("__del__"))

View File

@@ -12,6 +12,7 @@
*/ */
import python import python
private import LegacyPointsTo
from ClassObject c from ClassObject c
where not c.isNewStyle() and c.declaresAttribute("__slots__") and not c.failedInference() where not c.isNewStyle() and c.declaresAttribute("__slots__") and not c.failedInference()

View File

@@ -11,6 +11,7 @@
*/ */
import python import python
private import LegacyPointsTo
predicate uses_of_super_in_old_style_class(Call s) { predicate uses_of_super_in_old_style_class(Call s) {
exists(Function f, ClassObject c | exists(Function f, ClassObject c |

View File

@@ -12,6 +12,7 @@
import python import python
import ClassAttributes import ClassAttributes
private import LegacyPointsTo
predicate undefined_class_attribute(SelfAttributeRead a, CheckClass c, int line, string name) { predicate undefined_class_attribute(SelfAttributeRead a, CheckClass c, int line, string name) {
name = a.getName() and name = a.getName() and

View File

@@ -13,6 +13,7 @@
*/ */
import python import python
private import LegacyPointsTo
predicate fewer_than_two_public_methods(Class cls, int methods) { predicate fewer_than_two_public_methods(Class cls, int methods) {
(methods = 0 or methods = 1) and (methods = 0 or methods = 1) and

View File

@@ -16,6 +16,7 @@
import python import python
import Expressions.CallArgs import Expressions.CallArgs
private import LegacyPointsTo
from Call call, ClassValue cls, string name, FunctionValue init from Call call, ClassValue cls, string name, FunctionValue init
where where

View File

@@ -15,6 +15,7 @@
import python import python
import Expressions.CallArgs import Expressions.CallArgs
private import LegacyPointsTo
from Call call, ClassValue cls, string too, string should, int limit, FunctionValue init from Call call, ClassValue cls, string too, string should, int limit, FunctionValue init
where where

View File

@@ -12,8 +12,9 @@
*/ */
import python 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 where
ex.handledException(t, c, origin) and ex.handledException(t, c, origin) and
( (

View File

@@ -14,6 +14,7 @@
import python import python
import Raising import Raising
import Exceptions.NotImplemented import Exceptions.NotImplemented
private import LegacyPointsTo
from Raise r, ClassValue t from Raise r, ClassValue t
where where

View File

@@ -13,7 +13,6 @@
import python import python
private import LegacyPointsTo private import LegacyPointsTo
import semmle.python.pointsto.PointsTo
predicate rhs_in_expr(ControlFlowNode rhs, Compare cmp) { predicate rhs_in_expr(ControlFlowNode rhs, Compare cmp) {
exists(Cmpop op, int i | cmp.getOp(i) = op and cmp.getComparator(i) = rhs.getNode() | exists(Cmpop op, int i | cmp.getOp(i) = op and cmp.getComparator(i) = rhs.getNode() |

View File

@@ -2,7 +2,6 @@
import python import python
private import LegacyPointsTo 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. */ /** 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) { predicate comparison_using_is(Compare comp, ControlFlowNode left, Cmpop op, ControlFlowNode right) {

View File

@@ -13,6 +13,7 @@
import python import python
import IsComparisons import IsComparisons
private import LegacyPointsTo
from Compare comp, Cmpop op, ClassValue c from Compare comp, Cmpop op, ClassValue c
where where

View File

@@ -1,6 +1,7 @@
/** Helper functions for queries that test redundant comparisons. */ /** Helper functions for queries that test redundant comparisons. */
import python import python
private import LegacyPointsTo
/** A comparison where the left and right hand sides appear to be identical. */ /** A comparison where the left and right hand sides appear to be identical. */
class RedundantComparison extends Compare { class RedundantComparison extends Compare {

View File

@@ -16,6 +16,7 @@
import python import python
import Expressions.CallArgs import Expressions.CallArgs
private import LegacyPointsTo
from Call call, FunctionObject func, string name from Call call, FunctionObject func, string name
where where

View File

@@ -15,7 +15,6 @@
import python import python
import LegacyPointsTo import LegacyPointsTo
import semmle.python.objects.ObjectInternal
import semmle.python.strings import semmle.python.strings
predicate string_format(BinaryExpr operation, StringLiteral str, Value args, AstNode origin) { predicate string_format(BinaryExpr operation, StringLiteral str, Value args, AstNode origin) {

View File

@@ -13,6 +13,7 @@
*/ */
import python import python
private import LegacyPointsTo
import CallArgs import CallArgs
from Call call, FunctionValue func, string too, string should, int limit from Call call, FunctionValue func, string too, string should, int limit

View File

@@ -12,6 +12,7 @@
*/ */
import python import python
private import LegacyPointsTo
predicate explicitly_returns_non_none(Function func) { predicate explicitly_returns_non_none(Function func) {
exists(Return return | exists(Return return |
@@ -21,7 +22,7 @@ predicate explicitly_returns_non_none(Function func) {
} }
predicate has_implicit_return(Function func) { predicate has_implicit_return(Function func) {
exists(ControlFlowNode fallthru | exists(ControlFlowNodeWithPointsTo fallthru |
fallthru = func.getFallthroughNode() and not fallthru.unlikelyReachable() fallthru = func.getFallthroughNode() and not fallthru.unlikelyReachable()
) )
or or

View File

@@ -10,6 +10,7 @@
*/ */
import python import python
private import LegacyPointsTo
predicate slice_method_name(string name) { predicate slice_method_name(string name) {
name = "__getslice__" or name = "__setslice__" or name = "__delslice__" name = "__getslice__" or name = "__setslice__" or name = "__delslice__"

View File

@@ -14,6 +14,7 @@
import python import python
import Expressions.CallArgs import Expressions.CallArgs
private import LegacyPointsTo
from Call call, FunctionValue func, FunctionValue overridden, string problem from Call call, FunctionValue func, FunctionValue overridden, string problem
where where

View File

@@ -14,6 +14,7 @@
import python import python
import Expressions.CallArgs import Expressions.CallArgs
private import LegacyPointsTo
from Call call, FunctionValue func, FunctionValue overriding, string problem from Call call, FunctionValue func, FunctionValue overriding, string problem
where where

View File

@@ -12,6 +12,7 @@
*/ */
import python import python
private import LegacyPointsTo
from ClassValue iterable, FunctionValue iter, ClassValue iterator from ClassValue iterable, FunctionValue iter, ClassValue iterator
where where

View File

@@ -12,11 +12,12 @@
*/ */
import python import python
private import LegacyPointsTo
from FunctionValue method from FunctionValue method
where where
exists(ClassValue c | exists(ClassValue c |
c.declaredAttribute("__del__") = method and c.declaredAttribute("__del__") = method and
method.getScope().getMetrics().getCyclomaticComplexity() > 3 method.getScope().(FunctionMetrics).getCyclomaticComplexity() > 3
) )
select method, "Overly complex '__del__' method." select method, "Overly complex '__del__' method."

View File

@@ -14,7 +14,7 @@
*/ */
import python import python
import semmle.python.objects.Callables private import LegacyPointsTo
predicate meaningful_return_value(Expr val) { predicate meaningful_return_value(Expr val) {
val instanceof Name val instanceof Name

View File

@@ -1,5 +1,6 @@
import python import python
private import LegacyPointsTo private import LegacyPointsTo
private import semmle.python.types.ImportTime
predicate is_import_time(Stmt s) { not s.getScope+() instanceof Function } predicate is_import_time(Stmt s) { not s.getScope+() instanceof Function }

View File

@@ -13,6 +13,7 @@
import python import python
import Cyclic import Cyclic
private import LegacyPointsTo
from ModuleValue m1, ModuleValue m2, Stmt imp from ModuleValue m1, ModuleValue m2, Stmt imp
where where

View File

@@ -12,6 +12,7 @@
*/ */
import python import python
private import LegacyPointsTo
predicate modules_imports_itself(ImportingStmt i, ModuleValue m) { predicate modules_imports_itself(ImportingStmt i, ModuleValue m) {
i.getEnclosingModule() = m.getScope() and i.getEnclosingModule() = m.getScope() and

View File

@@ -14,6 +14,7 @@
import python import python
import Cyclic import Cyclic
private import LegacyPointsTo
// This is a potentially crashing bug if // 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) // 1. the imports in the whole cycle are lexically outside a def (and so executed at import time)

View File

@@ -13,6 +13,8 @@
*/ */
import python import python
private import LegacyPointsTo
private import semmle.python.types.ImportTime
predicate import_star(ImportStar imp, ModuleValue exporter) { predicate import_star(ImportStar imp, ModuleValue exporter) {
exporter.importedAs(imp.getImportedModuleName()) exporter.importedAs(imp.getImportedModuleName())

View File

@@ -10,6 +10,7 @@
*/ */
import python import python
private import LegacyPointsTo
from Function f from FunctionMetrics f
select f, f.getMetrics().getNumberOfLinesOfCode() as n order by n desc select f, f.getNumberOfLinesOfCode() as n order by n desc

View File

@@ -11,6 +11,7 @@
*/ */
import python import python
private import LegacyPointsTo
from ClassMetrics cls from ClassMetrics cls
select cls, cls.getAfferentCoupling() as n order by n desc select cls, cls.getAfferentCoupling() as n order by n desc

View File

@@ -11,6 +11,7 @@
*/ */
import python import python
private import LegacyPointsTo
from ClassMetrics cls from ClassMetrics cls
select cls, cls.getEfferentCoupling() as n order by n desc select cls, cls.getEfferentCoupling() as n order by n desc

View File

@@ -12,8 +12,10 @@
*/ */
import python import python
private import LegacyPointsTo
from Module m, ModuleMetrics mm from ModuleMetrics mm
where mm = m.getMetrics() and mm.getNumberOfLines() > 0 where mm.getNumberOfLines() > 0
select m, 100.0 * (mm.getNumberOfLinesOfComments().(float) / mm.getNumberOfLines().(float)) as ratio select mm,
100.0 * (mm.getNumberOfLinesOfComments().(float) / mm.getNumberOfLines().(float)) as ratio
order by ratio desc order by ratio desc

View File

@@ -13,7 +13,8 @@
*/ */
import python import python
private import LegacyPointsTo
from Function func, int complexity from FunctionMetrics func, int complexity
where complexity = func.getMetrics().getCyclomaticComplexity() where complexity = func.getCyclomaticComplexity()
select func, complexity order by complexity desc select func, complexity order by complexity desc

View File

@@ -8,6 +8,7 @@
import python import python
import semmle.python.dependencies.TechInventory import semmle.python.dependencies.TechInventory
private import LegacyPointsTo
/* /*
* This query creates the source links for the ExternalDependencies.ql query. * This query creates the source links for the ExternalDependencies.ql query.

View File

@@ -11,6 +11,7 @@
*/ */
import python import python
private import LegacyPointsTo
from ModuleValue m, int n from ModuleValue m, int n
where n = count(ModuleValue imp | imp = m.getAnImportedModule()) where n = count(ModuleValue imp | imp = m.getAnImportedModule())

View File

@@ -11,9 +11,10 @@
*/ */
import python import python
private import LegacyPointsTo
from Module m, ModuleMetrics mm from ModuleMetrics mm
where mm = m.getMetrics() and mm.getNumberOfLines() > 0 where mm.getNumberOfLines() > 0
select m, select mm,
100.0 * (mm.getNumberOfLinesOfDocStrings().(float) / mm.getNumberOfLines().(float)) as ratio 100.0 * (mm.getNumberOfLinesOfDocStrings().(float) / mm.getNumberOfLines().(float)) as ratio
order by ratio desc order by ratio desc

View File

@@ -9,7 +9,8 @@
*/ */
import python import python
private import LegacyPointsTo
from Module m, int n from ModuleMetrics m, int n
where n = m.getMetrics().getNumberOfLines() where n = m.getNumberOfLines()
select m, n order by n desc select m, n order by n desc

View File

@@ -11,7 +11,8 @@
*/ */
import python import python
private import LegacyPointsTo
from Module m, int n from ModuleMetrics m, int n
where n = m.getMetrics().getNumberOfLinesOfCode() where n = m.getNumberOfLinesOfCode()
select m, n order by n desc select m, n order by n desc

View File

@@ -10,8 +10,8 @@
*/ */
import python import python
private import LegacyPointsTo
from Module m, int n from ModuleMetrics m, int n
where where n = m.getNumberOfLinesOfComments() + m.getNumberOfLinesOfDocStrings()
n = m.getMetrics().getNumberOfLinesOfComments() + m.getMetrics().getNumberOfLinesOfDocStrings()
select m, n order by n desc select m, n order by n desc

View File

@@ -9,6 +9,7 @@
*/ */
import python import python
private import LegacyPointsTo
from FunctionMetrics func from FunctionMetrics func
select func, func.getNumberOfCalls() as n order by n desc select func, func.getNumberOfCalls() as n order by n desc

View File

@@ -11,6 +11,7 @@
*/ */
import python import python
private import LegacyPointsTo
from FunctionMetrics func from FunctionMetrics func
select func, func.getStatementNestingDepth() as n order by n desc 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