mirror of
https://github.com/github/codeql.git
synced 2026-05-14 11:19:27 +02:00
Python: Port NonIteratorInForLoop.ql
Uses the `DuckTyping` module to approximate whether something is likely to be an iterator or not. We lose one test result due to the fact that we don't know what to do about `for ... in 1` (because `1` is an instance of a built-in). I'm going to defer addressing this until we get some modelling of built-in types.
This commit is contained in:
@@ -12,16 +12,15 @@
|
||||
*/
|
||||
|
||||
import python
|
||||
private import LegacyPointsTo
|
||||
private import semmle.python.dataflow.new.internal.DataFlowDispatch
|
||||
|
||||
from For loop, ControlFlowNodeWithPointsTo iter, Value v, ClassValue t, ControlFlowNode origin
|
||||
from For loop, Expr iter, Class cls
|
||||
where
|
||||
loop.getIter().getAFlowNode() = iter and
|
||||
iter.pointsTo(_, v, origin) and
|
||||
v.getClass() = t and
|
||||
not t.isIterable() and
|
||||
not t.failedInference(_) and
|
||||
not v = Value::named("None") and
|
||||
not t.isDescriptorType()
|
||||
select loop, "This for-loop may attempt to iterate over a $@ of class $@.", origin,
|
||||
"non-iterable instance", t, t.getName()
|
||||
iter = loop.getIter() and
|
||||
classInstanceTracker(cls).asExpr() = iter and
|
||||
not DuckTyping::isIterable(cls) and
|
||||
not DuckTyping::isDescriptor(cls) and
|
||||
not (loop.isAsync() and DuckTyping::hasMethod(cls, "__aiter__")) and
|
||||
not DuckTyping::hasUnresolvedBase(getADirectSuperclass*(cls))
|
||||
select loop, "This for-loop may attempt to iterate over a $@ of class $@.", iter,
|
||||
"non-iterable instance", cls, cls.getName()
|
||||
|
||||
@@ -1,2 +1 @@
|
||||
| async_iterator.py:26:11:26:34 | For | This for-loop may attempt to iterate over a $@ of class $@. | async_iterator.py:26:20:26:33 | ControlFlowNode for MissingAiter() | non-iterable instance | async_iterator.py:13:1:13:19 | class MissingAiter | MissingAiter |
|
||||
| statements_test.py:34:5:34:19 | For | This for-loop may attempt to iterate over a $@ of class $@. | statements_test.py:34:18:34:18 | ControlFlowNode for IntegerLiteral | non-iterable instance | file://:0:0:0:0 | builtin-class int | int |
|
||||
| async_iterator.py:26:11:26:34 | For | This for-loop may attempt to iterate over a $@ of class $@. | async_iterator.py:26:20:26:33 | MissingAiter() | non-iterable instance | async_iterator.py:13:1:13:19 | Class MissingAiter | MissingAiter |
|
||||
|
||||
@@ -1 +1 @@
|
||||
| test.py:50:1:50:23 | For | This for-loop may attempt to iterate over a $@ of class $@. | test.py:50:10:50:22 | ControlFlowNode for NonIterator() | non-iterable instance | test.py:45:1:45:26 | class NonIterator | NonIterator |
|
||||
| test.py:50:1:50:23 | For | This for-loop may attempt to iterate over a $@ of class $@. | test.py:50:10:50:22 | NonIterator() | non-iterable instance | test.py:45:1:45:26 | Class NonIterator | NonIterator |
|
||||
|
||||
Reference in New Issue
Block a user