sptk



[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Mem leak fix in CXmlDoc



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

Authoright © Total Knowledge: 2005