| 2689 | } |
| 2690 | |
| 2691 | xmlNode * |
| 2692 | getXpathResult(xmlXPathObjectPtr xpathObj, int index) |
| 2693 | { |
| 2694 | xmlNode *match = NULL; |
| 2695 | CRM_CHECK(index >= 0, return NULL); |
| 2696 | CRM_CHECK(xpathObj != NULL, return NULL); |
| 2697 | |
| 2698 | if(index >= xpathObj->nodesetval->nodeNr) { |
| 2699 | crm_err("Requested index %d of only %d items", index, xpathObj->nodesetval->nodeNr); |
| 2700 | return NULL; |
| 2701 | } |
| 2702 | |
| 2703 | match = xpathObj->nodesetval->nodeTab[index]; |
| 2704 | CRM_CHECK(match != NULL, return NULL); |
| 2705 | |
| 2706 | /* |
| 2707 | * From xpath2.c |
| 2708 | * |
| 2709 | * All the elements returned by an XPath query are pointers to |
| 2710 | * elements from the tree *except* namespace nodes where the XPath |
| 2711 | * semantic is different from the implementation in libxml2 tree. |
| 2712 | * As a result when a returned node set is freed when |
| 2713 | * xmlXPathFreeObject() is called, that routine must check the |
| 2714 | * element type. But node from the returned set may have been removed |
| 2715 | * by xmlNodeSetContent() resulting in access to freed data. |
| 2716 | * This can be exercised by running |
| 2717 | * valgrind xpath2 test3.xml '//discarded' discarded |
| 2718 | * There is 2 ways around it: |
| 2719 | * - make a copy of the pointers to the nodes from the result set |
| 2720 | * then call xmlXPathFreeObject() and then modify the nodes |
| 2721 | * or |
| 2722 | * - remove the reference to the modified nodes from the node set |
| 2723 | * as they are processed, if they are not namespace nodes. |
| 2724 | */ |
| 2725 | if (xpathObj->nodesetval->nodeTab[index]->type != XML_NAMESPACE_DECL) { |
| 2726 | xpathObj->nodesetval->nodeTab[index] = NULL; |
| 2727 | } |
| 2728 | |
| 2729 | if(match->type == XML_DOCUMENT_NODE) { |
| 2730 | /* Will happen if section = '/' */ |
| 2731 | match = match->children; |
| 2732 | |
| 2733 | } else if(match->type != XML_ELEMENT_NODE |
| 2734 | && match->parent |
| 2735 | && match->parent->type == XML_ELEMENT_NODE) { |
| 2736 | /* reurning the parent instead */ |
| 2737 | match = match->parent; |
| 2738 | |
| 2739 | } else if(match->type != XML_ELEMENT_NODE) { |
| 2740 | /* We only support searching nodes */ |
| 2741 | crm_err("We only support %d not %d", XML_ELEMENT_NODE, match->type); |
| 2742 | match = NULL; |
| 2743 | } |
| 2744 | return match; |
| 2745 | } |
| 2746 | |
| 2747 | /* the caller needs to check if the result contains a xmlDocPtr or xmlNodePtr */ |
| 2748 | xmlXPathObjectPtr |
no outgoing calls
no test coverage detected