[xml] Memory reference after xmlFree in XPath evaluation



All,

I have found a case in XPath evaluation that leads to references to memory that has been xmlFree()d. The particular case I have found is when filtering a node-set returned by a function using an expression similar to
        func()[ name='xxx']
or
        func()/yyy
however, there may also be other cases.

The problem arises when func() generates a node-set from scratch rather than merely referencing nodes in the document being processed. In this case the function will use code like

    ret = xmlXPathNewNodeSet (NULL);
    if (ret != NULL) {
        ret->boolval = 1;
        /* possibly create a fake node and assign to ret->user */
    }
    /* nodes created and added to the node-set here */
    valuePush (ctxt, ret);

as is the case in some libexslt code. During evaluation of the XPath filter on the node-set returned by the function, there is code which creates a new node-set as a subset of the original. Code similar to the following is then used to place the new node-set on the stack (taken from xpath.c:10487)

                    xmlXPathFreeObject(obj);
                    ctxt->context->node = NULL;
                    ctxt->context->contextSize = -1;
                    ctxt->context->proximityPosition = -1;
                    valuePush(ctxt, xmlXPathWrapNodeSet(newset));

Unfortunately after xmlXPathFreeObject(obj) is called to destroy the original node-set the new node-set is left with dangling references to nodes which have been freed causing a SIGSEGV in some cases. I have found three instances of code like this in xpath.c however there may be other more subtle cases.

I am unsure about the best way to solve this problem as the simpler solutions I have thought of all lead to memory leaks. I suspect the best approach is to NULL out entries in obj->nodesetval if they are added to newset. Then instead of calling XmlXPathFreeObject(), the remaining nodes from the old node-set are freed by the same algorithm used in xmlXPathFreeObject() for nodes of type XPATH_NODESET or XPATH_XSLT_TREE. I am unclear as to what should be done with the value of obj->user; obviously, if a fake node is created as in the libexslt string:tokenize() implementation then it must be preserved but I cannot say whether this is always the case.

I suspect similar considerations as outlined above apply to XPATH_LOCATIONSET XPath objects.

Unfortunately I am not yet sufficiently familiar with the code in xpath.c to be able to offer a patch. (Hopefully soon though.)

Regards
Brian Stafford





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