xref: /aosp_15_r20/external/libxml2/fuzz/api.c (revision 7c5688314b92172186c154356a6374bf7684c3ca)
1 /*
2  * api.c: a libFuzzer target to test node-related API functions.
3  *
4  * See Copyright for the status of this software.
5  *
6  * This is a simple virtual machine which runs fuzz data as a program.
7  * An important design goal is to execute as many API calls as possible
8  * per input byte.
9  *
10  * We use a fixed number of registers for basic types like integers
11  * or strings as well as libxml2 objects like xmlNode. The opcodes are
12  * single bytes which typically result in a call to an API function
13  * using the freshest registers for each argument type and storing the
14  * result in the stalest register. This can be implemented using a ring
15  * buffer.
16  *
17  * There are a few other opcodes to initialize or duplicate registers,
18  * so all kinds of API calls can potentially be generated from fuzz
19  * data.
20  *
21  * This architecture is similar to stack machine and benefits from
22  * great code density. The main difference is that values aren't
23  * destroyed when popping arguments from the stack and that the bottom
24  * of the stack is eventually overwritten if the ring buffer overflows.
25  *
26  * The main complication is memory management of nodes. Whenever a
27  * reference between two nodes is removed, whether by an API call or
28  * the VM clearing a register, we must check whether this leaves
29  * unreferenced nodes which can then be freed. There are no opcodes
30  * to free a node explicitly. The FIFO patterns generated by
31  * overflowing the ring buffer and freeing the registers at the end of
32  * a program seem to do a good enough job.
33  */
34 
35 #include <stdlib.h>
36 #include <string.h>
37 
38 #define XML_DEPRECATED
39 
40 #include <libxml/catalog.h>
41 #include <libxml/HTMLtree.h>
42 #include <libxml/parser.h>
43 #include <libxml/tree.h>
44 #include <libxml/xmlerror.h>
45 #include "fuzz.h"
46 
47 #if 0
48   #define DEBUG printf
49 #else
50   #define DEBUG(...)
51 #endif
52 
53 #define MAX_CONTENT     100
54 #define MAX_COPY_NODES   50
55 #define MAX_COPY_OPS     20
56 
57 typedef enum {
58     /* Basic operations */
59     OP_CREATE_INTEGER,
60     OP_CREATE_STRING,
61     OP_DUP_INTEGER,
62     OP_DUP_STRING,
63     OP_DUP_NODE,
64 
65     /*** tree.h ***/
66 
67     /* Tree constructors */
68     OP_XML_NEW_DOC,
69     OP_XML_NEW_NODE,
70     OP_XML_NEW_NODE_EAT_NAME,
71     OP_XML_NEW_DOC_NODE,
72     OP_XML_NEW_DOC_NODE_EAT_NAME,
73     OP_XML_NEW_DOC_RAW_NODE,
74     OP_XML_NEW_CHILD,
75     OP_XML_NEW_TEXT_CHILD,
76     OP_XML_NEW_PROP,
77     OP_XML_NEW_DOC_PROP,
78     OP_XML_NEW_NS_PROP,
79     OP_XML_NEW_NS_PROP_EAT_NAME,
80     OP_XML_NEW_TEXT,
81     OP_XML_NEW_TEXT_LEN,
82     OP_XML_NEW_DOC_TEXT,
83     OP_XML_NEW_DOC_TEXT_LEN,
84     OP_XML_NEW_PI,
85     OP_XML_NEW_DOC_PI,
86     OP_XML_NEW_COMMENT,
87     OP_XML_NEW_DOC_COMMENT,
88     OP_XML_NEW_CDATA_BLOCK,
89     OP_XML_NEW_CHAR_REF,
90     OP_XML_NEW_REFERENCE,
91     OP_XML_NEW_DOC_FRAGMENT,
92     OP_XML_CREATE_INT_SUBSET,
93     OP_XML_NEW_DTD,
94 
95     /* Node copying */
96     OP_XML_COPY_DOC,
97     OP_XML_COPY_NODE,
98     OP_XML_COPY_NODE_LIST,
99     OP_XML_DOC_COPY_NODE,
100     OP_XML_DOC_COPY_NODE_LIST,
101     OP_XML_COPY_PROP,
102     OP_XML_COPY_PROP_LIST,
103     OP_XML_COPY_DTD,
104 
105     /* Node accessors */
106     OP_NODE_PARENT,
107     OP_NODE_NEXT_SIBLING,
108     OP_NODE_PREV_SIBLING,
109     OP_NODE_FIRST_CHILD,
110     OP_XML_GET_LAST_CHILD,
111     OP_NODE_NAME,
112     OP_XML_NODE_SET_NAME,
113     OP_XML_NODE_GET_CONTENT,
114     OP_XML_NODE_SET_CONTENT,
115     OP_XML_NODE_SET_CONTENT_LEN,
116     OP_XML_NODE_ADD_CONTENT,
117     OP_XML_NODE_ADD_CONTENT_LEN,
118     OP_XML_GET_INT_SUBSET,
119     OP_XML_GET_LINE_NO,
120     OP_XML_GET_NODE_PATH,
121     OP_XML_DOC_GET_ROOT_ELEMENT,
122     OP_XML_DOC_SET_ROOT_ELEMENT,
123     OP_XML_NODE_IS_TEXT,
124     OP_XML_NODE_GET_ATTR_VALUE,
125     OP_XML_NODE_GET_LANG,
126     OP_XML_NODE_SET_LANG,
127     OP_XML_NODE_GET_SPACE_PRESERVE,
128     OP_XML_NODE_SET_SPACE_PRESERVE,
129     OP_XML_NODE_GET_BASE,
130     OP_XML_NODE_GET_BASE_SAFE,
131     OP_XML_NODE_SET_BASE,
132     OP_XML_IS_BLANK_NODE,
133 
134     /* Attributes */
135     OP_XML_HAS_PROP,
136     OP_XML_HAS_NS_PROP,
137     OP_XML_GET_PROP,
138     OP_XML_GET_NS_PROP,
139     OP_XML_GET_NO_NS_PROP,
140     OP_XML_SET_PROP,
141     OP_XML_SET_NS_PROP,
142     OP_XML_REMOVE_PROP,
143     OP_XML_UNSET_PROP,
144     OP_XML_UNSET_NS_PROP,
145 
146     /* Namespaces */
147     OP_XML_NEW_NS,
148     OP_XML_SEARCH_NS,
149     OP_XML_SEARCH_NS_BY_HREF,
150     OP_XML_GET_NS_LIST,
151     OP_XML_GET_NS_LIST_SAFE,
152     OP_XML_SET_NS,
153     OP_XML_COPY_NAMESPACE,
154     OP_XML_COPY_NAMESPACE_LIST,
155 
156     /* Tree manipulation */
157     OP_XML_UNLINK_NODE,
158     OP_XML_ADD_CHILD,
159     OP_XML_ADD_CHILD_LIST,
160     OP_XML_REPLACE_NODE,
161     OP_XML_ADD_SIBLING,
162     OP_XML_ADD_PREV_SIBLING,
163     OP_XML_ADD_NEXT_SIBLING,
164 
165     /* String output */
166     OP_XML_DOC_DUMP_MEMORY,
167     OP_XML_DOC_DUMP_MEMORY_ENC,
168     OP_XML_DOC_DUMP_FORMAT_MEMORY,
169     OP_XML_DOC_DUMP_FORMAT_MEMORY_ENC,
170 
171     /* FILE output, TODO, use fmemopen */
172     OP_XML_DOC_DUMP,
173     OP_XML_DOC_FORMAT_DUMP,
174     OP_XML_ELEM_DUMP,
175 
176     /* xmlBuf output, TODO, no public API */
177     OP_XML_BUF_NODE_DUMP,
178     OP_XML_BUF_GET_NODE_CONTENT,
179 
180     /* xmlBuffer output */
181     OP_XML_NODE_DUMP,
182     OP_XML_NODE_BUF_GET_CONTENT,
183     OP_XML_ATTR_SERIALIZE_TXT_CONTENT,
184     OP_XML_DUMP_ELEMENT_DECL,
185     OP_XML_DUMP_ELEMENT_TABLE,
186     OP_XML_DUMP_ATTRIBUTE_DECL,
187     OP_XML_DUMP_ATTRIBUTE_TABLE,
188     OP_XML_DUMP_NOTATION_DECL,
189     OP_XML_DUMP_NOTATION_TABLE,
190     OP_XML_DUMP_ENTITY_DECL,
191     OP_XML_DUMP_ENTITIES_TABLE,
192 
193     /* xmlOutputBuffer */
194     OP_XML_SAVE_FILE_TO,
195     OP_XML_SAVE_FORMAT_FILE_TO,
196     OP_XML_NODE_DUMP_OUTPUT,
197 
198     /* Misc */
199     OP_XML_TEXT_MERGE,
200     OP_XML_TEXT_CONCAT,
201     OP_XML_STRING_GET_NODE_LIST,
202     OP_XML_STRING_LEN_GET_NODE_LIST,
203     OP_XML_NODE_LIST_GET_STRING,
204     OP_XML_NODE_LIST_GET_RAW_STRING,
205     OP_XML_IS_XHTML,
206 
207     /* DOM */
208     OP_XML_DOM_WRAP_RECONCILE_NAMESPACES,
209     OP_XML_DOM_WRAP_ADOPT_NODE,
210     OP_XML_DOM_WRAP_REMOVE_NODE,
211     OP_XML_DOM_WRAP_CLONE_NODE,
212     OP_XML_CHILD_ELEMENT_COUNT,
213     OP_XML_FIRST_ELEMENT_CHILD,
214     OP_XML_LAST_ELEMENT_CHILD,
215     OP_XML_NEXT_ELEMENT_SIBLING,
216     OP_XML_PREVIOUS_ELEMENT_SIBLING,
217 
218     /*** parser.h ***/
219 
220     OP_PARSE_DOCUMENT,
221 
222     /*** valid.h ***/
223 
224     OP_XML_ADD_ELEMENT_DECL,
225     OP_XML_ADD_ATTRIBUTE_DECL,
226     OP_XML_ADD_NOTATION_DECL,
227 
228     OP_XML_GET_DTD_ELEMENT_DESC,
229     OP_XML_GET_DTD_QELEMENT_DESC,
230     OP_XML_GET_DTD_ATTR_DESC,
231     OP_XML_GET_DTD_QATTR_DESC,
232     OP_XML_GET_DTD_NOTATION_DESC,
233 
234     OP_XML_ADD_ID,
235     OP_XML_ADD_ID_SAFE,
236     OP_XML_GET_ID,
237     OP_XML_IS_ID,
238     OP_XML_REMOVE_ID,
239 
240     OP_XML_ADD_REF,
241     OP_XML_GET_REFS,
242     OP_XML_IS_REF,
243     OP_XML_REMOVE_REF,
244 
245     OP_XML_IS_MIXED_ELEMENT,
246 
247     OP_VALIDATE,
248     OP_XML_VALIDATE_ATTRIBUTE_VALUE,
249     OP_XML_VALIDATE_DTD,
250     OP_XML_VALIDATE_NOTATION_USE,
251 
252     OP_XML_VALIDATE_NAME_VALUE,
253     OP_XML_VALIDATE_NAMES_VALUE,
254     OP_XML_VALIDATE_NMTOKEN_VALUE,
255     OP_XML_VALIDATE_NMTOKENS_VALUE,
256 
257     OP_XML_VALID_NORMALIZE_ATTRIBUTE_VALUE,
258     OP_XML_VALID_CTXT_NORMALIZE_ATTRIBUTE_VALUE,
259     OP_XML_VALID_GET_POTENTIAL_CHILDREN,
260     OP_XML_VALID_GET_VALID_ELEMENTS,
261 
262     /*** entities.h ***/
263 
264     OP_XML_NEW_ENTITY,
265     OP_XML_ADD_ENTITY,
266     OP_XML_ADD_DOC_ENTITY,
267     OP_XML_ADD_DTD_ENTITY,
268 
269     OP_XML_GET_PREDEFINED_ENTITY,
270     OP_XML_GET_DOC_ENTITY,
271     OP_XML_GET_DTD_ENTITY,
272     OP_XML_GET_PARAMETER_ENTITY,
273 
274     OP_XML_ENCODE_ENTITIES_REENTRANT,
275     OP_XML_ENCODE_SPECIAL_CHARS,
276 
277     /*** HTMLtree.h ***/
278 
279     OP_HTML_NEW_DOC,
280     OP_HTML_NEW_DOC_NO_DTD,
281     OP_HTML_GET_META_ENCODING,
282     OP_HTML_SET_META_ENCODING,
283     OP_HTML_IS_BOOLEAN_ATTR,
284 
285     OP_HTML_DOC_DUMP_MEMORY,
286     OP_HTML_DOC_DUMP_MEMORY_FORMAT,
287     OP_HTML_DOC_DUMP,
288     OP_HTML_NODE_DUMP_FILE,
289     OP_HTML_NODE_DUMP_FILE_FORMAT,
290     OP_HTML_NODE_DUMP,
291     OP_HTML_DOC_CONTENT_DUMP_OUTPUT,
292     OP_HTML_DOC_CONTENT_DUMP_FORMAT_OUTPUT,
293     OP_HTML_NODE_DUMP_OUTPUT,
294     OP_HTML_NODE_DUMP_FORMAT_OUTPUT,
295 
296     OP_MAX
297 } opType;
298 
299 #define NODE_MASK_TEXT_CONTENT ( \
300     (1 << XML_TEXT_NODE) | \
301     (1 << XML_CDATA_SECTION_NODE) | \
302     (1 << XML_COMMENT_NODE) | \
303     (1 << XML_PI_NODE))
304 
305 #define CHILD_MASK_DOCUMENT ( \
306     (1 << XML_ELEMENT_NODE) | \
307     (1 << XML_PI_NODE) | \
308     (1 << XML_COMMENT_NODE))
309 
310 #define CHILD_MASK_CONTENT ( \
311     (1 << XML_ELEMENT_NODE) | \
312     (1 << XML_TEXT_NODE) | \
313     (1 << XML_CDATA_SECTION_NODE) | \
314     (1 << XML_ENTITY_REF_NODE) | \
315     (1 << XML_PI_NODE) | \
316     (1 << XML_COMMENT_NODE))
317 
318 #define CHILD_MASK_ELEMENT ( \
319     CHILD_MASK_CONTENT | \
320     (1 << XML_ATTRIBUTE_NODE))
321 
322 #define CHILD_MASK_ATTRIBUTE ( \
323     (1 << XML_TEXT_NODE) | \
324     (1 << XML_ENTITY_REF_NODE))
325 
326 #define CHILD_MASK_DTD ( \
327     (1 << XML_ELEMENT_DECL) | \
328     (1 << XML_ATTRIBUTE_DECL) | \
329     (1 << XML_ENTITY_DECL))
330 
331 static const int childMasks[] = {
332     0,
333     CHILD_MASK_ELEMENT, /* XML_ELEMENT_NODE */
334     CHILD_MASK_ATTRIBUTE, /* XML_ATTRIBUTE_NODE */
335     0, /* XML_TEXT_NODE */
336     0, /* XML_CDATA_SECTION_NODE */
337     0, /* XML_ENTITY_REF_NODE */
338     0, /* XML_ENTITY_NODE */
339     0, /* XML_PI_NODE */
340     0, /* XML_COMMENT_NODE */
341     CHILD_MASK_DOCUMENT, /* XML_DOCUMENT_NODE */
342     0, /* XML_DOCUMENT_TYPE_NODE */
343     CHILD_MASK_CONTENT, /* XML_DOCUMENT_FRAG_NODE */
344     0, /* XML_NOTATION_NODE */
345     CHILD_MASK_DOCUMENT, /* XML_HTML_DOCUMENT_NODE */
346     0, /* XML_DTD_NODE */
347     0, /* XML_ELEMENT_DECL */
348     0, /* XML_ATTRIBUTE_DECL */
349     0, /* XML_ENTITY_DECL */
350     0, /* XML_NAMESPACE_DECL */
351     0, /* XML_XINCLUDE_START */
352     0, /* XML_XINCLUDE_END */
353     CHILD_MASK_DOCUMENT /* XML_DOCB_DOCUMENT_NODE */
354 };
355 
356 #define REG_MAX 8
357 #define REG_MASK (REG_MAX - 1)
358 
359 typedef struct {
360     /* Indexes point beyond the most recent item */
361     int intIdx;
362     int stringIdx;
363     int nodeIdx;
364 
365     int numCopyOps;
366 
367     const char *opName;
368 
369     /* Registers */
370     int integers[REG_MAX];
371     xmlChar *strings[REG_MAX];
372     xmlNodePtr nodes[REG_MAX];
373 } xmlFuzzApiVars;
374 
375 static xmlFuzzApiVars varsStruct;
376 static xmlFuzzApiVars *const vars = &varsStruct;
377 
378 /* Debug output */
379 
380 static void
startOp(const char * name)381 startOp(const char *name) {
382     vars->opName = name;
383     DEBUG("%s(", name);
384 }
385 
386 static void
endOp(void)387 endOp(void) {
388     DEBUG(" )\n");
389 }
390 
391 /* Integers */
392 
393 static int
getInt(int offset)394 getInt(int offset) {
395     int idx = (vars->intIdx - offset - 1) & REG_MASK;
396     DEBUG(" %d", vars->integers[idx]);
397     return vars->integers[idx];
398 }
399 
400 static void
setInt(int offset,int n)401 setInt(int offset, int n) {
402     int idx = (vars->intIdx - offset - 1) & REG_MASK;
403     vars->integers[idx] = n;
404 }
405 
406 static void
incIntIdx(void)407 incIntIdx(void) {
408     vars->intIdx = (vars->intIdx + 1) & REG_MASK;
409 }
410 
411 /* Strings */
412 
413 static const xmlChar *
getStr(int offset)414 getStr(int offset) {
415     int idx = (vars->stringIdx - offset - 1) & REG_MASK;
416     const xmlChar *str = vars->strings[idx];
417 
418     if (str == NULL)
419         DEBUG(" NULL");
420     else
421         DEBUG(" \"%.20s\"", str);
422 
423     return str;
424 }
425 
426 static const char *
getCStr(int offset)427 getCStr(int offset) {
428     return (const char *) getStr(offset);
429 }
430 
431 static void
setStr(int offset,xmlChar * str)432 setStr(int offset, xmlChar *str) {
433     xmlChar **strings = vars->strings;
434     int idx = (vars->stringIdx - offset - 1) & REG_MASK;
435     xmlChar *oldString = strings[idx];
436 
437     strings[idx] = str;
438     if (oldString)
439         xmlFree(oldString);
440 }
441 
442 static void
moveStr(int offset,xmlChar * str)443 moveStr(int offset, xmlChar *str) {
444     if (xmlStrlen(str) > 1000) {
445         setStr(offset, NULL);
446         xmlFree(str);
447     } else {
448         setStr(offset, str);
449     }
450 }
451 
452 /*
453  * This doesn't use xmlMalloc and can't fail because of malloc failure
454  * injection.
455  */
456 static xmlChar *
uncheckedStrndup(const xmlChar * str,int size)457 uncheckedStrndup(const xmlChar *str, int size) {
458     xmlChar *copy;
459 
460     if (str == NULL)
461         return NULL;
462 
463     copy = BAD_CAST strndup((const char *) str, size);
464     if (copy == NULL) {
465         fprintf(stderr, "out of memory\n");
466         abort();
467     }
468 
469     return copy;
470 }
471 
472 static xmlChar *
uncheckedStrdup(const xmlChar * str)473 uncheckedStrdup(const xmlChar *str) {
474     return uncheckedStrndup(str, MAX_CONTENT);
475 }
476 
477 static void
copyStr(int offset,const xmlChar * str)478 copyStr(int offset, const xmlChar *str) {
479     setStr(offset, uncheckedStrdup(str));
480 }
481 
482 static void
incStrIdx(void)483 incStrIdx(void) {
484     vars->stringIdx = (vars->stringIdx + 1) & REG_MASK;
485 }
486 
487 /* Nodes */
488 
489 static void
490 dropNode(xmlNodePtr node);
491 
492 static xmlNodePtr
getNode(int offset)493 getNode(int offset) {
494     int idx = (vars->nodeIdx - offset - 1) & REG_MASK;
495     if (vars->nodes[idx])
496         DEBUG(" n%d", idx);
497     else
498         DEBUG(" NULL");
499     fflush(stdout);
500     return vars->nodes[idx];
501 }
502 
503 static xmlDocPtr
getDoc(int offset)504 getDoc(int offset) {
505     xmlNodePtr node = getNode(offset);
506 
507     if (node == NULL)
508         return NULL;
509     return node->doc;
510 }
511 
512 static xmlAttrPtr
getAttr(int offset)513 getAttr(int offset) {
514     xmlNodePtr node = getNode(offset);
515 
516     if (node == NULL)
517         return NULL;
518     if (node->type == XML_ATTRIBUTE_NODE)
519         return (xmlAttrPtr) node;
520     if (node->type == XML_ELEMENT_NODE)
521         return node->properties;
522 
523     return NULL;
524 }
525 
526 static xmlDtdPtr
getDtd(int offset)527 getDtd(int offset) {
528     xmlNodePtr node = getNode(offset);
529     xmlDocPtr doc;
530 
531     if (node == NULL)
532         return NULL;
533 
534     if (node->type == XML_DTD_NODE)
535         return (xmlDtdPtr) node;
536 
537     doc = node->doc;
538     if (doc == NULL)
539         return NULL;
540     if (doc->intSubset != NULL)
541         return doc->intSubset;
542     return doc->extSubset;
543 }
544 
545 static void
setNode(int offset,xmlNodePtr node)546 setNode(int offset, xmlNodePtr node) {
547     int idx = (vars->nodeIdx - offset - 1) & REG_MASK;
548     xmlNodePtr oldNode = vars->nodes[idx];
549 
550     if (node != oldNode) {
551         vars->nodes[idx] = node;
552         dropNode(oldNode);
553     }
554 
555     if (node == NULL)
556         DEBUG(" ) /* NULL */\n");
557     else
558         DEBUG(" ) -> n%d\n", idx);
559 }
560 
561 static void
incNodeIdx(void)562 incNodeIdx(void) {
563     xmlNodePtr oldNode;
564     int idx;
565 
566     idx = vars->nodeIdx & REG_MASK;
567     vars->nodeIdx = (idx + 1) & REG_MASK;
568     oldNode = vars->nodes[idx];
569 
570     if (oldNode != NULL) {
571         vars->nodes[idx] = NULL;
572         dropNode(oldNode);
573     }
574 }
575 
576 static int
isValidChildType(xmlNodePtr parent,int childType)577 isValidChildType(xmlNodePtr parent, int childType) {
578     return ((1 << childType) & childMasks[parent->type]) != 0;
579 }
580 
581 static int
isValidChild(xmlNodePtr parent,xmlNodePtr child)582 isValidChild(xmlNodePtr parent, xmlNodePtr child) {
583     xmlNodePtr cur;
584 
585     if (child == NULL || parent == NULL)
586         return 1;
587 
588     if (parent == child)
589         return 0;
590 
591     if (((1 << child->type) & childMasks[parent->type]) == 0)
592         return 0;
593 
594     if (child->children == NULL)
595         return 1;
596 
597     for (cur = parent->parent; cur != NULL; cur = cur->parent)
598         if (cur == child)
599             return 0;
600 
601     return 1;
602 }
603 
604 static int
isTextContentNode(xmlNodePtr child)605 isTextContentNode(xmlNodePtr child) {
606     if (child == NULL)
607         return 0;
608 
609     return ((1 << child->type) & NODE_MASK_TEXT_CONTENT) != 0;
610 }
611 
612 static int
isDtdChild(xmlNodePtr child)613 isDtdChild(xmlNodePtr child) {
614     if (child == NULL)
615         return 0;
616 
617     return ((1 << child->type) & CHILD_MASK_DTD) != 0;
618 }
619 
620 static xmlNodePtr
nodeGetTree(xmlNodePtr node)621 nodeGetTree(xmlNodePtr node) {
622     xmlNodePtr cur = node;
623 
624     while (cur->parent)
625         cur = cur->parent;
626     return cur;
627 }
628 
629 /*
630  * This function is called whenever a reference to a node is removed.
631  * It checks whether the node is still reachable and frees unreferenced
632  * nodes.
633  *
634  * A node is reachable if its tree, identified by the root node,
635  * is reachable. If a non-document tree is unreachable, it can be
636  * freed.
637  *
638  * Multiple trees can share the same document, so a document tree
639  * can only be freed if no other trees reference the document.
640  */
641 static void
dropNode(xmlNodePtr node)642 dropNode(xmlNodePtr node) {
643     xmlNodePtr *nodes = vars->nodes;
644     xmlNodePtr tree;
645     xmlDocPtr doc;
646     int docReferenced = 0;
647     int i;
648 
649     if (node == NULL)
650         return;
651 
652     tree = nodeGetTree(node);
653     doc = node->doc;
654 
655     for (i = 0; i < REG_MAX; i++) {
656         xmlNodePtr other;
657 
658         other = nodes[i];
659         if (other == NULL)
660             continue;
661 
662         /*
663          * Return if tree is referenced from another node
664          */
665         if (nodeGetTree(other) == tree)
666             return;
667         if (doc != NULL && other->doc == doc)
668             docReferenced = 1;
669     }
670 
671     if (tree != (xmlNodePtr) doc && !isDtdChild(tree)) {
672         if (doc == NULL || tree->type != XML_DTD_NODE ||
673             ((xmlDtdPtr) tree != doc->intSubset &&
674              (xmlDtdPtr) tree != doc->extSubset))
675             xmlFreeNode(tree);
676     }
677 
678     /*
679      * Also free document if it isn't referenced from other nodes
680      */
681     if (doc != NULL && !docReferenced)
682         xmlFreeDoc(doc);
683 }
684 
685 /*
686  * removeNode and removeChildren remove all references to a node
687  * or its children from the registers. These functions should be
688  * called if an API function destroys nodes, for example by merging
689  * text nodes.
690  */
691 
692 static void
removeNode(xmlNodePtr node)693 removeNode(xmlNodePtr node) {
694     int i;
695 
696     for (i = 0; i < REG_MAX; i++)
697         if (vars->nodes[i] == node)
698             vars->nodes[i] = NULL;
699 }
700 
701 static void
removeChildren(xmlNodePtr parent,int self)702 removeChildren(xmlNodePtr parent, int self) {
703     int i;
704 
705     if (parent == NULL || (!self && parent->children == NULL))
706         return;
707 
708     for (i = 0; i < REG_MAX; i++) {
709         xmlNodePtr node = vars->nodes[i];
710 
711         if (node == parent) {
712             if (self)
713                 vars->nodes[i] = NULL;
714             continue;
715         }
716 
717         while (node != NULL) {
718             node = node->parent;
719             if (node == parent) {
720                 vars->nodes[i] = NULL;
721                 break;
722             }
723         }
724     }
725 }
726 
727 static xmlNsPtr
nodeGetNs(xmlNodePtr node,int k)728 nodeGetNs(xmlNodePtr node, int k) {
729     int i = 0;
730     xmlNsPtr ns, next;
731 
732     if (node == NULL || node->type != XML_ELEMENT_NODE)
733         return NULL;
734 
735     ns = NULL;
736     next = node->nsDef;
737     while (1) {
738         while (next == NULL) {
739             node = node->parent;
740             if (node == NULL || node->type != XML_ELEMENT_NODE)
741                 break;
742             next = node->nsDef;
743         }
744 
745         if (next == NULL)
746             break;
747 
748         ns = next;
749         if (i == k)
750             break;
751 
752         next = ns->next;
753         i += 1;
754     }
755 
756     return ns;
757 }
758 
759 /*
760  * It's easy for programs to exhibit exponential growth patterns.
761  * For example, a tree being copied and added to the original source
762  * node doubles memory usage with two operations. Repeating these
763  * operations leads to 2^n nodes. Similar issues can arise when
764  * concatenating strings.
765  *
766  * We simply ignore tree copies or truncate text if they grow too
767  * large.
768  */
769 
770 static void
checkContent(xmlNodePtr node)771 checkContent(xmlNodePtr node) {
772     if (node != NULL &&
773         (node->type == XML_TEXT_NODE ||
774          node->type == XML_CDATA_SECTION_NODE ||
775          node->type == XML_ENTITY_NODE ||
776          node->type == XML_PI_NODE ||
777          node->type == XML_COMMENT_NODE ||
778          node->type == XML_NOTATION_NODE) &&
779         xmlStrlen(node->content) > MAX_CONTENT) {
780         xmlNodeSetContent(node, NULL);
781         node->content = uncheckedStrdup(BAD_CAST "");
782     }
783 }
784 
785 static int
countNodes(xmlNodePtr node)786 countNodes(xmlNodePtr node) {
787     xmlNodePtr cur;
788     int numNodes;
789 
790     if (node == NULL)
791         return 0;
792 
793     cur = node;
794     numNodes = 0;
795 
796     while (1) {
797         numNodes += 1;
798 
799         if (cur->children != NULL &&
800             cur->type != XML_ENTITY_REF_NODE) {
801             cur = cur->children;
802         } else {
803             while (cur->next == NULL) {
804                 if (cur == node)
805                     goto done;
806                 cur = cur->parent;
807             }
808             cur = cur->next;
809         }
810     }
811 
812 done:
813     return numNodes;
814 }
815 
816 static xmlNodePtr
checkCopy(xmlNodePtr copy)817 checkCopy(xmlNodePtr copy) {
818     vars->numCopyOps += 1;
819 
820     if (copy != NULL &&
821         (vars->numCopyOps > MAX_COPY_OPS ||
822          countNodes(copy) > MAX_COPY_NODES)) {
823         if (copy->type == XML_DOCUMENT_NODE ||
824             copy->type == XML_HTML_DOCUMENT_NODE)
825             xmlFreeDoc((xmlDocPtr) copy);
826         else
827             xmlFreeNode(copy);
828         copy = NULL;
829     }
830 
831     return copy;
832 }
833 
834 /*
835  * Fix namespaces, for example after unlinking a node. This makes
836  * sure that the node only references namespaces declared in ancestor
837  * nodes.
838  */
839 static int
fixNs(xmlNodePtr node)840 fixNs(xmlNodePtr node) {
841     if (node == NULL)
842         return 0;
843 
844     if (node->type == XML_ELEMENT_NODE) {
845         return xmlReconciliateNs(node->doc, node);
846     } else if (node->type == XML_ATTRIBUTE_NODE) {
847         xmlNodePtr parent = node->parent;
848 
849         if (parent != NULL)
850             return xmlReconciliateNs(parent->doc, parent);
851         else
852             node->ns = NULL;
853     }
854 
855     return 0;
856 }
857 
858 /* Node operations */
859 
860 static void
opNodeAccessor(int op)861 opNodeAccessor(int op) {
862     xmlNodePtr node;
863 
864     switch (op) {
865         case OP_NODE_PARENT:
866             startOp("parent"); break;
867         case OP_NODE_NEXT_SIBLING:
868             startOp("next"); break;
869         case OP_NODE_PREV_SIBLING:
870             startOp("prev"); break;
871         case OP_NODE_FIRST_CHILD:
872             startOp("children"); break;
873         case OP_XML_GET_LAST_CHILD:
874             startOp("xmlGetLastChild"); break;
875         case OP_XML_GET_INT_SUBSET:
876             startOp("xmlGetIntSubset"); break;
877         case OP_XML_DOC_GET_ROOT_ELEMENT:
878             startOp("xmlDocGetRootElement"); break;
879         default:
880             break;
881     }
882 
883     incNodeIdx();
884     node = getNode(1);
885 
886     if (node != NULL) {
887         switch (op) {
888             case OP_NODE_PARENT:
889                 node = node->parent; break;
890             case OP_NODE_NEXT_SIBLING:
891                 node = node->next; break;
892             case OP_NODE_PREV_SIBLING:
893                 node = node->prev; break;
894             case OP_NODE_FIRST_CHILD:
895                 node = node->children; break;
896             case OP_XML_GET_LAST_CHILD:
897                 node = xmlGetLastChild(node); break;
898             case OP_XML_GET_INT_SUBSET:
899                 node = (xmlNodePtr) xmlGetIntSubset(node->doc); break;
900             case OP_XML_DOC_GET_ROOT_ELEMENT:
901                 node = xmlDocGetRootElement(node->doc); break;
902             default:
903                 break;
904         }
905 
906         /*
907          * Don't descend into predefined entities
908          */
909         if (node != NULL && node->type == XML_ENTITY_DECL) {
910             xmlEntityPtr ent = (xmlEntityPtr) node;
911 
912             if (ent->etype == XML_INTERNAL_PREDEFINED_ENTITY)
913                 node = NULL;
914         }
915     }
916 
917     setNode(0, node);
918 }
919 
920 static void
opDup(int op)921 opDup(int op) {
922     int offset;
923 
924     switch (op) {
925         case OP_DUP_INTEGER:
926             incIntIdx(); break;
927         case OP_DUP_STRING:
928             incStrIdx(); break;
929         case OP_DUP_NODE:
930             incNodeIdx(); break;
931         default:
932             break;
933     }
934 
935     offset = (xmlFuzzReadInt(1) + 1) & REG_MASK;
936 
937     if (offset != 0) {
938         startOp("dup");
939         switch (op) {
940             case OP_DUP_INTEGER:
941                 setInt(0, getInt(offset));
942                 endOp();
943                 break;
944             case OP_DUP_STRING:
945                 copyStr(0, getStr(offset));
946                 endOp();
947                 break;
948             case OP_DUP_NODE:
949                 setNode(0, getNode(offset));
950                 break;
951             default:
952                 break;
953         }
954     }
955 }
956 
957 int
LLVMFuzzerInitialize(int * argc ATTRIBUTE_UNUSED,char *** argv ATTRIBUTE_UNUSED)958 LLVMFuzzerInitialize(int *argc ATTRIBUTE_UNUSED,
959                      char ***argv ATTRIBUTE_UNUSED) {
960     xmlFuzzMemSetup();
961     xmlInitParser();
962 #ifdef LIBXML_CATALOG_ENABLED
963     xmlInitializeCatalog();
964     xmlCatalogSetDefaults(XML_CATA_ALLOW_NONE);
965 #endif
966     xmlSetGenericErrorFunc(NULL, xmlFuzzErrorFunc);
967 
968     return 0;
969 }
970 
971 int
LLVMFuzzerTestOneInput(const char * data,size_t size)972 LLVMFuzzerTestOneInput(const char *data, size_t size) {
973     size_t maxAlloc;
974     int i;
975 
976     if (size > 1000)
977         return 0;
978 
979     memset(vars, 0, sizeof(*vars));
980 
981     xmlFuzzDataInit(data, size);
982 
983     maxAlloc = xmlFuzzReadInt(4) % (size * 50 + 10);
984     xmlFuzzMemSetLimit(maxAlloc);
985 
986     /*
987      * Interpreter loop
988      *
989      * Processing an opcode typically involves
990      *
991      * - startOp for debugging
992      * - increase output register index if non-void
993      * - get arguments from input registers
994      * - invoke API function
995      * - set oomReport
996      * - set output register
997      * - memory management and other adjustments
998      * - endOp for void functions
999      */
1000 
1001     while (xmlFuzzBytesRemaining()) {
1002         size_t readSize;
1003         int op = xmlFuzzReadInt(1);
1004         int oomReport = -1; /* -1 means unknown */
1005 
1006         vars->opName = "[unset]";
1007 
1008         switch (op) {
1009             case OP_CREATE_INTEGER:
1010                 incIntIdx();
1011                 setInt(0, (int) xmlFuzzReadInt(4));
1012                 break;
1013 
1014             case OP_CREATE_STRING:
1015                 incStrIdx();
1016                 copyStr(0, BAD_CAST xmlFuzzReadString(&readSize));
1017                 break;
1018 
1019             case OP_DUP_INTEGER:
1020             case OP_DUP_STRING:
1021             case OP_DUP_NODE:
1022                 opDup(op);
1023                 break;
1024 
1025             case OP_PARSE_DOCUMENT:
1026                 /*
1027                  * We don't really want to test the parser but exposing
1028                  * xmlReadDoc seems like a useful way generate or
1029                  * round-trip documents.
1030                  *
1031                  * This also creates documents with a dictionary which
1032                  * is crucial to hit some code paths.
1033                  */
1034                 startOp("xmlReadDoc");
1035                 incNodeIdx();
1036                 setNode(0, (xmlNodePtr) xmlReadDoc(
1037                     getStr(0),
1038                     getCStr(1),
1039                     getCStr(2),
1040                     getInt(0)));
1041                 break;
1042 
1043             case OP_XML_NEW_DOC: {
1044                 xmlDocPtr doc;
1045 
1046                 /*
1047                  * TODO: There's no public API function to generate a
1048                  * document with a dictionary. We should add an extra
1049                  * opcode that sets doc->dict.
1050                  */
1051                 startOp("xmlNewDoc");
1052                 incNodeIdx();
1053                 doc = xmlNewDoc(getStr(0));
1054                 oomReport = (doc == NULL);
1055                 setNode(0, (xmlNodePtr) doc);
1056                 break;
1057             }
1058 
1059             case OP_XML_NEW_NODE: {
1060                 xmlNodePtr node;
1061                 const xmlChar *name;
1062 
1063                 startOp("xmlNewNode");
1064                 incNodeIdx();
1065                 node = xmlNewNode(
1066                     nodeGetNs(getNode(1), getInt(0)),
1067                     name = getStr(0));
1068                 oomReport = (name != NULL && node == NULL);
1069                 if (fixNs(node) < 0)
1070                     oomReport = 1;
1071                 setNode(0, node);
1072                 break;
1073             }
1074 
1075             case OP_XML_NEW_NODE_EAT_NAME: {
1076                 xmlNodePtr node;
1077                 xmlChar *name;
1078 
1079                 startOp("xmlNewNodeEatName");
1080                 incNodeIdx();
1081                 node = xmlNewNodeEatName(
1082                     nodeGetNs(getNode(1), getInt(0)),
1083                     name = uncheckedStrdup(getStr(0)));
1084                 oomReport = (name != NULL && node == NULL);
1085                 if (fixNs(node) < 0)
1086                     oomReport = 1;
1087                 setNode(0, node);
1088                 break;
1089             }
1090 
1091             case OP_XML_NEW_DOC_NODE: {
1092                 xmlNodePtr node;
1093                 const xmlChar *name;
1094 
1095                 startOp("xmlNewDocNode");
1096                 incNodeIdx();
1097                 node = xmlNewDocNode(
1098                     getDoc(1),
1099                     nodeGetNs(getNode(2), getInt(0)),
1100                     name = getStr(0),
1101                     getStr(1));
1102                 oomReport = (name != NULL && node == NULL);
1103                 if (fixNs(node) < 0)
1104                     oomReport = 1;
1105                 setNode(0, node);
1106                 break;
1107             }
1108 
1109             case OP_XML_NEW_DOC_NODE_EAT_NAME: {
1110                 xmlNodePtr node;
1111                 xmlChar *name;
1112 
1113                 startOp("xmlNewDocNodeEatName");
1114                 incNodeIdx();
1115                 node = xmlNewDocNodeEatName(
1116                     getDoc(1),
1117                     nodeGetNs(getNode(2), getInt(0)),
1118                     name = uncheckedStrdup(getStr(0)),
1119                     getStr(1));
1120                 oomReport = (name != NULL && node == NULL);
1121                 if (fixNs(node) < 0)
1122                     oomReport = 1;
1123                 setNode(0, node);
1124                 break;
1125             }
1126 
1127             case OP_XML_NEW_DOC_RAW_NODE: {
1128                 xmlNodePtr node;
1129                 const xmlChar *name;
1130 
1131                 startOp("xmlNewDocRawNode");
1132                 incNodeIdx();
1133                 node = xmlNewDocRawNode(
1134                     getDoc(1),
1135                     nodeGetNs(getNode(2), getInt(0)),
1136                     name = getStr(0),
1137                     getStr(1));
1138                 oomReport = (name != NULL && node == NULL);
1139                 if (fixNs(node) < 0)
1140                     oomReport = 1;
1141                 setNode(0, node);
1142                 break;
1143             }
1144 
1145             case OP_XML_NEW_CHILD: {
1146                 xmlNodePtr parent, node;
1147                 const xmlChar *name;
1148 
1149                 startOp("xmlNewChild");
1150                 incNodeIdx();
1151                 /* Use parent namespace without fixup */
1152                 node = xmlNewChild(
1153                     parent = getNode(1),
1154                     nodeGetNs(getNode(1), getInt(0)),
1155                     name = getStr(0),
1156                     getStr(1));
1157                 oomReport =
1158                     (parent != NULL &&
1159                      isValidChildType(parent, XML_ELEMENT_NODE) &&
1160                      name != NULL &&
1161                      node == NULL);
1162                 setNode(0, node);
1163                 break;
1164             }
1165 
1166             case OP_XML_NEW_TEXT_CHILD: {
1167                 xmlNodePtr parent, node;
1168                 const xmlChar *name;
1169 
1170                 startOp("xmlNewTextChild");
1171                 incNodeIdx();
1172                 /* Use parent namespace without fixup */
1173                 node = xmlNewTextChild(
1174                     parent = getNode(1),
1175                     nodeGetNs(getNode(1), getInt(0)),
1176                     name = getStr(0),
1177                     getStr(1));
1178                 oomReport =
1179                     (parent != NULL &&
1180                      isValidChildType(parent, XML_ELEMENT_NODE) &&
1181                      name != NULL &&
1182                      node == NULL);
1183                 setNode(0, node);
1184                 break;
1185             }
1186 
1187             case OP_XML_NEW_PROP: {
1188                 xmlNodePtr parent;
1189                 xmlAttrPtr attr;
1190                 const xmlChar *name;
1191 
1192                 startOp("xmlNewProp");
1193                 incNodeIdx();
1194                 attr = xmlNewProp(
1195                     parent = getNode(1),
1196                     name = getStr(0),
1197                     getStr(1));
1198                 oomReport =
1199                     ((parent == NULL || parent->type == XML_ELEMENT_NODE) &&
1200                      name != NULL &&
1201                      attr == NULL);
1202                 setNode(0, (xmlNodePtr) attr);
1203                 break;
1204             }
1205 
1206             case OP_XML_NEW_DOC_PROP: {
1207                 xmlAttrPtr attr;
1208                 const xmlChar *name;
1209 
1210                 startOp("xmlNewDocProp");
1211                 incNodeIdx();
1212                 attr = xmlNewDocProp(
1213                     getDoc(1),
1214                     name = getStr(0),
1215                     getStr(1));
1216                 oomReport = (name != NULL && attr == NULL);
1217                 setNode(0, (xmlNodePtr) attr);
1218                 break;
1219             }
1220 
1221             case OP_XML_NEW_NS_PROP: {
1222                 xmlAttrPtr attr;
1223 
1224                 startOp("xmlNewNsProp");
1225                 incNodeIdx();
1226                 attr = xmlNewNsProp(
1227                     getNode(1),
1228                     nodeGetNs(getNode(1), getInt(0)),
1229                     getStr(0),
1230                     getStr(1));
1231                 /* xmlNewNsProp returns NULL on duplicate prefixes. */
1232                 if (attr != NULL)
1233                     oomReport = 0;
1234                 setNode(0, (xmlNodePtr) attr);
1235                 break;
1236             }
1237 
1238             case OP_XML_NEW_NS_PROP_EAT_NAME: {
1239                 xmlAttrPtr attr;
1240 
1241                 startOp("xmlNewNsPropEatName");
1242                 incNodeIdx();
1243                 attr = xmlNewNsPropEatName(
1244                     getNode(1),
1245                     nodeGetNs(getNode(1), getInt(0)),
1246                     uncheckedStrdup(getStr(0)),
1247                     getStr(1));
1248                 if (attr != NULL)
1249                     oomReport = 0;
1250                 setNode(0, (xmlNodePtr) attr);
1251                 break;
1252             }
1253 
1254             case OP_XML_NEW_TEXT: {
1255                 xmlNodePtr node;
1256 
1257                 startOp("xmlNewText");
1258                 incNodeIdx();
1259                 node = xmlNewText(getStr(0));
1260                 oomReport = (node == NULL);
1261                 setNode(0, node);
1262                 break;
1263             }
1264 
1265             case OP_XML_NEW_TEXT_LEN: {
1266                 xmlNodePtr node;
1267                 const xmlChar *text;
1268 
1269                 startOp("xmlNewTextLen");
1270                 incNodeIdx();
1271                 text = getStr(0);
1272                 node = xmlNewTextLen(text, xmlStrlen(text));
1273                 oomReport = (node == NULL);
1274                 setNode(0, node);
1275                 break;
1276             }
1277 
1278             case OP_XML_NEW_DOC_TEXT: {
1279                 xmlNodePtr node;
1280 
1281                 startOp("xmlNewDocText");
1282                 incNodeIdx();
1283                 node = xmlNewDocText(getDoc(1), getStr(0));
1284                 oomReport = (node == NULL);
1285                 setNode(0, node);
1286                 break;
1287             }
1288 
1289             case OP_XML_NEW_DOC_TEXT_LEN: {
1290                 xmlDocPtr doc;
1291                 xmlNodePtr node;
1292                 const xmlChar *text;
1293 
1294                 startOp("xmlNewDocTextLen");
1295                 incNodeIdx();
1296                 doc = getDoc(1);
1297                 text = getStr(0);
1298                 node = xmlNewDocTextLen(doc, text, xmlStrlen(text));
1299                 oomReport = (node == NULL);
1300                 setNode(0, node);
1301                 break;
1302             }
1303 
1304             case OP_XML_NEW_PI: {
1305                 xmlNodePtr node;
1306                 const xmlChar *name;
1307 
1308                 startOp("xmlNewPI");
1309                 incNodeIdx();
1310                 node = xmlNewPI(
1311                     name = getStr(0),
1312                     getStr(1));
1313                 oomReport = (name != NULL && node == NULL);
1314                 setNode(0, node);
1315                 break;
1316             }
1317 
1318             case OP_XML_NEW_DOC_PI: {
1319                 xmlNodePtr node;
1320                 const xmlChar *name;
1321 
1322                 startOp("xmlNewDocPI");
1323                 incNodeIdx();
1324                 node = xmlNewDocPI(
1325                     getDoc(1),
1326                     name = getStr(0),
1327                     getStr(1));
1328                 oomReport = (name != NULL && node == NULL);
1329                 setNode(0, node);
1330                 break;
1331             }
1332 
1333             case OP_XML_NEW_COMMENT: {
1334                 xmlNodePtr node;
1335 
1336                 startOp("xmlNewComment");
1337                 incNodeIdx();
1338                 node = xmlNewComment(getStr(0));
1339                 oomReport = (node == NULL);
1340                 setNode(0, node);
1341                 break;
1342             }
1343 
1344             case OP_XML_NEW_DOC_COMMENT: {
1345                 xmlNodePtr node;
1346 
1347                 startOp("xmlNewDocComment");
1348                 incNodeIdx();
1349                 node = xmlNewDocComment(
1350                     getDoc(1),
1351                     getStr(0));
1352                 oomReport = (node == NULL);
1353                 setNode(0, node);
1354                 break;
1355             }
1356 
1357             case OP_XML_NEW_CDATA_BLOCK: {
1358                 xmlDocPtr doc;
1359                 xmlNodePtr node;
1360                 const xmlChar *text;
1361 
1362                 startOp("xmlNewCDataBlock");
1363                 incNodeIdx();
1364                 doc = getDoc(1);
1365                 text = getStr(0);
1366                 node = xmlNewDocTextLen(
1367                     doc,
1368                     text,
1369                     xmlStrlen(text));
1370                 oomReport = (node == NULL);
1371                 setNode(0, node);
1372                 break;
1373             }
1374 
1375             case OP_XML_NEW_CHAR_REF: {
1376                 xmlNodePtr node;
1377                 const xmlChar *name;
1378 
1379                 startOp("xmlNewCharRef");
1380                 incNodeIdx();
1381                 node = xmlNewCharRef(
1382                     getDoc(1),
1383                     name = getStr(0));
1384                 oomReport = (name != NULL && node == NULL);
1385                 setNode(0, node);
1386                 break;
1387             }
1388 
1389             case OP_XML_NEW_REFERENCE: {
1390                 xmlNodePtr node;
1391                 const xmlChar *name;
1392 
1393                 startOp("xmlNewReference");
1394                 incNodeIdx();
1395                 node = xmlNewReference(
1396                     getDoc(1),
1397                     name = getStr(0));
1398                 oomReport = (name != NULL && node == NULL);
1399                 setNode(0, node);
1400                 break;
1401             }
1402 
1403             case OP_XML_NEW_DOC_FRAGMENT: {
1404                 xmlNodePtr node;
1405 
1406                 startOp("xmlNewDocFragment");
1407                 incNodeIdx();
1408                 node = xmlNewDocFragment(getDoc(1));
1409                 oomReport = (node == NULL);
1410                 setNode(0, node);
1411                 break;
1412             }
1413 
1414             case OP_XML_CREATE_INT_SUBSET: {
1415                 xmlDocPtr doc;
1416                 xmlDtdPtr dtd = NULL;
1417 
1418                 startOp("xmlCreateIntSubset");
1419                 incNodeIdx();
1420                 doc = getDoc(1);
1421                 if (doc == NULL || doc->intSubset == NULL) {
1422                     dtd = xmlCreateIntSubset(
1423                         doc,
1424                         getStr(0),
1425                         getStr(1),
1426                         getStr(2));
1427                     oomReport = (dtd == NULL);
1428                 }
1429                 setNode(0, (xmlNodePtr) dtd);
1430                 break;
1431             }
1432 
1433             case OP_XML_NEW_DTD: {
1434                 xmlDocPtr doc;
1435                 xmlDtdPtr dtd = NULL;
1436 
1437                 startOp("xmlNewDtd");
1438                 incNodeIdx();
1439                 doc = getDoc(1);
1440                 if (doc == NULL || doc->extSubset == NULL) {
1441                     dtd = xmlNewDtd(
1442                         doc,
1443                         getStr(0),
1444                         getStr(1),
1445                         getStr(2));
1446                     oomReport = (dtd == NULL);
1447                 }
1448                 setNode(0, (xmlNodePtr) dtd);
1449                 break;
1450             }
1451 
1452             case OP_XML_COPY_DOC: {
1453                 xmlDocPtr copy;
1454 
1455                 startOp("xmlCopyDoc");
1456                 incNodeIdx();
1457                 copy = xmlCopyDoc(
1458                     getDoc(1),
1459                     getInt(0));
1460                 /*
1461                  * TODO: Copying DTD nodes without a document can
1462                  * result in an empty list.
1463                  */
1464                 if (copy != NULL)
1465                     oomReport = 0;
1466                 setNode(0, checkCopy((xmlNodePtr) copy));
1467                 break;
1468             }
1469 
1470             case OP_XML_COPY_NODE: {
1471                 xmlNodePtr copy;
1472 
1473                 startOp("xmlCopyNode");
1474                 incNodeIdx();
1475                 copy = xmlCopyNode(
1476                     getNode(1),
1477                     getInt(0));
1478                 if (copy != NULL)
1479                     oomReport = 0;
1480                 setNode(0, checkCopy((xmlNodePtr) copy));
1481                 break;
1482             }
1483 
1484             case OP_XML_COPY_NODE_LIST: {
1485                 xmlNodePtr copy;
1486 
1487                 startOp("xmlCopyNodeList");
1488                 copy = xmlCopyNodeList(getNode(0));
1489                 if (copy != NULL)
1490                     oomReport = 0;
1491                 xmlFreeNodeList(copy);
1492                 endOp();
1493                 break;
1494             }
1495 
1496             case OP_XML_DOC_COPY_NODE: {
1497                 xmlNodePtr node, copy;
1498                 xmlDocPtr doc;
1499 
1500                 startOp("xmlDocCopyNode");
1501                 incNodeIdx();
1502                 copy = xmlDocCopyNode(
1503                     node = getNode(1),
1504                     doc = getDoc(2),
1505                     getInt(0));
1506                 if (copy != NULL)
1507                     oomReport = 0;
1508                 setNode(0, checkCopy((xmlNodePtr) copy));
1509                 break;
1510             }
1511 
1512             case OP_XML_DOC_COPY_NODE_LIST: {
1513                 xmlNodePtr copy;
1514 
1515                 startOp("xmlDocCopyNodeList");
1516                 copy = xmlDocCopyNodeList(
1517                     getDoc(0),
1518                     getNode(1));
1519                 if (copy != NULL)
1520                     oomReport = 0;
1521                 xmlFreeNodeList(copy);
1522                 endOp();
1523                 break;
1524             }
1525 
1526             case OP_XML_COPY_PROP: {
1527                 xmlAttrPtr copy;
1528 
1529                 startOp("xmlCopyProp");
1530                 incNodeIdx();
1531                 copy = xmlCopyProp(
1532                     getNode(1),
1533                     getAttr(2));
1534                 /*
1535                  * TODO: Copying attributes can result in an empty list
1536                  * if there's a duplicate namespace prefix.
1537                  */
1538                 if (copy != NULL)
1539                     oomReport = 0;
1540                 if (copy != NULL) {
1541                     /* Quirk */
1542                     copy->parent = NULL;
1543                     /* Fix namespace */
1544                     copy->ns = NULL;
1545                 }
1546                 setNode(0, checkCopy((xmlNodePtr) copy));
1547                 break;
1548             }
1549 
1550             case OP_XML_COPY_PROP_LIST: {
1551                 xmlAttrPtr copy;
1552 
1553                 startOp("xmlCopyPropList");
1554                 copy = xmlCopyPropList(
1555                     getNode(0),
1556                     getAttr(1));
1557                 if (copy != NULL)
1558                     oomReport = 0;
1559                 xmlFreePropList(copy);
1560                 endOp();
1561                 break;
1562             }
1563 
1564             case OP_XML_COPY_DTD: {
1565                 xmlDtdPtr dtd, copy;
1566 
1567                 startOp("xmlCopyDtd");
1568                 incNodeIdx();
1569                 copy = xmlCopyDtd(
1570                     dtd = getDtd(1));
1571                 oomReport = (dtd != NULL && copy == NULL);
1572                 setNode(0, checkCopy((xmlNodePtr) copy));
1573                 break;
1574             }
1575 
1576             case OP_NODE_PARENT:
1577             case OP_NODE_NEXT_SIBLING:
1578             case OP_NODE_PREV_SIBLING:
1579             case OP_NODE_FIRST_CHILD:
1580             case OP_XML_GET_LAST_CHILD:
1581             case OP_XML_GET_INT_SUBSET:
1582             case OP_XML_DOC_GET_ROOT_ELEMENT:
1583                 opNodeAccessor(op);
1584                 oomReport = 0;
1585                 break;
1586 
1587             case OP_NODE_NAME: {
1588                 xmlNodePtr node;
1589 
1590                 startOp("name");
1591                 incStrIdx();
1592                 node = getNode(0);
1593                 copyStr(0, node ? node->name : NULL);
1594                 oomReport = 0;
1595                 endOp();
1596                 break;
1597             }
1598 
1599             case OP_XML_NODE_SET_NAME:
1600                 startOp("xmlNodeSetName");
1601                 xmlNodeSetName(
1602                     getNode(0),
1603                     getStr(0));
1604                 endOp();
1605                 break;
1606 
1607             case OP_XML_NODE_GET_CONTENT: {
1608                 xmlChar *content;
1609 
1610                 incStrIdx();
1611                 startOp("xmlNodeGetContent");
1612                 content = xmlNodeGetContent(getNode(0));
1613                 if (content != NULL)
1614                     oomReport = 0;
1615                 moveStr(0, content);
1616                 endOp();
1617                 break;
1618             }
1619 
1620             case OP_XML_NODE_SET_CONTENT: {
1621                 xmlNodePtr node;
1622                 int res;
1623 
1624                 startOp("xmlNodeSetContent");
1625                 node = getNode(0);
1626                 removeChildren(node, 0);
1627                 res = xmlNodeSetContent(
1628                     node,
1629                     getStr(0));
1630                 oomReport = (res < 0);
1631                 endOp();
1632                 break;
1633             }
1634 
1635             case OP_XML_NODE_SET_CONTENT_LEN: {
1636                 xmlNodePtr node;
1637                 const xmlChar *content;
1638                 int res;
1639 
1640                 startOp("xmlNodeSetContentLen");
1641                 node = getNode(0);
1642                 content = getStr(0);
1643                 removeChildren(node, 0);
1644                 res = xmlNodeSetContentLen(
1645                     node,
1646                     content,
1647                     xmlStrlen(content));
1648                 oomReport = (res < 0);
1649                 endOp();
1650                 break;
1651             }
1652 
1653             case OP_XML_NODE_ADD_CONTENT: {
1654                 xmlNodePtr node, text;
1655                 int res;
1656 
1657                 startOp("xmlNodeAddContent");
1658                 node = getNode(0);
1659                 res = xmlNodeAddContent(
1660                     node,
1661                     getStr(0));
1662                 oomReport = (res < 0);
1663                 if (node != NULL) {
1664                     if (node->type == XML_ELEMENT_NODE ||
1665                         node->type == XML_DOCUMENT_FRAG_NODE)
1666                         text = node->last;
1667                     else
1668                         text = node;
1669                     checkContent(text);
1670                 }
1671                 endOp();
1672                 break;
1673             }
1674 
1675             case OP_XML_NODE_ADD_CONTENT_LEN: {
1676                 xmlNodePtr node, text;
1677                 const xmlChar *content;
1678                 int res;
1679 
1680                 startOp("xmlNodeAddContentLen");
1681                 node = getNode(0);
1682                 content = getStr(0);
1683                 res = xmlNodeAddContentLen(
1684                     node,
1685                     content,
1686                     xmlStrlen(content));
1687                 oomReport = res < 0;
1688                 if (node != NULL) {
1689                     if (node->type == XML_ELEMENT_NODE ||
1690                         node->type == XML_DOCUMENT_FRAG_NODE)
1691                         text = node->last;
1692                     else
1693                         text = node;
1694                     checkContent(text);
1695                 }
1696                 endOp();
1697                 break;
1698             }
1699 
1700             case OP_XML_GET_LINE_NO:
1701                 incIntIdx();
1702                 startOp("xmlGetLineNo");
1703                 setInt(0, xmlGetLineNo(getNode(0)));
1704                 oomReport = 0;
1705                 endOp();
1706                 break;
1707 
1708             case OP_XML_GET_NODE_PATH: {
1709                 xmlChar *path;
1710 
1711                 incStrIdx();
1712                 startOp("xmlGetNodePath");
1713                 path = xmlGetNodePath(getNode(0));
1714                 if (path != NULL)
1715                     oomReport = 0;
1716                 moveStr(0, path);
1717                 endOp();
1718                 break;
1719             }
1720 
1721             case OP_XML_DOC_SET_ROOT_ELEMENT: {
1722                 xmlDocPtr oldDoc, doc;
1723                 xmlNodePtr oldRoot, oldParent, root;
1724 
1725                 startOp("xmlDocSetRootElement");
1726                 incNodeIdx();
1727                 doc = getDoc(1);
1728                 root = getNode(2);
1729                 if (doc != NULL && doc->parent != NULL)
1730                     doc = NULL;
1731                 if (!isValidChild((xmlNodePtr) doc, root))
1732                     root = NULL;
1733                 oldDoc = root ? root->doc : NULL;
1734                 oldParent = root ? root->parent : NULL;
1735 
1736                 oldRoot = xmlDocSetRootElement(doc, root);
1737                 /* We can't really know whether xmlSetTreeDoc failed */
1738                 if (oldRoot != NULL ||
1739                     root == NULL ||
1740                     root->doc == oldDoc)
1741                     oomReport = 0;
1742                 setNode(0, oldRoot);
1743 
1744                 if (root &&
1745                     (root->parent != oldParent ||
1746                      root->doc != oldDoc)) {
1747                     if (fixNs(root) < 0)
1748                         oomReport = 1;
1749                     if (oldParent != NULL)
1750                         dropNode(oldParent);
1751                     else
1752                         dropNode((xmlNodePtr) oldDoc);
1753                 }
1754                 endOp();
1755                 break;
1756             }
1757 
1758             case OP_XML_NODE_IS_TEXT:
1759                 incIntIdx();
1760                 startOp("xmlNodeIsText");
1761                 setInt(0, xmlNodeIsText(getNode(0)));
1762                 oomReport = 0;
1763                 endOp();
1764                 break;
1765 
1766             case OP_XML_NODE_GET_ATTR_VALUE: {
1767                 xmlChar *value = NULL;
1768                 int res;
1769 
1770                 incStrIdx();
1771                 startOp("xmlNodeGetAttrValue");
1772                 res = xmlNodeGetAttrValue(
1773                     getNode(0),
1774                     getStr(1),
1775                     getStr(2),
1776                     &value);
1777                 oomReport = (res < 0);
1778                 moveStr(0, value);
1779                 endOp();
1780                 break;
1781             }
1782 
1783             case OP_XML_NODE_GET_LANG: {
1784                 xmlChar *lang;
1785 
1786                 incStrIdx();
1787                 startOp("xmlNodeGetLang");
1788                 lang = xmlNodeGetLang(getNode(0));
1789                 if (lang != NULL)
1790                     oomReport = 0;
1791                 moveStr(0, lang);
1792                 endOp();
1793                 break;
1794             }
1795 
1796             case OP_XML_NODE_SET_LANG: {
1797                 xmlNodePtr node;
1798                 xmlAttrPtr attr;
1799                 int res;
1800 
1801                 startOp("xmlNodeSetLang");
1802                 node = getNode(0);
1803                 attr = xmlHasNsProp(
1804                     node,
1805                     BAD_CAST "lang",
1806                     XML_XML_NAMESPACE);
1807                 xmlFuzzResetMallocFailed();
1808                 removeChildren((xmlNodePtr) attr, 0);
1809                 res = xmlNodeSetLang(
1810                     node,
1811                     getStr(0));
1812                 oomReport = (res < 0);
1813                 endOp();
1814                 break;
1815             }
1816 
1817             case OP_XML_NODE_GET_SPACE_PRESERVE: {
1818                 int res;
1819 
1820                 incIntIdx();
1821                 startOp("xmlNodeGetSpacePreserve");
1822                 res = xmlNodeGetSpacePreserve(getNode(0));
1823                 if (res >= 0)
1824                     oomReport = 0;
1825                 setInt(0, res);
1826                 endOp();
1827                 break;
1828             }
1829 
1830             case OP_XML_NODE_SET_SPACE_PRESERVE: {
1831                 xmlNodePtr node;
1832                 xmlAttrPtr attr;
1833                 int res;
1834 
1835                 startOp("xmlNodeSetSpacePreserve");
1836                 node = getNode(0);
1837                 attr = xmlHasNsProp(
1838                     node,
1839                     BAD_CAST "space",
1840                     XML_XML_NAMESPACE);
1841                 xmlFuzzResetMallocFailed();
1842                 removeChildren((xmlNodePtr) attr, 0);
1843                 res = xmlNodeSetSpacePreserve(
1844                     node,
1845                     getInt(0));
1846                 oomReport = (res < 0);
1847                 endOp();
1848                 break;
1849             }
1850 
1851             case OP_XML_NODE_GET_BASE: {
1852                 xmlChar *base;
1853 
1854                 incStrIdx();
1855                 startOp("xmlNodeGetBase");
1856                 base = xmlNodeGetBase(
1857                     getDoc(0),
1858                     getNode(1));
1859                 if (base != NULL)
1860                     oomReport = 0;
1861                 moveStr(0, base);
1862                 endOp();
1863                 break;
1864             }
1865 
1866             case OP_XML_NODE_GET_BASE_SAFE: {
1867                 xmlChar *base;
1868                 int res;
1869 
1870                 startOp("xmlNodeGetBaseSafe");
1871                 incStrIdx();
1872                 res = xmlNodeGetBaseSafe(
1873                     getDoc(0),
1874                     getNode(1),
1875                     &base);
1876                 oomReport = (res < 0);
1877                 moveStr(0, base);
1878                 endOp();
1879                 break;
1880             }
1881 
1882             case OP_XML_NODE_SET_BASE: {
1883                 xmlNodePtr node;
1884                 xmlAttrPtr attr;
1885                 int res;
1886 
1887                 startOp("xmlNodeSetBase");
1888                 node = getNode(0);
1889                 attr = xmlHasNsProp(
1890                     node,
1891                     BAD_CAST "base",
1892                     XML_XML_NAMESPACE);
1893                 xmlFuzzResetMallocFailed();
1894                 removeChildren((xmlNodePtr) attr, 0);
1895                 res = xmlNodeSetBase(
1896                     node,
1897                     getStr(0));
1898                 if (res == 0)
1899                     oomReport = 0;
1900                 endOp();
1901                 break;
1902             }
1903 
1904             case OP_XML_IS_BLANK_NODE:
1905                 startOp("xmlIsBlankNode");
1906                 incNodeIdx();
1907                 setInt(0, xmlIsBlankNode(getNode(0)));
1908                 oomReport = 0;
1909                 break;
1910 
1911             case OP_XML_HAS_PROP: {
1912                 xmlNodePtr node;
1913                 xmlAttrPtr attr;
1914 
1915                 startOp("xmlHasProp");
1916                 incNodeIdx();
1917                 attr = xmlHasProp(
1918                     node = getNode(1),
1919                     getStr(0));
1920                 if (node != NULL &&
1921                     node->doc != NULL &&
1922                     node->doc->intSubset != NULL) {
1923                     /*
1924                      * xmlHasProp tries to look up default attributes,
1925                      * requiring a memory allocation which isn't
1926                      * checked.
1927                      */
1928                     if (attr != NULL)
1929                         oomReport = 0;
1930                 } else {
1931                     oomReport = 0;
1932                 }
1933                 setNode(0, (xmlNodePtr) attr);
1934                 break;
1935             }
1936 
1937             case OP_XML_HAS_NS_PROP: {
1938                 xmlNodePtr node;
1939                 xmlAttrPtr attr;
1940 
1941                 startOp("xmlHasNsProp");
1942                 incNodeIdx();
1943                 attr = xmlHasNsProp(
1944                     node = getNode(1),
1945                     getStr(0),
1946                     getStr(1));
1947                 if (node != NULL &&
1948                     node->doc != NULL &&
1949                     node->doc->intSubset != NULL) {
1950                     if (attr != NULL)
1951                         oomReport = 0;
1952                 } else {
1953                     oomReport = 0;
1954                 }
1955                 setNode(0, (xmlNodePtr) attr);
1956                 break;
1957             }
1958 
1959             case OP_XML_GET_PROP: {
1960                 xmlChar *content;
1961 
1962                 startOp("xmlGetProp");
1963                 incStrIdx();
1964                 content = xmlGetProp(
1965                     getNode(0),
1966                     getStr(1));
1967                 if (content != NULL)
1968                     oomReport = 0;
1969                 moveStr(0, content);
1970                 endOp();
1971                 break;
1972             }
1973 
1974             case OP_XML_GET_NS_PROP: {
1975                 xmlChar *content;
1976 
1977                 startOp("xmlGetNsProp");
1978                 incStrIdx();
1979                 content = xmlGetNsProp(
1980                     getNode(0),
1981                     getStr(1),
1982                     getStr(2));
1983                 if (content != NULL)
1984                     oomReport = 0;
1985                 moveStr(0, content);
1986                 endOp();
1987                 break;
1988             }
1989 
1990             case OP_XML_GET_NO_NS_PROP: {
1991                 xmlChar *content;
1992 
1993                 startOp("xmlGetNoNsProp");
1994                 incStrIdx();
1995                 content = xmlGetNoNsProp(
1996                     getNode(0),
1997                     getStr(1));
1998                 if (content != NULL)
1999                     oomReport = 0;
2000                 moveStr(0, content);
2001                 endOp();
2002                 break;
2003             }
2004 
2005             case OP_XML_SET_PROP: {
2006                 xmlNodePtr node;
2007                 xmlAttrPtr oldAttr, attr;
2008                 xmlNsPtr ns = NULL;
2009                 const xmlChar *name, *value, *localName;
2010                 xmlChar *prefix;
2011                 int prefixLen;
2012 
2013                 startOp("xmlSetProp");
2014                 incNodeIdx();
2015                 node = getNode(1);
2016                 name = getStr(0);
2017                 value = getStr(1);
2018 
2019                 /*
2020                  * Find the old attribute node which will be deleted.
2021                  */
2022                 localName = xmlSplitQName3(name, &prefixLen);
2023                 if (localName != NULL) {
2024                     prefix = uncheckedStrndup(name, prefixLen);
2025                     ns = xmlSearchNs(NULL, node, prefix);
2026                     xmlFree(prefix);
2027                 }
2028                 if (ns == NULL)
2029                     oldAttr = xmlHasNsProp(node, name, NULL);
2030                 else
2031                     oldAttr = xmlHasNsProp(node, localName, ns->href);
2032                 xmlFuzzResetMallocFailed();
2033                 if (oldAttr != NULL)
2034                     removeChildren((xmlNodePtr) oldAttr, 0);
2035 
2036                 attr = xmlSetProp(node, name, value);
2037 
2038                 oomReport =
2039                     (node != NULL && node->type == XML_ELEMENT_NODE &&
2040                      name != NULL &&
2041                      attr == NULL);
2042                 setNode(0, (xmlNodePtr) attr);
2043                 break;
2044             }
2045 
2046             case OP_XML_SET_NS_PROP: {
2047                 xmlNodePtr node;
2048                 xmlNsPtr ns;
2049                 xmlAttrPtr oldAttr, attr;
2050                 const xmlChar *name, *value;
2051 
2052                 startOp("xmlSetNsProp");
2053                 incNodeIdx();
2054                 node = getNode(1);
2055                 ns = nodeGetNs(getNode(2), getInt(0));
2056                 name = getStr(0);
2057                 value = getStr(1);
2058                 oldAttr = xmlHasNsProp(node, name, ns ? ns->href : NULL);
2059                 xmlFuzzResetMallocFailed();
2060                 if (oldAttr != NULL)
2061                     removeChildren((xmlNodePtr) oldAttr, 0);
2062                 attr = xmlSetNsProp(node, ns, name, value);
2063                 oomReport =
2064                     ((node == NULL || node->type == XML_ELEMENT_NODE) &&
2065                      (ns == NULL || ns->href != NULL) &&
2066                      name != NULL &&
2067                      attr == NULL);
2068                 setNode(0, (xmlNodePtr) attr);
2069                 if (ns != NULL) {
2070                     if (fixNs((xmlNodePtr) attr) < 0)
2071                         oomReport = 1;
2072                 }
2073                 break;
2074             }
2075 
2076             case OP_XML_REMOVE_PROP: {
2077                 xmlNodePtr attr, parent = NULL;
2078 
2079                 startOp("xmlRemoveProp");
2080                 incIntIdx();
2081                 attr = getNode(0);
2082                 if (attr != NULL) {
2083                     if (attr->parent != NULL &&
2084                         attr->type == XML_ATTRIBUTE_NODE)
2085                         removeChildren(attr, 1);
2086                     else
2087                         attr = NULL;
2088                 }
2089                 if (attr != NULL)
2090                     parent = attr->parent;
2091                 setInt(0, xmlRemoveProp((xmlAttrPtr) attr));
2092                 oomReport = 0;
2093                 dropNode(parent);
2094                 endOp();
2095                 break;
2096             }
2097 
2098             case OP_XML_UNSET_PROP: {
2099                 xmlNodePtr node;
2100                 xmlAttrPtr attr;
2101                 const xmlChar *name;
2102 
2103                 startOp("xmlUnsetProp");
2104                 incIntIdx();
2105                 node = getNode(0);
2106                 name = getStr(0);
2107                 attr = xmlHasNsProp(node, name, NULL);
2108                 xmlFuzzResetMallocFailed();
2109                 if (attr != NULL)
2110                     removeChildren((xmlNodePtr) attr, 1);
2111                 setInt(0, xmlUnsetProp(node, name));
2112                 oomReport = 0;
2113                 dropNode(node);
2114                 endOp();
2115                 break;
2116             }
2117 
2118             case OP_XML_UNSET_NS_PROP: {
2119                 xmlNodePtr node;
2120                 xmlNsPtr ns;
2121                 xmlAttrPtr attr;
2122                 const xmlChar *name;
2123 
2124                 startOp("xmlUnsetNsProp");
2125                 incIntIdx();
2126                 node = getNode(0);
2127                 ns = nodeGetNs(getNode(1), getInt(1));
2128                 name = getStr(0);
2129                 attr = xmlHasNsProp(node, name, ns ? ns->href : NULL);
2130                 xmlFuzzResetMallocFailed();
2131                 if (attr != NULL)
2132                     removeChildren((xmlNodePtr) attr, 1);
2133                 setInt(0, xmlUnsetNsProp(node, ns, name));
2134                 oomReport = 0;
2135                 dropNode(node);
2136                 endOp();
2137                 break;
2138             }
2139 
2140             case OP_XML_NEW_NS: {
2141                 xmlNodePtr node;
2142                 xmlNsPtr ns;
2143 
2144                 startOp("xmlNewNs");
2145                 ns = xmlNewNs(
2146                     node = getNode(0),
2147                     getStr(0),
2148                     getStr(1));
2149                 if (ns != NULL)
2150                     oomReport = 0;
2151                 if (node == NULL)
2152                     xmlFreeNs(ns);
2153                 endOp();
2154                 break;
2155             }
2156 
2157             case OP_XML_SEARCH_NS: {
2158                 xmlNsPtr ns;
2159 
2160                 startOp("xmlSearchNs");
2161                 ns = xmlSearchNs(
2162                     getDoc(0),
2163                     getNode(1),
2164                     getStr(0));
2165                 if (ns != NULL)
2166                     oomReport = 0;
2167                 endOp();
2168                 break;
2169             }
2170 
2171             case OP_XML_SEARCH_NS_BY_HREF: {
2172                 xmlNsPtr ns;
2173 
2174                 startOp("xmlSearchNsByHref");
2175                 ns = xmlSearchNsByHref(
2176                     getDoc(0),
2177                     getNode(1),
2178                     getStr(0));
2179                 if (ns != NULL)
2180                     oomReport = 0;
2181                 endOp();
2182                 break;
2183             }
2184 
2185             case OP_XML_GET_NS_LIST: {
2186                 xmlNsPtr *list;
2187 
2188                 startOp("xmlGetNsList");
2189                 list = xmlGetNsList(
2190                     getDoc(0),
2191                     getNode(1));
2192                 if (list != NULL)
2193                     oomReport = 0;
2194                 xmlFree(list);
2195                 endOp();
2196                 break;
2197             }
2198 
2199             case OP_XML_GET_NS_LIST_SAFE: {
2200                 xmlNsPtr *list;
2201                 int res;
2202 
2203                 startOp("xmlGetNsList");
2204                 res = xmlGetNsListSafe(
2205                     getDoc(0),
2206                     getNode(1),
2207                     &list);
2208                 oomReport = (res < 0);
2209                 xmlFree(list);
2210                 endOp();
2211                 break;
2212             }
2213 
2214             case OP_XML_SET_NS: {
2215                 xmlNodePtr node;
2216                 xmlNsPtr ns;
2217 
2218                 startOp("xmlSetNs");
2219                 node = getNode(0),
2220                 ns = nodeGetNs(getNode(1), getInt(0));
2221                 xmlSetNs(node, ns);
2222                 oomReport = 0;
2223                 if (ns != NULL) {
2224                     if (fixNs(node) < 0)
2225                         oomReport = 1;
2226                 }
2227                 endOp();
2228                 break;
2229             }
2230 
2231             case OP_XML_COPY_NAMESPACE: {
2232                 xmlNsPtr ns, copy;
2233 
2234                 startOp("xmlCopyNamespace");
2235                 copy = xmlCopyNamespace(
2236                     ns = nodeGetNs(getNode(0), getInt(0)));
2237                 oomReport = (ns != NULL && copy == NULL);
2238                 xmlFreeNs(copy);
2239                 endOp();
2240                 break;
2241             }
2242 
2243             case OP_XML_COPY_NAMESPACE_LIST: {
2244                 xmlNsPtr list, copy;
2245 
2246                 startOp("xmlCopyNamespaceList");
2247                 copy = xmlCopyNamespaceList(
2248                     list = nodeGetNs(getNode(0), getInt(0)));
2249                 oomReport = (list != NULL && copy == NULL);
2250                 xmlFreeNsList(copy);
2251                 endOp();
2252                 break;
2253             }
2254 
2255             case OP_XML_UNLINK_NODE: {
2256                 xmlNodePtr node, oldParent;
2257                 xmlDocPtr doc;
2258 
2259                 startOp("xmlUnlinkNode");
2260                 node = getNode(0);
2261                 doc = node ? node->doc : NULL;
2262                 /*
2263                  * Unlinking DTD children can cause invalid references
2264                  * which would be expensive to fix.
2265                  *
2266                  * Don't unlink DTD if it is the internal or external
2267                  * subset of the document.
2268                  */
2269                 if (node != NULL &&
2270                     (isDtdChild(node) ||
2271                      (node->type == XML_DTD_NODE &&
2272                       doc != NULL &&
2273                       ((xmlDtdPtr) node == doc->intSubset ||
2274                        (xmlDtdPtr) node == doc->extSubset))))
2275                     node = NULL;
2276                 oldParent = node ? node->parent : NULL;
2277                 xmlUnlinkNode(node);
2278                 oomReport = 0;
2279                 if (node != NULL && node->parent != oldParent) {
2280                     if (fixNs(node) < 0)
2281                         oomReport = 1;
2282                     dropNode(oldParent);
2283                 }
2284                 endOp();
2285                 break;
2286             }
2287 
2288             case OP_XML_REPLACE_NODE: {
2289                 xmlNodePtr old, oldParent, node, oldNodeParent, result;
2290                 xmlDocPtr oldDoc, oldNodeDoc;
2291 
2292                 startOp("xmlReplaceNode");
2293                 old = getNode(0);
2294                 node = getNode(1);
2295 
2296                 /*
2297                  * Unlinking DTD children can cause invalid references
2298                  * which would be expensive to fix.
2299                  *
2300                  * Don't unlink DTD if it is the internal or external
2301                  * subset of the document.
2302                  */
2303                 old = old ? old->parent : NULL;
2304                 oldDoc = old ? old->doc : NULL;
2305                 if (old != NULL &&
2306                     (isDtdChild(old) ||
2307                      (old->type == XML_DTD_NODE &&
2308                       oldDoc != NULL &&
2309                       ((xmlDtdPtr) old == oldDoc->intSubset ||
2310                        (xmlDtdPtr) old == oldDoc->extSubset))))
2311                     old = NULL;
2312                 if (old != NULL && !isValidChild(old->parent, node))
2313                     node = NULL;
2314 
2315                 oldParent = old ? old->parent : NULL;
2316                 oldNodeParent = node ? node->parent : NULL;
2317                 oldNodeDoc = node ? node->doc : NULL;
2318 
2319                 result = xmlReplaceNode(old, node);
2320                 oomReport =
2321                     (old != NULL && old->parent != NULL &&
2322                      node != NULL &&
2323                      old != node &&
2324                      result == NULL);
2325 
2326                 if (old != NULL && old->parent != oldParent) {
2327                     if (fixNs(old) < 0)
2328                         oomReport = 1;
2329                 }
2330                 if (node == NULL) {
2331                     /* Old node was unlinked */
2332                     dropNode(oldParent);
2333                 } else if (node->parent != oldNodeParent ||
2334                            node->doc != oldNodeDoc) {
2335                     if (fixNs(node) < 0)
2336                         oomReport = 1;
2337                     /* Drop old parent of new node */
2338                     if (oldNodeParent != NULL)
2339                         dropNode(oldNodeParent);
2340                     else
2341                         dropNode((xmlNodePtr) oldNodeDoc);
2342                 }
2343                 endOp();
2344                 break;
2345             }
2346 
2347             case OP_XML_ADD_CHILD:
2348             case OP_XML_ADD_SIBLING:
2349             case OP_XML_ADD_PREV_SIBLING:
2350             case OP_XML_ADD_NEXT_SIBLING: {
2351                 xmlNodePtr target, parent, node, oldNodeParent, result;
2352                 xmlDocPtr oldNodeDoc;
2353                 int argsOk;
2354 
2355                 switch (op) {
2356                     case OP_XML_ADD_CHILD:
2357                         startOp("xmlAddChild"); break;
2358                     case OP_XML_ADD_SIBLING:
2359                         startOp("xmlAddSibling"); break;
2360                     case OP_XML_ADD_PREV_SIBLING:
2361                         startOp("xmlAddPrevSibling"); break;
2362                     case OP_XML_ADD_NEXT_SIBLING:
2363                         startOp("xmlAddNextSibling"); break;
2364                 }
2365 
2366                 if (op == OP_XML_ADD_CHILD) {
2367                     target = NULL;
2368                     parent = getNode(0);
2369                 } else {
2370                     target = getNode(0);
2371                     parent = target ? target->parent : NULL;
2372                 }
2373                 node = getNode(1);
2374 
2375                 /* Don't append to root node */
2376                 if (target != NULL && parent == NULL)
2377                     node = NULL;
2378 
2379                 /* Check tree structure */
2380                 if (isDtdChild(node) ||
2381                     !isValidChild(parent, node))
2382                     node = NULL;
2383 
2384                 /* Attributes */
2385                 if (node != NULL && node->type == XML_ATTRIBUTE_NODE) {
2386                     if ((op == OP_XML_ADD_CHILD) ||
2387                         ((target != NULL &&
2388                          (target->type == XML_ATTRIBUTE_NODE)))) {
2389                         xmlAttrPtr attr = xmlHasNsProp(parent, node->name,
2390                             node->ns ? node->ns->href : NULL);
2391 
2392                         xmlFuzzResetMallocFailed();
2393                         /* Attribute might be replaced */
2394                         if (attr != NULL && attr != (xmlAttrPtr) node)
2395                             removeChildren((xmlNodePtr) attr, 1);
2396                     } else {
2397                         target = NULL;
2398                     }
2399                 } else if (target != NULL &&
2400                            target->type == XML_ATTRIBUTE_NODE) {
2401                     node = NULL;
2402                 }
2403 
2404                 oldNodeParent = node ? node->parent : NULL;
2405                 oldNodeDoc = node ? node->doc : NULL;
2406                 argsOk =
2407                     (target != NULL &&
2408                      node != NULL &&
2409                      target != node);
2410 
2411                 switch (op) {
2412                     case OP_XML_ADD_CHILD:
2413                         argsOk = (parent != NULL && node != NULL);
2414                         result = xmlAddChild(parent, node);
2415                         break;
2416                     case OP_XML_ADD_SIBLING:
2417                         result = xmlAddSibling(target, node);
2418                         break;
2419                     case OP_XML_ADD_PREV_SIBLING:
2420                         result = xmlAddPrevSibling(target, node);
2421                         break;
2422                     case OP_XML_ADD_NEXT_SIBLING:
2423                         result = xmlAddNextSibling(target, node);
2424                         break;
2425                 }
2426                 oomReport = (argsOk && result == NULL);
2427 
2428                 if (result != NULL && result != node) {
2429                     /* Text node was merged */
2430                     removeNode(node);
2431                     checkContent(result);
2432                     /* Drop old parent of node */
2433                     if (oldNodeParent != NULL)
2434                         dropNode(oldNodeParent);
2435                     else
2436                         dropNode((xmlNodePtr) oldNodeDoc);
2437                 } else if (node != NULL &&
2438                            (node->parent != oldNodeParent ||
2439                             node->doc != oldNodeDoc)) {
2440                     if (fixNs(node) < 0)
2441                         oomReport = 1;
2442                     /* Drop old parent of node */
2443                     if (oldNodeParent != NULL)
2444                         dropNode(oldNodeParent);
2445                     else
2446                         dropNode((xmlNodePtr) oldNodeDoc);
2447                 }
2448 
2449                 endOp();
2450                 break;
2451             }
2452 
2453             case OP_XML_TEXT_MERGE: {
2454                 xmlNodePtr first, second, parent = NULL, res;
2455                 int argsOk;
2456 
2457                 startOp("xmlTextMerge");
2458                 first = getNode(0);
2459                 second = getNode(1);
2460                 argsOk =
2461                     (first != NULL && first->type == XML_TEXT_NODE &&
2462                      second != NULL && second->type == XML_TEXT_NODE &&
2463                      first != second &&
2464                      first->name == second->name);
2465                 if (argsOk) {
2466                     if (second->parent != NULL)
2467                         parent = second->parent;
2468                     else
2469                         parent = (xmlNodePtr) second->doc;
2470 
2471                 }
2472                 res = xmlTextMerge(first, second);
2473                 oomReport = (argsOk && res == NULL);
2474                 if (res != NULL) {
2475                     removeNode(second);
2476                     dropNode(parent);
2477                     checkContent(first);
2478                 }
2479                 endOp();
2480                 break;
2481             }
2482 
2483             case OP_XML_TEXT_CONCAT: {
2484                 xmlNodePtr node;
2485                 const xmlChar *text;
2486                 int res;
2487 
2488                 startOp("xmlTextConcat");
2489                 node = getNode(0);
2490                 text = getStr(0);
2491                 res = xmlTextConcat(
2492                     node,
2493                     text,
2494                     xmlStrlen(text));
2495                 oomReport = (isTextContentNode(node) && res < 0);
2496                 checkContent(node);
2497                 endOp();
2498                 break;
2499             }
2500 
2501             case OP_XML_STRING_GET_NODE_LIST: {
2502                 xmlNodePtr list;
2503                 const xmlChar *value;
2504 
2505                 startOp("xmlStringGetNodeList");
2506                 list = xmlStringGetNodeList(
2507                     getDoc(0),
2508                     value = getStr(0));
2509                 oomReport = (value != NULL && value[0] != 0 && list == NULL);
2510                 xmlFreeNodeList(list);
2511                 endOp();
2512                 break;
2513             }
2514 
2515             case OP_XML_STRING_LEN_GET_NODE_LIST: {
2516                 xmlDocPtr doc;
2517                 xmlNodePtr list;
2518                 const xmlChar *value;
2519 
2520                 startOp("xmlStringLenGetNodeList");
2521                 doc = getDoc(0);
2522                 value = getStr(0);
2523                 list = xmlStringLenGetNodeList(
2524                     doc,
2525                     value,
2526                     xmlStrlen(value));
2527                 oomReport = (value != NULL && value[0] != 0 && list == NULL);
2528                 xmlFreeNodeList(list);
2529                 endOp();
2530                 break;
2531             }
2532 
2533             case OP_XML_NODE_LIST_GET_STRING: {
2534                 xmlDocPtr doc;
2535                 xmlNodePtr list;
2536                 xmlChar *string;
2537 
2538                 startOp("xmlNodeListGetString");
2539                 incStrIdx();
2540                 doc = getDoc(0);
2541                 list = getNode(1);
2542                 string = xmlNodeListGetString(
2543                     doc,
2544                     list,
2545                     getInt(0));
2546                 oomReport = (list != NULL && string == NULL);
2547                 moveStr(0, string);
2548                 endOp();
2549                 break;
2550             }
2551 
2552             case OP_XML_NODE_LIST_GET_RAW_STRING: {
2553                 xmlDocPtr doc;
2554                 xmlNodePtr list;
2555                 xmlChar *string;
2556 
2557                 startOp("xmlNodeListGetRawString");
2558                 incStrIdx();
2559                 doc = getDoc(0);
2560                 list = getNode(1);
2561                 string = xmlNodeListGetRawString(
2562                     doc,
2563                     list,
2564                     getInt(0));
2565                 oomReport = (list != NULL && string == NULL);
2566                 moveStr(0, string);
2567                 endOp();
2568                 break;
2569             }
2570 
2571             case OP_XML_IS_XHTML:
2572                 startOp("xmlIsXHTML");
2573                 incIntIdx();
2574                 setInt(0, xmlIsXHTML(
2575                     getStr(0),
2576                     getStr(1)));
2577                 oomReport = 0;
2578                 break;
2579 
2580             case OP_XML_ADD_ELEMENT_DECL: {
2581                 xmlElementPtr decl;
2582 
2583                 startOp("xmlAddElementDecl");
2584                 incNodeIdx();
2585                 decl = xmlAddElementDecl(
2586                     NULL,
2587                     getDtd(1),
2588                     getStr(0),
2589                     (xmlElementTypeVal) getInt(0),
2590                     NULL);
2591                 if (decl != NULL)
2592                     oomReport = 0;
2593                 setNode(0, (xmlNodePtr) decl);
2594                 break;
2595             }
2596 
2597             case OP_XML_ADD_ATTRIBUTE_DECL: {
2598                 xmlAttributePtr decl;
2599 
2600                 startOp("xmlAddAttributeDecl");
2601                 incNodeIdx();
2602                 decl = xmlAddAttributeDecl(
2603                     NULL,
2604                     getDtd(1),
2605                     getStr(0),
2606                     getStr(1),
2607                     getStr(2),
2608                     (xmlAttributeType) getInt(0),
2609                     (xmlAttributeDefault) getInt(1),
2610                     getStr(3),
2611                     NULL);
2612                 if (decl != NULL)
2613                     oomReport = 0;
2614                 setNode(0, (xmlNodePtr) decl);
2615                 break;
2616             }
2617 
2618             case OP_XML_ADD_NOTATION_DECL: {
2619                 xmlNotationPtr decl;
2620 
2621                 startOp("xmlAddNotationDecl");
2622                 decl = xmlAddNotationDecl(
2623                     NULL,
2624                     getDtd(1),
2625                     getStr(0),
2626                     getStr(1),
2627                     getStr(2));
2628                 if (decl != NULL)
2629                     oomReport = 0;
2630                 endOp();
2631                 break;
2632             }
2633 
2634             case OP_XML_GET_DTD_ELEMENT_DESC: {
2635                 xmlElementPtr elem;
2636 
2637                 startOp("xmlGetDtdElementDesc");
2638                 incNodeIdx();
2639                 elem = xmlGetDtdElementDesc(
2640                     getDtd(1),
2641                     getStr(0));
2642                 if (elem != NULL)
2643                     oomReport = 0;
2644                 /*
2645                  * Don't reference XML_ELEMENT_TYPE_UNDEFINED dummy
2646                  * declarations.
2647                  */
2648                 if (elem != NULL && elem->parent == NULL)
2649                     elem = NULL;
2650                 setNode(0, (xmlNodePtr) elem);
2651                 break;
2652             }
2653 
2654             case OP_XML_GET_DTD_QELEMENT_DESC: {
2655                 xmlElementPtr elem;
2656 
2657                 startOp("xmlGetDtdQElementDesc");
2658                 incNodeIdx();
2659                 elem = xmlGetDtdQElementDesc(
2660                     getDtd(1),
2661                     getStr(0),
2662                     getStr(1));
2663                 oomReport = 0;
2664                 if (elem != NULL && elem->parent == NULL)
2665                     elem = NULL;
2666                 setNode(0, (xmlNodePtr) elem);
2667                 break;
2668             }
2669 
2670             case OP_XML_GET_DTD_ATTR_DESC: {
2671                 xmlAttributePtr decl;
2672 
2673                 startOp("xmlGetDtdAttrDesc");
2674                 incNodeIdx();
2675                 decl = xmlGetDtdAttrDesc(
2676                     getDtd(1),
2677                     getStr(0),
2678                     getStr(1));
2679                 if (decl != NULL)
2680                     oomReport = 0;
2681                 setNode(0, (xmlNodePtr) decl);
2682                 break;
2683             }
2684 
2685             case OP_XML_GET_DTD_QATTR_DESC: {
2686                 xmlAttributePtr decl;
2687 
2688                 startOp("xmlGetDtdQAttrDesc");
2689                 incNodeIdx();
2690                 decl = xmlGetDtdQAttrDesc(
2691                     getDtd(1),
2692                     getStr(0),
2693                     getStr(1),
2694                     getStr(2));
2695                 oomReport = 0;
2696                 setNode(0, (xmlNodePtr) decl);
2697                 break;
2698             }
2699 
2700             case OP_XML_GET_DTD_NOTATION_DESC:
2701                 startOp("xmlGetDtdNotationDesc");
2702                 xmlGetDtdNotationDesc(
2703                     getDtd(1),
2704                     getStr(0));
2705                 oomReport = 0;
2706                 endOp();
2707                 break;
2708 
2709             case OP_XML_ADD_ID:
2710                 startOp("xmlAddID");
2711                 xmlAddID(
2712                     NULL,
2713                     getDoc(0),
2714                     getStr(0),
2715                     getAttr(1));
2716                 endOp();
2717                 break;
2718 
2719             case OP_XML_ADD_ID_SAFE: {
2720                 int res;
2721 
2722                 startOp("xmlAddIDSafe");
2723                 res = xmlAddIDSafe(
2724                     getAttr(0),
2725                     getStr(0));
2726                 oomReport = (res < 0);
2727                 endOp();
2728                 break;
2729             }
2730 
2731             case OP_XML_GET_ID:
2732                 startOp("xmlGetID");
2733                 incNodeIdx();
2734                 setNode(0, (xmlNodePtr) xmlGetID(
2735                     getDoc(1),
2736                     getStr(0)));
2737                 oomReport = 0;
2738                 break;
2739 
2740             case OP_XML_IS_ID: {
2741                 int res;
2742 
2743                 startOp("xmlIsID");
2744                 res = xmlIsID(
2745                     getDoc(2),
2746                     getNode(1),
2747                     getAttr(0));
2748                 oomReport = (res < 0);
2749                 endOp();
2750                 break;
2751             }
2752 
2753             case OP_XML_REMOVE_ID:
2754                 startOp("xmlRemoveID");
2755                 xmlRemoveID(
2756                     getDoc(1),
2757                     getAttr(0));
2758                 oomReport = 0;
2759                 endOp();
2760                 break;
2761 
2762             case OP_XML_ADD_REF: {
2763                 xmlDocPtr doc;
2764                 xmlAttrPtr attr;
2765                 xmlRefPtr ref;
2766                 const xmlChar *value;
2767 
2768                 startOp("xmlAddRef");
2769                 ref = xmlAddRef(
2770                     NULL,
2771                     doc = getDoc(0),
2772                     value = getStr(0),
2773                     attr = getAttr(1));
2774                 oomReport =
2775                     (doc != NULL &&
2776                      value != NULL &&
2777                      attr != NULL &&
2778                      ref == NULL);
2779                 endOp();
2780                 break;
2781             }
2782 
2783             case OP_XML_GET_REFS:
2784                 startOp("xmlGetRefs");
2785                 xmlGetRefs(
2786                     getDoc(1),
2787                     getStr(0));
2788                 oomReport = 0;
2789                 endOp();
2790                 break;
2791 
2792             case OP_XML_IS_REF:
2793                 startOp("xmlIsRef");
2794                 xmlIsRef(
2795                     getDoc(2),
2796                     getNode(1),
2797                     getAttr(0));
2798                 oomReport = 0;
2799                 endOp();
2800                 break;
2801 
2802             case OP_XML_REMOVE_REF: {
2803                 int res;
2804 
2805                 startOp("xmlRemoveRef");
2806                 res = xmlRemoveRef(
2807                     getDoc(1),
2808                     getAttr(0));
2809                 if (res == 0)
2810                     oomReport = 0;
2811                 endOp();
2812                 break;
2813             }
2814 
2815             case OP_XML_NEW_ENTITY: {
2816                 xmlDocPtr doc;
2817                 xmlEntityPtr ent;
2818 
2819                 startOp("xmlNewEntity");
2820                 incNodeIdx();
2821                 ent = xmlNewEntity(
2822                     doc = getDoc(1),
2823                     getStr(0),
2824                     getInt(0),
2825                     getStr(1),
2826                     getStr(2),
2827                     getStr(3));
2828                 if (ent != NULL)
2829                     oomReport = 0;
2830                 if (doc == NULL || doc->intSubset == NULL) {
2831                     xmlFreeEntity(ent);
2832                     ent = NULL;
2833                 }
2834                 setNode(0, (xmlNodePtr) ent);
2835                 break;
2836             }
2837 
2838             case OP_XML_ADD_ENTITY: {
2839                 xmlEntityPtr ent;
2840                 int res;
2841 
2842                 startOp("xmlAddEntity");
2843                 incNodeIdx();
2844                 res = xmlAddEntity(
2845                     getDoc(1),
2846                     getInt(0),
2847                     getStr(0),
2848                     getInt(1),
2849                     getStr(1),
2850                     getStr(2),
2851                     getStr(3),
2852                     &ent);
2853                 oomReport = (res == XML_ERR_NO_MEMORY);
2854                 setNode(0, (xmlNodePtr) ent);
2855                 break;
2856             }
2857 
2858             case OP_XML_ADD_DOC_ENTITY: {
2859                 xmlEntityPtr ent;
2860 
2861                 startOp("xmlAddDocEntity");
2862                 incNodeIdx();
2863                 ent = xmlAddDocEntity(
2864                     getDoc(1),
2865                     getStr(0),
2866                     getInt(1),
2867                     getStr(1),
2868                     getStr(2),
2869                     getStr(3));
2870                 if (ent != NULL)
2871                     oomReport = 0;
2872                 setNode(0, (xmlNodePtr) ent);
2873                 break;
2874             }
2875 
2876             case OP_XML_ADD_DTD_ENTITY: {
2877                 xmlEntityPtr ent;
2878 
2879                 startOp("xmlAddDtdEntity");
2880                 incNodeIdx();
2881                 ent = xmlAddDtdEntity(
2882                     getDoc(1),
2883                     getStr(0),
2884                     getInt(1),
2885                     getStr(1),
2886                     getStr(2),
2887                     getStr(3));
2888                 setNode(0, (xmlNodePtr) ent);
2889                 break;
2890             }
2891 
2892             case OP_XML_GET_PREDEFINED_ENTITY:
2893                 startOp("xmlGetPredefinedEntity");
2894                 incNodeIdx();
2895                 setNode(0, (xmlNodePtr) xmlGetPredefinedEntity(
2896                     getStr(0)));
2897                 oomReport = 0;
2898                 break;
2899 
2900             case OP_XML_GET_DOC_ENTITY:
2901                 startOp("xmlGetDocEntity");
2902                 incNodeIdx();
2903                 setNode(0, (xmlNodePtr) xmlGetDocEntity(
2904                     getDoc(1),
2905                     getStr(0)));
2906                 oomReport = 0;
2907                 break;
2908 
2909             case OP_XML_GET_DTD_ENTITY:
2910                 startOp("xmlGetDtdEntity");
2911                 incNodeIdx();
2912                 setNode(0, (xmlNodePtr) xmlGetDtdEntity(
2913                     getDoc(1),
2914                     getStr(0)));
2915                 oomReport = 0;
2916                 break;
2917 
2918             case OP_XML_GET_PARAMETER_ENTITY:
2919                 startOp("xmlGetParameterEntity");
2920                 incNodeIdx();
2921                 setNode(0, (xmlNodePtr) xmlGetParameterEntity(
2922                     getDoc(1),
2923                     getStr(0)));
2924                 oomReport = 0;
2925                 break;
2926 
2927             case OP_XML_ENCODE_ENTITIES_REENTRANT: {
2928                 const xmlChar *string;
2929                 xmlChar *encoded;
2930 
2931                 startOp("xmlEncodeEntitiesReentrant");
2932                 incStrIdx();
2933                 encoded = xmlEncodeEntitiesReentrant(
2934                     getDoc(0),
2935                     string = getStr(1));
2936                 oomReport = (string != NULL && encoded == NULL);
2937                 moveStr(0, encoded);
2938                 endOp();
2939                 break;
2940             }
2941 
2942             case OP_XML_ENCODE_SPECIAL_CHARS: {
2943                 const xmlChar *string;
2944                 xmlChar *encoded;
2945 
2946                 startOp("xmlEncodespecialChars");
2947                 incStrIdx();
2948                 encoded = xmlEncodeSpecialChars(
2949                     getDoc(0),
2950                     string = getStr(1));
2951                 oomReport = (string != NULL && encoded == NULL);
2952                 moveStr(0, encoded);
2953                 endOp();
2954                 break;
2955             }
2956 
2957 #ifdef LIBXML_HTML_ENABLED
2958             case OP_HTML_NEW_DOC: {
2959                 htmlDocPtr doc;
2960 
2961                 startOp("htmlNewDoc");
2962                 incNodeIdx();
2963                 doc = htmlNewDoc(
2964                     getStr(0),
2965                     getStr(1));
2966                 oomReport = (doc == NULL);
2967                 setNode(0, (xmlNodePtr) doc);
2968                 break;
2969             }
2970 
2971             case OP_HTML_NEW_DOC_NO_DTD: {
2972                 htmlDocPtr doc;
2973 
2974                 startOp("htmlNewDocNoDtD");
2975                 incNodeIdx();
2976                 doc = htmlNewDocNoDtD(
2977                     getStr(0),
2978                     getStr(1));
2979                 oomReport = (doc == NULL);
2980                 setNode(0, (xmlNodePtr) doc);
2981                 break;
2982             }
2983 
2984             case OP_HTML_GET_META_ENCODING: {
2985                 const xmlChar *encoding;
2986 
2987                 startOp("htmlGetMetaEncoding");
2988                 incStrIdx();
2989                 encoding = htmlGetMetaEncoding(getDoc(0));
2990                 if (encoding != NULL)
2991                     oomReport = 0;
2992                 copyStr(0, encoding);
2993                 break;
2994             }
2995 
2996             case OP_HTML_SET_META_ENCODING:
2997                 /* TODO (can destroy inner text) */
2998                 break;
2999 
3000             case OP_HTML_IS_BOOLEAN_ATTR:
3001                 startOp("htmlIsBooleanAttr");
3002                 htmlIsBooleanAttr(getStr(0));
3003                 oomReport = 0;
3004                 endOp();
3005                 break;
3006 #endif
3007 
3008 #ifdef LIBXML_VALID_ENABLED
3009             case OP_VALIDATE: {
3010                 xmlNodePtr node;
3011                 int type;
3012                 int res = 1;
3013 
3014                 startOp("validate");
3015                 incIntIdx();
3016                 node = getNode(0);
3017                 type = node ? node->type : 0;
3018                 xmlValidCtxtPtr vctxt = xmlNewValidCtxt();
3019                 xmlFuzzResetMallocFailed();
3020 
3021                 switch (type) {
3022                     case XML_DOCUMENT_NODE:
3023                     case XML_HTML_DOCUMENT_NODE:
3024                         res = xmlValidateDocument(vctxt, (xmlDocPtr) node);
3025                         break;
3026                     case XML_ELEMENT_DECL:
3027                         res = xmlValidateElementDecl(vctxt, node->doc,
3028                             (xmlElementPtr) node);
3029                         break;
3030                     case XML_ATTRIBUTE_DECL:
3031                         res = xmlValidateAttributeDecl(vctxt, node->doc,
3032                             (xmlAttributePtr) node);
3033                         break;
3034                     case XML_ELEMENT_NODE:
3035                         res = xmlValidateElement(vctxt, node->doc, node);
3036                         break;
3037                     default:
3038                         break;
3039                 }
3040 
3041                 if (res != 0)
3042                     oomReport = 0;
3043                 xmlFreeValidCtxt(vctxt);
3044                 setInt(0, res);
3045                 endOp();
3046                 break;
3047             }
3048 
3049             case OP_XML_VALIDATE_DTD: {
3050                 xmlValidCtxtPtr vctxt;
3051                 int res;
3052 
3053                 startOp("xmlValidateDtd");
3054                 incIntIdx();
3055                 vctxt = xmlNewValidCtxt();
3056                 res = xmlValidateDtd(
3057                     vctxt,
3058                     getDoc(0),
3059                     getDtd(1));
3060                 if (res != 0)
3061                     oomReport = 0;
3062                 xmlFreeValidCtxt(vctxt);
3063                 setInt(0, res);
3064                 endOp();
3065                 break;
3066             }
3067 #endif /* LIBXML_VALID_ENABLED */
3068 
3069 #ifdef LIBXML_OUTPUT_ENABLED
3070             case OP_XML_DOC_DUMP_MEMORY:
3071             case OP_XML_DOC_DUMP_MEMORY_ENC:
3072             case OP_XML_DOC_DUMP_FORMAT_MEMORY:
3073             case OP_XML_DOC_DUMP_FORMAT_MEMORY_ENC:
3074             case OP_HTML_DOC_DUMP_MEMORY:
3075             case OP_HTML_DOC_DUMP_MEMORY_FORMAT: {
3076                 xmlDocPtr doc;
3077                 xmlChar *out = NULL;
3078                 int outSize = 0;
3079 
3080                 switch (op) {
3081                     case OP_XML_DOC_DUMP_MEMORY:
3082                         startOp("xmlDocDumpMemory"); break;
3083                     case OP_XML_DOC_DUMP_MEMORY_ENC:
3084                         startOp("xmlDocDumpMemoryEnc"); break;
3085                     case OP_XML_DOC_DUMP_FORMAT_MEMORY:
3086                         startOp("xmlDocDumpFormatMemory"); break;
3087                     case OP_XML_DOC_DUMP_FORMAT_MEMORY_ENC:
3088                         startOp("xmlDocDumpFormatMemoryEnc"); break;
3089                     case OP_HTML_DOC_DUMP_MEMORY:
3090                         startOp("htmlDocDumpMemory"); break;
3091                     case OP_HTML_DOC_DUMP_MEMORY_FORMAT:
3092                         startOp("htmlDocDumpMemoryFormat"); break;
3093                 }
3094 
3095                 incStrIdx();
3096                 doc = getDoc(0);
3097 
3098                 switch (op) {
3099                     case OP_XML_DOC_DUMP_MEMORY:
3100                         xmlDocDumpMemory(doc, &out, &outSize);
3101                         break;
3102                     case OP_XML_DOC_DUMP_MEMORY_ENC:
3103                         xmlDocDumpMemoryEnc(doc, &out, &outSize,
3104                             (const char *) getStr(1));
3105                         break;
3106                     case OP_XML_DOC_DUMP_FORMAT_MEMORY:
3107                         xmlDocDumpFormatMemory(doc, &out, &outSize,
3108                             getInt(0));
3109                         break;
3110                     case OP_XML_DOC_DUMP_FORMAT_MEMORY_ENC:
3111                         xmlDocDumpFormatMemoryEnc(doc, &out, &outSize,
3112                             (const char *) getStr(1),
3113                             getInt(0));
3114                         break;
3115 #ifdef LIBXML_HTML_ENABLED
3116                     case OP_HTML_DOC_DUMP_MEMORY:
3117                         htmlDocDumpMemory(doc, &out, &outSize);
3118                         break;
3119                     case OP_HTML_DOC_DUMP_MEMORY_FORMAT:
3120                         htmlDocDumpMemoryFormat(doc, &out, &outSize,
3121                             getInt(0));
3122                         break;
3123 #endif /* LIBXML_HTML_ENABLED */
3124                 }
3125 
3126                 /* Could be an unknown encoding */
3127                 if (out != NULL)
3128                     oomReport = 0;
3129                 moveStr(0, out);
3130                 endOp();
3131                 break;
3132             }
3133 
3134             case OP_XML_NODE_DUMP:
3135             case OP_XML_NODE_BUF_GET_CONTENT:
3136             case OP_XML_ATTR_SERIALIZE_TXT_CONTENT:
3137             case OP_XML_DUMP_ELEMENT_DECL:
3138             case OP_XML_DUMP_ELEMENT_TABLE:
3139             case OP_XML_DUMP_ATTRIBUTE_DECL:
3140             case OP_XML_DUMP_ATTRIBUTE_TABLE:
3141             case OP_XML_DUMP_ENTITY_DECL:
3142             case OP_XML_DUMP_ENTITIES_TABLE:
3143             case OP_XML_DUMP_NOTATION_DECL:
3144             case OP_XML_DUMP_NOTATION_TABLE:
3145             case OP_HTML_NODE_DUMP: {
3146                 xmlNodePtr node;
3147                 xmlDocPtr doc;
3148                 xmlBufferPtr buffer;
3149                 xmlChar *dump;
3150                 int level, format, res;
3151 
3152                 switch (op) {
3153                     case OP_XML_NODE_DUMP:
3154                         startOp("xmlNodeDump"); break;
3155                     case OP_XML_NODE_BUF_GET_CONTENT:
3156                         startOp("xmlNodeBufGetContent"); break;
3157                     case OP_XML_ATTR_SERIALIZE_TXT_CONTENT:
3158                         startOp("xmlAttrSerializeTxtContent"); break;
3159                     case OP_XML_DUMP_ELEMENT_DECL:
3160                         startOp("xmlDumpElementDecl"); break;
3161                     case OP_XML_DUMP_ELEMENT_TABLE:
3162                         startOp("xmlDumpElementTable"); break;
3163                     case OP_XML_DUMP_ATTRIBUTE_DECL:
3164                         startOp("xmlDumpAttributeDecl"); break;
3165                     case OP_XML_DUMP_ATTRIBUTE_TABLE:
3166                         startOp("xmlDumpAttributeTable"); break;
3167                     case OP_XML_DUMP_ENTITY_DECL:
3168                         startOp("xmlDumpEntityDecl"); break;
3169                     case OP_XML_DUMP_ENTITIES_TABLE:
3170                         startOp("xmlDumpEntitiesTable"); break;
3171                     case OP_XML_DUMP_NOTATION_DECL:
3172                         startOp("xmlDumpNotationDecl"); break;
3173                     case OP_XML_DUMP_NOTATION_TABLE:
3174                         startOp("xmlDumpNotationTable"); break;
3175                     case OP_HTML_NODE_DUMP:
3176                         startOp("htmlNodeDump"); break;
3177                 }
3178 
3179                 incStrIdx();
3180                 buffer = xmlBufferCreate();
3181                 xmlFuzzResetMallocFailed();
3182                 node = getNode(0);
3183                 doc = node ? node->doc : NULL;
3184                 level = getInt(0);
3185                 format = getInt(0);
3186                 res = 0;
3187 
3188                 switch (op) {
3189                     case OP_XML_NODE_DUMP:
3190                         res = xmlNodeDump(buffer, doc, node, level, format);
3191                         break;
3192                     case OP_XML_NODE_BUF_GET_CONTENT:
3193                         res = xmlNodeBufGetContent(buffer, node);
3194                         break;
3195                     case OP_XML_ATTR_SERIALIZE_TXT_CONTENT:
3196                         if (node != NULL && node->type != XML_ATTRIBUTE_NODE)
3197                             node = NULL;
3198                         xmlAttrSerializeTxtContent(
3199                             buffer, doc,
3200                             (xmlAttrPtr) node,
3201                             getStr(1));
3202                         break;
3203                     case OP_XML_DUMP_ELEMENT_DECL:
3204                         if (node != NULL && node->type != XML_ELEMENT_DECL)
3205                             node = NULL;
3206                         xmlDumpElementDecl(buffer, (xmlElementPtr) node);
3207                         break;
3208                     case OP_XML_DUMP_ATTRIBUTE_DECL:
3209                         if (node != NULL && node->type != XML_ATTRIBUTE_DECL)
3210                             node = NULL;
3211                         xmlDumpAttributeDecl(buffer, (xmlAttributePtr) node);
3212                         break;
3213                     case OP_XML_DUMP_NOTATION_DECL:
3214                         /* TODO */
3215                         break;
3216                     case OP_XML_DUMP_ENTITY_DECL:
3217                         if (node != NULL && node->type != XML_ENTITY_DECL)
3218                             node = NULL;
3219                         xmlDumpEntityDecl(buffer, (xmlEntityPtr) node);
3220                         break;
3221                     case OP_XML_DUMP_ELEMENT_TABLE: {
3222                         xmlElementTablePtr table;
3223 
3224                         table = node != NULL && node->type == XML_DTD_NODE ?
3225                                 ((xmlDtdPtr) node)->elements :
3226                                 NULL;
3227                         xmlDumpElementTable(buffer, table);
3228                         break;
3229                     }
3230                     case OP_XML_DUMP_ATTRIBUTE_TABLE: {
3231                         xmlAttributeTablePtr table;
3232 
3233                         table = node != NULL && node->type == XML_DTD_NODE ?
3234                                 ((xmlDtdPtr) node)->attributes :
3235                                 NULL;
3236                         xmlDumpAttributeTable(buffer, table);
3237                         break;
3238                     }
3239                     case OP_XML_DUMP_NOTATION_TABLE: {
3240                         xmlNotationTablePtr table;
3241 
3242                         table = node != NULL && node->type == XML_DTD_NODE ?
3243                                 ((xmlDtdPtr) node)->notations :
3244                                 NULL;
3245                         xmlDumpNotationTable(buffer, table);
3246                         break;
3247                     }
3248                     case OP_XML_DUMP_ENTITIES_TABLE: {
3249                         xmlEntitiesTablePtr table;
3250 
3251                         table = node != NULL && node->type == XML_DTD_NODE ?
3252                                 ((xmlDtdPtr) node)->entities :
3253                                 NULL;
3254                         xmlDumpEntitiesTable(buffer, table);
3255                         break;
3256                     }
3257 #ifdef LIBXML_HTML_ENABLED
3258                     case OP_HTML_NODE_DUMP:
3259                         res = htmlNodeDump(buffer, doc, node);
3260                         break;
3261 #endif /* LIBXML_HTML_ENABLED */
3262                 }
3263 
3264                 dump = xmlBufferDetach(buffer);
3265                 if (res == 0 && dump != NULL)
3266                     oomReport = 0;
3267                 moveStr(0, dump);
3268                 xmlBufferFree(buffer);
3269                 endOp();
3270                 break;
3271             }
3272 
3273             case OP_XML_SAVE_FILE_TO:
3274             case OP_XML_SAVE_FORMAT_FILE_TO:
3275             case OP_XML_NODE_DUMP_OUTPUT:
3276             case OP_HTML_DOC_CONTENT_DUMP_OUTPUT:
3277             case OP_HTML_DOC_CONTENT_DUMP_FORMAT_OUTPUT:
3278             case OP_HTML_NODE_DUMP_OUTPUT:
3279             case OP_HTML_NODE_DUMP_FORMAT_OUTPUT: {
3280                 xmlNodePtr node;
3281                 xmlDocPtr doc;
3282                 xmlOutputBufferPtr output;
3283                 const char *encoding;
3284                 int level, format, argsOk, res, closed;
3285 
3286                 switch (op) {
3287                     case OP_XML_SAVE_FILE_TO:
3288                         startOp("xmlSaveFileTo"); break;
3289                     case OP_XML_SAVE_FORMAT_FILE_TO:
3290                         startOp("xmlSaveFormatFileTo"); break;
3291                     case OP_XML_NODE_DUMP_OUTPUT:
3292                         startOp("xmlNodeDumpOutput"); break;
3293                     case OP_HTML_DOC_CONTENT_DUMP_OUTPUT:
3294                         startOp("htmlDocContentDumpOutput"); break;
3295                     case OP_HTML_DOC_CONTENT_DUMP_FORMAT_OUTPUT:
3296                         startOp("htmlDocContentDumpFormatOutput"); break;
3297                     case OP_HTML_NODE_DUMP_OUTPUT:
3298                         startOp("htmlNodeDumpOutput"); break;
3299                     case OP_HTML_NODE_DUMP_FORMAT_OUTPUT:
3300                         startOp("htmlNodeDumpFormatOutput"); break;
3301                 }
3302 
3303                 incStrIdx();
3304                 output = xmlAllocOutputBuffer(NULL);
3305                 xmlFuzzResetMallocFailed();
3306                 node = getNode(0);
3307                 doc = node ? node->doc : NULL;
3308                 encoding = (const char *) getStr(1);
3309                 level = getInt(0);
3310                 format = getInt(0);
3311                 argsOk = (output != NULL);
3312                 res = 0;
3313                 closed = 0;
3314 
3315                 switch (op) {
3316                     case OP_XML_SAVE_FILE_TO:
3317                         argsOk &= (doc != NULL);
3318                         res = xmlSaveFileTo(output, doc, encoding);
3319                         closed = 1;
3320                         break;
3321                     case OP_XML_SAVE_FORMAT_FILE_TO:
3322                         argsOk &= (doc != NULL);
3323                         res = xmlSaveFormatFileTo(output, doc, encoding, format);
3324                         closed = 1;
3325                         break;
3326                     case OP_XML_NODE_DUMP_OUTPUT:
3327                         argsOk &= (node != NULL);
3328                         xmlNodeDumpOutput(output, doc, node, level, format,
3329                                           encoding);
3330                         break;
3331 #ifdef LIBXML_HTML_ENABLED
3332                     case OP_HTML_DOC_CONTENT_DUMP_OUTPUT:
3333                         argsOk &= (doc != NULL);
3334                         htmlDocContentDumpOutput(output, doc, encoding);
3335                         break;
3336                     case OP_HTML_DOC_CONTENT_DUMP_FORMAT_OUTPUT:
3337                         argsOk &= (doc != NULL);
3338                         htmlDocContentDumpFormatOutput(output, doc, encoding,
3339                                                        format);
3340                         break;
3341                     case OP_HTML_NODE_DUMP_OUTPUT:
3342                         argsOk &= (node != NULL);
3343                         htmlNodeDumpOutput(output, doc, node, encoding);
3344                         break;
3345                     case OP_HTML_NODE_DUMP_FORMAT_OUTPUT:
3346                         argsOk &= (node != NULL);
3347                         htmlNodeDumpFormatOutput(output, doc, node, encoding,
3348                                                  format);
3349                         break;
3350 #endif /* LIBXML_HTML_ENABLED */
3351                 }
3352 
3353                 if (closed) {
3354                     if (res >= 0)
3355                         oomReport = 0;
3356                     moveStr(0, NULL);
3357                 } else {
3358                     oomReport =
3359                         (output != NULL &&
3360                          output->error == XML_ERR_NO_MEMORY);
3361                     if (argsOk && !output->error)
3362                         copyStr(0, xmlBufContent(output->buffer));
3363                     else
3364                         moveStr(0, NULL);
3365                     xmlOutputBufferClose(output);
3366                 }
3367                 endOp();
3368                 break;
3369             }
3370 #endif /* LIBXML_OUTPUT_ENABLED */
3371 
3372             case OP_XML_DOM_WRAP_RECONCILE_NAMESPACES: {
3373                 xmlNodePtr node;
3374                 int res;
3375 
3376                 startOp("xmlDOMWrapReconcileNamespaces");
3377                 res = xmlDOMWrapReconcileNamespaces(
3378                     NULL,
3379                     node = getNode(0),
3380                     getInt(0));
3381                 oomReport =
3382                     (node != NULL &&
3383                      node->doc != NULL &&
3384                      node->type == XML_ELEMENT_NODE &&
3385                      res < 0);
3386                 endOp();
3387                 break;
3388             }
3389 
3390             case OP_XML_DOM_WRAP_ADOPT_NODE: {
3391                 xmlDOMWrapCtxtPtr ctxt;
3392                 xmlDocPtr doc, destDoc, oldDoc;
3393                 xmlNodePtr node, destParent, oldParent;
3394                 int res;
3395 
3396                 startOp("xmlDOMWrapAdoptNode");
3397                 ctxt = xmlDOMWrapNewCtxt();
3398                 doc = getDoc(0);
3399                 node = getNode(1);
3400                 destDoc = getDoc(2);
3401                 destParent = getNode(3);
3402 
3403                 if (!isValidChild(destParent, node))
3404                     destParent = NULL;
3405 
3406                 oldParent = node ? node->parent : NULL;
3407                 oldDoc = node ? node->doc : NULL;
3408 
3409                 res = xmlDOMWrapAdoptNode(
3410                     ctxt,
3411                     doc,
3412                     node,
3413                     destDoc,
3414                     destParent,
3415                     getInt(0));
3416                 if (ctxt == NULL)
3417                     oomReport = 1;
3418                 else if (res == 0)
3419                     oomReport = 0;
3420 
3421                 if (node != NULL) {
3422                     /* Node can reference destParent's namespaces */
3423                     if (destParent != NULL &&
3424                         node->parent == NULL &&
3425                         node->doc == destParent->doc) {
3426                         if (node->type == XML_ATTRIBUTE_NODE) {
3427                             xmlNodePtr prop;
3428 
3429                             /* Insert without removing duplicates */
3430                             node->parent = destParent;
3431                             prop = (xmlNodePtr) destParent->properties;
3432                             node->next = prop;
3433                             if (prop != NULL)
3434                                 prop->prev = node;
3435                             destParent->properties = (xmlAttrPtr) node;
3436                         } else if (node->type != XML_TEXT_NODE) {
3437                             xmlAddChild(destParent, node);
3438                         }
3439                     }
3440 
3441                     /* Node can be unlinked and moved to a new document. */
3442                     if (oldParent != NULL && node->parent != oldParent)
3443                         dropNode(oldParent);
3444                     else if (node->doc != oldDoc)
3445                         dropNode((xmlNodePtr) oldDoc);
3446                 }
3447 
3448                 xmlDOMWrapFreeCtxt(ctxt);
3449                 endOp();
3450                 break;
3451             }
3452 
3453             case OP_XML_DOM_WRAP_REMOVE_NODE: {
3454                 xmlDocPtr doc;
3455                 xmlNodePtr node, oldParent;
3456                 int res;
3457 
3458                 startOp("xmlDOMWrapRemoveNode");
3459                 doc = getDoc(0);
3460                 node = getNode(1);
3461                 oldParent = node ? node->parent : NULL;
3462                 res = xmlDOMWrapRemoveNode(NULL, doc, node, 0);
3463                 oomReport =
3464                     (node != NULL &&
3465                      doc != NULL &&
3466                      node->doc == doc &&
3467                      res < 0);
3468                 if (node != NULL && node->parent != oldParent) {
3469                     if (fixNs(node) < 0)
3470                         oomReport = 1;
3471                     dropNode(oldParent);
3472                 }
3473                 endOp();
3474                 break;
3475             }
3476 
3477             case OP_XML_DOM_WRAP_CLONE_NODE: {
3478                 xmlDOMWrapCtxtPtr ctxt;
3479                 xmlDocPtr doc, destDoc;
3480                 xmlNodePtr node, destParent, copy = NULL;
3481                 int res;
3482 
3483                 startOp("xmlDOMWrapCloneNode");
3484                 incNodeIdx();
3485                 ctxt = xmlDOMWrapNewCtxt();
3486                 doc = getDoc(1);
3487                 node = getNode(2);
3488                 destDoc = getDoc(3);
3489                 destParent = getNode(4);
3490 
3491                 if (destParent != NULL &&
3492                     node != NULL &&
3493                     !isValidChildType(destParent, node->type))
3494                     destParent = NULL;
3495 
3496                 /* xmlDOMWrapCloneNode returns a garbage node on error. */
3497                 res = xmlDOMWrapCloneNode(
3498                     ctxt,
3499                     doc,
3500                     node,
3501                     &copy,
3502                     destDoc,
3503                     destParent,
3504                     getInt(0),
3505                     0);
3506                 if (ctxt == NULL)
3507                     oomReport = 1;
3508                 else if (res == 0)
3509                     oomReport = 0;
3510                 copy = checkCopy(copy);
3511 
3512                 /* Copy can reference destParent's namespaces */
3513                 if (destParent != NULL && copy != NULL) {
3514                     if (copy->type == XML_ATTRIBUTE_NODE) {
3515                         xmlNodePtr prop;
3516 
3517                         /* Insert without removing duplicates */
3518                         copy->parent = destParent;
3519                         prop = (xmlNodePtr) destParent->properties;
3520                         copy->next = prop;
3521                         if (prop != NULL)
3522                             prop->prev = copy;
3523                         destParent->properties = (xmlAttrPtr) copy;
3524                     } else if (copy->type != XML_TEXT_NODE) {
3525                         xmlAddChild(destParent, copy);
3526                     }
3527                 }
3528 
3529                 xmlDOMWrapFreeCtxt(ctxt);
3530                 setNode(0, copy);
3531                 break;
3532             }
3533 
3534             case OP_XML_CHILD_ELEMENT_COUNT:
3535                 startOp("xmlChildElementCount");
3536                 incIntIdx();
3537                 setInt(0, xmlChildElementCount(getNode(0)));
3538                 oomReport = 0;
3539                 break;
3540 
3541             case OP_XML_FIRST_ELEMENT_CHILD:
3542                 startOp("xmlFirstElementChild");
3543                 incNodeIdx();
3544                 setNode(0, xmlFirstElementChild(getNode(1)));
3545                 oomReport = 0;
3546                 break;
3547 
3548             case OP_XML_LAST_ELEMENT_CHILD:
3549                 startOp("xmlLastElementChild");
3550                 incNodeIdx();
3551                 setNode(0, xmlLastElementChild(getNode(1)));
3552                 oomReport = 0;
3553                 break;
3554 
3555             case OP_XML_NEXT_ELEMENT_SIBLING:
3556                 startOp("xmlNextElementSibling");
3557                 incNodeIdx();
3558                 setNode(0, xmlNextElementSibling(getNode(1)));
3559                 oomReport = 0;
3560                 break;
3561 
3562             case OP_XML_PREVIOUS_ELEMENT_SIBLING:
3563                 startOp("xmlPreviousElementSibling");
3564                 incNodeIdx();
3565                 setNode(0, xmlPreviousElementSibling(getNode(1)));
3566                 oomReport = 0;
3567                 break;
3568 
3569             default:
3570                 break;
3571         }
3572 
3573         xmlFuzzCheckMallocFailure(vars->opName, oomReport);
3574     }
3575 
3576     for (i = 0; i < REG_MAX; i++)
3577         xmlFree(vars->strings[i]);
3578 
3579     for (i = 0; i < REG_MAX; i++) {
3580         xmlNodePtr node = vars->nodes[i];
3581 
3582         vars->nodes[i] = NULL;
3583         dropNode(node);
3584     }
3585 
3586     xmlFuzzMemSetLimit(0);
3587     xmlFuzzDataCleanup();
3588     xmlResetLastError();
3589     return(0);
3590 }
3591 
3592