mirror of
https://github.com/github/codeql.git
synced 2026-04-29 18:55:14 +02:00
Python: Autoformat everything using qlformat.
Will need subsequent PRs fixing up test failures (due to deprecated methods moving around), but other than that everything should be straight-forward.
This commit is contained in:
@@ -6,138 +6,138 @@ import python
|
||||
import semmle.python.pointsto.PointsTo
|
||||
|
||||
private newtype TDefinition =
|
||||
TLocalDefinition(AstNode a) { a instanceof Expr or a instanceof Stmt or a instanceof Module }
|
||||
TLocalDefinition(AstNode a) { a instanceof Expr or a instanceof Stmt or a instanceof Module }
|
||||
|
||||
/** A definition for the purposes of jump-to-definition. */
|
||||
class Definition extends TLocalDefinition {
|
||||
/** Gets a textual representation of this element. */
|
||||
string toString() { result = "Definition " + this.getAstNode().getLocation().toString() }
|
||||
/** Gets a textual representation of this element. */
|
||||
string toString() { result = "Definition " + this.getAstNode().getLocation().toString() }
|
||||
|
||||
AstNode getAstNode() { this = TLocalDefinition(result) }
|
||||
AstNode getAstNode() { this = TLocalDefinition(result) }
|
||||
|
||||
Module getModule() { result = this.getAstNode().getScope().getEnclosingModule() }
|
||||
Module getModule() { result = this.getAstNode().getScope().getEnclosingModule() }
|
||||
|
||||
Location getLocation() { result = this.getAstNode().getLocation() }
|
||||
Location getLocation() { result = this.getAstNode().getLocation() }
|
||||
}
|
||||
|
||||
private predicate jump_to_defn(ControlFlowNode use, Definition defn) {
|
||||
exists(EssaVariable var |
|
||||
use = var.getASourceUse() and
|
||||
ssa_variable_defn(var, defn)
|
||||
)
|
||||
or
|
||||
exists(string name |
|
||||
use.isLoad() and
|
||||
jump_to_defn_attribute(use.(AttrNode).getObject(name), name, defn)
|
||||
)
|
||||
or
|
||||
exists(PythonModuleObject mod |
|
||||
use.(ImportExprNode).refersTo(mod) and
|
||||
defn.getAstNode() = mod.getModule()
|
||||
)
|
||||
or
|
||||
exists(PythonModuleObject mod, string name |
|
||||
use.(ImportMemberNode).getModule(name).refersTo(mod) and
|
||||
scope_jump_to_defn_attribute(mod.getModule(), name, defn)
|
||||
)
|
||||
or
|
||||
exists(PackageObject package |
|
||||
use.(ImportExprNode).refersTo(package) and
|
||||
defn.getAstNode() = package.getInitModule().getModule()
|
||||
)
|
||||
or
|
||||
exists(PackageObject package, string name |
|
||||
use.(ImportMemberNode).getModule(name).refersTo(package) and
|
||||
scope_jump_to_defn_attribute(package.getInitModule().getModule(), name, defn)
|
||||
)
|
||||
or
|
||||
(use instanceof PyFunctionObject or use instanceof ClassObject) and
|
||||
defn.getAstNode() = use.getNode()
|
||||
exists(EssaVariable var |
|
||||
use = var.getASourceUse() and
|
||||
ssa_variable_defn(var, defn)
|
||||
)
|
||||
or
|
||||
exists(string name |
|
||||
use.isLoad() and
|
||||
jump_to_defn_attribute(use.(AttrNode).getObject(name), name, defn)
|
||||
)
|
||||
or
|
||||
exists(PythonModuleObject mod |
|
||||
use.(ImportExprNode).refersTo(mod) and
|
||||
defn.getAstNode() = mod.getModule()
|
||||
)
|
||||
or
|
||||
exists(PythonModuleObject mod, string name |
|
||||
use.(ImportMemberNode).getModule(name).refersTo(mod) and
|
||||
scope_jump_to_defn_attribute(mod.getModule(), name, defn)
|
||||
)
|
||||
or
|
||||
exists(PackageObject package |
|
||||
use.(ImportExprNode).refersTo(package) and
|
||||
defn.getAstNode() = package.getInitModule().getModule()
|
||||
)
|
||||
or
|
||||
exists(PackageObject package, string name |
|
||||
use.(ImportMemberNode).getModule(name).refersTo(package) and
|
||||
scope_jump_to_defn_attribute(package.getInitModule().getModule(), name, defn)
|
||||
)
|
||||
or
|
||||
(use instanceof PyFunctionObject or use instanceof ClassObject) and
|
||||
defn.getAstNode() = use.getNode()
|
||||
}
|
||||
|
||||
/* Prefer class and functions to class-expressions and function-expressions. */
|
||||
private predicate preferred_jump_to_defn(Expr use, Definition def) {
|
||||
not use instanceof ClassExpr and
|
||||
not use instanceof FunctionExpr and
|
||||
jump_to_defn(use.getAFlowNode(), def)
|
||||
not use instanceof ClassExpr and
|
||||
not use instanceof FunctionExpr and
|
||||
jump_to_defn(use.getAFlowNode(), def)
|
||||
}
|
||||
|
||||
private predicate unique_jump_to_defn(Expr use, Definition def) {
|
||||
preferred_jump_to_defn(use, def) and
|
||||
not exists(Definition other |
|
||||
other != def and
|
||||
preferred_jump_to_defn(use, other)
|
||||
)
|
||||
preferred_jump_to_defn(use, def) and
|
||||
not exists(Definition other |
|
||||
other != def and
|
||||
preferred_jump_to_defn(use, other)
|
||||
)
|
||||
}
|
||||
|
||||
private predicate ssa_variable_defn(EssaVariable var, Definition defn) {
|
||||
ssa_defn_defn(var.getDefinition(), defn)
|
||||
ssa_defn_defn(var.getDefinition(), defn)
|
||||
}
|
||||
|
||||
/** Holds if the phi-function `phi` refers to (`value`, `cls`, `origin`) given the context `context`. */
|
||||
private predicate ssa_phi_defn(PhiFunction phi, Definition defn) {
|
||||
ssa_variable_defn(phi.getAnInput(), defn)
|
||||
ssa_variable_defn(phi.getAnInput(), defn)
|
||||
}
|
||||
|
||||
/** Holds if the ESSA defn `def` refers to (`value`, `cls`, `origin`) given the context `context`. */
|
||||
private predicate ssa_defn_defn(EssaDefinition def, Definition defn) {
|
||||
ssa_phi_defn(def, defn)
|
||||
or
|
||||
ssa_node_defn(def, defn)
|
||||
or
|
||||
ssa_filter_defn(def, defn)
|
||||
or
|
||||
ssa_node_refinement_defn(def, defn)
|
||||
ssa_phi_defn(def, defn)
|
||||
or
|
||||
ssa_node_defn(def, defn)
|
||||
or
|
||||
ssa_filter_defn(def, defn)
|
||||
or
|
||||
ssa_node_refinement_defn(def, defn)
|
||||
}
|
||||
|
||||
/** Holds if ESSA edge refinement, `def`, is defined by `defn` */
|
||||
predicate ssa_filter_defn(PyEdgeRefinement def, Definition defn) {
|
||||
ssa_variable_defn(def.getInput(), defn)
|
||||
ssa_variable_defn(def.getInput(), defn)
|
||||
}
|
||||
|
||||
/** Holds if ESSA defn, `uniphi`,is defined by `defn` */
|
||||
predicate uni_edged_phi_defn(SingleSuccessorGuard uniphi, Definition defn) {
|
||||
ssa_variable_defn(uniphi.getInput(), defn)
|
||||
ssa_variable_defn(uniphi.getInput(), defn)
|
||||
}
|
||||
|
||||
pragma[noinline]
|
||||
private predicate ssa_node_defn(EssaNodeDefinition def, Definition defn) {
|
||||
assignment_jump_to_defn(def, defn)
|
||||
or
|
||||
parameter_defn(def, defn)
|
||||
or
|
||||
delete_defn(def, defn)
|
||||
or
|
||||
scope_entry_defn(def, defn)
|
||||
or
|
||||
implicit_submodule_defn(def, defn)
|
||||
assignment_jump_to_defn(def, defn)
|
||||
or
|
||||
parameter_defn(def, defn)
|
||||
or
|
||||
delete_defn(def, defn)
|
||||
or
|
||||
scope_entry_defn(def, defn)
|
||||
or
|
||||
implicit_submodule_defn(def, defn)
|
||||
}
|
||||
|
||||
/* Definition for normal assignments `def = ...` */
|
||||
private predicate assignment_jump_to_defn(AssignmentDefinition def, Definition defn) {
|
||||
defn = TLocalDefinition(def.getValue().getNode())
|
||||
defn = TLocalDefinition(def.getValue().getNode())
|
||||
}
|
||||
|
||||
pragma[noinline]
|
||||
private predicate ssa_node_refinement_defn(EssaNodeRefinement def, Definition defn) {
|
||||
method_callsite_defn(def, defn)
|
||||
or
|
||||
import_star_defn(def, defn)
|
||||
or
|
||||
attribute_assignment_defn(def, defn)
|
||||
or
|
||||
callsite_defn(def, defn)
|
||||
or
|
||||
argument_defn(def, defn)
|
||||
or
|
||||
attribute_delete_defn(def, defn)
|
||||
or
|
||||
uni_edged_phi_defn(def, defn)
|
||||
method_callsite_defn(def, defn)
|
||||
or
|
||||
import_star_defn(def, defn)
|
||||
or
|
||||
attribute_assignment_defn(def, defn)
|
||||
or
|
||||
callsite_defn(def, defn)
|
||||
or
|
||||
argument_defn(def, defn)
|
||||
or
|
||||
attribute_delete_defn(def, defn)
|
||||
or
|
||||
uni_edged_phi_defn(def, defn)
|
||||
}
|
||||
|
||||
/* Definition for parameter. `def foo(param): ...` */
|
||||
private predicate parameter_defn(ParameterDefinition def, Definition defn) {
|
||||
defn.getAstNode() = def.getDefiningNode().getNode()
|
||||
defn.getAstNode() = def.getDefiningNode().getNode()
|
||||
}
|
||||
|
||||
/* Definition for deletion: `del name` */
|
||||
@@ -145,11 +145,11 @@ private predicate delete_defn(DeletionDefinition def, Definition defn) { none()
|
||||
|
||||
/* Implicit "defn" of the names of submodules at the start of an `__init__.py` file. */
|
||||
private predicate implicit_submodule_defn(ImplicitSubModuleDefinition def, Definition defn) {
|
||||
exists(PackageObject package, ModuleObject mod |
|
||||
package.getInitModule().getModule() = def.getDefiningNode().getScope() and
|
||||
mod = package.submodule(def.getSourceVariable().getName()) and
|
||||
defn.getAstNode() = mod.getModule()
|
||||
)
|
||||
exists(PackageObject package, ModuleObject mod |
|
||||
package.getInitModule().getModule() = def.getDefiningNode().getScope() and
|
||||
mod = package.submodule(def.getSourceVariable().getName()) and
|
||||
defn.getAstNode() = mod.getModule()
|
||||
)
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -158,42 +158,42 @@ private predicate implicit_submodule_defn(ImplicitSubModuleDefinition def, Defin
|
||||
*/
|
||||
|
||||
private predicate scope_entry_value_transfer_at_callsite(
|
||||
EssaVariable pred_var, ScopeEntryDefinition succ_def
|
||||
EssaVariable pred_var, ScopeEntryDefinition succ_def
|
||||
) {
|
||||
exists(CallNode callsite, FunctionObject f |
|
||||
f.getACall() = callsite and
|
||||
pred_var.getSourceVariable() = succ_def.getSourceVariable() and
|
||||
pred_var.getAUse() = callsite and
|
||||
succ_def.getDefiningNode() = f.getFunction().getEntryNode()
|
||||
)
|
||||
exists(CallNode callsite, FunctionObject f |
|
||||
f.getACall() = callsite and
|
||||
pred_var.getSourceVariable() = succ_def.getSourceVariable() and
|
||||
pred_var.getAUse() = callsite and
|
||||
succ_def.getDefiningNode() = f.getFunction().getEntryNode()
|
||||
)
|
||||
}
|
||||
|
||||
/* Model the transfer of values at scope-entry points. Transfer from `pred_var, pred_context` to `succ_def, succ_context` */
|
||||
private predicate scope_entry_value_transfer(EssaVariable pred_var, ScopeEntryDefinition succ_def) {
|
||||
BaseFlow::scope_entry_value_transfer_from_earlier(pred_var, _, succ_def, _)
|
||||
or
|
||||
scope_entry_value_transfer_at_callsite(pred_var, succ_def)
|
||||
or
|
||||
class_entry_value_transfer(pred_var, succ_def)
|
||||
BaseFlow::scope_entry_value_transfer_from_earlier(pred_var, _, succ_def, _)
|
||||
or
|
||||
scope_entry_value_transfer_at_callsite(pred_var, succ_def)
|
||||
or
|
||||
class_entry_value_transfer(pred_var, succ_def)
|
||||
}
|
||||
|
||||
/* Helper for scope_entry_value_transfer */
|
||||
private predicate class_entry_value_transfer(EssaVariable pred_var, ScopeEntryDefinition succ_def) {
|
||||
exists(ImportTimeScope scope, ControlFlowNode class_def |
|
||||
class_def = pred_var.getAUse() and
|
||||
scope.entryEdge(class_def, succ_def.getDefiningNode()) and
|
||||
pred_var.getSourceVariable() = succ_def.getSourceVariable()
|
||||
)
|
||||
exists(ImportTimeScope scope, ControlFlowNode class_def |
|
||||
class_def = pred_var.getAUse() and
|
||||
scope.entryEdge(class_def, succ_def.getDefiningNode()) and
|
||||
pred_var.getSourceVariable() = succ_def.getSourceVariable()
|
||||
)
|
||||
}
|
||||
|
||||
/* Definition for implicit variable declarations at scope-entry. */
|
||||
pragma[noinline]
|
||||
private predicate scope_entry_defn(ScopeEntryDefinition def, Definition defn) {
|
||||
/* Transfer from another scope */
|
||||
exists(EssaVariable var |
|
||||
scope_entry_value_transfer(var, def) and
|
||||
ssa_variable_defn(var, defn)
|
||||
)
|
||||
/* Transfer from another scope */
|
||||
exists(EssaVariable var |
|
||||
scope_entry_value_transfer(var, def) and
|
||||
ssa_variable_defn(var, defn)
|
||||
)
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -203,73 +203,73 @@ private predicate scope_entry_defn(ScopeEntryDefinition def, Definition defn) {
|
||||
|
||||
pragma[noinline]
|
||||
private predicate callsite_defn(CallsiteRefinement def, Definition defn) {
|
||||
ssa_variable_defn(def.getInput(), defn)
|
||||
ssa_variable_defn(def.getInput(), defn)
|
||||
}
|
||||
|
||||
/* Pass through for `self` for the implicit re-defn of `self` in `self.foo()` */
|
||||
private predicate method_callsite_defn(MethodCallsiteRefinement def, Definition defn) {
|
||||
/* The value of self remains the same, only the attributes may change */
|
||||
ssa_variable_defn(def.getInput(), defn)
|
||||
/* The value of self remains the same, only the attributes may change */
|
||||
ssa_variable_defn(def.getInput(), defn)
|
||||
}
|
||||
|
||||
/** Helpers for import_star_defn */
|
||||
pragma[noinline]
|
||||
private predicate module_and_name_for_import_star(
|
||||
ModuleObject mod, string name, ImportStarRefinement def
|
||||
ModuleObject mod, string name, ImportStarRefinement def
|
||||
) {
|
||||
exists(ImportStarNode im_star |
|
||||
module_and_name_for_import_star_helper(mod, name, im_star, def) and
|
||||
mod.exports(name)
|
||||
)
|
||||
exists(ImportStarNode im_star |
|
||||
module_and_name_for_import_star_helper(mod, name, im_star, def) and
|
||||
mod.exports(name)
|
||||
)
|
||||
}
|
||||
|
||||
pragma[noinline]
|
||||
private predicate module_and_name_for_import_star_helper(
|
||||
ModuleObject mod, string name, ImportStarNode im_star, ImportStarRefinement def
|
||||
ModuleObject mod, string name, ImportStarNode im_star, ImportStarRefinement def
|
||||
) {
|
||||
im_star = def.getDefiningNode() and
|
||||
im_star.getModule().refersTo(mod) and
|
||||
name = def.getSourceVariable().getName()
|
||||
im_star = def.getDefiningNode() and
|
||||
im_star.getModule().refersTo(mod) and
|
||||
name = def.getSourceVariable().getName()
|
||||
}
|
||||
|
||||
/** Holds if `def` is technically a defn of `var`, but the `from ... import *` does not in fact define `var` */
|
||||
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
|
||||
not mod.exports(var.getSourceVariable().getName())
|
||||
)
|
||||
var = def.getInput() and
|
||||
exists(ModuleObject mod |
|
||||
def.getDefiningNode().(ImportStarNode).getModule().refersTo(mod) and
|
||||
not mod.exports(var.getSourceVariable().getName())
|
||||
)
|
||||
}
|
||||
|
||||
/* Definition for `from ... import *` */
|
||||
private predicate import_star_defn(ImportStarRefinement def, Definition defn) {
|
||||
exists(ModuleObject mod, string name | module_and_name_for_import_star(mod, name, def) |
|
||||
/* Attribute from imported module */
|
||||
scope_jump_to_defn_attribute(mod.getModule(), name, defn)
|
||||
)
|
||||
or
|
||||
exists(EssaVariable var |
|
||||
/* Retain value held before import */
|
||||
variable_not_redefined_by_import_star(var, def) and
|
||||
ssa_variable_defn(var, defn)
|
||||
)
|
||||
exists(ModuleObject mod, string name | module_and_name_for_import_star(mod, name, def) |
|
||||
/* Attribute from imported module */
|
||||
scope_jump_to_defn_attribute(mod.getModule(), name, defn)
|
||||
)
|
||||
or
|
||||
exists(EssaVariable var |
|
||||
/* Retain value held before import */
|
||||
variable_not_redefined_by_import_star(var, def) and
|
||||
ssa_variable_defn(var, defn)
|
||||
)
|
||||
}
|
||||
|
||||
/** Attribute assignments have no effect as far as defn tracking is concerned */
|
||||
private predicate attribute_assignment_defn(AttributeAssignment def, Definition defn) {
|
||||
ssa_variable_defn(def.getInput(), defn)
|
||||
ssa_variable_defn(def.getInput(), defn)
|
||||
}
|
||||
|
||||
/** Ignore the effects of calls on their arguments. This is an approximation, but attempting to improve accuracy would be very expensive for very little gain. */
|
||||
private predicate argument_defn(ArgumentRefinement def, Definition defn) {
|
||||
ssa_variable_defn(def.getInput(), defn)
|
||||
ssa_variable_defn(def.getInput(), defn)
|
||||
}
|
||||
|
||||
/** Attribute deletions have no effect as far as value tracking is concerned. */
|
||||
pragma[noinline]
|
||||
private predicate attribute_delete_defn(EssaAttributeDeletion def, Definition defn) {
|
||||
ssa_variable_defn(def.getInput(), defn)
|
||||
ssa_variable_defn(def.getInput(), defn)
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -284,119 +284,119 @@ private predicate attribute_delete_defn(EssaAttributeDeletion def, Definition de
|
||||
* Holds if the attribute `name` of the ssa variable `var` refers to (`value`, `cls`, `origin`)
|
||||
*/
|
||||
predicate ssa_variable_jump_to_defn_attribute(EssaVariable var, string name, Definition defn) {
|
||||
ssa_defn_jump_to_defn_attribute(var.getDefinition(), name, defn)
|
||||
ssa_defn_jump_to_defn_attribute(var.getDefinition(), name, defn)
|
||||
}
|
||||
|
||||
/** Helper for ssa_variable_jump_to_defn_attribute */
|
||||
private predicate ssa_defn_jump_to_defn_attribute(EssaDefinition def, string name, Definition defn) {
|
||||
ssa_phi_jump_to_defn_attribute(def, name, defn)
|
||||
or
|
||||
ssa_node_jump_to_defn_attribute(def, name, defn)
|
||||
or
|
||||
ssa_node_refinement_jump_to_defn_attribute(def, name, defn)
|
||||
or
|
||||
ssa_filter_jump_to_defn_attribute(def, name, defn)
|
||||
ssa_phi_jump_to_defn_attribute(def, name, defn)
|
||||
or
|
||||
ssa_node_jump_to_defn_attribute(def, name, defn)
|
||||
or
|
||||
ssa_node_refinement_jump_to_defn_attribute(def, name, defn)
|
||||
or
|
||||
ssa_filter_jump_to_defn_attribute(def, name, defn)
|
||||
}
|
||||
|
||||
/** Holds if ESSA edge refinement, `def`, is defined by `defn` of `priority` */
|
||||
predicate ssa_filter_jump_to_defn_attribute(PyEdgeRefinement def, string name, Definition defn) {
|
||||
ssa_variable_jump_to_defn_attribute(def.getInput(), name, defn)
|
||||
ssa_variable_jump_to_defn_attribute(def.getInput(), name, defn)
|
||||
}
|
||||
|
||||
/** Holds if the attribute `name` of the ssa phi-function defn `phi` refers to (`value`, `cls`, `origin`) */
|
||||
private predicate ssa_phi_jump_to_defn_attribute(PhiFunction phi, string name, Definition defn) {
|
||||
ssa_variable_jump_to_defn_attribute(phi.getAnInput(), name, defn)
|
||||
ssa_variable_jump_to_defn_attribute(phi.getAnInput(), name, defn)
|
||||
}
|
||||
|
||||
/** Helper for ssa_defn_jump_to_defn_attribute */
|
||||
pragma[noinline]
|
||||
private predicate ssa_node_jump_to_defn_attribute(
|
||||
EssaNodeDefinition def, string name, Definition defn
|
||||
EssaNodeDefinition def, string name, Definition defn
|
||||
) {
|
||||
assignment_jump_to_defn_attribute(def, name, defn)
|
||||
or
|
||||
self_parameter_jump_to_defn_attribute(def, name, defn)
|
||||
or
|
||||
scope_entry_jump_to_defn_attribute(def, name, defn)
|
||||
assignment_jump_to_defn_attribute(def, name, defn)
|
||||
or
|
||||
self_parameter_jump_to_defn_attribute(def, name, defn)
|
||||
or
|
||||
scope_entry_jump_to_defn_attribute(def, name, defn)
|
||||
}
|
||||
|
||||
/** Helper for ssa_defn_jump_to_defn_attribute */
|
||||
pragma[noinline]
|
||||
private predicate ssa_node_refinement_jump_to_defn_attribute(
|
||||
EssaNodeRefinement def, string name, Definition defn
|
||||
EssaNodeRefinement def, string name, Definition defn
|
||||
) {
|
||||
attribute_assignment_jump_to_defn_attribute(def, name, defn)
|
||||
or
|
||||
argument_jump_to_defn_attribute(def, name, defn)
|
||||
attribute_assignment_jump_to_defn_attribute(def, name, defn)
|
||||
or
|
||||
argument_jump_to_defn_attribute(def, name, defn)
|
||||
}
|
||||
|
||||
pragma[noinline]
|
||||
private predicate scope_entry_jump_to_defn_attribute(
|
||||
ScopeEntryDefinition def, string name, Definition defn
|
||||
ScopeEntryDefinition def, string name, Definition defn
|
||||
) {
|
||||
exists(EssaVariable var |
|
||||
scope_entry_value_transfer(var, def) and
|
||||
ssa_variable_jump_to_defn_attribute(var, name, defn)
|
||||
)
|
||||
exists(EssaVariable var |
|
||||
scope_entry_value_transfer(var, def) and
|
||||
ssa_variable_jump_to_defn_attribute(var, name, defn)
|
||||
)
|
||||
}
|
||||
|
||||
private predicate scope_jump_to_defn_attribute(ImportTimeScope s, string name, Definition defn) {
|
||||
exists(EssaVariable var |
|
||||
BaseFlow::reaches_exit(var) and
|
||||
var.getScope() = s and
|
||||
var.getName() = name
|
||||
|
|
||||
ssa_variable_defn(var, defn)
|
||||
)
|
||||
exists(EssaVariable var |
|
||||
BaseFlow::reaches_exit(var) and
|
||||
var.getScope() = s and
|
||||
var.getName() = name
|
||||
|
|
||||
ssa_variable_defn(var, defn)
|
||||
)
|
||||
}
|
||||
|
||||
private predicate jump_to_defn_attribute(ControlFlowNode use, string name, Definition defn) {
|
||||
/* Local attribute */
|
||||
exists(EssaVariable var |
|
||||
use = var.getASourceUse() and
|
||||
ssa_variable_jump_to_defn_attribute(var, name, defn)
|
||||
)
|
||||
/* Local attribute */
|
||||
exists(EssaVariable var |
|
||||
use = var.getASourceUse() and
|
||||
ssa_variable_jump_to_defn_attribute(var, name, defn)
|
||||
)
|
||||
or
|
||||
/* Instance attributes */
|
||||
exists(ClassObject cls | use.refersTo(_, cls, _) |
|
||||
scope_jump_to_defn_attribute(cls.getPyClass(), name, defn)
|
||||
)
|
||||
or
|
||||
/* Super attributes */
|
||||
exists(AttrNode f, SuperBoundMethod sbm, Object function |
|
||||
use = f.getObject(name) and
|
||||
f.refersTo(sbm) and
|
||||
function = sbm.getFunction(_) and
|
||||
function.getOrigin() = defn.getAstNode()
|
||||
)
|
||||
or
|
||||
/* Class or module attribute */
|
||||
exists(Object obj, Scope scope |
|
||||
use.refersTo(obj) and
|
||||
scope_jump_to_defn_attribute(scope, name, defn)
|
||||
|
|
||||
obj.(ClassObject).getPyClass() = scope
|
||||
or
|
||||
/* Instance attributes */
|
||||
exists(ClassObject cls | use.refersTo(_, cls, _) |
|
||||
scope_jump_to_defn_attribute(cls.getPyClass(), name, defn)
|
||||
)
|
||||
obj.(PythonModuleObject).getModule() = scope
|
||||
or
|
||||
/* Super attributes */
|
||||
exists(AttrNode f, SuperBoundMethod sbm, Object function |
|
||||
use = f.getObject(name) and
|
||||
f.refersTo(sbm) and
|
||||
function = sbm.getFunction(_) and
|
||||
function.getOrigin() = defn.getAstNode()
|
||||
)
|
||||
or
|
||||
/* Class or module attribute */
|
||||
exists(Object obj, Scope scope |
|
||||
use.refersTo(obj) and
|
||||
scope_jump_to_defn_attribute(scope, name, defn)
|
||||
|
|
||||
obj.(ClassObject).getPyClass() = scope
|
||||
or
|
||||
obj.(PythonModuleObject).getModule() = scope
|
||||
or
|
||||
obj.(PackageObject).getInitModule().getModule() = scope
|
||||
)
|
||||
obj.(PackageObject).getInitModule().getModule() = scope
|
||||
)
|
||||
}
|
||||
|
||||
pragma[noinline]
|
||||
private predicate assignment_jump_to_defn_attribute(
|
||||
AssignmentDefinition def, string name, Definition defn
|
||||
AssignmentDefinition def, string name, Definition defn
|
||||
) {
|
||||
jump_to_defn_attribute(def.getValue(), name, defn)
|
||||
jump_to_defn_attribute(def.getValue(), name, defn)
|
||||
}
|
||||
|
||||
pragma[noinline]
|
||||
private predicate attribute_assignment_jump_to_defn_attribute(
|
||||
AttributeAssignment def, string name, Definition defn
|
||||
AttributeAssignment def, string name, Definition defn
|
||||
) {
|
||||
defn.getAstNode() = def.getDefiningNode().getNode() and name = def.getName()
|
||||
or
|
||||
ssa_variable_jump_to_defn_attribute(def.getInput(), name, defn) and not name = def.getName()
|
||||
defn.getAstNode() = def.getDefiningNode().getNode() and name = def.getName()
|
||||
or
|
||||
ssa_variable_jump_to_defn_attribute(def.getInput(), name, defn) and not name = def.getName()
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -404,42 +404,42 @@ private predicate attribute_assignment_jump_to_defn_attribute(
|
||||
* `def` takes the form `setattr(use, "name")` where `use` is the input to the defn.
|
||||
*/
|
||||
private predicate sets_attribute(ArgumentRefinement def, string name) {
|
||||
exists(CallNode call |
|
||||
call = def.getDefiningNode() and
|
||||
call.getFunction().refersTo(Object::builtin("setattr")) and
|
||||
def.getInput().getAUse() = call.getArg(0) and
|
||||
call.getArg(1).getNode().(StrConst).getText() = name
|
||||
)
|
||||
exists(CallNode call |
|
||||
call = def.getDefiningNode() and
|
||||
call.getFunction().refersTo(Object::builtin("setattr")) and
|
||||
def.getInput().getAUse() = call.getArg(0) and
|
||||
call.getArg(1).getNode().(StrConst).getText() = name
|
||||
)
|
||||
}
|
||||
|
||||
pragma[noinline]
|
||||
private predicate argument_jump_to_defn_attribute(
|
||||
ArgumentRefinement def, string name, Definition defn
|
||||
ArgumentRefinement def, string name, Definition defn
|
||||
) {
|
||||
if sets_attribute(def, name)
|
||||
then jump_to_defn(def.getDefiningNode().(CallNode).getArg(2), defn)
|
||||
else ssa_variable_jump_to_defn_attribute(def.getInput(), name, defn)
|
||||
if sets_attribute(def, name)
|
||||
then jump_to_defn(def.getDefiningNode().(CallNode).getArg(2), defn)
|
||||
else ssa_variable_jump_to_defn_attribute(def.getInput(), name, defn)
|
||||
}
|
||||
|
||||
/** Gets the (temporally) preceding variable for "self", e.g. `def` is in method foo() and `result` is in `__init__()`. */
|
||||
private EssaVariable preceding_self_variable(ParameterDefinition def) {
|
||||
def.isSelf() and
|
||||
exists(Function preceding, Function method |
|
||||
method = def.getScope() and
|
||||
// Only methods
|
||||
preceding.isMethod() and
|
||||
preceding.precedes(method) and
|
||||
BaseFlow::reaches_exit(result) and
|
||||
result.getSourceVariable().(Variable).isSelf() and
|
||||
result.getScope() = preceding
|
||||
)
|
||||
def.isSelf() and
|
||||
exists(Function preceding, Function method |
|
||||
method = def.getScope() and
|
||||
// Only methods
|
||||
preceding.isMethod() and
|
||||
preceding.precedes(method) and
|
||||
BaseFlow::reaches_exit(result) and
|
||||
result.getSourceVariable().(Variable).isSelf() and
|
||||
result.getScope() = preceding
|
||||
)
|
||||
}
|
||||
|
||||
pragma[noinline]
|
||||
private predicate self_parameter_jump_to_defn_attribute(
|
||||
ParameterDefinition def, string name, Definition defn
|
||||
ParameterDefinition def, string name, Definition defn
|
||||
) {
|
||||
ssa_variable_jump_to_defn_attribute(preceding_self_variable(def), name, defn)
|
||||
ssa_variable_jump_to_defn_attribute(preceding_self_variable(def), name, defn)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -447,11 +447,11 @@ private predicate self_parameter_jump_to_defn_attribute(
|
||||
* This exists primarily for testing use `getPreferredDefinition()` instead.
|
||||
*/
|
||||
Definition getADefinition(Expr use) {
|
||||
jump_to_defn(use.getAFlowNode(), result) and
|
||||
not use instanceof Call and
|
||||
not use.isArtificial() and
|
||||
// Not the use itself
|
||||
not result = TLocalDefinition(use)
|
||||
jump_to_defn(use.getAFlowNode(), result) and
|
||||
not use instanceof Call and
|
||||
not use.isArtificial() and
|
||||
// Not the use itself
|
||||
not result = TLocalDefinition(use)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -459,44 +459,45 @@ Definition getADefinition(Expr use) {
|
||||
* Helper for the jump-to-definition query.
|
||||
*/
|
||||
Definition getUniqueDefinition(Expr use) {
|
||||
unique_jump_to_defn(use, result) and
|
||||
not use instanceof Call and
|
||||
not use.isArtificial() and
|
||||
// Not the use itself
|
||||
not result = TLocalDefinition(use)
|
||||
unique_jump_to_defn(use, result) and
|
||||
not use instanceof Call and
|
||||
not use.isArtificial() and
|
||||
// Not the use itself
|
||||
not result = TLocalDefinition(use)
|
||||
}
|
||||
|
||||
/** Helper class to get suitable locations for attributes */
|
||||
class NiceLocationExpr extends @py_expr {
|
||||
/** Gets a textual representation of this element. */
|
||||
string toString() { result = this.(Expr).toString() }
|
||||
/**
|
||||
* Holds if this element is at the specified location.
|
||||
* The location spans column `bc` of line `bl` to
|
||||
* column `ec` of line `el` in file `f`.
|
||||
* For more information, see
|
||||
* [Locations](https://help.semmle.com/QL/learn-ql/ql/locations.html).
|
||||
*/
|
||||
predicate hasLocationInfo(string f, int bl, int bc, int el, int ec) {
|
||||
/* Attribute location for x.y is that of 'y' so that url does not overlap with that of 'x' */
|
||||
exists(int abl, int abc | this.(Attribute).getLocation().hasLocationInfo(f, abl, abc, el, ec) |
|
||||
bl = el and bc = ec - this.(Attribute).getName().length() + 1
|
||||
)
|
||||
or
|
||||
this.(Name).getLocation().hasLocationInfo(f, bl, bc, el, ec)
|
||||
or
|
||||
// Show xxx for `xxx` in `from xxx import y` or
|
||||
// for `import xxx` or for `import xxx as yyy`.
|
||||
this.(ImportExpr).getLocation().hasLocationInfo(f, bl, bc, el, ec)
|
||||
or
|
||||
/* Show y for `y` in `from xxx import y` */
|
||||
exists(string name |
|
||||
name = this.(ImportMember).getName() and
|
||||
this.(ImportMember).getLocation().hasLocationInfo(f, _, _, el, ec) and
|
||||
bl = el and
|
||||
bc = ec - name.length() + 1
|
||||
)
|
||||
}
|
||||
/** Gets a textual representation of this element. */
|
||||
string toString() { result = this.(Expr).toString() }
|
||||
|
||||
/**
|
||||
* Holds if this element is at the specified location.
|
||||
* The location spans column `bc` of line `bl` to
|
||||
* column `ec` of line `el` in file `f`.
|
||||
* For more information, see
|
||||
* [Locations](https://help.semmle.com/QL/learn-ql/ql/locations.html).
|
||||
*/
|
||||
predicate hasLocationInfo(string f, int bl, int bc, int el, int ec) {
|
||||
/* Attribute location for x.y is that of 'y' so that url does not overlap with that of 'x' */
|
||||
exists(int abl, int abc | this.(Attribute).getLocation().hasLocationInfo(f, abl, abc, el, ec) |
|
||||
bl = el and bc = ec - this.(Attribute).getName().length() + 1
|
||||
)
|
||||
or
|
||||
this.(Name).getLocation().hasLocationInfo(f, bl, bc, el, ec)
|
||||
or
|
||||
// Show xxx for `xxx` in `from xxx import y` or
|
||||
// for `import xxx` or for `import xxx as yyy`.
|
||||
this.(ImportExpr).getLocation().hasLocationInfo(f, bl, bc, el, ec)
|
||||
or
|
||||
/* Show y for `y` in `from xxx import y` */
|
||||
exists(string name |
|
||||
name = this.(ImportMember).getName() and
|
||||
this.(ImportMember).getLocation().hasLocationInfo(f, _, _, el, ec) and
|
||||
bl = el and
|
||||
bc = ec - name.length() + 1
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -504,13 +505,13 @@ class NiceLocationExpr extends @py_expr {
|
||||
*/
|
||||
cached
|
||||
Definition definitionOf(NiceLocationExpr use, string kind) {
|
||||
exists(string f, int l |
|
||||
result = getUniqueDefinition(use) and
|
||||
kind = "Definition" and
|
||||
use.hasLocationInfo(f, l, _, _, _) and
|
||||
// Ignore if the definition is on the same line as the use
|
||||
not result.getLocation().hasLocationInfo(f, l, _, _, _)
|
||||
)
|
||||
exists(string f, int l |
|
||||
result = getUniqueDefinition(use) and
|
||||
kind = "Definition" and
|
||||
use.hasLocationInfo(f, l, _, _, _) and
|
||||
// Ignore if the definition is on the same line as the use
|
||||
not result.getLocation().hasLocationInfo(f, l, _, _, _)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user