neeraj 2003/01/16 10:40:31 Modified: java/src/org/apache/xerces/util SecurityManager.java java/src/org/apache/xerces/impl/xs/models CMBuilder.java java/src/org/apache/xerces/impl/xs XMLSchemaValidator.java XMLSchemaLoader.java Log: Fixing another security problem. High value of maxOccur attirbute causes stackoverflow error. When application switches the mode of parser to behave in security conscious way using SecurityConfiguration. It sets the maximum number of nodes that should be created when building content model from maxOccurs attribute value specified in schema document, number of nodes created depneds upon the type of content model and value of maxOccurs attribute.Current limit of maximum number ofnodes has been set to 3000. However, it can be set to higher value if required by the application using SecurityManager Object. Revision Changes Path 1.2 +23 -1 xml-xerces/java/src/org/apache/xerces/util/SecurityManager.java Index: SecurityManager.java =================================================================== RCS file: /home/cvs/xml-xerces/java/src/org/apache/xerces/util/SecurityManager.java,v retrieving revision 1.1 retrieving revision 1.2 diff -u -r1.1 -r1.2 --- SecurityManager.java 8 Jan 2003 23:03:12 -0000 1.1 +++ SecurityManager.java 16 Jan 2003 18:40:29 -0000 1.2 @@ -83,6 +83,9 @@ // default value for entity expansion limit private final static int DEFAULT_ENTITY_EXPANSION_LIMIT = 100000; + + //default value of number of nodes created + private final static int DEFAULT_MAX_OCCUR_NODE_LIMIT = 3000; // // Data @@ -90,11 +93,13 @@ /** entity expansion limit */ private int entityExpansionLimit; + private int maxOccurLimit; // default constructor. Establishes default values for // all known security holes. public SecurityManager() { entityExpansionLimit = DEFAULT_ENTITY_EXPANSION_LIMIT; + maxOccurLimit = DEFAULT_MAX_OCCUR_NODE_LIMIT ; } // set the number of entity expansions that the @@ -108,5 +113,22 @@ public int getEntityExpansionLimit() { return entityExpansionLimit; } + + //sets the limit of the number of nodes that should be allowed to create when building + //content model from maxOccurs attribute value specified in schema document, number of nodes + //created depneds upon the type of content model and value of maxOccurs attribute. + public void setMaxOccurNodeLimit(int limit){ + maxOccurLimit = limit ; + } + + + //get the limit of the number of nodes that should be allowed to create when building + //content model from maxOccurs attribute value specified in schema document, number of nodes + //created depneds upon the type of content model and value of maxOccurs attribute. + + public int getMaxOccurNodeLimit(){ + return maxOccurLimit ; + } + } // class SecurityManager 1.15 +28 -20 xml-xerces/java/src/org/apache/xerces/impl/xs/models/CMBuilder.java Index: CMBuilder.java =================================================================== RCS file: /home/cvs/xml-xerces/java/src/org/apache/xerces/impl/xs/models/CMBuilder.java,v retrieving revision 1.14 retrieving revision 1.15 diff -u -r1.14 -r1.15 --- CMBuilder.java 8 Nov 2002 15:55:31 -0000 1.14 +++ CMBuilder.java 16 Jan 2003 18:40:29 -0000 1.15 @@ -87,14 +87,22 @@ private int fLeafCount; // needed for UPA private int fParticleCount; + //Factory to create Bin, Uni, Leaf nodes + private CMNodeFactory fNodeFactory ; - public CMBuilder() { + public CMBuilder(CMNodeFactory nodeFactory) { fDeclPool = null; + fNodeFactory = nodeFactory ; } public CMBuilder(XSDeclarationPool pool) { fDeclPool = pool; - } + //xxx is this constructor used ? but there would be nothing wrong if factory is created.. but we dont have security manager set. + if(fNodeFactory == null) + { + fNodeFactory = CMNodeFactory.newInstance(); + } + }//CMBuilder public void setDeclPool(XSDeclarationPool declPool) { fDeclPool = declPool; @@ -107,7 +115,7 @@ * @return a content model validator */ public XSCMValidator getContentModel(XSComplexTypeDecl typeDecl) { - + // for complex type with empty or simple content, // there is no content model validator short contentType = typeDecl.getContentType(); @@ -117,7 +125,7 @@ } XSParticleDecl particle = (XSParticleDecl)typeDecl.getParticle(); - + // if the content is element only or mixed, but no particle // is defined, return the empty content model if (particle == null) @@ -194,7 +202,7 @@ // are two references to the same group, we have two different // leaf particles for the same element or wildcard decl. // This is useful for checking UPA. - nodeRet = new XSCMLeaf(particle.fType, particle.fValue, fParticleCount++, fLeafCount++); + nodeRet = fNodeFactory.getCMLeafNode(particle.fType, particle.fValue, fParticleCount++, fLeafCount++); // (task 2) expand occurrence values nodeRet = expandContentModel(nodeRet, minOccurs, maxOccurs); } @@ -222,7 +230,7 @@ nodeRet = temp; } else { - nodeRet = new XSCMBinOp(group.fCompositor, nodeRet, temp); + nodeRet = fNodeFactory.getCMBinOpNode(group.fCompositor, nodeRet, temp); // record the fact that there are at least 2 children twoChildren = true; } @@ -236,7 +244,7 @@ // particle. if (group.fCompositor == XSModelGroupImpl.MODELGROUP_CHOICE && !twoChildren && group.fParticleCount > 1) { - nodeRet = new XSCMUniOp(XSParticleDecl.PARTICLE_ZERO_OR_ONE, nodeRet); + nodeRet = fNodeFactory.getCMUniOpNode(XSParticleDecl.PARTICLE_ZERO_OR_ONE, nodeRet); } nodeRet = expandContentModel(nodeRet, minOccurs, maxOccurs); } @@ -258,27 +266,27 @@ } else if (minOccurs==0 && maxOccurs==1) { //zero or one - nodeRet = new XSCMUniOp(XSParticleDecl.PARTICLE_ZERO_OR_ONE, node); + nodeRet = fNodeFactory.getCMUniOpNode(XSParticleDecl.PARTICLE_ZERO_OR_ONE, node); } else if (minOccurs == 0 && maxOccurs==SchemaSymbols.OCCURRENCE_UNBOUNDED) { //zero or more - nodeRet = new XSCMUniOp(XSParticleDecl.PARTICLE_ZERO_OR_MORE, node); + nodeRet = fNodeFactory.getCMUniOpNode(XSParticleDecl.PARTICLE_ZERO_OR_MORE, node); } else if (minOccurs == 1 && maxOccurs==SchemaSymbols.OCCURRENCE_UNBOUNDED) { //one or more - nodeRet = new XSCMUniOp(XSParticleDecl.PARTICLE_ONE_OR_MORE, node); + nodeRet = fNodeFactory.getCMUniOpNode(XSParticleDecl.PARTICLE_ONE_OR_MORE, node); } else if (maxOccurs == SchemaSymbols.OCCURRENCE_UNBOUNDED) { // => a,a,..,a+ // create a+ node first, then put minOccurs-1 a's in front of it // for the first time "node" is used, we don't need to make a copy // and for other references to node, we make copies - nodeRet = new XSCMUniOp(XSParticleDecl.PARTICLE_ONE_OR_MORE, node); + nodeRet = fNodeFactory.getCMUniOpNode(XSParticleDecl.PARTICLE_ONE_OR_MORE, node); for (int i=0; i < minOccurs-1; i++) { // (task 4) we need to call copyNode here, so that we append // an entire new copy of the node (a subtree). this is to ensure // all leaf nodes have distinct position - nodeRet = new XSCMBinOp(XSModelGroupImpl.MODELGROUP_SEQUENCE, + nodeRet = fNodeFactory.getCMBinOpNode(XSModelGroupImpl.MODELGROUP_SEQUENCE, copyNode(node), nodeRet); } } @@ -289,21 +297,21 @@ if (minOccurs > 0) { nodeRet = node; for (int i=0; i<minOccurs-1; i++) { - nodeRet = new XSCMBinOp(XSModelGroupImpl.MODELGROUP_SEQUENCE, + nodeRet = fNodeFactory.getCMBinOpNode(XSModelGroupImpl.MODELGROUP_SEQUENCE, nodeRet, copyNode(node)); } } if (maxOccurs > minOccurs) { - node = new XSCMUniOp(XSParticleDecl.PARTICLE_ZERO_OR_ONE, node); + node = fNodeFactory.getCMUniOpNode(XSParticleDecl.PARTICLE_ZERO_OR_ONE, node); if (nodeRet == null) { nodeRet = node; } else { - nodeRet = new XSCMBinOp(XSModelGroupImpl.MODELGROUP_SEQUENCE, + nodeRet = fNodeFactory.getCMBinOpNode(XSModelGroupImpl.MODELGROUP_SEQUENCE, nodeRet, copyNode(node)); } for (int i=minOccurs; i<maxOccurs-1; i++) { - nodeRet = new XSCMBinOp(XSModelGroupImpl.MODELGROUP_SEQUENCE, + nodeRet = fNodeFactory.getCMBinOpNode(XSModelGroupImpl.MODELGROUP_SEQUENCE, nodeRet, copyNode(node)); } } @@ -319,7 +327,7 @@ if (type == XSModelGroupImpl.MODELGROUP_CHOICE || type == XSModelGroupImpl.MODELGROUP_SEQUENCE) { XSCMBinOp bin = (XSCMBinOp)node; - node = new XSCMBinOp(type, copyNode(bin.getLeft()), + node = fNodeFactory.getCMBinOpNode(type, copyNode(bin.getLeft()), copyNode(bin.getRight())); } // for ?+*, copy the subtree, and put it in a new ?+* node @@ -327,14 +335,14 @@ type == XSParticleDecl.PARTICLE_ONE_OR_MORE || type == XSParticleDecl.PARTICLE_ZERO_OR_ONE) { XSCMUniOp uni = (XSCMUniOp)node; - node = new XSCMUniOp(type, copyNode(uni.getChild())); + node = fNodeFactory.getCMUniOpNode(type, copyNode(uni.getChild())); } // for element/wildcard (leaf), make a new leaf node, // with a distinct position else if (type == XSParticleDecl.PARTICLE_ELEMENT || type == XSParticleDecl.PARTICLE_WILDCARD) { XSCMLeaf leaf = (XSCMLeaf)node; - node = new XSCMLeaf(leaf.type(), leaf.getLeaf(), leaf.getParticleId(), fLeafCount++); + node = fNodeFactory.getCMLeafNode(leaf.type(), leaf.getLeaf(), leaf.getParticleId(), fLeafCount++); } return node; 1.129 +8 -3 xml-xerces/java/src/org/apache/xerces/impl/xs/XMLSchemaValidator.java Index: XMLSchemaValidator.java =================================================================== RCS file: /home/cvs/xml-xerces/java/src/org/apache/xerces/impl/xs/XMLSchemaValidator.java,v retrieving revision 1.128 retrieving revision 1.129 diff -u -r1.128 -r1.129 --- XMLSchemaValidator.java 14 Jan 2003 20:21:45 -0000 1.128 +++ XMLSchemaValidator.java 16 Jan 2003 18:40:30 -0000 1.129 @@ -118,6 +118,7 @@ import java.util.Stack; import java.util.Vector; import java.io.IOException; +import org.apache.xerces.impl.xs.models.CMNodeFactory; /** * The XML Schema validator. The validator implements a document @@ -1070,10 +1071,11 @@ // REVISIT: in new simple type design, make things in DVs static, // so that we can QNameDV.getCompiledForm() final XSSimpleType fQNameDV = (XSSimpleType)SchemaGrammar.SG_SchemaNS.getGlobalTypeDecl(SchemaSymbols.ATTVAL_QNAME); - + + final CMNodeFactory nodeFactory = CMNodeFactory.newInstance(); /** used to build content models */ // REVISIT: create decl pool, and pass it to each traversers - final CMBuilder fCMBuilder = new CMBuilder(); + final CMBuilder fCMBuilder = new CMBuilder(nodeFactory); // state @@ -1374,6 +1376,9 @@ catch (XMLConfigurationException e){ } + //pass the component manager to the factory.. + nodeFactory.reset(componentManager); + // clear grammars, and put the one for schema namespace there // logic for resetting grammar-related components moved // to schema loader 1.13 +7 -2 xml-xerces/java/src/org/apache/xerces/impl/xs/XMLSchemaLoader.java Index: XMLSchemaLoader.java =================================================================== RCS file: /home/cvs/xml-xerces/java/src/org/apache/xerces/impl/xs/XMLSchemaLoader.java,v retrieving revision 1.12 retrieving revision 1.13 diff -u -r1.12 -r1.13 --- XMLSchemaLoader.java 11 Nov 2002 20:47:31 -0000 1.12 +++ XMLSchemaLoader.java 16 Jan 2003 18:40:31 -0000 1.13 @@ -88,6 +88,8 @@ import java.io.FileInputStream; import java.io.FileNotFoundException; import java.util.Vector; +import org.apache.xerces.impl.xs.models.CMNodeFactory; + /** * This class implements XMLGrammarLoader. It is designed to interact * either with a proxy for a user application which wants to preparse schemas, @@ -238,8 +240,11 @@ sHandler = new SubstitutionGroupHandler(fGrammarBucket); } fSubGroupHandler = sHandler; + //get the factory instance.. this class is singleton + CMNodeFactory nodeFactory = CMNodeFactory.newInstance() ; + //REVISIT: shouldn't the SecurityManager be allowed to set, if an application tries to load standalone schema - nb. if(builder == null) { - builder = new CMBuilder(); + builder = new CMBuilder(nodeFactory); } fCMBuilder = builder; fSchemaHandler = new XSDHandler(fGrammarBucket);
--------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]