mirror of
https://github.com/github/codeql.git
synced 2026-05-14 11:19:27 +02:00
Python: Port ContainsNonContainer.ql
Uses the new `DuckTyping` module to handle recognising whether a class is a container or not. Only trivial test changes (one version uses "class", the other "Class"). Note that the ported query has no understanding of built-in classes. At some point we'll likely want to replace `hasUnresolvedBase` (which will hold for any class that extends a built-in) with something that's aware of the built-in classes.
This commit is contained in:
@@ -12,25 +12,21 @@
|
||||
*/
|
||||
|
||||
import python
|
||||
private import LegacyPointsTo
|
||||
import semmle.python.dataflow.new.DataFlow
|
||||
private import semmle.python.dataflow.new.internal.DataFlowDispatch
|
||||
|
||||
predicate rhs_in_expr(ControlFlowNode rhs, Compare cmp) {
|
||||
exists(Cmpop op, int i | cmp.getOp(i) = op and cmp.getComparator(i) = rhs.getNode() |
|
||||
predicate rhs_in_expr(Expr rhs, Compare cmp) {
|
||||
exists(Cmpop op, int i | cmp.getOp(i) = op and cmp.getComparator(i) = rhs |
|
||||
op instanceof In or op instanceof NotIn
|
||||
)
|
||||
}
|
||||
|
||||
from
|
||||
ControlFlowNodeWithPointsTo non_seq, Compare cmp, Value v, ClassValue cls, ControlFlowNode origin
|
||||
from Compare cmp, DataFlow::LocalSourceNode origin, DataFlow::Node rhs, Class cls
|
||||
where
|
||||
rhs_in_expr(non_seq, cmp) 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 = ClassValue::nonetype() and
|
||||
not cls = Value::named("types.MappingProxyType")
|
||||
origin = classInstanceTracker(cls) and
|
||||
origin.flowsTo(rhs) and
|
||||
not DuckTyping::isContainer(cls) and
|
||||
not DuckTyping::hasUnresolvedBase(getADirectSuperclass*(cls)) and
|
||||
rhs_in_expr(rhs.asExpr(), cmp)
|
||||
select cmp, "This test may raise an Exception as the $@ may be of non-container class $@.", origin,
|
||||
"target", cls, cls.getName()
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
| expressions_test.py:89:8:89:15 | Compare | This test may raise an Exception as the $@ may be of non-container class $@. | expressions_test.py:88:11:88:17 | ControlFlowNode for XIter() | target | expressions_test.py:77:1:77:20 | class XIter | XIter |
|
||||
| expressions_test.py:91:8:91:19 | Compare | This test may raise an Exception as the $@ may be of non-container class $@. | expressions_test.py:88:11:88:17 | ControlFlowNode for XIter() | target | expressions_test.py:77:1:77:20 | class XIter | XIter |
|
||||
| expressions_test.py:89:8:89:15 | Compare | This test may raise an Exception as the $@ may be of non-container class $@. | expressions_test.py:88:11:88:17 | ControlFlowNode for XIter() | target | expressions_test.py:77:1:77:20 | Class XIter | XIter |
|
||||
| expressions_test.py:91:8:91:19 | Compare | This test may raise an Exception as the $@ may be of non-container class $@. | expressions_test.py:88:11:88:17 | ControlFlowNode for XIter() | target | expressions_test.py:77:1:77:20 | Class XIter | XIter |
|
||||
|
||||
Reference in New Issue
Block a user