Skip to content

Commit 73cae53

Browse files
author
Robert Marsh
committed
C++: new query for dead code after goto or break
1 parent 7543fa4 commit 73cae53

File tree

6 files changed

+118
-0
lines changed

6 files changed

+118
-0
lines changed
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
goto err;
2+
free(pointer);
3+
err: return -1;
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
<!DOCTYPE qhelp PUBLIC
2+
"-//Semmle//qhelp//EN"
3+
"qhelp.dtd">
4+
<qhelp>
5+
6+
7+
<overview>
8+
<p>
9+
Code following a goto or break statement will not be executed, unless there is a label or switch
10+
case. When the code is necessary, this leads to logical errors or resource leaks. If the code is
11+
unnecessary, it may confuse readers.
12+
</p>
13+
</overview>
14+
<recommendation>
15+
<p>
16+
If the unreachable code is necessary, move the goto or break statement to after the code.
17+
Otherwise, delete the unreachable code.
18+
</p>
19+
20+
</recommendation>
21+
<example><sample src="DeadCodeGoto.cpp" />
22+
</example>
23+
<references>
24+
<li>
25+
The CERT C Secure Coding Standard: <a href="https://wiki.sei.cmu.edu/confluence/display/c/MSC12-C.+Detect+and+remove+code+that+has+no+effect+or+is+never+executed">MSC12-C. Detect and remove code that has no effect or is never executed</a>
26+
</li>
27+
</references>
28+
</qhelp>
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
/**
2+
* @name Dead code due to goto or break statement
3+
* @description A goto or break statement is followed by unreachable code.
4+
* @kind problem
5+
* @problem.severity warning
6+
* @id cpp/dead-code-goto
7+
* @tags maintainability
8+
* external/cwe/cwe-561
9+
*/
10+
11+
import cpp
12+
13+
Stmt getNextRealStmt(Block b, int i) {
14+
result = b.getStmt(i + 1) and
15+
not result instanceof EmptyStmt
16+
or
17+
b.getStmt(i + 1) instanceof EmptyStmt and
18+
result = getNextRealStmt(b, i + 1)
19+
}
20+
21+
from JumpStmt js, Block b, int i, Stmt s
22+
where b.getStmt(i) = js
23+
and s = getNextRealStmt(b, i)
24+
// the next statement isn't jumped to
25+
and not s instanceof LabelStmt
26+
and not s instanceof SwitchCase
27+
// the next statement isn't breaking out of a switch
28+
and not s.(BreakStmt).getBreakable() instanceof SwitchStmt
29+
// the jump isn't a goto into the body of the next statement
30+
and not exists (LabelStmt ls | s.(Loop).getStmt().getAChild*() = ls | ls.getName() = js.(GotoStmt).getName())
31+
select js, "This statement makes $@ dead.", s, s.toString()
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
| test.cpp:2:2:2:12 | goto ... | This statement makes $@ dead. | test.cpp:3:2:3:5 | ExprStmt | ExprStmt |
2+
| test.cpp:9:3:9:8 | break; | This statement makes $@ dead. | test.cpp:10:3:10:6 | ExprStmt | ExprStmt |
3+
| test.cpp:37:3:37:8 | break; | This statement makes $@ dead. | test.cpp:38:3:38:11 | return ... | return ... |
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Critical/DeadCodeGoto.ql
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
int test1(int x) {
2+
goto label; // BAD
3+
x++;
4+
label: return x;
5+
}
6+
7+
int test2(int x) {
8+
do {
9+
break; // BAD
10+
x++;
11+
} while(false);
12+
return x;
13+
}
14+
15+
int test3(int x) {
16+
goto label; // GOOD
17+
label: x++;
18+
return x;
19+
}
20+
21+
int test4(int x) {
22+
goto label; // GOOD
23+
do {
24+
label: x++;
25+
} while(false);
26+
return x;
27+
}
28+
29+
int test5(int x, int y) {
30+
switch(y) {
31+
case 0:
32+
break; // GOOD
33+
case 1:
34+
goto label; // GOOD
35+
break;
36+
case 2:
37+
break; // BAD
38+
return x;
39+
case 3:
40+
return x;
41+
break; // GOOD
42+
case 4:
43+
goto label; // GOOD
44+
case 5:
45+
goto label;; // GOOD
46+
default:
47+
x++;
48+
}
49+
label:
50+
return x;
51+
}
52+

0 commit comments

Comments
 (0)