[xml] xmlNodeSetContent trouble



I'm trying to learn by modifying the example code from the web site.  The 
following works (with parser warnings & error messages):

1. #include <stdio.h>
2. #include <libxml/parser.h>
3. #include <libxml/tree.h>
4. #include <libxml/xpath.h>
5. #include <assert.h>
6. 
7. 
8. /**
9.  * update_xpath_nodes:
10. * @nodes:           the nodes set.
11. * @value:           the new value for the node(s)
12. *
13. * Prints the @nodes content to @output.
14. */
15.static void
16.update_xpath_nodes(xmlNodeSetPtr nodes, const xmlChar* value) {
17.    int size;
18.    int i;
19.    
20.    assert(value);
21.    size = (nodes) ? nodes->nodeNr : 0;
22.    
23.    /*
24.     * NOTE: the nodes are processed in reverse order, i.e. reverse document
25.     *       order because xmlNodeSetContent can actually free up descendant
26.     *       of the node and such nodes may have been selected too ! Handling
27.     *       in reverse order ensure that descendant are accessed first, before
28.     *       they get removed. Mixing XPath and modifications on a tree must be
29.     *       done carefully !
30.     */
31.    for(i = size - 1; i >= 0; i--) {
32.     assert(nodes->nodeTab[i]);
33.     
34.     xmlNodeSetContent(nodes->nodeTab[i], value);
35.     /*
36.      * All the elements returned by an XPath query are pointers to
37.      * elements from the tree *except* namespace nodes where the XPath
38.      * semantic is different from the implementation in libxml2 tree.
39.      * As a result when a returned node set is freed when
40.      * xmlXPathFreeObject() is called, that routine must check the
41.      * element type. But node from the returned set may have been removed
42.      * by xmlNodeSetContent() resulting in access to freed data.
43.      * This can be exercised by running
44.      *       valgrind xpath2 test3.xml '//discarded' discarded
45.      * There is 2 ways around it:
46.      *   - make a copy of the pointers to the nodes from the result set 
47.      *     then call xmlXPathFreeObject() and then modify the nodes
48.      * or
49.      *   - remove the reference to the modified nodes from the node set
50.      *     as they are processed, if they are not namespace nodes.
51.      */
52.     if (nodes->nodeTab[i]->type != XML_NAMESPACE_DECL)
53.         nodes->nodeTab[i] = NULL;
54.    }
55.}
56.
57./**
58. * example1Func:
59. * @filename: a filename or an URL
60. *
61. * Parse the resource and free the resulting tree
62. */
63.static int
64.replaceValue(xmlDocPtr doc, const xmlChar * xpathExpr, const xmlChar * value) {
65.   xmlXPathContextPtr xpathCtx; 
66.   xmlXPathObjectPtr xpathObj; 
67.
68.    /* Create xpath evaluation context */
69.   xpathCtx = xmlXPathNewContext(doc);
70.   if(xpathCtx == NULL) {
71.      fprintf(stderr,"Error: unable to create new XPath context\n");
72.      xmlFreeDoc(doc); 
73.      return(-1);
74.   }
75.    
76.   /* Evaluate xpath expression */
77.   xpathObj = xmlXPathEvalExpression(xpathExpr, xpathCtx);
78.   if(xpathObj == NULL) {
79.      fprintf(stderr,"Error: unable to evaluate xpath expression \"%s\"\n", xpathExpr);
80.      xmlXPathFreeContext(xpathCtx); 
81.      xmlFreeDoc(doc); 
82.      return(-1);
83.   }
84.
85.    /* update selected nodes */
86.   update_xpath_nodes(xpathObj->nodesetval, value);
87.    
88.   /* Cleanup of XPath data */
89.   xmlXPathFreeObject(xpathObj);
90.   xmlXPathFreeContext(xpathCtx); 
91.   
92.   /* dump the resulting document */
93.   xmlDocDump(stdout, doc);
94.   
95.
96.   xmlFreeDoc(doc);
97.   return 0;
98.}
99.
100int main(int argc, char **argv) {
101   xmlDocPtr doc;
102   int retval;
103   if (argc != 2){
104      fprintf(stderr, "Usage: %s path\n", argv[0]);
105      return(1);
106   }
107
108    /*
109     * this initialize the library and check potential ABI mismatches
110     * between the version it was compiled for and the actual shared
111     * library used.
112     */
113    LIBXML_TEST_VERSION
114
115    //doc = xmlReadFile(argv[1], NULL, XML_PARSE_NOERROR + XML_PARSE_NOWARNING);
116    doc = xmlParseFile(argv[1]);
117    if (doc == NULL) {
118       fprintf(stderr, "Error: unable to parse file \"%s\"\n", argv[1]);
119       return(-1);
120    }
121
122    retval = replaceValue(doc, BAD_CAST "/gnc-v2/book/count-data[ type='account']/text()", BAD_CAST "*");
123
124    /*
125     * Cleanup function for the XML library.
126     */
127    xmlCleanupParser();
128    /*
129     * this is to debug memory for regression tests
130     */
131    xmlMemoryDump();
132    return(retval);
133}

However, if I use line 115 instead of 116, I get no parser messages, but get this:

*** glibc detected *** free(): invalid pointer: 0x08052c53 ***
which occurs at line 34.  Any suggestions?

Wayne



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