forked from phoedos/pmd
Merge pull request #5210 from adangel/issue-5059-core-xml-cdata
[core] Fix PMD's XMLRenderer to escape CDATA
This commit is contained in:
commit
77b763e321
@ -20,6 +20,8 @@ This is a {{ site.pmd.release_type }} release.
|
|||||||
(ApexCRUDViolation, CognitiveComplexity, OperationWithLimitsInLoop)
|
(ApexCRUDViolation, CognitiveComplexity, OperationWithLimitsInLoop)
|
||||||
* [#5163](https://github.com/pmd/pmd/issues/5163): \[apex] Parser error when using toLabel in SOSL query
|
* [#5163](https://github.com/pmd/pmd/issues/5163): \[apex] Parser error when using toLabel in SOSL query
|
||||||
* [#5182](https://github.com/pmd/pmd/issues/5182): \[apex] Parser error when using GROUPING in a SOQL query
|
* [#5182](https://github.com/pmd/pmd/issues/5182): \[apex] Parser error when using GROUPING in a SOQL query
|
||||||
|
* core
|
||||||
|
* [#5059](https://github.com/pmd/pmd/issues/5059): \[core] xml output doesn't escape CDATA inside its own CDATA
|
||||||
* java
|
* java
|
||||||
* [#5190](https://github.com/pmd/pmd/issues/5190): \[java] NPE in type inference
|
* [#5190](https://github.com/pmd/pmd/issues/5190): \[java] NPE in type inference
|
||||||
|
|
||||||
|
@ -196,7 +196,14 @@ public class XMLRenderer extends AbstractIncrementingRenderer {
|
|||||||
xmlWriter.writeAttribute("filename", determineFileName(pe.getFileId()));
|
xmlWriter.writeAttribute("filename", determineFileName(pe.getFileId()));
|
||||||
xmlWriter.writeAttribute("msg", pe.getMsg());
|
xmlWriter.writeAttribute("msg", pe.getMsg());
|
||||||
writeNewLine();
|
writeNewLine();
|
||||||
xmlWriter.writeCData(pe.getDetail());
|
|
||||||
|
// in case the message contains itself some CDATA sections, they need to be handled
|
||||||
|
// in order to not produce invalid XML...
|
||||||
|
String detail = pe.getDetail();
|
||||||
|
// split "]]>" into "]]" and ">" into two cdata sections
|
||||||
|
detail = detail.replace("]]>", "]]]]><![CDATA[>");
|
||||||
|
|
||||||
|
xmlWriter.writeCData(detail);
|
||||||
writeNewLine();
|
writeNewLine();
|
||||||
xmlWriter.writeEndElement();
|
xmlWriter.writeEndElement();
|
||||||
}
|
}
|
||||||
|
@ -7,6 +7,7 @@ package net.sourceforge.pmd.cpd;
|
|||||||
import static org.hamcrest.MatcherAssert.assertThat;
|
import static org.hamcrest.MatcherAssert.assertThat;
|
||||||
import static org.hamcrest.Matchers.containsString;
|
import static org.hamcrest.Matchers.containsString;
|
||||||
import static org.hamcrest.Matchers.not;
|
import static org.hamcrest.Matchers.not;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
|
||||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
|
||||||
import java.io.ByteArrayInputStream;
|
import java.io.ByteArrayInputStream;
|
||||||
@ -15,6 +16,7 @@ import java.io.StringReader;
|
|||||||
import java.io.StringWriter;
|
import java.io.StringWriter;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import javax.xml.XMLConstants;
|
import javax.xml.XMLConstants;
|
||||||
|
import javax.xml.parsers.DocumentBuilder;
|
||||||
import javax.xml.parsers.DocumentBuilderFactory;
|
import javax.xml.parsers.DocumentBuilderFactory;
|
||||||
import javax.xml.parsers.ParserConfigurationException;
|
import javax.xml.parsers.ParserConfigurationException;
|
||||||
import javax.xml.parsers.SAXParser;
|
import javax.xml.parsers.SAXParser;
|
||||||
@ -316,6 +318,29 @@ class XMLRendererTest {
|
|||||||
assertEquals(processingError.getDetail(), textContent);
|
assertEquals(processingError.getDetail(), textContent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Note, that CPD's processing error isn't output as a CDATA section at the moment.
|
||||||
|
* This test just makes sure, the XML is valid, in case {@code <error>} is changed into CDATA.
|
||||||
|
* Currently, {@code >>]} is automatically escaped into {@code ]]>}.
|
||||||
|
*
|
||||||
|
* @see <a href="https://github.com/pmd/pmd/issues/5059">[core] xml output doesn't escape CDATA inside its own CDATA</a>
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
void cdataSectionInError() throws Exception {
|
||||||
|
FileId fileId = FileId.fromPathLikeString("file1.txt");
|
||||||
|
Report.ProcessingError processingError = new Report.ProcessingError(
|
||||||
|
new LexException(2, 1, fileId, "test exception", new RuntimeException("Invalid source: '<![CDATA[ ... ]]> ...'")),
|
||||||
|
fileId);
|
||||||
|
CPDReportRenderer renderer = new XMLRenderer();
|
||||||
|
StringWriter sw = new StringWriter();
|
||||||
|
renderer.render(CpdTestUtils.makeReport(Collections.emptyList(), Collections.emptyMap(), Collections.singletonList(processingError)), sw);
|
||||||
|
String report = sw.toString();
|
||||||
|
assertReportIsValidSchema(report);
|
||||||
|
|
||||||
|
DocumentBuilder documentBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
|
||||||
|
assertDoesNotThrow(() -> documentBuilder.parse(new InputSource(new StringReader(report))));
|
||||||
|
}
|
||||||
|
|
||||||
private static void assertReportIsValidSchema(String report) throws SAXException, ParserConfigurationException, IOException {
|
private static void assertReportIsValidSchema(String report) throws SAXException, ParserConfigurationException, IOException {
|
||||||
SchemaFactory schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
|
SchemaFactory schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
|
||||||
Schema schema = schemaFactory.newSchema(new StreamSource(XMLRenderer.class.getResourceAsStream("/cpd-report_1_0_0.xsd")));
|
Schema schema = schemaFactory.newSchema(new StreamSource(XMLRenderer.class.getResourceAsStream("/cpd-report_1_0_0.xsd")));
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
|
|
||||||
package net.sourceforge.pmd.renderers;
|
package net.sourceforge.pmd.renderers;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
|
||||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||||
@ -15,6 +16,7 @@ import java.io.StringReader;
|
|||||||
import java.nio.charset.Charset;
|
import java.nio.charset.Charset;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
|
import javax.xml.parsers.DocumentBuilder;
|
||||||
import javax.xml.parsers.DocumentBuilderFactory;
|
import javax.xml.parsers.DocumentBuilderFactory;
|
||||||
|
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
@ -26,6 +28,7 @@ import org.xml.sax.InputSource;
|
|||||||
import net.sourceforge.pmd.FooRule;
|
import net.sourceforge.pmd.FooRule;
|
||||||
import net.sourceforge.pmd.PMDVersion;
|
import net.sourceforge.pmd.PMDVersion;
|
||||||
import net.sourceforge.pmd.internal.util.IOUtil;
|
import net.sourceforge.pmd.internal.util.IOUtil;
|
||||||
|
import net.sourceforge.pmd.lang.ast.ParseException;
|
||||||
import net.sourceforge.pmd.lang.document.FileId;
|
import net.sourceforge.pmd.lang.document.FileId;
|
||||||
import net.sourceforge.pmd.lang.document.FileLocation;
|
import net.sourceforge.pmd.lang.document.FileLocation;
|
||||||
import net.sourceforge.pmd.lang.document.TextRange2d;
|
import net.sourceforge.pmd.lang.document.TextRange2d;
|
||||||
@ -161,6 +164,19 @@ class XMLRendererTest extends AbstractRendererTest {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see <a href="https://github.com/pmd/pmd/issues/5059">[core] xml output doesn't escape CDATA inside its own CDATA</a>
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
void cdataSectionInError() throws Exception {
|
||||||
|
ProcessingError processingError = new ProcessingError(new ParseException("Invalid source: '<![CDATA[ ... ]]> ...'"),
|
||||||
|
FileId.fromPathLikeString("dummy.txt"));
|
||||||
|
String result = renderReport(getRenderer(), it -> it.onError(processingError), StandardCharsets.UTF_8);
|
||||||
|
|
||||||
|
DocumentBuilder documentBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
|
||||||
|
assertDoesNotThrow(() -> documentBuilder.parse(new InputSource(new StringReader(result))));
|
||||||
|
}
|
||||||
|
|
||||||
private String renderTempFile(Renderer renderer, Report report, Charset expectedCharset) throws IOException {
|
private String renderTempFile(Renderer renderer, Report report, Charset expectedCharset) throws IOException {
|
||||||
File reportFile = folder.resolve("report.out").toFile();
|
File reportFile = folder.resolve("report.out").toFile();
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user