Files
codeql/python/ql/src/Classes/InitCallsSubclass/InitCallsSubclassMethod.ql
Taus 6113d4be9e Python: Fix test issues
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).
2026-01-30 12:50:25 +00:00

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()