Skip to content

Commit a9fd2a2

Browse files
committed
Python: Add DuckTyping::hasUnreliableMro
The relative simplicity of the MRO computation in `DataFlowDispatch` was causing quite a lot of FPs to appear for the "wrong number/name of arguments in class instantiation" queries. The easiest fix was to just exclude cases where we know the MRO computation will be imprecise -- when there are superclasses with multiple inheritance or unknown bases.
1 parent f6cd63f commit a9fd2a2

File tree

3 files changed

+15
-0
lines changed

3 files changed

+15
-0
lines changed

python/ql/lib/semmle/python/dataflow/new/internal/DataFlowDispatch.qll

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2118,6 +2118,19 @@ module DuckTyping {
21182118
*/
21192119
Function getInit(Class cls) { result = invokedFunctionFromClassConstruction(cls, "__init__") }
21202120

2121+
/**
2122+
* Holds if `cls` or any of its superclasses uses multiple inheritance, or
2123+
* has an unresolved base class. In these cases, our MRO approximation may
2124+
* resolve to the wrong `__init__`, so we should not flag argument mismatches.
2125+
*/
2126+
predicate hasUnreliableMro(Class cls) {
2127+
exists(Class sup | sup = getADirectSuperclass*(cls) |
2128+
exists(sup.getBase(1))
2129+
or
2130+
hasUnresolvedBase(sup)
2131+
)
2132+
}
2133+
21212134
/**
21222135
* Holds if `f` overrides a method in a superclass with the same name.
21232136
*/

python/ql/src/Classes/WrongNameForArgumentInClassInstantiation.ql

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ predicate illegally_named_parameter(Call call, Class cls, string name) {
4343
from Call call, Class cls, string name, Function init
4444
where
4545
illegally_named_parameter(call, cls, name) and
46+
not DuckTyping::hasUnreliableMro(cls) and
4647
init = DuckTyping::getInit(cls)
4748
select call, "Keyword argument '" + name + "' is not a supported parameter name of $@.", init,
4849
init.getQualifiedName()

python/ql/src/Classes/WrongNumberArgumentsInClassInstantiation.ql

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ where
7878
too = "too few arguments" and
7979
should = "no fewer than "
8080
) and
81+
not DuckTyping::hasUnreliableMro(cls) and
8182
init = DuckTyping::getInit(cls)
8283
select call, "Call to $@ with " + too + "; should be " + should + limit.toString() + ".", init,
8384
init.getQualifiedName()

0 commit comments

Comments
 (0)