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

Skip to content

Commit b8a9a35

Browse files
committed
Python: Autoformat Variables/*
1 parent 25ab0ed commit b8a9a35

17 files changed

Lines changed: 231 additions & 260 deletions

python/ql/src/Variables/Definition.qll

Lines changed: 22 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,20 @@
11
import python
22

3-
43
/**
54
* A control-flow node that defines a variable
65
*/
76
class Definition extends NameNode, DefinitionNode {
8-
97
/**
108
* The variable defined by this control-flow node.
119
*/
12-
Variable getVariable() {
13-
this.defines(result)
14-
}
10+
Variable getVariable() { this.defines(result) }
1511

1612
/**
1713
* The SSA variable corresponding to the current definition. Since SSA variables
1814
* are only generated for definitions with at least one use, not all definitions
1915
* will have an SSA variable.
2016
*/
21-
SsaVariable getSsaVariable() {
22-
result.getDefinition() = this
23-
}
17+
SsaVariable getSsaVariable() { result.getDefinition() = this }
2418

2519
/**
2620
* The index of this definition in its basic block.
@@ -42,9 +36,7 @@ class Definition extends NameNode, DefinitionNode {
4236
}
4337

4438
/** Is this definition the first in its basic block for its variable? */
45-
predicate isFirst() {
46-
this.rankInBB(_, _) = 1
47-
}
39+
predicate isFirst() { this.rankInBB(_, _) = 1 }
4840

4941
/** Is this definition the last in its basic block for its variable? */
5042
predicate isLast() {
@@ -66,8 +58,10 @@ class Definition extends NameNode, DefinitionNode {
6658
this.getVariable().getScope() = this.getScope() and
6759
// A call to locals() or vars() in the variable scope counts as a use
6860
not exists(Function f, Call c, string locals_or_vars |
69-
c.getScope() = f and this.getScope() = f and
70-
c.getFunc().(Name).getId() = locals_or_vars |
61+
c.getScope() = f and
62+
this.getScope() = f and
63+
c.getFunc().(Name).getId() = locals_or_vars
64+
|
7165
locals_or_vars = "locals" or locals_or_vars = "vars"
7266
)
7367
}
@@ -96,55 +90,45 @@ class Definition extends NameNode, DefinitionNode {
9690
* We also ignore anything named "_", "empty", "unused" or "dummy"
9791
*/
9892
predicate isRelevant() {
99-
exists(AstNode p |
100-
p = this.getNode().getParentNode() |
93+
exists(AstNode p | p = this.getNode().getParentNode() |
10194
p instanceof Assign or p instanceof AugAssign or p instanceof Tuple
102-
)
103-
and
104-
not name_acceptable_for_unused_variable(this.getVariable())
105-
and
95+
) and
96+
not name_acceptable_for_unused_variable(this.getVariable()) and
10697
/* Decorated classes and functions are used */
107-
not exists(this.getNode().getParentNode().(FunctionDef).getDefinedFunction().getADecorator())
108-
and
98+
not exists(this.getNode().getParentNode().(FunctionDef).getDefinedFunction().getADecorator()) and
10999
not exists(this.getNode().getParentNode().(ClassDef).getDefinedClass().getADecorator())
110100
}
111-
112101
}
113102

114103
/**
115104
* Check whether basic block `a` reaches basic block `b` without an intervening
116105
* definition of variable `v`. The relation is not transitive by default, so any
117106
* observed transitivity will be caused by loops in the control-flow graph.
118107
*/
119-
private
120-
predicate reaches_without_redef(Variable v, BasicBlock a, BasicBlock b) {
108+
private predicate reaches_without_redef(Variable v, BasicBlock a, BasicBlock b) {
121109
exists(Definition def | a.getASuccessor() = b |
122110
def.getBasicBlock() = a and def.getVariable() = v and maybe_redefined(v)
123-
) or
111+
)
112+
or
124113
exists(BasicBlock mid | reaches_without_redef(v, a, mid) |
125-
not exists(NameNode cfn | cfn.defines(v) |
126-
cfn.getBasicBlock() = mid
127-
) and
114+
not exists(NameNode cfn | cfn.defines(v) | cfn.getBasicBlock() = mid) and
128115
mid.getASuccessor() = b
129116
)
130117
}
131118

132-
private predicate maybe_redefined(Variable v) {
133-
strictcount(Definition d | d.defines(v)) > 1
134-
}
119+
private predicate maybe_redefined(Variable v) { strictcount(Definition d | d.defines(v)) > 1 }
135120

136121
predicate name_acceptable_for_unused_variable(Variable var) {
137-
exists(string name |
138-
var.getId() = name |
139-
name.regexpMatch("_+") or name = "empty" or
140-
name.matches("%unused%") or name = "dummy" or
122+
exists(string name | var.getId() = name |
123+
name.regexpMatch("_+") or
124+
name = "empty" or
125+
name.matches("%unused%") or
126+
name = "dummy" or
141127
name.regexpMatch("__.*")
142128
)
143129
}
144130

145-
146131
class ListComprehensionDeclaration extends ListComp {
147-
148132
Name getALeakedVariableUse() {
149133
major_version() = 2 and
150134
this.getIterationVariable(_).getId() = result.getId() and
@@ -153,8 +137,5 @@ class ListComprehensionDeclaration extends ListComp {
153137
result.isUse()
154138
}
155139

156-
Name getDefinition() {
157-
result = this.getIterationVariable(0).getAStore()
158-
}
159-
140+
Name getDefinition() { result = this.getIterationVariable(0).getAStore() }
160141
}

python/ql/src/Variables/Global.ql

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,5 +14,3 @@ import python
1414
from Global g
1515
where not g.getScope() instanceof Module
1616
select g, "Updating global variables except at module initialization is discouraged"
17-
18-

python/ql/src/Variables/GlobalAtModuleLevel.ql

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,4 +14,4 @@ import python
1414

1515
from Global g
1616
where g.getScope() instanceof Module
17-
select g, "Declaring '" + g.getAName() + "' as global at module-level is redundant."
17+
select g, "Declaring '" + g.getAName() + "' as global at module-level is redundant."

python/ql/src/Variables/LeakingListComprehension.ql

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -15,16 +15,17 @@ import Definition
1515

1616
from ListComprehensionDeclaration l, Name use, Name defn
1717
where
18-
use = l.getALeakedVariableUse() and
19-
defn = l.getDefinition() and
20-
l.getAFlowNode().strictlyReaches(use.getAFlowNode()) and
21-
/* Make sure we aren't in a loop, as the variable may be redefined */
22-
not use.getAFlowNode().strictlyReaches(l.getAFlowNode()) and
23-
not l.contains(use) and
24-
not use.deletes(_) and
25-
not exists(SsaVariable v |
26-
v.getAUse() = use.getAFlowNode() and
27-
not v.getDefinition().strictlyDominates(l.getAFlowNode())
28-
)
29-
30-
select use, use.getId() + " may have a different value in Python 3, as the $@ will not be in scope.", defn, "list comprehension variable"
18+
use = l.getALeakedVariableUse() and
19+
defn = l.getDefinition() and
20+
l.getAFlowNode().strictlyReaches(use.getAFlowNode()) and
21+
/* Make sure we aren't in a loop, as the variable may be redefined */
22+
not use.getAFlowNode().strictlyReaches(l.getAFlowNode()) and
23+
not l.contains(use) and
24+
not use.deletes(_) and
25+
not exists(SsaVariable v |
26+
v.getAUse() = use.getAFlowNode() and
27+
not v.getDefinition().strictlyDominates(l.getAFlowNode())
28+
)
29+
select use,
30+
use.getId() + " may have a different value in Python 3, as the $@ will not be in scope.", defn,
31+
"list comprehension variable"

python/ql/src/Variables/Loop.qll

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,19 @@
11
import python
22

3-
43
private predicate empty_sequence(Expr e) {
5-
exists(SsaVariable var | var.getAUse().getNode() = e | empty_sequence(var.getDefinition().getNode())) or
6-
e instanceof List and not exists(e.(List).getAnElt()) or
7-
e instanceof Tuple and not exists(e.(Tuple).getAnElt()) or
4+
exists(SsaVariable var | var.getAUse().getNode() = e |
5+
empty_sequence(var.getDefinition().getNode())
6+
)
7+
or
8+
e instanceof List and not exists(e.(List).getAnElt())
9+
or
10+
e instanceof Tuple and not exists(e.(Tuple).getAnElt())
11+
or
812
e.(StrConst).getText().length() = 0
913
}
1014

1115
/* This has the potential for refinement, but we err on the side of fewer false positives for now. */
12-
private predicate probably_non_empty_sequence(Expr e) {
13-
not empty_sequence(e)
14-
}
16+
private predicate probably_non_empty_sequence(Expr e) { not empty_sequence(e) }
1517

1618
/** A loop which probably defines v */
1719
private Stmt loop_probably_defines(Variable v) {
@@ -24,8 +26,7 @@ private Stmt loop_probably_defines(Variable v) {
2426

2527
/** Holds if the variable used by `use` is probably defined in a loop */
2628
predicate probably_defined_in_loop(Name use) {
27-
exists(Stmt loop |
28-
loop = loop_probably_defines(use.getVariable()) |
29+
exists(Stmt loop | loop = loop_probably_defines(use.getVariable()) |
2930
loop.getAFlowNode().strictlyReaches(use.getAFlowNode())
3031
)
3132
}

python/ql/src/Variables/LoopVariableCapture.ql

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,11 +30,12 @@ predicate capturing_looping_construct(CallableExpr capturing, AstNode loop, Vari
3030
}
3131

3232
predicate escaping_capturing_looping_construct(CallableExpr capturing, AstNode loop, Variable var) {
33-
capturing_looping_construct(capturing, loop, var)
34-
and
33+
capturing_looping_construct(capturing, loop, var) and
3534
// Escapes if used out side of for loop or is a lambda in a comprehension
3635
(
37-
exists(Expr e, For forloop | forloop = loop and e.pointsTo(_, _, capturing) | not forloop.contains(e))
36+
exists(Expr e, For forloop | forloop = loop and e.pointsTo(_, _, capturing) |
37+
not forloop.contains(e)
38+
)
3839
or
3940
loop.(Comp).getElt() = capturing
4041
or

python/ql/src/Variables/MultiplyDefined.ql

Lines changed: 23 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -15,29 +15,39 @@ import python
1515
import Definition
1616

1717
predicate multiply_defined(AstNode asgn1, AstNode asgn2, Variable v) {
18-
/* Must be redefined on all possible paths in the CFG corresponding to the original source.
18+
/*
19+
* Must be redefined on all possible paths in the CFG corresponding to the original source.
1920
* For example, splitting may create a path where `def` is unconditionally redefined, even though
20-
* it is not in the original source. */
21+
* it is not in the original source.
22+
*/
23+
2124
forex(Definition def, Definition redef |
2225
def.getVariable() = v and
2326
def = asgn1.getAFlowNode() and
24-
redef = asgn2.getAFlowNode() |
27+
redef = asgn2.getAFlowNode()
28+
|
2529
def.isUnused() and
2630
def.getARedef() = redef and
2731
def.isRelevant()
2832
)
2933
}
3034

3135
predicate simple_literal(Expr e) {
32-
e.(Num).getN() = "0" or
33-
e instanceof NameConstant or
34-
e instanceof List and not exists(e.(List).getAnElt()) or
35-
e instanceof Tuple and not exists(e.(Tuple).getAnElt()) or
36-
e instanceof Dict and not exists(e.(Dict).getAKey()) or
36+
e.(Num).getN() = "0"
37+
or
38+
e instanceof NameConstant
39+
or
40+
e instanceof List and not exists(e.(List).getAnElt())
41+
or
42+
e instanceof Tuple and not exists(e.(Tuple).getAnElt())
43+
or
44+
e instanceof Dict and not exists(e.(Dict).getAKey())
45+
or
3746
e.(StrConst).getText() = ""
3847
}
3948

40-
/** A multiple definition is 'uninteresting' if it sets a variable to a
49+
/**
50+
* A multiple definition is 'uninteresting' if it sets a variable to a
4151
* simple literal before reassigning it.
4252
* x = None
4353
* if cond:
@@ -46,16 +56,14 @@ predicate simple_literal(Expr e) {
4656
* x = value2
4757
*/
4858
predicate uninteresting_definition(AstNode asgn1) {
49-
exists(AssignStmt a |
50-
a.getATarget() = asgn1 |
51-
simple_literal(a.getValue())
52-
)
59+
exists(AssignStmt a | a.getATarget() = asgn1 | simple_literal(a.getValue()))
5360
}
5461

55-
5662
from AstNode asgn1, AstNode asgn2, Variable v
5763
where
5864
multiply_defined(asgn1, asgn2, v) and
5965
forall(Name el | el = asgn1.getParentNode().(Tuple).getAnElt() | multiply_defined(el, _, _)) and
6066
not uninteresting_definition(asgn1)
61-
select asgn1, "This assignment to '" + v.getId() + "' is unnecessary as it is redefined $@ before this value is used.", asgn2 as t, "here"
67+
select asgn1,
68+
"This assignment to '" + v.getId() +
69+
"' is unnecessary as it is redefined $@ before this value is used.", asgn2 as t, "here"

python/ql/src/Variables/ShadowBuiltin.ql

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -44,9 +44,10 @@ predicate white_list(string name) {
4444
}
4545

4646
predicate shadows(Name d, string name, Scope scope, int line) {
47-
exists(LocalVariable l | d.defines(l) and
48-
l.getId() = name and
49-
exists(Builtin::builtin(l.getId()))
47+
exists(LocalVariable l |
48+
d.defines(l) and
49+
l.getId() = name and
50+
exists(Builtin::builtin(l.getId()))
5051
) and
5152
scope instanceof Function and
5253
d.getScope() = scope and
@@ -58,7 +59,8 @@ predicate shadows(Name d, string name, Scope scope, int line) {
5859
predicate first_shadowing_definition(Name d, string name) {
5960
exists(int first, Scope scope |
6061
shadows(d, name, scope, first) and
61-
first = min(int line | shadows(_, name, scope, line)))
62+
first = min(int line | shadows(_, name, scope, line))
63+
)
6264
}
6365

6466
from Name d, string name

python/ql/src/Variables/ShadowGlobal.ql

Lines changed: 19 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -17,51 +17,55 @@ import Shadowing
1717
import semmle.python.types.Builtins
1818

1919
predicate shadows(Name d, GlobalVariable g, Scope scope, int line) {
20-
exists(LocalVariable l | d.defines(l) and l.getId() = g.getId() and
21-
scope instanceof Function and g.getScope() = scope.getScope() and
20+
exists(LocalVariable l |
21+
d.defines(l) and
22+
l.getId() = g.getId() and
23+
scope instanceof Function and
24+
g.getScope() = scope.getScope() and
2225
not exists(Import il, Import ig, Name gd | il.contains(d) and gd.defines(g) and ig.contains(gd)) and
2326
not exists(Assign a | a.getATarget() = d and a.getValue() = g.getAnAccess())
2427
) and
2528
not exists(Builtin::builtin(g.getId())) and
2629
d.getScope() = scope and
2730
d.getLocation().getStartLine() = line and
28-
exists(Name defn | defn.defines(g) |
29-
not exists(If i | i.isNameEqMain() |
30-
i.contains(defn)
31-
)
32-
) and
31+
exists(Name defn | defn.defines(g) | not exists(If i | i.isNameEqMain() | i.contains(defn))) and
3332
not optimizing_parameter(d)
3433
}
3534

3635
/* pytest dynamically populates its namespace so, we cannot look directly for the pytest.fixture function */
3736
AttrNode pytest_fixture_attr() {
38-
exists(ModuleValue pytest |
39-
result.getObject("fixture").pointsTo(pytest)
40-
)
37+
exists(ModuleValue pytest | result.getObject("fixture").pointsTo(pytest))
4138
}
4239

4340
Value pytest_fixture() {
4441
exists(CallNode call |
4542
call.getFunction() = pytest_fixture_attr()
4643
or
4744
call.getFunction().(CallNode).getFunction() = pytest_fixture_attr()
48-
|
45+
|
4946
call.pointsTo(result)
5047
)
5148
}
5249

5350
/* pytest fixtures require that the parameter name is also a global */
5451
predicate assigned_pytest_fixture(GlobalVariable v) {
55-
exists(NameNode def | def.defines(v) and def.(DefinitionNode).getValue().pointsTo(pytest_fixture()))
52+
exists(NameNode def |
53+
def.defines(v) and def.(DefinitionNode).getValue().pointsTo(pytest_fixture())
54+
)
5655
}
5756

5857
predicate first_shadowing_definition(Name d, GlobalVariable g) {
5958
exists(int first, Scope scope |
6059
shadows(d, g, scope, first) and
61-
first = min(int line | shadows(_, g, scope, line)))
60+
first = min(int line | shadows(_, g, scope, line))
61+
)
6262
}
6363

6464
from Name d, GlobalVariable g, Name def
65-
where first_shadowing_definition(d, g) and not exists(Name n | n.deletes(g)) and
66-
def.defines(g) and not assigned_pytest_fixture(g) and not g.getId() = "_"
65+
where
66+
first_shadowing_definition(d, g) and
67+
not exists(Name n | n.deletes(g)) and
68+
def.defines(g) and
69+
not assigned_pytest_fixture(g) and
70+
not g.getId() = "_"
6771
select d, "Local variable '" + g.getId() + "' shadows a global variable defined $@.", def, "here"

0 commit comments

Comments
 (0)