[ 
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}

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}

  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.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. Using the JDK parser, everything's fine");
  }
}
{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}
> 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}



--
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

Reply via email to