Read error locations in the correct order from XML (#3226)

When ErrorMessage::callStack elements are serialized to XML they are
saved in the reverse order. But when they read back from XML they are
added at the end of the list. Thus the round trip via XML reverses the
order of ErrorMessage::callStack.

From the user point of view it looks like the usage of the
--cppcheck-build-dir option sometimes (when the file wasn't reanalyzed,
but that is hard to spot) results in incorrect location info for some
diagnostic messages.

Moreover, when the first location matches some suppression rule and the
last doesn't match any (or vice versa), usage of --cppcheck-build-dir
results in some diagnostic messages appearing and disappearing seemingly
at random (again, depending on whether the file was reanalyzed or not).
This commit is contained in:
dummyunit 2021-04-22 15:28:33 +03:00 committed by GitHub
parent 207361b174
commit 229832e72e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 36 additions and 2 deletions

View File

@ -632,7 +632,7 @@ test/testconstructors.o: test/testconstructors.cpp lib/astutils.h lib/check.h li
test/testcppcheck.o: test/testcppcheck.cpp lib/analyzerinfo.h lib/check.h lib/config.h lib/cppcheck.h lib/errorlogger.h lib/errortypes.h lib/importproject.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/standards.h lib/suppressions.h lib/timer.h lib/utils.h test/testsuite.h
$(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CPPFILESDIR) $(CXXFLAGS) $(UNDEF_STRICT_ANSI) -c -o test/testcppcheck.o test/testcppcheck.cpp
test/testerrorlogger.o: test/testerrorlogger.cpp lib/analyzerinfo.h lib/check.h lib/config.h lib/cppcheck.h lib/errorlogger.h lib/errortypes.h lib/importproject.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/standards.h lib/suppressions.h lib/timer.h lib/utils.h test/testsuite.h
test/testerrorlogger.o: test/testerrorlogger.cpp externals/tinyxml2/tinyxml2.h lib/analyzerinfo.h lib/check.h lib/config.h lib/cppcheck.h lib/errorlogger.h lib/errortypes.h lib/importproject.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/standards.h lib/suppressions.h lib/timer.h lib/utils.h test/testsuite.h
$(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CPPFILESDIR) $(CXXFLAGS) $(UNDEF_STRICT_ANSI) -c -o test/testerrorlogger.o test/testerrorlogger.cpp
test/testexceptionsafety.o: test/testexceptionsafety.cpp lib/astutils.h lib/check.h lib/checkexceptionsafety.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/importproject.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/standards.h lib/suppressions.h lib/templatesimplifier.h lib/timer.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/valueflow.h test/testsuite.h

View File

@ -216,7 +216,7 @@ ErrorMessage::ErrorMessage(const tinyxml2::XMLElement * const errmsg)
const char *info = strinfo ? strinfo : "";
const int line = strline ? std::atoi(strline) : 0;
const int column = strcolumn ? std::atoi(strcolumn) : 0;
callStack.emplace_back(file, info, line, column);
callStack.emplace_front(file, info, line, column);
}
}
}

View File

@ -22,6 +22,7 @@
#include "suppressions.h"
#include "testsuite.h"
#include <tinyxml2.h>
#include <list>
#include <string>
@ -49,6 +50,7 @@ private:
TEST_CASE(ToXmlV2);
TEST_CASE(ToXmlV2Locations);
TEST_CASE(ToXmlV2Encoding);
TEST_CASE(FromXmlV2);
// Inconclusive results in xml reports..
TEST_CASE(InconclusiveXml);
@ -231,6 +233,38 @@ private:
}
}
void FromXmlV2() const {
const char xmldata[] = "<?xml version=\"1.0\"?>\n"
"<error id=\"errorId\""
" severity=\"error\""
" cwe=\"123\""
" inconclusive=\"true\""
" msg=\"Programming error.\""
" verbose=\"Verbose error\""
" hash=\"456\""
">\n"
" <location file=\"bar.cpp\" line=\"8\" column=\"1\"/>\n"
" <location file=\"foo.cpp\" line=\"5\" column=\"2\"/>\n"
"</error>";
tinyxml2::XMLDocument doc;
doc.Parse(xmldata, sizeof(xmldata));
ErrorMessage msg(doc.FirstChildElement());
ASSERT_EQUALS("errorId", msg.id);
ASSERT_EQUALS(Severity::error, msg.severity);
ASSERT_EQUALS(123u, msg.cwe.id);
ASSERT_EQUALS(Certainty::inconclusive, msg.certainty);
ASSERT_EQUALS("Programming error.", msg.shortMessage());
ASSERT_EQUALS("Verbose error", msg.verboseMessage());
ASSERT_EQUALS(456u, msg.hash);
ASSERT_EQUALS(2u, msg.callStack.size());
ASSERT_EQUALS("foo.cpp", msg.callStack.front().getfile());
ASSERT_EQUALS(5, msg.callStack.front().line);
ASSERT_EQUALS(2u, msg.callStack.front().column);
ASSERT_EQUALS("bar.cpp", msg.callStack.back().getfile());
ASSERT_EQUALS(8, msg.callStack.back().line);
ASSERT_EQUALS(1u, msg.callStack.back().column);
}
void InconclusiveXml() const {
// Location
std::list<ErrorMessage::FileLocation> locs(1, fooCpp5);