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:
Reijo Tomperi 2009-05-07 23:17:29 +03:00
parent 917a48cd65
commit dd8b738f7f
8 changed files with 90 additions and 19 deletions

View File

@ -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

View File

@ -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"));
*/
}

View File

@ -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;

View File

@ -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=&num;"); "res=&num;}");
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]=&num;"); "arr[0]=&num;}");
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 &num;"); "return &num;}");
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());
} }
}; };

View File

@ -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());
} }

View File

@ -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());
} }

View File

@ -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"));
} }

View File

@ -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)