mirror of
https://github.com/github/codeql.git
synced 2025-12-28 06:36:33 +01:00
Without backticks, the text UNDERSCORE UNDERSCORE eq UNDERSCORE UNDERSCORE would be considered to make things bold in our markdown output, making the query info look strange. Example https://codeql.github.com/codeql-query-help/python/py-slots-in-old-style-class/
93 lines
3.0 KiB
Plaintext
93 lines
3.0 KiB
Plaintext
/**
|
|
* @name Overwriting attribute in super-class or sub-class
|
|
* @description Assignment to self attribute overwrites attribute previously defined in subclass or superclass `__init__` method.
|
|
* @kind problem
|
|
* @tags reliability
|
|
* maintainability
|
|
* modularity
|
|
* @problem.severity warning
|
|
* @sub-severity low
|
|
* @precision medium
|
|
* @id py/overwritten-inherited-attribute
|
|
*/
|
|
|
|
import python
|
|
|
|
class InitCallStmt extends ExprStmt {
|
|
InitCallStmt() {
|
|
exists(Call call, Attribute attr | call = this.getValue() and attr = call.getFunc() |
|
|
attr.getName() = "__init__"
|
|
)
|
|
}
|
|
}
|
|
|
|
predicate overwrites_which(Function subinit, AssignStmt write_attr, string which) {
|
|
write_attr.getScope() = subinit and
|
|
self_write_stmt(write_attr, _) and
|
|
exists(Stmt top | top.contains(write_attr) or top = write_attr |
|
|
(
|
|
exists(int i, int j, InitCallStmt call | call.getScope() = subinit |
|
|
i > j and top = subinit.getStmt(i) and call = subinit.getStmt(j) and which = "superclass"
|
|
)
|
|
or
|
|
exists(int i, int j, InitCallStmt call | call.getScope() = subinit |
|
|
i < j and top = subinit.getStmt(i) and call = subinit.getStmt(j) and which = "subclass"
|
|
)
|
|
)
|
|
)
|
|
}
|
|
|
|
predicate self_write_stmt(Stmt s, string attr) {
|
|
exists(Attribute a, Name self |
|
|
self = a.getObject() and
|
|
s.contains(a) and
|
|
self.getId() = "self" and
|
|
a.getCtx() instanceof Store and
|
|
a.getName() = attr
|
|
)
|
|
}
|
|
|
|
predicate both_assign_attribute(Stmt s1, Stmt s2, Function f1, Function f2) {
|
|
exists(string name |
|
|
s1.getScope() = f1 and
|
|
s2.getScope() = f2 and
|
|
self_write_stmt(s1, name) and
|
|
self_write_stmt(s2, name)
|
|
)
|
|
}
|
|
|
|
predicate attribute_overwritten(
|
|
AssignStmt overwrites, AssignStmt overwritten, string name, string classtype, string classname
|
|
) {
|
|
exists(
|
|
FunctionObject superinit, FunctionObject subinit, ClassObject superclass, ClassObject subclass,
|
|
AssignStmt subattr, AssignStmt superattr
|
|
|
|
|
(
|
|
classtype = "superclass" and
|
|
classname = superclass.getName() and
|
|
overwrites = subattr and
|
|
overwritten = superattr
|
|
or
|
|
classtype = "subclass" and
|
|
classname = subclass.getName() and
|
|
overwrites = superattr and
|
|
overwritten = subattr
|
|
) and
|
|
/* OK if overwritten in subclass and is a class attribute */
|
|
(not exists(superclass.declaredAttribute(name)) or classtype = "subclass") and
|
|
superclass.declaredAttribute("__init__") = superinit and
|
|
subclass.declaredAttribute("__init__") = subinit and
|
|
superclass = subclass.getASuperType() and
|
|
overwrites_which(subinit.getFunction(), subattr, classtype) and
|
|
both_assign_attribute(subattr, superattr, subinit.getFunction(), superinit.getFunction()) and
|
|
self_write_stmt(superattr, name)
|
|
)
|
|
}
|
|
|
|
from string classtype, AssignStmt overwrites, AssignStmt overwritten, string name, string classname
|
|
where attribute_overwritten(overwrites, overwritten, name, classtype, classname)
|
|
select overwrites,
|
|
"Assignment overwrites attribute " + name + ", which was previously defined in " + classtype +
|
|
" $@.", overwritten, classname
|