# HG changeset patch # User aefimov # Date 1467951010 -3600 # Node ID f968b06f80c67c03e8df692467d0411affc5a594 # Parent 023fdb2f8ee2e93a1e48bb12fafc91906f17bd38 8149962: Better delineation of XML processing Reviewed-by: dfuchs, lancea, ahgross diff -r 023fdb2f8ee2 -r f968b06f80c6 src/com/sun/org/apache/xalan/internal/XalanConstants.java --- a/src/com/sun/org/apache/xalan/internal/XalanConstants.java Fri Jul 08 04:17:27 2016 +0100 +++ b/src/com/sun/org/apache/xalan/internal/XalanConstants.java Fri Jul 08 05:10:10 2016 +0100 @@ -81,6 +81,14 @@ */ public static final String JDK_GENEAL_ENTITY_SIZE_LIMIT = ORACLE_JAXP_PROPERTY_PREFIX + "maxGeneralEntitySizeLimit"; + + /** + * JDK node count limit in entities that limits the total number of nodes + * in all of entity references. + */ + public static final String JDK_ENTITY_REPLACEMENT_LIMIT = + ORACLE_JAXP_PROPERTY_PREFIX + "entityReplacementLimit"; + /** * JDK maximum parameter entity size limit */ @@ -137,6 +145,13 @@ * JDK maximum general entity size limit */ public static final String SP_GENEAL_ENTITY_SIZE_LIMIT = "jdk.xml.maxGeneralEntitySizeLimit"; + + /** + * JDK node count limit in entities that limits the total number of nodes + * in all of entity references. + */ + public static final String SP_ENTITY_REPLACEMENT_LIMIT = "jdk.xml.entityReplacementLimit"; + /** * JDK maximum parameter entity size limit */ diff -r 023fdb2f8ee2 -r f968b06f80c6 src/com/sun/org/apache/xalan/internal/utils/XMLSecurityManager.java --- a/src/com/sun/org/apache/xalan/internal/utils/XMLSecurityManager.java Fri Jul 08 04:17:27 2016 +0100 +++ b/src/com/sun/org/apache/xalan/internal/utils/XMLSecurityManager.java Fri Jul 08 05:10:10 2016 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -80,7 +80,9 @@ MAX_ELEMENT_DEPTH_LIMIT("MaxElementDepthLimit", XalanConstants.JDK_MAX_ELEMENT_DEPTH, XalanConstants.SP_MAX_ELEMENT_DEPTH, 0, 0), MAX_NAME_LIMIT("MaxXMLNameLimit", XalanConstants.JDK_XML_NAME_LIMIT, - XalanConstants.SP_XML_NAME_LIMIT, 1000, 1000); + XalanConstants.SP_XML_NAME_LIMIT, 1000, 1000), + ENTITY_REPLACEMENT_LIMIT("EntityReplacementLimit", XalanConstants.JDK_ENTITY_REPLACEMENT_LIMIT, + XalanConstants.SP_ENTITY_REPLACEMENT_LIMIT, 0, 3000000); final String key; final String apiProperty; diff -r 023fdb2f8ee2 -r f968b06f80c6 src/com/sun/org/apache/xerces/internal/impl/Constants.java --- a/src/com/sun/org/apache/xerces/internal/impl/Constants.java Fri Jul 08 04:17:27 2016 +0100 +++ b/src/com/sun/org/apache/xerces/internal/impl/Constants.java Fri Jul 08 05:10:10 2016 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2005, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved. */ /* @@ -242,6 +242,14 @@ */ public static final String JDK_GENEAL_ENTITY_SIZE_LIMIT = ORACLE_JAXP_PROPERTY_PREFIX + "maxGeneralEntitySizeLimit"; + + /** + * JDK node count limit in entities that limits the total number of nodes + * in all of entity references. + */ + public static final String JDK_ENTITY_REPLACEMENT_LIMIT = + ORACLE_JAXP_PROPERTY_PREFIX + "entityReplacementLimit"; + /** * JDK maximum parameter entity size limit */ @@ -295,6 +303,13 @@ * JDK maximum general entity size limit */ public static final String SP_GENEAL_ENTITY_SIZE_LIMIT = "jdk.xml.maxGeneralEntitySizeLimit"; + + /** + * JDK node count limit in entities that limits the total number of nodes + * in all of entity references. + */ + public static final String SP_ENTITY_REPLACEMENT_LIMIT = "jdk.xml.entityReplacementLimit"; + /** * JDK maximum parameter entity size limit */ diff -r 023fdb2f8ee2 -r f968b06f80c6 src/com/sun/org/apache/xerces/internal/impl/XML11DTDScannerImpl.java --- a/src/com/sun/org/apache/xerces/internal/impl/XML11DTDScannerImpl.java Fri Jul 08 04:17:27 2016 +0100 +++ b/src/com/sun/org/apache/xerces/internal/impl/XML11DTDScannerImpl.java Fri Jul 08 05:10:10 2016 +0100 @@ -1,62 +1,21 @@ /* - * reserved comment block - * DO NOT REMOVE OR ALTER! + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. */ /* - * The Apache Software License, Version 1.1 - * - * - * Copyright (c) 1999-2004 The Apache Software Foundation. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * 3. The end-user documentation included with the redistribution, - * if any, must include the following acknowledgment: - * "This product includes software developed by the - * Apache Software Foundation (http://www.apache.org/)." - * Alternately, this acknowledgment may appear in the software itself, - * if and wherever such third-party acknowledgments normally appear. + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at * - * 4. The names "Xerces" and "Apache Software Foundation" must - * not be used to endorse or promote products derived from this - * software without prior written permission. For written - * permission, please contact apache@apache.org. - * - * 5. Products derived from this software may not be called "Apache", - * nor may "Apache" appear in their name, without prior written - * permission of the Apache Software Foundation. + * http://www.apache.org/licenses/LICENSE-2.0 * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR - * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * ==================================================================== - * - * This software consists of voluntary contributions made by many - * individuals on behalf of the Apache Software Foundation and was - * originally based on software copyright (c) 1999, International - * Business Machines, Inc., http://www.apache.org. For more - * information on the Apache Software Foundation, please see - * . + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package com.sun.org.apache.xerces.internal.impl; @@ -156,7 +115,7 @@ protected boolean scanPubidLiteral(XMLString literal) throws IOException, XNIException { - int quote = fEntityScanner.scanChar(); + int quote = fEntityScanner.scanChar(null); if (quote != '\'' && quote != '"') { reportFatalError("QuoteRequiredInPublicID", null); return false; @@ -167,7 +126,7 @@ boolean skipSpace = true; boolean dataok = true; while (true) { - int c = fEntityScanner.scanChar(); + int c = fEntityScanner.scanChar(null); // REVISIT: it could really only be \n or 0x20; all else is normalized, no? - neilg if (c == ' ' || c == '\n' || c == '\r' || c == 0x85 || c == 0x2028) { if (!skipSpace) { diff -r 023fdb2f8ee2 -r f968b06f80c6 src/com/sun/org/apache/xerces/internal/impl/XML11DocumentScannerImpl.java --- a/src/com/sun/org/apache/xerces/internal/impl/XML11DocumentScannerImpl.java Fri Jul 08 04:17:27 2016 +0100 +++ b/src/com/sun/org/apache/xerces/internal/impl/XML11DocumentScannerImpl.java Fri Jul 08 05:10:10 2016 +0100 @@ -1,74 +1,32 @@ /* - * reserved comment block - * DO NOT REMOVE OR ALTER! + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. */ /* - * The Apache Software License, Version 1.1 - * - * - * Copyright (c) 1999-2004 The Apache Software Foundation. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * 3. The end-user documentation included with the redistribution, - * if any, must include the following acknowledgment: - * "This product includes software developed by the - * Apache Software Foundation (http://www.apache.org/)." - * Alternately, this acknowledgment may appear in the software itself, - * if and wherever such third-party acknowledgments normally appear. + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at * - * 4. The names "Xerces" and "Apache Software Foundation" must - * not be used to endorse or promote products derived from this - * software without prior written permission. For written - * permission, please contact apache@apache.org. - * - * 5. Products derived from this software may not be called "Apache", - * nor may "Apache" appear in their name, without prior written - * permission of the Apache Software Foundation. + * http://www.apache.org/licenses/LICENSE-2.0 * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR - * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * ==================================================================== - * - * This software consists of voluntary contributions made by many - * individuals on behalf of the Apache Software Foundation and was - * originally based on software copyright (c) 1999, International - * Business Machines, Inc., http://www.apache.org. For more - * information on the Apache Software Foundation, please see - * . + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package com.sun.org.apache.xerces.internal.impl; -import java.io.IOException; - import com.sun.org.apache.xerces.internal.impl.msg.XMLMessageFormatter; import com.sun.org.apache.xerces.internal.util.XML11Char; import com.sun.org.apache.xerces.internal.util.XMLChar; import com.sun.org.apache.xerces.internal.util.XMLStringBuffer; import com.sun.org.apache.xerces.internal.xni.XMLString; import com.sun.org.apache.xerces.internal.xni.XNIException; +import java.io.IOException; /** * This class is responsible for scanning XML document structure @@ -135,7 +93,7 @@ // happens when there is the character reference // but scanContent doesn't do entity expansions... // is this *really* necessary??? - NG - fEntityScanner.scanChar(); + fEntityScanner.scanChar(null); content.append((char)c); c = -1; } @@ -144,7 +102,7 @@ } */ if (c == ']') { - content.append((char)fEntityScanner.scanChar()); + content.append((char)fEntityScanner.scanChar(null)); // remember where we are in case we get an endEntity before we // could flush the buffer out - this happens when we're parsing an // entity which ends with a ] @@ -153,12 +111,12 @@ // We work on a single character basis to handle cases such as: // ']]]>' which we might otherwise miss. // - if (fEntityScanner.skipChar(']')) { + if (fEntityScanner.skipChar(']', null)) { content.append(']'); - while (fEntityScanner.skipChar(']')) { + while (fEntityScanner.skipChar(']', null)) { content.append(']'); } - if (fEntityScanner.skipChar('>')) { + if (fEntityScanner.skipChar('>', null)) { reportFatalError("CDEndInContent", null); } } @@ -204,7 +162,7 @@ reportFatalError("OpenQuoteExpected", new Object[]{eleName,atName}); } - fEntityScanner.scanChar(); + fEntityScanner.scanChar(NameType.ATTRIBUTE); int entityDepth = fEntityDepth; int c = fEntityScanner.scanLiteral(quote, value, isNSURI); @@ -217,7 +175,7 @@ if (c == quote && (fromIndex = isUnchangedByNormalization(value)) == -1) { /** Both the non-normalized and normalized attribute values are equal. **/ nonNormalizedValue.setValues(value); - int cquote = fEntityScanner.scanChar(); + int cquote = fEntityScanner.scanChar(NameType.ATTRIBUTE); if (cquote != quote) { reportFatalError("CloseQuoteExpected", new Object[]{eleName,atName}); } @@ -240,11 +198,11 @@ + fStringBuffer.toString() + "\""); } if (c == '&') { - fEntityScanner.skipChar('&'); + fEntityScanner.skipChar('&', NameType.REFERENCE); if (entityDepth == fEntityDepth) { fStringBuffer2.append('&'); } - if (fEntityScanner.skipChar('#')) { + if (fEntityScanner.skipChar('#', NameType.REFERENCE)) { if (entityDepth == fEntityDepth) { fStringBuffer2.append('#'); } @@ -258,59 +216,22 @@ } } else { - String entityName = fEntityScanner.scanName(); + String entityName = fEntityScanner.scanName(NameType.REFERENCE); if (entityName == null) { reportFatalError("NameRequiredInReference", null); } else if (entityDepth == fEntityDepth) { fStringBuffer2.append(entityName); } - if (!fEntityScanner.skipChar(';')) { + if (!fEntityScanner.skipChar(';', NameType.REFERENCE)) { reportFatalError("SemicolonRequiredInReference", new Object []{entityName}); } else if (entityDepth == fEntityDepth) { fStringBuffer2.append(';'); } - if (entityName == fAmpSymbol) { - fStringBuffer.append('&'); - if (DEBUG_ATTR_NORMALIZATION) { - System.out.println("** value5: \"" - + fStringBuffer.toString() - + "\""); - } - } - else if (entityName == fAposSymbol) { - fStringBuffer.append('\''); - if (DEBUG_ATTR_NORMALIZATION) { - System.out.println("** value7: \"" - + fStringBuffer.toString() - + "\""); - } - } - else if (entityName == fLtSymbol) { - fStringBuffer.append('<'); - if (DEBUG_ATTR_NORMALIZATION) { - System.out.println("** value9: \"" - + fStringBuffer.toString() - + "\""); - } - } - else if (entityName == fGtSymbol) { - fStringBuffer.append('>'); - if (DEBUG_ATTR_NORMALIZATION) { - System.out.println("** valueB: \"" - + fStringBuffer.toString() - + "\""); - } - } - else if (entityName == fQuotSymbol) { - fStringBuffer.append('"'); - if (DEBUG_ATTR_NORMALIZATION) { - System.out.println("** valueD: \"" - + fStringBuffer.toString() - + "\""); - } + if (resolveCharacter(entityName, fStringBuffer)) { + checkEntityLimit(false, fEntityScanner.fCurrentEntity.name, 1); } else { if (fEntityManager.isExternalEntity(entityName)) { @@ -341,13 +262,13 @@ else if (c == '<') { reportFatalError("LessthanInAttValue", new Object[] { eleName, atName }); - fEntityScanner.scanChar(); + fEntityScanner.scanChar(null); if (entityDepth == fEntityDepth) { fStringBuffer2.append((char)c); } } else if (c == '%' || c == ']') { - fEntityScanner.scanChar(); + fEntityScanner.scanChar(null); fStringBuffer.append((char)c); if (entityDepth == fEntityDepth) { fStringBuffer2.append((char)c); @@ -361,7 +282,7 @@ // XML11EntityScanner. Not sure why // this check was originally necessary. - NG else if (c == '\n' || c == '\r' || c == 0x85 || c == 0x2028) { - fEntityScanner.scanChar(); + fEntityScanner.scanChar(null); fStringBuffer.append(' '); if (entityDepth == fEntityDepth) { fStringBuffer2.append('\n'); @@ -384,7 +305,7 @@ else if (c != -1 && isInvalidLiteral(c)) { reportFatalError("InvalidCharInAttValue", new Object[] {eleName, atName, Integer.toString(c, 16)}); - fEntityScanner.scanChar(); + fEntityScanner.scanChar(null); if (entityDepth == fEntityDepth) { fStringBuffer2.append((char)c); } @@ -406,7 +327,7 @@ nonNormalizedValue.setValues(fStringBuffer2); // quote - int cquote = fEntityScanner.scanChar(); + int cquote = fEntityScanner.scanChar(null); if (cquote != quote) { reportFatalError("CloseQuoteExpected", new Object[]{eleName,atName}); } @@ -441,7 +362,7 @@ protected boolean scanPubidLiteral(XMLString literal) throws IOException, XNIException { - int quote = fEntityScanner.scanChar(); + int quote = fEntityScanner.scanChar(null); if (quote != '\'' && quote != '"') { reportFatalError("QuoteRequiredInPublicID", null); return false; @@ -452,7 +373,7 @@ boolean skipSpace = true; boolean dataok = true; while (true) { - int c = fEntityScanner.scanChar(); + int c = fEntityScanner.scanChar(null); // REVISIT: none of these except \n and 0x20 should make it past the entity scanner if (c == ' ' || c == '\n' || c == '\r' || c == 0x85 || c == 0x2028) { if (!skipSpace) { diff -r 023fdb2f8ee2 -r f968b06f80c6 src/com/sun/org/apache/xerces/internal/impl/XML11EntityScanner.java --- a/src/com/sun/org/apache/xerces/internal/impl/XML11EntityScanner.java Fri Jul 08 04:17:27 2016 +0100 +++ b/src/com/sun/org/apache/xerces/internal/impl/XML11EntityScanner.java Fri Jul 08 05:10:10 2016 +0100 @@ -20,6 +20,7 @@ package com.sun.org.apache.xerces.internal.impl; +import com.sun.org.apache.xerces.internal.impl.XMLScanner.NameType; import com.sun.org.apache.xerces.internal.impl.msg.XMLMessageFormatter; import com.sun.org.apache.xerces.internal.util.XML11Char; import com.sun.org.apache.xerces.internal.util.XMLChar; @@ -93,7 +94,7 @@ * @throws IOException Thrown if i/o error occurs. * @throws EOFException Thrown on end of file. */ - public int scanChar() throws IOException { + protected int scanChar(NameType nt) throws IOException { // load more characters, if needed if (fCurrentEntity.position == fCurrentEntity.count) { @@ -101,6 +102,7 @@ } // scan character + int offset = fCurrentEntity.position; int c = fCurrentEntity.ch[fCurrentEntity.position++]; boolean external = false; if (c == '\n' || @@ -111,6 +113,7 @@ invokeListeners(1); fCurrentEntity.ch[0] = (char)c; load(1, false, false); + offset = 0; } if (c == '\r' && external) { int cc = fCurrentEntity.ch[fCurrentEntity.position++]; @@ -123,6 +126,9 @@ // return character that was scanned fCurrentEntity.columnNumber++; + if (!detectingVersion) { + checkEntityLimit(nt, fCurrentEntity, offset, fCurrentEntity.position - offset); + } return c; } // scanChar():int @@ -142,7 +148,7 @@ * @see com.sun.org.apache.xerces.internal.util.SymbolTable * @see com.sun.org.apache.xerces.internal.util.XML11Char#isXML11Name */ - public String scanNmtoken() throws IOException { + protected String scanNmtoken() throws IOException { // load more characters, if needed if (fCurrentEntity.position == fCurrentEntity.count) { load(0, true, true); @@ -249,6 +255,8 @@ * Note: The string returned must be a symbol. The * SymbolTable can be used for this purpose. * + * @param nt The type of the name (element or attribute) + * * @throws IOException Thrown if i/o error occurs. * @throws EOFException Thrown on end of file. * @@ -256,7 +264,7 @@ * @see com.sun.org.apache.xerces.internal.util.XML11Char#isXML11Name * @see com.sun.org.apache.xerces.internal.util.XML11Char#isXML11NameStart */ - public String scanName() throws IOException { + protected String scanName(NameType nt) throws IOException { // load more characters, if needed if (fCurrentEntity.position == fCurrentEntity.count) { load(0, true, true); @@ -357,6 +365,7 @@ String symbol = null; if (length > 0) { checkLimit(Limit.MAX_NAME_LIMIT, fCurrentEntity, offset, length); + checkEntityLimit(nt, fCurrentEntity, offset, length); symbol = fSymbolTable.addSymbol(fCurrentEntity.ch, offset, length); } return symbol; @@ -379,7 +388,7 @@ * @see com.sun.org.apache.xerces.internal.util.XML11Char#isXML11NCName * @see com.sun.org.apache.xerces.internal.util.XML11Char#isXML11NCNameStart */ - public String scanNCName() throws IOException { + protected String scanNCName() throws IOException { // load more characters, if needed if (fCurrentEntity.position == fCurrentEntity.count) { @@ -535,6 +544,7 @@ * this purpose. * * @param qname The qualified name structure to fill. + * @param nt The type of the name (element or attribute) * * @return Returns true if a qualified name appeared immediately on * the input and was scanned, false otherwise. @@ -546,7 +556,7 @@ * @see com.sun.org.apache.xerces.internal.util.XML11Char#isXML11Name * @see com.sun.org.apache.xerces.internal.util.XML11Char#isXML11NameStart */ - public boolean scanQName(QName qname) throws IOException { + protected boolean scanQName(QName qname, XMLScanner.NameType nt) throws IOException { // load more characters, if needed if (fCurrentEntity.position == fCurrentEntity.count) { @@ -566,6 +576,7 @@ fCurrentEntity.columnNumber++; String name = fSymbolTable.addSymbol(fCurrentEntity.ch, 0, 1); qname.setValues(null, name, name, null); + checkEntityLimit(nt, fCurrentEntity, 0, 1); return true; } } @@ -596,6 +607,7 @@ fCurrentEntity.columnNumber += 2; String name = fSymbolTable.addSymbol(fCurrentEntity.ch, 0, 2); qname.setValues(null, name, name, null); + checkEntityLimit(nt, fCurrentEntity, 0, 2); return true; } } @@ -700,6 +712,7 @@ checkLimit(Limit.MAX_NAME_LIMIT, fCurrentEntity, offset, length); } qname.setValues(prefix, localpart, rawname, null); + checkEntityLimit(nt, fCurrentEntity, offset, length); return true; } return false; @@ -732,7 +745,7 @@ * @throws IOException Thrown if i/o error occurs. * @throws EOFException Thrown on end of file. */ - public int scanContent(XMLString content) throws IOException { + protected int scanContent(XMLString content) throws IOException { // load more characters, if needed if (fCurrentEntity.position == fCurrentEntity.count) { @@ -750,6 +763,7 @@ int offset = fCurrentEntity.position; int c = fCurrentEntity.ch[offset]; int newlines = 0; + boolean counted = false; boolean external = fCurrentEntity.isExternal(); if (c == '\n' || ((c == '\r' || c == 0x85 || c == 0x2028) && external)) { do { @@ -759,11 +773,13 @@ fCurrentEntity.lineNumber++; fCurrentEntity.columnNumber = 1; if (fCurrentEntity.position == fCurrentEntity.count) { + checkEntityLimit(null, fCurrentEntity, offset, newlines); offset = 0; fCurrentEntity.baseCharOffset += (fCurrentEntity.position - fCurrentEntity.startPosition); fCurrentEntity.position = newlines; fCurrentEntity.startPosition = newlines; if (load(newlines, false, true)) { + counted = true; break; } } @@ -782,11 +798,13 @@ fCurrentEntity.lineNumber++; fCurrentEntity.columnNumber = 1; if (fCurrentEntity.position == fCurrentEntity.count) { + checkEntityLimit(null, fCurrentEntity, offset, newlines); offset = 0; fCurrentEntity.baseCharOffset += (fCurrentEntity.position - fCurrentEntity.startPosition); fCurrentEntity.position = newlines; fCurrentEntity.startPosition = newlines; if (load(newlines, false, true)) { + counted = true; break; } } @@ -801,6 +819,7 @@ } int length = fCurrentEntity.position - offset; if (fCurrentEntity.position == fCurrentEntity.count - 1) { + checkEntityLimit(null, fCurrentEntity, offset, length); content.setValues(fCurrentEntity.ch, offset, length); return -1; } @@ -828,8 +847,8 @@ } int length = fCurrentEntity.position - offset; fCurrentEntity.columnNumber += length - newlines; - if (fCurrentEntity.isGE) { - checkLimit(Limit.TOTAL_ENTITY_SIZE_LIMIT, fCurrentEntity, offset, length); + if (!counted) { + checkEntityLimit(null, fCurrentEntity, offset, length); } content.setValues(fCurrentEntity.ch, offset, length); @@ -878,7 +897,7 @@ * @throws IOException Thrown if i/o error occurs. * @throws EOFException Thrown on end of file. */ - public int scanLiteral(int quote, XMLString content, boolean isNSURI) + protected int scanLiteral(int quote, XMLString content, boolean isNSURI) throws IOException { // load more characters, if needed if (fCurrentEntity.position == fCurrentEntity.count) { @@ -976,9 +995,8 @@ } int length = fCurrentEntity.position - offset; fCurrentEntity.columnNumber += length - newlines; - if (fCurrentEntity.isGE) { - checkLimit(Limit.TOTAL_ENTITY_SIZE_LIMIT, fCurrentEntity, offset, length); - } + + checkEntityLimit(null, fCurrentEntity, offset, length); if (isNSURI) { checkLimit(Limit.MAX_NAME_LIMIT, fCurrentEntity, offset, length); } @@ -1031,7 +1049,7 @@ * @throws IOException Thrown if i/o error occurs. * @throws EOFException Thrown on end of file. */ - public boolean scanData(String delimiter, XMLStringBuffer buffer) + protected boolean scanData(String delimiter, XMLStringBuffer buffer) throws IOException { boolean done = false; @@ -1063,6 +1081,7 @@ if (fCurrentEntity.position >= fCurrentEntity.count - delimLen) { // something must be wrong with the input: e.g., file ends an unterminated comment int length = fCurrentEntity.count - fCurrentEntity.position; + checkEntityLimit(NameType.COMMENT, fCurrentEntity, fCurrentEntity.position, length); buffer.append (fCurrentEntity.ch, fCurrentEntity.position, length); fCurrentEntity.columnNumber += fCurrentEntity.count; fCurrentEntity.baseCharOffset += (fCurrentEntity.position - fCurrentEntity.startPosition); @@ -1127,6 +1146,7 @@ } int length = fCurrentEntity.position - offset; if (fCurrentEntity.position == fCurrentEntity.count - 1) { + checkEntityLimit(NameType.COMMENT, fCurrentEntity, offset, length); buffer.append(fCurrentEntity.ch, offset, length); return true; } @@ -1165,6 +1185,7 @@ fCurrentEntity.position--; int length = fCurrentEntity.position - offset; fCurrentEntity.columnNumber += length - newlines; + checkEntityLimit(NameType.COMMENT, fCurrentEntity, offset, length); buffer.append(fCurrentEntity.ch, offset, length); return true; } @@ -1202,6 +1223,7 @@ fCurrentEntity.position--; int length = fCurrentEntity.position - offset; fCurrentEntity.columnNumber += length - newlines; + checkEntityLimit(NameType.COMMENT, fCurrentEntity, offset, length); buffer.append(fCurrentEntity.ch, offset, length); return true; } @@ -1209,6 +1231,7 @@ } int length = fCurrentEntity.position - offset; fCurrentEntity.columnNumber += length - newlines; + checkEntityLimit(NameType.COMMENT, fCurrentEntity, offset, length); if (done) { length -= delimLen; } @@ -1233,7 +1256,7 @@ * @throws IOException Thrown if i/o error occurs. * @throws EOFException Thrown on end of file. */ - public boolean skipChar(int c) throws IOException { + protected boolean skipChar(int c, NameType nt) throws IOException { // load more characters, if needed if (fCurrentEntity.position == fCurrentEntity.count) { @@ -1241,6 +1264,7 @@ } // skip character + int offset = fCurrentEntity.position; int cc = fCurrentEntity.ch[fCurrentEntity.position]; if (cc == c) { fCurrentEntity.position++; @@ -1251,12 +1275,14 @@ else { fCurrentEntity.columnNumber++; } + checkEntityLimit(nt, fCurrentEntity, offset, fCurrentEntity.position - offset); return true; } else if (c == '\n' && ((cc == 0x2028 || cc == 0x85) && fCurrentEntity.isExternal())) { fCurrentEntity.position++; fCurrentEntity.lineNumber++; fCurrentEntity.columnNumber = 1; + checkEntityLimit(nt, fCurrentEntity, offset, fCurrentEntity.position - offset); return true; } else if (c == '\n' && (cc == '\r' ) && fCurrentEntity.isExternal()) { @@ -1272,6 +1298,7 @@ } fCurrentEntity.lineNumber++; fCurrentEntity.columnNumber = 1; + checkEntityLimit(nt, fCurrentEntity, offset, fCurrentEntity.position - offset); return true; } @@ -1294,7 +1321,7 @@ * @see com.sun.org.apache.xerces.internal.util.XMLChar#isSpace * @see com.sun.org.apache.xerces.internal.util.XML11Char#isXML11Space */ - public boolean skipSpaces() throws IOException { + protected boolean skipSpaces() throws IOException { // load more characters, if needed if (fCurrentEntity.position == fCurrentEntity.count) { @@ -1314,7 +1341,7 @@ // skip spaces int c = fCurrentEntity.ch[fCurrentEntity.position]; - + int offset = fCurrentEntity.position - 1; // External -- Match: S + 0x85 + 0x2028, and perform end of line normalization if (fCurrentEntity.isExternal()) { if (XML11Char.isXML11Space(c)) { @@ -1350,6 +1377,11 @@ else { fCurrentEntity.columnNumber++; } + + //If this is a general entity, spaces within a start element should be counted + checkEntityLimit(null, fCurrentEntity, offset, fCurrentEntity.position - offset); + offset = fCurrentEntity.position; + // load more characters, if needed if (!entityChanged) fCurrentEntity.position++; @@ -1389,6 +1421,11 @@ else { fCurrentEntity.columnNumber++; } + + //If this is a general entity, spaces within a start element should be counted + checkEntityLimit(null, fCurrentEntity, offset, fCurrentEntity.position - offset); + offset = fCurrentEntity.position; + // load more characters, if needed if (!entityChanged) fCurrentEntity.position++; @@ -1422,7 +1459,7 @@ * @throws IOException Thrown if i/o error occurs. * @throws EOFException Thrown on end of file. */ - public boolean skipString(String s) throws IOException { + protected boolean skipString(String s) throws IOException { // load more characters, if needed if (fCurrentEntity.position == fCurrentEntity.count) { @@ -1431,6 +1468,7 @@ // skip string final int length = s.length(); + final int beforeSkip = fCurrentEntity.position ; for (int i = 0; i < length; i++) { char c = fCurrentEntity.ch[fCurrentEntity.position++]; if (c != s.charAt(i)) { @@ -1450,6 +1488,9 @@ } } fCurrentEntity.columnNumber += length; + if (!detectingVersion) { + checkEntityLimit(null, fCurrentEntity, beforeSkip, length); + } return true; } // skipString(String):boolean diff -r 023fdb2f8ee2 -r f968b06f80c6 src/com/sun/org/apache/xerces/internal/impl/XML11NSDocumentScannerImpl.java --- a/src/com/sun/org/apache/xerces/internal/impl/XML11NSDocumentScannerImpl.java Fri Jul 08 04:17:27 2016 +0100 +++ b/src/com/sun/org/apache/xerces/internal/impl/XML11NSDocumentScannerImpl.java Fri Jul 08 05:10:10 2016 +0100 @@ -136,7 +136,7 @@ if (DEBUG_START_END_ELEMENT) System.out.println(">>> scanStartElementNS()"); // Note: namespace processing is on by default - fEntityScanner.scanQName(fElementQName); + fEntityScanner.scanQName(fElementQName, NameType.ATTRIBUTE); // REVISIT - [Q] Why do we need this local variable? -- mrglavas String rawname = fElementQName.rawname; if (fBindNamespaces) { @@ -174,11 +174,11 @@ // end tag? int c = fEntityScanner.peekChar(); if (c == '>') { - fEntityScanner.scanChar(); + fEntityScanner.scanChar(null); break; } else if (c == '/') { - fEntityScanner.scanChar(); - if (!fEntityScanner.skipChar('>')) { + fEntityScanner.scanChar(null); + if (!fEntityScanner.skipChar('>', null)) { reportFatalError( "ElementUnterminated", new Object[] { rawname }); @@ -346,7 +346,7 @@ protected void scanStartElementName () throws IOException, XNIException { // Note: namespace processing is on by default - fEntityScanner.scanQName(fElementQName); + fEntityScanner.scanQName(fElementQName, NameType.ATTRIBUTE); // Must skip spaces here because the DTD scanner // would consume them at the end of the external subset. fSawSpace = fEntityScanner.skipSpaces(); @@ -396,11 +396,11 @@ // end tag? int c = fEntityScanner.peekChar(); if (c == '>') { - fEntityScanner.scanChar(); + fEntityScanner.scanChar(null); break; } else if (c == '/') { - fEntityScanner.scanChar(); - if (!fEntityScanner.skipChar('>')) { + fEntityScanner.scanChar(null); + if (!fEntityScanner.skipChar('>', null)) { reportFatalError( "ElementUnterminated", new Object[] { rawname }); @@ -572,11 +572,11 @@ System.out.println(">>> scanAttribute()"); // name - fEntityScanner.scanQName(fAttributeQName); + fEntityScanner.scanQName(fAttributeQName, NameType.ATTRIBUTE); // equals fEntityScanner.skipSpaces(); - if (!fEntityScanner.skipChar('=')) { + if (!fEntityScanner.skipChar('=', NameType.ATTRIBUTE)) { reportFatalError( "EqRequiredInAttribute", new Object[] { @@ -756,7 +756,7 @@ // end fEntityScanner.skipSpaces(); - if (!fEntityScanner.skipChar('>')) { + if (!fEntityScanner.skipChar('>', NameType.ELEMENTEND)) { reportFatalError( "ETagUnterminated", new Object[] { endElementName.rawname }); diff -r 023fdb2f8ee2 -r f968b06f80c6 src/com/sun/org/apache/xerces/internal/impl/XMLDTDScannerImpl.java --- a/src/com/sun/org/apache/xerces/internal/impl/XMLDTDScannerImpl.java Fri Jul 08 04:17:27 2016 +0100 +++ b/src/com/sun/org/apache/xerces/internal/impl/XMLDTDScannerImpl.java Fri Jul 08 05:10:10 2016 +0100 @@ -41,9 +41,6 @@ import com.sun.org.apache.xerces.internal.xni.parser.XMLDTDScanner; import com.sun.org.apache.xerces.internal.xni.parser.XMLInputSource; import com.sun.org.apache.xerces.internal.xni.Augmentations; -import com.sun.org.apache.xerces.internal.impl.XMLErrorReporter; -import com.sun.org.apache.xerces.internal.impl.XMLEntityHandler; -import com.sun.org.apache.xerces.internal.impl.Constants; import com.sun.org.apache.xerces.internal.utils.XMLLimitAnalyzer; import com.sun.org.apache.xerces.internal.utils.XMLSecurityManager; import com.sun.xml.internal.stream.Entity; @@ -370,6 +367,7 @@ // we're done, set starting state for external subset setScannerState(SCANNER_STATE_TEXT_DECL); // we're done scanning DTD. + fLimitAnalyzer.reset(XMLSecurityManager.Limit.GENEAL_ENTITY_SIZE_LIMIT); fLimitAnalyzer.reset(XMLSecurityManager.Limit.TOTAL_ENTITY_SIZE_LIMIT); return false; } @@ -760,7 +758,7 @@ fStringBuffer.clear(); fStringBuffer.append("xml"); while (isValidNameChar(fEntityScanner.peekChar())) { - fStringBuffer.append((char)fEntityScanner.scanChar()); + fStringBuffer.append((char)fEntityScanner.scanChar(null)); } String target = fSymbolTable.addSymbol(fStringBuffer.ch, @@ -860,7 +858,7 @@ } // element name - String name = fEntityScanner.scanName(); + String name = fEntityScanner.scanName(NameType.ELEMENTSTART); if (name == null) { reportFatalError("MSG_ELEMENT_TYPE_REQUIRED_IN_ELEMENTDECL", null); @@ -893,7 +891,7 @@ } } else { - if (!fEntityScanner.skipChar('(')) { + if (!fEntityScanner.skipChar('(', null)) { reportFatalError("MSG_OPEN_PAREN_OR_ELEMENT_TYPE_REQUIRED_IN_CHILDREN", new Object[]{name}); } @@ -923,7 +921,7 @@ fReportEntity = false; skipSeparator(false, !scanningInternalSubset()); // end - if (!fEntityScanner.skipChar('>')) { + if (!fEntityScanner.skipChar('>', null)) { reportFatalError("ElementDeclUnterminated", new Object[]{name}); } fReportEntity = true; @@ -960,7 +958,7 @@ fDTDContentModelHandler.pcdata(null); } skipSeparator(false, !scanningInternalSubset()); - while (fEntityScanner.skipChar('|')) { + while (fEntityScanner.skipChar('|', null)) { fStringBuffer.append('|'); // call handler if (fDTDContentModelHandler != null) { @@ -969,7 +967,7 @@ } skipSeparator(false, !scanningInternalSubset()); - childName = fEntityScanner.scanName(); + childName = fEntityScanner.scanName(NameType.ENTITY); if (childName == null) { reportFatalError("MSG_ELEMENT_TYPE_REQUIRED_IN_MIXED_CONTENT", new Object[]{elName}); @@ -998,7 +996,7 @@ reportFatalError("MixedContentUnterminated", new Object[]{elName}); } - else if (fEntityScanner.skipChar(')')){ + else if (fEntityScanner.skipChar(')', null)){ fStringBuffer.append(')'); // call handler if (fDTDContentModelHandler != null) { @@ -1036,7 +1034,7 @@ int currentOp = 0; int c; while (true) { - if (fEntityScanner.skipChar('(')) { + if (fEntityScanner.skipChar('(', null)) { fMarkUpDepth++; fStringBuffer.append('('); // call handler @@ -1050,7 +1048,7 @@ continue; } skipSeparator(false, !scanningInternalSubset()); - String childName = fEntityScanner.scanName(); + String childName = fEntityScanner.scanName(NameType.ELEMENTSTART); if (childName == null) { reportFatalError("MSG_OPEN_PAREN_OR_ELEMENT_TYPE_REQUIRED_IN_CHILDREN", new Object[]{elName}); @@ -1077,7 +1075,7 @@ } fDTDContentModelHandler.occurrence(oc, null); } - fEntityScanner.scanChar(); + fEntityScanner.scanChar(null); fStringBuffer.append((char)c); } while (true) { @@ -1090,7 +1088,7 @@ fDTDContentModelHandler.separator(XMLDTDContentModelHandler.SEPARATOR_SEQUENCE, null); } - fEntityScanner.scanChar(); + fEntityScanner.scanChar(null); fStringBuffer.append(','); break; } @@ -1101,7 +1099,7 @@ fDTDContentModelHandler.separator(XMLDTDContentModelHandler.SEPARATOR_CHOICE, null); } - fEntityScanner.scanChar(); + fEntityScanner.scanChar(null); fStringBuffer.append('|'); break; } @@ -1147,7 +1145,7 @@ } else { // no occurrence specified - fEntityScanner.scanChar(); + fEntityScanner.scanChar(null); fStringBuffer.append(')'); } fMarkUpDepth--; @@ -1179,7 +1177,7 @@ } // element name - String elName = fEntityScanner.scanName(); + String elName = fEntityScanner.scanName(NameType.ELEMENTSTART); if (elName == null) { reportFatalError("MSG_ELEMENT_TYPE_REQUIRED_IN_ATTLISTDECL", null); @@ -1193,7 +1191,7 @@ // spaces if (!skipSeparator(true, !scanningInternalSubset())) { // no space, is it the end yet? - if (fEntityScanner.skipChar('>')) { + if (fEntityScanner.skipChar('>', null)) { // yes, stop here // call handler if (fDTDHandler != null) { @@ -1209,8 +1207,8 @@ } // definitions - while (!fEntityScanner.skipChar('>')) { - String name = fEntityScanner.scanName(); + while (!fEntityScanner.skipChar('>', null)) { + String name = fEntityScanner.scanName(NameType.ATTRIBUTE); if (name == null) { reportFatalError("AttNameRequiredInAttDef", new Object[]{elName}); @@ -1346,7 +1344,7 @@ new Object[]{elName, atName}); } // open paren - int c = fEntityScanner.scanChar(); + int c = fEntityScanner.scanChar(null); if (c != '(') { reportFatalError("MSG_OPEN_PAREN_REQUIRED_IN_NOTATIONTYPE", new Object[]{elName, atName}); @@ -1354,7 +1352,7 @@ fMarkUpDepth++; do { skipSeparator(false, !scanningInternalSubset()); - String aName = fEntityScanner.scanName(); + String aName = fEntityScanner.scanName(NameType.ATTRIBUTE); if (aName == null) { reportFatalError("MSG_NAME_REQUIRED_IN_NOTATIONTYPE", new Object[]{elName, atName}); @@ -1362,7 +1360,7 @@ ensureEnumerationSize(fEnumerationCount + 1); fEnumeration[fEnumerationCount++] = aName; skipSeparator(false, !scanningInternalSubset()); - c = fEntityScanner.scanChar(); + c = fEntityScanner.scanChar(null); } while (c == '|'); if (c != ')') { reportFatalError("NotationTypeUnterminated", @@ -1373,7 +1371,7 @@ else { // Enumeration type = "ENUMERATION"; // open paren - int c = fEntityScanner.scanChar(); + int c = fEntityScanner.scanChar(null); if (c != '(') { // "OPEN_PAREN_REQUIRED_BEFORE_ENUMERATION_IN_ATTRDECL", reportFatalError("AttTypeRequiredInAttDef", @@ -1390,7 +1388,7 @@ ensureEnumerationSize(fEnumerationCount + 1); fEnumeration[fEnumerationCount++] = token; skipSeparator(false, !scanningInternalSubset()); - c = fEntityScanner.scanChar(); + c = fEntityScanner.scanChar(null); } while (c == '|'); if (c != ')') { reportFatalError("EnumerationUnterminated", @@ -1468,7 +1466,7 @@ boolean sawPERef = false; fReportEntity = false; if (fEntityScanner.skipSpaces()) { - if (!fEntityScanner.skipChar('%')) { + if (!fEntityScanner.skipChar('%', NameType.REFERENCE)) { isPEDecl = false; // } else if (skipSeparator(true, !scanningInternalSubset())) { @@ -1489,7 +1487,7 @@ sawPERef = true; } } - else if (scanningInternalSubset() || !fEntityScanner.skipChar('%')) { + else if (scanningInternalSubset() || !fEntityScanner.skipChar('%', NameType.REFERENCE)) { // or reportFatalError("MSG_SPACE_REQUIRED_BEFORE_ENTITY_NAME_IN_ENTITYDECL", null); @@ -1506,11 +1504,11 @@ } if (sawPERef) { while (true) { - String peName = fEntityScanner.scanName(); + String peName = fEntityScanner.scanName(NameType.REFERENCE); if (peName == null) { reportFatalError("NameRequiredInPEReference", null); } - else if (!fEntityScanner.skipChar(';')) { + else if (!fEntityScanner.skipChar(';', NameType.REFERENCE)) { reportFatalError("SemicolonRequiredInPEReference", new Object[]{peName}); } @@ -1518,20 +1516,20 @@ startPE(peName, false); } fEntityScanner.skipSpaces(); - if (!fEntityScanner.skipChar('%')) + if (!fEntityScanner.skipChar('%', NameType.REFERENCE)) break; if (!isPEDecl) { if (skipSeparator(true, !scanningInternalSubset())) { isPEDecl = true; break; } - isPEDecl = fEntityScanner.skipChar('%'); + isPEDecl = fEntityScanner.skipChar('%', NameType.REFERENCE); } } } // name - String name = fEntityScanner.scanName(); + String name = fEntityScanner.scanName(NameType.ENTITY); if (name == null) { reportFatalError("MSG_ENTITY_NAME_REQUIRED_IN_ENTITYDECL", null); } @@ -1566,7 +1564,7 @@ reportFatalError("MSG_SPACE_REQUIRED_BEFORE_NOTATION_NAME_IN_UNPARSED_ENTITYDECL", new Object[]{name}); } - notation = fEntityScanner.scanName(); + notation = fEntityScanner.scanName(NameType.NOTATION); if (notation == null) { reportFatalError("MSG_NOTATION_NAME_REQUIRED_FOR_UNPARSED_ENTITYDECL", new Object[]{name}); @@ -1588,7 +1586,7 @@ skipSeparator(false, !scanningInternalSubset()); // end - if (!fEntityScanner.skipChar('>')) { + if (!fEntityScanner.skipChar('>', null)) { reportFatalError("EntityDeclUnterminated", new Object[]{name}); } fMarkUpDepth--; @@ -1643,7 +1641,7 @@ protected final void scanEntityValue(String entityName, boolean isPEDecl, XMLString value, XMLString nonNormalizedValue) throws IOException, XNIException { - int quote = fEntityScanner.scanChar(); + int quote = fEntityScanner.scanChar(null); if (quote != '\'' && quote != '"') { reportFatalError("OpenQuoteMissingInDecl", null); } @@ -1661,20 +1659,21 @@ if (fEntityScanner.scanLiteral(quote, fString, false) != quote) { fStringBuffer.clear(); fStringBuffer2.clear(); + int offset; do { - checkEntityLimit(isPEDecl, entityName, fString.length + countChar); countChar = 0; + offset = fStringBuffer.length; fStringBuffer.append(fString); fStringBuffer2.append(fString); - if (fEntityScanner.skipChar('&')) { - if (fEntityScanner.skipChar('#')) { + if (fEntityScanner.skipChar('&', NameType.REFERENCE)) { + if (fEntityScanner.skipChar('#', NameType.REFERENCE)) { fStringBuffer2.append("&#"); scanCharReferenceValue(fStringBuffer, fStringBuffer2); } else { fStringBuffer.append('&'); fStringBuffer2.append('&'); - String eName = fEntityScanner.scanName(); + String eName = fEntityScanner.scanName(NameType.REFERENCE); if (eName == null) { reportFatalError("NameRequiredInReference", null); @@ -1683,7 +1682,7 @@ fStringBuffer.append(eName); fStringBuffer2.append(eName); } - if (!fEntityScanner.skipChar(';')) { + if (!fEntityScanner.skipChar(';', NameType.REFERENCE)) { reportFatalError("SemicolonRequiredInReference", new Object[]{eName}); } @@ -1693,15 +1692,15 @@ } } } - else if (fEntityScanner.skipChar('%')) { + else if (fEntityScanner.skipChar('%', NameType.REFERENCE)) { while (true) { fStringBuffer2.append('%'); - String peName = fEntityScanner.scanName(); + String peName = fEntityScanner.scanName(NameType.REFERENCE); if (peName == null) { reportFatalError("NameRequiredInPEReference", null); } - else if (!fEntityScanner.skipChar(';')) { + else if (!fEntityScanner.skipChar(';', NameType.REFERENCE)) { reportFatalError("SemicolonRequiredInPEReference", new Object[]{peName}); } @@ -1718,20 +1717,20 @@ // REVISIT: This will make returning the non- // normalized value harder. -Ac fEntityScanner.skipSpaces(); - if (!fEntityScanner.skipChar('%')) + if (!fEntityScanner.skipChar('%', NameType.REFERENCE)) break; } } else { - countChar++; int c = fEntityScanner.peekChar(); if (XMLChar.isHighSurrogate(c)) { + countChar++; scanSurrogates(fStringBuffer2); } else if (isInvalidLiteral(c)) { reportFatalError("InvalidCharInLiteral", new Object[]{Integer.toHexString(c)}); - fEntityScanner.scanChar(); + fEntityScanner.scanChar(null); } // if it's not the delimiting quote or if it is but from a // different entity than the one this literal started from, @@ -1739,10 +1738,12 @@ else if (c != quote || entityDepth != fEntityDepth) { fStringBuffer.append((char)c); fStringBuffer2.append((char)c); - fEntityScanner.scanChar(); + fEntityScanner.scanChar(null); } } + checkEntityLimit(isPEDecl, entityName, fStringBuffer.length - offset + countChar); } while (fEntityScanner.scanLiteral(quote, fString, false) != quote); + checkEntityLimit(isPEDecl, entityName, fString.length); fStringBuffer.append(fString); fStringBuffer2.append(fString); literal = fStringBuffer; @@ -1753,10 +1754,14 @@ value.setValues(literal); nonNormalizedValue.setValues(literal2); if (fLimitAnalyzer != null) { - fLimitAnalyzer.endEntity(XMLSecurityManager.Limit.PARAMETER_ENTITY_SIZE_LIMIT, entityName); + if (isPEDecl) { + fLimitAnalyzer.endEntity(XMLSecurityManager.Limit.PARAMETER_ENTITY_SIZE_LIMIT, entityName); + } else { + fLimitAnalyzer.endEntity(XMLSecurityManager.Limit.GENEAL_ENTITY_SIZE_LIMIT, entityName); + } } - if (!fEntityScanner.skipChar(quote)) { + if (!fEntityScanner.skipChar(quote, null)) { reportFatalError("CloseQuoteMissingInDecl", null); } } // scanEntityValue(XMLString,XMLString):void @@ -1781,7 +1786,7 @@ } // notation name - String name = fEntityScanner.scanName(); + String name = fEntityScanner.scanName(NameType.NOTATION); if (name == null) { reportFatalError("MSG_NOTATION_NAME_REQUIRED_IN_NOTATIONDECL", null); @@ -1808,7 +1813,7 @@ skipSeparator(false, !scanningInternalSubset()); // end - if (!fEntityScanner.skipChar('>')) { + if (!fEntityScanner.skipChar('>', null)) { reportFatalError("NotationDeclUnterminated", new Object[]{name}); } fMarkUpDepth--; @@ -1856,7 +1861,7 @@ XMLErrorReporter.SEVERITY_ERROR); } // call handler - if (!fEntityScanner.skipChar('[')) { + if (!fEntityScanner.skipChar('[', null)) { reportFatalError("MSG_MARKUP_NOT_RECOGNIZED_IN_DTD", null); } @@ -1881,7 +1886,7 @@ fDTDHandler.startConditional(XMLDTDHandler.CONDITIONAL_IGNORE, null); } - if (!fEntityScanner.skipChar('[')) { + if (!fEntityScanner.skipChar('[', null)) { reportFatalError("MSG_MARKUP_NOT_RECOGNIZED_IN_DTD", null); } fReportEntity = true; @@ -1890,7 +1895,7 @@ fIgnoreConditionalBuffer.clear(); } while (true) { - if (fEntityScanner.skipChar('<')) { + if (fEntityScanner.skipChar('<', null)) { if (fDTDHandler != null) { fIgnoreConditionalBuffer.append('<'); } @@ -1898,8 +1903,8 @@ // These tests are split so that we handle cases like // '<', etc. // - if (fEntityScanner.skipChar(']')) { + if (fEntityScanner.skipChar(']', null)) { if (fDTDHandler != null) { fIgnoreConditionalBuffer.append(']'); } - while (fEntityScanner.skipChar(']')) { + while (fEntityScanner.skipChar(']', null)) { /* empty loop body */ if (fDTDHandler != null) { fIgnoreConditionalBuffer.append(']'); } } - if (fEntityScanner.skipChar('>')) { + if (fEntityScanner.skipChar('>', null)) { if (fIncludeSectDepth-- == initialDepth) { fMarkUpDepth--; // call handler @@ -1946,7 +1951,7 @@ } } else { - int c = fEntityScanner.scanChar(); + int c = fEntityScanner.scanChar(null); if (fScannerState == SCANNER_STATE_END_OF_INPUT) { reportFatalError("IgnoreSectUnterminated", null); return; @@ -1983,16 +1988,16 @@ //System.out.println("scanDecls"+fScannerState); while (again && fScannerState == SCANNER_STATE_MARKUP_DECL) { again = complete; - if (fEntityScanner.skipChar('<')) { + if (fEntityScanner.skipChar('<', null)) { fMarkUpDepth++; - if (fEntityScanner.skipChar('?')) { + if (fEntityScanner.skipChar('?', null)) { fStringBuffer.clear(); scanPI(fStringBuffer); fMarkUpDepth--; // we're done with this decl } - else if (fEntityScanner.skipChar('!')) { - if (fEntityScanner.skipChar('-')) { - if (!fEntityScanner.skipChar('-')) { + else if (fEntityScanner.skipChar('!', null)) { + if (fEntityScanner.skipChar('-', null)) { + if (!fEntityScanner.skipChar('-', null)) { reportFatalError("MSG_MARKUP_NOT_RECOGNIZED_IN_DTD", null); } else { @@ -2011,7 +2016,7 @@ else if (fEntityScanner.skipString("NOTATION")) { scanNotationDecl(); } - else if (fEntityScanner.skipChar('[') && + else if (fEntityScanner.skipChar('[', null) && !scanningInternalSubset()) { scanConditionalSect(fPEDepth); } @@ -2026,10 +2031,10 @@ reportFatalError("MSG_MARKUP_NOT_RECOGNIZED_IN_DTD", null); } } - else if (fIncludeSectDepth > 0 && fEntityScanner.skipChar(']')) { + else if (fIncludeSectDepth > 0 && fEntityScanner.skipChar(']', null)) { // end of conditional section? - if (!fEntityScanner.skipChar(']') - || !fEntityScanner.skipChar('>')) { + if (!fEntityScanner.skipChar(']', null) + || !fEntityScanner.skipChar('>', null)) { reportFatalError("IncludeSectUnterminated", null); } // call handler @@ -2076,21 +2081,21 @@ throws IOException, XNIException { int depth = fPEDepth; boolean sawSpace = fEntityScanner.skipSpaces(); - if (!lookForPERefs || !fEntityScanner.skipChar('%')) { + if (!lookForPERefs || !fEntityScanner.skipChar('%', NameType.REFERENCE)) { return !spaceRequired || sawSpace || (depth != fPEDepth); } while (true) { - String name = fEntityScanner.scanName(); + String name = fEntityScanner.scanName(NameType.ENTITY); if (name == null) { reportFatalError("NameRequiredInPEReference", null); } - else if (!fEntityScanner.skipChar(';')) { + else if (!fEntityScanner.skipChar(';', NameType.REFERENCE)) { reportFatalError("SemicolonRequiredInPEReference", new Object[]{name}); } startPE(name, false); fEntityScanner.skipSpaces(); - if (!fEntityScanner.skipChar('%')) + if (!fEntityScanner.skipChar('%', NameType.REFERENCE)) return true; } } @@ -2174,56 +2179,6 @@ fSecurityManager = fEntityManager.fSecurityManager; } - /** - * Add the count of the content buffer and check if the accumulated - * value exceeds the limit - * @param isPEDecl a flag to indicate whether the entity is parameter - * @param entityName entity name - * @param buffer content buffer - */ - private void checkEntityLimit(boolean isPEDecl, String entityName, XMLString buffer) { - checkEntityLimit(isPEDecl, entityName, buffer.length); - } - - /** - * Add the count and check limit - * @param isPEDecl a flag to indicate whether the entity is parameter - * @param entityName entity name - * @param len length of the buffer - */ - private void checkEntityLimit(boolean isPEDecl, String entityName, int len) { - if (fLimitAnalyzer == null) { - fLimitAnalyzer = fEntityManager.fLimitAnalyzer; - } - if (isPEDecl) { - fLimitAnalyzer.addValue(XMLSecurityManager.Limit.PARAMETER_ENTITY_SIZE_LIMIT, "%" + entityName, len); - if (fSecurityManager.isOverLimit(XMLSecurityManager.Limit.PARAMETER_ENTITY_SIZE_LIMIT, fLimitAnalyzer)) { - fSecurityManager.debugPrint(fLimitAnalyzer); - reportFatalError("MaxEntitySizeLimit", new Object[]{"%" + entityName, - fLimitAnalyzer.getValue(XMLSecurityManager.Limit.PARAMETER_ENTITY_SIZE_LIMIT), - fSecurityManager.getLimit(XMLSecurityManager.Limit.PARAMETER_ENTITY_SIZE_LIMIT), - fSecurityManager.getStateLiteral(XMLSecurityManager.Limit.PARAMETER_ENTITY_SIZE_LIMIT)}); - } - } else { - fLimitAnalyzer.addValue(XMLSecurityManager.Limit.GENEAL_ENTITY_SIZE_LIMIT, entityName, len); - if (fSecurityManager.isOverLimit(XMLSecurityManager.Limit.GENEAL_ENTITY_SIZE_LIMIT, fLimitAnalyzer)) { - fSecurityManager.debugPrint(fLimitAnalyzer); - reportFatalError("MaxEntitySizeLimit", new Object[]{entityName, - fLimitAnalyzer.getValue(XMLSecurityManager.Limit.GENEAL_ENTITY_SIZE_LIMIT), - fSecurityManager.getLimit(XMLSecurityManager.Limit.GENEAL_ENTITY_SIZE_LIMIT), - fSecurityManager.getStateLiteral(XMLSecurityManager.Limit.GENEAL_ENTITY_SIZE_LIMIT)}); - } - } - if (fSecurityManager.isOverLimit(XMLSecurityManager.Limit.TOTAL_ENTITY_SIZE_LIMIT, fLimitAnalyzer)) { - fSecurityManager.debugPrint(fLimitAnalyzer); - reportFatalError("TotalEntitySizeLimit", - new Object[]{fLimitAnalyzer.getTotalValue(XMLSecurityManager.Limit.TOTAL_ENTITY_SIZE_LIMIT), - fSecurityManager.getLimit(XMLSecurityManager.Limit.TOTAL_ENTITY_SIZE_LIMIT), - fSecurityManager.getStateLiteral(XMLSecurityManager.Limit.TOTAL_ENTITY_SIZE_LIMIT)}); - } - - } - public DTDGrammar getGrammar(){ return nvGrammarInfo; } diff -r 023fdb2f8ee2 -r f968b06f80c6 src/com/sun/org/apache/xerces/internal/impl/XMLDocumentFragmentScannerImpl.java --- a/src/com/sun/org/apache/xerces/internal/impl/XMLDocumentFragmentScannerImpl.java Fri Jul 08 04:17:27 2016 +0100 +++ b/src/com/sun/org/apache/xerces/internal/impl/XMLDocumentFragmentScannerImpl.java Fri Jul 08 05:10:10 2016 +0100 @@ -21,21 +21,17 @@ package com.sun.org.apache.xerces.internal.impl; -import com.sun.xml.internal.stream.XMLBufferListener; -import com.sun.xml.internal.stream.XMLEntityStorage; -import com.sun.xml.internal.stream.XMLInputFactoryImpl; -import com.sun.xml.internal.stream.dtd.DTDGrammarUtil; - -import java.io.EOFException; -import java.io.IOException; -import javax.xml.stream.XMLInputFactory; -import javax.xml.stream.events.XMLEvent; import com.sun.org.apache.xerces.internal.impl.msg.XMLMessageFormatter; import com.sun.org.apache.xerces.internal.util.AugmentationsImpl; import com.sun.org.apache.xerces.internal.util.XMLAttributesIteratorImpl; import com.sun.org.apache.xerces.internal.util.XMLChar; import com.sun.org.apache.xerces.internal.util.XMLStringBuffer; import com.sun.org.apache.xerces.internal.util.XMLSymbols; +import com.sun.org.apache.xerces.internal.utils.SecuritySupport; +import com.sun.org.apache.xerces.internal.utils.XMLSecurityManager; +import com.sun.org.apache.xerces.internal.utils.XMLSecurityManager.Limit; +import com.sun.org.apache.xerces.internal.utils.XMLSecurityPropertyManager; +import com.sun.org.apache.xerces.internal.xni.Augmentations; import com.sun.org.apache.xerces.internal.xni.QName; import com.sun.org.apache.xerces.internal.xni.XMLAttributes; import com.sun.org.apache.xerces.internal.xni.XMLDocumentHandler; @@ -47,18 +43,12 @@ import com.sun.org.apache.xerces.internal.xni.parser.XMLConfigurationException; import com.sun.org.apache.xerces.internal.xni.parser.XMLDocumentScanner; import com.sun.org.apache.xerces.internal.xni.parser.XMLInputSource; -import com.sun.org.apache.xerces.internal.xni.Augmentations; -import com.sun.org.apache.xerces.internal.impl.Constants; -import com.sun.org.apache.xerces.internal.impl.XMLEntityHandler; -import com.sun.org.apache.xerces.internal.util.NamespaceSupport; -import com.sun.org.apache.xerces.internal.utils.SecuritySupport; -import com.sun.org.apache.xerces.internal.utils.XMLLimitAnalyzer; -import com.sun.org.apache.xerces.internal.utils.XMLSecurityManager; -import com.sun.org.apache.xerces.internal.utils.XMLSecurityManager.Limit; -import com.sun.org.apache.xerces.internal.utils.XMLSecurityManager.State; -import com.sun.org.apache.xerces.internal.utils.XMLSecurityPropertyManager; -import com.sun.org.apache.xerces.internal.xni.NamespaceContext; -import javax.xml.XMLConstants; +import com.sun.xml.internal.stream.XMLBufferListener; +import com.sun.xml.internal.stream.XMLEntityStorage; +import com.sun.xml.internal.stream.dtd.DTDGrammarUtil; +import java.io.EOFException; +import java.io.IOException; +import javax.xml.stream.XMLInputFactory; import javax.xml.stream.XMLStreamConstants; import javax.xml.stream.events.XMLEvent; @@ -460,6 +450,7 @@ //fDocumentHandler.startElement(getElementQName(),fAttributes,null); break; case XMLStreamConstants.CHARACTERS : + fEntityScanner.checkNodeCount(fEntityScanner.fCurrentEntity); fDocumentHandler.characters(getCharacterData(),null); break; case XMLStreamConstants.SPACE: @@ -468,13 +459,15 @@ //fDocumentHandler.ignorableWhitespace(getCharacterData(), null); break; case XMLStreamConstants.ENTITY_REFERENCE : + fEntityScanner.checkNodeCount(fEntityScanner.fCurrentEntity); //entity reference callback are given in startEntity break; case XMLStreamConstants.PROCESSING_INSTRUCTION : + fEntityScanner.checkNodeCount(fEntityScanner.fCurrentEntity); fDocumentHandler.processingInstruction(getPITarget(),getPIData(),null); break; case XMLStreamConstants.COMMENT : - //System.out.println(" in COMMENT of the XMLNSDocumentScannerImpl"); + fEntityScanner.checkNodeCount(fEntityScanner.fCurrentEntity); fDocumentHandler.comment(getCharacterData(),null); break; case XMLStreamConstants.DTD : @@ -483,6 +476,7 @@ //therefore we don't need to take care of anything here. So Just break; break; case XMLStreamConstants.CDATA: + fEntityScanner.checkNodeCount(fEntityScanner.fCurrentEntity); fDocumentHandler.startCDATA(null); //xxx: check if CDATA values comes from getCharacterData() function fDocumentHandler.characters(getCharacterData(),null); @@ -1279,9 +1273,9 @@ fElementQName = fElementStack.nextElement(); // name if (fNamespaces) { - fEntityScanner.scanQName(fElementQName); + fEntityScanner.scanQName(fElementQName, NameType.ELEMENTSTART); } else { - String name = fEntityScanner.scanName(); + String name = fEntityScanner.scanName(NameType.ELEMENTSTART); fElementQName.setValues(null, name, name, null); } @@ -1382,11 +1376,11 @@ // end tag? final int c = fEntityScanner.peekChar(); if (c == '>') { - fEntityScanner.scanChar(); + fEntityScanner.scanChar(null); return true; } else if (c == '/') { - fEntityScanner.scanChar(); - if (!fEntityScanner.skipChar('>')) { + fEntityScanner.scanChar(null); + if (!fEntityScanner.skipChar('>', NameType.ELEMENTEND)) { reportFatalError("ElementUnterminated", new Object[]{fElementQName.rawname}); } @@ -1519,15 +1513,15 @@ // name if (fNamespaces) { - fEntityScanner.scanQName(fAttributeQName); + fEntityScanner.scanQName(fAttributeQName, NameType.ATTRIBUTENAME); } else { - String name = fEntityScanner.scanName(); + String name = fEntityScanner.scanName(NameType.ATTRIBUTENAME); fAttributeQName.setValues(null, name, name, null); } // equals fEntityScanner.skipSpaces(); - if (!fEntityScanner.skipChar('=')) { + if (!fEntityScanner.skipChar('=', NameType.ATTRIBUTE)) { reportFatalError("EqRequiredInAttribute", new Object[] {fCurrentElement.rawname, fAttributeQName.rawname}); } @@ -1594,13 +1588,13 @@ if (c == '\r') { // happens when there is the character reference //xxx: We know the next chracter.. we should just skip it and add ']' directlry - fEntityScanner.scanChar(); + fEntityScanner.scanChar(null); content.append((char)c); c = -1; } else if (c == ']') { //fStringBuffer.clear(); //xxx: We know the next chracter.. we should just skip it and add ']' directlry - content.append((char)fEntityScanner.scanChar()); + content.append((char)fEntityScanner.scanChar(null)); // remember where we are in case we get an endEntity before we // could flush the buffer out - this happens when we're parsing an // entity which ends with a ] @@ -1609,12 +1603,12 @@ // We work on a single character basis to handle cases such as: // ']]]>' which we might otherwise miss. // - if (fEntityScanner.skipChar(']')) { + if (fEntityScanner.skipChar(']', null)) { content.append(']'); - while (fEntityScanner.skipChar(']')) { + while (fEntityScanner.skipChar(']', null)) { content.append(']'); } - if (fEntityScanner.skipChar('>')) { + if (fEntityScanner.skipChar('>', null)) { reportFatalError("CDEndInContent", null); } } @@ -1689,7 +1683,7 @@ } else { reportFatalError("InvalidCharInCDSect", new Object[]{Integer.toString(c,16)}); - fEntityScanner.scanChar(); + fEntityScanner.scanChar(null); } } //by this time we have also read surrogate contents if any... @@ -1751,7 +1745,7 @@ // end fEntityScanner.skipSpaces(); - if (!fEntityScanner.skipChar('>')) { + if (!fEntityScanner.skipChar('>', NameType.ELEMENTEND)) { reportFatalError("ETagUnterminated", new Object[]{rawname}); } @@ -1841,12 +1835,12 @@ * notification. */ protected void scanEntityReference(XMLStringBuffer content) throws IOException, XNIException { - String name = fEntityScanner.scanName(); + String name = fEntityScanner.scanName(NameType.REFERENCE); if (name == null) { reportFatalError("NameRequiredInReference", null); return; } - if (!fEntityScanner.skipChar(';')) { + if (!fEntityScanner.skipChar(';', NameType.REFERENCE)) { reportFatalError("SemicolonRequiredInReference", new Object []{name}); } if (fEntityStore.isUnparsedEntity(name)) { @@ -1943,6 +1937,7 @@ */ private void handleCharacter(char c, String entity, XMLStringBuffer content) throws XNIException { foundBuiltInRefs = true; + checkEntityLimit(false, fEntityScanner.fCurrentEntity.name, 1); content.append(c); if (fDocumentHandler != null) { fSingleChar[0] = c; @@ -2605,13 +2600,13 @@ switch(ch){ case '?' :{ setScannerState(SCANNER_STATE_PI); - fEntityScanner.skipChar(ch); + fEntityScanner.skipChar(ch, null); break; } case '!' :{ - fEntityScanner.skipChar(ch); - if (fEntityScanner.skipChar('-')) { - if (!fEntityScanner.skipChar('-')) { + fEntityScanner.skipChar(ch, null); + if (fEntityScanner.skipChar('-', null)) { + if (!fEntityScanner.skipChar('-', NameType.COMMENT)) { reportFatalError("InvalidCommentStart", null); } @@ -2626,7 +2621,7 @@ } case '/' :{ setScannerState(SCANNER_STATE_END_ELEMENT_TAG); - fEntityScanner.skipChar(ch); + fEntityScanner.skipChar(ch, NameType.ELEMENTEND); break; } default :{ @@ -2642,9 +2637,9 @@ }//startOfMarkup private void startOfContent() throws IOException { - if (fEntityScanner.skipChar('<')) { + if (fEntityScanner.skipChar('<', null)) { setScannerState(SCANNER_STATE_START_OF_MARKUP); - } else if (fEntityScanner.skipChar('&')) { + } else if (fEntityScanner.skipChar('&', NameType.REFERENCE)) { setScannerState(SCANNER_STATE_REFERENCE) ; //XMLEvent.ENTITY_REFERENCE ); //SCANNER_STATE_REFERENCE } else { //element content is there.. @@ -2717,10 +2712,10 @@ case SCANNER_STATE_CONTENT: { final int ch = fEntityScanner.peekChar(); if (ch == '<') { - fEntityScanner.scanChar(); + fEntityScanner.scanChar(null); setScannerState(SCANNER_STATE_START_OF_MARKUP); } else if (ch == '&') { - fEntityScanner.scanChar(); + fEntityScanner.scanChar(NameType.REFERENCE); setScannerState(SCANNER_STATE_REFERENCE) ; //XMLEvent.ENTITY_REFERENCE ); //SCANNER_STATE_REFERENCE break; } else { @@ -2820,9 +2815,9 @@ if(DEBUG){ System.out.println("fTempString = " + fTempString); } - if(fEntityScanner.skipChar('<')){ + if(fEntityScanner.skipChar('<', null)){ //check if we have reached end of element - if(fEntityScanner.skipChar('/')){ + if(fEntityScanner.skipChar('/', NameType.ELEMENTEND)){ //increase the mark up depth fMarkupDepth++; fLastSectionWasCharacterData = false; @@ -2872,7 +2867,7 @@ } // happens when there is the character reference //xxx: We know the next chracter.. we should just skip it and add ']' directlry - fEntityScanner.scanChar(); + fEntityScanner.scanChar(null); fUsebuffer = true; fContentBuffer.append((char)c); c = -1 ; @@ -2880,7 +2875,7 @@ //fStringBuffer.clear(); //xxx: We know the next chracter.. we should just skip it and add ']' directlry fUsebuffer = true; - fContentBuffer.append((char)fEntityScanner.scanChar()); + fContentBuffer.append((char)fEntityScanner.scanChar(null)); // remember where we are in case we get an endEntity before we // could flush the buffer out - this happens when we're parsing an // entity which ends with a ] @@ -2889,12 +2884,12 @@ // We work on a single character basis to handle cases such as: // ']]]>' which we might otherwise miss. // - if (fEntityScanner.skipChar(']')) { + if (fEntityScanner.skipChar(']', null)) { fContentBuffer.append(']'); - while (fEntityScanner.skipChar(']')) { + while (fEntityScanner.skipChar(']', null)) { fContentBuffer.append(']'); } - if (fEntityScanner.skipChar('>')) { + if (fEntityScanner.skipChar('>', null)) { reportFatalError("CDEndInContent", null); } } @@ -2907,12 +2902,12 @@ // we need not to grow the buffer only when isCoalesce() is not true; if (c == '<') { - fEntityScanner.scanChar(); + fEntityScanner.scanChar(null); setScannerState(SCANNER_STATE_START_OF_MARKUP); break; }//xxx what should be the behavior if entity reference is present in the content ? else if (c == '&') { - fEntityScanner.scanChar(); + fEntityScanner.scanChar(NameType.REFERENCE); setScannerState(SCANNER_STATE_REFERENCE); break; }///xxx since this part is also characters, it should be merged... @@ -2925,7 +2920,7 @@ reportFatalError("InvalidCharInContent", new Object[] { Integer.toString(c, 16)}); - fEntityScanner.scanChar(); + fEntityScanner.scanChar(null); } break; } @@ -3051,7 +3046,7 @@ } fUsebuffer = true ; //take care of character reference - if (fEntityScanner.skipChar('#')) { + if (fEntityScanner.skipChar('#', NameType.REFERENCE)) { scanCharReferenceValue(fContentBuffer, null); fMarkupDepth--; if(!fIsCoalesce){ @@ -3102,11 +3097,11 @@ if (fNamespaces) { while (isValidNCName(fEntityScanner.peekChar())) { - fStringBuffer.append((char)fEntityScanner.scanChar()); + fStringBuffer.append((char)fEntityScanner.scanChar(null)); } } else { while (isValidNameChar(fEntityScanner.peekChar())) { - fStringBuffer.append((char)fEntityScanner.scanChar()); + fStringBuffer.append((char)fEntityScanner.scanChar(null)); } } String target = fSymbolTable.addSymbol(fStringBuffer.ch, fStringBuffer.offset, fStringBuffer.length); diff -r 023fdb2f8ee2 -r f968b06f80c6 src/com/sun/org/apache/xerces/internal/impl/XMLDocumentScannerImpl.java --- a/src/com/sun/org/apache/xerces/internal/impl/XMLDocumentScannerImpl.java Fri Jul 08 04:17:27 2016 +0100 +++ b/src/com/sun/org/apache/xerces/internal/impl/XMLDocumentScannerImpl.java Fri Jul 08 05:10:10 2016 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved. */ /* @@ -636,7 +636,7 @@ } // root element name - fDoctypeName = fEntityScanner.scanName(); + fDoctypeName = fEntityScanner.scanName(NameType.DOCTYPE); if (fDoctypeName == null) { reportFatalError("MSG_ROOT_ELEMENT_TYPE_REQUIRED", null); } @@ -676,10 +676,10 @@ // is there an internal subset? boolean internalSubset = true; - if (!fEntityScanner.skipChar('[')) { + if (!fEntityScanner.skipChar('[', null)) { internalSubset = false; fEntityScanner.skipSpaces(); - if (!fEntityScanner.skipChar('>')) { + if (!fEntityScanner.skipChar('>', null)) { reportFatalError("DoctypedeclUnterminated", new Object[]{fDoctypeName}); } fMarkupDepth--; @@ -758,7 +758,7 @@ fStringBuffer.clear(); fStringBuffer.append("xml"); while (XMLChar.isName(fEntityScanner.peekChar())) { - fStringBuffer.append((char)fEntityScanner.scanChar()); + fStringBuffer.append((char)fEntityScanner.scanChar(null)); } String target = fSymbolTable.addSymbol(fStringBuffer.ch, fStringBuffer.offset, fStringBuffer.length); //this function should fill the data.. and set the fEvent object to this event. @@ -836,9 +836,9 @@ switch (fScannerState) { case SCANNER_STATE_PROLOG: { fEntityScanner.skipSpaces(); - if (fEntityScanner.skipChar('<')) { + if (fEntityScanner.skipChar('<', null)) { setScannerState(SCANNER_STATE_START_OF_MARKUP); - } else if (fEntityScanner.skipChar('&')) { + } else if (fEntityScanner.skipChar('&', NameType.REFERENCE)) { setScannerState(SCANNER_STATE_REFERENCE); } else { setScannerState(SCANNER_STATE_CONTENT); @@ -849,11 +849,11 @@ case SCANNER_STATE_START_OF_MARKUP: { fMarkupDepth++; - if (fEntityScanner.skipChar('?')) { + if (fEntityScanner.skipChar('?', null)) { setScannerState(SCANNER_STATE_PI); - } else if (fEntityScanner.skipChar('!')) { - if (fEntityScanner.skipChar('-')) { - if (!fEntityScanner.skipChar('-')) { + } else if (fEntityScanner.skipChar('!', null)) { + if (fEntityScanner.skipChar('-', null)) { + if (!fEntityScanner.skipChar('-', null)) { reportFatalError("InvalidCommentStart", null); } @@ -997,7 +997,7 @@ case SCANNER_STATE_CONTENT: { reportFatalError("ContentIllegalInProlog", null); - fEntityScanner.scanChar(); + fEntityScanner.scanChar(null); } case SCANNER_STATE_REFERENCE: { reportFatalError("ReferenceIllegalInProlog", null); @@ -1111,12 +1111,12 @@ fReadingDTD=false; if (!moreToScan) { // end doctype declaration - if (!fEntityScanner.skipChar(']')) { + if (!fEntityScanner.skipChar(']', null)) { reportFatalError("EXPECTED_SQUARE_BRACKET_TO_CLOSE_INTERNAL_SUBSET", null); } fEntityScanner.skipSpaces(); - if (!fEntityScanner.skipChar('>')) { + if (!fEntityScanner.skipChar('>', null)) { reportFatalError("DoctypedeclUnterminated", new Object[]{fDoctypeName}); } fMarkupDepth--; @@ -1380,7 +1380,7 @@ if(fScannerState == SCANNER_STATE_TERMINATED ){ return XMLEvent.END_DOCUMENT ; } - if (fEntityScanner.skipChar('<')) { + if (fEntityScanner.skipChar('<', null)) { setScannerState(SCANNER_STATE_START_OF_MARKUP); } else { setScannerState(SCANNER_STATE_CONTENT); @@ -1389,11 +1389,11 @@ } case SCANNER_STATE_START_OF_MARKUP: { fMarkupDepth++; - if (fEntityScanner.skipChar('?')) { + if (fEntityScanner.skipChar('?', null)) { setScannerState(SCANNER_STATE_PI); - } else if (fEntityScanner.skipChar('!')) { + } else if (fEntityScanner.skipChar('!', null)) { setScannerState(SCANNER_STATE_COMMENT); - } else if (fEntityScanner.skipChar('/')) { + } else if (fEntityScanner.skipChar('/', null)) { reportFatalError("MarkupNotRecognizedInMisc", null); } else if (XMLChar.isNameStart(fEntityScanner.peekChar())) { @@ -1435,7 +1435,7 @@ } else{ reportFatalError("ContentIllegalInTrailingMisc", null); - fEntityScanner.scanChar(); + fEntityScanner.scanChar(null); setScannerState(SCANNER_STATE_TRAILING_MISC); return XMLEvent.CHARACTERS; } diff -r 023fdb2f8ee2 -r f968b06f80c6 src/com/sun/org/apache/xerces/internal/impl/XMLEntityScanner.java --- a/src/com/sun/org/apache/xerces/internal/impl/XMLEntityScanner.java Fri Jul 08 04:17:27 2016 +0100 +++ b/src/com/sun/org/apache/xerces/internal/impl/XMLEntityScanner.java Fri Jul 08 05:10:10 2016 +0100 @@ -21,6 +21,7 @@ package com.sun.org.apache.xerces.internal.impl; +import com.sun.org.apache.xerces.internal.impl.XMLScanner.NameType; import com.sun.org.apache.xerces.internal.impl.io.ASCIIReader; import com.sun.org.apache.xerces.internal.impl.io.UCSReader; import com.sun.org.apache.xerces.internal.impl.io.UTF8Reader; @@ -142,6 +143,10 @@ // SAPJVM: Remember, that the XML version has explicitly been set, // so that XMLStreamReader.getVersion() can find that out. boolean xmlVersionSetExplicitly = false; + + // indicates that the operation is for detecting XML version + boolean detectingVersion = false; + // // Constructors // @@ -528,10 +533,12 @@ *

