[ https://issues.apache.org/jira/browse/XMLBEANS-512?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]
Michel Jung updated XMLBEANS-512: --------------------------------- Description: In {{SaxHandler}}, if an XML entity exceeds the entity byte limit, an exception is thrown. Too bad the counter is not being reset, so when the same {{SaxHandler}} parses another, valid XML message, the same exception is thrown again. This only happens when using the default XMLReader {{Piccolo}}, since its {{PiccoloSaxHandler}} is cached: {code} private static SaxLoader getPiccoloSaxLoader() { SaxLoader piccoloLoader = (SaxLoader) SystemCache.get().getSaxLoader(); if (piccoloLoader == null) { piccoloLoader = PiccoloSaxLoader.newInstance(); SystemCache.get().setSaxLoader(piccoloLoader); } return piccoloLoader; } {code} When using a differend XMLReader, everything is fine since the XMLReader is never cached: {code} if (options.hasOption(XmlOptions.LOAD_USE_XMLREADER)) { XMLReader xr = (XMLReader) options.get( XmlOptions.LOAD_USE_XMLREADER); if (xr == null) throw new IllegalArgumentException("XMLReader is null"); sl = new XmlReaderSaxLoader(xr); // I've noticed that most XMLReaders don't like a null EntityResolver... if (er != null) xr.setEntityResolver(er); } {code} The following example reproduces the problem: {code} package xmlbeansbug; import java.io.IOException; import javax.xml.parsers.ParserConfigurationException; import javax.xml.parsers.SAXParserFactory; import org.apache.xmlbeans.XmlException; import org.apache.xmlbeans.XmlOptions; import org.apache.xmlbeans.impl.common.SystemCache; import org.apache.xmlbeans.impl.store.Locale; import org.xml.sax.SAXException; public class Bug { private static final String BILLION_LAUGHS = "<?xml version=\"1.0\"?>\n" + "<!DOCTYPE lolz [\n" + " <!ENTITY lol \"lol\">\n" + " <!ELEMENT lolz (#PCDATA)>\n" + " <!ENTITY lol1 \"&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;\">\n" + " <!ENTITY lol2 \"&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;\">\n" + " <!ENTITY lol3 \"&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;\">\n" + " <!ENTITY lol4 \"&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;\">\n" + " <!ENTITY lol5 \"&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;\">\n" + " <!ENTITY lol6 \"&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;\">\n" + " <!ENTITY lol7 \"&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;\">\n" + " <!ENTITY lol8 \"&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;\">\n" + " <!ENTITY lol9 \"&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;\">\n" + "]>\n" + "<lolz>&lol9;</lolz>"; private static final String VALID_XML = "<?xml version=\"1.0\"?>\n" + "<root>foobar</root>"; public static void main(String[] args) throws IOException, SAXException, XmlException, ParserConfigurationException { new Bug().demonstrate(); } private void demonstrate() throws IOException, SAXException, XmlException, ParserConfigurationException { Locale.parseToXmlObject(null, VALID_XML, null, new XmlOptions()); System.out.println("1. Valid XML message was parsed successfully"); try { Locale.parseToXmlObject(null, BILLION_LAUGHS, null, new XmlOptions()); } catch (XmlException e) { System.err.println("2. Billion Laughs XML could not be parsed: " + e.getMessage()); } try { Locale.parseToXmlObject(null, VALID_XML, null, new XmlOptions()); } catch (XmlException e) { System.err.println("3. Now, parsing a valid XML message also throws an exception"); } XmlOptions xmlOptions = new XmlOptions(); xmlOptions.setLoadUseXMLReader(SAXParserFactory.newInstance().newSAXParser().getXMLReader()); Locale.parseToXmlObject(null, VALID_XML, null, xmlOptions); System.out.println("4. When using a different parser, everything's fine"); SystemCache.get().setSaxLoader(null); Locale.parseToXmlObject(null, VALID_XML, null, new XmlOptions()); System.out.println("5. After resetting the cached SaxLoader, Piccolo works again"); } } {code} was: In {{SaxHandler}}, if an XML entity exceeds the entity byte limit, an exception is thrown. Too bad the counter is not being reset, so when the same {{SaxHandler}} parses another, valid XML message, the same exception is thrown again. This only happens when using the default XMLReader {{Piccolo}}, since its {{PiccoloSaxHandler}} is cached: {code} private static SaxLoader getPiccoloSaxLoader() { SaxLoader piccoloLoader = (SaxLoader) SystemCache.get().getSaxLoader(); if (piccoloLoader == null) { piccoloLoader = PiccoloSaxLoader.newInstance(); SystemCache.get().setSaxLoader(piccoloLoader); } return piccoloLoader; } {code} When using a differend XMLReader, everything is fine since the XMLReader is never cached: {code} if (options.hasOption(XmlOptions.LOAD_USE_XMLREADER)) { XMLReader xr = (XMLReader) options.get( XmlOptions.LOAD_USE_XMLREADER); if (xr == null) throw new IllegalArgumentException("XMLReader is null"); sl = new XmlReaderSaxLoader(xr); // I've noticed that most XMLReaders don't like a null EntityResolver... if (er != null) xr.setEntityResolver(er); } {code} The following example reproduces the problem: {code} package xmlbeansbug; import java.io.IOException; import javax.xml.parsers.ParserConfigurationException; import javax.xml.parsers.SAXParserFactory; import org.apache.xmlbeans.XmlException; import org.apache.xmlbeans.XmlOptions; import org.apache.xmlbeans.impl.common.SystemCache; import org.apache.xmlbeans.impl.store.Locale; import org.xml.sax.SAXException; public class Bug { private static final String BILLION_LAUGHS = "<?xml version=\"1.0\"?>\n" + "<!DOCTYPE lolz [\n" + " <!ENTITY lol \"lol\">\n" + " <!ELEMENT lolz (#PCDATA)>\n" + " <!ENTITY lol1 \"&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;\">\n" + " <!ENTITY lol2 \"&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;\">\n" + " <!ENTITY lol3 \"&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;\">\n" + " <!ENTITY lol4 \"&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;\">\n" + " <!ENTITY lol5 \"&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;\">\n" + " <!ENTITY lol6 \"&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;\">\n" + " <!ENTITY lol7 \"&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;\">\n" + " <!ENTITY lol8 \"&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;\">\n" + " <!ENTITY lol9 \"&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;\">\n" + "]>\n" + "<lolz>&lol9;</lolz>"; private static final String VALID_XML = "<?xml version=\"1.0\"?>\n" + "<root>foobar</root>"; public static void main(String[] args) throws IOException, SAXException, XmlException, ParserConfigurationException { new Bug().demonstrate(); } private void demonstrate() throws IOException, SAXException, XmlException, ParserConfigurationException { Locale.parseToXmlObject(null, VALID_XML, null, new XmlOptions()); System.out.println("1. Valid XML message was parsed successfully"); try { Locale.parseToXmlObject(null, BILLION_LAUGHS, null, new XmlOptions()); } catch (XmlException e) { System.err.println("2. Billion Laughs XML could not be parsed: " + e.getMessage()); } try { Locale.parseToXmlObject(null, VALID_XML, null, new XmlOptions()); } catch (XmlException e) { System.err.println("3. Now, parsing a valid XML message also throws an exception"); } XmlOptions xmlOptions = new XmlOptions(); xmlOptions.setLoadUseXMLReader(SAXParserFactory.newInstance().newSAXParser().getXMLReader()); Locale.parseToXmlObject(null, VALID_XML, null, xmlOptions); System.out.println("4. When using a different parser, everything's fine"); SystemCache.get().setSaxLoader(null); Locale.parseToXmlObject(null, VALID_XML, null, new XmlOptions()); System.out.println("5. After resetting the cached SaxLoader, Piccolo works again"); } } {code} The problem's here (Locale.java:3296): {code} if (_insideEntity!=0) { if ((_entityBytes += length) > _entityBytesLimit) { XmlError err = XmlError.forMessage(XmlErrorCodes.EXCEPTION_EXCEEDED_ENTITY_BYTES, new Integer[]{ new Integer(_entityBytesLimit) }); throw new SAXException(err.getMessage()); } } {code} > SaxHandler should be reset on exception > --------------------------------------- > > Key: XMLBEANS-512 > URL: https://issues.apache.org/jira/browse/XMLBEANS-512 > Project: XMLBeans > Issue Type: Bug > Affects Versions: Version 2.6 > Reporter: Michel Jung > > In {{SaxHandler}}, if an XML entity exceeds the entity byte limit, an > exception is thrown. Too bad the counter is not being reset, so when the same > {{SaxHandler}} parses another, valid XML message, the same exception is > thrown again. This only happens when using the default XMLReader {{Piccolo}}, > since its {{PiccoloSaxHandler}} is cached: > {code} > private static SaxLoader getPiccoloSaxLoader() > { > SaxLoader piccoloLoader = (SaxLoader) > SystemCache.get().getSaxLoader(); > if (piccoloLoader == null) > { > piccoloLoader = PiccoloSaxLoader.newInstance(); > SystemCache.get().setSaxLoader(piccoloLoader); > } > return piccoloLoader; > } > {code} > When using a differend XMLReader, everything is fine since the XMLReader is > never cached: > {code} > if (options.hasOption(XmlOptions.LOAD_USE_XMLREADER)) > { > XMLReader xr = (XMLReader) options.get( > XmlOptions.LOAD_USE_XMLREADER); > if (xr == null) > throw new IllegalArgumentException("XMLReader is null"); > sl = new XmlReaderSaxLoader(xr); > // I've noticed that most XMLReaders don't like a null > EntityResolver... > if (er != null) > xr.setEntityResolver(er); > } > {code} > The following example reproduces the problem: > {code} > package xmlbeansbug; > import java.io.IOException; > import javax.xml.parsers.ParserConfigurationException; > import javax.xml.parsers.SAXParserFactory; > import org.apache.xmlbeans.XmlException; > import org.apache.xmlbeans.XmlOptions; > import org.apache.xmlbeans.impl.common.SystemCache; > import org.apache.xmlbeans.impl.store.Locale; > import org.xml.sax.SAXException; > public class Bug { > private static final String BILLION_LAUGHS = "<?xml version=\"1.0\"?>\n" + > "<!DOCTYPE lolz [\n" + > " <!ENTITY lol \"lol\">\n" + > " <!ELEMENT lolz (#PCDATA)>\n" + > " <!ENTITY lol1 > \"&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;\">\n" + > " <!ENTITY lol2 > \"&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;\">\n" + > " <!ENTITY lol3 > \"&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;\">\n" + > " <!ENTITY lol4 > \"&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;\">\n" + > " <!ENTITY lol5 > \"&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;\">\n" + > " <!ENTITY lol6 > \"&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;\">\n" + > " <!ENTITY lol7 > \"&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;\">\n" + > " <!ENTITY lol8 > \"&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;\">\n" + > " <!ENTITY lol9 > \"&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;\">\n" + > "]>\n" + > "<lolz>&lol9;</lolz>"; > private static final String VALID_XML = "<?xml version=\"1.0\"?>\n" + > "<root>foobar</root>"; > public static void main(String[] args) throws IOException, SAXException, > XmlException, ParserConfigurationException { > new Bug().demonstrate(); > } > private void demonstrate() throws IOException, SAXException, XmlException, > ParserConfigurationException { > Locale.parseToXmlObject(null, VALID_XML, null, new XmlOptions()); > System.out.println("1. Valid XML message was parsed successfully"); > try { > Locale.parseToXmlObject(null, BILLION_LAUGHS, null, new XmlOptions()); > } catch (XmlException e) { > System.err.println("2. Billion Laughs XML could not be parsed: " + > e.getMessage()); > } > try { > Locale.parseToXmlObject(null, VALID_XML, null, new XmlOptions()); > } catch (XmlException e) { > System.err.println("3. Now, parsing a valid XML message also throws an > exception"); > } > XmlOptions xmlOptions = new XmlOptions(); > > xmlOptions.setLoadUseXMLReader(SAXParserFactory.newInstance().newSAXParser().getXMLReader()); > Locale.parseToXmlObject(null, VALID_XML, null, xmlOptions); > System.out.println("4. When using a different parser, everything's fine"); > SystemCache.get().setSaxLoader(null); > Locale.parseToXmlObject(null, VALID_XML, null, new XmlOptions()); > System.out.println("5. After resetting the cached SaxLoader, Piccolo > works again"); > } > } > {code} -- This message was sent by Atlassian JIRA (v6.2#6252) --------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscr...@xmlbeans.apache.org For additional commands, e-mail: dev-h...@xmlbeans.apache.org