mirror of
https://github.com/github/codeql.git
synced 2025-12-16 16:53:25 +01:00
Python: Remove points-to to from ControlFlowNode
Moves the existing points-to predicates to the newly added class `ControlFlowNodeWithPointsTo` which resides in the `LegacyPointsTo` module. (Existing code that uses these predicates should import this module, and references to `ControlFlowNode` should be changed to `ControlFlowNodeWithPointsTo`.) Also updates all existing points-to based code to do just this.
This commit is contained in:
@@ -10,9 +10,10 @@
|
||||
*/
|
||||
|
||||
import python
|
||||
private import LegacyPointsTo
|
||||
|
||||
from SubscriptNode store
|
||||
where
|
||||
store.isStore() and
|
||||
store.getIndex().pointsTo(Value::named("None"))
|
||||
store.getIndex().(ControlFlowNodeWithPointsTo).pointsTo(Value::named("None"))
|
||||
select store
|
||||
|
||||
121
python/ql/lib/LegacyPointsTo.qll
Normal file
121
python/ql/lib/LegacyPointsTo.qll
Normal file
@@ -0,0 +1,121 @@
|
||||
/**
|
||||
* DEPRECATED: Using the methods in this module may lead to a degradation of performance. Use at
|
||||
* your own peril.
|
||||
*
|
||||
* This module contains legacy points-to predicates and methods for various classes in the
|
||||
* points-to analysis.
|
||||
*
|
||||
* Existing code that depends on, say, points-to predicates on `ControlFlowNode` should be modified
|
||||
* to use `ControlFlowNodeWithPointsTo` instead. In particular, if inside a method call chain such
|
||||
* as
|
||||
*
|
||||
* `someCallNode.getFunction().pointsTo(...)`
|
||||
*
|
||||
* an explicit cast should be added as follows
|
||||
*
|
||||
* `someCallNode.getFunction().(ControlFlowNodeWithPointsTo).pointsTo(...)`
|
||||
*
|
||||
* Similarly, if a bound variable has type `ControlFlowNode`, and a points-to method is called on
|
||||
* it, the type should be changed to `ControlFlowNodeWithPointsTo`.
|
||||
*/
|
||||
|
||||
private import python
|
||||
private import semmle.python.pointsto.PointsTo
|
||||
|
||||
/**
|
||||
* An extension of `ControlFlowNode` that provides points-to predicates.
|
||||
*/
|
||||
class ControlFlowNodeWithPointsTo extends ControlFlowNode {
|
||||
/** Gets the value that this ControlFlowNode points-to. */
|
||||
predicate pointsTo(Value value) { this.pointsTo(_, value, _) }
|
||||
|
||||
/** Gets the value that this ControlFlowNode points-to. */
|
||||
Value pointsTo() { this.pointsTo(_, result, _) }
|
||||
|
||||
/** Gets a value that this ControlFlowNode may points-to. */
|
||||
Value inferredValue() { this.pointsTo(_, result, _) }
|
||||
|
||||
/** Gets the value and origin that this ControlFlowNode points-to. */
|
||||
predicate pointsTo(Value value, ControlFlowNode origin) { this.pointsTo(_, value, origin) }
|
||||
|
||||
/** Gets the value and origin that this ControlFlowNode points-to, given the context. */
|
||||
predicate pointsTo(Context context, Value value, ControlFlowNode origin) {
|
||||
PointsTo::pointsTo(this, context, value, origin)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets what this flow node might "refer-to". Performs a combination of localized (intra-procedural) points-to
|
||||
* analysis and global module-level analysis. This points-to analysis favours precision over recall. It is highly
|
||||
* precise, but may not provide information for a significant number of flow-nodes.
|
||||
* If the class is unimportant then use `refersTo(value)` or `refersTo(value, origin)` instead.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
predicate refersTo(Object obj, ClassObject cls, ControlFlowNode origin) {
|
||||
this.refersTo(_, obj, cls, origin)
|
||||
}
|
||||
|
||||
/** Gets what this expression might "refer-to" in the given `context`. */
|
||||
pragma[nomagic]
|
||||
predicate refersTo(Context context, Object obj, ClassObject cls, ControlFlowNode origin) {
|
||||
not obj = unknownValue() and
|
||||
not cls = theUnknownType() and
|
||||
PointsTo::points_to(this, context, obj, cls, origin)
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether this flow node might "refer-to" to `value` which is from `origin`
|
||||
* Unlike `this.refersTo(value, _, origin)` this predicate includes results
|
||||
* where the class cannot be inferred.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
predicate refersTo(Object obj, ControlFlowNode origin) {
|
||||
not obj = unknownValue() and
|
||||
PointsTo::points_to(this, _, obj, _, origin)
|
||||
}
|
||||
|
||||
/** Equivalent to `this.refersTo(value, _)` */
|
||||
predicate refersTo(Object obj) { this.refersTo(obj, _) }
|
||||
|
||||
/**
|
||||
* Check whether this control-flow node has complete points-to information.
|
||||
* This would mean that the analysis managed to infer an over approximation
|
||||
* of possible values at runtime.
|
||||
*/
|
||||
predicate hasCompletePointsToSet() {
|
||||
// If the tracking failed, then `this` will be its own "origin". In that
|
||||
// case, we want to exclude nodes for which there is also a different
|
||||
// origin, as that would indicate that some paths failed and some did not.
|
||||
this.refersTo(_, _, this) and
|
||||
not exists(ControlFlowNode other | other != this and this.refersTo(_, _, other))
|
||||
or
|
||||
// If `this` is a use of a variable, then we must have complete points-to
|
||||
// for that variable.
|
||||
exists(SsaVariable v | v.getAUse() = this | varHasCompletePointsToSet(v))
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether a SSA variable has complete points-to information.
|
||||
* This would mean that the analysis managed to infer an overapproximation
|
||||
* of possible values at runtime.
|
||||
*/
|
||||
private predicate varHasCompletePointsToSet(SsaVariable var) {
|
||||
// Global variables may be modified non-locally or concurrently.
|
||||
not var.getVariable() instanceof GlobalVariable and
|
||||
(
|
||||
// If we have complete points-to information on the definition of
|
||||
// this variable, then the variable has complete information.
|
||||
var.getDefinition()
|
||||
.(DefinitionNode)
|
||||
.getValue()
|
||||
.(ControlFlowNodeWithPointsTo)
|
||||
.hasCompletePointsToSet()
|
||||
or
|
||||
// If this variable is a phi output, then we have complete
|
||||
// points-to information about it if all phi inputs had complete
|
||||
// information.
|
||||
forex(SsaVariable phiInput | phiInput = var.getAPhiInput() |
|
||||
varHasCompletePointsToSet(phiInput)
|
||||
)
|
||||
)
|
||||
}
|
||||
@@ -3,6 +3,7 @@
|
||||
*/
|
||||
|
||||
import python
|
||||
private import LegacyPointsTo
|
||||
import semmle.python.pointsto.PointsTo
|
||||
import IDEContextual
|
||||
|
||||
@@ -36,22 +37,22 @@ private predicate jump_to_defn(ControlFlowNode use, Definition defn) {
|
||||
)
|
||||
or
|
||||
exists(PythonModuleObject mod |
|
||||
use.(ImportExprNode).refersTo(mod) and
|
||||
use.(ImportExprNode).(ControlFlowNodeWithPointsTo).refersTo(mod) and
|
||||
defn.getAstNode() = mod.getModule()
|
||||
)
|
||||
or
|
||||
exists(PythonModuleObject mod, string name |
|
||||
use.(ImportMemberNode).getModule(name).refersTo(mod) and
|
||||
use.(ImportMemberNode).getModule(name).(ControlFlowNodeWithPointsTo).refersTo(mod) and
|
||||
scope_jump_to_defn_attribute(mod.getModule(), name, defn)
|
||||
)
|
||||
or
|
||||
exists(PackageObject package |
|
||||
use.(ImportExprNode).refersTo(package) and
|
||||
use.(ImportExprNode).(ControlFlowNodeWithPointsTo).refersTo(package) and
|
||||
defn.getAstNode() = package.getInitModule().getModule()
|
||||
)
|
||||
or
|
||||
exists(PackageObject package, string name |
|
||||
use.(ImportMemberNode).getModule(name).refersTo(package) and
|
||||
use.(ImportMemberNode).getModule(name).(ControlFlowNodeWithPointsTo).refersTo(package) and
|
||||
scope_jump_to_defn_attribute(package.getInitModule().getModule(), name, defn)
|
||||
)
|
||||
or
|
||||
@@ -230,7 +231,7 @@ private predicate module_and_name_for_import_star_helper(
|
||||
ModuleObject mod, string name, ImportStarNode im_star, ImportStarRefinement def
|
||||
) {
|
||||
im_star = def.getDefiningNode() and
|
||||
im_star.getModule().refersTo(mod) and
|
||||
im_star.getModule().(ControlFlowNodeWithPointsTo).refersTo(mod) and
|
||||
name = def.getSourceVariable().getName()
|
||||
}
|
||||
|
||||
@@ -239,7 +240,7 @@ pragma[noinline]
|
||||
private predicate variable_not_redefined_by_import_star(EssaVariable var, ImportStarRefinement def) {
|
||||
var = def.getInput() and
|
||||
exists(ModuleObject mod |
|
||||
def.getDefiningNode().(ImportStarNode).getModule().refersTo(mod) and
|
||||
def.getDefiningNode().(ImportStarNode).getModule().(ControlFlowNodeWithPointsTo).refersTo(mod) and
|
||||
not mod.exports(var.getSourceVariable().getName())
|
||||
)
|
||||
}
|
||||
@@ -352,7 +353,9 @@ private predicate scope_jump_to_defn_attribute(ImportTimeScope s, string name, D
|
||||
)
|
||||
}
|
||||
|
||||
private predicate jump_to_defn_attribute(ControlFlowNode use, string name, Definition defn) {
|
||||
private predicate jump_to_defn_attribute(
|
||||
ControlFlowNodeWithPointsTo use, string name, Definition defn
|
||||
) {
|
||||
/* Local attribute */
|
||||
exists(EssaVariable var |
|
||||
use = var.getASourceUse() and
|
||||
@@ -367,7 +370,7 @@ private predicate jump_to_defn_attribute(ControlFlowNode use, string name, Defin
|
||||
/* Super attributes */
|
||||
exists(AttrNode f, SuperBoundMethod sbm, Object function |
|
||||
use = f.getObject(name) and
|
||||
f.refersTo(sbm) and
|
||||
f.(ControlFlowNodeWithPointsTo).refersTo(sbm) and
|
||||
function = sbm.getFunction(_) and
|
||||
function.getOrigin() = defn.getAstNode()
|
||||
)
|
||||
@@ -408,7 +411,7 @@ private predicate attribute_assignment_jump_to_defn_attribute(
|
||||
private predicate sets_attribute(ArgumentRefinement def, string name) {
|
||||
exists(CallNode call |
|
||||
call = def.getDefiningNode() and
|
||||
call.getFunction().refersTo(Object::builtin("setattr")) and
|
||||
call.getFunction().(ControlFlowNodeWithPointsTo).refersTo(Object::builtin("setattr")) and
|
||||
def.getInput().getAUse() = call.getArg(0) and
|
||||
call.getArg(1).getNode().(StringLiteral).getText() = name
|
||||
)
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import python
|
||||
private import LegacyPointsTo
|
||||
private import semmle.python.pointsto.PointsTo
|
||||
private import semmle.python.objects.ObjectInternal
|
||||
private import semmle.python.internal.CachedStages
|
||||
@@ -71,7 +72,9 @@ class Expr extends Expr_, AstNode {
|
||||
* Gets what this expression might "refer-to" in the given `context`.
|
||||
*/
|
||||
predicate refersTo(Context context, Object obj, ClassObject cls, AstNode origin) {
|
||||
this.getAFlowNode().refersTo(context, obj, cls, origin.getAFlowNode())
|
||||
this.getAFlowNode()
|
||||
.(ControlFlowNodeWithPointsTo)
|
||||
.refersTo(context, obj, cls, origin.getAFlowNode())
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -82,7 +85,7 @@ class Expr extends Expr_, AstNode {
|
||||
*/
|
||||
pragma[nomagic]
|
||||
predicate refersTo(Object obj, AstNode origin) {
|
||||
this.getAFlowNode().refersTo(obj, origin.getAFlowNode())
|
||||
this.getAFlowNode().(ControlFlowNodeWithPointsTo).refersTo(obj, origin.getAFlowNode())
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -96,14 +99,16 @@ class Expr extends Expr_, AstNode {
|
||||
* in the given `context`.
|
||||
*/
|
||||
predicate pointsTo(Context context, Value value, AstNode origin) {
|
||||
this.getAFlowNode().pointsTo(context, value, origin.getAFlowNode())
|
||||
this.getAFlowNode()
|
||||
.(ControlFlowNodeWithPointsTo)
|
||||
.pointsTo(context, value, origin.getAFlowNode())
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if this expression might "point-to" to `value` which is from `origin`.
|
||||
*/
|
||||
predicate pointsTo(Value value, AstNode origin) {
|
||||
this.getAFlowNode().pointsTo(value, origin.getAFlowNode())
|
||||
this.getAFlowNode().(ControlFlowNodeWithPointsTo).pointsTo(value, origin.getAFlowNode())
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import python
|
||||
private import semmle.python.pointsto.PointsTo
|
||||
private import semmle.python.internal.CachedStages
|
||||
private import codeql.controlflow.BasicBlock as BB
|
||||
|
||||
@@ -144,56 +143,6 @@ class ControlFlowNode extends @py_flow_node {
|
||||
/** Whether this flow node is the first in its scope */
|
||||
predicate isEntryNode() { py_scope_flow(this, _, -1) }
|
||||
|
||||
/** Gets the value that this ControlFlowNode points-to. */
|
||||
predicate pointsTo(Value value) { this.pointsTo(_, value, _) }
|
||||
|
||||
/** Gets the value that this ControlFlowNode points-to. */
|
||||
Value pointsTo() { this.pointsTo(_, result, _) }
|
||||
|
||||
/** Gets a value that this ControlFlowNode may points-to. */
|
||||
Value inferredValue() { this.pointsTo(_, result, _) }
|
||||
|
||||
/** Gets the value and origin that this ControlFlowNode points-to. */
|
||||
predicate pointsTo(Value value, ControlFlowNode origin) { this.pointsTo(_, value, origin) }
|
||||
|
||||
/** Gets the value and origin that this ControlFlowNode points-to, given the context. */
|
||||
predicate pointsTo(Context context, Value value, ControlFlowNode origin) {
|
||||
PointsTo::pointsTo(this, context, value, origin)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets what this flow node might "refer-to". Performs a combination of localized (intra-procedural) points-to
|
||||
* analysis and global module-level analysis. This points-to analysis favours precision over recall. It is highly
|
||||
* precise, but may not provide information for a significant number of flow-nodes.
|
||||
* If the class is unimportant then use `refersTo(value)` or `refersTo(value, origin)` instead.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
predicate refersTo(Object obj, ClassObject cls, ControlFlowNode origin) {
|
||||
this.refersTo(_, obj, cls, origin)
|
||||
}
|
||||
|
||||
/** Gets what this expression might "refer-to" in the given `context`. */
|
||||
pragma[nomagic]
|
||||
predicate refersTo(Context context, Object obj, ClassObject cls, ControlFlowNode origin) {
|
||||
not obj = unknownValue() and
|
||||
not cls = theUnknownType() and
|
||||
PointsTo::points_to(this, context, obj, cls, origin)
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether this flow node might "refer-to" to `value` which is from `origin`
|
||||
* Unlike `this.refersTo(value, _, origin)` this predicate includes results
|
||||
* where the class cannot be inferred.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
predicate refersTo(Object obj, ControlFlowNode origin) {
|
||||
not obj = unknownValue() and
|
||||
PointsTo::points_to(this, _, obj, _, origin)
|
||||
}
|
||||
|
||||
/** Equivalent to `this.refersTo(value, _)` */
|
||||
predicate refersTo(Object obj) { this.refersTo(obj, _) }
|
||||
|
||||
/** Gets the basic block containing this flow node */
|
||||
BasicBlock getBasicBlock() { result.contains(this) }
|
||||
|
||||
@@ -259,23 +208,6 @@ class ControlFlowNode extends @py_flow_node {
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether this control-flow node has complete points-to information.
|
||||
* This would mean that the analysis managed to infer an over approximation
|
||||
* of possible values at runtime.
|
||||
*/
|
||||
predicate hasCompletePointsToSet() {
|
||||
// If the tracking failed, then `this` will be its own "origin". In that
|
||||
// case, we want to exclude nodes for which there is also a different
|
||||
// origin, as that would indicate that some paths failed and some did not.
|
||||
this.refersTo(_, _, this) and
|
||||
not exists(ControlFlowNode other | other != this and this.refersTo(_, _, other))
|
||||
or
|
||||
// If `this` is a use of a variable, then we must have complete points-to
|
||||
// for that variable.
|
||||
exists(SsaVariable v | v.getAUse() = this | varHasCompletePointsToSet(v))
|
||||
}
|
||||
|
||||
/** Whether this strictly dominates other. */
|
||||
pragma[inline]
|
||||
predicate strictlyDominates(ControlFlowNode other) {
|
||||
@@ -332,28 +264,6 @@ private class AnyNode extends ControlFlowNode {
|
||||
override AstNode getNode() { result = super.getNode() }
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether a SSA variable has complete points-to information.
|
||||
* This would mean that the analysis managed to infer an overapproximation
|
||||
* of possible values at runtime.
|
||||
*/
|
||||
private predicate varHasCompletePointsToSet(SsaVariable var) {
|
||||
// Global variables may be modified non-locally or concurrently.
|
||||
not var.getVariable() instanceof GlobalVariable and
|
||||
(
|
||||
// If we have complete points-to information on the definition of
|
||||
// this variable, then the variable has complete information.
|
||||
var.getDefinition().(DefinitionNode).getValue().hasCompletePointsToSet()
|
||||
or
|
||||
// If this variable is a phi output, then we have complete
|
||||
// points-to information about it if all phi inputs had complete
|
||||
// information.
|
||||
forex(SsaVariable phiInput | phiInput = var.getAPhiInput() |
|
||||
varHasCompletePointsToSet(phiInput)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
/** A control flow node corresponding to a call expression, such as `func(...)` */
|
||||
class CallNode extends ControlFlowNode {
|
||||
CallNode() { toAst(this) instanceof Call }
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import python
|
||||
private import LegacyPointsTo
|
||||
|
||||
/** The metrics for a function */
|
||||
class FunctionMetrics extends Function {
|
||||
@@ -59,7 +60,7 @@ class FunctionMetrics extends Function {
|
||||
not non_coupling_method(result) and
|
||||
exists(Call call | call.getScope() = this |
|
||||
exists(FunctionObject callee | callee.getFunction() = result |
|
||||
call.getAFlowNode().getFunction().refersTo(callee)
|
||||
call.getAFlowNode().getFunction().(ControlFlowNodeWithPointsTo).refersTo(callee)
|
||||
)
|
||||
or
|
||||
exists(Attribute a | call.getFunc() = a |
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
*/
|
||||
|
||||
private import python
|
||||
private import LegacyPointsTo
|
||||
|
||||
/** A control flow node which might correspond to a special method call. */
|
||||
class PotentialSpecialMethodCallNode extends ControlFlowNode instanceof SpecialMethod::Potential { }
|
||||
@@ -106,7 +107,11 @@ class SpecialMethodCallNode extends PotentialSpecialMethodCallNode {
|
||||
SpecialMethodCallNode() {
|
||||
exists(SpecialMethod::Potential pot |
|
||||
this = pot and
|
||||
pot.getSelf().pointsTo().getClass().lookup(pot.getSpecialMethodName()) = resolvedSpecialMethod
|
||||
pot.getSelf()
|
||||
.(ControlFlowNodeWithPointsTo)
|
||||
.pointsTo()
|
||||
.getClass()
|
||||
.lookup(pot.getSpecialMethodName()) = resolvedSpecialMethod
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import python
|
||||
private import LegacyPointsTo
|
||||
import semmle.python.dataflow.TaintTracking
|
||||
private import semmle.python.objects.ObjectInternal
|
||||
private import semmle.python.pointsto.Filters as Filters
|
||||
@@ -374,7 +375,7 @@ class TaintTrackingImplementation extends string instanceof TaintTracking::Confi
|
||||
exists(ModuleValue m, string name |
|
||||
src = TTaintTrackingNode_(_, context, path, kind, this) and
|
||||
this.moduleAttributeTainted(m, name, src) and
|
||||
node.asCfgNode().(ImportMemberNode).getModule(name).pointsTo(m)
|
||||
node.asCfgNode().(ImportMemberNode).getModule(name).(ControlFlowNodeWithPointsTo).pointsTo(m)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -408,7 +409,9 @@ class TaintTrackingImplementation extends string instanceof TaintTracking::Confi
|
||||
src = TTaintTrackingNode_(srcnode, context, srcpath, srckind, this) and
|
||||
exists(CallNode call, ControlFlowNode arg |
|
||||
call = node.asCfgNode() and
|
||||
call.getFunction().pointsTo(ObjectInternal::builtin("getattr")) and
|
||||
call.getFunction()
|
||||
.(ControlFlowNodeWithPointsTo)
|
||||
.pointsTo(ObjectInternal::builtin("getattr")) and
|
||||
arg = call.getArg(0) and
|
||||
attrname = call.getArg(1).getNode().(StringLiteral).getText() and
|
||||
arg = srcnode.asCfgNode()
|
||||
@@ -515,7 +518,7 @@ class TaintTrackingImplementation extends string instanceof TaintTracking::Confi
|
||||
TaintTrackingContext caller, TaintTrackingContext callee
|
||||
) {
|
||||
exists(ClassValue cls |
|
||||
call.getFunction().pointsTo(cls) and
|
||||
call.getFunction().(ControlFlowNodeWithPointsTo).pointsTo(cls) and
|
||||
cls.lookup("__init__") = init
|
||||
|
|
||||
exists(int arg, TaintKind callerKind, AttributePath callerPath, DataFlow::Node argument |
|
||||
@@ -878,7 +881,7 @@ private class EssaTaintTracking extends string instanceof TaintTracking::Configu
|
||||
const.getNode() instanceof ImmutableLiteral
|
||||
)
|
||||
or
|
||||
exists(ControlFlowNode c, ClassValue cls |
|
||||
exists(ControlFlowNodeWithPointsTo c, ClassValue cls |
|
||||
Filters::isinstance(test, c, use) and
|
||||
c.pointsTo(cls)
|
||||
|
|
||||
@@ -978,7 +981,7 @@ module Implementation {
|
||||
tonode.getArg(0) = fromnode
|
||||
)
|
||||
or
|
||||
tonode.getFunction().pointsTo(ObjectInternal::builtin("reversed")) and
|
||||
tonode.getFunction().(ControlFlowNodeWithPointsTo).pointsTo(ObjectInternal::builtin("reversed")) and
|
||||
tonode.getArg(0) = fromnode
|
||||
}
|
||||
}
|
||||
|
||||
@@ -87,6 +87,7 @@
|
||||
*/
|
||||
|
||||
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
|
||||
@@ -267,7 +268,11 @@ module DictKind {
|
||||
Implementation::copyCall(fromnode, tonode) and
|
||||
edgeLabel = "dict copy"
|
||||
or
|
||||
tonode.(CallNode).getFunction().pointsTo(ObjectInternal::builtin("dict")) and
|
||||
tonode
|
||||
.(CallNode)
|
||||
.getFunction()
|
||||
.(ControlFlowNodeWithPointsTo)
|
||||
.pointsTo(ObjectInternal::builtin("dict")) and
|
||||
tonode.(CallNode).getArg(0) = fromnode and
|
||||
edgeLabel = "dict() call"
|
||||
}
|
||||
@@ -615,7 +620,7 @@ module DataFlow {
|
||||
TCfgNode(ControlFlowNode node)
|
||||
|
||||
abstract class Node extends TDataFlowNode {
|
||||
abstract ControlFlowNode asCfgNode();
|
||||
abstract ControlFlowNodeWithPointsTo asCfgNode();
|
||||
|
||||
abstract EssaVariable asVariable();
|
||||
|
||||
@@ -632,7 +637,7 @@ module DataFlow {
|
||||
}
|
||||
|
||||
class CfgNode extends Node, TCfgNode {
|
||||
override ControlFlowNode asCfgNode() { this = TCfgNode(result) }
|
||||
override ControlFlowNodeWithPointsTo asCfgNode() { this = TCfgNode(result) }
|
||||
|
||||
override EssaVariable asVariable() { none() }
|
||||
|
||||
@@ -647,7 +652,7 @@ module DataFlow {
|
||||
}
|
||||
|
||||
class EssaNode extends Node, TEssaNode {
|
||||
override ControlFlowNode asCfgNode() { none() }
|
||||
override ControlFlowNodeWithPointsTo asCfgNode() { none() }
|
||||
|
||||
override EssaVariable asVariable() { this = TEssaNode(result) }
|
||||
|
||||
@@ -668,7 +673,11 @@ pragma[noinline]
|
||||
private predicate dict_construct(ControlFlowNode itemnode, ControlFlowNode dictnode) {
|
||||
dictnode.(DictNode).getAValue() = itemnode
|
||||
or
|
||||
dictnode.(CallNode).getFunction().pointsTo(ObjectInternal::builtin("dict")) and
|
||||
dictnode
|
||||
.(CallNode)
|
||||
.getFunction()
|
||||
.(ControlFlowNodeWithPointsTo)
|
||||
.pointsTo(ObjectInternal::builtin("dict")) and
|
||||
dictnode.(CallNode).getArgByName(_) = itemnode
|
||||
}
|
||||
|
||||
@@ -688,7 +697,7 @@ private predicate sequence_construct(ControlFlowNode itemnode, ControlFlowNode s
|
||||
pragma[noinline]
|
||||
private predicate sequence_call(ControlFlowNode fromnode, CallNode tonode) {
|
||||
tonode.getArg(0) = fromnode and
|
||||
exists(ControlFlowNode cls | cls = tonode.getFunction() |
|
||||
exists(ControlFlowNodeWithPointsTo cls | cls = tonode.getFunction() |
|
||||
cls.pointsTo(ObjectInternal::builtin("list"))
|
||||
or
|
||||
cls.pointsTo(ObjectInternal::builtin("tuple"))
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import python
|
||||
private import LegacyPointsTo
|
||||
import semmle.python.dependencies.DependencyKind
|
||||
|
||||
private predicate importDependency(Object target, AstNode source) {
|
||||
@@ -59,7 +60,7 @@ class PythonUse extends DependencyKind {
|
||||
interesting(target) and
|
||||
this = this and
|
||||
source != target.(ControlFlowNode).getNode() and
|
||||
exists(ControlFlowNode use, Object obj |
|
||||
exists(ControlFlowNodeWithPointsTo use, Object obj |
|
||||
use.getNode() = source and
|
||||
use.refersTo(obj) and
|
||||
use.isLoad()
|
||||
@@ -114,12 +115,14 @@ private predicate attribute_access_dependency(Object target, AstNode source) {
|
||||
|
||||
private predicate use_of_attribute(Attribute attr, Scope s, string name) {
|
||||
exists(AttrNode cfg | cfg.isLoad() and cfg.getNode() = attr |
|
||||
exists(Object obj | cfg.getObject(name).refersTo(obj) |
|
||||
exists(Object obj | cfg.getObject(name).(ControlFlowNodeWithPointsTo).refersTo(obj) |
|
||||
s = obj.(PythonModuleObject).getModule() or
|
||||
s = obj.(ClassObject).getPyClass()
|
||||
)
|
||||
or
|
||||
exists(ClassObject cls | cfg.getObject(name).refersTo(_, cls, _) | s = cls.getPyClass())
|
||||
exists(ClassObject cls | cfg.getObject(name).(ControlFlowNodeWithPointsTo).refersTo(_, cls, _) |
|
||||
s = cls.getPyClass()
|
||||
)
|
||||
)
|
||||
or
|
||||
exists(SelfAttributeRead sar | sar = attr |
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
*/
|
||||
|
||||
import python
|
||||
private import LegacyPointsTo
|
||||
private import TObject
|
||||
private import semmle.python.objects.ObjectInternal
|
||||
private import semmle.python.pointsto.PointsTo
|
||||
@@ -704,12 +705,14 @@ abstract class FunctionValue extends CallableValue {
|
||||
abstract ClassValue getARaisedType();
|
||||
|
||||
/** Gets a call-site from where this function is called as a function */
|
||||
CallNode getAFunctionCall() { result.getFunction().pointsTo() = this }
|
||||
CallNode getAFunctionCall() {
|
||||
result.getFunction().(ControlFlowNodeWithPointsTo).pointsTo() = this
|
||||
}
|
||||
|
||||
/** Gets a call-site from where this function is called as a method */
|
||||
CallNode getAMethodCall() {
|
||||
exists(BoundMethodObjectInternal bm |
|
||||
result.getFunction().pointsTo() = bm and
|
||||
result.getFunction().(ControlFlowNodeWithPointsTo).pointsTo() = bm and
|
||||
bm.getFunction() = this
|
||||
)
|
||||
}
|
||||
@@ -753,7 +756,7 @@ class PythonFunctionValue extends FunctionValue {
|
||||
* explicit return nodes that we can query and get the class of.
|
||||
*/
|
||||
|
||||
result = this.getAReturnedNode().pointsTo().getClass()
|
||||
result = this.getAReturnedNode().(ControlFlowNodeWithPointsTo).pointsTo().getClass()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import python
|
||||
private import LegacyPointsTo
|
||||
private import semmle.python.objects.Classes
|
||||
private import semmle.python.objects.Instances
|
||||
private import semmle.python.pointsto.PointsTo
|
||||
@@ -193,7 +194,9 @@ class ClassObject extends Object {
|
||||
* It is guaranteed that getProbableSingletonInstance() returns at most one Object for each ClassObject.
|
||||
*/
|
||||
Object getProbableSingletonInstance() {
|
||||
exists(ControlFlowNode use, Expr origin | use.refersTo(result, this, origin.getAFlowNode()) |
|
||||
exists(ControlFlowNodeWithPointsTo use, Expr origin |
|
||||
use.refersTo(result, this, origin.getAFlowNode())
|
||||
|
|
||||
this.hasStaticallyUniqueInstance() and
|
||||
/* Ensure that original expression will be executed only one. */
|
||||
origin.getScope() instanceof ImportTimeScope and
|
||||
@@ -351,7 +354,7 @@ class ClassObject extends Object {
|
||||
* Gets a call to this class. Note that the call may not create a new instance of
|
||||
* this class, as that depends on the `__new__` method of this class.
|
||||
*/
|
||||
CallNode getACall() { result.getFunction().refersTo(this) }
|
||||
CallNode getACall() { result.getFunction().(ControlFlowNodeWithPointsTo).refersTo(this) }
|
||||
|
||||
override predicate notClass() { none() }
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
*/
|
||||
|
||||
import python
|
||||
private import LegacyPointsTo
|
||||
|
||||
/** The subset of ControlFlowNodes which might raise an exception */
|
||||
class RaisingNode extends ControlFlowNode {
|
||||
@@ -30,7 +31,9 @@ class RaisingNode extends ControlFlowNode {
|
||||
)
|
||||
}
|
||||
|
||||
private predicate quits() { this.(CallNode).getFunction().refersTo(Object::quitter(_)) }
|
||||
private predicate quits() {
|
||||
this.(CallNode).getFunction().(ControlFlowNodeWithPointsTo).refersTo(Object::quitter(_))
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the type of an exception that may be raised
|
||||
@@ -68,7 +71,7 @@ class RaisingNode extends ControlFlowNode {
|
||||
private ClassObject localRaisedType_objectapi() {
|
||||
result.isSubclassOf(theBaseExceptionType()) and
|
||||
(
|
||||
exists(ControlFlowNode ex |
|
||||
exists(ControlFlowNodeWithPointsTo ex |
|
||||
ex = this.getExceptionNode() and
|
||||
(ex.refersTo(result) or ex.refersTo(_, result, _))
|
||||
)
|
||||
@@ -95,7 +98,7 @@ class RaisingNode extends ControlFlowNode {
|
||||
private ClassValue localRaisedType() {
|
||||
result.getASuperType() = ClassValue::baseException() and
|
||||
(
|
||||
exists(ControlFlowNode ex |
|
||||
exists(ControlFlowNodeWithPointsTo ex |
|
||||
ex = this.getExceptionNode() and
|
||||
(ex.pointsTo(result) or ex.pointsTo().getClass() = result)
|
||||
)
|
||||
@@ -153,7 +156,9 @@ class RaisingNode extends ControlFlowNode {
|
||||
/* Call to an unknown object */
|
||||
this.getNode() instanceof Call and
|
||||
not exists(FunctionObject func | this = func.getACall()) and
|
||||
not exists(ClassObject known | this.(CallNode).getFunction().refersTo(known))
|
||||
not exists(ClassObject known |
|
||||
this.(CallNode).getFunction().(ControlFlowNodeWithPointsTo).refersTo(known)
|
||||
)
|
||||
or
|
||||
this.getNode() instanceof Exec
|
||||
or
|
||||
@@ -371,7 +376,7 @@ class ExceptFlowNode extends ControlFlowNode {
|
||||
* Gets the type handled by this exception handler.
|
||||
* `ExceptionType` in `except ExceptionType as e:`
|
||||
*/
|
||||
ControlFlowNode getType() {
|
||||
ControlFlowNodeWithPointsTo getType() {
|
||||
exists(ExceptStmt ex |
|
||||
this.getBasicBlock().dominates(result.getBasicBlock()) and
|
||||
ex = this.getNode() and
|
||||
@@ -470,7 +475,7 @@ class ExceptGroupFlowNode extends ControlFlowNode {
|
||||
}
|
||||
}
|
||||
|
||||
private ControlFlowNode 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())
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import python
|
||||
private import LegacyPointsTo
|
||||
import semmle.python.types.Exceptions
|
||||
private import semmle.python.pointsto.PointsTo
|
||||
private import semmle.python.objects.Callables
|
||||
@@ -32,27 +33,31 @@ abstract class FunctionObject extends Object {
|
||||
abstract string descriptiveString();
|
||||
|
||||
/** Gets a call-site from where this function is called as a function */
|
||||
CallNode getAFunctionCall() { result.getFunction().inferredValue() = this.theCallable() }
|
||||
CallNode getAFunctionCall() {
|
||||
result.getFunction().(ControlFlowNodeWithPointsTo).inferredValue() = this.theCallable()
|
||||
}
|
||||
|
||||
/** Gets a call-site from where this function is called as a method */
|
||||
CallNode getAMethodCall() {
|
||||
exists(BoundMethodObjectInternal bm |
|
||||
result.getFunction().inferredValue() = bm and
|
||||
result.getFunction().(ControlFlowNodeWithPointsTo).inferredValue() = bm and
|
||||
bm.getFunction() = this.theCallable()
|
||||
)
|
||||
}
|
||||
|
||||
/** Gets a call-site from where this function is called */
|
||||
ControlFlowNode getACall() { result = this.theCallable().getACall() }
|
||||
ControlFlowNodeWithPointsTo getACall() { result = this.theCallable().getACall() }
|
||||
|
||||
/** Gets a call-site from where this function is called, given the `context` */
|
||||
ControlFlowNode getACall(Context context) { result = this.theCallable().getACall(context) }
|
||||
ControlFlowNodeWithPointsTo getACall(Context context) {
|
||||
result = this.theCallable().getACall(context)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the `ControlFlowNode` that will be passed as the nth argument to `this` when called at `call`.
|
||||
* This predicate will correctly handle `x.y()`, treating `x` as the zeroth argument.
|
||||
*/
|
||||
ControlFlowNode getArgumentForCall(CallNode call, int n) {
|
||||
ControlFlowNodeWithPointsTo getArgumentForCall(CallNode call, int n) {
|
||||
result = this.theCallable().getArgumentForCall(call, n)
|
||||
}
|
||||
|
||||
@@ -60,7 +65,7 @@ abstract class FunctionObject extends Object {
|
||||
* Gets the `ControlFlowNode` that will be passed as the named argument to `this` when called at `call`.
|
||||
* This predicate will correctly handle `x.y()`, treating `x` as the self argument.
|
||||
*/
|
||||
ControlFlowNode getNamedArgumentForCall(CallNode call, string name) {
|
||||
ControlFlowNodeWithPointsTo getNamedArgumentForCall(CallNode call, string name) {
|
||||
result = this.theCallable().getNamedArgumentForCall(call, name)
|
||||
}
|
||||
|
||||
@@ -134,7 +139,9 @@ class PyFunctionObject extends FunctionObject {
|
||||
override predicate raisesUnknownType() { scope_raises_unknown(this.getFunction()) }
|
||||
|
||||
/** Gets a control flow node corresponding to the value of a return statement */
|
||||
ControlFlowNode getAReturnedNode() { result = this.getFunction().getAReturnValueFlowNode() }
|
||||
ControlFlowNodeWithPointsTo getAReturnedNode() {
|
||||
result = this.getFunction().getAReturnValueFlowNode()
|
||||
}
|
||||
|
||||
override string descriptiveString() {
|
||||
if this.getFunction().isMethod()
|
||||
@@ -216,7 +223,7 @@ abstract class BuiltinCallable extends FunctionObject {
|
||||
|
||||
abstract override string getQualifiedName();
|
||||
|
||||
override ControlFlowNode getArgumentForCall(CallNode call, int n) {
|
||||
override ControlFlowNodeWithPointsTo getArgumentForCall(CallNode call, int n) {
|
||||
call = this.getACall() and result = call.getArg(n)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +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
|
||||
@@ -41,7 +42,7 @@ class Object extends @py_object {
|
||||
* for a control flow node 'f'
|
||||
*/
|
||||
ClassObject getAnInferredType() {
|
||||
exists(ControlFlowNode somewhere | somewhere.refersTo(this, result, _))
|
||||
exists(ControlFlowNodeWithPointsTo somewhere | somewhere.refersTo(this, result, _))
|
||||
or
|
||||
this.asBuiltin().getClass() = result.asBuiltin() and not this = unknownValue()
|
||||
or
|
||||
@@ -327,7 +328,7 @@ abstract class SequenceObject extends Object {
|
||||
Object getInferredElement(int n) {
|
||||
result = this.getBuiltinElement(n)
|
||||
or
|
||||
this.getSourceElement(n).refersTo(result)
|
||||
this.getSourceElement(n).(ControlFlowNodeWithPointsTo).refersTo(result)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -438,7 +439,8 @@ class SuperBoundMethod extends Object {
|
||||
string name;
|
||||
|
||||
SuperBoundMethod() {
|
||||
this.(AttrNode).getObject(name).inferredValue().getClass() = Value::named("super")
|
||||
this.(AttrNode).getObject(name).(ControlFlowNodeWithPointsTo).inferredValue().getClass() =
|
||||
Value::named("super")
|
||||
}
|
||||
|
||||
override string toString() { result = "super()." + name }
|
||||
@@ -446,7 +448,7 @@ class SuperBoundMethod extends Object {
|
||||
Object getFunction(string fname) {
|
||||
fname = name and
|
||||
exists(SuperInstance sup, BoundMethodObjectInternal m |
|
||||
sup = this.(AttrNode).getObject(name).inferredValue() and
|
||||
sup = this.(AttrNode).getObject(name).(ControlFlowNodeWithPointsTo).inferredValue() and
|
||||
sup.attribute(name, m, _) and
|
||||
result = m.getFunction().getSource()
|
||||
)
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import python
|
||||
private import LegacyPointsTo
|
||||
|
||||
/**
|
||||
* A Python property:
|
||||
@@ -77,32 +78,32 @@ class BuiltinPropertyObject extends PropertyObject {
|
||||
}
|
||||
|
||||
private predicate property_getter(CallNode decorated, FunctionObject getter) {
|
||||
decorated.getFunction().refersTo(thePropertyType()) and
|
||||
decorated.getArg(0).refersTo(getter)
|
||||
decorated.getFunction().(ControlFlowNodeWithPointsTo).refersTo(thePropertyType()) and
|
||||
decorated.getArg(0).(ControlFlowNodeWithPointsTo).refersTo(getter)
|
||||
}
|
||||
|
||||
private predicate property_setter(CallNode decorated, FunctionObject setter) {
|
||||
property_getter(decorated, _) and
|
||||
exists(CallNode setter_call, AttrNode prop_setter |
|
||||
prop_setter.getObject("setter").refersTo(decorated)
|
||||
prop_setter.getObject("setter").(ControlFlowNodeWithPointsTo).refersTo(decorated)
|
||||
|
|
||||
setter_call.getArg(0).refersTo(setter) and
|
||||
setter_call.getArg(0).(ControlFlowNodeWithPointsTo).refersTo(setter) and
|
||||
setter_call.getFunction() = prop_setter
|
||||
)
|
||||
or
|
||||
decorated.getFunction().refersTo(thePropertyType()) and
|
||||
decorated.getArg(1).refersTo(setter)
|
||||
decorated.getFunction().(ControlFlowNodeWithPointsTo).refersTo(thePropertyType()) and
|
||||
decorated.getArg(1).(ControlFlowNodeWithPointsTo).refersTo(setter)
|
||||
}
|
||||
|
||||
private predicate property_deleter(CallNode decorated, FunctionObject deleter) {
|
||||
property_getter(decorated, _) and
|
||||
exists(CallNode deleter_call, AttrNode prop_deleter |
|
||||
prop_deleter.getObject("deleter").refersTo(decorated)
|
||||
prop_deleter.getObject("deleter").(ControlFlowNodeWithPointsTo).refersTo(decorated)
|
||||
|
|
||||
deleter_call.getArg(0).refersTo(deleter) and
|
||||
deleter_call.getArg(0).(ControlFlowNodeWithPointsTo).refersTo(deleter) and
|
||||
deleter_call.getFunction() = prop_deleter
|
||||
)
|
||||
or
|
||||
decorated.getFunction().refersTo(thePropertyType()) and
|
||||
decorated.getArg(2).refersTo(deleter)
|
||||
decorated.getFunction().(ControlFlowNodeWithPointsTo).refersTo(thePropertyType()) and
|
||||
decorated.getArg(2).(ControlFlowNodeWithPointsTo).refersTo(deleter)
|
||||
}
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
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(ControlFlowNode n, string attr) {
|
||||
predicate string_attribute_all(ControlFlowNodeWithPointsTo n, string attr) {
|
||||
(n.getNode() instanceof Unicode or n.getNode() instanceof Bytes) and
|
||||
attr = "const"
|
||||
or
|
||||
@@ -19,18 +23,27 @@ predicate tracked_object(ControlFlowNode obj, string attr) {
|
||||
tracked_object_any(obj, attr)
|
||||
}
|
||||
|
||||
predicate open_file(Object obj) { obj.(CallNode).getFunction().refersTo(Object::builtin("open")) }
|
||||
predicate open_file(Object obj) {
|
||||
obj.(CallNode).getFunction().(ControlFlowNodeWithPointsTo).refersTo(Object::builtin("open"))
|
||||
}
|
||||
|
||||
predicate string_attribute_any(ControlFlowNode n, string attr) {
|
||||
predicate string_attribute_any(ControlFlowNodeWithPointsTo n, string attr) {
|
||||
attr = "user-input" and
|
||||
exists(Object input | n.(CallNode).getFunction().refersTo(input) |
|
||||
exists(Object input | n.(CallNode).getFunction().(ControlFlowNodeWithPointsTo).refersTo(input) |
|
||||
if major_version() = 2
|
||||
then input = Object::builtin("raw_input")
|
||||
else input = Object::builtin("input")
|
||||
)
|
||||
or
|
||||
attr = "file-input" and
|
||||
exists(Object fd | n.(CallNode).getFunction().(AttrNode).getObject("read").refersTo(fd) |
|
||||
exists(Object fd |
|
||||
n.(CallNode)
|
||||
.getFunction()
|
||||
.(AttrNode)
|
||||
.getObject("read")
|
||||
.(ControlFlowNodeWithPointsTo)
|
||||
.refersTo(fd)
|
||||
|
|
||||
open_file(fd)
|
||||
)
|
||||
or
|
||||
@@ -65,7 +78,7 @@ ControlFlowNode sequence_for_iterator(ControlFlowNode f) {
|
||||
}
|
||||
|
||||
pragma[noinline]
|
||||
private predicate tracking_step(ControlFlowNode src, ControlFlowNode dest) {
|
||||
private predicate tracking_step(ControlFlowNode src, ControlFlowNodeWithPointsTo dest) {
|
||||
src = dest.(BinaryExprNode).getAnOperand()
|
||||
or
|
||||
src = dest.(UnaryExprNode).getOperand()
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
*/
|
||||
|
||||
import python
|
||||
private import LegacyPointsTo
|
||||
import semmle.python.pointsto.PointsTo
|
||||
|
||||
predicate rhs_in_expr(ControlFlowNode rhs, Compare cmp) {
|
||||
@@ -20,7 +21,8 @@ predicate rhs_in_expr(ControlFlowNode rhs, Compare cmp) {
|
||||
)
|
||||
}
|
||||
|
||||
from ControlFlowNode non_seq, Compare cmp, Value v, ClassValue cls, ControlFlowNode origin
|
||||
from
|
||||
ControlFlowNodeWithPointsTo non_seq, Compare cmp, Value v, ClassValue cls, ControlFlowNode origin
|
||||
where
|
||||
rhs_in_expr(non_seq, cmp) and
|
||||
non_seq.pointsTo(_, v, origin) and
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import python
|
||||
private import LegacyPointsTo
|
||||
|
||||
/** A string constant that looks like it may be used in string formatting operations. */
|
||||
class PossibleAdvancedFormatString extends StringLiteral {
|
||||
@@ -98,11 +99,15 @@ private predicate brace_pair(PossibleAdvancedFormatString fmt, int start, int en
|
||||
|
||||
private predicate advanced_format_call(Call format_expr, PossibleAdvancedFormatString fmt, int args) {
|
||||
exists(CallNode call | call = format_expr.getAFlowNode() |
|
||||
call.getFunction().pointsTo(Value::named("format")) and
|
||||
call.getArg(0).pointsTo(_, fmt.getAFlowNode()) and
|
||||
call.getFunction().(ControlFlowNodeWithPointsTo).pointsTo(Value::named("format")) and
|
||||
call.getArg(0).(ControlFlowNodeWithPointsTo).pointsTo(_, fmt.getAFlowNode()) and
|
||||
args = count(format_expr.getAnArg()) - 1
|
||||
or
|
||||
call.getFunction().(AttrNode).getObject("format").pointsTo(_, fmt.getAFlowNode()) and
|
||||
call.getFunction()
|
||||
.(AttrNode)
|
||||
.getObject("format")
|
||||
.(ControlFlowNodeWithPointsTo)
|
||||
.pointsTo(_, fmt.getAFlowNode()) and
|
||||
args = count(format_expr.getAnArg())
|
||||
)
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
*/
|
||||
|
||||
import python
|
||||
private import LegacyPointsTo
|
||||
|
||||
/*
|
||||
* This assumes that any indexing operation where the value is not a sequence or numpy array involves hashing.
|
||||
@@ -41,13 +42,13 @@ predicate unhashable_subscript(ControlFlowNode f, ClassValue c, ControlFlowNode
|
||||
is_unhashable(f, c, origin) and
|
||||
exists(SubscriptNode sub | sub.getIndex() = f |
|
||||
exists(Value custom_getitem |
|
||||
sub.getObject().pointsTo(custom_getitem) and
|
||||
sub.getObject().(ControlFlowNodeWithPointsTo).pointsTo(custom_getitem) and
|
||||
not has_custom_getitem(custom_getitem)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
predicate is_unhashable(ControlFlowNode f, ClassValue cls, ControlFlowNode origin) {
|
||||
predicate is_unhashable(ControlFlowNodeWithPointsTo f, ClassValue cls, ControlFlowNode origin) {
|
||||
exists(Value v | f.pointsTo(v, origin) and v.getClass() = cls |
|
||||
not cls.hasAttribute("__hash__") and not cls.failedInference(_) and cls.isNewStyle()
|
||||
or
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
/** INTERNAL - Helper predicates for queries that inspect the comparison of objects using `is`. */
|
||||
|
||||
import python
|
||||
private import LegacyPointsTo
|
||||
|
||||
/** 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) {
|
||||
@@ -42,7 +43,7 @@ predicate invalid_to_use_is_portably(ClassValue c) {
|
||||
}
|
||||
|
||||
/** Holds if the control flow node `f` points to either `True`, `False`, or `None`. */
|
||||
predicate simple_constant(ControlFlowNode f) {
|
||||
predicate simple_constant(ControlFlowNodeWithPointsTo f) {
|
||||
exists(Value val | f.pointsTo(val) |
|
||||
val = Value::named("True") or val = Value::named("False") or val = Value::named("None")
|
||||
)
|
||||
@@ -84,7 +85,7 @@ predicate universally_interned_constant(Expr e) {
|
||||
}
|
||||
|
||||
private predicate comparison_both_types(Compare comp, Cmpop op, ClassValue cls1, ClassValue cls2) {
|
||||
exists(ControlFlowNode op1, ControlFlowNode op2 |
|
||||
exists(ControlFlowNodeWithPointsTo op1, ControlFlowNodeWithPointsTo op2 |
|
||||
comparison_using_is(comp, op1, op, op2) or comparison_using_is(comp, op2, op, op1)
|
||||
|
|
||||
op1.inferredValue().getClass() = cls1 and
|
||||
@@ -94,7 +95,7 @@ private predicate comparison_both_types(Compare comp, Cmpop op, ClassValue cls1,
|
||||
|
||||
private predicate comparison_one_type(Compare comp, Cmpop op, ClassValue cls) {
|
||||
not comparison_both_types(comp, _, _, _) and
|
||||
exists(ControlFlowNode operand |
|
||||
exists(ControlFlowNodeWithPointsTo operand |
|
||||
comparison_using_is(comp, operand, op, _) or comparison_using_is(comp, _, op, operand)
|
||||
|
|
||||
operand.inferredValue().getClass() = cls
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
*/
|
||||
|
||||
import python
|
||||
private import LegacyPointsTo
|
||||
|
||||
from BinaryExpr div, ControlFlowNode left, ControlFlowNode right
|
||||
where
|
||||
@@ -20,9 +21,9 @@ where
|
||||
exists(BinaryExprNode bin, Value lval, Value rval |
|
||||
bin = div.getAFlowNode() and
|
||||
bin.getNode().getOp() instanceof Div and
|
||||
bin.getLeft().pointsTo(lval, left) and
|
||||
bin.getLeft().(ControlFlowNodeWithPointsTo).pointsTo(lval, left) and
|
||||
lval.getClass() = ClassValue::int_() and
|
||||
bin.getRight().pointsTo(rval, right) and
|
||||
bin.getRight().(ControlFlowNodeWithPointsTo).pointsTo(rval, right) and
|
||||
rval.getClass() = ClassValue::int_() and
|
||||
// Ignore instances where integer division leaves no remainder
|
||||
not lval.(NumericValue).getIntValue() % rval.(NumericValue).getIntValue() = 0 and
|
||||
|
||||
@@ -10,8 +10,9 @@
|
||||
*/
|
||||
|
||||
import python
|
||||
private import LegacyPointsTo
|
||||
private import semmle.python.types.Builtins
|
||||
|
||||
from CallNode call, ControlFlowNode func
|
||||
from CallNode call, ControlFlowNodeWithPointsTo func
|
||||
where major_version() = 2 and call.getFunction() = func and func.pointsTo(Value::named("apply"))
|
||||
select call, "Call to the obsolete builtin function 'apply'."
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
*/
|
||||
|
||||
import python
|
||||
private import LegacyPointsTo
|
||||
import semmle.python.filters.Tests
|
||||
|
||||
from ImportMember im, ModuleValue m, AttrNode store_attr, string name
|
||||
@@ -23,7 +24,7 @@ where
|
||||
/* variable resulting from import must have a long lifetime */
|
||||
not im.getScope() instanceof Function and
|
||||
store_attr.isStore() and
|
||||
store_attr.getObject(name).pointsTo(m) and
|
||||
store_attr.getObject(name).(ControlFlowNodeWithPointsTo).pointsTo(m) and
|
||||
/* Import not in same module as modification. */
|
||||
not im.getEnclosingModule() = store_attr.getScope().getEnclosingModule() and
|
||||
/* Modification is not in a test */
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
*/
|
||||
|
||||
import python
|
||||
private import LegacyPointsTo
|
||||
import semmle.python.filters.Tests
|
||||
|
||||
predicate has_string_type(Value v) {
|
||||
@@ -21,7 +22,7 @@ predicate has_string_type(Value v) {
|
||||
}
|
||||
|
||||
from
|
||||
For loop, ControlFlowNode iter, Value str, Value seq, ControlFlowNode seq_origin,
|
||||
For loop, ControlFlowNodeWithPointsTo iter, Value str, Value seq, ControlFlowNode seq_origin,
|
||||
ControlFlowNode str_origin
|
||||
where
|
||||
loop.getIter().getAFlowNode() = iter and
|
||||
|
||||
@@ -12,8 +12,11 @@
|
||||
*/
|
||||
|
||||
import python
|
||||
private import LegacyPointsTo
|
||||
|
||||
predicate originIsLocals(ControlFlowNode n) { n.pointsTo(_, _, Value::named("locals").getACall()) }
|
||||
predicate originIsLocals(ControlFlowNodeWithPointsTo n) {
|
||||
n.pointsTo(_, _, Value::named("locals").getACall())
|
||||
}
|
||||
|
||||
predicate modification_of_locals(ControlFlowNode f) {
|
||||
originIsLocals(f.(SubscriptNode).getObject()) and
|
||||
|
||||
@@ -12,8 +12,9 @@
|
||||
*/
|
||||
|
||||
import python
|
||||
private import LegacyPointsTo
|
||||
|
||||
from For loop, ControlFlowNode iter, Value v, ClassValue t, ControlFlowNode origin
|
||||
from For loop, ControlFlowNodeWithPointsTo iter, Value v, ClassValue t, ControlFlowNode origin
|
||||
where
|
||||
loop.getIter().getAFlowNode() = iter and
|
||||
iter.pointsTo(_, v, origin) and
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
*/
|
||||
|
||||
import python
|
||||
private import LegacyPointsTo
|
||||
|
||||
predicate calls_close(Call c) { exists(Attribute a | c.getFunc() = a and a.getName() = "close") }
|
||||
|
||||
@@ -22,7 +23,7 @@ predicate only_stmt_in_finally(Try t, Call c) {
|
||||
)
|
||||
}
|
||||
|
||||
predicate points_to_context_manager(ControlFlowNode f, ClassValue cls) {
|
||||
predicate points_to_context_manager(ControlFlowNodeWithPointsTo f, ClassValue cls) {
|
||||
forex(Value v | f.pointsTo(v) | v.getClass() = cls) and
|
||||
cls.isContextManager()
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
*/
|
||||
|
||||
import python
|
||||
private import LegacyPointsTo
|
||||
|
||||
predicate string_concat_in_loop(BinaryExpr b) {
|
||||
b.getOp() instanceof Add and
|
||||
@@ -19,7 +20,7 @@ predicate string_concat_in_loop(BinaryExpr b) {
|
||||
|
|
||||
d.getDefinition().(DefinitionNode).getValue() = add and
|
||||
u.getAUse() = add.getAnOperand() and
|
||||
add.getAnOperand().pointsTo().getClass() = ClassValue::str()
|
||||
add.getAnOperand().(ControlFlowNodeWithPointsTo).pointsTo().getClass() = ClassValue::str()
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -12,9 +12,10 @@
|
||||
*/
|
||||
|
||||
import python
|
||||
private import LegacyPointsTo
|
||||
|
||||
from CallNode call, string name
|
||||
where call.getFunction().pointsTo(Value::siteQuitter(name))
|
||||
where call.getFunction().(ControlFlowNodeWithPointsTo).pointsTo(Value::siteQuitter(name))
|
||||
select call,
|
||||
"The '" + name +
|
||||
"' site.Quitter object may not exist if the 'site' module is not loaded or is modified."
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
import python
|
||||
private import LegacyPointsTo
|
||||
|
||||
/** Whether `mox` or `.StubOutWithMock()` is used in thin module `m`. */
|
||||
predicate useOfMoxInModule(Module m) {
|
||||
exists(ModuleObject mox | mox.getName() = "mox" or mox.getName() = "mox3.mox" |
|
||||
exists(ControlFlowNode use |
|
||||
exists(ControlFlowNodeWithPointsTo use |
|
||||
use.refersTo(mox) and
|
||||
use.getScope().getEnclosingModule() = m
|
||||
)
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import python
|
||||
private import LegacyPointsTo
|
||||
|
||||
predicate monkey_patched_builtin(string name) {
|
||||
exists(AttrNode attr, SubscriptNode subscr, StringLiteral s |
|
||||
@@ -6,19 +7,19 @@ predicate monkey_patched_builtin(string name) {
|
||||
subscr.getIndex().getNode() = s and
|
||||
s.getText() = name and
|
||||
subscr.getObject() = attr and
|
||||
attr.getObject("__dict__").pointsTo(Module::builtinModule())
|
||||
attr.getObject("__dict__").(ControlFlowNodeWithPointsTo).pointsTo(Module::builtinModule())
|
||||
)
|
||||
or
|
||||
exists(CallNode call, ControlFlowNode bltn, StringLiteral s |
|
||||
exists(CallNode call, ControlFlowNodeWithPointsTo bltn, StringLiteral s |
|
||||
call.getArg(0) = bltn and
|
||||
bltn.pointsTo(Module::builtinModule()) and
|
||||
call.getArg(1).getNode() = s and
|
||||
s.getText() = name and
|
||||
call.getFunction().pointsTo(Value::named("setattr"))
|
||||
call.getFunction().(ControlFlowNodeWithPointsTo).pointsTo(Value::named("setattr"))
|
||||
)
|
||||
or
|
||||
exists(AttrNode attr |
|
||||
attr.isStore() and
|
||||
attr.getObject(name).pointsTo(Module::builtinModule())
|
||||
attr.getObject(name).(ControlFlowNodeWithPointsTo).pointsTo(Module::builtinModule())
|
||||
)
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
*/
|
||||
|
||||
import python
|
||||
private import LegacyPointsTo
|
||||
import Shadowing
|
||||
import semmle.python.types.Builtins
|
||||
|
||||
@@ -35,7 +36,9 @@ predicate shadows(Name d, GlobalVariable g, Function scope, int line) {
|
||||
|
||||
/* pytest dynamically populates its namespace so, we cannot look directly for the pytest.fixture function */
|
||||
AttrNode pytest_fixture_attr() {
|
||||
exists(ModuleValue pytest | result.getObject("fixture").pointsTo(pytest))
|
||||
exists(ModuleValue pytest |
|
||||
result.getObject("fixture").(ControlFlowNodeWithPointsTo).pointsTo(pytest)
|
||||
)
|
||||
}
|
||||
|
||||
Value pytest_fixture() {
|
||||
@@ -44,14 +47,15 @@ Value pytest_fixture() {
|
||||
or
|
||||
call.getFunction().(CallNode).getFunction() = pytest_fixture_attr()
|
||||
|
|
||||
call.pointsTo(result)
|
||||
call.(ControlFlowNodeWithPointsTo).pointsTo(result)
|
||||
)
|
||||
}
|
||||
|
||||
/* pytest fixtures require that the parameter name is also a global */
|
||||
predicate assigned_pytest_fixture(GlobalVariable v) {
|
||||
exists(NameNode def |
|
||||
def.defines(v) and def.(DefinitionNode).getValue().pointsTo(pytest_fixture())
|
||||
def.defines(v) and
|
||||
def.(DefinitionNode).getValue().(ControlFlowNodeWithPointsTo).pointsTo(pytest_fixture())
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
*/
|
||||
|
||||
import python
|
||||
private import LegacyPointsTo
|
||||
import Definition
|
||||
|
||||
predicate is_increment(Stmt s) {
|
||||
@@ -55,7 +56,7 @@ predicate points_to_call_to_range(ControlFlowNode f) {
|
||||
)
|
||||
or
|
||||
/* Handle list(range(...)) and list(list(range(...))) */
|
||||
f.(CallNode).pointsTo().getClass() = ClassValue::list() and
|
||||
f.(CallNode).(ControlFlowNodeWithPointsTo).pointsTo().getClass() = ClassValue::list() and
|
||||
points_to_call_to_range(f.(CallNode).getArg(0))
|
||||
}
|
||||
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
*/
|
||||
|
||||
import python
|
||||
private import LegacyPointsTo
|
||||
|
||||
/** Whether name is declared in the __all__ list of this module */
|
||||
predicate declaredInAll(Module m, StringLiteral name) {
|
||||
@@ -44,7 +45,7 @@ predicate mutates_globals(ModuleValue m) {
|
||||
enum_convert = enum_class.attr("_convert") and
|
||||
exists(CallNode call | call.getScope() = m.getScope() |
|
||||
enum_convert.getACall() = call or
|
||||
call.getFunction().pointsTo(enum_convert)
|
||||
call.getFunction().(ControlFlowNodeWithPointsTo).pointsTo(enum_convert)
|
||||
)
|
||||
)
|
||||
or
|
||||
@@ -52,7 +53,11 @@ predicate mutates_globals(ModuleValue m) {
|
||||
// analysis doesn't handle that well enough. So we need a special case for this
|
||||
not exists(enum_class.attr("_convert")) and
|
||||
exists(CallNode call | call.getScope() = m.getScope() |
|
||||
call.getFunction().(AttrNode).getObject(["_convert", "_convert_"]).pointsTo() = enum_class
|
||||
call.getFunction()
|
||||
.(AttrNode)
|
||||
.getObject(["_convert", "_convert_"])
|
||||
.(ControlFlowNodeWithPointsTo)
|
||||
.pointsTo() = enum_class
|
||||
)
|
||||
)
|
||||
)
|
||||
@@ -65,9 +70,9 @@ predicate is_exported_submodule_name(ModuleValue m, string exported_name) {
|
||||
|
||||
predicate contains_unknown_import_star(ModuleValue m) {
|
||||
exists(ImportStarNode imp | imp.getEnclosingModule() = m.getScope() |
|
||||
imp.getModule().pointsTo().isAbsent()
|
||||
imp.getModule().(ControlFlowNodeWithPointsTo).pointsTo().isAbsent()
|
||||
or
|
||||
not exists(imp.getModule().pointsTo())
|
||||
not exists(imp.getModule().(ControlFlowNodeWithPointsTo).pointsTo())
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
*/
|
||||
|
||||
import python
|
||||
private import LegacyPointsTo
|
||||
import analysis.DefinitionTracking
|
||||
|
||||
predicate uniqueness_error(int number, string what, string problem) {
|
||||
@@ -208,18 +209,22 @@ predicate function_object_consistency(string clsname, string problem, string wha
|
||||
predicate multiple_origins_per_object(Object obj) {
|
||||
not obj.isC() and
|
||||
not obj instanceof ModuleObject and
|
||||
exists(ControlFlowNode use, Context ctx |
|
||||
exists(ControlFlowNodeWithPointsTo use, Context ctx |
|
||||
strictcount(ControlFlowNode orig | use.refersTo(ctx, obj, _, orig)) > 1
|
||||
)
|
||||
}
|
||||
|
||||
predicate intermediate_origins(ControlFlowNode use, ControlFlowNode inter, Object obj) {
|
||||
predicate intermediate_origins(
|
||||
ControlFlowNodeWithPointsTo use, ControlFlowNodeWithPointsTo inter, Object obj
|
||||
) {
|
||||
exists(ControlFlowNode orig, Context ctx | not inter = orig |
|
||||
use.refersTo(ctx, obj, _, inter) and
|
||||
inter.refersTo(ctx, obj, _, orig) and
|
||||
// It can sometimes happen that two different modules (e.g. cPickle and Pickle)
|
||||
// have the same attribute, but different origins.
|
||||
not strictcount(Object val | inter.(AttrNode).getObject().refersTo(val)) > 1
|
||||
not strictcount(Object val |
|
||||
inter.(AttrNode).getObject().(ControlFlowNodeWithPointsTo).refersTo(val)
|
||||
) > 1
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
*/
|
||||
|
||||
import python
|
||||
private import LegacyPointsTo
|
||||
import semmle.python.pointsto.PointsTo
|
||||
import semmle.python.pointsto.PointsToContext
|
||||
|
||||
@@ -18,11 +19,11 @@ predicate trivial(ControlFlowNode f) {
|
||||
from int interesting_facts, int interesting_facts_in_source, int total_size, float efficiency
|
||||
where
|
||||
interesting_facts =
|
||||
strictcount(ControlFlowNode f, Object value, ClassObject cls |
|
||||
strictcount(ControlFlowNodeWithPointsTo f, Object value, ClassObject cls |
|
||||
f.refersTo(value, cls, _) and not trivial(f)
|
||||
) and
|
||||
interesting_facts_in_source =
|
||||
strictcount(ControlFlowNode f, Object value, ClassObject cls |
|
||||
strictcount(ControlFlowNodeWithPointsTo f, Object value, ClassObject cls |
|
||||
f.refersTo(value, cls, _) and
|
||||
not trivial(f) and
|
||||
exists(f.getScope().getEnclosingModule().getFile().getRelativePath())
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
*/
|
||||
|
||||
import python
|
||||
private import LegacyPointsTo
|
||||
|
||||
ImportExpr alternative_import(ImportExpr ie) {
|
||||
exists(Alias thisalias, Alias otheralias |
|
||||
@@ -62,7 +63,10 @@ class VersionTest extends ControlFlowNode {
|
||||
VersionTest() {
|
||||
exists(string name |
|
||||
name.matches("%version%") and
|
||||
this.(CompareNode).getAChild+().pointsTo(Module::named("sys").attr(name))
|
||||
this.(CompareNode)
|
||||
.getAChild+()
|
||||
.(ControlFlowNodeWithPointsTo)
|
||||
.pointsTo(Module::named("sys").attr(name))
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -9,7 +9,8 @@
|
||||
*/
|
||||
|
||||
import python
|
||||
private import LegacyPointsTo
|
||||
|
||||
from Expr e
|
||||
where exists(ControlFlowNode f | f = e.getAFlowNode() | not f.refersTo(_))
|
||||
where exists(ControlFlowNodeWithPointsTo f | f = e.getAFlowNode() | not f.refersTo(_))
|
||||
select e, "Expression does not 'point-to' any object."
|
||||
|
||||
@@ -8,8 +8,9 @@
|
||||
*/
|
||||
|
||||
import python
|
||||
private import LegacyPointsTo
|
||||
|
||||
from ControlFlowNode f, Object o
|
||||
from ControlFlowNodeWithPointsTo f, Object o
|
||||
where
|
||||
f.refersTo(o) and
|
||||
not f.refersTo(o, _, _)
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
import python
|
||||
private import LegacyPointsTo
|
||||
|
||||
from ClassValue cls, string res
|
||||
where
|
||||
exists(CallNode call |
|
||||
call.getFunction().(NameNode).getId() = "test" and
|
||||
call.getAnArg().pointsTo(cls)
|
||||
call.getAnArg().(ControlFlowNodeWithPointsTo).pointsTo(cls)
|
||||
) and
|
||||
(
|
||||
cls.isSequence() and
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import python
|
||||
private import LegacyPointsTo
|
||||
|
||||
from int line, ControlFlowNode f, Object o, ControlFlowNode orig
|
||||
from int line, ControlFlowNodeWithPointsTo f, Object o, ControlFlowNode orig
|
||||
where
|
||||
not f.getLocation().getFile().inStdlib() and
|
||||
f.refersTo(o, orig) and
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import python
|
||||
private import LegacyPointsTo
|
||||
|
||||
from int line, ControlFlowNode f, Object o, ControlFlowNode orig
|
||||
from int line, ControlFlowNodeWithPointsTo f, Object o, ControlFlowNode orig
|
||||
where
|
||||
not f.getLocation().getFile().inStdlib() and
|
||||
f.refersTo(o, orig) and
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import python
|
||||
private import LegacyPointsTo
|
||||
|
||||
from int line, ControlFlowNode f, Object o, ClassObject cls, ControlFlowNode orig
|
||||
from int line, ControlFlowNodeWithPointsTo f, Object o, ClassObject cls, ControlFlowNode orig
|
||||
where
|
||||
not f.getLocation().getFile().inStdlib() and
|
||||
f.refersTo(o, cls, orig) and
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
import python
|
||||
private import LegacyPointsTo
|
||||
|
||||
string short_loc(Location l) { result = l.getFile().getShortName() + ":" + l.getStartLine() }
|
||||
|
||||
from ControlFlowNode use, Object obj, ControlFlowNode orig, int line
|
||||
from ControlFlowNodeWithPointsTo use, Object obj, ControlFlowNode orig, int line
|
||||
where
|
||||
use.refersTo(obj, orig) and
|
||||
use.getLocation().getFile().getShortName() = "test.py" and
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import python
|
||||
private import LegacyPointsTo
|
||||
|
||||
from ControlFlowNode f, Object o, ControlFlowNode x
|
||||
from ControlFlowNodeWithPointsTo f, Object o, ControlFlowNode x
|
||||
where f.refersTo(o, x)
|
||||
select f.getLocation().getStartLine(), f.toString(), o.toString(), x.getLocation().getStartLine()
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import python
|
||||
private import LegacyPointsTo
|
||||
|
||||
from ControlFlowNode f, Object o, ClassObject c, ControlFlowNode x
|
||||
from ControlFlowNodeWithPointsTo f, Object o, ClassObject c, ControlFlowNode x
|
||||
where f.refersTo(o, c, x)
|
||||
select f.getLocation().getStartLine(), f.toString(), o.toString(), c.toString(),
|
||||
x.getLocation().getStartLine()
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
import python
|
||||
private import LegacyPointsTo
|
||||
|
||||
from ClassValue cls, string res
|
||||
where
|
||||
exists(CallNode call |
|
||||
call.getFunction().(NameNode).getId() = "test" and
|
||||
call.getAnArg().pointsTo(cls)
|
||||
call.getAnArg().(ControlFlowNodeWithPointsTo).pointsTo(cls)
|
||||
) and
|
||||
(
|
||||
cls.isSequence() and
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import python
|
||||
private import LegacyPointsTo
|
||||
|
||||
from int line, ControlFlowNode f, Object o, ControlFlowNode orig
|
||||
from int line, ControlFlowNodeWithPointsTo f, Object o, ControlFlowNode orig
|
||||
where
|
||||
not f.getLocation().getFile().inStdlib() and
|
||||
f.refersTo(o, orig) and
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import python
|
||||
private import LegacyPointsTo
|
||||
|
||||
from int line, ControlFlowNode f, Object o, ClassObject cls, ControlFlowNode orig
|
||||
from int line, ControlFlowNodeWithPointsTo f, Object o, ClassObject cls, ControlFlowNode orig
|
||||
where
|
||||
not f.getLocation().getFile().inStdlib() and
|
||||
f.refersTo(o, cls, orig) and
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import python
|
||||
private import LegacyPointsTo
|
||||
|
||||
from ControlFlowNode f, Context ctx, Value v, ControlFlowNode origin
|
||||
from ControlFlowNodeWithPointsTo f, Context ctx, Value v, ControlFlowNode origin
|
||||
where
|
||||
f.pointsTo(ctx, v, origin) and
|
||||
f.getLocation().getFile().getBaseName() = "test.py"
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import python
|
||||
private import LegacyPointsTo
|
||||
import semmle.python.objects.Modules
|
||||
|
||||
from Value val, ControlFlowNode f
|
||||
from Value val, ControlFlowNodeWithPointsTo f
|
||||
where f.pointsTo(val)
|
||||
select f, val
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import python
|
||||
private import LegacyPointsTo
|
||||
|
||||
from CallNode call, Value func
|
||||
where call.getFunction().pointsTo(func)
|
||||
where call.getFunction().(ControlFlowNodeWithPointsTo).pointsTo(func)
|
||||
select call.getLocation().getStartLine(), call.toString(), func.toString()
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import python
|
||||
private import LegacyPointsTo
|
||||
|
||||
from int line, ControlFlowNode f, Value v
|
||||
from int line, ControlFlowNodeWithPointsTo f, Value v
|
||||
where
|
||||
any(ExprStmt s).getValue() = f.getNode() and
|
||||
line = f.getLocation().getStartLine() and
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
import python
|
||||
private import LegacyPointsTo
|
||||
|
||||
// We don't care about the internals of functools which vary from
|
||||
// version to version, just the end result.
|
||||
from NameNode f, Object o, ControlFlowNode x, int line
|
||||
where
|
||||
f.refersTo(o, x) and
|
||||
f.(ControlFlowNodeWithPointsTo).refersTo(o, x) and
|
||||
f.getLocation().getFile().getBaseName() = "test.py" and
|
||||
line = f.getLocation().getStartLine()
|
||||
select line, f.toString(), o.toString(), x.getLocation().toString()
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import python
|
||||
private import LegacyPointsTo
|
||||
import interesting
|
||||
|
||||
from int line, ControlFlowNode f, Object o, ImportTimeScope n
|
||||
from int line, ControlFlowNodeWithPointsTo f, Object o, ImportTimeScope n
|
||||
where
|
||||
of_interest(f, line) and
|
||||
f.refersTo(o) and
|
||||
|
||||
@@ -6,10 +6,11 @@
|
||||
*/
|
||||
|
||||
import python
|
||||
private import LegacyPointsTo
|
||||
import interesting
|
||||
import Util
|
||||
|
||||
from int line, ControlFlowNode f, Object o
|
||||
from int line, ControlFlowNodeWithPointsTo f, Object o
|
||||
where
|
||||
of_interest(f, line) and
|
||||
f.refersTo(o)
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
import python
|
||||
private import LegacyPointsTo
|
||||
import interesting
|
||||
import Util
|
||||
|
||||
from int line, ControlFlowNode f, Object o, ClassObject cls
|
||||
from int line, ControlFlowNodeWithPointsTo f, Object o, ClassObject cls
|
||||
where
|
||||
of_interest(f, line) and
|
||||
f.refersTo(o, cls, _)
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import python
|
||||
private import LegacyPointsTo
|
||||
|
||||
from ControlFlowNode f, Object o, ControlFlowNode x
|
||||
from ControlFlowNodeWithPointsTo f, Object o, ControlFlowNode x
|
||||
where
|
||||
f.refersTo(o, x) and
|
||||
exists(CallNode call | call.getFunction().getNode().(Name).getId() = "use" and call.getArg(0) = f)
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import python
|
||||
private import LegacyPointsTo
|
||||
|
||||
from ControlFlowNode f, Object o, ClassObject c, ControlFlowNode x
|
||||
from ControlFlowNodeWithPointsTo f, Object o, ClassObject c, ControlFlowNode x
|
||||
where
|
||||
f.refersTo(o, c, x) and
|
||||
exists(CallNode call | call.getFunction().getNode().(Name).getId() = "use" and call.getArg(0) = f)
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import python
|
||||
private import LegacyPointsTo
|
||||
|
||||
from ControlFlowNode f, Context ctx, Value v, ControlFlowNode origin
|
||||
from ControlFlowNodeWithPointsTo f, Context ctx, Value v, ControlFlowNode origin
|
||||
where f.pointsTo(ctx, v, origin)
|
||||
select f, ctx, v
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import python
|
||||
private import LegacyPointsTo
|
||||
|
||||
from ControlFlowNode f, Object o, ControlFlowNode x
|
||||
from ControlFlowNodeWithPointsTo f, Object o, ControlFlowNode x
|
||||
where
|
||||
f.refersTo(o, x) and
|
||||
f.getLocation().getFile().getBaseName() = "test.py"
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import python
|
||||
private import LegacyPointsTo
|
||||
|
||||
from ControlFlowNode f, Object o, ClassObject c, ControlFlowNode x
|
||||
from ControlFlowNodeWithPointsTo f, Object o, ClassObject c, ControlFlowNode x
|
||||
where
|
||||
f.refersTo(o, c, x) and
|
||||
f.getLocation().getFile().getBaseName() = "test.py"
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import python
|
||||
private import LegacyPointsTo
|
||||
|
||||
from NameNode n, Object value, ClassObject cls
|
||||
where n.getId() = "self" and n.refersTo(value, cls, _)
|
||||
where n.getId() = "self" and n.(ControlFlowNodeWithPointsTo).refersTo(value, cls, _)
|
||||
select n.getNode().getLocation().getStartLine(), value.toString(), cls.toString()
|
||||
|
||||
@@ -4,10 +4,11 @@
|
||||
*/
|
||||
|
||||
private import python
|
||||
private import LegacyPointsTo
|
||||
import semmle.python.dataflow.new.DataFlow
|
||||
|
||||
predicate pointsToOrigin(DataFlow::CfgNode pointer, DataFlow::CfgNode origin) {
|
||||
origin.getNode() = pointer.getNode().pointsTo().getOrigin()
|
||||
origin.getNode() = pointer.getNode().(ControlFlowNodeWithPointsTo).pointsTo().getOrigin()
|
||||
}
|
||||
|
||||
module PointsToConfig implements DataFlow::ConfigSig {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import python
|
||||
private import LegacyPointsTo
|
||||
import Util
|
||||
|
||||
from ControlFlowNode f, ControlFlowNode x
|
||||
from ControlFlowNodeWithPointsTo f, ControlFlowNode x
|
||||
where f.refersTo(theNoneObject(), _, x)
|
||||
select locate(f.getLocation(), "abcdghijklmopqr"), f.toString(), x.getLocation().getStartLine()
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import python
|
||||
private import LegacyPointsTo
|
||||
import Util
|
||||
|
||||
from ControlFlowNode f, Context ctx, Value v, ControlFlowNode origin
|
||||
from ControlFlowNodeWithPointsTo f, Context ctx, Value v, ControlFlowNode origin
|
||||
where f.pointsTo(ctx, v, origin)
|
||||
select locate(f.getLocation(), "abeghijklmnpqrstu"), f.toString(), ctx, vrepr(v),
|
||||
vrepr(v.getClass())
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import python
|
||||
private import LegacyPointsTo
|
||||
import semmle.python.objects.ObjectInternal
|
||||
|
||||
string vrepr(Value v) {
|
||||
@@ -8,6 +9,6 @@ string vrepr(Value v) {
|
||||
v = ObjectInternal::boundMethod() and result = "builtin-class method"
|
||||
}
|
||||
|
||||
from ControlFlowNode f, Context ctx, Value v, ControlFlowNode origin
|
||||
from ControlFlowNodeWithPointsTo f, Context ctx, Value v, ControlFlowNode origin
|
||||
where f.pointsTo(ctx, v, origin)
|
||||
select f.getLocation(), f.toString(), ctx, vrepr(v), vrepr(v.getClass())
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import python
|
||||
private import LegacyPointsTo
|
||||
|
||||
from ControlFlowNode arg, CallNode call, string debug
|
||||
from ControlFlowNodeWithPointsTo arg, CallNode call, string debug
|
||||
where
|
||||
call.getAnArg() = arg and
|
||||
call.getFunction().(NameNode).getId() = "check" and
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import python
|
||||
private import LegacyPointsTo
|
||||
|
||||
from ControlFlowNode arg, CallNode call, string debug
|
||||
from ControlFlowNodeWithPointsTo arg, CallNode call, string debug
|
||||
where
|
||||
call.getAnArg() = arg and
|
||||
call.getFunction().(NameNode).getId() = "check" and
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import python
|
||||
private import LegacyPointsTo
|
||||
|
||||
from ControlFlowNode arg, CallNode call, string debug
|
||||
from ControlFlowNodeWithPointsTo arg, CallNode call, string debug
|
||||
where
|
||||
call.getAnArg() = arg and
|
||||
call.getFunction().(NameNode).getId() = "check" and
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
import python
|
||||
private import LegacyPointsTo
|
||||
|
||||
from NameNode name, CallNode call, string debug
|
||||
where
|
||||
call.getAnArg() = name and
|
||||
call.getFunction().(NameNode).getId() = "check" and
|
||||
if exists(name.pointsTo())
|
||||
then debug = name.pointsTo().toString()
|
||||
if exists(name.(ControlFlowNodeWithPointsTo).pointsTo())
|
||||
then debug = name.(ControlFlowNodeWithPointsTo).pointsTo().toString()
|
||||
else debug = "<MISSING pointsTo()>"
|
||||
select name, debug
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
import python
|
||||
private import LegacyPointsTo
|
||||
import semmle.python.pointsto.PointsTo
|
||||
import semmle.python.pointsto.PointsToContext
|
||||
import semmle.python.objects.ObjectInternal
|
||||
|
||||
from CallNode call, SuperInstance sup, BoundMethodObjectInternal bm
|
||||
where
|
||||
call.getFunction().inferredValue() = bm and
|
||||
call.getFunction().(AttrNode).getObject().inferredValue() = sup
|
||||
call.getFunction().(ControlFlowNodeWithPointsTo).inferredValue() = bm and
|
||||
call.getFunction().(AttrNode).getObject().(ControlFlowNodeWithPointsTo).inferredValue() = sup
|
||||
select call.getLocation().getStartLine(), call.toString(),
|
||||
bm.getFunction().getSource().(FunctionObject).getQualifiedName()
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import python
|
||||
private import LegacyPointsTo
|
||||
|
||||
from StringObject s, ControlFlowNode f
|
||||
from StringObject s, ControlFlowNodeWithPointsTo f
|
||||
where f.refersTo(s)
|
||||
select f.getLocation().toString(), s.getText()
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import python
|
||||
private import LegacyPointsTo
|
||||
import semmle.python.dataflow.TaintTracking
|
||||
|
||||
class SimpleTest extends TaintKind {
|
||||
@@ -30,7 +31,7 @@ predicate visit_call(CallNode call, FunctionObject func) {
|
||||
exists(AttrNode attr, ClassObject cls, string name |
|
||||
name.matches("visit\\_%") and
|
||||
func = cls.lookupAttribute(name) and
|
||||
attr.getObject("visit").refersTo(_, cls, _) and
|
||||
attr.getObject("visit").(ControlFlowNodeWithPointsTo).refersTo(_, cls, _) and
|
||||
attr = call.getFunction()
|
||||
)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user