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

Skip to content

Commit 739804a

Browse files
CPP : Ill-defined for-loop (C6293)
Superset of C6293, it looks for a mismatch between the initialization statement && condition and the direction of the iteration expression in a for loop.
1 parent 54493eb commit 739804a

8 files changed

Lines changed: 373 additions & 0 deletions

File tree

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,3 +13,6 @@
1313
/.vs/ql/v15/Browse.VC.db
1414
/.vs/ProjectSettings.json
1515

16+
/.vs/slnx.sqlite-journal
17+
/.vs/ql_6293a/v15/Browse.VC.opendb
18+
/.vs/ql_6293a/v15/Browse.VC.db
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
void f()
2+
{
3+
for (signed char i = 0; i < 100; i--)
4+
{
5+
// code ...
6+
}
7+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
<!DOCTYPE qhelp PUBLIC
2+
"-//Semmle//qhelp//EN"
3+
"qhelp.dtd">
4+
<qhelp>
5+
6+
<overview>
7+
<p>A <code>for-loop</code> iteration expression goes backwards with respect of the initialization statement and condition expression.</p>
8+
<p>This warning indicates that a <code>for-loop</code> might not function as intended.</p>
9+
</overview>
10+
11+
<recommendation>
12+
<p>Verify the iteration expression on the <code>for-loop</code> and make sure the direction of the iteration expression is correct.</p>
13+
</recommendation>
14+
15+
<example>
16+
<p>In the following example, the initialization statement (<code>i = 0</code>) and the condition expression (<code>i < 100</code>) indicate that the intended iteration expression should have been incrementing, but instead a postfix decrement operator is used (<code>i--</code>).</p>
17+
<sample src="illDefinedForLoop.c" />
18+
19+
<p>To fix this issue, change the iteration expression to match the direction of the initialization statement and the condition expression: <code>i++</code>.</p>
20+
</example>
21+
22+
<references>
23+
<li><a href="https://docs.microsoft.com/en-us/previous-versions/visualstudio/visual-studio-2012/58teb7hd(v=vs.110)">warning C6293: Ill-defined for-loop: counts down from minimum</a>
24+
</li>
25+
</references>
26+
27+
</qhelp>
Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
/**
2+
* @name Ill-defined for loop
3+
* @description A for-loop iteration expressions goes backward with respect of the initialization statement and condition expression.
4+
* @id cpp/ill-defined-for-loop
5+
* @kind problem
6+
* @problem.severity warning
7+
* @precision high
8+
* @tags external/microsoft/6293
9+
* @msrc.severity important
10+
*/
11+
import cpp
12+
import semmle.code.cpp.rangeanalysis.SimpleRangeAnalysis
13+
14+
predicate illDefinedDecrForStmt( ForStmt forstmt, Variable v, Expr initialCondition, Expr terminalCondition ) {
15+
v.getAnAssignedValue() = initialCondition
16+
and
17+
exists(
18+
RelationalOperation rel, Expr e |
19+
rel = forstmt.getCondition() |
20+
e = rel.getGreaterOperand()
21+
and v.getAnAccess() = rel.getLesserOperand()
22+
and terminalCondition = e
23+
)
24+
and
25+
(
26+
exists(
27+
PostfixDecrExpr pdec |
28+
pdec = forstmt.getUpdate().(PostfixDecrExpr)
29+
and pdec.getAnOperand() = v.getAnAccess()
30+
) or
31+
exists(
32+
PrefixDecrExpr pdec |
33+
pdec = forstmt.getUpdate().(PrefixDecrExpr)
34+
and pdec.getAnOperand() = v.getAnAccess()
35+
)
36+
)
37+
and
38+
upperBound(initialCondition) < lowerBound(terminalCondition)
39+
}
40+
41+
predicate illDefinedIncrForStmt( ForStmt forstmt, Variable v, Expr initialCondition, Expr terminalCondition ) {
42+
v.getAnAssignedValue() = initialCondition
43+
and
44+
exists(
45+
RelationalOperation rel, Expr e |
46+
rel = forstmt.getCondition() |
47+
e = rel.getLesserOperand()
48+
and v.getAnAccess() = rel.getGreaterOperand()
49+
and terminalCondition = e
50+
)
51+
and
52+
( exists( PostfixIncrExpr pincr |
53+
pincr = forstmt.getUpdate().(PostfixIncrExpr)
54+
and
55+
pincr.getAnOperand() = v.getAnAccess()
56+
) or
57+
exists( PrefixIncrExpr pincr |
58+
pincr = forstmt.getUpdate().(PrefixIncrExpr)
59+
and
60+
pincr.getAnOperand() = v.getAnAccess()
61+
)
62+
)
63+
and
64+
upperBound(terminalCondition) < lowerBound(initialCondition)
65+
}
66+
67+
predicate illDefinedForStmtWrongDirection( ForStmt forstmt, Variable v, Expr initialCondition, Expr terminalCondition
68+
, boolean isIncr ) {
69+
( illDefinedDecrForStmt( forstmt, v, initialCondition, terminalCondition) and isIncr = false )
70+
or
71+
( illDefinedIncrForStmt( forstmt, v, initialCondition, terminalCondition) and isIncr = true)
72+
}
73+
74+
bindingset[b]
75+
private string forLoopdirection(boolean b){
76+
if( b = true ) then result = "upward"
77+
else result = "downward"
78+
}
79+
80+
bindingset[b]
81+
private string forLoopTerminalConditionRelationship(boolean b){
82+
if( b = true ) then result = "lower"
83+
else result = "higher"
84+
}
85+
86+
predicate illDefinedForStmt( ForStmt for, string message ) {
87+
exists(
88+
boolean isIncr,
89+
Variable v,
90+
Expr initialCondition,
91+
Expr terminalCondition |
92+
illDefinedForStmtWrongDirection(for, v, initialCondition, terminalCondition, isIncr)
93+
and
94+
message = "Ill-defined for-loop: a loop using variable \"" + v + "\" counts "
95+
+ forLoopdirection(isIncr) + " from a value ("+ initialCondition +"), but the terminal condition is "
96+
+ forLoopTerminalConditionRelationship(isIncr) + " (" + terminalCondition + ")."
97+
)
98+
}
99+
100+
from ForStmt forstmt, string message
101+
where illDefinedForStmt(forstmt, message)
102+
select forstmt, message
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
void Signed()
2+
{
3+
signed char i;
4+
5+
for (i = 0; i < 100; i--) //BUG
6+
{
7+
}
8+
9+
for (i = 0; i < 100; i++)
10+
{
11+
}
12+
13+
for (i = 100; i >= 0; i++) //BUG
14+
{
15+
}
16+
17+
for (i = 100; i >= 0; i--)
18+
{
19+
}
20+
21+
}
22+
23+
void Unsigned()
24+
{
25+
unsigned long i;
26+
27+
for (i = 0; i < 100; i--) //BUG
28+
{
29+
}
30+
31+
for (i = 0; i < 100; i++)
32+
{
33+
}
34+
35+
for (i = 100; i >= 0; i++) //BUG
36+
{
37+
}
38+
39+
for (i = 100; i >= 0; i--)
40+
{
41+
}
42+
}
43+
44+
void InitializationOutsideLoop()
45+
{
46+
signed char i = 0;
47+
48+
for (; i < 100; i--) //BUG
49+
{
50+
}
51+
52+
i = 0;
53+
for (; i < 100; i++)
54+
{
55+
}
56+
57+
i = 100;
58+
for (; i >= 0; i++) //BUG
59+
{
60+
}
61+
62+
i = 100;
63+
for (; i >= 0; i--)
64+
{
65+
}
66+
}
67+
68+
void NegativeTestCase()
69+
{
70+
int i;
71+
for (i = 0; (200 - i) < 100; i--)
72+
{
73+
// code ...
74+
}
75+
}
76+
77+
void NegativeTestCaseNested()
78+
{
79+
int k;
80+
int i;
81+
82+
for (k = 200; k < 300; k++)
83+
{
84+
for (i = 0; (k - i) < 100; i--)
85+
{
86+
// code ...
87+
}
88+
}
89+
}
Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
void Signed()
2+
{
3+
signed char i;
4+
5+
for (i = 0; i < 100; i--) //BUG
6+
{
7+
}
8+
9+
for (i = 0; i < 100; i++)
10+
{
11+
}
12+
13+
for (i = 100; i >= 0; i++) //BUG
14+
{
15+
}
16+
17+
for (i = 100; i >= 0; i--)
18+
{
19+
}
20+
21+
}
22+
23+
void Unsigned()
24+
{
25+
unsigned long i;
26+
27+
for (i = 0; i < 100; i--) //BUG
28+
{
29+
}
30+
31+
for (i = 0; i < 100; i++)
32+
{
33+
}
34+
35+
for (i = 100; i >= 0; i++) //BUG
36+
{
37+
}
38+
39+
for (i = 100; i >= 0; i--)
40+
{
41+
}
42+
}
43+
44+
void DeclarationInLoop()
45+
{
46+
for (signed char i = 0; i < 100; i--) //BUG
47+
{
48+
}
49+
50+
for (signed char i = 0; i < 100; i++)
51+
{
52+
}
53+
54+
for (unsigned char i = 100; i >= 0; i++) //BUG
55+
{
56+
}
57+
58+
for (unsigned char i = 100; i >= 0; i--)
59+
{
60+
}
61+
}
62+
63+
void SignedWithVariables()
64+
{
65+
signed char i;
66+
signed char min = 0;
67+
signed char max = 100;
68+
69+
for (i = min; i < max; i--) //BUG
70+
{
71+
}
72+
73+
for (i = min; i < max; i++)
74+
{
75+
}
76+
77+
for (i = max; i >= min; i++) //BUG
78+
{
79+
}
80+
81+
for (i = max; i >= min; i--)
82+
{
83+
}
84+
85+
}
86+
87+
void InitializationOutsideLoop()
88+
{
89+
signed char i = 0;
90+
91+
for (; i < 100; i--) //BUG
92+
{
93+
}
94+
95+
i = 0;
96+
for (; i < 100; i++)
97+
{
98+
}
99+
100+
i = 100;
101+
for (; i >= 0; i++) //BUG
102+
{
103+
}
104+
105+
i = 100;
106+
for (; i >= 0; i--)
107+
{
108+
}
109+
}
110+
111+
void NegativeTestCase()
112+
{
113+
for (int i = 0; (200 - i) < 100; i--)
114+
{
115+
// code ...
116+
}
117+
}
118+
119+
void NegativeTestCaseNested()
120+
{
121+
for (int k = 200; k < 300; k++)
122+
{
123+
for (int i = 0; (k - i) < 100; i--)
124+
{
125+
// code ...
126+
}
127+
}
128+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
| illDefinedForLoop.c:5:5:7:5 | for(...;...;...) ... | Ill-defined for-loop: a loop using variable "i" counts downward from a value (0), but the terminal condition is higher (100). |
2+
| illDefinedForLoop.c:13:5:15:5 | for(...;...;...) ... | Ill-defined for-loop: a loop using variable "i" counts upward from a value (100), but the terminal condition is lower (0). |
3+
| illDefinedForLoop.c:27:5:29:5 | for(...;...;...) ... | Ill-defined for-loop: a loop using variable "i" counts downward from a value (0), but the terminal condition is higher (100). |
4+
| illDefinedForLoop.c:35:5:37:5 | for(...;...;...) ... | Ill-defined for-loop: a loop using variable "i" counts upward from a value (100), but the terminal condition is lower (0). |
5+
| illDefinedForLoop.c:48:5:50:5 | for(...;...;...) ... | Ill-defined for-loop: a loop using variable "i" counts downward from a value (0), but the terminal condition is higher (100). |
6+
| illDefinedForLoop.c:58:5:60:5 | for(...;...;...) ... | Ill-defined for-loop: a loop using variable "i" counts upward from a value (100), but the terminal condition is lower (0). |
7+
| illDefinedForLoop.cpp:5:5:7:5 | for(...;...;...) ... | Ill-defined for-loop: a loop using variable "i" counts downward from a value (0), but the terminal condition is higher (100). |
8+
| illDefinedForLoop.cpp:13:5:15:5 | for(...;...;...) ... | Ill-defined for-loop: a loop using variable "i" counts upward from a value (100), but the terminal condition is lower (0). |
9+
| illDefinedForLoop.cpp:27:5:29:5 | for(...;...;...) ... | Ill-defined for-loop: a loop using variable "i" counts downward from a value (0), but the terminal condition is higher (100). |
10+
| illDefinedForLoop.cpp:35:5:37:5 | for(...;...;...) ... | Ill-defined for-loop: a loop using variable "i" counts upward from a value (100), but the terminal condition is lower (0). |
11+
| illDefinedForLoop.cpp:46:5:48:5 | for(...;...;...) ... | Ill-defined for-loop: a loop using variable "i" counts downward from a value (0), but the terminal condition is higher (100). |
12+
| illDefinedForLoop.cpp:54:5:56:5 | for(...;...;...) ... | Ill-defined for-loop: a loop using variable "i" counts upward from a value (100), but the terminal condition is lower (0). |
13+
| illDefinedForLoop.cpp:69:5:71:5 | for(...;...;...) ... | Ill-defined for-loop: a loop using variable "i" counts downward from a value (min), but the terminal condition is higher (max). |
14+
| illDefinedForLoop.cpp:77:5:79:5 | for(...;...;...) ... | Ill-defined for-loop: a loop using variable "i" counts upward from a value (max), but the terminal condition is lower (min). |
15+
| illDefinedForLoop.cpp:91:5:93:5 | for(...;...;...) ... | Ill-defined for-loop: a loop using variable "i" counts downward from a value (0), but the terminal condition is higher (100). |
16+
| illDefinedForLoop.cpp:101:5:103:5 | for(...;...;...) ... | Ill-defined for-loop: a loop using variable "i" counts upward from a value (100), but the terminal condition is lower (0). |
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Likely Bugs/Likely Typos/illDefinedForLoop.ql

0 commit comments

Comments
 (0)