Author: mrglavas
Date: Tue Aug 13 15:42:35 2013
New Revision: 1513559

URL: http://svn.apache.org/r1513559
Log:
Improve the way in which Xerces counts parameter entity expansions so that it 
scales better towards the entity expansion limit like it does for general 
entities.

Modified:
    xerces/java/trunk/src/org/apache/xerces/impl/XMLDTDScannerImpl.java
    xerces/java/trunk/src/org/apache/xerces/impl/XMLEntityManager.java

Modified: xerces/java/trunk/src/org/apache/xerces/impl/XMLDTDScannerImpl.java
URL: 
http://svn.apache.org/viewvc/xerces/java/trunk/src/org/apache/xerces/impl/XMLDTDScannerImpl.java?rev=1513559&r1=1513558&r2=1513559&view=diff
==============================================================================
--- xerces/java/trunk/src/org/apache/xerces/impl/XMLDTDScannerImpl.java 
(original)
+++ xerces/java/trunk/src/org/apache/xerces/impl/XMLDTDScannerImpl.java Tue Aug 
13 15:42:35 2013
@@ -631,7 +631,7 @@ public class XMLDTDScannerImpl
      * @param name The name of the parameter entity to start (without the '%')
      * @param literal Whether this is happening within a literal
      */
-    protected void startPE(String name, boolean literal) 
+    protected String startPE(String name, boolean literal) 
         throws IOException, XNIException {
         int depth = fPEDepth;
         String pName = "%"+name;
@@ -650,6 +650,7 @@ public class XMLDTDScannerImpl
         if (depth != fPEDepth && fEntityScanner.isExternal()) {
             scanTextDecl();
         }
+        return pName;
     }
 
     /** 
@@ -1511,9 +1512,11 @@ public class XMLDTDScannerImpl
             }
         }
 
+        // count of direct and indirect references to parameter entities in 
the value of the entity.
+        int paramEntityRefs = 0;
         // internal entity
         if (systemId == null) {
-            scanEntityValue(fLiteral, fLiteral2);
+            paramEntityRefs = scanEntityValue(fLiteral, fLiteral2);
             // since we need it's value anyway, let's snag it so it doesn't 
get corrupted 
             // if a new load takes place before we store the entity values
             fStringBuffer.clear();
@@ -1556,7 +1559,7 @@ public class XMLDTDScannerImpl
             }
         }
         else {
-            fEntityManager.addInternalEntity(name, fStringBuffer.toString());
+            fEntityManager.addInternalEntity(name, fStringBuffer.toString(), 
paramEntityRefs);
             if (fDTDHandler != null) {
                 fDTDHandler.internalEntityDecl(name, fStringBuffer, 
fStringBuffer2, null); 
             }
@@ -1576,8 +1579,8 @@ public class XMLDTDScannerImpl
      * the use of scanCharReferenceValue), and fStringBuffer2, anything in them
      * at the time of calling is lost.
      */
-    protected final void scanEntityValue(XMLString value, 
-                                         XMLString nonNormalizedValue)
+    protected final int scanEntityValue(XMLString value, 
+                                        XMLString nonNormalizedValue)
         throws IOException, XNIException
     {
         int quote = fEntityScanner.scanChar();
@@ -1586,6 +1589,8 @@ public class XMLDTDScannerImpl
         }
         // store at which depth of entities we start
         int entityDepth = fEntityDepth;
+        // count of direct and indirect references to parameter entities in 
the value of the entity.
+        int paramEntityRefs = 0;
 
         XMLString literal = fString;
         XMLString literal2 = fString;
@@ -1642,7 +1647,8 @@ public class XMLDTDScannerImpl
                             fStringBuffer2.append(peName);
                             fStringBuffer2.append(';');
                         }
-                        startPE(peName, true);
+                        final String pNameWithPct = startPE(peName, true);
+                        paramEntityRefs += 
(fEntityManager.getParamEntityRefCount(pNameWithPct) + 1);
                         // REVISIT: [Q] Why do we skip spaces here? -Ac
                         // REVISIT: This will make returning the non-
                         //          normalized value harder. -Ac
@@ -1681,7 +1687,8 @@ public class XMLDTDScannerImpl
         if (!fEntityScanner.skipChar(quote)) {
             reportFatalError("CloseQuoteMissingInDecl", null);
         }
-    } // scanEntityValue(XMLString,XMLString):void
+        return paramEntityRefs;
+    } // scanEntityValue(XMLString,XMLString):int
 
     /**
      * Scans a notation declaration

Modified: xerces/java/trunk/src/org/apache/xerces/impl/XMLEntityManager.java
URL: 
http://svn.apache.org/viewvc/xerces/java/trunk/src/org/apache/xerces/impl/XMLEntityManager.java?rev=1513559&r1=1513558&r2=1513559&view=diff
==============================================================================
--- xerces/java/trunk/src/org/apache/xerces/impl/XMLEntityManager.java 
(original)
+++ xerces/java/trunk/src/org/apache/xerces/impl/XMLEntityManager.java Tue Aug 
13 15:42:35 2013
@@ -473,12 +473,13 @@ public class XMLEntityManager
      *
      * @param name The name of the entity.
      * @param text The text of the entity.
+     * @param paramEntityRefs Count of direct and indirect references to 
parameter entities in the value of the entity.
      *
      * @see SymbolTable
      */
