Skip to content

Commit 5114436

Browse files
authored
Fix #15107: Exporting XML via GUI escapes special characters twice. (#8943)
1 parent 3f3249f commit 5114436

7 files changed

Lines changed: 51 additions & 59 deletions

File tree

‎gui/test/data/xmlfiles/xmlreport_v2.xml‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,10 @@
22
<results version="2">
33
<cppcheck version="1.47"/>
44
<errors>
5-
<error id="unreadVariable" severity="style" msg="Variable &amp;#039;a&amp;#039; is assigned a value that is never used" verbose="Variable &amp;#039;a&amp;#039; is assigned a value that is never used">
5+
<error id="unreadVariable" severity="style" msg="Variable 'a' is assigned a value that is never used" verbose="Variable 'a' is assigned a value that is never used">
66
<location file="test.cxx" line="11"/>
77
</error>
8-
<error id="unreadVariable" severity="style" msg="Variable &amp;#039;b&amp;#039; is assigned a value that is never used" verbose="Variable &amp;#039;b&amp;#039; is assigned a value that is never used">
8+
<error id="unreadVariable" severity="style" msg="Variable 'b' is assigned a value that is never used" verbose="Variable 'b' is assigned a value that is never used">
99
<location file="test.cxx" line="28"/>
1010
</error>
1111
<error id="memleak" severity="error" msg="Memory leak: b" verbose="Memory leak: b">
@@ -15,7 +15,7 @@
1515
<location file="test.cxx" line="32"/>
1616
<location file="test.cxx" line="16"/>
1717
</error>
18-
<error id="obsoleteFunctionsgets" severity="style" msg="Found obsolescent function &amp;#039;gets&amp;#039;. It is recommended to use the function &amp;#039;fgets&amp;#039; instead" verbose="Found obsolescent function &amp;#039;gets&amp;#039;. With gets you&amp;#039;ll get buffer overruns if the input data too big for the buffer. It is recommended to use the function &amp;#039;fgets&amp;#039; instead.">
18+
<error id="obsoleteFunctionsgets" severity="style" msg="Found obsolescent function 'gets'. It is recommended to use the function 'fgets' instead" verbose="Found obsolescent function 'gets'. With gets you'll get buffer overruns if the input data too big for the buffer. It is recommended to use the function 'fgets' instead.">
1919
<location file="test.cxx" line="31"/>
2020
</error>
2121
<error id="postfixOperator" severity="performance" msg="Prefer prefix ++/-- operators for non-primitive types." verbose="Prefix ++/-- operators should be preferred for non-primitive types. Pre-increment/decrement can be more efficient than post-increment/decrement. Post-increment/decrement usually involves keeping a copy of the previous value around and adds a little extra code.">

