xref: /aosp_15_r20/external/libxml2/error.c (revision 7c5688314b92172186c154356a6374bf7684c3ca)
1 /*
2  * error.c: module displaying/handling XML parser errors
3  *
4  * See Copyright for the status of this software.
5  *
6  * Daniel Veillard <[email protected]>
7  */
8 
9 #define IN_LIBXML
10 #include "libxml.h"
11 
12 #include <string.h>
13 #include <stdarg.h>
14 #include <stdlib.h>
15 #include <libxml/parser.h>
16 #include <libxml/xmlerror.h>
17 #include <libxml/xmlmemory.h>
18 
19 #include "private/error.h"
20 #include "private/globals.h"
21 #include "private/string.h"
22 
23 /************************************************************************
24  *									*
25  *			Error struct					*
26  *									*
27  ************************************************************************/
28 
29 static int
xmlVSetError(xmlError * err,void * ctxt,xmlNodePtr node,int domain,int code,xmlErrorLevel level,const char * file,int line,const char * str1,const char * str2,const char * str3,int int1,int col,const char * fmt,va_list ap)30 xmlVSetError(xmlError *err,
31              void *ctxt, xmlNodePtr node,
32              int domain, int code, xmlErrorLevel level,
33              const char *file, int line,
34              const char *str1, const char *str2, const char *str3,
35              int int1, int col,
36              const char *fmt, va_list ap)
37 {
38     char *message = NULL;
39     char *fileCopy = NULL;
40     char *str1Copy = NULL;
41     char *str2Copy = NULL;
42     char *str3Copy = NULL;
43 
44     if (code == XML_ERR_OK) {
45         xmlResetError(err);
46         return(0);
47     }
48 
49     /*
50      * Formatting the message
51      */
52     if (fmt == NULL) {
53         message = xmlMemStrdup("No error message provided");
54     } else {
55         xmlChar *tmp;
56         int res;
57 
58         res = xmlStrVASPrintf(&tmp, MAX_ERR_MSG_SIZE, fmt, ap);
59         if (res < 0)
60             goto err_memory;
61         message = (char *) tmp;
62     }
63     if (message == NULL)
64         goto err_memory;
65 
66     if (file != NULL) {
67         fileCopy = (char *) xmlStrdup((const xmlChar *) file);
68         if (fileCopy == NULL)
69             goto err_memory;
70     }
71     if (str1 != NULL) {
72         str1Copy = (char *) xmlStrdup((const xmlChar *) str1);
73         if (str1Copy == NULL)
74             goto err_memory;
75     }
76     if (str2 != NULL) {
77         str2Copy = (char *) xmlStrdup((const xmlChar *) str2);
78         if (str2Copy == NULL)
79             goto err_memory;
80     }
81     if (str3 != NULL) {
82         str3Copy = (char *) xmlStrdup((const xmlChar *) str3);
83         if (str3Copy == NULL)
84             goto err_memory;
85     }
86 
87     xmlResetError(err);
88 
89     err->domain = domain;
90     err->code = code;
91     err->message = message;
92     err->level = level;
93     err->file = fileCopy;
94     err->line = line;
95     err->str1 = str1Copy;
96     err->str2 = str2Copy;
97     err->str3 = str3Copy;
98     err->int1 = int1;
99     err->int2 = col;
100     err->node = node;
101     err->ctxt = ctxt;
102 
103     return(0);
104 
105 err_memory:
106     xmlFree(message);
107     xmlFree(fileCopy);
108     xmlFree(str1Copy);
109     xmlFree(str2Copy);
110     xmlFree(str3Copy);
111     return(-1);
112 }
113 
114 static int LIBXML_ATTR_FORMAT(14,15)
xmlSetError(xmlError * err,void * ctxt,xmlNodePtr node,int domain,int code,xmlErrorLevel level,const char * file,int line,const char * str1,const char * str2,const char * str3,int int1,int col,const char * fmt,...)115 xmlSetError(xmlError *err,
116             void *ctxt, xmlNodePtr node,
117             int domain, int code, xmlErrorLevel level,
118             const char *file, int line,
119             const char *str1, const char *str2, const char *str3,
120             int int1, int col,
121             const char *fmt, ...)
122 {
123     va_list ap;
124     int res;
125 
126     va_start(ap, fmt);
127     res = xmlVSetError(err, ctxt, node, domain, code, level, file, line,
128                        str1, str2, str3, int1, col, fmt, ap);
129     va_end(ap);
130 
131     return(res);
132 }
133 
134 static int
xmlVUpdateError(xmlError * err,void * ctxt,xmlNodePtr node,int domain,int code,xmlErrorLevel level,const char * file,int line,const char * str1,const char * str2,const char * str3,int int1,int col,const char * fmt,va_list ap)135 xmlVUpdateError(xmlError *err,
136                 void *ctxt, xmlNodePtr node,
137                 int domain, int code, xmlErrorLevel level,
138                 const char *file, int line,
139                 const char *str1, const char *str2, const char *str3,
140                 int int1, int col,
141                 const char *fmt, va_list ap)
142 {
143     int res;
144 
145     /*
146      * Find first element parent.
147      */
148     if (node != NULL) {
149         int i;
150 
151         for (i = 0; i < 10; i++) {
152             if ((node->type == XML_ELEMENT_NODE) ||
153                 (node->parent == NULL))
154                 break;
155             node = node->parent;
156         }
157     }
158 
159     /*
160      * Get file and line from node.
161      */
162     if (node != NULL) {
163         if ((file == NULL) && (node->doc != NULL))
164             file = (const char *) node->doc->URL;
165 
166         if (line == 0) {
167             if (node->type == XML_ELEMENT_NODE)
168                 line = node->line;
169             if ((line == 0) || (line == 65535))
170                 line = xmlGetLineNo(node);
171         }
172     }
173 
174     res = xmlVSetError(err, ctxt, node, domain, code, level, file, line,
175                        str1, str2, str3, int1, col, fmt, ap);
176 
177     return(res);
178 }
179 
180 /************************************************************************
181  *									*
182  *			Handling of out of context errors		*
183  *									*
184  ************************************************************************/
185 
186 /**
187  * xmlGenericErrorDefaultFunc:
188  * @ctx:  an error context
189  * @msg:  the message to display/transmit
190  * @...:  extra parameters for the message display
191  *
192  * Default handler for out of context error messages.
193  */
194 void
xmlGenericErrorDefaultFunc(void * ctx ATTRIBUTE_UNUSED,const char * msg,...)195 xmlGenericErrorDefaultFunc(void *ctx ATTRIBUTE_UNUSED, const char *msg, ...) {
196     va_list args;
197 
198     if (xmlGenericErrorContext == NULL)
199 	xmlGenericErrorContext = (void *) stderr;
200 
201     va_start(args, msg);
202     vfprintf((FILE *)xmlGenericErrorContext, msg, args);
203     va_end(args);
204 }
205 
206 /**
207  * initGenericErrorDefaultFunc:
208  * @handler:  the handler
209  *
210  * DEPRECATED: Use xmlSetGenericErrorFunc.
211  *
212  * Set or reset (if NULL) the default handler for generic errors
213  * to the builtin error function.
214  */
215 void
initGenericErrorDefaultFunc(xmlGenericErrorFunc * handler)216 initGenericErrorDefaultFunc(xmlGenericErrorFunc * handler)
217 {
218     if (handler == NULL)
219         xmlGenericError = xmlGenericErrorDefaultFunc;
220     else
221         xmlGenericError = (*handler);
222 }
223 
224 /**
225  * xmlSetGenericErrorFunc:
226  * @ctx:  the new error handling context
227  * @handler:  the new handler function
228  *
229  * DEPRECATED: See xmlSetStructuredErrorFunc for alternatives.
230  *
231  * Set the global "generic" handler and context for error messages.
232  * The generic error handler will only receive fragments of error
233  * messages which should be concatenated or printed to a stream.
234  *
235  * If handler is NULL, use the built-in default handler which prints
236  * to stderr.
237  *
238  * Since this is a global setting, it's a good idea to reset the
239  * error handler to its default value after collecting the errors
240  * you're interested in.
241  *
242  * For multi-threaded applications, this must be set separately for
243  * each thread.
244  */
245 void
xmlSetGenericErrorFunc(void * ctx,xmlGenericErrorFunc handler)246 xmlSetGenericErrorFunc(void *ctx, xmlGenericErrorFunc handler) {
247     xmlGenericErrorContext = ctx;
248     if (handler != NULL)
249 	xmlGenericError = handler;
250     else
251 	xmlGenericError = xmlGenericErrorDefaultFunc;
252 }
253 
254 /**
255  * xmlSetStructuredErrorFunc:
256  * @ctx:  the new error handling context
257  * @handler:  the new handler function
258  *
259  * DEPRECATED: Use a per-context error handler.
260  *
261  * It's recommended to use the per-context error handlers instead:
262  *
263  * - xmlCtxtSetErrorHandler (since 2.13.0)
264  * - xmlTextReaderSetStructuredErrorHandler
265  * - xmlXPathSetErrorHandler (since 2.13.0)
266  * - xmlXIncludeSetErrorHandler (since 2.13.0)
267  * - xmlSchemaSetParserStructuredErrors
268  * - xmlSchemaSetValidStructuredErrors
269  * - xmlRelaxNGSetParserStructuredErrors
270  * - xmlRelaxNGSetValidStructuredErrors
271  *
272  * Set the global "structured" handler and context for error messages.
273  * If handler is NULL, the error handler is deactivated.
274  *
275  * The structured error handler takes precedence over "generic"
276  * handlers, even per-context generic handlers.
277  *
278  * Since this is a global setting, it's a good idea to deactivate the
279  * error handler after collecting the errors you're interested in.
280  *
281  * For multi-threaded applications, this must be set separately for
282  * each thread.
283  */
284 void
xmlSetStructuredErrorFunc(void * ctx,xmlStructuredErrorFunc handler)285 xmlSetStructuredErrorFunc(void *ctx, xmlStructuredErrorFunc handler) {
286     xmlStructuredErrorContext = ctx;
287     xmlStructuredError = handler;
288 }
289 
290 /************************************************************************
291  *									*
292  *			Handling of parsing errors			*
293  *									*
294  ************************************************************************/
295 
296 /**
297  * xmlParserPrintFileInfo:
298  * @input:  an xmlParserInputPtr input
299  *
300  * DEPRECATED: Use xmlFormatError.
301  *
302  * Displays the associated file and line information for the current input
303  */
304 
305 void
xmlParserPrintFileInfo(xmlParserInputPtr input)306 xmlParserPrintFileInfo(xmlParserInputPtr input) {
307     if (input != NULL) {
308 	if (input->filename)
309 	    xmlGenericError(xmlGenericErrorContext,
310 		    "%s:%d: ", input->filename,
311 		    input->line);
312 	else
313 	    xmlGenericError(xmlGenericErrorContext,
314 		    "Entity: line %d: ", input->line);
315     }
316 }
317 
318 /**
319  * xmlParserPrintFileContextInternal:
320  * @input:  an xmlParserInputPtr input
321  *
322  * Displays current context within the input content for error tracking
323  */
324 
325 static void
xmlParserPrintFileContextInternal(xmlParserInputPtr input,xmlGenericErrorFunc channel,void * data)326 xmlParserPrintFileContextInternal(xmlParserInputPtr input ,
327 		xmlGenericErrorFunc channel, void *data ) {
328     const xmlChar *cur, *base, *start;
329     unsigned int n, col;	/* GCC warns if signed, because compared with sizeof() */
330     xmlChar  content[81]; /* space for 80 chars + line terminator */
331     xmlChar *ctnt;
332 
333     if ((input == NULL) || (input->cur == NULL))
334         return;
335 
336     cur = input->cur;
337     base = input->base;
338     /* skip backwards over any end-of-lines */
339     while ((cur > base) && ((*(cur) == '\n') || (*(cur) == '\r'))) {
340 	cur--;
341     }
342     n = 0;
343     /* search backwards for beginning-of-line (to max buff size) */
344     while ((n < sizeof(content) - 1) && (cur > base) &&
345 	   (*cur != '\n') && (*cur != '\r')) {
346         cur--;
347         n++;
348     }
349     if ((n > 0) && ((*cur == '\n') || (*cur == '\r'))) {
350         cur++;
351     } else {
352         /* skip over continuation bytes */
353         while ((cur < input->cur) && ((*cur & 0xC0) == 0x80))
354             cur++;
355     }
356     /* calculate the error position in terms of the current position */
357     col = input->cur - cur;
358     /* search forward for end-of-line (to max buff size) */
359     n = 0;
360     start = cur;
361     /* copy selected text to our buffer */
362     while ((*cur != 0) && (*(cur) != '\n') && (*(cur) != '\r')) {
363         int len = input->end - cur;
364         int c = xmlGetUTF8Char(cur, &len);
365 
366         if ((c < 0) || (n + len > sizeof(content)-1))
367             break;
368         cur += len;
369 	n += len;
370     }
371     memcpy(content, start, n);
372     content[n] = 0;
373     /* print out the selected text */
374     channel(data ,"%s\n", content);
375     /* create blank line with problem pointer */
376     n = 0;
377     ctnt = content;
378     /* (leave buffer space for pointer + line terminator) */
379     while ((n<col) && (n++ < sizeof(content)-2) && (*ctnt != 0)) {
380 	if (*(ctnt) != '\t')
381 	    *(ctnt) = ' ';
382 	ctnt++;
383     }
384     *ctnt++ = '^';
385     *ctnt = 0;
386     channel(data ,"%s\n", content);
387 }
388 
389 /**
390  * xmlParserPrintFileContext:
391  * @input:  an xmlParserInputPtr input
392  *
393  * DEPRECATED: Use xmlFormatError.
394  *
395  * Displays current context within the input content for error tracking
396  */
397 void
xmlParserPrintFileContext(xmlParserInputPtr input)398 xmlParserPrintFileContext(xmlParserInputPtr input) {
399    xmlParserPrintFileContextInternal(input, xmlGenericError,
400                                      xmlGenericErrorContext);
401 }
402 
403 /**
404  * xmlFormatError:
405  * @err:  the error
406  * @channel:  callback
407  * @data:  user data for callback
408  *
409  * Report a formatted error to a printf-like callback.
410  *
411  * This can result in a verbose multi-line report including additional
412  * information from the parser context.
413  *
414  * Available since 2.13.0.
415  */
416 void
xmlFormatError(const xmlError * err,xmlGenericErrorFunc channel,void * data)417 xmlFormatError(const xmlError *err, xmlGenericErrorFunc channel, void *data)
418 {
419     const char *message;
420     const char *file;
421     int line;
422     int code;
423     int domain;
424     const xmlChar *name = NULL;
425     xmlNodePtr node;
426     xmlErrorLevel level;
427     xmlParserCtxtPtr ctxt = NULL;
428     xmlParserInputPtr input = NULL;
429     xmlParserInputPtr cur = NULL;
430 
431     if ((err == NULL) || (channel == NULL))
432         return;
433 
434     message = err->message;
435     file = err->file;
436     line = err->line;
437     code = err->code;
438     domain = err->domain;
439     level = err->level;
440     node = err->node;
441 
442     if (code == XML_ERR_OK)
443         return;
444 
445     if ((domain == XML_FROM_PARSER) || (domain == XML_FROM_HTML) ||
446         (domain == XML_FROM_DTD) || (domain == XML_FROM_NAMESPACE) ||
447 	(domain == XML_FROM_IO) || (domain == XML_FROM_VALID)) {
448 	ctxt = err->ctxt;
449     }
450 
451     if ((node != NULL) && (node->type == XML_ELEMENT_NODE) &&
452         (domain != XML_FROM_SCHEMASV))
453         name = node->name;
454 
455     /*
456      * Maintain the compatibility with the legacy error handling
457      */
458     if ((ctxt != NULL) && (ctxt->input != NULL)) {
459         input = ctxt->input;
460         if ((input->filename == NULL) &&
461             (ctxt->inputNr > 1)) {
462             cur = input;
463             input = ctxt->inputTab[ctxt->inputNr - 2];
464         }
465         if (input->filename)
466             channel(data, "%s:%d: ", input->filename, input->line);
467         else if ((line != 0) && (domain == XML_FROM_PARSER))
468             channel(data, "Entity: line %d: ", input->line);
469     } else {
470         if (file != NULL)
471             channel(data, "%s:%d: ", file, line);
472         else if ((line != 0) &&
473 	         ((domain == XML_FROM_PARSER) || (domain == XML_FROM_SCHEMASV)||
474 		  (domain == XML_FROM_SCHEMASP)||(domain == XML_FROM_DTD) ||
475 		  (domain == XML_FROM_RELAXNGP)||(domain == XML_FROM_RELAXNGV)))
476             channel(data, "Entity: line %d: ", line);
477     }
478     if (name != NULL) {
479         channel(data, "element %s: ", name);
480     }
481     switch (domain) {
482         case XML_FROM_PARSER:
483             channel(data, "parser ");
484             break;
485         case XML_FROM_NAMESPACE:
486             channel(data, "namespace ");
487             break;
488         case XML_FROM_DTD:
489         case XML_FROM_VALID:
490             channel(data, "validity ");
491             break;
492         case XML_FROM_HTML:
493             channel(data, "HTML parser ");
494             break;
495         case XML_FROM_MEMORY:
496             channel(data, "memory ");
497             break;
498         case XML_FROM_OUTPUT:
499             channel(data, "output ");
500             break;
501         case XML_FROM_IO:
502             channel(data, "I/O ");
503             break;
504         case XML_FROM_XINCLUDE:
505             channel(data, "XInclude ");
506             break;
507         case XML_FROM_XPATH:
508             channel(data, "XPath ");
509             break;
510         case XML_FROM_XPOINTER:
511             channel(data, "parser ");
512             break;
513         case XML_FROM_REGEXP:
514             channel(data, "regexp ");
515             break;
516         case XML_FROM_MODULE:
517             channel(data, "module ");
518             break;
519         case XML_FROM_SCHEMASV:
520             channel(data, "Schemas validity ");
521             break;
522         case XML_FROM_SCHEMASP:
523             channel(data, "Schemas parser ");
524             break;
525         case XML_FROM_RELAXNGP:
526             channel(data, "Relax-NG parser ");
527             break;
528         case XML_FROM_RELAXNGV:
529             channel(data, "Relax-NG validity ");
530             break;
531         case XML_FROM_CATALOG:
532             channel(data, "Catalog ");
533             break;
534         case XML_FROM_C14N:
535             channel(data, "C14N ");
536             break;
537         case XML_FROM_XSLT:
538             channel(data, "XSLT ");
539             break;
540         case XML_FROM_I18N:
541             channel(data, "encoding ");
542             break;
543         case XML_FROM_SCHEMATRONV:
544             channel(data, "schematron ");
545             break;
546         case XML_FROM_BUFFER:
547             channel(data, "internal buffer ");
548             break;
549         case XML_FROM_URI:
550             channel(data, "URI ");
551             break;
552         default:
553             break;
554     }
555     switch (level) {
556         case XML_ERR_NONE:
557             channel(data, ": ");
558             break;
559         case XML_ERR_WARNING:
560             channel(data, "warning : ");
561             break;
562         case XML_ERR_ERROR:
563             channel(data, "error : ");
564             break;
565         case XML_ERR_FATAL:
566             channel(data, "error : ");
567             break;
568     }
569     if (message != NULL) {
570         int len;
571 	len = xmlStrlen((const xmlChar *) message);
572 	if ((len > 0) && (message[len - 1] != '\n'))
573 	    channel(data, "%s\n", message);
574 	else
575 	    channel(data, "%s", message);
576     } else {
577         channel(data, "%s\n", "No error message provided");
578     }
579 
580     if (ctxt != NULL) {
581         if ((input != NULL) &&
582             ((input->buf == NULL) || (input->buf->encoder == NULL)) &&
583             (code == XML_ERR_INVALID_ENCODING) &&
584             (input->cur < input->end)) {
585             int i;
586 
587             channel(data, "Bytes:");
588             for (i = 0; i < 4; i++) {
589                 if (input->cur + i >= input->end)
590                     break;
591                 channel(data, " 0x%02X", input->cur[i]);
592             }
593             channel(data, "\n");
594         }
595 
596         xmlParserPrintFileContextInternal(input, channel, data);
597 
598         if (cur != NULL) {
599             if (cur->filename)
600                 channel(data, "%s:%d: \n", cur->filename, cur->line);
601             else if ((line != 0) && (domain == XML_FROM_PARSER))
602                 channel(data, "Entity: line %d: \n", cur->line);
603             xmlParserPrintFileContextInternal(cur, channel, data);
604         }
605     }
606     if ((domain == XML_FROM_XPATH) && (err->str1 != NULL) &&
607         (err->int1 < 100) &&
608 	(err->int1 < xmlStrlen((const xmlChar *)err->str1))) {
609 	xmlChar buf[150];
610 	int i;
611 
612 	channel(data, "%s\n", err->str1);
613 	for (i=0;i < err->int1;i++)
614 	     buf[i] = ' ';
615 	buf[i++] = '^';
616 	buf[i] = 0;
617 	channel(data, "%s\n", buf);
618     }
619 }
620 
621 /**
622  * xmlRaiseMemoryError:
623  * @schannel: the structured callback channel
624  * @channel: the old callback channel
625  * @data: the callback data
626  * @domain: the domain for the error
627  * @error: optional error struct to be filled
628  *
629  * Update the global and optional error structure, then forward the
630  * error to an error handler.
631  *
632  * This function doesn't make memory allocations which are likely
633  * to fail after an OOM error.
634  */
635 void
xmlRaiseMemoryError(xmlStructuredErrorFunc schannel,xmlGenericErrorFunc channel,void * data,int domain,xmlError * error)636 xmlRaiseMemoryError(xmlStructuredErrorFunc schannel, xmlGenericErrorFunc channel,
637                     void *data, int domain, xmlError *error)
638 {
639     xmlError *lastError = xmlGetLastErrorInternal();
640 
641     xmlResetLastError();
642     lastError->domain = domain;
643     lastError->code = XML_ERR_NO_MEMORY;
644     lastError->level = XML_ERR_FATAL;
645 
646     if (error != NULL) {
647         xmlResetError(error);
648         error->domain = domain;
649         error->code = XML_ERR_NO_MEMORY;
650         error->level = XML_ERR_FATAL;
651     }
652 
653     if (schannel != NULL) {
654         schannel(data, lastError);
655     } else if (xmlStructuredError != NULL) {
656         xmlStructuredError(xmlStructuredErrorContext, lastError);
657     } else if (channel != NULL) {
658         channel(data, "libxml2: out of memory\n");
659     }
660 }
661 
662 /**
663  * xmlVRaiseError:
664  * @schannel: the structured callback channel
665  * @channel: the old callback channel
666  * @data: the callback data
667  * @ctx: the parser context or NULL
668  * @node: the current node or NULL
669  * @domain: the domain for the error
670  * @code: the code for the error
671  * @level: the xmlErrorLevel for the error
672  * @file: the file source of the error (or NULL)
673  * @line: the line of the error or 0 if N/A
674  * @str1: extra string info
675  * @str2: extra string info
676  * @str3: extra string info
677  * @int1: extra int info
678  * @col: column number of the error or 0 if N/A
679  * @msg:  the message to display/transmit
680  * @ap:  extra parameters for the message display
681  *
682  * Update the appropriate global or contextual error structure,
683  * then forward the error message down the parser or generic
684  * error callback handler
685  *
686  * Returns 0 on success, -1 if a memory allocation failed.
687  */
688 int
xmlVRaiseError(xmlStructuredErrorFunc schannel,xmlGenericErrorFunc channel,void * data,void * ctx,xmlNode * node,int domain,int code,xmlErrorLevel level,const char * file,int line,const char * str1,const char * str2,const char * str3,int int1,int col,const char * msg,va_list ap)689 xmlVRaiseError(xmlStructuredErrorFunc schannel,
690                xmlGenericErrorFunc channel, void *data, void *ctx,
691                xmlNode *node, int domain, int code, xmlErrorLevel level,
692                const char *file, int line, const char *str1,
693                const char *str2, const char *str3, int int1, int col,
694                const char *msg, va_list ap)
695 {
696     xmlParserCtxtPtr ctxt = NULL;
697     /* xmlLastError is a macro retrieving the per-thread global. */
698     xmlErrorPtr lastError = xmlGetLastErrorInternal();
699     xmlErrorPtr to = lastError;
700 
701     if (code == XML_ERR_OK)
702         return(0);
703 #ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
704     if (code == XML_ERR_INTERNAL_ERROR)
705         xmlAbort("Unexpected error: %d\n", code);
706 #endif
707     if ((xmlGetWarningsDefaultValue == 0) && (level == XML_ERR_WARNING))
708         return(0);
709 
710     if ((domain == XML_FROM_PARSER) || (domain == XML_FROM_HTML) ||
711         (domain == XML_FROM_DTD) || (domain == XML_FROM_NAMESPACE) ||
712 	(domain == XML_FROM_IO) || (domain == XML_FROM_VALID)) {
713 	ctxt = (xmlParserCtxtPtr) ctx;
714 
715         if (ctxt != NULL)
716             to = &ctxt->lastError;
717     }
718 
719     if (xmlVUpdateError(to, ctxt, node, domain, code, level, file, line,
720                         str1, str2, str3, int1, col, msg, ap))
721         return(-1);
722 
723     if (to != lastError) {
724         if (xmlCopyError(to, lastError) < 0)
725             return(-1);
726     }
727 
728     if (schannel != NULL) {
729 	schannel(data, to);
730     } else if (xmlStructuredError != NULL) {
731         xmlStructuredError(xmlStructuredErrorContext, to);
732     } else if (channel != NULL) {
733         /* Don't invoke legacy error handlers */
734         if ((channel == xmlGenericErrorDefaultFunc) ||
735             (channel == xmlParserError) ||
736             (channel == xmlParserWarning) ||
737             (channel == xmlParserValidityError) ||
738             (channel == xmlParserValidityWarning))
739             xmlFormatError(to, xmlGenericError, xmlGenericErrorContext);
740         else
741 	    channel(data, "%s", to->message);
742     }
743 
744     return(0);
745 }
746 
747 /**
748  * xmlRaiseError:
749  * @schannel: the structured callback channel
750  * @channel: the old callback channel
751  * @data: the callback data
752  * @ctx: the parser context or NULL
753  * @nod: the node or NULL
754  * @domain: the domain for the error
755  * @code: the code for the error
756  * @level: the xmlErrorLevel for the error
757  * @file: the file source of the error (or NULL)
758  * @line: the line of the error or 0 if N/A
759  * @str1: extra string info
760  * @str2: extra string info
761  * @str3: extra string info
762  * @int1: extra int info
763  * @col: column number of the error or 0 if N/A
764  * @msg:  the message to display/transmit
765  * @...:  extra parameters for the message display
766  *
767  * Update the appropriate global or contextual error structure,
768  * then forward the error message down the parser or generic
769  * error callback handler
770  *
771  * Returns 0 on success, -1 if a memory allocation failed.
772  */
773 int
xmlRaiseError(xmlStructuredErrorFunc schannel,xmlGenericErrorFunc channel,void * data,void * ctx,xmlNode * node,int domain,int code,xmlErrorLevel level,const char * file,int line,const char * str1,const char * str2,const char * str3,int int1,int col,const char * msg,...)774 xmlRaiseError(xmlStructuredErrorFunc schannel,
775               xmlGenericErrorFunc channel, void *data, void *ctx,
776               xmlNode *node, int domain, int code, xmlErrorLevel level,
777               const char *file, int line, const char *str1,
778               const char *str2, const char *str3, int int1, int col,
779               const char *msg, ...)
780 {
781     va_list ap;
782     int res;
783 
784     va_start(ap, msg);
785     res = xmlVRaiseError(schannel, channel, data, ctx, node, domain, code,
786                          level, file, line, str1, str2, str3, int1, col, msg,
787                          ap);
788     va_end(ap);
789 
790     return(res);
791 }
792 
793 static void
xmlVFormatLegacyError(void * ctx,const char * level,const char * fmt,va_list ap)794 xmlVFormatLegacyError(void *ctx, const char *level,
795                       const char *fmt, va_list ap) {
796     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
797     xmlParserInputPtr input = NULL;
798     xmlParserInputPtr cur = NULL;
799     xmlChar *str = NULL;
800 
801     if (ctxt != NULL) {
802 	input = ctxt->input;
803 	if ((input != NULL) && (input->filename == NULL) &&
804 	    (ctxt->inputNr > 1)) {
805 	    cur = input;
806 	    input = ctxt->inputTab[ctxt->inputNr - 2];
807 	}
808 	xmlParserPrintFileInfo(input);
809     }
810 
811     xmlGenericError(xmlGenericErrorContext, "%s: ", level);
812 
813     xmlStrVASPrintf(&str, MAX_ERR_MSG_SIZE, fmt, ap);
814     if (str != NULL) {
815         xmlGenericError(xmlGenericErrorContext, "%s", (char *) str);
816 	xmlFree(str);
817     }
818 
819     if (ctxt != NULL) {
820 	xmlParserPrintFileContext(input);
821 	if (cur != NULL) {
822 	    xmlParserPrintFileInfo(cur);
823 	    xmlGenericError(xmlGenericErrorContext, "\n");
824 	    xmlParserPrintFileContext(cur);
825 	}
826     }
827 }
828 
829 /**
830  * xmlParserError:
831  * @ctx:  an XML parser context
832  * @msg:  the message to display/transmit
833  * @...:  extra parameters for the message display
834  *
835  * Display and format an error messages, gives file, line, position and
836  * extra parameters.
837  */
838 void
xmlParserError(void * ctx,const char * msg ATTRIBUTE_UNUSED,...)839 xmlParserError(void *ctx, const char *msg ATTRIBUTE_UNUSED, ...)
840 {
841     va_list ap;
842 
843     va_start(ap, msg);
844     xmlVFormatLegacyError(ctx, "error", msg, ap);
845     va_end(ap);
846 }
847 
848 /**
849  * xmlParserWarning:
850  * @ctx:  an XML parser context
851  * @msg:  the message to display/transmit
852  * @...:  extra parameters for the message display
853  *
854  * Display and format a warning messages, gives file, line, position and
855  * extra parameters.
856  */
857 void
xmlParserWarning(void * ctx,const char * msg ATTRIBUTE_UNUSED,...)858 xmlParserWarning(void *ctx, const char *msg ATTRIBUTE_UNUSED, ...)
859 {
860     va_list ap;
861 
862     va_start(ap, msg);
863     xmlVFormatLegacyError(ctx, "warning", msg, ap);
864     va_end(ap);
865 }
866 
867 /**
868  * xmlParserValidityError:
869  * @ctx:  an XML parser context
870  * @msg:  the message to display/transmit
871  * @...:  extra parameters for the message display
872  *
873  * Display and format an validity error messages, gives file,
874  * line, position and extra parameters.
875  */
876 void
xmlParserValidityError(void * ctx,const char * msg ATTRIBUTE_UNUSED,...)877 xmlParserValidityError(void *ctx, const char *msg ATTRIBUTE_UNUSED, ...)
878 {
879     va_list ap;
880 
881     va_start(ap, msg);
882     xmlVFormatLegacyError(ctx, "validity error", msg, ap);
883     va_end(ap);
884 }
885 
886 /**
887  * xmlParserValidityWarning:
888  * @ctx:  an XML parser context
889  * @msg:  the message to display/transmit
890  * @...:  extra parameters for the message display
891  *
892  * Display and format a validity warning messages, gives file, line,
893  * position and extra parameters.
894  */
895 void
xmlParserValidityWarning(void * ctx,const char * msg ATTRIBUTE_UNUSED,...)896 xmlParserValidityWarning(void *ctx, const char *msg ATTRIBUTE_UNUSED, ...)
897 {
898     va_list ap;
899 
900     va_start(ap, msg);
901     xmlVFormatLegacyError(ctx, "validity warning", msg, ap);
902     va_end(ap);
903 }
904 
905 
906 /************************************************************************
907  *									*
908  *			Extended Error Handling				*
909  *									*
910  ************************************************************************/
911 
912 /**
913  * xmlGetLastError:
914  *
915  * Get the last global error registered. This is per thread if compiled
916  * with thread support.
917  *
918  * Returns a pointer to the error
919  */
920 const xmlError *
xmlGetLastError(void)921 xmlGetLastError(void)
922 {
923     const xmlError *error = xmlGetLastErrorInternal();
924 
925     if (error->code == XML_ERR_OK)
926         return(NULL);
927     return(error);
928 }
929 
930 /**
931  * xmlResetError:
932  * @err: pointer to the error.
933  *
934  * Cleanup the error.
935  */
936 void
xmlResetError(xmlErrorPtr err)937 xmlResetError(xmlErrorPtr err)
938 {
939     if (err == NULL)
940         return;
941     if (err->code == XML_ERR_OK)
942         return;
943     if (err->message != NULL)
944         xmlFree(err->message);
945     if (err->file != NULL)
946         xmlFree(err->file);
947     if (err->str1 != NULL)
948         xmlFree(err->str1);
949     if (err->str2 != NULL)
950         xmlFree(err->str2);
951     if (err->str3 != NULL)
952         xmlFree(err->str3);
953     memset(err, 0, sizeof(xmlError));
954     err->code = XML_ERR_OK;
955 }
956 
957 /**
958  * xmlResetLastError:
959  *
960  * Cleanup the last global error registered. For parsing error
961  * this does not change the well-formedness result.
962  */
963 void
xmlResetLastError(void)964 xmlResetLastError(void)
965 {
966     xmlError *error = xmlGetLastErrorInternal();
967 
968     if (error->code != XML_ERR_OK)
969         xmlResetError(error);
970 }
971 
972 /**
973  * xmlCopyError:
974  * @from:  a source error
975  * @to:  a target error
976  *
977  * Save the original error to the new place.
978  *
979  * Returns 0 in case of success and -1 in case of error.
980  */
981 int
xmlCopyError(const xmlError * from,xmlErrorPtr to)982 xmlCopyError(const xmlError *from, xmlErrorPtr to) {
983     const char *fmt = NULL;
984 
985     if ((from == NULL) || (to == NULL))
986         return(-1);
987 
988     if (from->message != NULL)
989         fmt = "%s";
990 
991     return(xmlSetError(to, from->ctxt, from->node,
992                        from->domain, from->code, from->level,
993                        from->file, from->line,
994                        from->str1, from->str2, from->str3,
995                        from->int1, from->int2,
996                        fmt, from->message));
997 }
998 
999 /**
1000  * xmlErrString:
1001  * @code:  an xmlParserErrors code
1002  *
1003  * Returns an error message for a code.
1004  */
1005 const char *
xmlErrString(xmlParserErrors code)1006 xmlErrString(xmlParserErrors code) {
1007     const char *errmsg;
1008 
1009     switch (code) {
1010         case XML_ERR_INVALID_HEX_CHARREF:
1011             errmsg = "CharRef: invalid hexadecimal value";
1012             break;
1013         case XML_ERR_INVALID_DEC_CHARREF:
1014             errmsg = "CharRef: invalid decimal value";
1015             break;
1016         case XML_ERR_INVALID_CHARREF:
1017             errmsg = "CharRef: invalid value";
1018             break;
1019         case XML_ERR_INTERNAL_ERROR:
1020             errmsg = "internal error";
1021             break;
1022         case XML_ERR_PEREF_AT_EOF:
1023             errmsg = "PEReference at end of document";
1024             break;
1025         case XML_ERR_PEREF_IN_PROLOG:
1026             errmsg = "PEReference in prolog";
1027             break;
1028         case XML_ERR_PEREF_IN_EPILOG:
1029             errmsg = "PEReference in epilog";
1030             break;
1031         case XML_ERR_PEREF_NO_NAME:
1032             errmsg = "PEReference: no name";
1033             break;
1034         case XML_ERR_PEREF_SEMICOL_MISSING:
1035             errmsg = "PEReference: expecting ';'";
1036             break;
1037         case XML_ERR_ENTITY_LOOP:
1038             errmsg = "Detected an entity reference loop";
1039             break;
1040         case XML_ERR_ENTITY_NOT_STARTED:
1041             errmsg = "EntityValue: \" or ' expected";
1042             break;
1043         case XML_ERR_ENTITY_PE_INTERNAL:
1044             errmsg = "PEReferences forbidden in internal subset";
1045             break;
1046         case XML_ERR_ENTITY_NOT_FINISHED:
1047             errmsg = "EntityValue: \" or ' expected";
1048             break;
1049         case XML_ERR_ATTRIBUTE_NOT_STARTED:
1050             errmsg = "AttValue: \" or ' expected";
1051             break;
1052         case XML_ERR_LT_IN_ATTRIBUTE:
1053             errmsg = "Unescaped '<' not allowed in attributes values";
1054             break;
1055         case XML_ERR_LITERAL_NOT_STARTED:
1056             errmsg = "SystemLiteral \" or ' expected";
1057             break;
1058         case XML_ERR_LITERAL_NOT_FINISHED:
1059             errmsg = "Unfinished System or Public ID \" or ' expected";
1060             break;
1061         case XML_ERR_MISPLACED_CDATA_END:
1062             errmsg = "Sequence ']]>' not allowed in content";
1063             break;
1064         case XML_ERR_URI_REQUIRED:
1065             errmsg = "SYSTEM or PUBLIC, the URI is missing";
1066             break;
1067         case XML_ERR_PUBID_REQUIRED:
1068             errmsg = "PUBLIC, the Public Identifier is missing";
1069             break;
1070         case XML_ERR_HYPHEN_IN_COMMENT:
1071             errmsg = "Comment must not contain '--' (double-hyphen)";
1072             break;
1073         case XML_ERR_PI_NOT_STARTED:
1074             errmsg = "xmlParsePI : no target name";
1075             break;
1076         case XML_ERR_RESERVED_XML_NAME:
1077             errmsg = "Invalid PI name";
1078             break;
1079         case XML_ERR_NOTATION_NOT_STARTED:
1080             errmsg = "NOTATION: Name expected here";
1081             break;
1082         case XML_ERR_NOTATION_NOT_FINISHED:
1083             errmsg = "'>' required to close NOTATION declaration";
1084             break;
1085         case XML_ERR_VALUE_REQUIRED:
1086             errmsg = "Entity value required";
1087             break;
1088         case XML_ERR_URI_FRAGMENT:
1089             errmsg = "Fragment not allowed";
1090             break;
1091         case XML_ERR_ATTLIST_NOT_STARTED:
1092             errmsg = "'(' required to start ATTLIST enumeration";
1093             break;
1094         case XML_ERR_NMTOKEN_REQUIRED:
1095             errmsg = "NmToken expected in ATTLIST enumeration";
1096             break;
1097         case XML_ERR_ATTLIST_NOT_FINISHED:
1098             errmsg = "')' required to finish ATTLIST enumeration";
1099             break;
1100         case XML_ERR_MIXED_NOT_STARTED:
1101             errmsg = "MixedContentDecl : '|' or ')*' expected";
1102             break;
1103         case XML_ERR_PCDATA_REQUIRED:
1104             errmsg = "MixedContentDecl : '#PCDATA' expected";
1105             break;
1106         case XML_ERR_ELEMCONTENT_NOT_STARTED:
1107             errmsg = "ContentDecl : Name or '(' expected";
1108             break;
1109         case XML_ERR_ELEMCONTENT_NOT_FINISHED:
1110             errmsg = "ContentDecl : ',' '|' or ')' expected";
1111             break;
1112         case XML_ERR_PEREF_IN_INT_SUBSET:
1113             errmsg =
1114                 "PEReference: forbidden within markup decl in internal subset";
1115             break;
1116         case XML_ERR_GT_REQUIRED:
1117             errmsg = "expected '>'";
1118             break;
1119         case XML_ERR_CONDSEC_INVALID:
1120             errmsg = "XML conditional section '[' expected";
1121             break;
1122         case XML_ERR_INT_SUBSET_NOT_FINISHED:
1123             errmsg = "Content error in the internal subset";
1124             break;
1125         case XML_ERR_EXT_SUBSET_NOT_FINISHED:
1126             errmsg = "Content error in the external subset";
1127             break;
1128         case XML_ERR_CONDSEC_INVALID_KEYWORD:
1129             errmsg =
1130                 "conditional section INCLUDE or IGNORE keyword expected";
1131             break;
1132         case XML_ERR_CONDSEC_NOT_FINISHED:
1133             errmsg = "XML conditional section not closed";
1134             break;
1135         case XML_ERR_XMLDECL_NOT_STARTED:
1136             errmsg = "Text declaration '<?xml' required";
1137             break;
1138         case XML_ERR_XMLDECL_NOT_FINISHED:
1139             errmsg = "parsing XML declaration: '?>' expected";
1140             break;
1141         case XML_ERR_EXT_ENTITY_STANDALONE:
1142             errmsg = "external parsed entities cannot be standalone";
1143             break;
1144         case XML_ERR_ENTITYREF_SEMICOL_MISSING:
1145             errmsg = "EntityRef: expecting ';'";
1146             break;
1147         case XML_ERR_DOCTYPE_NOT_FINISHED:
1148             errmsg = "DOCTYPE improperly terminated";
1149             break;
1150         case XML_ERR_LTSLASH_REQUIRED:
1151             errmsg = "EndTag: '</' not found";
1152             break;
1153         case XML_ERR_EQUAL_REQUIRED:
1154             errmsg = "expected '='";
1155             break;
1156         case XML_ERR_STRING_NOT_CLOSED:
1157             errmsg = "String not closed expecting \" or '";
1158             break;
1159         case XML_ERR_STRING_NOT_STARTED:
1160             errmsg = "String not started expecting ' or \"";
1161             break;
1162         case XML_ERR_ENCODING_NAME:
1163             errmsg = "Invalid XML encoding name";
1164             break;
1165         case XML_ERR_STANDALONE_VALUE:
1166             errmsg = "standalone accepts only 'yes' or 'no'";
1167             break;
1168         case XML_ERR_DOCUMENT_EMPTY:
1169             errmsg = "Document is empty";
1170             break;
1171         case XML_ERR_DOCUMENT_END:
1172             errmsg = "Extra content at the end of the document";
1173             break;
1174         case XML_ERR_NOT_WELL_BALANCED:
1175             errmsg = "chunk is not well balanced";
1176             break;
1177         case XML_ERR_EXTRA_CONTENT:
1178             errmsg = "extra content at the end of well balanced chunk";
1179             break;
1180         case XML_ERR_VERSION_MISSING:
1181             errmsg = "Malformed declaration expecting version";
1182             break;
1183         case XML_ERR_NAME_TOO_LONG:
1184             errmsg = "Name too long";
1185             break;
1186         case XML_ERR_INVALID_ENCODING:
1187             errmsg = "Invalid bytes in character encoding";
1188             break;
1189         case XML_ERR_RESOURCE_LIMIT:
1190             errmsg = "Resource limit exceeded";
1191             break;
1192         case XML_ERR_ARGUMENT:
1193             errmsg = "Invalid argument";
1194             break;
1195         case XML_ERR_SYSTEM:
1196             errmsg = "Out of system resources";
1197             break;
1198         case XML_ERR_REDECL_PREDEF_ENTITY:
1199             errmsg = "Invalid redeclaration of predefined entity";
1200             break;
1201         case XML_ERR_UNSUPPORTED_ENCODING:
1202             errmsg = "Unsupported encoding";
1203             break;
1204         case XML_ERR_INVALID_CHAR:
1205             errmsg = "Invalid character";
1206             break;
1207 
1208         case XML_IO_UNKNOWN:
1209             errmsg = "Unknown IO error"; break;
1210         case XML_IO_EACCES:
1211             errmsg = "Permission denied"; break;
1212         case XML_IO_EAGAIN:
1213             errmsg = "Resource temporarily unavailable"; break;
1214         case XML_IO_EBADF:
1215             errmsg = "Bad file descriptor"; break;
1216         case XML_IO_EBADMSG:
1217             errmsg = "Bad message"; break;
1218         case XML_IO_EBUSY:
1219             errmsg = "Resource busy"; break;
1220         case XML_IO_ECANCELED:
1221             errmsg = "Operation canceled"; break;
1222         case XML_IO_ECHILD:
1223             errmsg = "No child processes"; break;
1224         case XML_IO_EDEADLK:
1225             errmsg = "Resource deadlock avoided"; break;
1226         case XML_IO_EDOM:
1227             errmsg = "Domain error"; break;
1228         case XML_IO_EEXIST:
1229             errmsg = "File exists"; break;
1230         case XML_IO_EFAULT:
1231             errmsg = "Bad address"; break;
1232         case XML_IO_EFBIG:
1233             errmsg = "File too large"; break;
1234         case XML_IO_EINPROGRESS:
1235             errmsg = "Operation in progress"; break;
1236         case XML_IO_EINTR:
1237             errmsg = "Interrupted function call"; break;
1238         case XML_IO_EINVAL:
1239             errmsg = "Invalid argument"; break;
1240         case XML_IO_EIO:
1241             errmsg = "Input/output error"; break;
1242         case XML_IO_EISDIR:
1243             errmsg = "Is a directory"; break;
1244         case XML_IO_EMFILE:
1245             errmsg = "Too many open files"; break;
1246         case XML_IO_EMLINK:
1247             errmsg = "Too many links"; break;
1248         case XML_IO_EMSGSIZE:
1249             errmsg = "Inappropriate message buffer length"; break;
1250         case XML_IO_ENAMETOOLONG:
1251             errmsg = "Filename too long"; break;
1252         case XML_IO_ENFILE:
1253             errmsg = "Too many open files in system"; break;
1254         case XML_IO_ENODEV:
1255             errmsg = "No such device"; break;
1256         case XML_IO_ENOENT:
1257             errmsg = "No such file or directory"; break;
1258         case XML_IO_ENOEXEC:
1259             errmsg = "Exec format error"; break;
1260         case XML_IO_ENOLCK:
1261             errmsg = "No locks available"; break;
1262         case XML_IO_ENOMEM:
1263             errmsg = "Not enough space"; break;
1264         case XML_IO_ENOSPC:
1265             errmsg = "No space left on device"; break;
1266         case XML_IO_ENOSYS:
1267             errmsg = "Function not implemented"; break;
1268         case XML_IO_ENOTDIR:
1269             errmsg = "Not a directory"; break;
1270         case XML_IO_ENOTEMPTY:
1271             errmsg = "Directory not empty"; break;
1272         case XML_IO_ENOTSUP:
1273             errmsg = "Not supported"; break;
1274         case XML_IO_ENOTTY:
1275             errmsg = "Inappropriate I/O control operation"; break;
1276         case XML_IO_ENXIO:
1277             errmsg = "No such device or address"; break;
1278         case XML_IO_EPERM:
1279             errmsg = "Operation not permitted"; break;
1280         case XML_IO_EPIPE:
1281             errmsg = "Broken pipe"; break;
1282         case XML_IO_ERANGE:
1283             errmsg = "Result too large"; break;
1284         case XML_IO_EROFS:
1285             errmsg = "Read-only file system"; break;
1286         case XML_IO_ESPIPE:
1287             errmsg = "Invalid seek"; break;
1288         case XML_IO_ESRCH:
1289             errmsg = "No such process"; break;
1290         case XML_IO_ETIMEDOUT:
1291             errmsg = "Operation timed out"; break;
1292         case XML_IO_EXDEV:
1293             errmsg = "Improper link"; break;
1294         case XML_IO_NETWORK_ATTEMPT:
1295             errmsg = "Attempt to load network entity"; break;
1296         case XML_IO_ENCODER:
1297             errmsg = "encoder error"; break;
1298         case XML_IO_FLUSH:
1299             errmsg = "flush error"; break;
1300         case XML_IO_WRITE:
1301             errmsg = "write error"; break;
1302         case XML_IO_NO_INPUT:
1303             errmsg = "no input"; break;
1304         case XML_IO_BUFFER_FULL:
1305             errmsg = "buffer full"; break;
1306         case XML_IO_LOAD_ERROR:
1307             errmsg = "loading error"; break;
1308         case XML_IO_ENOTSOCK:
1309             errmsg = "not a socket"; break;
1310         case XML_IO_EISCONN:
1311             errmsg = "already connected"; break;
1312         case XML_IO_ECONNREFUSED:
1313             errmsg = "connection refused"; break;
1314         case XML_IO_ENETUNREACH:
1315             errmsg = "unreachable network"; break;
1316         case XML_IO_EADDRINUSE:
1317             errmsg = "address in use"; break;
1318         case XML_IO_EALREADY:
1319             errmsg = "already in use"; break;
1320         case XML_IO_EAFNOSUPPORT:
1321             errmsg = "unknown address family"; break;
1322         case XML_IO_UNSUPPORTED_PROTOCOL:
1323             errmsg = "unsupported protocol"; break;
1324 
1325         default:
1326             errmsg = "Unregistered error message";
1327     }
1328 
1329     return(errmsg);
1330 }
1331 
1332 void
xmlVPrintErrorMessage(const char * fmt,va_list ap)1333 xmlVPrintErrorMessage(const char *fmt, va_list ap) {
1334     vfprintf(stderr, fmt, ap);
1335 }
1336 
1337 void
xmlPrintErrorMessage(const char * fmt,...)1338 xmlPrintErrorMessage(const char *fmt, ...) {
1339     va_list ap;
1340 
1341     va_start(ap, fmt);
1342     xmlVPrintErrorMessage(fmt, ap);
1343     va_end(ap);
1344 }
1345 
1346 void
xmlAbort(const char * fmt,...)1347 xmlAbort(const char *fmt, ...) {
1348     va_list ap;
1349 
1350     va_start(ap, fmt);
1351     xmlVPrintErrorMessage(fmt, ap);
1352     va_end(ap);
1353 
1354     abort();
1355 }
1356