Fix so array access out of bounds for external arrays are detected again

This commit is contained in:
Daniel Marjamäki 2017-03-30 10:14:17 +02:00
parent 7cae057615
commit cc3ef7bbe8
4 changed files with 91 additions and 2 deletions

View File

@ -37,6 +37,10 @@
*/ */
#define CHECK_WRONG_DATA(X) (X) #define CHECK_WRONG_DATA(X) (X)
namespace tinyxml2 {
class XMLElement;
}
/// @addtogroup Core /// @addtogroup Core
/// @{ /// @{
@ -108,6 +112,11 @@ public:
return nullptr; return nullptr;
} }
virtual FileInfo * loadFileInfoFromXml(const tinyxml2::XMLElement *xmlElement) const {
(void)xmlElement;
return nullptr;
}
virtual void analyseWholeProgram(const std::list<FileInfo*> &fileInfo, const Settings& settings, ErrorLogger &errorLogger) { virtual void analyseWholeProgram(const std::list<FileInfo*> &fileInfo, const Settings& settings, ErrorLogger &errorLogger) {
(void)fileInfo; (void)fileInfo;
(void)settings; (void)settings;

View File

@ -32,6 +32,7 @@
#include <list> #include <list>
#include <cstdlib> #include <cstdlib>
#include <stack> #include <stack>
#include <tinyxml2.h>
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
@ -1966,6 +1967,38 @@ Check::FileInfo* CheckBufferOverrun::getFileInfo(const Tokenizer *tokenizer, con
return fileInfo; return fileInfo;
} }
Check::FileInfo * CheckBufferOverrun::loadFileInfoFromXml(const tinyxml2::XMLElement *xmlElement) const
{
const std::string ArrayUsage("ArrayUsage");
const std::string ArraySize("ArraySize");
MyFileInfo *fileInfo = new MyFileInfo;
for (const tinyxml2::XMLElement *e = xmlElement->FirstChildElement(); e; e = e->NextSiblingElement()) {
if (e->Name() == ArrayUsage) {
const char *array = e->Attribute("array");
const char *arrayIndex = e->Attribute("index");
const char *fileName = e->Attribute("fileName");
const char *linenr = e->Attribute("linenr");
if (!array || !arrayIndex || !MathLib::isInt(arrayIndex) || !fileName || !linenr || !MathLib::isInt(linenr))
continue;
struct MyFileInfo::ArrayUsage arrayUsage;
arrayUsage.index = MathLib::toLongNumber(arrayIndex);
arrayUsage.fileName = fileName;
arrayUsage.linenr = MathLib::toLongNumber(linenr);
fileInfo->arrayUsage[array] = arrayUsage;
} else if (e->Name() == ArraySize) {
const char *array = e->Attribute("array");
const char *size = e->Attribute("size");
if (!array || !size || !MathLib::isInt(size))
continue;
fileInfo->arraySize[array] = MathLib::toLongNumber(size);
}
}
return fileInfo;
}
void CheckBufferOverrun::analyseWholeProgram(const std::list<Check::FileInfo*> &fileInfo, const Settings&, ErrorLogger &errorLogger) void CheckBufferOverrun::analyseWholeProgram(const std::list<Check::FileInfo*> &fileInfo, const Settings&, ErrorLogger &errorLogger)
{ {
// Merge all fileInfo // Merge all fileInfo

View File

@ -227,6 +227,8 @@ public:
/** @brief Parse current TU and extract file info */ /** @brief Parse current TU and extract file info */
Check::FileInfo *getFileInfo(const Tokenizer *tokenizer, const Settings *settings) const; Check::FileInfo *getFileInfo(const Tokenizer *tokenizer, const Settings *settings) const;
Check::FileInfo * loadFileInfoFromXml(const tinyxml2::XMLElement *xmlElement) const;
/** @brief Analyse all file infos for all TU */ /** @brief Analyse all file infos for all TU */
void analyseWholeProgram(const std::list<Check::FileInfo*> &fileInfo, const Settings& settings, ErrorLogger &errorLogger); void analyseWholeProgram(const std::list<Check::FileInfo*> &fileInfo, const Settings& settings, ErrorLogger &errorLogger);

View File

@ -25,13 +25,14 @@
#include "path.h" #include "path.h"
#include "checkunusedfunctions.h" #include "checkunusedfunctions.h"
#include "timer.h"
#include "version.h"
#include <algorithm> #include <algorithm>
#include <fstream> #include <fstream>
#include <sstream> #include <sstream>
#include <stdexcept> #include <stdexcept>
#include "timer.h" #include <tinyxml2.h>
#include "version.h"
#ifdef HAVE_RULES #ifdef HAVE_RULES
#define PCRE_STATIC #define PCRE_STATIC
@ -742,6 +743,50 @@ void CppCheck::analyseWholeProgram(const std::string &buildDir, const std::map<s
return; return;
if (_settings.isEnabled("unusedFunction")) if (_settings.isEnabled("unusedFunction"))
CheckUnusedFunctions::analyseWholeProgram(this, buildDir); CheckUnusedFunctions::analyseWholeProgram(this, buildDir);
std::list<Check::FileInfo*> fileInfoList;
// Load all analyzer info data..
const std::string filesTxt(buildDir + "/files.txt");
std::ifstream fin(filesTxt.c_str());
std::string filesTxtLine;
while (std::getline(fin, filesTxtLine)) {
const std::string::size_type firstColon = filesTxtLine.find(':');
if (firstColon == std::string::npos)
continue;
const std::string::size_type lastColon = filesTxtLine.rfind(':');
if (firstColon == lastColon)
continue;
const std::string xmlfile = buildDir + '/' + filesTxtLine.substr(0,firstColon);
const std::string sourcefile = filesTxtLine.substr(lastColon+1);
tinyxml2::XMLDocument doc;
tinyxml2::XMLError error = doc.LoadFile(xmlfile.c_str());
if (error != tinyxml2::XML_SUCCESS)
continue;
const tinyxml2::XMLElement * const rootNode = doc.FirstChildElement();
if (rootNode == nullptr)
continue;
for (const tinyxml2::XMLElement *e = rootNode->FirstChildElement(); e; e = e->NextSiblingElement()) {
if (std::strcmp(e->Name(), "FileInfo") != 0)
continue;
const char *checkClassAttr = e->Attribute("check");
if (!checkClassAttr)
continue;
for (std::list<Check *>::const_iterator it = Check::instances().begin(); it != Check::instances().end(); ++it) {
if (checkClassAttr == (*it)->name())
fileInfoList.push_back((*it)->loadFileInfoFromXml(e));
}
}
}
// Analyse the tokens
for (std::list<Check *>::const_iterator it = Check::instances().begin(); it != Check::instances().end(); ++it)
(*it)->analyseWholeProgram(fileInfoList, _settings, *this);
for (std::list<Check::FileInfo*>::iterator fi = fileInfoList.begin(); fi != fileInfoList.end(); ++fi)
delete(*fi);
} }
bool CppCheck::isUnusedFunctionCheckEnabled() const bool CppCheck::isUnusedFunctionCheckEnabled() const