Python: Modernise the py/non-iterable-in-for-loop query.

Also adds a small test case exhibiting the same false positive seen in
ODASA-8042.
This commit is contained in:
Taus Brock-Nannestad
2019-09-05 12:24:51 +02:00
parent ef7984d1cb
commit d336140c19
4 changed files with 20 additions and 4 deletions

View File

@@ -13,11 +13,11 @@
import python
from For loop, ControlFlowNode iter, ClassObject t, ControlFlowNode origin
from For loop, ControlFlowNode iter, Value v, ClassValue t, ControlFlowNode origin
where loop.getIter().getAFlowNode() = iter and
iter.refersTo(_, t, origin) and
not t.isIterable() and not t.failedInference() and
not t = theNoneType() 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, "$@ of class '$@' may be used in for-loop.", origin, "Non-iterator", t, t.getName()

View File

@@ -346,6 +346,18 @@ class ClassValue extends Value {
this.(ClassObjectInternal).lookup("__call__", _, _)
}
/** Holds if this class is an iterable. */
predicate isIterable() {
this.hasAttribute("__iter__")
or
this.hasAttribute("__getitem__")
}
/** Holds if this class is a descriptor. */
predicate isDescriptorType() {
this.hasAttribute("__get__")
}
/** Gets the qualified name for this class.
* Should return the same name as the `__qualname__` attribute on classes in Python 3.
*/

View File

@@ -1 +1,2 @@
| test.py:50:1:50:23 | For | $@ of class '$@' may be used in for-loop. | test.py:50:10:50:22 | ControlFlowNode for NonIterator() | Non-iterator | test.py:45:1:45:26 | class NonIterator | NonIterator |
| test.py:170:10:170:22 | For | $@ of class '$@' may be used in for-loop. | test.py:170:10:170:22 | ControlFlowNode for .0 | Non-iterator | test.py:169:1:169:21 | class false_positive | false_positive |

View File

@@ -165,4 +165,7 @@ def no_with():
def assert_ok(seq):
assert all(isinstance(element, (str, unicode)) for element in seq)
# False positive. ODASA-8042
class false_positive:
e = (x for x in [])