-
Notifications
You must be signed in to change notification settings - Fork 2k
Expand file tree
/
Copy pathEmptyExcept.ql
More file actions
executable file
·134 lines (118 loc) · 4.24 KB
/
EmptyExcept.ql
File metadata and controls
executable file
·134 lines (118 loc) · 4.24 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
/**
* @name Empty except
* @description Except doesn't do anything and has no comment
* @kind problem
* @tags reliability
* maintainability
* external/cwe/cwe-390
* @problem.severity recommendation
* @sub-severity high
* @precision high
* @id py/empty-except
*/
import python
predicate
empty_except(ExceptStmt ex) {
not exists(Stmt s | s = ex.getAStmt() and not s instanceof Pass)
}
predicate no_else(ExceptStmt ex) {
not exists(ex.getTry().getOrelse())
}
predicate no_comment(ExceptStmt ex) {
not exists(Comment c |
c.getLocation().getFile() = ex.getLocation().getFile() and
c.getLocation().getStartLine() >= ex.getLocation().getStartLine() and
c.getLocation().getEndLine() <= ex.getBody().getLastItem().getLocation().getEndLine()
)
}
predicate non_local_control_flow(ExceptStmt ex) {
ex.getType().pointsTo(ClassValue::stopIteration())
}
predicate try_has_normal_exit(Try try) {
exists(ControlFlowNode pred, ControlFlowNode succ |
/* Exists a non-exception predecessor, successor pair */
pred.getASuccessor() = succ and
not pred.getAnExceptionalSuccessor() = succ |
/* Successor is either a normal flow node or a fall-through exit */
not exists(Scope s | s.getReturnNode() = succ) and
/* Predecessor is in try body and successor is not */
pred.getNode().getParentNode*() = try.getAStmt() and
not succ.getNode().getParentNode*() = try.getAStmt()
)
}
predicate attribute_access(Stmt s) {
s.(ExprStmt).getValue() instanceof Attribute
or
exists(string name |
s.(ExprStmt).getValue().(Call).getFunc().(Name).getId() = name |
name = "getattr" or name = "setattr" or name = "delattr"
)
or
s.(Delete).getATarget() instanceof Attribute
}
predicate subscript(Stmt s) {
s.(ExprStmt).getValue() instanceof Subscript
or
s.(Delete).getATarget() instanceof Subscript
}
predicate encode_decode_objectapi(Expr ex, ClassObject type) {
exists(string name |
ex.(Call).getFunc().(Attribute).getName() = name |
name = "encode" and type = Object::builtin("UnicodeEncodeError")
or
name = "decode" and type = Object::builtin("UnicodeDecodeError")
)
}
predicate encode_decode(Expr ex, ClassValue type) {
exists(string name |
ex.(Call).getFunc().(Attribute).getName() = name |
name = "encode" and type = ClassValue::unicodeEncodeError()
or
name = "decode" and type = ClassValue::unicodeDecodeError()
)
}
predicate small_handler_objectapi(ExceptStmt ex, Stmt s, ClassObject type) {
not exists(ex.getTry().getStmt(1)) and
s = ex.getTry().getStmt(0) and
ex.getType().refersTo(type)
}
predicate small_handler(ExceptStmt ex, Stmt s, ClassValue type) {
not exists(ex.getTry().getStmt(1)) and
s = ex.getTry().getStmt(0) and
ex.getType().pointsTo(type)
}
/** Holds if this exception handler is sufficiently small in scope to not need a comment
* as to what it is doing.
*/
predicate focussed_handler_objectapi(ExceptStmt ex) {
exists(Stmt s, ClassObject type |
small_handler_objectapi(ex, s, type) |
subscript(s) and type.getAnImproperSuperType() = theLookupErrorType()
or
attribute_access(s) and type = theAttributeErrorType()
or
s.(ExprStmt).getValue() instanceof Name and type = theNameErrorType()
or
encode_decode_objectapi(s.(ExprStmt).getValue(), type)
)
}
predicate focussed_handler(ExceptStmt ex) {
exists(Stmt s, ClassValue type |
small_handler(ex, s, type) |
subscript(s) and type.getASuperType() = ClassValue::lookupError()
or
attribute_access(s) and type = ClassValue::attributeError()
or
s.(ExprStmt).getValue() instanceof Name and type = ClassValue::nameError()
or
encode_decode(s.(ExprStmt).getValue(), type)
)
}
Try try_return() {
not exists(result.getStmt(1)) and result.getStmt(0) instanceof Return
}
from ExceptStmt ex
where empty_except(ex) and no_else(ex) and no_comment(ex) and not non_local_control_flow(ex)
and not ex.getTry() = try_return() and try_has_normal_exit(ex.getTry()) and
not focussed_handler(ex)
select ex, "'except' clause does nothing but pass and there is no explanatory comment."