* Note: The character is consumed. * + * @param nt The type of the name (element or attribute) + * * @throws IOException Thrown if i/o error occurs. * @throws EOFException Thrown on end of file. */ - public int scanChar() throws IOException { + protected int scanChar(NameType nt) throws IOException { if (DEBUG_BUFFER) { System.out.print("(scanChar: "); print(); @@ -544,6 +551,7 @@ } // scan character + int offset = fCurrentEntity.position; int c = fCurrentEntity.ch[fCurrentEntity.position++]; if (c == '\n' || (c == '\r' && isExternal)) { @@ -553,6 +561,7 @@ invokeListeners(1); fCurrentEntity.ch[0] = (char)c; load(1, false, false); + offset = 0; } if (c == '\r' && isExternal) { if (fCurrentEntity.ch[fCurrentEntity.position++] != '\n') { @@ -569,6 +578,9 @@ System.out.println(" -> '"+(char)c+"'"); } fCurrentEntity.columnNumber++; + if (!detectingVersion) { + checkEntityLimit(nt, fCurrentEntity, offset, fCurrentEntity.position - offset); + } return c; } // scanChar():int @@ -588,7 +600,7 @@ * @see com.sun.org.apache.xerces.internal.util.SymbolTable * @see com.sun.org.apache.xerces.internal.util.XMLChar#isName */ - public String scanNmtoken() throws IOException { + protected String scanNmtoken() throws IOException { if (DEBUG_BUFFER) { System.out.print("(scanNmtoken: "); print(); @@ -660,6 +672,8 @@ * Note: The string returned must be a symbol. The * SymbolTable can be used for this purpose. * + * @param nt The type of the name (element or attribute) + * * @throws IOException Thrown if i/o error occurs. * @throws EOFException Thrown on end of file. * @@ -667,7 +681,7 @@ * @see com.sun.org.apache.xerces.internal.util.XMLChar#isName * @see com.sun.org.apache.xerces.internal.util.XMLChar#isNameStart */ - public String scanName() throws IOException { + protected String scanName(NameType nt) throws IOException { if (DEBUG_BUFFER) { System.out.print("(scanName: "); print(); @@ -724,6 +738,7 @@ String symbol; if (length > 0) { checkLimit(Limit.MAX_NAME_LIMIT, fCurrentEntity, offset, length); + checkEntityLimit(nt, fCurrentEntity, offset, length); symbol = fSymbolTable.addSymbol(fCurrentEntity.ch, offset, length); } else symbol = null; @@ -747,6 +762,7 @@ * this purpose. * * @param qname The qualified name structure to fill. + * @param nt The type of the name (element or attribute) * * @return Returns true if a qualified name appeared immediately on * the input and was scanned, false otherwise. @@ -758,7 +774,7 @@ * @see com.sun.org.apache.xerces.internal.util.XMLChar#isName * @see com.sun.org.apache.xerces.internal.util.XMLChar#isNameStart */ - public boolean scanQName(QName qname) throws IOException { + protected boolean scanQName(QName qname, NameType nt) throws IOException { if (DEBUG_BUFFER) { System.out.print("(scanQName, "+qname+": "); print(); @@ -794,6 +810,7 @@ print(); System.out.println(" -> true"); } + checkEntityLimit(nt, fCurrentEntity, 0, 1); return true; } } @@ -859,6 +876,7 @@ print(); System.out.println(" -> true"); } + checkEntityLimit(nt, fCurrentEntity, offset, length); return true; } } @@ -891,7 +909,7 @@ int nameLength = length; if (nameOffset != -1) { nameOffset = nameOffset - offset; - nameLength = length - nameOffset - 1; + nameLength = length - nameOffset; } else { nameOffset = offset; } @@ -913,22 +931,65 @@ } /** + * If the current entity is an Entity reference, check the accumulated size + * against the limit. + * + * @param nt type of name (element, attribute or entity) + * @param entity The current entity + * @param offset The index of the first byte + * @param length The length of the entity scanned + */ + protected void checkEntityLimit(NameType nt, ScannedEntity entity, int offset, int length) { + if (entity == null || !entity.isGE) { + return; + } + + if (nt != NameType.REFERENCE) { + checkLimit(Limit.GENEAL_ENTITY_SIZE_LIMIT, entity, offset, length); + } + if (nt == NameType.ELEMENTSTART || nt == NameType.ATTRIBUTENAME) { + checkNodeCount(entity); + } + } + + /** + * If the current entity is an Entity reference, counts the total nodes in + * the entity and checks the accumulated value against the limit. + * + * @param entity The current entity + */ + protected void checkNodeCount(ScannedEntity entity) { + if (entity != null && entity.isGE) { + checkLimit(Limit.ENTITY_REPLACEMENT_LIMIT, entity, 0, 1); + } + } + + /** * Checks whether the value of the specified Limit exceeds its limit * - * @param limit The Limit to be checked. - * @param entity The current entity. + * @param limit The Limit to be checked + * @param entity The current entity * @param offset The index of the first byte - * @param length The length of the entity scanned. + * @param length The length of the entity scanned */ protected void checkLimit(Limit limit, ScannedEntity entity, int offset, int length) { - fLimitAnalyzer.addValue(limit, null, length); + fLimitAnalyzer.addValue(limit, entity.name, length); if (fSecurityManager.isOverLimit(limit, fLimitAnalyzer)) { fSecurityManager.debugPrint(fLimitAnalyzer); + Object[] e = (limit == Limit.ENTITY_REPLACEMENT_LIMIT) ? + new Object[]{fLimitAnalyzer.getValue(limit), + fSecurityManager.getLimit(limit), fSecurityManager.getStateLiteral(limit)} : + new Object[]{entity.name, fLimitAnalyzer.getValue(limit), + fSecurityManager.getLimit(limit), fSecurityManager.getStateLiteral(limit)}; fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN, limit.key(), - new Object[]{new String(entity.ch, offset, length), - fLimitAnalyzer.getTotalValue(limit), - fSecurityManager.getLimit(limit), - fSecurityManager.getStateLiteral(limit)}, + e, XMLErrorReporter.SEVERITY_FATAL_ERROR); + } + if (fSecurityManager.isOverLimit(Limit.TOTAL_ENTITY_SIZE_LIMIT, fLimitAnalyzer)) { + fSecurityManager.debugPrint(fLimitAnalyzer); + fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN, "TotalEntitySizeLimit", + new Object[]{fLimitAnalyzer.getTotalValue(Limit.TOTAL_ENTITY_SIZE_LIMIT), + fSecurityManager.getLimit(Limit.TOTAL_ENTITY_SIZE_LIMIT), + fSecurityManager.getStateLiteral(Limit.TOTAL_ENTITY_SIZE_LIMIT)}, XMLErrorReporter.SEVERITY_FATAL_ERROR); } } @@ -955,7 +1016,7 @@ * @throws IOException Thrown if i/o error occurs. * @throws EOFException Thrown on end of file. */ - public int scanContent(XMLString content) throws IOException { + protected int scanContent(XMLString content) throws IOException { if (DEBUG_BUFFER) { System.out.print("(scanContent: "); print(); @@ -976,6 +1037,7 @@ int offset = fCurrentEntity.position; int c = fCurrentEntity.ch[offset]; int newlines = 0; + boolean counted = false; if (c == '\n' || (c == '\r' && isExternal)) { if (DEBUG_BUFFER) { System.out.print("[newline, "+offset+", "+fCurrentEntity.position+": "); @@ -989,9 +1051,11 @@ fCurrentEntity.lineNumber++; fCurrentEntity.columnNumber = 1; if (fCurrentEntity.position == fCurrentEntity.count) { + checkEntityLimit(null, fCurrentEntity, offset, newlines); offset = 0; fCurrentEntity.position = newlines; if (load(newlines, false, true)) { + counted = true; break; } } @@ -1008,9 +1072,11 @@ fCurrentEntity.lineNumber++; fCurrentEntity.columnNumber = 1; if (fCurrentEntity.position == fCurrentEntity.count) { + checkEntityLimit(null, fCurrentEntity, offset, newlines); offset = 0; fCurrentEntity.position = newlines; if (load(newlines, false, true)) { + counted = true; break; } } @@ -1024,6 +1090,7 @@ } int length = fCurrentEntity.position - offset; if (fCurrentEntity.position == fCurrentEntity.count - 1) { + checkEntityLimit(null, fCurrentEntity, offset, length); //CHANGED: dont replace the value.. append to the buffer. This gives control to the callee //on buffering the data.. content.setValues(fCurrentEntity.ch, offset, length); @@ -1051,8 +1118,8 @@ } int length = fCurrentEntity.position - offset; fCurrentEntity.columnNumber += length - newlines; - if (fCurrentEntity.isGE) { - checkLimit(Limit.TOTAL_ENTITY_SIZE_LIMIT, fCurrentEntity, offset, length); + if (!counted) { + checkEntityLimit(null, fCurrentEntity, offset, length); } //CHANGED: dont replace the value.. append to the buffer. This gives control to the callee @@ -1108,7 +1175,7 @@ * @throws IOException Thrown if i/o error occurs. * @throws EOFException Thrown on end of file. */ - public int scanLiteral(int quote, XMLString content, boolean isNSURI) + protected int scanLiteral(int quote, XMLString content, boolean isNSURI) throws IOException { if (DEBUG_BUFFER) { System.out.print("(scanLiteral, '"+(char)quote+"': "); @@ -1229,9 +1296,8 @@ } int length = fCurrentEntity.position - offset; fCurrentEntity.columnNumber += length - newlines; - if (fCurrentEntity.isGE) { - checkLimit(Limit.TOTAL_ENTITY_SIZE_LIMIT, fCurrentEntity, offset, length); - } + + checkEntityLimit(null, fCurrentEntity, offset, length); if (isNSURI) { checkLimit(Limit.MAX_NAME_LIMIT, fCurrentEntity, offset, length); } @@ -1282,7 +1348,7 @@ * @throws IOException Thrown if i/o error occurs. * @throws EOFException Thrown on end of file. */ - public boolean scanData(String delimiter, XMLStringBuffer buffer) + protected boolean scanData(String delimiter, XMLStringBuffer buffer) throws IOException { boolean done = false; @@ -1320,6 +1386,7 @@ if (fCurrentEntity.position > fCurrentEntity.count - delimLen) { // something must be wrong with the input: e.g., file ends in an unterminated comment int length = fCurrentEntity.count - fCurrentEntity.position; + checkEntityLimit(NameType.COMMENT, fCurrentEntity, fCurrentEntity.position, length); buffer.append (fCurrentEntity.ch, fCurrentEntity.position, length); fCurrentEntity.columnNumber += fCurrentEntity.count; fCurrentEntity.baseCharOffset += (fCurrentEntity.position - fCurrentEntity.startPosition); @@ -1382,6 +1449,7 @@ } int length = fCurrentEntity.position - offset; if (fCurrentEntity.position == fCurrentEntity.count - 1) { + checkEntityLimit(NameType.COMMENT, fCurrentEntity, offset, length); buffer.append(fCurrentEntity.ch, offset, length); if (DEBUG_BUFFER) { System.out.print("]newline, "+offset+", "+fCurrentEntity.position+": "); @@ -1425,12 +1493,14 @@ fCurrentEntity.position--; int length = fCurrentEntity.position - offset; fCurrentEntity.columnNumber += length - newlines; + checkEntityLimit(NameType.COMMENT, fCurrentEntity, offset, length); buffer.append(fCurrentEntity.ch, offset, length); return true; } } int length = fCurrentEntity.position - offset; fCurrentEntity.columnNumber += length - newlines; + checkEntityLimit(NameType.COMMENT, fCurrentEntity, offset, length); if (done) { length -= delimLen; } @@ -1454,13 +1524,14 @@ * the specified character. * * @param c The character to skip. + * @param nt The type of the name (element or attribute) * * @return Returns true if the character was skipped. * * @throws IOException Thrown if i/o error occurs. * @throws EOFException Thrown on end of file. */ - public boolean skipChar(int c) throws IOException { + protected boolean skipChar(int c, NameType nt) throws IOException { if (DEBUG_BUFFER) { System.out.print("(skipChar, '"+(char)c+"': "); print(); @@ -1473,6 +1544,7 @@ } // skip character + int offset = fCurrentEntity.position; int cc = fCurrentEntity.ch[fCurrentEntity.position]; if (cc == c) { fCurrentEntity.position++; @@ -1487,6 +1559,7 @@ print(); System.out.println(" -> true"); } + checkEntityLimit(nt, fCurrentEntity, offset, fCurrentEntity.position - offset); return true; } else if (c == '\n' && cc == '\r' && isExternal) { // handle newlines @@ -1506,6 +1579,7 @@ print(); System.out.println(" -> true"); } + checkEntityLimit(nt, fCurrentEntity, offset, fCurrentEntity.position - offset); return true; } @@ -1535,7 +1609,7 @@ * * @see com.sun.org.apache.xerces.internal.util.XMLChar#isSpace */ - public boolean skipSpaces() throws IOException { + protected boolean skipSpaces() throws IOException { if (DEBUG_BUFFER) { System.out.print("(skipSpaces: "); print(); @@ -1559,6 +1633,7 @@ // skip spaces int c = fCurrentEntity.ch[fCurrentEntity.position]; + int offset = fCurrentEntity.position - 1; if (XMLChar.isSpace(c)) { do { boolean entityChanged = false; @@ -1588,6 +1663,11 @@ } else { fCurrentEntity.columnNumber++; } + + //If this is a general entity, spaces within a start element should be counted + checkEntityLimit(null, fCurrentEntity, offset, fCurrentEntity.position - offset); + offset = fCurrentEntity.position; + // load more characters, if needed if (!entityChanged){ fCurrentEntity.position++; @@ -1629,7 +1709,7 @@ /** - * @param legnth This function checks that following number of characters are available. + * @param length This function checks that following number of characters are available. * to the underlying buffer. * @return This function returns true if capacity asked is available. */ @@ -1638,9 +1718,9 @@ } /** - * @param legnth This function checks that following number of characters are available. + * @param length This function checks that following number of characters are available. * to the underlying buffer. - * @param if the underlying function should change the entity + * @param changeEntity a flag to indicate that the underlying function should change the entity * @return This function returns true if capacity asked is available. * */ @@ -1703,7 +1783,7 @@ * @throws IOException Thrown if i/o error occurs. * @throws EOFException Thrown on end of file. */ - public boolean skipString(String s) throws IOException { + protected boolean skipString(String s) throws IOException { final int length = s.length(); @@ -1723,6 +1803,9 @@ if(afterSkip-- == beforeSkip){ fCurrentEntity.position = fCurrentEntity.position + length ; fCurrentEntity.columnNumber += length; + if (!detectingVersion) { + checkEntityLimit(null, fCurrentEntity, beforeSkip, length); + } return true; } } @@ -1731,7 +1814,7 @@ return false; } // skipString(String):boolean - public boolean skipString(char [] s) throws IOException { + protected boolean skipString(char [] s) throws IOException { final int length = s.length; //first make sure that required capacity is avaible @@ -1751,6 +1834,9 @@ } fCurrentEntity.position = fCurrentEntity.position + length ; fCurrentEntity.columnNumber += length; + if (!detectingVersion) { + checkEntityLimit(null, fCurrentEntity, beforeSkip, length); + } return true; } @@ -2148,7 +2234,7 @@ * * @see com.sun.org.apache.xerces.internal.util.XMLChar#isSpace */ - public final boolean skipDeclSpaces() throws IOException { + protected final boolean skipDeclSpaces() throws IOException { if (DEBUG_BUFFER) { System.out.print("(skipDeclSpaces: "); //XMLEntityManager.print(fCurrentEntity); diff -r 023fdb2f8ee2 -r f968b06f80c6 src/com/sun/org/apache/xerces/internal/impl/XMLNSDocumentScannerImpl.java --- a/src/com/sun/org/apache/xerces/internal/impl/XMLNSDocumentScannerImpl.java Fri Jul 08 04:17:27 2016 +0100 +++ b/src/com/sun/org/apache/xerces/internal/impl/XMLNSDocumentScannerImpl.java Fri Jul 08 05:10:10 2016 +0100 @@ -196,9 +196,9 @@ // There are two variables,fNamespaces and fBindNamespaces //StAX uses XMLNSDocumentScannerImpl so this distinction needs to be maintained if (fNamespaces) { - fEntityScanner.scanQName(fElementQName); + fEntityScanner.scanQName(fElementQName, NameType.ELEMENTSTART); } else { - String name = fEntityScanner.scanName(); + String name = fEntityScanner.scanName(NameType.ELEMENTSTART); fElementQName.setValues(null, name, name, null); } @@ -411,11 +411,11 @@ if (DEBUG_START_END_ELEMENT) System.out.println(this.getClass().toString() +">>> scanAttribute()"); // name - fEntityScanner.scanQName(fAttributeQName); + fEntityScanner.scanQName(fAttributeQName, NameType.ATTRIBUTE); // equals fEntityScanner.skipSpaces(); - if (!fEntityScanner.skipChar('=')) { + if (!fEntityScanner.skipChar('=', NameType.ATTRIBUTE)) { reportFatalError("EqRequiredInAttribute", new Object[]{fCurrentElement.rawname,fAttributeQName.rawname}); } diff -r 023fdb2f8ee2 -r f968b06f80c6 src/com/sun/org/apache/xerces/internal/impl/XMLScanner.java --- a/src/com/sun/org/apache/xerces/internal/impl/XMLScanner.java Fri Jul 08 04:17:27 2016 +0100 +++ b/src/com/sun/org/apache/xerces/internal/impl/XMLScanner.java Fri Jul 08 05:10:10 2016 +0100 @@ -35,7 +35,6 @@ import com.sun.org.apache.xerces.internal.utils.XMLLimitAnalyzer; import com.sun.org.apache.xerces.internal.utils.XMLSecurityManager; import com.sun.org.apache.xerces.internal.xni.Augmentations; -import com.sun.org.apache.xerces.internal.xni.QName; import com.sun.org.apache.xerces.internal.xni.XMLAttributes; import com.sun.org.apache.xerces.internal.xni.XMLResourceIdentifier; import com.sun.org.apache.xerces.internal.xni.XMLString; @@ -117,6 +116,30 @@ /** Debug attribute normalization. */ protected static final boolean DEBUG_ATTR_NORMALIZATION = false; + /** + * Type of names + */ + public static enum NameType { + ATTRIBUTE("attribute"), + ATTRIBUTENAME("attribute name"), + COMMENT("comment"), + DOCTYPE("doctype"), + ELEMENTSTART("startelement"), + ELEMENTEND("endelement"), + ENTITY("entity"), + NOTATION("notation"), + PI("pi"), + REFERENCE("reference"); + + final String literal; + NameType(String literal) { + this.literal = literal; + } + + String literal() { + return literal; + } + } //xxx: setting the default value as false, as we dont need to calculate this value //we should have a feature when set to true computes this value @@ -147,7 +170,7 @@ protected boolean fNotifyCharRefs = false; /** Internal parser-settings feature */ - protected boolean fParserSettings = true; + protected boolean fParserSettings = true; // properties @@ -176,13 +199,13 @@ /** event type */ protected XMLEvent fEvent ; - /** Entity scanner, this alwasy works on last entity that was opened. */ + /** Entity scanner, this always works on last entity that was opened. */ protected XMLEntityScanner fEntityScanner = null; /** Entity depth. */ protected int fEntityDepth; - /** Literal value of the last character refence scanned. */ + /** Literal value of the last character reference scanned. */ protected String fCharRefLiteral = null; /** Scanning attribute. */ @@ -550,10 +573,10 @@ } // end - if (!fEntityScanner.skipChar('?')) { + if (!fEntityScanner.skipChar('?', null)) { reportFatalError("XMLDeclUnterminated", null); } - if (!fEntityScanner.skipChar('>')) { + if (!fEntityScanner.skipChar('>', null)) { reportFatalError("XMLDeclUnterminated", null); } @@ -580,7 +603,7 @@ * Note: This method uses fStringBuffer2, anything in it * at the time of calling is lost. */ - public String scanPseudoAttribute(boolean scanningTextDecl, + protected String scanPseudoAttribute(boolean scanningTextDecl, XMLString value) throws IOException, XNIException { @@ -591,7 +614,7 @@ reportFatalError("PseudoAttrNameExpected", null); } fEntityScanner.skipSpaces(); - if (!fEntityScanner.skipChar('=')) { + if (!fEntityScanner.skipChar('=', null)) { reportFatalError(scanningTextDecl ? "EqRequiredInTextDecl" : "EqRequiredInXMLDecl", new Object[]{name}); } @@ -601,7 +624,7 @@ reportFatalError(scanningTextDecl ? "QuoteRequiredInTextDecl" : "QuoteRequiredInXMLDecl" , new Object[]{name}); } - fEntityScanner.scanChar(); + fEntityScanner.scanChar(NameType.ATTRIBUTE); int c = fEntityScanner.scanLiteral(quote, value, false); if (c != quote) { fStringBuffer2.clear(); @@ -609,7 +632,7 @@ fStringBuffer2.append(value); if (c != -1) { if (c == '&' || c == '%' || c == '<' || c == ']') { - fStringBuffer2.append((char)fEntityScanner.scanChar()); + fStringBuffer2.append((char)fEntityScanner.scanChar(NameType.ATTRIBUTE)); } else if (XMLChar.isHighSurrogate(c)) { scanSurrogates(fStringBuffer2); } else if (isInvalidLiteral(c)) { @@ -617,7 +640,7 @@ ? "InvalidCharInTextDecl" : "InvalidCharInXMLDecl"; reportFatalError(key, new Object[] {Integer.toString(c, 16)}); - fEntityScanner.scanChar(); + fEntityScanner.scanChar(null); } } c = fEntityScanner.scanLiteral(quote, value, false); @@ -625,7 +648,7 @@ fStringBuffer2.append(value); value.setValues(fStringBuffer2); } - if (!fEntityScanner.skipChar(quote)) { + if (!fEntityScanner.skipChar(quote, null)) { reportFatalError(scanningTextDecl ? "CloseQuoteMissingInTextDecl" : "CloseQuoteMissingInXMLDecl", new Object[]{name}); @@ -683,7 +706,7 @@ // target fReportEntity = false; - String target = fEntityScanner.scanName(); + String target = fEntityScanner.scanName(NameType.PI); if (target == null) { reportFatalError("PITargetRequired", null); } @@ -748,7 +771,7 @@ } else if (isInvalidLiteral(c)) { reportFatalError("InvalidCharInPI", new Object[]{Integer.toHexString(c)}); - fEntityScanner.scanChar(); + fEntityScanner.scanChar(null); } } } while (fEntityScanner.scanData("?>", data)); @@ -789,11 +812,11 @@ if (isInvalidLiteral(c)) { reportFatalError("InvalidCharInComment", new Object[] { Integer.toHexString(c) }); - fEntityScanner.scanChar(); + fEntityScanner.scanChar(NameType.COMMENT); } } } - if (!fEntityScanner.skipChar('>')) { + if (!fEntityScanner.skipChar('>', NameType.COMMENT)) { reportFatalError("DashDashInComment", null); } @@ -830,7 +853,7 @@ reportFatalError("OpenQuoteExpected", new Object[]{eleName, atName}); } - fEntityScanner.scanChar(); + fEntityScanner.scanChar(NameType.ATTRIBUTE); int entityDepth = fEntityDepth; int c = fEntityScanner.scanLiteral(quote, value, isNSURI); @@ -859,11 +882,11 @@ + stringBuffer.toString() + "\""); } if (c == '&') { - fEntityScanner.skipChar('&'); + fEntityScanner.skipChar('&', NameType.REFERENCE); if (entityDepth == fEntityDepth && fNeedNonNormalizedValue ) { fStringBuffer2.append('&'); } - if (fEntityScanner.skipChar('#')) { + if (fEntityScanner.skipChar('#', NameType.REFERENCE)) { if (entityDepth == fEntityDepth && fNeedNonNormalizedValue ) { fStringBuffer2.append('#'); } @@ -881,53 +904,20 @@ } } } else { - String entityName = fEntityScanner.scanName(); + String entityName = fEntityScanner.scanName(NameType.ENTITY); if (entityName == null) { reportFatalError("NameRequiredInReference", null); } else if (entityDepth == fEntityDepth && fNeedNonNormalizedValue) { fStringBuffer2.append(entityName); } - if (!fEntityScanner.skipChar(';')) { + if (!fEntityScanner.skipChar(';', NameType.REFERENCE)) { reportFatalError("SemicolonRequiredInReference", new Object []{entityName}); } else if (entityDepth == fEntityDepth && fNeedNonNormalizedValue) { fStringBuffer2.append(';'); } - if (entityName == fAmpSymbol) { - stringBuffer.append('&'); - if (DEBUG_ATTR_NORMALIZATION) { - System.out.println("** value5: \"" - + stringBuffer.toString() - + "\""); - } - } else if (entityName == fAposSymbol) { - stringBuffer.append('\''); - if (DEBUG_ATTR_NORMALIZATION) { - System.out.println("** value7: \"" - + stringBuffer.toString() - + "\""); - } - } else if (entityName == fLtSymbol) { - stringBuffer.append('<'); - if (DEBUG_ATTR_NORMALIZATION) { - System.out.println("** value9: \"" - + stringBuffer.toString() - + "\""); - } - } else if (entityName == fGtSymbol) { - stringBuffer.append('>'); - if (DEBUG_ATTR_NORMALIZATION) { - System.out.println("** valueB: \"" - + stringBuffer.toString() - + "\""); - } - } else if (entityName == fQuotSymbol) { - stringBuffer.append('"'); - if (DEBUG_ATTR_NORMALIZATION) { - System.out.println("** valueD: \"" - + stringBuffer.toString() - + "\""); - } + if (resolveCharacter(entityName, stringBuffer)) { + checkEntityLimit(false, fEntityScanner.fCurrentEntity.name, 1); } else { if (fEntityStore.isExternalEntity(entityName)) { reportFatalError("ReferenceToExternalEntity", @@ -954,12 +944,12 @@ } else if (c == '<') { reportFatalError("LessthanInAttValue", new Object[] { eleName, atName }); - fEntityScanner.scanChar(); + fEntityScanner.scanChar(null); if (entityDepth == fEntityDepth && fNeedNonNormalizedValue) { fStringBuffer2.append((char)c); } } else if (c == '%' || c == ']') { - fEntityScanner.scanChar(); + fEntityScanner.scanChar(null); stringBuffer.append((char)c); if (entityDepth == fEntityDepth && fNeedNonNormalizedValue) { fStringBuffer2.append((char)c); @@ -969,7 +959,7 @@ + stringBuffer.toString() + "\""); } } else if (c == '\n' || c == '\r') { - fEntityScanner.scanChar(); + fEntityScanner.scanChar(null); stringBuffer.append(' '); if (entityDepth == fEntityDepth && fNeedNonNormalizedValue) { fStringBuffer2.append('\n'); @@ -990,7 +980,7 @@ } else if (c != -1 && isInvalidLiteral(c)) { reportFatalError("InvalidCharInAttValue", new Object[] {eleName, atName, Integer.toString(c, 16)}); - fEntityScanner.scanChar(); + fEntityScanner.scanChar(null); if (entityDepth == fEntityDepth && fNeedNonNormalizedValue) { fStringBuffer2.append((char)c); } @@ -1016,7 +1006,7 @@ nonNormalizedValue.setValues(fStringBuffer2); // quote - int cquote = fEntityScanner.scanChar(); + int cquote = fEntityScanner.scanChar(NameType.ATTRIBUTE); if (cquote != quote) { reportFatalError("CloseQuoteExpected", new Object[]{eleName, atName}); } @@ -1024,6 +1014,39 @@ /** + * Resolves character entity references. + * @param entityName the name of the entity + * @param stringBuffer the current XMLStringBuffer to append the character to. + * @return true if resolved, false otherwise + */ + protected boolean resolveCharacter(String entityName, XMLStringBuffer stringBuffer) { + /** + * entityNames (symbols) are interned. The equals method would do the same, + * but I'm leaving it as comparisons by references are common in the impl + * and it made it explicit to others who read this code. + */ + if (entityName == fAmpSymbol) { + stringBuffer.append('&'); + return true; + } else if (entityName == fAposSymbol) { + stringBuffer.append('\''); + return true; + } else if (entityName == fLtSymbol) { + stringBuffer.append('<'); + return true; + } else if (entityName == fGtSymbol) { + checkEntityLimit(false, fEntityScanner.fCurrentEntity.name, 1); + stringBuffer.append('>'); + return true; + } else if (entityName == fQuotSymbol) { + checkEntityLimit(false, fEntityScanner.fCurrentEntity.name, 1); + stringBuffer.append('"'); + return true; + } + return false; + } + + /** * Scans External ID and return the public and system IDs. * * @param identifiers An array of size 2 to return the system id, @@ -1066,7 +1089,7 @@ } reportFatalError("QuoteRequiredInSystemID", null); } - fEntityScanner.scanChar(); + fEntityScanner.scanChar(null); XMLString ident = fString; if (fEntityScanner.scanLiteral(quote, ident, false) != quote) { fStringBuffer.clear(); @@ -1074,7 +1097,7 @@ fStringBuffer.append(ident); int c = fEntityScanner.peekChar(); if (XMLChar.isMarkup(c) || c == ']') { - fStringBuffer.append((char)fEntityScanner.scanChar()); + fStringBuffer.append((char)fEntityScanner.scanChar(null)); } else if (c != -1 && isInvalidLiteral(c)) { reportFatalError("InvalidCharInSystemID", new Object[] {Integer.toString(c, 16)}); @@ -1084,7 +1107,7 @@ ident = fStringBuffer; } systemId = ident.toString(); - if (!fEntityScanner.skipChar(quote)) { + if (!fEntityScanner.skipChar(quote, null)) { reportFatalError("SystemIDUnterminated", null); } } @@ -1116,7 +1139,7 @@ */ protected boolean scanPubidLiteral(XMLString literal) throws IOException, XNIException { - int quote = fEntityScanner.scanChar(); + int quote = fEntityScanner.scanChar(null); if (quote != '\'' && quote != '"') { reportFatalError("QuoteRequiredInPublicID", null); return false; @@ -1127,7 +1150,7 @@ boolean skipSpace = true; boolean dataok = true; while (true) { - int c = fEntityScanner.scanChar(); + int c = fEntityScanner.scanChar(null); if (c == ' ' || c == '\n' || c == '\r') { if (!skipSpace) { // take the first whitespace as a space and skip the others @@ -1243,9 +1266,10 @@ */ protected int scanCharReferenceValue(XMLStringBuffer buf, XMLStringBuffer buf2) throws IOException, XNIException { + int initLen = buf.length; // scan hexadecimal value boolean hex = false; - if (fEntityScanner.skipChar('x')) { + if (fEntityScanner.skipChar('x', NameType.REFERENCE)) { if (buf2 != null) { buf2.append('x'); } hex = true; fStringBuffer3.clear(); @@ -1257,7 +1281,7 @@ (c >= 'A' && c <= 'F'); if (digit) { if (buf2 != null) { buf2.append((char)c); } - fEntityScanner.scanChar(); + fEntityScanner.scanChar(NameType.REFERENCE); fStringBuffer3.append((char)c); do { @@ -1267,7 +1291,7 @@ (c >= 'A' && c <= 'F'); if (digit) { if (buf2 != null) { buf2.append((char)c); } - fEntityScanner.scanChar(); + fEntityScanner.scanChar(NameType.REFERENCE); fStringBuffer3.append((char)c); } } while (digit); @@ -1285,7 +1309,7 @@ digit = c >= '0' && c <= '9'; if (digit) { if (buf2 != null) { buf2.append((char)c); } - fEntityScanner.scanChar(); + fEntityScanner.scanChar(NameType.REFERENCE); fStringBuffer3.append((char)c); do { @@ -1293,7 +1317,7 @@ digit = c >= '0' && c <= '9'; if (digit) { if (buf2 != null) { buf2.append((char)c); } - fEntityScanner.scanChar(); + fEntityScanner.scanChar(NameType.REFERENCE); fStringBuffer3.append((char)c); } } while (digit); @@ -1303,7 +1327,7 @@ } // end - if (!fEntityScanner.skipChar(';')) { + if (!fEntityScanner.skipChar(';', NameType.REFERENCE)) { reportFatalError("SemicolonRequiredInCharRef", null); } if (buf2 != null) { buf2.append(';'); } @@ -1349,6 +1373,9 @@ } } + if (fEntityScanner.fCurrentEntity.isGE) { + checkEntityLimit(false, fEntityScanner.fCurrentEntity.name, buf.length - initLen); + } return value; } // returns true if the given character is not @@ -1402,14 +1429,14 @@ protected boolean scanSurrogates(XMLStringBuffer buf) throws IOException, XNIException { - int high = fEntityScanner.scanChar(); + int high = fEntityScanner.scanChar(null); int low = fEntityScanner.peekChar(); if (!XMLChar.isLowSurrogate(low)) { reportFatalError("InvalidCharInContent", new Object[] {Integer.toString(high, 16)}); return false; } - fEntityScanner.scanChar(); + fEntityScanner.scanChar(null); // convert surrogates to supplemental character int c = XMLChar.supplemental((char)high, (char)low); @@ -1472,5 +1499,52 @@ } } + /** + * Add the count of the content buffer and check if the accumulated + * value exceeds the limit + * @param isPEDecl a flag to indicate whether the entity is parameter + * @param entityName entity name + * @param buffer content buffer + */ + void checkEntityLimit(boolean isPEDecl, String entityName, XMLString buffer) { + checkEntityLimit(isPEDecl, entityName, buffer.length); + } + /** + * Add the count and check limit + * @param isPEDecl a flag to indicate whether the entity is parameter + * @param entityName entity name + * @param len length of the buffer + */ + void checkEntityLimit(boolean isPEDecl, String entityName, int len) { + if (fLimitAnalyzer == null) { + fLimitAnalyzer = fEntityManager.fLimitAnalyzer; + } + if (isPEDecl) { + fLimitAnalyzer.addValue(XMLSecurityManager.Limit.PARAMETER_ENTITY_SIZE_LIMIT, "%" + entityName, len); + if (fSecurityManager.isOverLimit(XMLSecurityManager.Limit.PARAMETER_ENTITY_SIZE_LIMIT, fLimitAnalyzer)) { + fSecurityManager.debugPrint(fLimitAnalyzer); + reportFatalError("MaxEntitySizeLimit", new Object[]{"%" + entityName, + fLimitAnalyzer.getValue(XMLSecurityManager.Limit.PARAMETER_ENTITY_SIZE_LIMIT), + fSecurityManager.getLimit(XMLSecurityManager.Limit.PARAMETER_ENTITY_SIZE_LIMIT), + fSecurityManager.getStateLiteral(XMLSecurityManager.Limit.PARAMETER_ENTITY_SIZE_LIMIT)}); + } + } else { + fLimitAnalyzer.addValue(XMLSecurityManager.Limit.GENEAL_ENTITY_SIZE_LIMIT, entityName, len); + if (fSecurityManager.isOverLimit(XMLSecurityManager.Limit.GENEAL_ENTITY_SIZE_LIMIT, fLimitAnalyzer)) { + fSecurityManager.debugPrint(fLimitAnalyzer); + reportFatalError("MaxEntitySizeLimit", new Object[]{entityName, + fLimitAnalyzer.getValue(XMLSecurityManager.Limit.GENEAL_ENTITY_SIZE_LIMIT), + fSecurityManager.getLimit(XMLSecurityManager.Limit.GENEAL_ENTITY_SIZE_LIMIT), + fSecurityManager.getStateLiteral(XMLSecurityManager.Limit.GENEAL_ENTITY_SIZE_LIMIT)}); + } + } + if (fSecurityManager.isOverLimit(XMLSecurityManager.Limit.TOTAL_ENTITY_SIZE_LIMIT, fLimitAnalyzer)) { + fSecurityManager.debugPrint(fLimitAnalyzer); + reportFatalError("TotalEntitySizeLimit", + new Object[]{fLimitAnalyzer.getTotalValue(XMLSecurityManager.Limit.TOTAL_ENTITY_SIZE_LIMIT), + fSecurityManager.getLimit(XMLSecurityManager.Limit.TOTAL_ENTITY_SIZE_LIMIT), + fSecurityManager.getStateLiteral(XMLSecurityManager.Limit.TOTAL_ENTITY_SIZE_LIMIT)}); + } + } } // class XMLScanner diff -r 023fdb2f8ee2 -r f968b06f80c6 src/com/sun/org/apache/xerces/internal/impl/XMLVersionDetector.java --- a/src/com/sun/org/apache/xerces/internal/impl/XMLVersionDetector.java Fri Jul 08 04:17:27 2016 +0100 +++ b/src/com/sun/org/apache/xerces/internal/impl/XMLVersionDetector.java Fri Jul 08 05:10:10 2016 +0100 @@ -1,62 +1,21 @@ /* - * reserved comment block - * DO NOT REMOVE OR ALTER! + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. */ /* - * The Apache Software License, Version 1.1 - * - * - * Copyright (c) 1999-2003 The Apache Software Foundation. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * 3. The end-user documentation included with the redistribution, - * if any, must include the following acknowledgment: - * "This product includes software developed by the - * Apache Software Foundation (http://www.apache.org/)." - * Alternately, this acknowledgment may appear in the software itself, - * if and wherever such third-party acknowledgments normally appear. + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at * - * 4. The names "Xerces" and "Apache Software Foundation" must - * not be used to endorse or promote products derived from this - * software without prior written permission. For written - * permission, please contact apache@apache.org. - * - * 5. Products derived from this software may not be called "Apache", - * nor may "Apache" appear in their name, without prior written - * permission of the Apache Software Foundation. + * http://www.apache.org/licenses/LICENSE-2.0 * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR - * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * ==================================================================== - * - * This software consists of voluntary contributions made by many - * individuals on behalf of the Apache Software Foundation and was - * originally based on software copyright (c) 2003, International - * Business Machines, Inc., http://www.apache.org. For more - * information on the Apache Software Foundation, please see - * . + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package com.sun.org.apache.xerces.internal.impl; @@ -192,40 +151,46 @@ // in the XML declaration. fEntityManager.setScannerVersion(Constants.XML_VERSION_1_0); XMLEntityScanner scanner = fEntityManager.getEntityScanner(); + scanner.detectingVersion = true; try { if (!scanner.skipString("