* Fix #9097 (Crash on thousands of "else ifs"s in gcc-avr package) * increase recursion count maximum to 512 because cppcheck was hitting the 256 limit * 512 was too much for windows
This commit is contained in:
parent
4a70208e0e
commit
74e3114a64
|
@ -159,6 +159,8 @@ void CheckLeakAutoVar::check()
|
|||
if (scope->hasInlineOrLambdaFunction())
|
||||
continue;
|
||||
|
||||
recursiveCount = 0;
|
||||
|
||||
// Empty variable info
|
||||
VarInfo varInfo;
|
||||
|
||||
|
@ -236,6 +238,11 @@ void CheckLeakAutoVar::checkScope(const Token * const startToken,
|
|||
VarInfo *varInfo,
|
||||
std::set<unsigned int> notzero)
|
||||
{
|
||||
// The C++ standard suggests a minimum of 256 nested control statements
|
||||
// but MSVC has a limit of 100. Cppcheck is hitting 256 when checking itself.
|
||||
if (++recursiveCount > 384)
|
||||
throw InternalError(startToken, "Internal limit: CheckLeakAutoVar::checkScope() Maximum recursive count of 384 reached.", InternalError::LIMIT);
|
||||
|
||||
std::map<unsigned int, VarInfo::AllocInfo> &alloctype = varInfo->alloctype;
|
||||
std::map<unsigned int, std::string> &possibleUsage = varInfo->possibleUsage;
|
||||
const std::set<unsigned int> conditionalAlloc(varInfo->conditionalAlloc);
|
||||
|
|
|
@ -95,12 +95,12 @@ public:
|
|||
class CPPCHECKLIB CheckLeakAutoVar : public Check {
|
||||
public:
|
||||
/** This constructor is used when registering the CheckLeakAutoVar */
|
||||
CheckLeakAutoVar() : Check(myName()) {
|
||||
CheckLeakAutoVar() : Check(myName()), recursiveCount(0) {
|
||||
}
|
||||
|
||||
/** This constructor is used when running checks. */
|
||||
CheckLeakAutoVar(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger)
|
||||
: Check(myName(), tokenizer, settings, errorLogger) {
|
||||
: Check(myName(), tokenizer, settings, errorLogger), recursiveCount(0) {
|
||||
}
|
||||
|
||||
void runChecks(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger) OVERRIDE {
|
||||
|
@ -163,6 +163,8 @@ private:
|
|||
std::string classInfo() const OVERRIDE {
|
||||
return "Detect when a auto variable is allocated but not deallocated or deallocated twice.\n";
|
||||
}
|
||||
|
||||
unsigned int recursiveCount;
|
||||
};
|
||||
/// @}
|
||||
//---------------------------------------------------------------------------
|
||||
|
|
|
@ -49,6 +49,9 @@ InternalError::InternalError(const Token *tok, const std::string &errorMsg, Type
|
|||
case INTERNAL:
|
||||
id = "cppcheckError";
|
||||
break;
|
||||
case LIMIT:
|
||||
id = "cppcheckLimit";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -54,7 +54,7 @@ namespace tinyxml2 {
|
|||
|
||||
/** @brief Simple container to be thrown when internal error is detected. */
|
||||
struct InternalError {
|
||||
enum Type {AST, SYNTAX, UNKNOWN_MACRO, INTERNAL};
|
||||
enum Type {AST, SYNTAX, UNKNOWN_MACRO, INTERNAL, LIMIT};
|
||||
InternalError(const Token *tok, const std::string &errorMsg, Type type = INTERNAL);
|
||||
const Token *token;
|
||||
std::string errorMessage;
|
||||
|
|
|
@ -23,6 +23,8 @@
|
|||
#include "testsuite.h"
|
||||
#include "tokenize.h"
|
||||
|
||||
#include <simplecpp.h>
|
||||
#include <vector>
|
||||
|
||||
class TestLeakAutoVar : public TestFixture {
|
||||
public:
|
||||
|
@ -163,6 +165,8 @@ private:
|
|||
TEST_CASE(inlineFunction); // #3989
|
||||
|
||||
TEST_CASE(smartPtrInContainer); // #8262
|
||||
|
||||
TEST_CASE(recursiveCountLimit); // #5872 #6157 #9097
|
||||
}
|
||||
|
||||
void check(const char code[], bool cpp = false) {
|
||||
|
@ -181,6 +185,32 @@ private:
|
|||
c.runChecks(&tokenizer, &settings, this);
|
||||
}
|
||||
|
||||
void checkP(const char code[], bool cpp = false) {
|
||||
// Clear the error buffer..
|
||||
errout.str("");
|
||||
|
||||
// Raw tokens..
|
||||
std::vector<std::string> files(1, cpp?"test.cpp":"test.c");
|
||||
std::istringstream istr(code);
|
||||
const simplecpp::TokenList tokens1(istr, files, files[0]);
|
||||
|
||||
// Preprocess..
|
||||
simplecpp::TokenList tokens2(files);
|
||||
std::map<std::string, simplecpp::TokenList*> filedata;
|
||||
simplecpp::preprocess(tokens2, tokens1, files, filedata, simplecpp::DUI());
|
||||
|
||||
// Tokenizer..
|
||||
Tokenizer tokenizer(&settings, this);
|
||||
tokenizer.createTokens(&tokens2);
|
||||
tokenizer.simplifyTokens1("");
|
||||
|
||||
// Check for leaks..
|
||||
CheckLeakAutoVar c;
|
||||
settings.checkLibrary = true;
|
||||
settings.addEnabled("information");
|
||||
c.runChecks(&tokenizer, &settings, this);
|
||||
}
|
||||
|
||||
void assign1() {
|
||||
check("void f() {\n"
|
||||
" char *p = malloc(10);\n"
|
||||
|
@ -1776,6 +1806,17 @@ private:
|
|||
ASSERT_EQUALS("", errout.str());
|
||||
}
|
||||
|
||||
void recursiveCountLimit() { // #5872 #6157 #9097
|
||||
ASSERT_THROW(checkP("#define ONE else if (0) { }\n"
|
||||
"#define TEN ONE ONE ONE ONE ONE ONE ONE ONE ONE ONE\n"
|
||||
"#define HUN TEN TEN TEN TEN TEN TEN TEN TEN TEN TEN\n"
|
||||
"#define THOU HUN HUN HUN HUN HUN HUN HUN HUN HUN HUN\n"
|
||||
"void foo() {\n"
|
||||
" if (0) { }\n"
|
||||
" THOU\n"
|
||||
"}"), InternalError);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
REGISTER_TEST(TestLeakAutoVar)
|
||||
|
|
Loading…
Reference in New Issue