Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[submodule "externals/cryptopp"]
path = externals/cryptopp
url = git@github.com:nirbar/cryptopp.git
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ if (BUILD_TESTS)
endif()

add_subdirectory(externals/tinyxml)
add_subdirectory(externals/cryptopp)
add_subdirectory(lib) # CppCheck Library
add_subdirectory(cli) # Client application
add_subdirectory(test) # Tests
Expand Down
11 changes: 10 additions & 1 deletion cli/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,16 +1,25 @@
include_directories(${PROJECT_SOURCE_DIR}/lib/)
include_directories(SYSTEM ${PROJECT_SOURCE_DIR}/externals/tinyxml/)
include_directories(SYSTEM ${PROJECT_SOURCE_DIR}/externals/)

file(GLOB hdrs "*.h")
file(GLOB srcs "*.cpp")
file(GLOB mainfile "main.cpp")
list(REMOVE_ITEM srcs ${mainfile})

set(libs
cryptopp-static
)
if(WIN32)
set(libs ${libs} Shlwapi.lib)
endif()

add_library(cli_objs OBJECT ${hdrs} ${srcs})
add_executable(cppcheck ${hdrs} ${mainfile} $<TARGET_OBJECTS:cli_objs> $<TARGET_OBJECTS:lib_objs> $<TARGET_OBJECTS:tinyxml_objs>)
if (HAVE_RULES)
target_link_libraries(cppcheck pcre)
set(libs ${libs} pcre)
endif()
target_link_libraries(cppcheck ${libs})

install(TARGETS cppcheck
RUNTIME DESTINATION ${CMAKE_INSTALL_FULL_BINDIR}
Expand Down
16 changes: 16 additions & 0 deletions cli/cmdlineparser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,22 @@ bool CmdLineParser::ParseFromArgs(int argc, const char* const argv[])
}
}

// Cache file (--cache=)
else if (std::strncmp(argv[i], "--cache=", strlen("--cache=")) == 0) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

strlen=>sizeof

std::string str(argv[i]);
str=str.substr(strlen("--cache="));
if( str.empty()){
PrintMessage("cppcheck: No cache file given to '--cache=' option.");
return false;
}

_settings->cacheFile = str;
if (0 != _settings->cache.Load(str))
{
PrintMessage("cppcheck: Failed loading cache file " + str);
}
}

