From eb23c11142739adec63f2fcd54f8e9a675dc3f15 Mon Sep 17 00:00:00 2001 From: Mark Shannon Date: Thu, 20 Jun 2019 10:33:40 +0100 Subject: [PATCH] Python: Fix ForNode class to support loop unrolling. --- python/ql/src/semmle/python/Flow.qll | 31 +++++++++++++++++++++++----- 1 file changed, 26 insertions(+), 5 deletions(-) diff --git a/python/ql/src/semmle/python/Flow.qll b/python/ql/src/semmle/python/Flow.qll index baa8b198a34..4333717a9ad 100755 --- a/python/ql/src/semmle/python/Flow.qll +++ b/python/ql/src/semmle/python/Flow.qll @@ -884,17 +884,38 @@ class ForNode extends ControlFlowNode { override For getNode() { result = super.getNode() } - /** Whether this `for` statement causes iteration over `sequence` storing each step of the iteration in `target` */ + /** Holds if this `for` statement causes iteration over `sequence` storing each step of the iteration in `target` */ predicate iterates(ControlFlowNode target, ControlFlowNode sequence) { + sequence = getSequence() and + target = possibleTarget() and + not target = unrolledSuffix().possibleTarget() + } + + /** Gets the sequence node for this `for` statement. */ + ControlFlowNode getSequence() { exists(For for | toAst(this) = for and - for.getTarget() = target.getNode() and - for.getIter() = sequence.getNode() | - sequence.getBasicBlock().dominates(this.getBasicBlock()) and - sequence.getBasicBlock().dominates(target.getBasicBlock()) + for.getIter() = result.getNode() | + result.getBasicBlock().dominates(this.getBasicBlock()) ) } + /** A possible `target` for this `for` statement, not accounting for loop unrolling */ + private ControlFlowNode possibleTarget() { + exists(For for | + toAst(this) = for and + for.getTarget() = result.getNode() and + this.getBasicBlock().dominates(result.getBasicBlock()) + ) + } + + /** The unrolled `for` statement node matching this one */ + private ForNode unrolledSuffix() { + not this = result and + toAst(this) = toAst(result) and + this.getBasicBlock().dominates(result.getBasicBlock()) + } + } /** A flow node for a `raise` statement */