forked from danmar/cppcheck
-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathtestdivision.cpp
203 lines (176 loc) · 6.19 KB
/
testdivision.cpp
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
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
/*
* Cppcheck - A tool for static C/C++ code analysis
* Copyright (C) 2007-2012 Daniel Marjamäki and Cppcheck team.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
// Check for dangerous division..
// such as "svar / uvar". Treating "svar" as unsigned data is not good
#include "tokenize.h"
#include "checkother.h"
#include "testsuite.h"
#include <sstream>
extern std::ostringstream errout;
class TestDivision : public TestFixture {
public:
TestDivision() : TestFixture("TestDivision")
{ }
private:
void check(const char code[], bool inconclusive = false) {
// Clear the error buffer..
errout.str("");
Settings settings;
settings.addEnabled("style");
settings.inconclusive = inconclusive;
// Tokenize..
Tokenizer tokenizer(&settings, this);
std::istringstream istr(code);
tokenizer.tokenize(istr, "test.cpp");
// Check for unsigned divisions..
CheckOther checkOther(&tokenizer, &settings, this);
checkOther.checkUnsignedDivision();
}
void run() {
TEST_CASE(division1);
TEST_CASE(division2);
TEST_CASE(division4);
TEST_CASE(division5);
TEST_CASE(division6);
TEST_CASE(division7);
TEST_CASE(division8);
TEST_CASE(division9);
TEST_CASE(division10);
}
void division1() {
check("void f() {\n"
" int ivar = -2;\n"
" unsigned int uvar = 2;\n"
" return ivar / uvar;\n"
"}", false);
ASSERT_EQUALS("", errout.str());
check("void f()\n"
"{\n"
" int ivar = -2;\n"
" unsigned int uvar = 2;\n"
" return ivar / uvar;\n"
"}", true);
ASSERT_EQUALS("[test.cpp:5]: (warning, inconclusive) Division with signed and unsigned operators. The result might be wrong.\n", errout.str());
}
void division2() {
check("void f()\n"
"{\n"
" int ivar = -2;\n"
" unsigned int uvar = 2;\n"
" return uvar / ivar;\n"
"}", true);
ASSERT_EQUALS("[test.cpp:5]: (warning, inconclusive) Division with signed and unsigned operators. The result might be wrong.\n", errout.str());
}
void division4() {
check("void f1()\n"
"{\n"
" int i1;\n"
"}\n"
"\n"
"void f2(unsigned int i1)\n"
"{\n"
" unsigned int i2;\n"
" result = i2 / i1;"
"}", true);
ASSERT_EQUALS("", errout.str());
check("void f1()\n"
"{\n"
" unsigned int num = 0;\n"
"}\n"
"\n"
"void f2(int X)\n"
"{\n"
" X = X / z;"
"}", true);
ASSERT_EQUALS("", errout.str());
}
void division5() {
check("#define USER_HASH (16)\n"
"void foo()\n"
"{\n"
" unsigned int val = 32;\n"
" val = val / USER_HASH;"
"}", true);
ASSERT_EQUALS("", errout.str());
}
void division6() {
check("void foo()\n"
"{\n"
" unsigned int val = 32;\n"
" int i = val / -2; }\n"
);
ASSERT_EQUALS("[test.cpp:4]: (error) Unsigned division. The result will be wrong.\n", errout.str());
}
void division7() {
check("void foo()\n"
"{\n"
" unsigned int val = 32;\n"
" int i = -96 / val; }\n");
ASSERT_EQUALS("[test.cpp:4]: (error) Unsigned division. The result will be wrong.\n", errout.str());
}
void division8() {
check("void foo(int b)\n"
"{\n"
" if (b > 0)\n"
" {\n"
" unsigned int a;\n"
" unsigned int c = a / b;\n"
" }\n"
"}", true);
ASSERT_EQUALS("", errout.str());
check("void foo(int b)\n"
"{\n"
" if (b < 0)\n"
" {\n"
" unsigned int a;\n"
" unsigned int c = a / b;\n"
" }\n"
"}", true);
TODO_ASSERT_EQUALS("[test.cpp:6]: (warning) Division with signed and unsigned operators. The result might be wrong.\n",
"", errout.str());
check("void a(int i) { }\n"
"int foo( unsigned int sz )\n"
"{\n"
" register unsigned int i=1;\n"
" return i/sz;\n"
"}", true);
ASSERT_EQUALS("", errout.str());
}
void division9() {
check("void f()\n"
"{\n"
" int ivar = -2;\n"
" unsigned long uvar = 2;\n"
" return ivar / uvar;\n"
"}", true);
ASSERT_EQUALS("[test.cpp:5]: (warning, inconclusive) Division with signed and unsigned operators. The result might be wrong.\n", errout.str());
check("void f()\n"
"{\n"
" int ivar = -2;\n"
" unsigned long long uvar = 2;\n"
" return ivar / uvar;\n"
"}", true);
ASSERT_EQUALS("[test.cpp:5]: (warning, inconclusive) Division with signed and unsigned operators. The result might be wrong.\n", errout.str());
}
void division10() {
// Ticket: #2932 - don't segfault
check("i / i", true);
ASSERT_EQUALS("", errout.str());
}
};
REGISTER_TEST(TestDivision)