-
Notifications
You must be signed in to change notification settings - Fork 1.7k
/
Copy pathConcatenationInLoops.ql
65 lines (60 loc) · 1.65 KB
/
ConcatenationInLoops.ql
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
/**
* @name String concatenation in loop
* @description Performing string concatenation in a loop that iterates many times may affect
* performance.
* @kind problem
* @problem.severity warning
* @precision low
* @id java/string-concatenation-in-loop
* @tags efficiency
* maintainability
*/
import semmle.code.java.Type
import semmle.code.java.Expr
import semmle.code.java.Statement
import semmle.code.java.JDK
/**
* An assignment of the form
*
* ```
* v = ... + ... v ...
* ```
* or
*
* ```
* v += ...
* ```
* where `v` is a simple variable (and not, for example,
* an array element).
*/
predicate useAndDef(Assignment a, Variable v) {
a.getDest() = v.getAnAccess() and
v.getType() instanceof TypeString and
(
a instanceof AssignAddExpr
or
exists(VarAccess use | use.getVariable() = v | use.getParent*() = a.getSource()) and
a.getSource() instanceof AddExpr
)
}
/**
* Holds if `e` is executed often in loop `loop`.
*/
predicate executedOften(Assignment a) {
a.getDest().getType() instanceof TypeString and
exists(ControlFlowNode n | a.getControlFlowNode() = n | getADeepSuccessor(n) = n)
}
/** Gets a sucessor of `n`, also following function calls. */
ControlFlowNode getADeepSuccessor(ControlFlowNode n) {
result = n.getASuccessor+()
or
exists(Call c, ControlFlowNode callee | c.(Expr).getControlFlowNode() = n.getASuccessor+() |
callee = c.getCallee().getBody().getControlFlowNode() and
result = getADeepSuccessor(callee)
)
}
from Assignment a, Variable v
where
useAndDef(a, v) and
executedOften(a)
select a, "The string " + v.getName() + " is built-up in a loop: use string buffer."