Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 85ad89c

Browse files
authored
Merge pull request #1292 from markshannon/python-prune-in-ql
Python: Do pruning in QL.
2 parents 1affd30 + 2040b01 commit 85ad89c

8 files changed

Lines changed: 845 additions & 26 deletions

File tree

python/ql/src/semmle/python/Exprs.qll

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -342,7 +342,7 @@ class Ellipsis extends Ellipsis_ {
342342
* and numeric literals.
343343
*/
344344
abstract class ImmutableLiteral extends Expr {
345-
345+
346346
abstract Object getLiteralObject();
347347

348348
abstract boolean booleanValue();
@@ -383,7 +383,7 @@ class IntegerLiteral extends Num {
383383
override Object getLiteralObject() {
384384
py_cobjecttypes(result, theIntType()) and py_cobjectnames(result, this.getN())
385385
or
386-
py_cobjecttypes(result, theLongType()) and py_cobjectnames(result, this.getN())
386+
py_cobjecttypes(result, theLongType()) and py_cobjectnames(result, this.getN())
387387
}
388388

389389
override boolean booleanValue() {
@@ -457,6 +457,25 @@ class ImaginaryLiteral extends Num {
457457

458458
}
459459

460+
class NegativeIntegerLiteral extends ImmutableLiteral, UnaryExpr {
461+
462+
NegativeIntegerLiteral() {
463+
this.getOp() instanceof USub and
464+
this.getOperand() instanceof IntegerLiteral
465+
}
466+
467+
override boolean booleanValue() {
468+
result = this.getOperand().(IntegerLiteral).booleanValue()
469+
}
470+
471+
override Object getLiteralObject() {
472+
(py_cobjecttypes(result, theIntType()) or py_cobjecttypes(result, theLongType()))
473+
and
474+
py_cobjectnames(result, "-" + this.getOperand().(IntegerLiteral).getN())
475+
}
476+
477+
}
478+
460479
/** A unicode string expression, such as `u"\u20ac"`. Note that unadorned string constants such as
461480
"hello" are treated as Bytes for Python2, but Unicode for Python3. */
462481
class Unicode extends StrConst {

python/ql/src/semmle/python/Flow.qll

Lines changed: 21 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
import python
22
import semmle.python.flow.NameNode
33
private import semmle.python.pointsto.PointsTo
4-
4+
private import semmle.python.Pruning
55

66
/* Note about matching parent and child nodes and CFG splitting:
77
*
88
* As a result of CFG splitting a single AST node may have multiple CFG nodes.
9-
* Therefore, when matching CFG nodes to children, we need to make sure that
9+
* Therefore, when matching CFG nodes to children, we need to make sure that
1010
* we don't match the child of one CFG node to the wrong parent.
1111
* We do this by checking dominance. If the CFG node for the parent precedes that of
1212
* the child, then he child node matches the parent node if it is dominated by it.
@@ -33,6 +33,10 @@ private AstNode toAst(ControlFlowNode n) {
3333
*/
3434
class ControlFlowNode extends @py_flow_node {
3535

36+
cached ControlFlowNode() {
37+
not Pruner::unreachable(this)
38+
}
39+
3640
/** Whether this control flow node is a load (including those in augmented assignments) */
3741
predicate isLoad() {
3842
exists(Expr e | e = toAst(this) | py_expr_contexts(_, 3, e) and not augstore(_, this))
@@ -234,7 +238,7 @@ class ControlFlowNode extends @py_flow_node {
234238

235239
/** Gets what this flow node might "refer-to". Performs a combination of localized (intra-procedural) points-to
236240
* analysis and global module-level analysis. This points-to analysis favours precision over recall. It is highly
237-
* precise, but may not provide information for a significant number of flow-nodes.
241+
* precise, but may not provide information for a significant number of flow-nodes.
238242
* If the class is unimportant then use `refersTo(value)` or `refersTo(value, origin)` instead.
239243
*/
240244
pragma [nomagic]
@@ -251,9 +255,9 @@ class ControlFlowNode extends @py_flow_node {
251255
PointsTo::points_to(this, context, obj, cls, origin)
252256
}
253257

254-
/** Whether this flow node might "refer-to" to `value` which is from `origin`
255-
* Unlike `this.refersTo(value, _, origin)` this predicate includes results
256-
* where the class cannot be inferred.
258+
/** Whether this flow node might "refer-to" to `value` which is from `origin`
259+
* Unlike `this.refersTo(value, _, origin)` this predicate includes results
260+
* where the class cannot be inferred.
257261
*/
258262
pragma [nomagic]
259263
predicate refersTo(Object obj, ControlFlowNode origin) {
@@ -323,7 +327,7 @@ class ControlFlowNode extends @py_flow_node {
323327
exists(BasicBlock b |
324328
start_bb_likely_reachable(b) and
325329
not end_bb_likely_reachable(b) and
326-
/* If there is an unlikely successor edge earlier in the BB
330+
/* If there is an unlikely successor edge earlier in the BB
327331
* than this node, then this node must be unreachable */
328332
exists(ControlFlowNode p, int i, int j |
329333
p.(RaisingNode).unlikelySuccessor(_) and
@@ -366,7 +370,7 @@ class ControlFlowNode extends @py_flow_node {
366370
}
367371

368372
/** Whether this dominates other.
369-
* Note that all nodes dominate themselves.
373+
* Note that all nodes dominate themselves.
370374
*/
371375
pragma [inline] predicate dominates(ControlFlowNode other) {
372376
// This predicate is gigantic, so it must be inlined.
@@ -457,7 +461,7 @@ class CallNode extends ControlFlowNode {
457461

458462
/** Gets the flow node corresponding to the named argument of the call corresponding to this flow node */
459463
ControlFlowNode getArgByName(string name) {
460-
exists(Call c, Keyword k | this.getNode() = c and k = c.getAKeyword() and
464+
exists(Call c, Keyword k | this.getNode() = c and k = c.getAKeyword() and
461465
k.getValue() = result.getNode() and k.getArg() = name and
462466
result.getBasicBlock().dominates(this.getBasicBlock()))
463467
}
@@ -514,7 +518,7 @@ class AttrNode extends ControlFlowNode {
514518
/** Gets the flow node corresponding to the object of the attribute expression corresponding to this flow node,
515519
with the matching name */
516520
ControlFlowNode getObject(string name) {
517-
exists(Attribute a |
521+
exists(Attribute a |
518522
this.getNode() = a and a.getObject() = result.getNode() and
519523
a.getName() = name and
520524
result.getBasicBlock().dominates(this.getBasicBlock()))
@@ -585,7 +589,7 @@ class SubscriptNode extends ControlFlowNode {
585589
toAst(this) instanceof Subscript
586590
}
587591

588-
/** DEPRECATED: Use `getObject()` instead.
592+
/** DEPRECATED: Use `getObject()` instead.
589593
* This will be formally deprecated before the end 2018 and removed in 2019.*/
590594
ControlFlowNode getValue() {
591595
exists(Subscript s | this.getNode() = s and s.getObject() = result.getNode() and
@@ -718,7 +722,7 @@ class UnaryExprNode extends ControlFlowNode {
718722
}
719723

720724
/** A control flow node corresponding to a definition, that is a control flow node
721-
* where a value is assigned to this node.
725+
* where a value is assigned to this node.
722726
* Includes control flow nodes for the targets of assignments, simple or augmented,
723727
* and nodes implicitly assigned in class and function definitions and imports.
724728
*/
@@ -945,7 +949,7 @@ class BasicBlock extends @py_flow_node {
945949

946950
/** Whether this basic block dominates the other */
947951
pragma[nomagic] predicate dominates(BasicBlock other) {
948-
this = other
952+
this = other
949953
or
950954
this.strictlyDominates(other)
951955
}
@@ -954,8 +958,8 @@ class BasicBlock extends @py_flow_node {
954958
this.firstNode().getImmediateDominator().getBasicBlock() = result
955959
}
956960

957-
/** Dominance frontier of a node x is the set of all nodes `other` such that `this` dominates a predecessor
958-
* of `other` but does not strictly dominate `other` */
961+
/** Dominance frontier of a node x is the set of all nodes `other` such that `this` dominates a predecessor
962+
* of `other` but does not strictly dominate `other` */
959963
predicate dominanceFrontier(BasicBlock other) {
960964
this.dominates(other.getAPredecessor()) and not this.strictlyDominates(other)
961965
}
@@ -1124,3 +1128,5 @@ private predicate end_bb_likely_reachable(BasicBlock b) {
11241128
)
11251129
}
11261130

1131+
1132+

0 commit comments

Comments
 (0)