// Filter errors
else if (std::strncmp(argv[i], "--exitcode-suppressions=", 24) == 0) {
// exitcode-suppressions=filename.txt
Expand Down
5 changes: 5 additions & 0 deletions cli/cppcheckexecutor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -880,6 +880,11 @@ int CppCheckExecutor::check_internal(CppCheck& cppcheck, int /*argc*/, const cha
reportErr(ErrorLogger::ErrorMessage::getXMLFooter(settings.xml_version));
}

if (!settings.cacheFile.empty())
{
settings.cache.Save();
}

_settings = 0;
if (returnValue)
return settings.exitCode;
Expand Down
1 change: 1 addition & 0 deletions externals/cryptopp
Submodule cryptopp added at 55f349
1 change: 1 addition & 0 deletions lib/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
include_directories(SYSTEM ${PROJECT_SOURCE_DIR}/externals/tinyxml/)
include_directories(SYSTEM ${PROJECT_SOURCE_DIR}/externals/)

file(GLOB_RECURSE hdrs "*.h")
file(GLOB_RECURSE srcs "*.cpp")
Expand Down
301 changes: 301 additions & 0 deletions lib/cache.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,301 @@
#include "cache.h"
#include "errorlogger.h"
#include <cryptopp/sha3.h>
#include <cryptopp/base64.h>
#include <cryptopp/files.h>
#include <fstream>
using namespace std;
using namespace tinyxml2;
using namespace CryptoPP;

Cache::Cache()
{
}

Cache::Cache(const Cache & other)
{
*this = other;
}

Cache & Cache::operator=(const Cache & other)
{
Clear();
if (!_cacheFile.empty())
{
Load(other._cacheFile);
}
return *this;
}

int Cache::Load(const string& file)
{
XMLError er = XML_SUCCESS;

if (!_cacheFile.empty())
{
return -1;
}

_cacheFile = file;
er = _cache.LoadFile(file.c_str());

return((er == XML_SUCCESS) || (er == XML_NO_ERROR)) ? 0 : (er | XML_SUCCESS);
}

int Cache::LoadFromCache(const char* filePath, const char* configuration, size_t* pCachedSize, std::string* pHash, const tinyxml2::XMLElement** ppElem) const
{
const XMLElement *elem = NULL;
const char* sizeStr = NULL;
const char* hashStr = NULL;
size_t tmpSize = 0;
string path;
(*pCachedSize) = 0;
(*ppElem) = NULL;
pHash->clear();

path = Normalize(filePath);

if ((Find(path.c_str(), configuration, &elem) != 0) || (elem == NULL))
{
return -1;
}

// Parse size
if ((sizeStr = elem->Attribute("Size")) == NULL)
{
return -1;
}

if ((tmpSize = ::stoull(sizeStr, NULL)) == 0)
{
return -1;
}

// Hash
if ((hashStr = elem->Attribute("Hash")) == NULL)
{
return -1;
}

(*pCachedSize) = tmpSize;
(*pHash) = hashStr;
(*ppElem) = elem;
return 0;
}

int Cache::Find(const char* filePath, const char* configuration, XMLElement** ppElem)
{
return Find(filePath, configuration, (const XMLElement**)ppElem);
}

int Cache::Find(const char* filePath, const char* configuration, const XMLElement** ppElem) const
{
(*ppElem) = NULL;

string path = Normalize(filePath);
if (path.empty() || _cacheFile.empty())
{
return -1;
}

const XMLElement* root = _cache.RootElement();
if (root == NULL)
{
return -1;
}

for (const XMLElement* currElem = root->FirstChildElement("File"); currElem != NULL; currElem = currElem->NextSiblingElement("File"))
{
if (currElem->Attribute("Path", path.c_str()) && currElem->Attribute("Configuration", configuration))
{
(*ppElem) = currElem;
break;
}
}

return ((*ppElem) == NULL);
}

string Cache::CalcHash(const char* code) const
{
SHA3_512 sha;
string out;
Base64Encoder* enc = new Base64Encoder(new StringSink(out), false);

StringSource(code, true, new HashFilter(sha, enc));

return out;
}

string Cache::Normalize(const char* filePath) const

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you should use our Path class to deal with filepaths. There is for instance a Path::fromNativeSeparators() function that might be useful here.

{
size_t i;
string path(filePath);

while ((i = path.find('\\')) != string::npos)
{
path = path.replace(i, 1, "/");
}
while ((i = path.find("//")) != string::npos)
{
path = path.replace(i, 2, "/");
}
return path;
}

bool Cache::ReportCachedResults(const char* filePath, const char* configuration, const char* code, ErrorLogger* pLogger) const
{
string cachedHash;
size_t cachedSize = 0;
const XMLElement* pElem = NULL;

// Cached?
if ((LoadFromCache(filePath, configuration, &cachedSize, &cachedHash, &pElem) != 0) || (cachedSize == 0) || cachedHash.empty() || (pElem == NULL))
{
return false;
}

// Compare size
size_t actualSize = strlen(code);
if (actualSize != cachedSize)
{
return false;
}

// Compare hash
string actualHash = CalcHash(code);
if (actualHash.compare(cachedHash) != 0)
{
return false;
}

for (const XMLElement* currChild = pElem->FirstChildElement("Report"); currChild != NULL; currChild = currChild->NextSiblingElement("Report"))
{
ErrorLogger::ErrorMessage msg;
string t = currChild->GetText();
if (!msg.deserialize(t))
{
return false;
}
if (msg._id.compare("syntaxError") != 0)
{
msg.file0 = filePath;
}
pLogger->reportErr(msg);
}

return true;
}

int Cache::CacheFile(const char* filePath, const char* configuration, const char* code, const std::list<std::string>& reports)
{
// Cache disabled
if (_cacheFile.empty())
{
return 0;
}

string path = Normalize(filePath);
if (path.empty())
{
return -1;
}

size_t actualSize = strlen(code);
if (actualSize == 0)
{
return -1;
}

string actualHash = CalcHash(code);
if (actualHash.empty())
{
return -1;
}

XMLElement* pElem = NULL;
if ((Find(path.c_str(), configuration, &pElem) != 0) || (pElem == NULL))
{
// Create element
XMLElement* root = _cache.RootElement();
if (root == NULL)
{
root = _cache.NewElement("CppCheckCache");
if (root == NULL)
{
return -1;
}

if (_cache.InsertFirstChild(root) == NULL)
{
return -1;
}
}

pElem = _cache.NewElement("File");
if (pElem == NULL)
{
return -1;
}

if (root->InsertEndChild(pElem) == NULL)
{
return -1;
}
}

pElem->DeleteChildren();
pElem->SetAttribute("Configuration", configuration);
pElem->SetAttribute("Size", actualSize);
pElem->SetAttribute("Hash", actualHash.c_str());
pElem->SetAttribute("Path", path.c_str());

// Insert reports
std::list<std::string>::const_iterator currIt, endIt;
for (currIt = reports.begin(), endIt = reports.end(); currIt != endIt; ++currIt)
{
XMLElement *report = _cache.NewElement("Report");
if (report == NULL)
{
return -1;
}

report->SetText(currIt->c_str());
pElem->InsertEndChild(report);
}

return 0;
}

int Cache::Remove(const char* filePath, const char* configuration)
{
XMLElement* pElem = NULL;
if ((Find(filePath, configuration, &pElem) != 0) || (pElem == NULL))
{
return 0;
}

XMLElement* root = _cache.RootElement();
if (root == NULL)
{
return -1;
}

root->DeleteChild(pElem);
return 0;
}

void Cache::Clear()
{
_cache.Clear();
_cacheFile.clear();
}

int Cache::Save()
{
XMLError er = XML_SUCCESS;

er = _cache.SaveFile(_cacheFile.c_str());

return((er == XML_SUCCESS) || (er == XML_NO_ERROR)) ? 0 : (er | XML_SUCCESS);
}
Loading