Fix ticket #315 (Segmentation fault when checking Linux kernel)

http://apps.sourceforge.net/trac/cppcheck/ticket/315
This commit is contained in:
Reijo Tomperi 2009-05-18 23:32:04 +03:00
parent 927918f9b0
commit d6d55c2db4
2 changed files with 86 additions and 7 deletions

View File

@ -713,10 +713,8 @@ public:
return _name; return _name;
} }
const std::string code(const std::vector<std::string> &params2) const bool code(const std::vector<std::string> &params2, std::string &macrocode) const
{ {
std::string macrocode;
if (_params.empty()) if (_params.empty())
{ {
std::string::size_type pos = _macro.find(" "); std::string::size_type pos = _macro.find(" ");
@ -765,12 +763,18 @@ public:
optcomma = false; optcomma = false;
str += params2[j]; str += params2[j];
} }
break;
} }
if (stringify) else if (i >= params2.size())
{
// Macro had more parameters than caller used.
macrocode = "";
return false;
}
else if (stringify)
str = "\"" + params2[i] + "\""; str = "\"" + params2[i] + "\"";
else else
str = params2[i]; str = params2[i];
break; break;
} }
} }
@ -788,7 +792,7 @@ public:
} }
} }
return macrocode; return true;
} }
}; };
@ -879,6 +883,7 @@ std::string Preprocessor::expandMacros(std::string code, const std::string &file
if (errorLogger) if (errorLogger)
{ {
// TODO, duplicate code. Refactor
std::string fname(filename); std::string fname(filename);
int lineno = 0; int lineno = 0;
for (std::string::size_type p = pos1; p > 0; --p) for (std::string::size_type p = pos1; p > 0; --p)
@ -1022,7 +1027,58 @@ std::string Preprocessor::expandMacros(std::string code, const std::string &file
continue; continue;
// Create macro code.. // Create macro code..
const std::string macrocode(std::string(numberOfNewlines, '\n') + macro.code(params)); std::string tempMacro;
if (!macro.code(params, tempMacro))
{
// Syntax error in code
if (errorLogger)
{
std::string fname(filename);
int lineno = 1;
for (std::string::size_type p = pos1; p > 0; --p)
{
// newline..
if (code[p-1] == '\n')
lineno++;
// #file..
else if (code[p-1] == '#')
{
// Previous char should be a newline..
if (p == 1 || code[p-2] == '\n')
{
// #file..
if (code.substr(p - 1, 6) == "#file ")
{
fname = code.substr(p + 5, code.find("\n", p) - p - 5);
break;
}
else
++lineno;
}
}
// start of file..
else if (p == 1)
++lineno;
}
std::list<ErrorLogger::ErrorMessage::FileLocation> locationList;
ErrorLogger::ErrorMessage::FileLocation loc;
loc.line = lineno;
loc.file = fname;
locationList.push_back(loc);
errorLogger->reportErr(
ErrorLogger::ErrorMessage(locationList,
"error",
std::string("Syntax error. Not enough parameters for macro '") + macro.name() + "'.",
"syntaxError"));
}
return "";
}
const std::string macrocode(std::string(numberOfNewlines, '\n') + tempMacro);
// Insert macro code.. // Insert macro code..
if (!macro.params().empty()) if (!macro.params().empty())

View File

@ -124,6 +124,7 @@ private:
TEST_CASE(define_part_of_func); TEST_CASE(define_part_of_func);
TEST_CASE(conditionalDefine); TEST_CASE(conditionalDefine);
TEST_CASE(multiline_comment); TEST_CASE(multiline_comment);
TEST_CASE(macro_parameters);
} }
@ -1008,6 +1009,28 @@ private:
ASSERT_EQUALS("", errout.str()); ASSERT_EQUALS("", errout.str());
} }
void macro_parameters()
{
errout.str("");
const char filedata[] = "#define BC(a, b, c, arg...) \\\n"
"AB(a, b, c, ## arg)\n"
"\n"
"void f()\n"
"{\n"
" BC(3);\n"
"}\n";
// Preprocess => actual result..
std::istringstream istr(filedata);
std::map<std::string, std::string> actual;
Preprocessor preprocessor;
preprocessor.preprocess(istr, actual, "file.c", std::list<std::string>(), this);
// Compare results..
ASSERT_EQUALS(1, static_cast<unsigned int>(actual.size()));
ASSERT_EQUALS("", actual[""]);
ASSERT_EQUALS("[file.c:6]: (error) Syntax error. Not enough parameters for macro 'BC'.\n", errout.str());
}
}; };