Skip to content

Commit

Permalink
fix: skip attribute entity references instead of choking when XMLInpu…
Browse files Browse the repository at this point in the history
…tFactory.IS_REPLACING_ENTITY_REFERENCES is set to false

allow SAXParserFactoryImpl to be customised

Refs: FasterXML#65
  • Loading branch information
cjmamo committed Mar 16, 2021
1 parent a5cdb5b commit b68dfdc
Show file tree
Hide file tree
Showing 3 changed files with 62 additions and 14 deletions.
26 changes: 14 additions & 12 deletions src/main/java/com/fasterxml/aalto/in/ReaderScanner.java
Original file line number Diff line number Diff line change
Expand Up @@ -896,20 +896,22 @@ private final int collectValue(int attrPtr, char quoteChar, PName attrName)
throwUnexpectedChar(c, "'<' not allowed in attribute value");
case XmlCharTypes.CT_AMP:
{
int d = handleEntityInText(false);
if (d == 0) { // unexpanded general entity... not good
reportUnexpandedEntityInAttr(attrName, false);
}
// Ok; does it need a surrogate though? (over 16 bits)
if ((d >> 16) != 0) {
d -= 0x10000;
attrBuffer[attrPtr++] = (char) (0xD800 | (d >> 10));
d = 0xDC00 | (d & 0x3FF);
if (attrPtr >= attrBuffer.length) {
attrBuffer = _attrCollector.valueBufferFull();
if (_config.willExpandEntities()) {
int d = handleEntityInText(false);
if (d == 0) { // unexpanded general entity... not good
reportUnexpandedEntityInAttr(attrName, false);
}
// Ok; does it need a surrogate though? (over 16 bits)
if ((d >> 16) != 0) {
d -= 0x10000;
attrBuffer[attrPtr++] = (char) (0xD800 | (d >> 10));
d = 0xDC00 | (d & 0x3FF);
if (attrPtr >= attrBuffer.length) {
attrBuffer = _attrCollector.valueBufferFull();
}
}
c = (char) d;
}
c = (char) d;
}
break;
case XmlCharTypes.CT_ATTR_QUOTE:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,11 @@ public class SAXParserFactoryImpl
{
final InputFactoryImpl mStaxFactory;

public SAXParserFactoryImpl(InputFactoryImpl inputFactory)
{
mStaxFactory = inputFactory;
}

public SAXParserFactoryImpl()
{
// defaults should be fine...
Expand Down
45 changes: 43 additions & 2 deletions src/test/java/com/fasterxml/aalto/sax/TestEntityResolver.java
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
package com.fasterxml.aalto.sax;

import java.io.*;
import java.util.concurrent.CountDownLatch;

import javax.xml.parsers.SAXParser;
import javax.xml.stream.XMLInputFactory;

import com.fasterxml.aalto.stax.InputFactoryImpl;
import org.xml.sax.*;
import org.xml.sax.helpers.DefaultHandler;

import com.fasterxml.aalto.sax.*;

/**
* Simple unit tests to verify that most fundamental parsing functionality
* works via Woodstox SAX implementation.
Expand Down Expand Up @@ -49,6 +50,46 @@ public void testWithDummyExtSubset()
}
}

public void testSkipAttributeEntityReference()
throws Exception
{
final String XML =
"<!DOCTYPE root PUBLIC '//some//public//id' 'no-such-thing.dtd'>\n"
+"<root b=\"&replace-me;\" />";

SAXParserFactoryImpl spf = new SAXParserFactoryImpl();
SAXParser sp = spf.newSAXParser();
DefaultHandler h = new DefaultHandler();

try {
sp.parse(new InputSource(new StringReader(XML)), h);
fail();
} catch (SAXException e) {
verifyException(e, "General entity reference (&replace-me;) encountered in entity expanding mode: operation not (yet) implemented\n at [row,col {unknown-source}]: [2,22]");
}

InputFactoryImpl inputFactory = new InputFactoryImpl();
inputFactory.setProperty(XMLInputFactory.IS_REPLACING_ENTITY_REFERENCES, false);
SAXParserFactoryImpl spfKeepEntityReferences = new SAXParserFactoryImpl(inputFactory);
spfKeepEntityReferences.setNamespaceAware(true);
SAXParser spKeepEntityReferences = spfKeepEntityReferences.newSAXParser();

final CountDownLatch countDownLatch = new CountDownLatch(1);
spKeepEntityReferences.parse(new InputSource(new StringReader(XML)), new DefaultHandler() {
@Override
public void startElement(String uri, String localName, String qName, Attributes attributes) {
assertEquals("root", localName);
assertEquals("root", qName);
assertEquals(1, attributes.getLength());
assertEquals("&replace-me;", attributes.getValue(0));

countDownLatch.countDown();
}
});

assertEquals(0, countDownLatch.getCount());
}

static class MyResolver
implements EntityResolver
{
Expand Down

0 comments on commit b68dfdc

Please sign in to comment.