Skip to content

Commit cc3ef7b

Browse files
committed
Fix so array access out of bounds for external arrays are detected again
1 parent 7cae057 commit cc3ef7b

4 files changed

Lines changed: 91 additions & 2 deletions

File tree

lib/check.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,10 @@
3737
*/
3838
#define CHECK_WRONG_DATA(X) (X)
3939

40+
namespace tinyxml2 {
41+
class XMLElement;
42+
}
43+
4044
/// @addtogroup Core
4145
/// @{
4246

@@ -108,6 +112,11 @@ class CPPCHECKLIB Check {
108112
return nullptr;
109113
}
110114

115+
virtual FileInfo * loadFileInfoFromXml(const tinyxml2::XMLElement *xmlElement) const {
116+
(void)xmlElement;
117+
return nullptr;
118+
}
119+
111120
virtual void analyseWholeProgram(const std::list<FileInfo*> &fileInfo, const Settings& settings, ErrorLogger &errorLogger) {
112121
(void)fileInfo;
113122
(void)settings;

lib/checkbufferoverrun.cpp

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
#include <list>
3333
#include <cstdlib>
3434
#include <stack>
35+
#include <tinyxml2.h>
3536

3637
//---------------------------------------------------------------------------
3738

@@ -1966,6 +1967,38 @@ Check::FileInfo* CheckBufferOverrun::getFileInfo(const Tokenizer *tokenizer, con
19661967
return fileInfo;
19671968
}
19681969

1970+
Check::FileInfo * CheckBufferOverrun::loadFileInfoFromXml(const tinyxml2::XMLElement *xmlElement) const
1971+
{
1972+
const std::string ArrayUsage("ArrayUsage");
1973+
const std::string ArraySize("ArraySize");
1974+
1975+
MyFileInfo *fileInfo = new MyFileInfo;
1976+
for (const tinyxml2::XMLElement *e = xmlElement->FirstChildElement(); e; e = e->NextSiblingElement()) {
1977+
if (e->Name() == ArrayUsage) {
1978+
const char *array = e->Attribute("array");
1979+
const char *arrayIndex = e->Attribute("index");
1980+
const char *fileName = e->Attribute("fileName");
1981+
const char *linenr = e->Attribute("linenr");
1982+
if (!array || !arrayIndex || !MathLib::isInt(arrayIndex) || !fileName || !linenr || !MathLib::isInt(linenr))
1983+
continue;
1984+
struct MyFileInfo::ArrayUsage arrayUsage;
1985+
arrayUsage.index = MathLib::toLongNumber(arrayIndex);
1986+
arrayUsage.fileName = fileName;
1987+
arrayUsage.linenr = MathLib::toLongNumber(linenr);
1988+
fileInfo->arrayUsage[array] = arrayUsage;
1989+
} else if (e->Name() == ArraySize) {
1990+
const char *array = e->Attribute("array");
1991+
const char *size = e->Attribute("size");
1992+
if (!array || !size || !MathLib::isInt(size))
1993+
continue;
1994+
fileInfo->arraySize[array] = MathLib::toLongNumber(size);
1995+
}
1996+
}
1997+
1998+
return fileInfo;
1999+
}
2000+
2001+
19692002
void CheckBufferOverrun::analyseWholeProgram(const std::list<Check::FileInfo*> &fileInfo, const Settings&, ErrorLogger &errorLogger)
19702003
{
19712004
// Merge all fileInfo

lib/checkbufferoverrun.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -227,6 +227,8 @@ class CPPCHECKLIB CheckBufferOverrun : public Check {
227227
/** @brief Parse current TU and extract file info */
228228
Check::FileInfo *getFileInfo(const Tokenizer *tokenizer, const Settings *settings) const;
229229

230+
Check::FileInfo * loadFileInfoFromXml(const tinyxml2::XMLElement *xmlElement) const;
231+
230232
/** @brief Analyse all file infos for all TU */
231233
void analyseWholeProgram(const std::list<Check::FileInfo*> &fileInfo, const Settings& settings, ErrorLogger &errorLogger);
232234

lib/cppcheck.cpp

Lines changed: 47 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,13 +25,14 @@
2525
#include "path.h"
2626

2727
#include "checkunusedfunctions.h"
28+
#include "timer.h"
29+
#include "version.h"
2830

2931
#include <algorithm>
3032
#include <fstream>
3133
#include <sstream>
3234
#include <stdexcept>
33-
#include "timer.h"
34-
#include "version.h"
35+
#include <tinyxml2.h>
3536

3637
#ifdef HAVE_RULES
3738
#define PCRE_STATIC
@@ -742,6 +743,50 @@ void CppCheck::analyseWholeProgram(const std::string &buildDir, const std::map<s
742743
return;
743744
if (_settings.isEnabled("unusedFunction"))
744745
CheckUnusedFunctions::analyseWholeProgram(this, buildDir);
746+
std::list<Check::FileInfo*> fileInfoList;
747+
748+
// Load all analyzer info data..
749+
const std::string filesTxt(buildDir + "/files.txt");
750+
std::ifstream fin(filesTxt.c_str());
751+
std::string filesTxtLine;
752+
while (std::getline(fin, filesTxtLine)) {
753+
const std::string::size_type firstColon = filesTxtLine.find(':');
754+
if (firstColon == std::string::npos)
755+
continue;
756+
const std::string::size_type lastColon = filesTxtLine.rfind(':');
757+
if (firstColon == lastColon)
758+
continue;
759+
const std::string xmlfile = buildDir + '/' + filesTxtLine.substr(0,firstColon);
760+
const std::string sourcefile = filesTxtLine.substr(lastColon+1);
761+
762+
tinyxml2::XMLDocument doc;
763+
tinyxml2::XMLError error = doc.LoadFile(xmlfile.c_str());
764+
if (error != tinyxml2::XML_SUCCESS)
765+
continue;
766+
767+
const tinyxml2::XMLElement * const rootNode = doc.FirstChildElement();
768+
if (rootNode == nullptr)
769+
continue;
770+
771+
for (const tinyxml2::XMLElement *e = rootNode->FirstChildElement(); e; e = e->NextSiblingElement()) {
772+
if (std::strcmp(e->Name(), "FileInfo") != 0)
773+
continue;
774+
const char *checkClassAttr = e->Attribute("check");
775+
if (!checkClassAttr)
776+
continue;
777+
for (std::list<Check *>::const_iterator it = Check::instances().begin(); it != Check::instances().end(); ++it) {
778+
if (checkClassAttr == (*it)->name())
779+
fileInfoList.push_back((*it)->loadFileInfoFromXml(e));
780+
}
781+
}
782+
}
783+
784+
// Analyse the tokens
785+
for (std::list<Check *>::const_iterator it = Check::instances().begin(); it != Check::instances().end(); ++it)
786+
(*it)->analyseWholeProgram(fileInfoList, _settings, *this);
787+
788+
for (std::list<Check::FileInfo*>::iterator fi = fileInfoList.begin(); fi != fileInfoList.end(); ++fi)
789+
delete(*fi);
745790
}
746791

747792
bool CppCheck::isUnusedFunctionCheckEnabled() const

0 commit comments

Comments
 (0)