Skip to content

Commit 1385f3c

Browse files
committed
Python: Fix non-container FP relating to MappingProxyType.
Fixes #2307. Also modernises the query to use the `Value` API.
1 parent ed4657c commit 1385f3c

File tree

3 files changed

+20
-4
lines changed

3 files changed

+20
-4
lines changed

python/ql/src/Expressions/ContainsNonContainer.ql

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,20 +11,23 @@
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() |
1718
op instanceof In or op instanceof NotIn
1819
)
1920
}
2021

21-
from ControlFlowNode non_seq, Compare cmp, ClassObject cls, ControlFlowNode origin
22+
from ControlFlowNode non_seq, Compare cmp, Value v, ClassValue cls, ControlFlowNode origin
2223
where rhs_in_expr(non_seq, cmp) and
23-
non_seq.refersTo(_, cls, origin) and
24-
not cls.failedInference() and
24+
non_seq.pointsTo(_, v, origin) and
25+
v.getClass() = cls and
26+
not Types::failedInference(cls, _) and
2527
not cls.hasAttribute("__contains__") and
2628
not cls.hasAttribute("__iter__") and
2729
not cls.hasAttribute("__getitem__") and
28-
not cls = theNoneType()
30+
not cls = ClassValue::nonetype() and
31+
not cls = Value::named("types.MappingProxyType")
2932

3033
select cmp, "This test may raise an Exception as the $@ may be of non-container class $@.", origin, "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)