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
{
std::istringstream istr(code);
_tokenizer.tokenize(istr, FileName);
if (!_tokenizer.tokenize(istr, FileName))
{
// File had syntax errors, abort
return;
}
}
// Set variable id

View File

@ -153,7 +153,7 @@ void Tokenizer::InsertTokens(Token *dest, Token *src, unsigned int n)
// 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..
_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);
if (!createLinks())
{
// Source has syntax errors, can't proceed
return false;
}
// Combine "- %num%" ..
for (Token *tok = _tokens; tok; tok = tok->next())
{
@ -464,6 +470,7 @@ void Tokenizer::tokenize(std::istream &code, const char FileName[])
// Handle templates..
simplifyTemplates();
return true;
}
//---------------------------------------------------------------------------
@ -945,6 +952,7 @@ bool Tokenizer::createLinks()
if (links.size() == 0)
{
// Error, { and } don't match.
syntaxError(token, '{');
return false;
}
@ -961,6 +969,7 @@ bool Tokenizer::createLinks()
if (links2.size() == 0)
{
// Error, ( and ) don't match.
syntaxError(token, '(');
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.
syntaxError(_tokens, '{');
return false;
}
if (links2.size() > 0)
{
// Error, { and } don't match.
syntaxError(_tokens, '(');
return false;
}
@ -2622,6 +2639,23 @@ const Token * Tokenizer::FindClassFunction(const Token *tok, const char classnam
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
* @param code input stream for code
* @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 */
void setVarId();
@ -208,6 +209,8 @@ private:
*/
bool createLinks();
void syntaxError(const Token *tok, char c);
Token *_tokensBack;
std::map<std::string, unsigned int> _typeSize;
std::vector<std::string> _files;

View File

@ -74,7 +74,7 @@ private:
check("void func1(int **res)\n"
"{\n"
" 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());
}
void testautovararray()
@ -82,7 +82,7 @@ private:
check("void func1(int* arr[2])\n"
"{\n"
" 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());
}
void testautovarreturn()
@ -90,7 +90,7 @@ private:
check("int* func1()\n"
"{\n"
" 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());
}
};

View File

@ -112,7 +112,7 @@ private:
"void f2(unsigned int i1)\n"
"{\n"
" unsigned int i2;\n"
" result = i2 / i1;\n"
" result = i2 / i1;}\n"
);
ASSERT_EQUALS(std::string(""), errout.str());
}
@ -123,7 +123,7 @@ private:
"void foo()\n"
"{\n"
" unsigned int val = 32;\n"
" val = val / USER_HASH;\n"
" val = val / USER_HASH;}\n"
);
ASSERT_EQUALS(std::string(""), errout.str());
}
@ -133,7 +133,7 @@ private:
check("void foo()\n"
"{\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());
}
@ -143,7 +143,7 @@ private:
check("void foo()\n"
"{\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());
}

View File

@ -142,8 +142,7 @@ private:
"{\n"
"{ 346.1,114.1 }, { 347.1,111.1 }\n"
"};\n"
"}\n"
"};\n");
"}\n");
ASSERT_EQUALS(std::string(""), errout.str());
}

View File

@ -358,11 +358,14 @@ private:
void invalidcode()
{
check("void f()\n"
"{\n"
" for ( \n"
"}\n");
ASSERT_EQUALS("", errout.str());
const std::string src = "void f()\n"
"{\n"
" for ( \n"
"}\n";
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(vardecl2);
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);
}
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)