mirror of
https://github.com/github/codeql.git
synced 2026-02-23 18:33:42 +01:00
Fixes the test failures that arose from making `ExtractedArgumentNode` local. For the consistency checks, we now explicitly exclude the `ExtractedArgumentNode`s (now much more plentiful due to the overapproximation) that don't have a corresponding `getCallArg` tuple. For various queries/tests using `instanceof ArgumentNode`, we instead us `isArgumentNode`, which explicitly filters out the ones for which `isArgumentOf` doesn't hold (which, again, is the case for most of the nodes in the overapproximation).
60 lines
1.9 KiB
Plaintext
60 lines
1.9 KiB
Plaintext
/**
|
|
* @name `__init__` method calls overridden method
|
|
* @description Calling a method from `__init__` that is overridden by a subclass may result in a partially
|
|
* initialized instance being observed.
|
|
* @kind problem
|
|
* @tags reliability
|
|
* correctness
|
|
* quality
|
|
* @problem.severity warning
|
|
* @sub-severity low
|
|
* @precision high
|
|
* @id py/init-calls-subclass
|
|
*/
|
|
|
|
import python
|
|
import semmle.python.dataflow.new.DataFlow
|
|
import semmle.python.dataflow.new.internal.DataFlowDispatch
|
|
import semmle.python.dataflow.new.internal.DataFlowPrivate
|
|
|
|
predicate initSelfCallOverridden(
|
|
Function init, DataFlow::Node self, DataFlow::MethodCallNode call, Function target,
|
|
Function override
|
|
) {
|
|
init.isInitMethod() and
|
|
call.getScope() = init and
|
|
exists(Class superclass, Class subclass, DataFlow::ParameterNode selfArg |
|
|
superclass = init.getScope() and
|
|
subclass = override.getScope() and
|
|
subclass = getADirectSubclass+(superclass) and
|
|
selfArg.getParameter() = init.getArg(0) and
|
|
DataFlow::localFlow(selfArg, self) and
|
|
call.calls(self, override.getName()) and
|
|
target = superclass.getAMethod() and
|
|
target.getName() = override.getName()
|
|
)
|
|
}
|
|
|
|
predicate readsFromSelf(Function method) {
|
|
exists(DataFlow::ParameterNode self, DataFlow::Node sink |
|
|
self.getParameter() = method.getArg(0) and
|
|
DataFlow::localFlow(self, sink)
|
|
|
|
|
isArgumentNode(sink, _, _)
|
|
or
|
|
sink = any(DataFlow::AttrRead a).getObject()
|
|
)
|
|
}
|
|
|
|
from
|
|
Function init, DataFlow::Node self, DataFlow::MethodCallNode call, Function target,
|
|
Function override
|
|
where
|
|
initSelfCallOverridden(init, self, call, target, override) and
|
|
readsFromSelf(override) and
|
|
not isClassmethod(override) and
|
|
not isStaticmethod(override) and
|
|
not target.getName().matches("\\_%")
|
|
select call, "This call to $@ in an initialization method is overridden by $@.", target,
|
|
target.getQualifiedName(), override, override.getQualifiedName()
|