There seems to be a buffer size of document lost during XML parsing (in case parsing succeeds). Attached patch fixes it. OK to apply? Ilya.
Index: src/xml/CXmlDoc.cpp
===================================================================
--- src/xml/CXmlDoc.cpp (revision 521)
+++ src/xml/CXmlDoc.cpp (working copy)
@@ -220,151 +220,155 @@
}
}
+class MemGuard
+{
+ char* m_mem;
+public:
+ MemGuard(char* mem): m_mem(mem) {}
+ ~MemGuard() { free(m_mem); }
+};
+
void CXmlDoc::load(const char* xmlData) {
clear();
CXmlNode* currentNode = this;
CXmlDocType *doctype = &docType();
char* buffer = strdup(xmlData);
- try {
- char* tokenStart = (char*)strchr(buffer,'<');
- while (tokenStart) {
- tokenStart++;
- char* tokenEnd = strpbrk(tokenStart," >");
- if (!tokenEnd)
- break; /// Tag started but not completed
+ MemGuard guard(buffer);
+ char* tokenStart = (char*)strchr(buffer,'<');
+ while (tokenStart) {
+ tokenStart++;
+ char* tokenEnd = strpbrk(tokenStart," >");
+ if (!tokenEnd)
+ break; /// Tag started but not completed
- char ch = *tokenEnd;
- *tokenEnd = 0;
- char* nodeName = tokenStart;
- char* nodeEnd;
- switch (*tokenStart) {
- case '!':
- if (strncmp(nodeName,"!--",3) == 0) {
- /// Comment
- *tokenEnd = ch; // ' ' or '>' could be within a comment
- nodeEnd = strstr(nodeName+3,"-->");
- if (!nodeEnd)
- throw CException("Invalid end of the comment tag");
+ char ch = *tokenEnd;
+ *tokenEnd = 0;
+ char* nodeName = tokenStart;
+ char* nodeEnd;
+ switch (*tokenStart) {
+ case '!':
+ if (strncmp(nodeName,"!--",3) == 0) {
+ /// Comment
+ *tokenEnd = ch; // ' ' or '>' could be within a comment
+ nodeEnd = strstr(nodeName+3,"-->");
+ if (!nodeEnd)
+ throw CException("Invalid end of the comment tag");
+ *nodeEnd = 0;
+ new CXmlComment(currentNode,nodeName + 3);
+ tokenEnd = nodeEnd + 2;
+ break;
+ }
+ if (strncmp(nodeName,"![CDATA[",8) == 0) {
+ /// CDATA section
+ if (ch != '>') {
+ nodeEnd = strstr(tokenEnd+1,"]]>");
+ *tokenEnd = ch;
+ } else
+ nodeEnd = strstr(nodeName+8,"]]");
+ if (!nodeEnd)
+ throw CException("Invalid CDATA section");
+ *nodeEnd = 0;
+ new CXmlCDataSection(currentNode,nodeName+8);
+ tokenEnd = nodeEnd + 3;
+ break;
+ }
+ if (strncmp(nodeName,"!DOCTYPE",8) == 0) {
+ /// DOCTYPE section
+ if (ch == '>')
+ break;
+ nodeEnd = strstr(tokenEnd+1,"]>");
+ if (nodeEnd) { /// ENTITIES
+ nodeEnd++;
*nodeEnd = 0;
- new CXmlComment(currentNode,nodeName + 3);
- tokenEnd = nodeEnd + 2;
- break;
- }
- if (strncmp(nodeName,"![CDATA[",8) == 0) {
- /// CDATA section
- if (ch != '>') {
- nodeEnd = strstr(tokenEnd+1,"]]>");
- *tokenEnd = ch;
- } else
- nodeEnd = strstr(nodeName+8,"]]");
+ } else {
+ nodeEnd = strchr(tokenEnd+1,'>');
if (!nodeEnd)
throw CException("Invalid CDATA section");
*nodeEnd = 0;
- new CXmlCDataSection(currentNode,nodeName+8);
- tokenEnd = nodeEnd + 3;
- break;
}
- if (strncmp(nodeName,"!DOCTYPE",8) == 0) {
- /// DOCTYPE section
- if (ch == '>')
- break;
- nodeEnd = strstr(tokenEnd+1,"]>");
- if (nodeEnd) { /// ENTITIES
- nodeEnd++;
- *nodeEnd = 0;
- } else {
- nodeEnd = strchr(tokenEnd+1,'>');
- if (!nodeEnd)
- throw CException("Invalid CDATA section");
- *nodeEnd = 0;
- }
- parseDocType(tokenEnd+1);
- tokenEnd = nodeEnd;
- break;
- }
+ parseDocType(tokenEnd+1);
+ tokenEnd = nodeEnd;
+ break;
+ }
- case '?': {
- /// Processing instructions
- const char *value;
- if (ch == ' ') {
- value = tokenEnd + 1;
- nodeEnd = (char*)strstr(value,"?>");
- } else {
- value = "";
- nodeEnd = strstr(tokenStart,"?");
- }
- if (!nodeEnd)
- throw CException("Invalid PI section");
- *nodeEnd = 0;
- new CXmlPI(currentNode,nodeName + 1,value);
- tokenEnd = nodeEnd + 2;
+ case '?': {
+ /// Processing instructions
+ const char *value;
+ if (ch == ' ') {
+ value = tokenEnd + 1;
+ nodeEnd = (char*)strstr(value,"?>");
+ } else {
+ value = "";
+ nodeEnd = strstr(tokenStart,"?");
}
+ if (!nodeEnd)
+ throw CException("Invalid PI section");
+ *nodeEnd = 0;
+ new CXmlPI(currentNode,nodeName + 1,value);
+ tokenEnd = nodeEnd + 2;
+ }
+ break;
+
+ case '/':
+ /// Closing tag
+ if (ch != '>')
+ throw CException("Invalid tag (spaces before closing '>')");
+ nodeName++;
+ if (currentNode->name() != nodeName)
+ throw CException("Closing tag <" + string(nodeName) + "> doesn't match opening <" + currentNode->name()+">");
+ currentNode = currentNode->parent();
+ if (!currentNode)
+ throw CException("Closing tag <" + string(nodeName) + "> doesn't have corresponding opening tag");
break;
- case '/':
- /// Closing tag
- if (ch != '>')
- throw CException("Invalid tag (spaces before closing '>')");
- nodeName++;
- if (currentNode->name() != nodeName)
- throw CException("Closing tag <" + string(nodeName) + "> doesn't match opening <" + currentNode->name()+">");
- currentNode = currentNode->parent();
- if (!currentNode)
- throw CException("Closing tag <" + string(nodeName) + "> doesn't have corresponding opening tag");
+ default:
+ /// Normal tag
+ if (ch == '>') {
+ if (*(tokenEnd-1) == '/') {
+ *(tokenEnd-1) = 0;
+ new CXmlElement(currentNode,nodeName);
+ } else
+ currentNode = new CXmlElement(currentNode,nodeName);
break;
+ }
- default:
- /// Normal tag
- if (ch == '>') {
- if (*(tokenEnd-1) == '/') {
- *(tokenEnd-1) = 0;
- new CXmlElement(currentNode,nodeName);
- } else
- currentNode = new CXmlElement(currentNode,nodeName);
+ /// Attributes
+ tokenStart = tokenEnd + 1;
+ nodeEnd = strchr(tokenStart,'>');
+ if (!nodeEnd)
+ throw CException("Invalid tag (started, not closed)");
+ *nodeEnd = 0;
+ CXmlNode* anode;
+ if (*(nodeEnd-1) == '/') {
+ anode = new CXmlElement(currentNode,nodeName);
+ *(nodeEnd-1) = 0;
+ } else {
+ anode = currentNode = new CXmlElement(currentNode,nodeName);
+ }
+ processAttributes(anode,tokenStart);
+ tokenEnd = nodeEnd;
+ break;
+ }
+ tokenStart = strchr(tokenEnd + 1,'<');
+ if (!tokenStart) {
+ if (currentNode == this)
+ return;
+ throw CException("Tag started but not closed");
+ }
+ unsigned char* textStart = (unsigned char*)tokenEnd + 1;
+ while (*textStart <= ' ') /// Skip leading spaces
+ textStart++;
+ if (*textStart != '<')
+ for (unsigned char* textTrail = (unsigned char*)tokenStart - 1; textTrail >= textStart; textTrail--) {
+ if (*textTrail > ' ') {
+ textTrail++;
+ *textTrail = 0;
+ CBuffer& decoded = m_decodeBuffer;
+ doctype->decodeEntities((char*)textStart, uint32_t(textTrail - textStart), decoded);
+ new CXmlText(currentNode,decoded.c_str());
break;
}
-
- /// Attributes
- tokenStart = tokenEnd + 1;
- nodeEnd = strchr(tokenStart,'>');
- if (!nodeEnd)
- throw CException("Invalid tag (started, not closed)");
- *nodeEnd = 0;
- CXmlNode* anode;
- if (*(nodeEnd-1) == '/') {
- anode = new CXmlElement(currentNode,nodeName);
- *(nodeEnd-1) = 0;
- } else {
- anode = currentNode = new CXmlElement(currentNode,nodeName);
- }
- processAttributes(anode,tokenStart);
- tokenEnd = nodeEnd;
- break;
}
- tokenStart = strchr(tokenEnd + 1,'<');
- if (!tokenStart) {
- if (currentNode == this)
- return;
- throw CException("Tag started but not closed");
- }
- unsigned char* textStart = (unsigned char*)tokenEnd + 1;
- while (*textStart <= ' ') /// Skip leading spaces
- textStart++;
- if (*textStart != '<')
- for (unsigned char* textTrail = (unsigned char*)tokenStart - 1; textTrail >= textStart; textTrail--) {
- if (*textTrail > ' ') {
- textTrail++;
- *textTrail = 0;
- CBuffer& decoded = m_decodeBuffer;
- doctype->decodeEntities((char*)textStart, uint32_t(textTrail - textStart), decoded);
- new CXmlText(currentNode,decoded.c_str());
- break;
- }
- }
- }
- } catch (...) {
- free(buffer);
- throw;
}
}
Index: sptk3/CWaiter.h
===================================================================
--- sptk3/CWaiter.h (revision 521)
+++ sptk3/CWaiter.h (working copy)
@@ -69,7 +69,7 @@
CWaiter();
/// @brief Destructor
- virtual ~CWaiter();
+ ~CWaiter();
/// @brief Tries to lock waiter. Blocks until the lock.
virtual void lock();
List hosted by Total Knowledge