Skip to content

Commit fecb349

Browse files
authored
Fix #14959 (Warning hash for token-based warnings) (#8778)
1 parent baf5eaa commit fecb349

5 files changed

Lines changed: 68 additions & 5 deletions

File tree

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -600,7 +600,7 @@ $(libcppdir)/cppcheck.o: lib/cppcheck.cpp externals/picojson/picojson.h external
600600
$(libcppdir)/ctu.o: lib/ctu.cpp externals/tinyxml2/tinyxml2.h lib/astutils.h lib/check.h lib/config.h lib/ctu.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/smallvector.h lib/sourcelocation.h lib/standards.h lib/symboldatabase.h lib/templatesimplifier.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/vfvalue.h lib/xml.h
601601
$(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/ctu.cpp
602602

603-
$(libcppdir)/errorlogger.o: lib/errorlogger.cpp externals/tinyxml2/tinyxml2.h lib/check.h lib/checkers.h lib/color.h lib/config.h lib/cppcheck.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/settings.h lib/smallvector.h lib/standards.h lib/suppressions.h lib/templatesimplifier.h lib/token.h lib/tokenlist.h lib/utils.h lib/vfvalue.h lib/xml.h
603+
$(libcppdir)/errorlogger.o: lib/errorlogger.cpp externals/tinyxml2/tinyxml2.h lib/check.h lib/checkers.h lib/color.h lib/config.h lib/cppcheck.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/settings.h lib/smallvector.h lib/sourcelocation.h lib/standards.h lib/suppressions.h lib/symboldatabase.h lib/templatesimplifier.h lib/token.h lib/tokenlist.h lib/utils.h lib/vfvalue.h lib/xml.h
604604
$(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/errorlogger.cpp
605605

606606
$(libcppdir)/errortypes.o: lib/errortypes.cpp lib/config.h lib/errortypes.h lib/utils.h

lib/errorlogger.cpp

Lines changed: 63 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
#include "path.h"
2424
#include "settings.h"
2525
#include "suppressions.h"
26+
#include "symboldatabase.h"
2627
#include "token.h"
2728
#include "tokenlist.h"
2829
#include "utils.h"
@@ -35,6 +36,7 @@
3536
#include <cstring>
3637
#include <fstream>
3738
#include <iomanip>
39+
#include <numeric>
3840
#include <sstream>
3941
#include <string>
4042
#include <unordered_map>
@@ -106,6 +108,8 @@ ErrorMessage::ErrorMessage(const std::list<const Token*>& callstack, const Token
106108
file0 = list->getFiles()[0];
107109

108110
setmsg(msg);
111+
112+
calculateWarningHash(callstack);
109113
}
110114

111115

@@ -126,7 +130,7 @@ ErrorMessage::ErrorMessage(const std::list<const Token*>& callstack, const Token
126130

127131
setmsg(msg);
128132

129-
// hash = calculateWarningHash(list, hashWarning.str());
133+
calculateWarningHash(callstack);
130134
}
131135

132136
ErrorMessage::ErrorMessage(ErrorPath errorPath, const TokenList *tokenList, Severity severity, const char id[], const std::string &msg, const CWE &cwe, Certainty certainty)
@@ -159,7 +163,12 @@ ErrorMessage::ErrorMessage(ErrorPath errorPath, const TokenList *tokenList, Seve
159163

160164
setmsg(msg);
161165

162-
// hash = calculateWarningHash(tokenList, hashWarning.str());
166+
std::list<const Token*> tokens;
167+
std::transform(errorPath.cbegin(), errorPath.cend(), std::back_inserter(tokens),
168+
[](const ErrorPathItem& e) {
169+
return e.first;
170+
});
171+
calculateWarningHash(tokens);
163172
}
164173

165174
// TODO: improve errorhandling?
@@ -244,6 +253,58 @@ void ErrorMessage::setmsg(const std::string &msg)
244253
}
245254
}
246255

