Python: Fix non-container FP relating to `MappingProxyType`.

Fixes #2307.

Also modernises the query to use the `Value` API.
This commit is contained in:
Taus Brock-Nannestad 2019-11-18 14:54:53 +01:00
Родитель ed4657c201
Коммит 1385f3c018
3 изменённых файлов: 20 добавлений и 4 удалений

Просмотреть файл

@ -11,6 +11,7 @@
*/
import python
import semmle.python.pointsto.PointsTo
predicate rhs_in_expr(ControlFlowNode rhs, Compare cmp) {
exists(Cmpop op, int i | cmp.getOp(i) = op and cmp.getComparator(i) = rhs.getNode() |
@ -18,13 +19,15 @@ predicate rhs_in_expr(ControlFlowNode rhs, Compare cmp) {
)
}
from ControlFlowNode non_seq, Compare cmp, ClassObject cls, ControlFlowNode origin
from ControlFlowNode non_seq, Compare cmp, Value v, ClassValue cls, ControlFlowNode origin
where rhs_in_expr(non_seq, cmp) and
non_seq.refersTo(_, cls, origin) and
not cls.failedInference() and
non_seq.pointsTo(_, v, origin) and
v.getClass() = cls and
not Types::failedInference(cls, _) and
not cls.hasAttribute("__contains__") and
not cls.hasAttribute("__iter__") and
not cls.hasAttribute("__getitem__") and
not cls = theNoneType()
not cls = ClassValue::nonetype() and
not cls = Value::named("types.MappingProxyType")
select cmp, "This test may raise an Exception as the $@ may be of non-container class $@.", origin, "target", cls, cls.getName()

Просмотреть файл

@ -660,4 +660,9 @@ module ClassValue {
result = TBuiltinClassObject(Builtin::special("ModuleType"))
}
/** Get the `ClassValue` for the `NoneType` class. */
ClassValue nonetype() {
result = TBuiltinClassObject(Builtin::special("NoneType"))
}
}

Просмотреть файл

@ -234,3 +234,11 @@ def func():
except TypeError:
return 1
return 0
# False positive for py/member-test-non-container
# Container wrapped in MappingProxyType
from types import MappingProxyType
def mpt_arg(d=MappingProxyType({})):
return 1 in d