mirror of
https://github.com/github/codeql.git
synced 2026-05-01 03:35:13 +02:00
Python ESSA: Move definition sub-classes from points-to folder to essa folder.
This commit is contained in:
@@ -590,3 +590,333 @@ private EssaVariable potential_input(EssaNodeRefinement ref) {
|
||||
var = ref.getSourceVariable()
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
|
||||
/** Python specific sub-class of generic EssaNodeDefinition */
|
||||
class PyNodeDefinition extends EssaNodeDefinition {
|
||||
|
||||
override string getRepresentation() {
|
||||
result = this.getAQlClass()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/** Python specific sub-class of generic EssaNodeRefinement */
|
||||
class PyNodeRefinement extends EssaNodeRefinement {
|
||||
|
||||
override string getRepresentation() {
|
||||
result = this.getAQlClass() + "(" + this.getInput().getRepresentation() + ")"
|
||||
or
|
||||
not exists(this.getInput()) and
|
||||
result = this.getAQlClass() + "(" + this.getSourceVariable().getName() + "??)"
|
||||
}
|
||||
}
|
||||
|
||||
/** An assignment to a variable `v = val` */
|
||||
class AssignmentDefinition extends PyNodeDefinition {
|
||||
|
||||
AssignmentDefinition() {
|
||||
SsaSource::assignment_definition(this.getSourceVariable(), this.getDefiningNode(), _)
|
||||
}
|
||||
|
||||
ControlFlowNode getValue() {
|
||||
SsaSource::assignment_definition(this.getSourceVariable(), this.getDefiningNode(), result)
|
||||
}
|
||||
|
||||
override string getRepresentation() {
|
||||
result = this.getValue().getNode().toString()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/** Capture of a raised exception `except ExceptionType ex:` */
|
||||
class ExceptionCapture extends PyNodeDefinition {
|
||||
|
||||
ExceptionCapture() {
|
||||
SsaSource::exception_capture(this.getSourceVariable(), this.getDefiningNode())
|
||||
}
|
||||
|
||||
ControlFlowNode getType() {
|
||||
exists(ExceptFlowNode ex |
|
||||
ex.getName() = this.getDefiningNode() and
|
||||
result = ex.getType()
|
||||
)
|
||||
}
|
||||
|
||||
override string getRepresentation() {
|
||||
result = "except " + this.getSourceVariable().getName()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/** An assignment to a variable as part of a multiple assignment `..., v, ... = val` */
|
||||
class MultiAssignmentDefinition extends PyNodeDefinition {
|
||||
|
||||
MultiAssignmentDefinition() {
|
||||
SsaSource::multi_assignment_definition(this.getSourceVariable(), this.getDefiningNode(), _, _)
|
||||
}
|
||||
|
||||
override string getRepresentation() {
|
||||
exists(ControlFlowNode value, int n |
|
||||
this.indexOf(n, value) and
|
||||
result = value.(DefinitionNode).getValue().getNode().toString() + "[" + n + "]"
|
||||
)
|
||||
}
|
||||
|
||||
predicate indexOf(int index, SequenceNode lhs) {
|
||||
SsaSource::multi_assignment_definition(this.getSourceVariable(), this.getDefiningNode(), index, lhs)
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/** A definition of a variable in a `with` statement */
|
||||
class WithDefinition extends PyNodeDefinition {
|
||||
|
||||
WithDefinition () {
|
||||
SsaSource::with_definition(this.getSourceVariable(), this.getDefiningNode())
|
||||
}
|
||||
|
||||
override string getRepresentation() {
|
||||
result = "with"
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/** A definition of a variable by declaring it as a parameter */
|
||||
class ParameterDefinition extends PyNodeDefinition {
|
||||
|
||||
ParameterDefinition() {
|
||||
SsaSource::parameter_definition(this.getSourceVariable(), this.getDefiningNode())
|
||||
}
|
||||
|
||||
predicate isSelf() {
|
||||
this.getDefiningNode().getNode().(Parameter).isSelf()
|
||||
}
|
||||
|
||||
/** Gets the control flow node for the default value of this parameter */
|
||||
ControlFlowNode getDefault() {
|
||||
result.getNode() = this.getParameter().getDefault()
|
||||
}
|
||||
|
||||
/** Gets the annotation control flow node of this parameter */
|
||||
ControlFlowNode getAnnotation() {
|
||||
result.getNode() = this.getParameter().getAnnotation()
|
||||
}
|
||||
|
||||
/** Gets the name of this parameter definition */
|
||||
string getName() {
|
||||
result = this.getParameter().asName().getId()
|
||||
}
|
||||
|
||||
predicate isVarargs() {
|
||||
exists(Function func | func.getVararg() = this.getDefiningNode().getNode())
|
||||
}
|
||||
|
||||
/** Holds if this parameter is a 'kwargs' parameter.
|
||||
* The `kwargs` in `f(a, b, **kwargs)`.
|
||||
*/
|
||||
predicate isKwargs() {
|
||||
exists(Function func | func.getKwarg() = this.getDefiningNode().getNode())
|
||||
}
|
||||
|
||||
Parameter getParameter() {
|
||||
result = this.getDefiningNode().getNode()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/** A deletion of a variable `del v` */
|
||||
class DeletionDefinition extends PyNodeDefinition {
|
||||
|
||||
DeletionDefinition() {
|
||||
SsaSource::deletion_definition(this.getSourceVariable(), this.getDefiningNode())
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/** Definition of variable at the entry of a scope. Usually this represents the transfer of
|
||||
* a global or non-local variable from one scope to another.
|
||||
*/
|
||||
class ScopeEntryDefinition extends PyNodeDefinition {
|
||||
|
||||
ScopeEntryDefinition() {
|
||||
this.getDefiningNode() = this.getSourceVariable().(PythonSsaSourceVariable).getScopeEntryDefinition() and
|
||||
not this instanceof ImplicitSubModuleDefinition
|
||||
}
|
||||
|
||||
override Scope getScope() {
|
||||
result.getEntryNode() = this.getDefiningNode()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/** Possible redefinition of variable via `from ... import *` */
|
||||
class ImportStarRefinement extends PyNodeRefinement {
|
||||
|
||||
ImportStarRefinement() {
|
||||
SsaSource::import_star_refinement(this.getSourceVariable(), _, this.getDefiningNode())
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/** Assignment of an attribute `obj.attr = val` */
|
||||
class AttributeAssignment extends PyNodeRefinement {
|
||||
|
||||
AttributeAssignment() {
|
||||
SsaSource::attribute_assignment_refinement(this.getSourceVariable(), _, this.getDefiningNode())
|
||||
}
|
||||
|
||||
string getName() {
|
||||
result = this.getDefiningNode().(AttrNode).getName()
|
||||
}
|
||||
|
||||
ControlFlowNode getValue() {
|
||||
result = this.getDefiningNode().(DefinitionNode).getValue()
|
||||
}
|
||||
|
||||
override string getRepresentation() {
|
||||
result = this.getAQlClass() + " '" + this.getName() + "'(" + this.getInput().getRepresentation() + ")"
|
||||
or
|
||||
not exists(this.getInput()) and
|
||||
result = this.getAQlClass() + " '" + this.getName() + "'(" + this.getSourceVariable().getName() + "??)"
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/** A use of a variable as an argument, `foo(v)`, which might modify the object referred to. */
|
||||
class ArgumentRefinement extends PyNodeRefinement {
|
||||
|
||||
ControlFlowNode argument;
|
||||
|
||||
ArgumentRefinement() {
|
||||
SsaSource::argument_refinement(this.getSourceVariable(), argument, this.getDefiningNode())
|
||||
}
|
||||
|
||||
ControlFlowNode getArgument() { result = argument }
|
||||
|
||||
CallNode getCall() { result = this.getDefiningNode() }
|
||||
}
|
||||
|
||||
/** Deletion of an attribute `del obj.attr`. */
|
||||
class EssaAttributeDeletion extends PyNodeRefinement {
|
||||
|
||||
EssaAttributeDeletion() {
|
||||
SsaSource::attribute_deletion_refinement(this.getSourceVariable(), _, this.getDefiningNode())
|
||||
}
|
||||
|
||||
string getName() {
|
||||
result = this.getDefiningNode().(AttrNode).getName()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/** A pi-node (guard) with only one successor. */
|
||||
class SingleSuccessorGuard extends PyNodeRefinement {
|
||||
|
||||
SingleSuccessorGuard() {
|
||||
SsaSource::test_refinement(this.getSourceVariable(), _, this.getDefiningNode())
|
||||
}
|
||||
|
||||
boolean getSense() {
|
||||
exists(this.getDefiningNode().getAFalseSuccessor()) and result = false
|
||||
or
|
||||
exists(this.getDefiningNode().getATrueSuccessor()) and result = true
|
||||
}
|
||||
|
||||
override string getRepresentation() {
|
||||
result = PyNodeRefinement.super.getRepresentation() + " [" + this.getSense().toString() + "]"
|
||||
or
|
||||
not exists(this.getSense()) and
|
||||
result = PyNodeRefinement.super.getRepresentation() + " [??]"
|
||||
}
|
||||
|
||||
ControlFlowNode getTest() {
|
||||
result = this.getDefiningNode()
|
||||
}
|
||||
|
||||
predicate useAndTest(ControlFlowNode use, ControlFlowNode test) {
|
||||
test = this.getDefiningNode() and
|
||||
SsaSource::test_refinement(this.getSourceVariable(), use, test)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/** Implicit definition of the names of sub-modules in a package.
|
||||
* Although the interpreter does not pre-define these names, merely populating them
|
||||
* as they are imported, this is a good approximation for static analysis.
|
||||
*/
|
||||
class ImplicitSubModuleDefinition extends PyNodeDefinition {
|
||||
|
||||
ImplicitSubModuleDefinition() {
|
||||
SsaSource::init_module_submodule_defn(this.getSourceVariable(), this.getDefiningNode())
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/** An implicit (possible) definition of an escaping variable at a call-site */
|
||||
class CallsiteRefinement extends PyNodeRefinement {
|
||||
|
||||
override string toString() {
|
||||
result = "CallsiteRefinement"
|
||||
}
|
||||
|
||||
CallsiteRefinement() {
|
||||
exists(PythonSsaSourceVariable var, ControlFlowNode defn |
|
||||
defn = var.redefinedAtCallSite() and
|
||||
this.definedBy(var, defn) and
|
||||
not this instanceof ArgumentRefinement and
|
||||
not this instanceof MethodCallsiteRefinement and
|
||||
not this instanceof SingleSuccessorGuard
|
||||
)
|
||||
}
|
||||
|
||||
CallNode getCall() {
|
||||
this.getDefiningNode() = result
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/** An implicit (possible) modification of the object referred at a method call */
|
||||
class MethodCallsiteRefinement extends PyNodeRefinement {
|
||||
|
||||
MethodCallsiteRefinement() {
|
||||
SsaSource::method_call_refinement(this.getSourceVariable(), _, this.getDefiningNode())
|
||||
and not this instanceof SingleSuccessorGuard
|
||||
}
|
||||
|
||||
CallNode getCall() {
|
||||
this.getDefiningNode() = result
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/** An implicit (possible) modification of `self` at a method call */
|
||||
class SelfCallsiteRefinement extends MethodCallsiteRefinement {
|
||||
|
||||
SelfCallsiteRefinement() {
|
||||
this.getSourceVariable().(Variable).isSelf()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/** Python specific sub-class of generic EssaEdgeRefinement */
|
||||
class PyEdgeRefinement extends EssaEdgeRefinement {
|
||||
|
||||
override string getRepresentation() {
|
||||
/* This is for testing so use capital 'P' to make it sort before 'phi' and
|
||||
* be more visually distinctive. */
|
||||
result = "Pi(" + this.getInput().getRepresentation() + ") [" + this.getSense() + "]"
|
||||
or
|
||||
not exists(this.getInput()) and
|
||||
result = "Pi(" + this.getSourceVariable().getName() + "??) [" + this.getSense() + "]"
|
||||
}
|
||||
|
||||
ControlFlowNode getTest() {
|
||||
result = this.getPredecessor().getLastNode()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -174,139 +174,6 @@ predicate function_can_never_return(FunctionObject func) {
|
||||
func = ModuleObject::named("sys").attr("exit")
|
||||
}
|
||||
|
||||
/** Python specific sub-class of generic EssaNodeDefinition */
|
||||
class PyNodeDefinition extends EssaNodeDefinition {
|
||||
|
||||
override string getRepresentation() {
|
||||
result = this.getAQlClass()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/** Python specific sub-class of generic EssaNodeRefinement */
|
||||
class PyNodeRefinement extends EssaNodeRefinement {
|
||||
|
||||
override string getRepresentation() {
|
||||
result = this.getAQlClass() + "(" + this.getInput().getRepresentation() + ")"
|
||||
or
|
||||
not exists(this.getInput()) and
|
||||
result = this.getAQlClass() + "(" + this.getSourceVariable().getName() + "??)"
|
||||
}
|
||||
}
|
||||
|
||||
/** An assignment to a variable `v = val` */
|
||||
class AssignmentDefinition extends PyNodeDefinition {
|
||||
|
||||
AssignmentDefinition() {
|
||||
SsaSource::assignment_definition(this.getSourceVariable(), this.getDefiningNode(), _)
|
||||
}
|
||||
|
||||
ControlFlowNode getValue() {
|
||||
SsaSource::assignment_definition(this.getSourceVariable(), this.getDefiningNode(), result)
|
||||
}
|
||||
|
||||
override string getRepresentation() {
|
||||
result = this.getValue().getNode().toString()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/** Capture of a raised exception `except ExceptionType ex:` */
|
||||
class ExceptionCapture extends PyNodeDefinition {
|
||||
|
||||
ExceptionCapture() {
|
||||
SsaSource::exception_capture(this.getSourceVariable(), this.getDefiningNode())
|
||||
}
|
||||
|
||||
ControlFlowNode getType() {
|
||||
exists(ExceptFlowNode ex |
|
||||
ex.getName() = this.getDefiningNode() and
|
||||
result = ex.getType()
|
||||
)
|
||||
}
|
||||
|
||||
override string getRepresentation() {
|
||||
result = "except " + this.getSourceVariable().getName()
|
||||
}
|
||||
|
||||
}
|
||||
/** An assignment to a variable as part of a multiple assignment `..., v, ... = val` */
|
||||
class MultiAssignmentDefinition extends PyNodeDefinition {
|
||||
|
||||
MultiAssignmentDefinition() {
|
||||
SsaSource::multi_assignment_definition(this.getSourceVariable(), this.getDefiningNode(), _, _)
|
||||
}
|
||||
|
||||
override string getRepresentation() {
|
||||
exists(ControlFlowNode value, int n |
|
||||
this.indexOf(n, value) and
|
||||
result = value.(DefinitionNode).getValue().getNode().toString() + "[" + n + "]"
|
||||
)
|
||||
}
|
||||
|
||||
predicate indexOf(int index, SequenceNode lhs) {
|
||||
SsaSource::multi_assignment_definition(this.getSourceVariable(), this.getDefiningNode(), index, lhs)
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
class WithDefinition extends PyNodeDefinition {
|
||||
|
||||
WithDefinition () {
|
||||
SsaSource::with_definition(this.getSourceVariable(), this.getDefiningNode())
|
||||
}
|
||||
|
||||
override string getRepresentation() {
|
||||
result = "with"
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/** A definition of a variable by declaring it as a parameter */
|
||||
class ParameterDefinition extends PyNodeDefinition {
|
||||
|
||||
ParameterDefinition() {
|
||||
SsaSource::parameter_definition(this.getSourceVariable(), this.getDefiningNode())
|
||||
}
|
||||
|
||||
predicate isSelf() {
|
||||
this.getDefiningNode().getNode().(Parameter).isSelf()
|
||||
}
|
||||
|
||||
/** Gets the control flow node for the default value of this parameter */
|
||||
ControlFlowNode getDefault() {
|
||||
result.getNode() = this.getParameter().getDefault()
|
||||
}
|
||||
|
||||
/** Gets the annotation control flow node of this parameter */
|
||||
ControlFlowNode getAnnotation() {
|
||||
result.getNode() = this.getParameter().getAnnotation()
|
||||
}
|
||||
|
||||
/** Gets the name of this parameter definition */
|
||||
string getName() {
|
||||
result = this.getParameter().asName().getId()
|
||||
}
|
||||
|
||||
predicate isVarargs() {
|
||||
exists(Function func | func.getVararg() = this.getDefiningNode().getNode())
|
||||
}
|
||||
|
||||
/** Holds if this parameter is a 'kwargs' parameter.
|
||||
* The `kwargs` in `f(a, b, **kwargs)`.
|
||||
*/
|
||||
predicate isKwargs() {
|
||||
exists(Function func | func.getKwarg() = this.getDefiningNode().getNode())
|
||||
}
|
||||
|
||||
Parameter getParameter() {
|
||||
result = this.getDefiningNode().getNode()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
private newtype TIterationDefinition =
|
||||
TIterationDefinition_(SsaSourceVariable var, ControlFlowNode def, ControlFlowNode sequence) {
|
||||
@@ -328,198 +195,6 @@ deprecated class IterationDefinition extends TIterationDefinition {
|
||||
}
|
||||
|
||||
|
||||
/** A deletion of a variable `del v` */
|
||||
class DeletionDefinition extends PyNodeDefinition {
|
||||
|
||||
DeletionDefinition() {
|
||||
SsaSource::deletion_definition(this.getSourceVariable(), this.getDefiningNode())
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/** Definition of variable at the entry of a scope. Usually this represents the transfer of
|
||||
* a global or non-local variable from one scope to another.
|
||||
*/
|
||||
class ScopeEntryDefinition extends PyNodeDefinition {
|
||||
|
||||
ScopeEntryDefinition() {
|
||||
this.getDefiningNode() = this.getSourceVariable().(PythonSsaSourceVariable).getScopeEntryDefinition() and
|
||||
not this instanceof ImplicitSubModuleDefinition
|
||||
}
|
||||
|
||||
override Scope getScope() {
|
||||
result.getEntryNode() = this.getDefiningNode()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/** Possible redefinition of variable via `from ... import *` */
|
||||
class ImportStarRefinement extends PyNodeRefinement {
|
||||
|
||||
ImportStarRefinement() {
|
||||
SsaSource::import_star_refinement(this.getSourceVariable(), _, this.getDefiningNode())
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/** Assignment of an attribute `obj.attr = val` */
|
||||
class AttributeAssignment extends PyNodeRefinement {
|
||||
|
||||
AttributeAssignment() {
|
||||
SsaSource::attribute_assignment_refinement(this.getSourceVariable(), _, this.getDefiningNode())
|
||||
}
|
||||
|
||||
string getName() {
|
||||
result = this.getDefiningNode().(AttrNode).getName()
|
||||
}
|
||||
|
||||
ControlFlowNode getValue() {
|
||||
result = this.getDefiningNode().(DefinitionNode).getValue()
|
||||
}
|
||||
|
||||
override string getRepresentation() {
|
||||
result = this.getAQlClass() + " '" + this.getName() + "'(" + this.getInput().getRepresentation() + ")"
|
||||
or
|
||||
not exists(this.getInput()) and
|
||||
result = this.getAQlClass() + " '" + this.getName() + "'(" + this.getSourceVariable().getName() + "??)"
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/** A use of a variable as an argument, `foo(v)`, which might modify the object referred to. */
|
||||
class ArgumentRefinement extends PyNodeRefinement {
|
||||
|
||||
ControlFlowNode argument;
|
||||
|
||||
ArgumentRefinement() {
|
||||
SsaSource::argument_refinement(this.getSourceVariable(), argument, this.getDefiningNode())
|
||||
}
|
||||
|
||||
ControlFlowNode getArgument() { result = argument }
|
||||
|
||||
CallNode getCall() { result = this.getDefiningNode() }
|
||||
}
|
||||
|
||||
/** Deletion of an attribute `del obj.attr`. */
|
||||
class EssaAttributeDeletion extends PyNodeRefinement {
|
||||
|
||||
EssaAttributeDeletion() {
|
||||
SsaSource::attribute_deletion_refinement(this.getSourceVariable(), _, this.getDefiningNode())
|
||||
}
|
||||
|
||||
string getName() {
|
||||
result = this.getDefiningNode().(AttrNode).getName()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/** A pi-node (guard) with only one successor. */
|
||||
class SingleSuccessorGuard extends PyNodeRefinement {
|
||||
|
||||
SingleSuccessorGuard() {
|
||||
SsaSource::test_refinement(this.getSourceVariable(), _, this.getDefiningNode())
|
||||
}
|
||||
|
||||
boolean getSense() {
|
||||
exists(this.getDefiningNode().getAFalseSuccessor()) and result = false
|
||||
or
|
||||
exists(this.getDefiningNode().getATrueSuccessor()) and result = true
|
||||
}
|
||||
|
||||
override string getRepresentation() {
|
||||
result = PyNodeRefinement.super.getRepresentation() + " [" + this.getSense().toString() + "]"
|
||||
or
|
||||
not exists(this.getSense()) and
|
||||
result = PyNodeRefinement.super.getRepresentation() + " [??]"
|
||||
}
|
||||
|
||||
ControlFlowNode getTest() {
|
||||
result = this.getDefiningNode()
|
||||
}
|
||||
|
||||
predicate useAndTest(ControlFlowNode use, ControlFlowNode test) {
|
||||
test = this.getDefiningNode() and
|
||||
SsaSource::test_refinement(this.getSourceVariable(), use, test)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/** Implicit definition of the names of sub-modules in a package.
|
||||
* Although the interpreter does not pre-define these names, merely populating them
|
||||
* as they are imported, this is a good approximation for static analysis.
|
||||
*/
|
||||
class ImplicitSubModuleDefinition extends PyNodeDefinition {
|
||||
|
||||
ImplicitSubModuleDefinition() {
|
||||
SsaSource::init_module_submodule_defn(this.getSourceVariable(), this.getDefiningNode())
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/** An implicit (possible) definition of an escaping variable at a call-site */
|
||||
class CallsiteRefinement extends PyNodeRefinement {
|
||||
|
||||
override string toString() {
|
||||
result = "CallsiteRefinement"
|
||||
}
|
||||
|
||||
CallsiteRefinement() {
|
||||
exists(PythonSsaSourceVariable var, ControlFlowNode defn |
|
||||
defn = var.redefinedAtCallSite() and
|
||||
this.definedBy(var, defn) and
|
||||
not this instanceof ArgumentRefinement and
|
||||
not this instanceof MethodCallsiteRefinement and
|
||||
not this instanceof SingleSuccessorGuard
|
||||
)
|
||||
}
|
||||
|
||||
CallNode getCall() {
|
||||
this.getDefiningNode() = result
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/** An implicit (possible) modification of the object referred at a method call */
|
||||
class MethodCallsiteRefinement extends PyNodeRefinement {
|
||||
|
||||
MethodCallsiteRefinement() {
|
||||
SsaSource::method_call_refinement(this.getSourceVariable(), _, this.getDefiningNode())
|
||||
and not this instanceof SingleSuccessorGuard
|
||||
}
|
||||
|
||||
CallNode getCall() {
|
||||
this.getDefiningNode() = result
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/** An implicit (possible) modification of `self` at a method call */
|
||||
class SelfCallsiteRefinement extends MethodCallsiteRefinement {
|
||||
|
||||
SelfCallsiteRefinement() {
|
||||
this.getSourceVariable().(Variable).isSelf()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/** Python specific sub-class of generic EssaEdgeRefinement */
|
||||
class PyEdgeRefinement extends EssaEdgeRefinement {
|
||||
|
||||
override string getRepresentation() {
|
||||
/* This is for testing so use capital 'P' to make it sort before 'phi' and
|
||||
* be more visually distinctive. */
|
||||
result = "Pi(" + this.getInput().getRepresentation() + ") [" + this.getSense() + "]"
|
||||
or
|
||||
not exists(this.getInput()) and
|
||||
result = "Pi(" + this.getSourceVariable().getName() + "??) [" + this.getSense() + "]"
|
||||
}
|
||||
|
||||
ControlFlowNode getTest() {
|
||||
result = this.getPredecessor().getLastNode()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/** Hold if outer contains inner, both are contained within a test and inner is a use is a plain use or an attribute lookup */
|
||||
pragma[noinline]
|
||||
predicate contains_interesting_expression_within_test(ControlFlowNode outer, ControlFlowNode inner) {
|
||||
|
||||
Reference in New Issue
Block a user