‎gui/test/resultstree/testresultstree.cpp‎

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -106,12 +106,6 @@ Application& ApplicationList::getApplication(const int /*unused*/) {
106106
const Application& ApplicationList::getApplication(const int index) const {
107107
return mApplications.at(index);
108108
}
109-
QString XmlReport::quoteMessage(const QString &message) {
110-
return message;
111-
}
112-
QString XmlReport::unquoteMessage(const QString &message) {
113-
return message;
114-
}
115109
XmlReport::XmlReport(const QString& filename) : Report(filename) {}
116110
// NOLINTNEXTLINE(performance-unnecessary-value-param)
117111
void ThreadResult::finishCheck(CheckThread::Details /*unused*/) {

‎gui/test/xmlreportv2/testxmlreportv2.cpp‎

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,9 @@
2121
#include "erroritem.h"
2222
#include "xmlreportv2.h"
2323

24+
#include <QFile>
2425
#include <QList>
26+
#include <QTemporaryDir>
2527
#include <QtTest>
2628

2729
void TestXmlReportV2::readXml() const
@@ -53,4 +55,39 @@ void TestXmlReportV2::readXml() const
5355
QCOMPARE(item2.message, QString("Mismatching allocation and deallocation: k"));
5456
}
5557

58+
void TestXmlReportV2::writeXmlEscaping() const
59+
{
60+
QTemporaryDir dir;
61+
const QString path = dir.path() + "/results.xml";
62+
63+
ErrorItem item;
64+
item.errorId = "id";
65+
item.severity = Severity::style;
66+
item.summary = "\"x\" & <y> &quot;";
67+
item.message = item.summary;
68+
QErrorPathItem loc;
69+
loc.file = "a&b.cpp";
70+
loc.line = 1;
71+
item.errorPath << loc;
72+
{
73+
XmlReportV2 report(path, QString());
74+
QVERIFY(report.create());
75+
report.writeHeader();
76+
report.writeError(item);
77+
report.writeFooter();
78+
}
79+
80+
QFile file(path);
81+
QVERIFY(file.open(QIODevice::ReadOnly));
82+
QVERIFY(file.readAll().contains("msg=\"&quot;x&quot; &amp; &lt;y&gt; &amp;quot;\""));
83+
84+
XmlReportV2 report(path, QString());
85+
QVERIFY(report.open());
86+
const QList<ErrorItem> errors = report.read();
87+
QCOMPARE(errors.size(), 1);
88+
QCOMPARE(errors[0].summary, item.summary);
89+
QCOMPARE(errors[0].message, item.message);
90+
QCOMPARE(errors[0].errorPath[0].file, loc.file);
91+
}
92+
5693
QTEST_MAIN(TestXmlReportV2)

‎gui/test/xmlreportv2/testxmlreportv2.h‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,4 +23,5 @@ class TestXmlReportV2 : public QObject {
2323

2424
private slots:
2525
void readXml() const;
26+
void writeXmlEscaping() const;
2627
};

‎gui/xmlreport.cpp‎

Lines changed: 0 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -32,28 +32,6 @@ XmlReport::XmlReport(const QString &filename) :
3232
Report(filename)
3333
{}
3434

35-
QString XmlReport::quoteMessage(const QString &message)
36-
{
37-
QString quotedMessage(message);
38-
quotedMessage.replace("&", "&amp;");
39-
quotedMessage.replace("\"", "&quot;");
40-
quotedMessage.replace("'", "&#039;");
41-
quotedMessage.replace("<", "&lt;");
42-
quotedMessage.replace(">", "&gt;");
43-
return quotedMessage;
44-
}
45-
46-
QString XmlReport::unquoteMessage(const QString &message)
47-
{
48-
QString quotedMessage(message);
49-
quotedMessage.replace("&amp;", "&");
50-
quotedMessage.replace("&quot;", "\"");
51-
quotedMessage.replace("&#039;", "'");
52-
quotedMessage.replace("&lt;", "<");
53-
quotedMessage.replace("&gt;", ">");
54-
return quotedMessage;
55-
}
56-
5735
int XmlReport::determineVersion(const QString &filename)
5836
{
5937
QFile file;

‎gui/xmlreport.h‎

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -42,20 +42,6 @@ class XmlReport : public Report {
4242
*/
4343
virtual QList<ErrorItem> read() = 0;
4444

45-
/**
46-
* @brief Quote the message.
47-
* @param message Message to quote.
48-
* @return quoted message.
49-
*/
50-
static QString quoteMessage(const QString &message);
51-
52-
/**
53-
* @brief Unquote the message.
54-
* @param message Message to quote.
55-
* @return quoted message.
56-
*/
57-
static QString unquoteMessage(const QString &message);
58-
5945
/**
6046
* @brief Get the XML report format version from the file.
6147
* @param filename Filename of the report file.

‎gui/xmlreportv2.cpp‎

Lines changed: 10 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -132,10 +132,8 @@ void XmlReportV2::writeError(const ErrorItem &error)
132132

133133
// Don't localize severity so we can read these files
134134
mXmlWriter->writeAttribute(SeverityAttribute, GuiSeverity::toString(error.severity));
135-
const QString summary = XmlReport::quoteMessage(error.summary);
136-
mXmlWriter->writeAttribute(MsgAttribute, summary);
137-
const QString message = XmlReport::quoteMessage(error.message);
138-
mXmlWriter->writeAttribute(VerboseAttribute, message);
135+
mXmlWriter->writeAttribute(MsgAttribute, error.summary);
136+
mXmlWriter->writeAttribute(VerboseAttribute, error.message);
139137
if (error.inconclusive)
140138
mXmlWriter->writeAttribute(InconclusiveAttribute, "true");
141139
if (!error.remark.isEmpty())
@@ -145,7 +143,7 @@ void XmlReportV2::writeError(const ErrorItem &error)
145143
if (error.hash > 0)
146144
mXmlWriter->writeAttribute(HashAttribute, QString::number(error.hash));
147145
if (!error.file0.isEmpty())
148-
mXmlWriter->writeAttribute(IncludedFromFilenameAttribute, quoteMessage(error.file0));
146+
mXmlWriter->writeAttribute(IncludedFromFilenameAttribute, error.file0);
149147
if (!error.sinceDate.isEmpty())
150148
mXmlWriter->writeAttribute(SinceDateAttribute, error.sinceDate);
151149
if (!error.tags.isEmpty())
@@ -155,12 +153,12 @@ void XmlReportV2::writeError(const ErrorItem &error)
155153
mXmlWriter->writeStartElement(LocationElementName);
156154

157155
QString file = QDir::toNativeSeparators(error.errorPath[i].file);
158-
mXmlWriter->writeAttribute(FilenameAttribute, XmlReport::quoteMessage(file));
156+
mXmlWriter->writeAttribute(FilenameAttribute, file);
159157
mXmlWriter->writeAttribute(LineAttribute, QString::number(error.errorPath[i].line));
160158
if (error.errorPath[i].column > 0)
161159
mXmlWriter->writeAttribute(ColumnAttribute, QString::number(error.errorPath[i].column));
162160
if (error.errorPath.count() > 1)
163-
mXmlWriter->writeAttribute(InfoAttribute, XmlReport::quoteMessage(error.errorPath[i].info));
161+
mXmlWriter->writeAttribute(InfoAttribute, error.errorPath[i].info);
164162

165163
mXmlWriter->writeEndElement();
166164
}
@@ -228,10 +226,8 @@ ErrorItem XmlReportV2::readError(const QXmlStreamReader *reader)
228226
QXmlStreamAttributes attribs = reader->attributes();
229227
item.errorId = attribs.value(QString(), IdAttribute).toString();
230228
item.severity = GuiSeverity::fromString(attribs.value(QString(), SeverityAttribute).toString());
231-
const QString summary = attribs.value(QString(), MsgAttribute).toString();
232-
item.summary = XmlReport::unquoteMessage(summary);
233-
const QString message = attribs.value(QString(), VerboseAttribute).toString();
234-
item.message = XmlReport::unquoteMessage(message);
229+
item.summary = attribs.value(QString(), MsgAttribute).toString();
230+
item.message = attribs.value(QString(), VerboseAttribute).toString();
235231
if (attribs.hasAttribute(QString(), InconclusiveAttribute))
236232
item.inconclusive = true;
237233
if (attribs.hasAttribute(QString(), RemarkAttribute))
@@ -258,14 +254,14 @@ ErrorItem XmlReportV2::readError(const QXmlStreamReader *reader)
258254
QXmlStreamAttributes attribs = mXmlReader->attributes();
259255
QString file0 = attribs.value(QString(), IncludedFromFilenameAttribute).toString();
260256
if (!file0.isEmpty())
261-
item.file0 = XmlReport::unquoteMessage(file0);
257+
item.file0 = file0;
262258
QErrorPathItem loc;
263-
loc.file = XmlReport::unquoteMessage(attribs.value(QString(), FilenameAttribute).toString());
259+
loc.file = attribs.value(QString(), FilenameAttribute).toString();
264260
loc.line = attribs.value(QString(), LineAttribute).toString().toUInt();
265261
if (attribs.hasAttribute(QString(), ColumnAttribute))
266262
loc.column = attribs.value(QString(), ColumnAttribute).toString().toInt();
267263
if (attribs.hasAttribute(QString(), InfoAttribute))
268-
loc.info = XmlReport::unquoteMessage(attribs.value(QString(), InfoAttribute).toString());
264+
loc.info = attribs.value(QString(), InfoAttribute).toString();
269265
item.errorPath.push_front(loc);
270266
}
271267
break;

0 commit comments

Comments
 (0)