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

Skip to content

Commit bbf7ff9

Browse files
committed
Python: do pruning in QL.
1 parent c674f54 commit bbf7ff9

6 files changed

Lines changed: 662 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
@@ -339,7 +339,7 @@ class Ellipsis extends Ellipsis_ {
339339
* and numeric literals.
340340
*/
341341
abstract class ImmutableLiteral extends Expr {
342-
342+
343343
abstract Object getLiteralObject();
344344

345345
abstract boolean booleanValue();
@@ -380,7 +380,7 @@ class IntegerLiteral extends Num {
380380
override Object getLiteralObject() {
381381
py_cobjecttypes(result, theIntType()) and py_cobjectnames(result, this.getN())
382382
or
383-
py_cobjecttypes(result, theLongType()) and py_cobjectnames(result, this.getN())
383+
py_cobjecttypes(result, theLongType()) and py_cobjectnames(result, this.getN())
384384
}
385385

386386
override boolean booleanValue() {
@@ -454,6 +454,25 @@ class ImaginaryLiteral extends Num {
454454

455455
}
456456

457+
class NegativeIntegerLiteral extends ImmutableLiteral, UnaryExpr {
458+
459+
NegativeIntegerLiteral() {
460+
this.getOp() instanceof USub and
461+
this.getOperand() instanceof IntegerLiteral
462+
}
463+
464+
override boolean booleanValue() {
465+
result = this.getOperand().(IntegerLiteral).booleanValue()
466+
}
467+
468+
override Object getLiteralObject() {
469+
py_cobjecttypes(result, theIntType()) and py_cobjectnames(result, "-" + this.getOperand().(IntegerLiteral).getN())
470+
or
471+
py_cobjecttypes(result, theLongType()) and py_cobjectnames(result, "-" + this.getOperand().(IntegerLiteral).getN())
472+
}
473+
474+
}
475+
457476
/** A unicode string expression, such as `u"\u20ac"`. Note that unadorned string constants such as
458477
"hello" are treated as Bytes for Python2, but Unicode for Python3. */
459478
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+
ControlFlowNode() {
37+
not Pruner::pruned(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))
@@ -219,7 +223,7 @@ class ControlFlowNode extends @py_flow_node {
219223

220224
/** Gets what this flow node might "refer-to". Performs a combination of localized (intra-procedural) points-to
221225
* analysis and global module-level analysis. This points-to analysis favours precision over recall. It is highly
222-
* precise, but may not provide information for a significant number of flow-nodes.
226+
* precise, but may not provide information for a significant number of flow-nodes.
223227
* If the class is unimportant then use `refersTo(value)` or `refersTo(value, origin)` instead.
224228
*/
225229
predicate refersTo(Object value, ClassObject cls, ControlFlowNode origin) {
@@ -238,9 +242,9 @@ class ControlFlowNode extends @py_flow_node {
238242
PointsTo::points_to(this, context, value, cls, origin)
239243
}
240244

241-
/** Whether this flow node might "refer-to" to `value` which is from `origin`
242-
* Unlike `this.refersTo(value, _, origin)` this predicate includes results
243-
* where the class cannot be inferred.
245+
/** Whether this flow node might "refer-to" to `value` which is from `origin`
246+
* Unlike `this.refersTo(value, _, origin)` this predicate includes results
247+
* where the class cannot be inferred.
244248
*/
245249
predicate refersTo(Object value, ControlFlowNode origin) {
246250
PointsTo::points_to(this, _, value, _, origin)
@@ -312,7 +316,7 @@ class ControlFlowNode extends @py_flow_node {
312316
exists(BasicBlock b |
313317
start_bb_likely_reachable(b) and
314318
not end_bb_likely_reachable(b) and
315-
/* If there is an unlikely successor edge earlier in the BB
319+
/* If there is an unlikely successor edge earlier in the BB
316320
* than this node, then this node must be unreachable */
317321
exists(ControlFlowNode p, int i, int j |
318322
p.(RaisingNode).unlikelySuccessor(_) and
@@ -355,7 +359,7 @@ class ControlFlowNode extends @py_flow_node {
355359
}
356360

357361
/** Whether this dominates other.
358-
* Note that all nodes dominate themselves.
362+
* Note that all nodes dominate themselves.
359363
*/
360364
pragma [inline] predicate dominates(ControlFlowNode other) {
361365
// This predicate is gigantic, so it must be inlined.
@@ -446,7 +450,7 @@ class CallNode extends ControlFlowNode {
446450

447451
/** Gets the flow node corresponding to the named argument of the call corresponding to this flow node */
448452
ControlFlowNode getArgByName(string name) {
449-
exists(Call c, Keyword k | this.getNode() = c and k = c.getAKeyword() and
453+
exists(Call c, Keyword k | this.getNode() = c and k = c.getAKeyword() and
450454
k.getValue() = result.getNode() and k.getArg() = name and
451455
result.getBasicBlock().dominates(this.getBasicBlock()))
452456
}
@@ -487,7 +491,7 @@ class AttrNode extends ControlFlowNode {
487491
/** Gets the flow node corresponding to the object of the attribute expression corresponding to this flow node,
488492
with the matching name */
489493
ControlFlowNode getObject(string name) {
490-
exists(Attribute a |
494+
exists(Attribute a |
491495
this.getNode() = a and a.getObject() = result.getNode() and
492496
a.getName() = name and
493497
result.getBasicBlock().dominates(this.getBasicBlock()))
@@ -558,7 +562,7 @@ class SubscriptNode extends ControlFlowNode {
558562
toAst(this) instanceof Subscript
559563
}
560564

561-
/** DEPRECATED: Use `getObject()` instead.
565+
/** DEPRECATED: Use `getObject()` instead.
562566
* This will be formally deprecated before the end 2018 and removed in 2019.*/
563567
ControlFlowNode getValue() {
564568
exists(Subscript s | this.getNode() = s and s.getObject() = result.getNode() and
@@ -681,7 +685,7 @@ class UnaryExprNode extends ControlFlowNode {
681685
}
682686

683687
/** A control flow node corresponding to a definition, that is a control flow node
684-
* where a value is assigned to this node.
688+
* where a value is assigned to this node.
685689
* Includes control flow nodes for the targets of assignments, simple or augmented,
686690
* and nodes implicitly assigned in class and function definitions and imports.
687691
*/
@@ -908,7 +912,7 @@ class BasicBlock extends @py_flow_node {
908912

909913
/** Whether this basic block dominates the other */
910914
pragma[nomagic] predicate dominates(BasicBlock other) {
911-
this = other
915+
this = other
912916
or
913917
this.strictlyDominates(other)
914918
}
@@ -917,8 +921,8 @@ class BasicBlock extends @py_flow_node {
917921
this.firstNode().getImmediateDominator().getBasicBlock() = result
918922
}
919923

920-
/** Dominance frontier of a node x is the set of all nodes `other` such that `this` dominates a predecessor
921-
* of `other` but does not strictly dominate `other` */
924+
/** Dominance frontier of a node x is the set of all nodes `other` such that `this` dominates a predecessor
925+
* of `other` but does not strictly dominate `other` */
922926
predicate dominanceFrontier(BasicBlock other) {
923927
this.dominates(other.getAPredecessor()) and not this.strictlyDominates(other)
924928
}
@@ -1059,3 +1063,5 @@ private predicate end_bb_likely_reachable(BasicBlock b) {
10591063
)
10601064
}
10611065

1066+
1067+

0 commit comments

Comments
 (0)