Introducing a default maximum entity replacement limit of 10kb, it can be controled by using the option XmlOptions.setLoadEntityBytesLimit.

Contribution by Jerry Sy.



git-svn-id: https://svn.apache.org/repos/asf/xmlbeans/trunk@1241680 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/src/store/org/apache/xmlbeans/impl/store/Locale.java b/src/store/org/apache/xmlbeans/impl/store/Locale.java
index ebf96a2..1f02a16 100755
--- a/src/store/org/apache/xmlbeans/impl/store/Locale.java
+++ b/src/store/org/apache/xmlbeans/impl/store/Locale.java
@@ -15,6 +15,7 @@
 
 package org.apache.xmlbeans.impl.store;
 
+import org.apache.xmlbeans.XmlErrorCodes;
 import org.xml.sax.Locator;
 import org.xml.sax.Attributes;
 import org.xml.sax.ContentHandler;
@@ -95,10 +96,8 @@
 import org.apache.xmlbeans.SchemaType;
 import org.apache.xmlbeans.SchemaTypeLoader;
 import org.apache.xmlbeans.XmlTokenSource;
-import org.apache.xmlbeans.XmlOptions;
 import org.apache.xmlbeans.QNameSet;
 import org.apache.xmlbeans.QNameCache;
-import org.apache.xmlbeans.XmlBeans;
 import org.apache.xmlbeans.XmlError;
 import org.apache.xmlbeans.XmlRuntimeException;
 import org.apache.xmlbeans.XmlDocumentProperties;
@@ -3173,6 +3172,9 @@
             _wantCdataBookmarks =
                 _startLocator != null &&
                 options.hasOption(XmlOptions.LOAD_SAVE_CDATA_BOOKMARKS);
+
+            if (options.hasOption(XmlOptions.LOAD_ENTITY_BYTES_LIMIT))
+                _entityBytesLimit = ((Integer)(options.get(XmlOptions.LOAD_ENTITY_BYTES_LIMIT))).intValue();
         }
 
         public void startDocument()
@@ -3287,8 +3289,20 @@
             throws SAXException
         {
             _context.text(ch, start, length);
+
             if (_wantCdataBookmarks && _insideCDATA)
                 _context.bookmarkLastNonAttr(CDataBookmark.CDATA_BOOKMARK);
+
+            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());
+                }
+            }
         }
 
         public void ignorableWhitespace(char ch[], int start, int length)
@@ -3361,13 +3375,19 @@
         public void startEntity(String name)
             throws SAXException
         {
-//            throw new RuntimeException( "Not impl: startEntity" );
+            _insideEntity++;
         }
 
         public void endEntity(String name)
             throws SAXException
         {
-//            throw new RuntimeException( "Not impl: endEntity" );
+            _insideEntity--;
+            assert _insideEntity>=0;
+
+            if (_insideEntity==0)
+            {
+                _entityBytes=0;
+            }
         }
 
         public void setDocumentLocator(Locator locator)
@@ -3401,6 +3421,9 @@
         private boolean _wantCdataBookmarks;
         private Locator _startLocator;
         private boolean _insideCDATA = false;
+        private int _entityBytesLimit = 10240;
+        private int _entityBytes = 0;
+        private int _insideEntity = 0;
     }
 
     private static abstract class SaxLoader
diff --git a/src/xmlpublic/org/apache/xmlbeans/XmlErrorCodes.java b/src/xmlpublic/org/apache/xmlbeans/XmlErrorCodes.java
index b896b9f..0a3c924 100644
--- a/src/xmlpublic/org/apache/xmlbeans/XmlErrorCodes.java
+++ b/src/xmlpublic/org/apache/xmlbeans/XmlErrorCodes.java
@@ -65,6 +65,7 @@
 
     public static final String INVALID_DOCUMENT_TYPE = "invalid.document.type";
     public static final String CANNOT_LOAD_FILE = "cannot.load.file";
+    public static final String EXCEPTION_EXCEEDED_ENTITY_BYTES = "exceeded-entity-bytes";
     public static final String EXCEPTION_LOADING_URL = "exception.loading.url";
     public static final String EXCEPTION_VALUE_NOT_SUPPORTED_J2S = "exception.value.not.supported.j2s";
     public static final String EXCEPTION_VALUE_NOT_SUPPORTED_S2J = "exception.value.not.supported.s2j";
diff --git a/src/xmlpublic/org/apache/xmlbeans/XmlOptions.java b/src/xmlpublic/org/apache/xmlbeans/XmlOptions.java
index 135a4f8..6af8ceb 100644
--- a/src/xmlpublic/org/apache/xmlbeans/XmlOptions.java
+++ b/src/xmlpublic/org/apache/xmlbeans/XmlOptions.java
@@ -861,6 +861,17 @@
         return set(COPY_USE_NEW_SYNC_DOMAIN, useNewSyncDomain ? Boolean.TRUE : Boolean.FALSE );
     }
 
+    /**
+     * Sets the maximum number of bytes allowed when an Entity is expanded during parsing.
+     * The default value is 10240 bytes.
+     * @param entityBytesLimit
+     * @return
+     */
+    public XmlOptions setLoadEntityBytesLimit (int entityBytesLimit)
+    {
+        return set(LOAD_ENTITY_BYTES_LIMIT,entityBytesLimit);
+    }
+
     public static final String GENERATE_JAVA_14 = "1.4";
     public static final String GENERATE_JAVA_15 = "1.5";
 
@@ -983,6 +994,8 @@
     public static final String GENERATE_JAVA_VERSION           = "GENERATE_JAVA_VERSION";
     /** @exclude */
     public static final String COPY_USE_NEW_SYNC_DOMAIN        = "COPY_USE_NEW_LOCALE";
+    /** @exclude */
+    public static final String LOAD_ENTITY_BYTES_LIMIT         = "LOAD_ENTITY_BYTES_LIMIT";
 
     private static final XmlOptions EMPTY_OPTIONS;
     static {
diff --git a/src/xmlpublic/org/apache/xmlbeans/message.properties b/src/xmlpublic/org/apache/xmlbeans/message.properties
index 1c53e5b..80d970b 100644
--- a/src/xmlpublic/org/apache/xmlbeans/message.properties
+++ b/src/xmlpublic/org/apache/xmlbeans/message.properties
@@ -970,3 +970,5 @@
 invalid-xpath = \
 Invalid xpath in identity constraint: {0}
 
+exceeded-entity-bytes = \
+Exceeded Entity dereference bytes limit, limit is {0} bytes.
\ No newline at end of file