mirror of
https://github.com/github/codeql.git
synced 2026-01-25 20:32:58 +01:00
72 lines
3.1 KiB
Plaintext
72 lines
3.1 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
|