-    public void addInternalEntity(String name, String text) {
+    public void addInternalEntity(String name, String text, int 
paramEntityRefs) {
         if (!fEntities.containsKey(name)) {
-            Entity entity = new InternalEntity(name, text, fInExternalSubset);
+            Entity entity = new InternalEntity(name, text, fInExternalSubset, 
paramEntityRefs);
             fEntities.put(name, entity);
         }
         else{
@@ -490,8 +491,46 @@ public class XMLEntityManager
             }
         }
 
+    } // addInternalEntity(String,String,int)    
+    
+    /**
+     * Adds an internal entity declaration.
+     * <p>
+     * <strong>Note:</strong> This method ignores subsequent entity
+     * declarations.
+     * <p>
+     * <strong>Note:</strong> The name should be a unique symbol. The
+     * SymbolTable can be used for this purpose.
+     *
+     * @param name The name of the entity.
+     * @param text The text of the entity.
+     *
+     * @see SymbolTable
+     */
+    public void addInternalEntity(String name, String text) {
+        addInternalEntity(name, text, 0);
     } // addInternalEntity(String,String)
-
+    
+    /**
+     * Returns the number of direct and indirect references to parameter 
+     * entities in the value of the entity. This value will only be
+     * non-zero for an internal parameter entity.
+     * 
+     * @param entityName The name of the entity to check.
+     * @return Count of direct and indirect references to parameter entities 
in the value of the entity
+     */
+    public int getParamEntityRefCount(String entityName) {
+        if (entityName != null && 
+            entityName.length() > 0 && 
+            entityName.charAt(0) == '%') {
+            final Entity entity = (Entity) fEntities.get(entityName);
+            if (entity != null && !entity.isExternal()) {
+                return ((InternalEntity) entity).paramEntityRefs;
+            }
+        }
+        return 0;
+    } // getParamEntityRefCount(String)
+    
     /**
      * Adds an external entity declaration.
      * <p>
@@ -901,20 +940,23 @@ public class XMLEntityManager
 
         String encoding = setupCurrentEntity(name, xmlInputSource, literal, 
isExternal);
 
-        //when entity expansion limit is set by the Application, we need to
-        //check for the entity expansion limit set by the parser, if number of 
entity
-        //expansions exceeds the entity expansion limit, parser will throw 
fatal error.
+        // when entity expansion limit is set by the Application, we need to
+        // check for the entity expansion limit set by the parser, if number 
of entity
+        // expansions exceeds the entity expansion limit, parser will throw 
fatal error.
         // Note that this is intentionally unbalanced; it counts
         // the number of expansions *per document*.
-        if( fSecurityManager != null && fEntityExpansionCount++ > 
fEntityExpansionLimit ){
-            fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN,
-                                             "EntityExpansionLimitExceeded",
-                                             new Object[]{new 
Integer(fEntityExpansionLimit) },
-                                             
XMLErrorReporter.SEVERITY_FATAL_ERROR );
-            // is there anything better to do than reset the counter?
-            // at least one can envision debugging applications where this 
might
-            // be useful...
-            fEntityExpansionCount = 0;
+        if (fSecurityManager != null) {
+            fEntityExpansionCount += getParamEntityRefCount(name);
+            if (fEntityExpansionCount++ > fEntityExpansionLimit) {
+                fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN,
+                        "EntityExpansionLimitExceeded",
+                        new Object[]{new Integer(fEntityExpansionLimit) },
+                        XMLErrorReporter.SEVERITY_FATAL_ERROR );
+                // is there anything better to do than reset the counter?
+                // at least one can envision debugging applications where this 
might
+                // be useful...
+                fEntityExpansionCount = 0;
+            }
         }
         
         // call handler
@@ -2473,6 +2515,9 @@ public class XMLEntityManager
 
         /** Text value of entity. */
         public String text;
+        
+        /** Count of direct and indirect references to parameter entities in 
the value of the entity. */
+        public int paramEntityRefs;
 
         //
         // Constructors
@@ -2488,6 +2533,12 @@ public class XMLEntityManager
             super(name,inExternalSubset);
             this.text = text;
         } // <init>(String,String)
+        
+        /** Constructs an internal entity. */
+        public InternalEntity(String name, String text, boolean 
inExternalSubset, int paramEntityRefs) {
+            this(name, text, inExternalSubset);
+            this.paramEntityRefs = paramEntityRefs;
+        } // <init>(String,String,int)
 
         //
         // Entity methods



---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to