From c95387307288862095d8cc431fbc70f1d39ca1f6 Mon Sep 17 00:00:00 2001 From: Mallory Adams Date: Fri, 21 Jul 2023 14:30:09 -0400 Subject: [PATCH] Ensure that the xunit reporter emits well-formed XML XML does not allow certain characters to appear in documents. This change ensures that those restricted characters are replaced by legal characters. This bug means that when a test ends up containing, for example, ANSI color codes (i.e. `<div`) then the generated XML file is invalid and some consumers (such as CircleCI) are unable to parse the contents. Link: https://www.w3.org/TR/2006/REC-xml11-20060816/#charsets --- lib/utils.js | 2 ++ test/reporters/xunit.spec.js | 39 ++++++++++++++++++++++++++++++++++++ 2 files changed, 41 insertions(+) diff --git a/lib/utils.js b/lib/utils.js index 7e1d566819..2e67ff8347 100644 --- a/lib/utils.js +++ b/lib/utils.js @@ -15,6 +15,7 @@ var util = require('util'); var he = require('he'); const MOCHA_ID_PROP_NAME = '__mocha_id__'; +const RESTRICTED_CHAR = /[\x01-\x08\x0B-\x0C\x0E-\x1F\x7F-\x84\x86-\x9F]/g; /** * Inherit the prototype methods from one constructor into another. @@ -35,6 +36,7 @@ exports.inherits = util.inherits; * @return {string} */ exports.escape = function (html) { + html = html.toString().replaceAll(RESTRICTED_CHAR, "�"); return he.encode(String(html), {useNamedReferences: false}); }; diff --git a/test/reporters/xunit.spec.js b/test/reporters/xunit.spec.js index a5e0f1bbeb..52228607ef 100644 --- a/test/reporters/xunit.spec.js +++ b/test/reporters/xunit.spec.js @@ -357,6 +357,45 @@ describe('XUnit reporter', function () { expect(expectedWrite, 'to be', expectedTag); }); + it('should write well-formed XML', function () { + var xunit = new XUnit(runner); + var inputMessage = '\x1Bsome message'; + expectedMessage = '�some message'; + var expectedTest = { + state: STATE_FAILED, + title: expectedTitle, + parent: { + fullTitle: function () { + return expectedClassName; + } + }, + duration: 1000, + err: { + actual: 'foo', + expected: 'bar', + message: inputMessage, + stack: expectedStack + } + }; + + xunit.test.call(fakeThis, expectedTest); + sinon.restore(); + + var expectedTag = + '' + + expectedMessage + + '\n' + + expectedDiff + + '\n' + + expectedStack + + ''; + expect(expectedWrite, 'to be', expectedTag); + }); + it('should handle non-string diff values', function () { var runner = new EventEmitter(); createStatsCollector(runner);