256+
void ErrorMessage::calculateWarningHash(const std::list<const Token*>& callstack)
257+
{
258+
if (callstack.empty())
259+
return;
260+
// Calculate a hash for this warning message
261+
std::string hashString;
262+
for (const Token* tok: callstack) {
263+
if (!tok)
264+
continue;
265+
if (!tok->scope())
266+
return; // might be a syntax error before scope info has been set
267+
if (tok->scope()->isExecutable()) {
268+
// Executable scope => include all tokens in the function => if the
269+
// function is changed the hash is changed
270+
for (const Token* t = tok; t; t = t->previous()) {
271+
if (!t->scope()->isExecutable())
272+
break;
273+
hashString += " " + t->str();
274+
}
275+
for (const Token* t = tok->next(); t; t = t->next()) {
276+
if (!t->scope()->isExecutable())
277+
break;
278+
hashString += " " + t->str();
279+
}
280+
} else {
281+
// Non executable scope => include tokens in current statement => if the current statement is changed the hash is changed
282+
for (const Token* t = tok; t; t = t->previous()) {
283+
if (t->str() == ";")
284+
break;
285+
if (t->scope() != tok->scope()) // stop on {} unless its an initializer
286+
break;
287+
hashString += " " + t->str();
288+
}
289+
for (const Token* t = tok->next(); t; t = t->next()) {
290+
hashString += " " + t->str();
291+
if (t->str() == ";")
292+
break;
293+
if (t->scope() != tok->scope()) // stop on {} unless its an initializer
294+
break;
295+
}
296+
}
297+
}
298+
299+
hashString = id + '\n' + mShortMessage + '\n' + hashString;
300+
301+
// hash algorithm: sdbm
302+
// any hash algorithm can be used but it has to be the same hash on different platforms and compilers
303+
hash = std::accumulate(hashString.cbegin(), hashString.cend(), std::size_t{0}, [](std::size_t h, unsigned char c) {
304+
return static_cast<std::size_t>(c) + (h << 6) + (h << 16) - h;
305+
});
306+
}
307+
247308
static void serializeString(std::string &oss, const std::string & str)
248309
{
249310
oss += std::to_string(str.length());

lib/errorlogger.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,8 @@ class CPPCHECKLIB ErrorMessage {
209209
private:
210210
static std::string fixInvalidChars(const std::string& raw);
211211

212+
void calculateWarningHash(const std::list<const Token*>& callstack);
213+
212214
/** Short message */
213215
std::string mShortMessage;
214216

oss-fuzz/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -270,7 +270,7 @@ $(libcppdir)/cppcheck.o: ../lib/cppcheck.cpp ../externals/picojson/picojson.h ..
270270
$(libcppdir)/ctu.o: ../lib/ctu.cpp ../externals/tinyxml2/tinyxml2.h ../lib/astutils.h ../lib/check.h ../lib/config.h ../lib/ctu.h ../lib/errorlogger.h ../lib/errortypes.h ../lib/library.h ../lib/mathlib.h ../lib/path.h ../lib/smallvector.h ../lib/sourcelocation.h ../lib/standards.h ../lib/symboldatabase.h ../lib/templatesimplifier.h ../lib/token.h ../lib/tokenize.h ../lib/tokenlist.h ../lib/utils.h ../lib/vfvalue.h ../lib/xml.h
271271
$(CXX) ${LIB_FUZZING_ENGINE} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/ctu.cpp
272272

273-
$(libcppdir)/errorlogger.o: ../lib/errorlogger.cpp ../externals/tinyxml2/tinyxml2.h ../lib/check.h ../lib/checkers.h ../lib/color.h ../lib/config.h ../lib/cppcheck.h ../lib/errorlogger.h ../lib/errortypes.h ../lib/library.h ../lib/mathlib.h ../lib/path.h ../lib/platform.h ../lib/settings.h ../lib/smallvector.h ../lib/standards.h ../lib/suppressions.h ../lib/templatesimplifier.h ../lib/token.h ../lib/tokenlist.h ../lib/utils.h ../lib/vfvalue.h ../lib/xml.h
273+
$(libcppdir)/errorlogger.o: ../lib/errorlogger.cpp ../externals/tinyxml2/tinyxml2.h ../lib/check.h ../lib/checkers.h ../lib/color.h ../lib/config.h ../lib/cppcheck.h ../lib/errorlogger.h ../lib/errortypes.h ../lib/library.h ../lib/mathlib.h ../lib/path.h ../lib/platform.h ../lib/settings.h ../lib/smallvector.h ../lib/sourcelocation.h ../lib/standards.h ../lib/suppressions.h ../lib/symboldatabase.h ../lib/templatesimplifier.h ../lib/token.h ../lib/tokenlist.h ../lib/utils.h ../lib/vfvalue.h ../lib/xml.h
274274
$(CXX) ${LIB_FUZZING_ENGINE} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/errorlogger.cpp
275275

276276
$(libcppdir)/errortypes.o: ../lib/errortypes.cpp ../lib/config.h ../lib/errortypes.h ../lib/utils.h

test/cli/other_test.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2666,7 +2666,7 @@ def test_xml_output(tmp_path): # #13391 / #13485
26662666
<results version="2">
26672667
<cppcheck version="{}"/>
26682668
<errors>
2669-
<error id="nullPointerRedundantCheck" severity="warning" msg="Either the condition &apos;p&apos; is redundant or there is possible null pointer dereference: p." verbose="Either the condition &apos;p&apos; is redundant or there is possible null pointer dereference: p." cwe="476" file0="{}" remark="boom">
2669+
<error id="nullPointerRedundantCheck" severity="warning" msg="Either the condition &apos;p&apos; is redundant or there is possible null pointer dereference: p." verbose="Either the condition &apos;p&apos; is redundant or there is possible null pointer dereference: p." cwe="476" hash="2884341854190588507" file0="{}" remark="boom">
26702670
<location file="{}" line="5" column="12" info="Null pointer dereference"/>
26712671
<location file="{}" line="4" column="8" info="Assuming that condition &apos;p&apos; is not redundant"/>
26722672
<symbol>p</symbol>

0 commit comments

Comments
 (0)