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]