Skip to content

Commit 231414c

Browse files
authored
Merge pull request #2374 from tausbn/python-fix-mappingproxytype-fp
Python: Fix non-container FP relating to `MappingProxyType`.
2 parents b43cbeb + 3491d90 commit 231414c

File tree

3 files changed

+28
-11
lines changed

3 files changed

+28
-11
lines changed

python/ql/src/Expressions/ContainsNonContainer.ql

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -11,20 +11,24 @@
1111
*/
1212

1313
import python
14+
import semmle.python.pointsto.PointsTo
1415

1516
predicate rhs_in_expr(ControlFlowNode rhs, Compare cmp) {
1617
exists(Cmpop op, int i | cmp.getOp(i) = op and cmp.getComparator(i) = rhs.getNode() |
17-
op instanceof In or op instanceof NotIn
18+
op instanceof In or op instanceof NotIn
1819
)
1920
}
2021

21-
from ControlFlowNode non_seq, Compare cmp, ClassObject cls, ControlFlowNode origin
22-
where rhs_in_expr(non_seq, cmp) and
23-
non_seq.refersTo(_, cls, origin) and
24-
not cls.failedInference() and
25-
not cls.hasAttribute("__contains__") and
26-
not cls.hasAttribute("__iter__") and
27-
not cls.hasAttribute("__getitem__") and
28-
not cls = theNoneType()
29-
30-
select cmp, "This test may raise an Exception as the $@ may be of non-container class $@.", origin, "target", cls, cls.getName()
22+
from ControlFlowNode non_seq, Compare cmp, Value v, ClassValue cls, ControlFlowNode origin
23+
where
24+
rhs_in_expr(non_seq, cmp) and
25+
non_seq.pointsTo(_, v, origin) and
26+
v.getClass() = cls and
27+
not Types::failedInference(cls, _) and
28+
not cls.hasAttribute("__contains__") and
29+
not cls.hasAttribute("__iter__") and
30+
not cls.hasAttribute("__getitem__") and
31+
not cls = ClassValue::nonetype() and
32+
not cls = Value::named("types.MappingProxyType")
33+
select cmp, "This test may raise an Exception as the $@ may be of non-container class $@.", origin,
34+
"target", cls, cls.getName()

python/ql/src/semmle/python/objects/ObjectAPI.qll

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -660,4 +660,9 @@ module ClassValue {
660660
result = TBuiltinClassObject(Builtin::special("ModuleType"))
661661
}
662662

663+
/** Get the `ClassValue` for the `NoneType` class. */
664+
ClassValue nonetype() {
665+
result = TBuiltinClassObject(Builtin::special("NoneType"))
666+
}
667+
663668
}

python/ql/test/query-tests/Expressions/general/expressions_test.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -234,3 +234,11 @@ def func():
234234
except TypeError:
235235
return 1
236236
return 0
237+
238+
# False positive for py/member-test-non-container
239+
240+
# Container wrapped in MappingProxyType
241+
from types import MappingProxyType
242+
243+
def mpt_arg(d=MappingProxyType({})):
244+
return 1 in d

0 commit comments

Comments
 (0)