Initial fix for ticket #283 (segmentation fault when checking xterm sources)
http://apps.sourceforge.net/trac/cppcheck/ticket/283 It should print out error message now instead of crashing. Cleanup is needed.
This commit is contained in:
parent
917a48cd65
commit
dd8b738f7f
|
@ -380,7 +380,11 @@ void CppCheck::checkFile(const std::string &code, const char FileName[])
|
||||||
// Tokenize the file
|
// Tokenize the file
|
||||||
{
|
{
|
||||||
std::istringstream istr(code);
|
std::istringstream istr(code);
|
||||||
_tokenizer.tokenize(istr, FileName);
|
if (!_tokenizer.tokenize(istr, FileName))
|
||||||
|
{
|
||||||
|
// File had syntax errors, abort
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set variable id
|
// Set variable id
|
||||||
|
|
|
@ -153,7 +153,7 @@ void Tokenizer::InsertTokens(Token *dest, Token *src, unsigned int n)
|
||||||
// Tokenize - tokenizes a given file.
|
// Tokenize - tokenizes a given file.
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
void Tokenizer::tokenize(std::istream &code, const char FileName[])
|
bool Tokenizer::tokenize(std::istream &code, const char FileName[])
|
||||||
{
|
{
|
||||||
// The "_files" vector remembers what files have been tokenized..
|
// The "_files" vector remembers what files have been tokenized..
|
||||||
_files.push_back(FileLister::simplifyPath(FileName));
|
_files.push_back(FileLister::simplifyPath(FileName));
|
||||||
|
@ -336,6 +336,12 @@ void Tokenizer::tokenize(std::istream &code, const char FileName[])
|
||||||
}
|
}
|
||||||
addtoken(CurrentToken.c_str(), lineno, FileIndex);
|
addtoken(CurrentToken.c_str(), lineno, FileIndex);
|
||||||
|
|
||||||
|
if (!createLinks())
|
||||||
|
{
|
||||||
|
// Source has syntax errors, can't proceed
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// Combine "- %num%" ..
|
// Combine "- %num%" ..
|
||||||
for (Token *tok = _tokens; tok; tok = tok->next())
|
for (Token *tok = _tokens; tok; tok = tok->next())
|
||||||
{
|
{
|
||||||
|
@ -464,6 +470,7 @@ void Tokenizer::tokenize(std::istream &code, const char FileName[])
|
||||||
|
|
||||||
// Handle templates..
|
// Handle templates..
|
||||||
simplifyTemplates();
|
simplifyTemplates();
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
@ -945,6 +952,7 @@ bool Tokenizer::createLinks()
|
||||||
if (links.size() == 0)
|
if (links.size() == 0)
|
||||||
{
|
{
|
||||||
// Error, { and } don't match.
|
// Error, { and } don't match.
|
||||||
|
syntaxError(token, '{');
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -961,6 +969,7 @@ bool Tokenizer::createLinks()
|
||||||
if (links2.size() == 0)
|
if (links2.size() == 0)
|
||||||
{
|
{
|
||||||
// Error, ( and ) don't match.
|
// Error, ( and ) don't match.
|
||||||
|
syntaxError(token, '(');
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -970,9 +979,17 @@ bool Tokenizer::createLinks()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (links.size() > 0 || links2.size() > 0)
|
if (links.size() > 0)
|
||||||
{
|
{
|
||||||
// Error, { and } don't match.
|
// Error, { and } don't match.
|
||||||
|
syntaxError(_tokens, '{');
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (links2.size() > 0)
|
||||||
|
{
|
||||||
|
// Error, { and } don't match.
|
||||||
|
syntaxError(_tokens, '(');
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2622,6 +2639,23 @@ const Token * Tokenizer::FindClassFunction(const Token *tok, const char classnam
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
// Error message for bad iterator usage..
|
||||||
|
|
||||||
|
void Tokenizer::syntaxError(const Token *tok, char c)
|
||||||
|
{
|
||||||
|
std::cout << "### Error: Invalid number of character " << c << std::endl;
|
||||||
|
/*
|
||||||
|
std::list<ErrorLogger::ErrorMessage::FileLocation> locationList;
|
||||||
|
ErrorLogger::ErrorMessage::FileLocation loc;
|
||||||
|
loc.line = tok->linenr();
|
||||||
|
loc.file = tok->fileIndex();
|
||||||
|
locationList.push_back(loc);
|
||||||
|
_errorLogger->reportErr(
|
||||||
|
ErrorLogger::ErrorMessage(locationList,
|
||||||
|
"error",
|
||||||
|
std::string("Invalid number of character (") + c + "). Can't process file. File is either invalid or unicode, which is currently not supported.",
|
||||||
|
"syntaxError"));
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -45,8 +45,9 @@ public:
|
||||||
* Tokenize code
|
* Tokenize code
|
||||||
* @param code input stream for code
|
* @param code input stream for code
|
||||||
* @param FileName The filename
|
* @param FileName The filename
|
||||||
|
* @return false if Source code contains syntax errors
|
||||||
*/
|
*/
|
||||||
void tokenize(std::istream &code, const char FileName[]);
|
bool tokenize(std::istream &code, const char FileName[]);
|
||||||
|
|
||||||
/** Set variable id */
|
/** Set variable id */
|
||||||
void setVarId();
|
void setVarId();
|
||||||
|
@ -208,6 +209,8 @@ private:
|
||||||
*/
|
*/
|
||||||
bool createLinks();
|
bool createLinks();
|
||||||
|
|
||||||
|
void syntaxError(const Token *tok, char c);
|
||||||
|
|
||||||
Token *_tokensBack;
|
Token *_tokensBack;
|
||||||
std::map<std::string, unsigned int> _typeSize;
|
std::map<std::string, unsigned int> _typeSize;
|
||||||
std::vector<std::string> _files;
|
std::vector<std::string> _files;
|
||||||
|
|
|
@ -74,7 +74,7 @@ private:
|
||||||
check("void func1(int **res)\n"
|
check("void func1(int **res)\n"
|
||||||
"{\n"
|
"{\n"
|
||||||
" int num=2;"
|
" int num=2;"
|
||||||
"res=#");
|
"res=#}");
|
||||||
ASSERT_EQUALS(std::string("[test.cpp:3]: (error) Wrong assignement of an auto-variable to an effective parameter of a function\n"), errout.str());
|
ASSERT_EQUALS(std::string("[test.cpp:3]: (error) Wrong assignement of an auto-variable to an effective parameter of a function\n"), errout.str());
|
||||||
}
|
}
|
||||||
void testautovararray()
|
void testautovararray()
|
||||||
|
@ -82,7 +82,7 @@ private:
|
||||||
check("void func1(int* arr[2])\n"
|
check("void func1(int* arr[2])\n"
|
||||||
"{\n"
|
"{\n"
|
||||||
" int num=2;"
|
" int num=2;"
|
||||||
"arr[0]=#");
|
"arr[0]=#}");
|
||||||
ASSERT_EQUALS(std::string("[test.cpp:3]: (error) Wrong assignement of an auto-variable to an effective parameter of a function\n"), errout.str());
|
ASSERT_EQUALS(std::string("[test.cpp:3]: (error) Wrong assignement of an auto-variable to an effective parameter of a function\n"), errout.str());
|
||||||
}
|
}
|
||||||
void testautovarreturn()
|
void testautovarreturn()
|
||||||
|
@ -90,7 +90,7 @@ private:
|
||||||
check("int* func1()\n"
|
check("int* func1()\n"
|
||||||
"{\n"
|
"{\n"
|
||||||
" int num=2;"
|
" int num=2;"
|
||||||
"return #");
|
"return #}");
|
||||||
ASSERT_EQUALS(std::string("[test.cpp:3]: (error) Return of the address of an auto-variable\n"), errout.str());
|
ASSERT_EQUALS(std::string("[test.cpp:3]: (error) Return of the address of an auto-variable\n"), errout.str());
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -112,7 +112,7 @@ private:
|
||||||
"void f2(unsigned int i1)\n"
|
"void f2(unsigned int i1)\n"
|
||||||
"{\n"
|
"{\n"
|
||||||
" unsigned int i2;\n"
|
" unsigned int i2;\n"
|
||||||
" result = i2 / i1;\n"
|
" result = i2 / i1;}\n"
|
||||||
);
|
);
|
||||||
ASSERT_EQUALS(std::string(""), errout.str());
|
ASSERT_EQUALS(std::string(""), errout.str());
|
||||||
}
|
}
|
||||||
|
@ -123,7 +123,7 @@ private:
|
||||||
"void foo()\n"
|
"void foo()\n"
|
||||||
"{\n"
|
"{\n"
|
||||||
" unsigned int val = 32;\n"
|
" unsigned int val = 32;\n"
|
||||||
" val = val / USER_HASH;\n"
|
" val = val / USER_HASH;}\n"
|
||||||
);
|
);
|
||||||
ASSERT_EQUALS(std::string(""), errout.str());
|
ASSERT_EQUALS(std::string(""), errout.str());
|
||||||
}
|
}
|
||||||
|
@ -133,7 +133,7 @@ private:
|
||||||
check("void foo()\n"
|
check("void foo()\n"
|
||||||
"{\n"
|
"{\n"
|
||||||
" unsigned int val = 32;\n"
|
" unsigned int val = 32;\n"
|
||||||
" int i = val / -2;\n"
|
" int i = val / -2; }\n"
|
||||||
);
|
);
|
||||||
ASSERT_EQUALS(std::string("[test.cpp:4]: (error) Unsigned division. The result will be wrong.\n"), errout.str());
|
ASSERT_EQUALS(std::string("[test.cpp:4]: (error) Unsigned division. The result will be wrong.\n"), errout.str());
|
||||||
}
|
}
|
||||||
|
@ -143,7 +143,7 @@ private:
|
||||||
check("void foo()\n"
|
check("void foo()\n"
|
||||||
"{\n"
|
"{\n"
|
||||||
" unsigned int val = 32;\n"
|
" unsigned int val = 32;\n"
|
||||||
" int i = -96 / val;\n"
|
" int i = -96 / val; }\n"
|
||||||
);
|
);
|
||||||
ASSERT_EQUALS(std::string("[test.cpp:4]: (error) Unsigned division. The result will be wrong.\n"), errout.str());
|
ASSERT_EQUALS(std::string("[test.cpp:4]: (error) Unsigned division. The result will be wrong.\n"), errout.str());
|
||||||
}
|
}
|
||||||
|
|
|
@ -142,8 +142,7 @@ private:
|
||||||
"{\n"
|
"{\n"
|
||||||
"{ 346.1,114.1 }, { 347.1,111.1 }\n"
|
"{ 346.1,114.1 }, { 347.1,111.1 }\n"
|
||||||
"};\n"
|
"};\n"
|
||||||
"}\n"
|
"}\n");
|
||||||
"};\n");
|
|
||||||
|
|
||||||
ASSERT_EQUALS(std::string(""), errout.str());
|
ASSERT_EQUALS(std::string(""), errout.str());
|
||||||
}
|
}
|
||||||
|
|
|
@ -358,11 +358,14 @@ private:
|
||||||
|
|
||||||
void invalidcode()
|
void invalidcode()
|
||||||
{
|
{
|
||||||
check("void f()\n"
|
const std::string src = "void f()\n"
|
||||||
"{\n"
|
"{\n"
|
||||||
" for ( \n"
|
" for ( \n"
|
||||||
"}\n");
|
"}\n";
|
||||||
ASSERT_EQUALS("", errout.str());
|
|
||||||
|
Tokenizer tokenizer;
|
||||||
|
std::istringstream istr(src);
|
||||||
|
ASSERT_EQUALS(false, tokenizer.tokenize(istr, "test.cpp"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -139,6 +139,7 @@ private:
|
||||||
TEST_CASE(vardecl1);
|
TEST_CASE(vardecl1);
|
||||||
TEST_CASE(vardecl2);
|
TEST_CASE(vardecl2);
|
||||||
TEST_CASE(volatile_variables);
|
TEST_CASE(volatile_variables);
|
||||||
|
TEST_CASE(syntax_error);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1709,6 +1710,33 @@ private:
|
||||||
|
|
||||||
ASSERT_EQUALS("int a ; a = 0 ;\nint b ; b = 0 ;\nint c ; c = 0 ;", actual);
|
ASSERT_EQUALS("int a ; a = 0 ;\nint b ; b = 0 ;\nint c ; c = 0 ;", actual);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void syntax_error()
|
||||||
|
{
|
||||||
|
{
|
||||||
|
const char code[] = "void f() {}";
|
||||||
|
Tokenizer tokenizer;
|
||||||
|
std::istringstream istr(code);
|
||||||
|
ASSERT_EQUALS(true, tokenizer.tokenize(istr, "test.cpp"));
|
||||||
|
ASSERT_EQUALS(std::string(""), errout.str());
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
const char code[] = "void f() {{}";
|
||||||
|
Tokenizer tokenizer;
|
||||||
|
std::istringstream istr(code);
|
||||||
|
ASSERT_EQUALS(false, tokenizer.tokenize(istr, "test.cpp"));
|
||||||
|
TODO_ASSERT_EQUALS(std::string("correct error message here"), errout.str());
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
const char code[] = "void f()) {}";
|
||||||
|
Tokenizer tokenizer;
|
||||||
|
std::istringstream istr(code);
|
||||||
|
ASSERT_EQUALS(false, tokenizer.tokenize(istr, "test.cpp"));
|
||||||
|
TODO_ASSERT_EQUALS(std::string("correct error message here"), errout.str());
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
REGISTER_TEST(TestTokenizer)
|
REGISTER_TEST(TestTokenizer)
|
||||||
|
|
Loading…
Reference in New Issue