Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Memory leak in xmpp framework by Robbiehanson

I have been using xmpp framework by Robbiehanson for mac.While checking with instruments tool in mac , I have observed a leak (around 64 bytes) in XMPPParser.m class which is increasing gradually with time.The code which leaks has been given below.

attrNs = xmlNewNs(NULL, NULL, nodePrefix); CHECK_FOR_NULL(attrNs);

Please provide a solution for this issue...

The method which contains this code is pasted below for reference:

static void xmpp_xmlStartElement(void *ctx, const xmlChar *nodeName,
const xmlChar *nodePrefix,
const xmlChar *nodeUri,
int nb_namespaces,
const xmlChar **namespaces,
int nb_attributes,
int nb_defaulted,
const xmlChar **attributes)
{

NSLog(@"IN xmppStartElement");
int i, j;
xmlNsPtr lastAddedNs = NULL;

xmlParserCtxt *ctxt = (xmlParserCtxt *)ctx;

// We store the parent node in the context's node pointer.
// We keep this updated by "pushing" the node in the startElement method,
// and "popping" the node in the endElement method.
xmlNodePtr parent = ctxt->node;

// Create the node
xmlNodePtr newNode = xmlNewDocNode(ctxt->myDoc, NULL, nodeName, NULL);
CHECK_FOR_NULL(newNode);

// Add the node to the tree
if(parent == NULL)
{
    // Root node
    xmlAddChild((xmlNodePtr)ctxt->myDoc, newNode);
}
else
{
    xmlAddChild(parent, newNode);
}

// Process the namespaces
for (i = 0, j = 0; j < nb_namespaces; j++)
{
    // Extract namespace prefix and uri
    const xmlChar *nsPrefix = namespaces[i++];
    const xmlChar *nsUri    = namespaces[i++];

    // Create the namespace
    xmlNsPtr newNs = xmlNewNs(NULL, nsUri, nsPrefix);
    CHECK_FOR_NULL(newNs);

    // Add namespace to node.
    // Each node has a linked list of nodes (in the nsDef variable).
    // The linked list is forward only.
    // In other words, each ns has a next, but not a prev pointer.

    if (newNode->nsDef == NULL)
    {
        newNode->nsDef = lastAddedNs = newNs;
    }
    else
    {
        lastAddedNs->next = newNs;
        lastAddedNs = newNs;
    }

    // Is this the namespace for the node?

    if (nodeUri && (nodePrefix == nsPrefix))
    {
        // Ex 1: node == <stream:stream xmlns:stream="url"> && newNs == stream:url
        // Ex 2: node == <starttls xmlns="url">             && newNs == null:url

        newNode->ns = newNs;
    }
}

// Search for the node's namespace if it wasn't already found
if ((nodeUri) && (newNode->ns == NULL))
{
    newNode->ns = xmpp_xmlSearchNs(ctxt->myDoc, newNode, nodePrefix);

    if (newNode->ns == NULL)
    {
        // We use href==NULL in the case of an element creation where the namespace was not defined.
        //
        // We do NOT use xmlNewNs(newNode, nodeUri, nodePrefix) because that method doesn't properly add
        // the namespace to BOTH nsDef and ns.

        xmlNsPtr newNs = xmlNewNs(NULL, nodeUri, nodePrefix);
        CHECK_FOR_NULL(newNs);

        if (newNode->nsDef == NULL)
        {
            newNode->nsDef = lastAddedNs = newNs;
        }
        else
        {
            lastAddedNs->next = newNs;
            lastAddedNs = newNs;
        }

        newNode->ns = newNs;
    }
}

// Process all the attributes
for (i = 0, j = 0; j < nb_attributes; j++)
{
    const xmlChar *attrName   = attributes[i++];
    const xmlChar *attrPrefix = attributes[i++];
    const xmlChar *attrUri    = attributes[i++];
    const xmlChar *valueBegin = attributes[i++];
    const xmlChar *valueEnd   = attributes[i++];

    // The attribute value might contain character references which need to be decoded.
    //
    // "Franks &#38; Beans" -> "Franks & Beans"

    xmlChar *value = xmlStringLenDecodeEntities(ctxt,                    // the parser context
                                                valueBegin,              // the input string
                                          (int)(valueEnd - valueBegin),  // the input string length
                                               (XML_SUBSTITUTE_REF),     // what to substitue
                                                0, 0, 0);                // end markers, 0 if none
    CHECK_FOR_NULL(value);

    if ((attrPrefix == NULL) && (attrUri == NULL))
    {
        // Normal attribute - no associated namespace
        xmlAttrPtr newAttr = xmlNewProp(newNode, attrName, value);
        CHECK_FOR_NULL(newAttr);
    }
    else
    {
        // Find the namespace for the attribute
        xmlNsPtr attrNs = xmpp_xmlSearchNs(ctxt->myDoc, newNode, attrPrefix);

        if (attrNs != NULL)
        {
            xmlAttrPtr newAttr = xmlNewNsProp(newNode, attrNs, attrName, value);
            CHECK_FOR_NULL(newAttr);
        }
        else
        {
            **attrNs = xmlNewNs(NULL, NULL, nodePrefix);
            CHECK_FOR_NULL(attrNs);**

            xmlAttrPtr newAttr = xmlNewNsProp(newNode, attrNs, attrName, value);
            CHECK_FOR_NULL(newAttr);

        }
    }

    xmlFree(value);

}

// Update our parent node pointer
ctxt->node = newNode;

// Invoke delegate methods if needed
xmpp_postStartElement(ctxt);

}
like image 623
sreenath Avatar asked Oct 22 '22 13:10

sreenath


1 Answers

Try adding xmlFreeNs(attrNs); below the last CHECK_FOR_NULL(newAttr);.

like image 164
Sas0ri Avatar answered Nov 02 '22 11:11

Sas0ri