You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@xerces.apache.org by am...@apache.org on 2011/04/15 17:19:16 UTC
svn commit: r1092737 - in /xerces/c/branches/xerces-2: ./
scripts/sanityTest_ExpectedResult.log
src/xercesc/validators/common/ContentSpecNode.cpp
src/xercesc/validators/common/ContentSpecNode.hpp
Author: amassari
Date: Fri Apr 15 15:19:16 2011
New Revision: 1092737
URL: http://svn.apache.org/viewvc?rev=1092737&view=rev
Log:
Avoid recursion when dealing with ContentSpecNode objects; it can easily turn into a stack overflow (XERCESC-1935)
Modified:
xerces/c/branches/xerces-2/ (props changed)
xerces/c/branches/xerces-2/scripts/sanityTest_ExpectedResult.log
xerces/c/branches/xerces-2/src/xercesc/validators/common/ContentSpecNode.cpp
xerces/c/branches/xerces-2/src/xercesc/validators/common/ContentSpecNode.hpp
Propchange: xerces/c/branches/xerces-2/
------------------------------------------------------------------------------
--- svn:ignore (original)
+++ svn:ignore Fri Apr 15 15:19:16 2011
@@ -1,5 +1,6 @@
+Build
Makefile
bin
+include
lib
obj
-include
Propchange: xerces/c/branches/xerces-2/
------------------------------------------------------------------------------
svn:mergeinfo = /xerces/c/trunk:1092729
Modified: xerces/c/branches/xerces-2/scripts/sanityTest_ExpectedResult.log
URL: http://svn.apache.org/viewvc/xerces/c/branches/xerces-2/scripts/sanityTest_ExpectedResult.log?rev=1092737&r1=1092736&r2=1092737&view=diff
==============================================================================
--- xerces/c/branches/xerces-2/scripts/sanityTest_ExpectedResult.log (original)
+++ xerces/c/branches/xerces-2/scripts/sanityTest_ExpectedResult.log Fri Apr 15 15:19:16 2011
@@ -982,7 +982,7 @@ Name: personnel
Model Type: Children
Create Reason: Declared
ContentType:
-Content Model: (person,)
+Content Model: (person+)
ComplexType:
TypeName: ,__AnonC0
ContentType:
@@ -991,7 +991,7 @@ Name: person
Model Type: Children
Create Reason: Declared
ContentType:
-Content Model: ((name,email,url),link)
+Content Model: (name,email*,url*,link?)
ComplexType:
TypeName: ,__AnonC1
ContentType:
Modified: xerces/c/branches/xerces-2/src/xercesc/validators/common/ContentSpecNode.cpp
URL: http://svn.apache.org/viewvc/xerces/c/branches/xerces-2/src/xercesc/validators/common/ContentSpecNode.cpp?rev=1092737&r1=1092736&r2=1092737&view=diff
==============================================================================
--- xerces/c/branches/xerces-2/src/xercesc/validators/common/ContentSpecNode.cpp (original)
+++ xerces/c/branches/xerces-2/src/xercesc/validators/common/ContentSpecNode.cpp Fri Apr 15 15:19:16 2011
@@ -26,6 +26,7 @@
#include <xercesc/framework/XMLBuffer.hpp>
#include <xercesc/validators/common/ContentSpecNode.hpp>
#include <xercesc/validators/schema/SchemaSymbols.hpp>
+#include <xercesc/util/ValueStackOf.hpp>
XERCES_CPP_NAMESPACE_BEGIN
@@ -64,107 +65,191 @@ ContentSpecNode::ContentSpecNode(const C
fSecond = new (fMemoryManager) ContentSpecNode(*tmp);
}
+ContentSpecNode::~ContentSpecNode()
+{
+ // Delete our children, avoiding recursive cleanup
+ if (fAdoptFirst && fFirst) {
+ deleteChildNode(fFirst);
+ }
+
+ if (fAdoptSecond && fSecond) {
+ deleteChildNode(fSecond);
+ }
+
+ delete fElement;
+}
+
+void ContentSpecNode::deleteChildNode(ContentSpecNode* node)
+{
+ ValueStackOf<ContentSpecNode*> toBeDeleted(10, fMemoryManager);
+ toBeDeleted.push(node);
+ while(!toBeDeleted.empty())
+ {
+ ContentSpecNode* node = toBeDeleted.pop();
+ if(node==0)
+ continue;
+ if(node->isFirstAdopted())
+ toBeDeleted.push(node->orphanFirst());
+ if(node->isSecondAdopted())
+ toBeDeleted.push(node->orphanSecond());
+ delete node;
+ }
+}
+
+class formatNodeHolder
+{
+public:
+ formatNodeHolder(const ContentSpecNode* n, const ContentSpecNode::NodeTypes p, XMLCh c) : node(n), parentType(p), character(c) {}
+ formatNodeHolder& operator =(const formatNodeHolder* other)
+ {
+ node=other->node;
+ parentType=other->parentType;
+ character=other->character;
+ }
+
+ const ContentSpecNode* node;
+ ContentSpecNode::NodeTypes parentType;
+ XMLCh character;
+};
+
// ---------------------------------------------------------------------------
// Local methods
// ---------------------------------------------------------------------------
static void formatNode( const ContentSpecNode* const curNode
- , const ContentSpecNode::NodeTypes parentType
- , XMLBuffer& bufToFill)
+ , XMLBuffer& bufToFill
+ , MemoryManager* const memMgr)
{
if (!curNode)
return;
- const ContentSpecNode* first = curNode->getFirst();
- const ContentSpecNode* second = curNode->getSecond();
- const ContentSpecNode::NodeTypes curType = curNode->getType();
-
- // Get the type of the first node
- const ContentSpecNode::NodeTypes firstType = first ?
- first->getType() :
- ContentSpecNode::Leaf;
-
- // Calculate the parens flag for the rep nodes
- bool doRepParens = false;
- if (((firstType != ContentSpecNode::Leaf)
- && (parentType != ContentSpecNode::UnknownType))
- || ((firstType == ContentSpecNode::Leaf)
- && (parentType == ContentSpecNode::UnknownType)))
- {
- doRepParens = true;
- }
+ ValueStackOf<formatNodeHolder> toBeProcessed(10, memMgr);
+ toBeProcessed.push(formatNodeHolder(curNode, ContentSpecNode::UnknownType, 0));
- // Now handle our type
- switch(curType & 0x0f)
- {
- case ContentSpecNode::Leaf :
- if (curNode->getElement()->getURI() == XMLElementDecl::fgPCDataElemId)
- bufToFill.append(XMLElementDecl::fgPCDataElemName);
- else
- bufToFill.append(curNode->getElement()->getRawName());
- break;
-
- case ContentSpecNode::ZeroOrOne :
- if (doRepParens)
- bufToFill.append(chOpenParen);
- formatNode(first, curType, bufToFill);
- if (doRepParens)
- bufToFill.append(chCloseParen);
- bufToFill.append(chQuestion);
- break;
-
- case ContentSpecNode::ZeroOrMore :
- if (doRepParens)
- bufToFill.append(chOpenParen);
- formatNode(first, curType, bufToFill);
- if (doRepParens)
- bufToFill.append(chCloseParen);
- bufToFill.append(chAsterisk);
- break;
-
- case ContentSpecNode::OneOrMore :
- if (doRepParens)
- bufToFill.append(chOpenParen);
- formatNode(first, curType, bufToFill);
- if (doRepParens)
- bufToFill.append(chCloseParen);
- bufToFill.append(chPlus);
- break;
-
- case ContentSpecNode::Choice :
- if (parentType != curType)
- bufToFill.append(chOpenParen);
- formatNode(first, curType, bufToFill);
- bufToFill.append(chPipe);
- formatNode(second, curType, bufToFill);
- if (parentType != curType)
- bufToFill.append(chCloseParen);
- break;
-
- case ContentSpecNode::Sequence :
- if (parentType != curType)
- bufToFill.append(chOpenParen);
- formatNode(first, curType, bufToFill);
- bufToFill.append(chComma);
- formatNode(second, curType, bufToFill);
- if (parentType != curType)
- bufToFill.append(chCloseParen);
- break;
-
- case ContentSpecNode::All :
- if (parentType != curType)
- {
- bufToFill.append(chLatin_A);
- bufToFill.append(chLatin_l);
- bufToFill.append(chLatin_l);
- bufToFill.append(chOpenParen);
- }
- formatNode(first, curType, bufToFill);
- bufToFill.append(chComma);
- formatNode(second, curType, bufToFill);
- if (parentType != curType)
- bufToFill.append(chCloseParen);
- break;
- }
+ while(!toBeProcessed.empty())
+ {
+ formatNodeHolder item=toBeProcessed.pop();
+ if(item.character!=0)
+ {
+ bufToFill.append(item.character);
+ continue;
+ }
+ const ContentSpecNode* curNode = item.node;
+ if(!curNode)
+ continue;
+ const ContentSpecNode::NodeTypes parentType = item.parentType;
+ const ContentSpecNode* first = curNode->getFirst();
+ const ContentSpecNode* second = curNode->getSecond();
+ const ContentSpecNode::NodeTypes curType = curNode->getType();
+
+ // Get the type of the first node
+ const ContentSpecNode::NodeTypes firstType = first ?
+ first->getType() :
+ ContentSpecNode::Leaf;
+
+ // Calculate the parens flag for the rep nodes
+ bool doRepParens = false;
+ if (((firstType != ContentSpecNode::Leaf)
+ && (parentType != ContentSpecNode::UnknownType))
+ || ((firstType == ContentSpecNode::Leaf)
+ && (parentType == ContentSpecNode::UnknownType)))
+ {
+ doRepParens = true;
+ }
+
+ // Now handle our type
+ switch(curType & 0x0f)
+ {
+ case ContentSpecNode::Leaf :
+ if (curNode->getElement()->getURI() == XMLElementDecl::fgPCDataElemId)
+ bufToFill.append(XMLElementDecl::fgPCDataElemName);
+ else
+ {
+ bufToFill.append(curNode->getElement()->getRawName());
+ // show the + and * modifiers also when we have a non-infinite number of repetitions
+ if(curNode->getMinOccurs()==0 && (curNode->getMaxOccurs()==-1 || curNode->getMaxOccurs()>1))
+ bufToFill.append(chAsterisk);
+ else if(curNode->getMinOccurs()==0 && curNode->getMaxOccurs()==1)
+ bufToFill.append(chQuestion);
+ else if(curNode->getMinOccurs()==1 && (curNode->getMaxOccurs()==-1 || curNode->getMaxOccurs()>1))
+ bufToFill.append(chPlus);
+ }
+ break;
+
+ case ContentSpecNode::ZeroOrOne :
+ if (doRepParens)
+ bufToFill.append(chOpenParen);
+
+ toBeProcessed.push(formatNodeHolder(0, ContentSpecNode::UnknownType, chQuestion));
+ if (doRepParens)
+ toBeProcessed.push(formatNodeHolder(0, ContentSpecNode::UnknownType, chCloseParen));
+ toBeProcessed.push(formatNodeHolder(first, curType, 0));
+ break;
+
+ case ContentSpecNode::ZeroOrMore :
+ if (doRepParens)
+ bufToFill.append(chOpenParen);
+
+ toBeProcessed.push(formatNodeHolder(0, ContentSpecNode::UnknownType, chAsterisk));
+ if (doRepParens)
+ toBeProcessed.push(formatNodeHolder(0, ContentSpecNode::UnknownType, chCloseParen));
+ toBeProcessed.push(formatNodeHolder(first, curType, 0));
+ break;
+
+ case ContentSpecNode::OneOrMore :
+ if (doRepParens)
+ bufToFill.append(chOpenParen);
+
+ toBeProcessed.push(formatNodeHolder(0, ContentSpecNode::UnknownType, chPlus));
+ if (doRepParens)
+ toBeProcessed.push(formatNodeHolder(0, ContentSpecNode::UnknownType, chCloseParen));
+ toBeProcessed.push(formatNodeHolder(first, curType, 0));
+ break;
+
+ case ContentSpecNode::Choice :
+ if ((parentType & 0x0f) != (curType & 0x0f))
+ bufToFill.append(chOpenParen);
+
+ if ((parentType & 0x0f) != (curType & 0x0f))
+ toBeProcessed.push(formatNodeHolder(0, ContentSpecNode::UnknownType, chCloseParen));
+ if(second!=NULL)
+ {
+ toBeProcessed.push(formatNodeHolder(second, curType, 0));
+ toBeProcessed.push(formatNodeHolder(0, ContentSpecNode::UnknownType, chPipe));
+ }
+ toBeProcessed.push(formatNodeHolder(first, curType, 0));
+ break;
+
+ case ContentSpecNode::Sequence :
+ if ((parentType & 0x0f) != (curType & 0x0f))
+ bufToFill.append(chOpenParen);
+
+ if ((parentType & 0x0f) != (curType & 0x0f))
+ toBeProcessed.push(formatNodeHolder(0, ContentSpecNode::UnknownType, chCloseParen));
+ if(second!=NULL)
+ {
+ toBeProcessed.push(formatNodeHolder(second, curType, 0));
+ toBeProcessed.push(formatNodeHolder(0, ContentSpecNode::UnknownType, chComma));
+ }
+ toBeProcessed.push(formatNodeHolder(first, curType, 0));
+ break;
+
+ case ContentSpecNode::All :
+ if ((parentType & 0x0f) != (curType & 0x0f))
+ {
+ bufToFill.append(chLatin_A);
+ bufToFill.append(chLatin_l);
+ bufToFill.append(chLatin_l);
+ bufToFill.append(chOpenParen);
+ }
+
+ if ((parentType & 0x0f) != (curType & 0x0f))
+ toBeProcessed.push(formatNodeHolder(0, ContentSpecNode::UnknownType, chCloseParen));
+ toBeProcessed.push(formatNodeHolder(second, curType, 0));
+ toBeProcessed.push(formatNodeHolder(0, ContentSpecNode::UnknownType, chComma));
+ toBeProcessed.push(formatNodeHolder(first, curType, 0));
+ break;
+ }
+ }
}
@@ -181,8 +266,8 @@ void ContentSpecNode::formatSpec(XMLBuff
formatNode
(
this
- , UnknownType
- , bufToFill
+ , bufToFill
+ , fMemoryManager
);
if (fType == ContentSpecNode::Leaf)
bufToFill.append(chCloseParen);
Modified: xerces/c/branches/xerces-2/src/xercesc/validators/common/ContentSpecNode.hpp
URL: http://svn.apache.org/viewvc/xerces/c/branches/xerces-2/src/xercesc/validators/common/ContentSpecNode.hpp?rev=1092737&r1=1092736&r2=1092737&view=diff
==============================================================================
--- xerces/c/branches/xerces-2/src/xercesc/validators/common/ContentSpecNode.hpp (original)
+++ xerces/c/branches/xerces-2/src/xercesc/validators/common/ContentSpecNode.hpp Fri Apr 15 15:19:16 2011
@@ -150,6 +150,10 @@ private :
// -----------------------------------------------------------------------
ContentSpecNode& operator=(const ContentSpecNode&);
+ // -----------------------------------------------------------------------
+ // Helper functions
+ // -----------------------------------------------------------------------
+ void deleteChildNode(ContentSpecNode* node);
// -----------------------------------------------------------------------
// Private Data Members
@@ -303,20 +307,6 @@ ContentSpecNode::ContentSpecNode(const
{
}
-inline ContentSpecNode::~ContentSpecNode()
-{
- // Delete our children, which cause recursive cleanup
- if (fAdoptFirst) {
- delete fFirst;
- }
-
- if (fAdoptSecond) {
- delete fSecond;
- }
-
- delete fElement;
-}
-
// ---------------------------------------------------------------------------
// ContentSpecNode: Getter methods
// ---------------------------------------------------------------------------
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@xerces.apache.org
For additional commands, e-mail: commits-help@xerces.apache.org