forked from cppcheck-opensource/cppcheck
-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathcheckother.h
More file actions
406 lines (337 loc) · 18.3 KB
/
checkother.h
File metadata and controls
406 lines (337 loc) · 18.3 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
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
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
/*
* Cppcheck - A tool for static C/C++ code analysis
* Copyright (C) 2007-2014 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/>.
*/
//---------------------------------------------------------------------------
#ifndef checkotherH
#define checkotherH
//---------------------------------------------------------------------------
#include "config.h"
#include "check.h"
class Function;
class Variable;
/** Is expressions same? */
bool isSameExpression(const Token *tok1, const Token *tok2, const std::set<std::string> &constFunctions);
/** Is expression of floating point type? */
bool astIsFloat(const Token *tok, bool unknown);
/// @addtogroup Checks
/// @{
/** @brief Various small checks */
class CPPCHECKLIB CheckOther : public Check {
public:
/** @brief This constructor is used when registering the CheckClass */
CheckOther() : Check(myName()) {
}
/** @brief This constructor is used when running checks. */
CheckOther(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger)
: Check(myName(), tokenizer, settings, errorLogger) {
}
/** @brief Run checks against the normal token list */
void runChecks(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger) {
CheckOther checkOther(tokenizer, settings, errorLogger);
// Checks
checkOther.warningOldStylePointerCast();
checkOther.invalidPointerCast();
checkOther.checkCharVariable();
checkOther.checkRedundantAssignment();
checkOther.checkRedundantAssignmentInSwitch();
checkOther.checkSuspiciousCaseInSwitch();
checkOther.checkDuplicateBranch();
checkOther.checkDuplicateExpression();
checkOther.checkUnreachableCode();
checkOther.checkSuspiciousSemicolon();
checkOther.checkVariableScope();
checkOther.checkSignOfUnsignedVariable(); // don't ignore casts (#3574)
checkOther.checkIncompleteArrayFill();
checkOther.checkVarFuncNullUB();
checkOther.checkNanInArithmeticExpression();
checkOther.checkCommaSeparatedReturn();
}
/** @brief Run checks against the simplified token list */
void runSimplifiedChecks(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger) {
CheckOther checkOther(tokenizer, settings, errorLogger);
// Checks
checkOther.clarifyCalculation();
checkOther.clarifyStatement();
checkOther.checkConstantFunctionParameter();
checkOther.checkIncompleteStatement();
checkOther.checkCastIntToCharAndBack();
checkOther.invalidFunctionUsage();
checkOther.checkZeroDivision();
checkOther.checkMathFunctions();
checkOther.redundantGetAndSetUserId();
checkOther.checkMisusedScopedObject();
checkOther.checkMemsetZeroBytes();
checkOther.checkMemsetInvalid2ndParam();
checkOther.checkSwitchCaseFallThrough();
checkOther.checkPipeParameterSize();
checkOther.checkInvalidFree();
checkOther.checkDoubleFree();
checkOther.checkRedundantCopy();
checkOther.checkNegativeBitwiseShift();
checkOther.checkSuspiciousEqualityComparison();
checkOther.checkComparisonFunctionIsAlwaysTrueOrFalse();
}
/** @brief Clarify calculation for ".. a * b ? .." */
void clarifyCalculation();
/** @brief Suspicious statement like '*A++;' */
void clarifyStatement();
/** @brief Are there C-style pointer casts in a c++ file? */
void warningOldStylePointerCast();
/** @brief Check for pointer casts to a type with an incompatible binary data representation */
void invalidPointerCast();
/**
* @brief Invalid function usage (invalid input value / overlapping data)
*
* %Check that given function parameters are valid according to the standard
* - wrong radix given for strtol/strtoul
* - overlapping data when using sprintf/snprintf
* - wrong input value according to library
*/
void invalidFunctionUsage();
/** @brief %Check scope of variables */
void checkVariableScope();
static bool checkInnerScope(const Token *tok, const Variable* var, bool& used);
/** @brief %Check for comma separated statements in return */
void checkCommaSeparatedReturn();
/** @brief %Check for constant function parameter */
void checkConstantFunctionParameter();
/** @brief Using char variable as array index / as operand in bit operation */
void checkCharVariable();
/** @brief Incomplete statement. A statement that only contains a constant or variable */
void checkIncompleteStatement();
/** @brief %Check zero division*/
void checkZeroDivision();
/** @brief %Check zero division / useless condition */
void checkZeroDivisionOrUselessCondition();
/** @brief Check for NaN (not-a-number) in an arithmetic expression */
void checkNanInArithmeticExpression();
/** @brief %Check for parameters given to math function that do not make sense*/
void checkMathFunctions();
/** @brief % Check for seteuid(geteuid()) or setuid(getuid())*/
void redundantGetAndSetUserId();
/** @brief copying to memory or assigning to a variable twice */
void checkRedundantAssignment();
/** @brief %Check for assigning to the same variable twice in a switch statement*/
void checkRedundantAssignmentInSwitch();
/** @brief %Check for code like 'case A||B:'*/
void checkSuspiciousCaseInSwitch();
/** @brief %Check for code like 'case A||B:'*/
void checkSuspiciousEqualityComparison();
/** @brief %Check for switch case fall through without comment */
void checkSwitchCaseFallThrough();
/** @brief %Check for objects that are destroyed immediately */
void checkMisusedScopedObject();
/** @brief %Check for filling zero bytes with memset() */
void checkMemsetZeroBytes();
/** @brief %Check for invalid 2nd parameter of memset() */
void checkMemsetInvalid2ndParam();
/** @brief %Check for suspicious code where multiple if have the same expression (e.g "if (a) { } else if (a) { }") */
void checkDuplicateIf();
/** @brief %Check for suspicious code where if and else branch are the same (e.g "if (a) b = true; else b = true;") */
void checkDuplicateBranch();
/** @brief %Check for suspicious code with the same expression on both sides of operator (e.g "if (a && a)") */
void checkDuplicateExpression();
/** @brief %Check for code that gets never executed, such as duplicate break statements */
void checkUnreachableCode();
/** @brief %Check for testing sign of unsigned variable */
void checkSignOfUnsignedVariable();
/** @brief %Check for suspicious use of semicolon */
void checkSuspiciousSemicolon();
/** @brief %Check for free() operations on invalid memory locations */
void checkInvalidFree();
void invalidFreeError(const Token *tok, bool inconclusive);
/** @brief %Check for double free or double close operations */
void checkDoubleFree();
void doubleFreeError(const Token *tok, const std::string &varname);
/** @brief %Check for code creating redundant copies */
void checkRedundantCopy();
/** @brief %Check for bitwise shift with negative right operand */
void checkNegativeBitwiseShift();
/** @brief %Check for buffers that are filled incompletely with memset and similar functions */
void checkIncompleteArrayFill();
/** @brief %Check that variadic function calls don't use NULL. If NULL is \#defined as 0 and the function expects a pointer, the behaviour is undefined. */
void checkVarFuncNullUB();
/** @brief %Check that calling the POSIX pipe() system call is called with an integer array of size two. */
void checkPipeParameterSize();
/** @brief %Check to avoid casting a return value to unsigned char and then back to integer type. */
void checkCastIntToCharAndBack();
/** @brief %Check for using of comparison functions evaluating always to true or false. */
void checkComparisonFunctionIsAlwaysTrueOrFalse();
private:
// Error messages..
void checkComparisonFunctionIsAlwaysTrueOrFalseError(const Token* tok, const std::string &strFunctionName, const std::string &varName, const bool result);
void checkCastIntToCharAndBackError(const Token *tok, const std::string &strFunctionName);
void checkPipeParameterSizeError(const Token *tok, const std::string &strVarName, const std::string &strDim);
void clarifyCalculationError(const Token *tok, const std::string &op);
void clarifyStatementError(const Token* tok);
void redundantGetAndSetUserIdError(const Token *tok);
void cstyleCastError(const Token *tok);
void invalidPointerCastError(const Token* tok, const std::string& from, const std::string& to, bool inconclusive);
void invalidFunctionArgError(const Token *tok, const std::string &functionName, int argnr, const std::string &validstr);
void invalidFunctionArgBoolError(const Token *tok, const std::string &functionName, int argnr);
void passedByValueError(const Token *tok, const std::string &parname);
void constStatementError(const Token *tok, const std::string &type);
void charArrayIndexError(const Token *tok);
void charBitOpError(const Token *tok);
void variableScopeError(const Token *tok, const std::string &varname);
void zerodivError(const Token *tok, bool inconclusive);
void zerodivcondError(const Token *tokcond, const Token *tokdiv, bool inconclusive);
void nanInArithmeticExpressionError(const Token *tok);
void mathfunctionCallWarning(const Token *tok, const unsigned int numParam = 1);
void mathfunctionCallWarning(const Token *tok, const std::string& oldexp, const std::string& newexp);
void redundantAssignmentError(const Token *tok1, const Token* tok2, const std::string& var, bool inconclusive);
void redundantAssignmentInSwitchError(const Token *tok1, const Token *tok2, const std::string &var);
void redundantCopyError(const Token *tok1, const Token* tok2, const std::string& var);
void redundantCopyInSwitchError(const Token *tok1, const Token* tok2, const std::string &var);
void redundantBitwiseOperationInSwitchError(const Token *tok, const std::string &varname);
void switchCaseFallThrough(const Token *tok);
void suspiciousCaseInSwitchError(const Token* tok, const std::string& operatorString);
void suspiciousEqualityComparisonError(const Token* tok);
void selfAssignmentError(const Token *tok, const std::string &varname);
void misusedScopeObjectError(const Token *tok, const std::string &varname);
void memsetZeroBytesError(const Token *tok, const std::string &varname);
void memsetFloatError(const Token *tok, const std::string &var_value);
void memsetValueOutOfRangeError(const Token *tok, const std::string &value);
void duplicateIfError(const Token *tok1, const Token *tok2);
void duplicateBranchError(const Token *tok1, const Token *tok2);
void duplicateExpressionError(const Token *tok1, const Token *tok2, const std::string &op);
void alwaysTrueFalseStringCompareError(const Token *tok, const std::string& str1, const std::string& str2);
void alwaysTrueStringVariableCompareError(const Token *tok, const std::string& str1, const std::string& str2);
void duplicateBreakError(const Token *tok, bool inconclusive);
void unreachableCodeError(const Token* tok, bool inconclusive);
void unsignedLessThanZeroError(const Token *tok, const std::string &varname, bool inconclusive);
void pointerLessThanZeroError(const Token *tok, bool inconclusive);
void unsignedPositiveError(const Token *tok, const std::string &varname, bool inconclusive);
void pointerPositiveError(const Token *tok, bool inconclusive);
void SuspiciousSemicolonError(const Token *tok);
void doubleCloseDirError(const Token *tok, const std::string &varname);
void negativeBitwiseShiftError(const Token *tok);
void redundantCopyError(const Token *tok, const std::string &varname);
void incompleteArrayFillError(const Token* tok, const std::string& buffer, const std::string& function, bool boolean);
void varFuncNullUBError(const Token *tok);
void commaSeparatedReturnError(const Token *tok);
void getErrorMessages(ErrorLogger *errorLogger, const Settings *settings) const {
CheckOther c(0, settings, errorLogger);
// error
c.invalidFunctionArgError(0, "func_name", 1, "1-4");
c.invalidFunctionArgBoolError(0, "func_name", 1);
c.zerodivError(0, false);
c.zerodivcondError(0,0,false);
c.misusedScopeObjectError(NULL, "varname");
c.doubleFreeError(0, "varname");
c.invalidPointerCastError(0, "float", "double", false);
c.negativeBitwiseShiftError(0);
c.checkPipeParameterSizeError(0, "varname", "dimension");
//performance
c.redundantCopyError(0, "varname");
c.redundantCopyError(0, 0, "var");
c.redundantAssignmentError(0, 0, "var", false);
// style/warning
c.checkComparisonFunctionIsAlwaysTrueOrFalseError(0,"isless","varName",false);
c.checkCastIntToCharAndBackError(0,"func_name");
c.cstyleCastError(0);
c.passedByValueError(0, "parametername");
c.constStatementError(0, "type");
c.charArrayIndexError(0);
c.charBitOpError(0);
c.variableScopeError(0, "varname");
c.redundantAssignmentInSwitchError(0, 0, "var");
c.redundantCopyInSwitchError(0, 0, "var");
c.switchCaseFallThrough(0);
c.suspiciousCaseInSwitchError(0, "||");
c.suspiciousEqualityComparisonError(0);
c.selfAssignmentError(0, "varname");
c.mathfunctionCallWarning(0);
c.mathfunctionCallWarning(0, "1 - erf(x)", "erfc(x)");
c.memsetZeroBytesError(0, "varname");
c.memsetFloatError(0, "varname");
c.memsetValueOutOfRangeError(0, "varname");
c.clarifyCalculationError(0, "+");
c.clarifyStatementError(0);
c.duplicateBranchError(0, 0);
c.duplicateExpressionError(0, 0, "&&");
c.duplicateBreakError(0, false);
c.unreachableCodeError(0, false);
c.unsignedLessThanZeroError(0, "varname", false);
c.unsignedPositiveError(0, "varname", false);
c.pointerLessThanZeroError(0, false);
c.pointerPositiveError(0, false);
c.SuspiciousSemicolonError(0);
c.incompleteArrayFillError(0, "buffer", "memset", false);
c.varFuncNullUBError(0);
c.nanInArithmeticExpressionError(0);
c.commaSeparatedReturnError(0);
}
static std::string myName() {
return "Other";
}
std::string classInfo() const {
return "Other checks\n"
// error
"* Assigning bool value to pointer (converting bool value to address)\n"
"* division with zero\n"
"* scoped object destroyed immediately after construction\n"
"* assignment in an assert statement\n"
"* free() or delete of an invalid memory location\n"
"* double free() or double closedir()\n"
"* bitwise operation with negative right operand\n"
"* provide wrong dimensioned array to pipe() system command (--std=posix)\n"
"* cast the return values of getc(),fgetc() and getchar() to character and compare it to EOF\n"
"* invalid input values for functions\n"
// warning
"* either division by zero or useless condition\n"
"* memset() with a value out of range as the 2nd parameter\n"
// performance
"* redundant data copying for const variable\n"
"* subsequent assignment or copying to a variable or buffer\n"
// portability
"* memset() with a float as the 2nd parameter\n"
// style
"* C-style pointer cast in cpp file\n"
"* casting between incompatible pointer types\n"
"* redundant if\n"
"* passing parameter by value\n"
"* [[IncompleteStatement|Incomplete statement]]\n"
"* [[charvar|check how signed char variables are used]]\n"
"* variable scope can be limited\n"
"* unusual pointer arithmetic. For example: \"abc\" + 'd'\n"
"* redundant assignment in a switch statement\n"
"* redundant pre/post operation in a switch statement\n"
"* redundant bitwise operation in a switch statement\n"
"* redundant strcpy in a switch statement\n"
"* assignment of a variable to itself\n"
"* Suspicious case labels in switch()\n"
"* Suspicious equality comparisons\n"
"* Comparison of values leading always to true or false\n"
"* Clarify calculation with parentheses\n"
"* suspicious comparison of '\\0' with a char* variable\n"
"* duplicate break statement\n"
"* unreachable code\n"
"* testing if unsigned variable is negative\n"
"* testing is unsigned variable is positive\n"
"* Suspicious use of ; at the end of 'if/for/while' statement.\n"
"* Array filled incompletely using memset/memcpy/memmove.\n"
"* redundant get and set function of user id (--std=posix).\n"
"* Passing NULL pointer to function with variable number of arguments leads to UB on some platforms.\n"
"* NaN (not a number) value used in arithmetic expression.\n"
"* comma in return statement (the comma can easily be misread as a semicolon).\n"
"* prefer erfc, expm1 or log1p to avoid loss of precision.\n";
}
};
/// @}
//---------------------------------------------------------------------------
#endif // checkotherH