mirror of
https://github.com/github/codeql.git
synced 2026-04-30 03:05:15 +02:00
Python: Autoformat query-local libs.
This commit is contained in:
@@ -1,35 +1,22 @@
|
||||
/**
|
||||
* Definition tracking for jump-to-defn query.
|
||||
*/
|
||||
import python
|
||||
|
||||
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 {
|
||||
string toString() { result = "Definition " + this.getAstNode().getLocation().toString() }
|
||||
|
||||
AstNode getAstNode() { this = TLocalDefinition(result) }
|
||||
|
||||
string toString() {
|
||||
result = "Definition " + this.getAstNode().getLocation().toString()
|
||||
}
|
||||
|
||||
AstNode getAstNode() {
|
||||
this = TLocalDefinition(result)
|
||||
}
|
||||
|
||||
Module getModule() {
|
||||
result = this.getAstNode().getScope().getEnclosingModule()
|
||||
}
|
||||
|
||||
Location getLocation() {
|
||||
result = this.getAstNode().getLocation()
|
||||
}
|
||||
Module getModule() { result = this.getAstNode().getScope().getEnclosingModule() }
|
||||
|
||||
Location getLocation() { result = this.getAstNode().getLocation() }
|
||||
}
|
||||
|
||||
private predicate jump_to_defn(ControlFlowNode use, Definition defn) {
|
||||
@@ -112,7 +99,7 @@ predicate uni_edged_phi_defn(SingleSuccessorGuard uniphi, Definition defn) {
|
||||
ssa_variable_defn(uniphi.getInput(), defn)
|
||||
}
|
||||
|
||||
pragma [noinline]
|
||||
pragma[noinline]
|
||||
private predicate ssa_node_defn(EssaNodeDefinition def, Definition defn) {
|
||||
assignment_jump_to_defn(def, defn)
|
||||
or
|
||||
@@ -130,7 +117,7 @@ private predicate assignment_jump_to_defn(AssignmentDefinition def, Definition d
|
||||
defn = TLocalDefinition(def.getValue().getNode())
|
||||
}
|
||||
|
||||
pragma [noinline]
|
||||
pragma[noinline]
|
||||
private predicate ssa_node_refinement_defn(EssaNodeRefinement def, Definition defn) {
|
||||
method_callsite_defn(def, defn)
|
||||
or
|
||||
@@ -147,16 +134,13 @@ private predicate ssa_node_refinement_defn(EssaNodeRefinement def, Definition de
|
||||
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()
|
||||
}
|
||||
|
||||
/* Definition for deletion: `del name` */
|
||||
private predicate delete_defn(DeletionDefinition def, Definition defn) {
|
||||
none()
|
||||
}
|
||||
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) {
|
||||
@@ -165,13 +149,16 @@ private predicate implicit_submodule_defn(ImplicitSubModuleDefinition def, Defin
|
||||
mod = package.submodule(def.getSourceVariable().getName()) and
|
||||
defn.getAstNode() = mod.getModule()
|
||||
)
|
||||
|
||||
}
|
||||
|
||||
/* Helper for scope_entry_value_transfer(...).
|
||||
* Transfer of values from the callsite to the callee, for enclosing variables, but not arguments/parameters
|
||||
/*
|
||||
* Helper for scope_entry_value_transfer(...).
|
||||
* Transfer of values from the callsite to the callee, for enclosing variables, but not arguments/parameters
|
||||
*/
|
||||
private predicate scope_entry_value_transfer_at_callsite(EssaVariable pred_var, ScopeEntryDefinition succ_def) {
|
||||
|
||||
private predicate scope_entry_value_transfer_at_callsite(
|
||||
EssaVariable pred_var, ScopeEntryDefinition succ_def
|
||||
) {
|
||||
exists(CallNode callsite, FunctionObject f |
|
||||
f.getACall() = callsite and
|
||||
pred_var.getSourceVariable() = succ_def.getSourceVariable() and
|
||||
@@ -181,8 +168,7 @@ private predicate scope_entry_value_transfer_at_callsite(EssaVariable pred_var,
|
||||
}
|
||||
|
||||
/* 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) {
|
||||
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)
|
||||
@@ -191,8 +177,7 @@ predicate scope_entry_value_transfer(EssaVariable pred_var, ScopeEntryDefinition
|
||||
}
|
||||
|
||||
/* Helper for scope_entry_value_transfer */
|
||||
private
|
||||
predicate class_entry_value_transfer(EssaVariable pred_var, ScopeEntryDefinition succ_def) {
|
||||
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
|
||||
@@ -201,7 +186,7 @@ predicate class_entry_value_transfer(EssaVariable pred_var, ScopeEntryDefinition
|
||||
}
|
||||
|
||||
/* Definition for implicit variable declarations at scope-entry. */
|
||||
pragma [noinline]
|
||||
pragma[noinline]
|
||||
private predicate scope_entry_defn(ScopeEntryDefinition def, Definition defn) {
|
||||
/* Transfer from another scope */
|
||||
exists(EssaVariable var |
|
||||
@@ -210,10 +195,12 @@ private predicate scope_entry_defn(ScopeEntryDefinition def, Definition defn) {
|
||||
)
|
||||
}
|
||||
|
||||
/* Definition for a variable (possibly) redefined by a call:
|
||||
/*
|
||||
* Definition for a variable (possibly) redefined by a call:
|
||||
* Just assume that call does not define variable
|
||||
*/
|
||||
pragma [noinline]
|
||||
|
||||
pragma[noinline]
|
||||
private predicate callsite_defn(CallsiteRefinement def, Definition defn) {
|
||||
ssa_variable_defn(def.getInput(), defn)
|
||||
}
|
||||
@@ -225,22 +212,27 @@ private predicate method_callsite_defn(MethodCallsiteRefinement def, Definition
|
||||
}
|
||||
|
||||
/** Helpers for import_star_defn */
|
||||
pragma [noinline]
|
||||
private predicate module_and_name_for_import_star(ModuleObject mod, string name, ImportStarRefinement def) {
|
||||
pragma[noinline]
|
||||
private predicate module_and_name_for_import_star(
|
||||
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)
|
||||
)
|
||||
}
|
||||
|
||||
pragma [noinline]
|
||||
private predicate module_and_name_for_import_star_helper(ModuleObject mod, string name, ImportStarNode im_star, ImportStarRefinement def) {
|
||||
pragma[noinline]
|
||||
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
|
||||
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]
|
||||
|
||||
/** 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 |
|
||||
@@ -251,8 +243,7 @@ private predicate variable_not_redefined_by_import_star(EssaVariable var, Import
|
||||
|
||||
/* 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) |
|
||||
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)
|
||||
)
|
||||
@@ -275,18 +266,20 @@ private predicate argument_defn(ArgumentRefinement def, Definition defn) {
|
||||
}
|
||||
|
||||
/** Attribute deletions have no effect as far as value tracking is concerned. */
|
||||
pragma [noinline]
|
||||
pragma[noinline]
|
||||
private predicate attribute_delete_defn(EssaAttributeDeletion def, Definition defn) {
|
||||
ssa_variable_defn(def.getInput(), defn)
|
||||
}
|
||||
|
||||
/* Definition flow for attributes. These mirror the "normal" defn predicates.
|
||||
/*
|
||||
* Definition flow for attributes. These mirror the "normal" defn predicates.
|
||||
* For each defn predicate `xxx_defn(XXX def, Definition defn)`
|
||||
* There is an equivalent predicate that tracks the values in attributes:
|
||||
* `xxx_jump_to_defn_attribute(XXX def, string name, Definition defn)`
|
||||
* */
|
||||
*/
|
||||
|
||||
/** INTERNAL -- Public for testing only.
|
||||
/**
|
||||
* INTERNAL -- Public for testing only.
|
||||
* 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) {
|
||||
@@ -316,7 +309,9 @@ private predicate ssa_phi_jump_to_defn_attribute(PhiFunction phi, string name, D
|
||||
|
||||
/** Helper for ssa_defn_jump_to_defn_attribute */
|
||||
pragma[noinline]
|
||||
private predicate ssa_node_jump_to_defn_attribute(EssaNodeDefinition def, string name, Definition defn) {
|
||||
private predicate ssa_node_jump_to_defn_attribute(
|
||||
EssaNodeDefinition def, string name, Definition defn
|
||||
) {
|
||||
assignment_jump_to_defn_attribute(def, name, defn)
|
||||
or
|
||||
self_parameter_jump_to_defn_attribute(def, name, defn)
|
||||
@@ -326,14 +321,18 @@ private predicate ssa_node_jump_to_defn_attribute(EssaNodeDefinition def, string
|
||||
|
||||
/** 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) {
|
||||
private predicate ssa_node_refinement_jump_to_defn_attribute(
|
||||
EssaNodeRefinement def, string name, Definition 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) {
|
||||
private predicate scope_entry_jump_to_defn_attribute(
|
||||
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)
|
||||
@@ -342,9 +341,10 @@ private predicate scope_entry_jump_to_defn_attribute(ScopeEntryDefinition def, s
|
||||
|
||||
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
|
||||
BaseFlow::reaches_exit(var) and
|
||||
var.getScope() = s and
|
||||
var.getName() = name
|
||||
|
|
||||
|
|
||||
ssa_variable_defn(var, defn)
|
||||
)
|
||||
}
|
||||
@@ -357,22 +357,23 @@ private predicate jump_to_defn_attribute(ControlFlowNode use, string name, Defin
|
||||
)
|
||||
or
|
||||
/* Instance attributes */
|
||||
exists(ClassObject cls |
|
||||
use.refersTo(_, cls, _) |
|
||||
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
|
||||
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) |
|
||||
scope_jump_to_defn_attribute(scope, name, defn)
|
||||
|
|
||||
obj.(ClassObject).getPyClass() = scope
|
||||
or
|
||||
obj.(PythonModuleObject).getModule() = scope
|
||||
@@ -382,18 +383,23 @@ private predicate jump_to_defn_attribute(ControlFlowNode use, string name, Defin
|
||||
}
|
||||
|
||||
pragma[noinline]
|
||||
private predicate assignment_jump_to_defn_attribute(AssignmentDefinition def, string name, Definition defn) {
|
||||
private predicate assignment_jump_to_defn_attribute(
|
||||
AssignmentDefinition def, string name, Definition 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) {
|
||||
private predicate attribute_assignment_jump_to_defn_attribute(
|
||||
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()
|
||||
}
|
||||
|
||||
/** Holds if `def` defines the attribute `name`
|
||||
/**
|
||||
* Holds if `def` defines the attribute `name`
|
||||
* `def` takes the form `setattr(use, "name")` where `use` is the input to the defn.
|
||||
*/
|
||||
private predicate sets_attribute(ArgumentRefinement def, string name) {
|
||||
@@ -406,31 +412,37 @@ private predicate sets_attribute(ArgumentRefinement def, string name) {
|
||||
}
|
||||
|
||||
pragma[noinline]
|
||||
private predicate argument_jump_to_defn_attribute(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)
|
||||
private predicate argument_jump_to_defn_attribute(
|
||||
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)
|
||||
}
|
||||
|
||||
/** Gets the (temporally) preceding variable for "self", e.g. `def` is in method foo() and `result` is in `__init__()`. */
|
||||
/** 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
|
||||
method = def.getScope() and
|
||||
// Only methods
|
||||
preceding.isMethod() and preceding.precedes(method) and
|
||||
BaseFlow::reaches_exit(result) and result.getSourceVariable().(Variable).isSelf() and
|
||||
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) {
|
||||
pragma[noinline]
|
||||
private predicate self_parameter_jump_to_defn_attribute(
|
||||
ParameterDefinition def, string name, Definition defn
|
||||
) {
|
||||
ssa_variable_jump_to_defn_attribute(preceding_self_variable(def), name, defn)
|
||||
}
|
||||
|
||||
/** Gets a definition for 'use'.
|
||||
/**
|
||||
* Gets a definition for 'use'.
|
||||
* This exists primarily for testing use `getPreferredDefinition()` instead.
|
||||
*/
|
||||
Definition getADefinition(Expr use) {
|
||||
@@ -441,7 +453,8 @@ Definition getADefinition(Expr use) {
|
||||
not result = TLocalDefinition(use)
|
||||
}
|
||||
|
||||
/** Gets the unique definition for 'use', if one can be found.
|
||||
/**
|
||||
* Gets the unique definition for 'use', if one can be found.
|
||||
* Helper for the jump-to-definition query.
|
||||
*/
|
||||
Definition getUniqueDefinition(Expr use) {
|
||||
@@ -452,18 +465,13 @@ Definition getUniqueDefinition(Expr use) {
|
||||
not result = TLocalDefinition(use)
|
||||
}
|
||||
|
||||
|
||||
/** Helper class to get suitable locations for attributes */
|
||||
class NiceLocationExpr extends @py_expr {
|
||||
|
||||
string toString() {
|
||||
result = this.(Expr).toString()
|
||||
}
|
||||
string toString() { result = this.(Expr).toString() }
|
||||
|
||||
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) |
|
||||
/* 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
|
||||
@@ -477,10 +485,8 @@ class NiceLocationExpr extends @py_expr {
|
||||
exists(string name |
|
||||
name = this.(ImportMember).getName() and
|
||||
this.(ImportMember).getLocation().hasLocationInfo(f, _, _, el, ec) and
|
||||
bl = el and bc = ec-name.length()+1
|
||||
bl = el and
|
||||
bc = ec - name.length() + 1
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user