Coverage Report

Created: 2023-06-07 06:05

/src/libxml2-2.10.3/error.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * error.c: module displaying/handling XML parser errors
3
 *
4
 * See Copyright for the status of this software.
5
 *
6
 * Daniel Veillard <daniel@veillard.com>
7
 */
8
9
#define IN_LIBXML
10
#include "libxml.h"
11
12
#include <string.h>
13
#include <stdarg.h>
14
#include <libxml/parser.h>
15
#include <libxml/xmlerror.h>
16
#include <libxml/xmlmemory.h>
17
#include <libxml/globals.h>
18
19
void XMLCDECL xmlGenericErrorDefaultFunc  (void *ctx ATTRIBUTE_UNUSED,
20
         const char *msg,
21
         ...) LIBXML_ATTR_FORMAT(2,3);
22
23
1.08M
#define XML_GET_VAR_STR(msg, str) {       \
24
1.08M
    int       size, prev_size = -1;       \
25
1.08M
    int       chars;            \
26
1.08M
    char      *larger;            \
27
1.08M
    va_list   ap;           \
28
1.08M
                \
29
1.08M
    str = (char *) xmlMalloc(150);        \
30
1.08M
    if (str != NULL) {           \
31
1.08M
                \
32
1.08M
    size = 150;             \
33
1.08M
                \
34
2.18M
    while (size < 64000) {         \
35
2.18M
  va_start(ap, msg);          \
36
2.18M
  chars = vsnprintf(str, size, msg, ap);      \
37
2.18M
  va_end(ap);           \
38
2.18M
  if ((chars > -1) && (chars < size)) {     \
39
2.17M
      if (prev_size == chars) {       \
40
1.08M
    break;            \
41
1.08M
      } else {           \
42
1.08M
    prev_size = chars;        \
43
1.08M
      }              \
44
2.17M
  }              \
45
2.18M
  if (chars > -1)           \
46
1.09M
      size += chars + 1;         \
47
1.09M
  else              \
48
1.09M
      size += 100;         \
49
1.09M
  if ((larger = (char *) xmlRealloc(str, size)) == NULL) {\
50
0
      break;            \
51
0
  }              \
52
1.09M
  str = larger;           \
53
1.09M
    }}               \
54
1.08M
}
55
56
/************************************************************************
57
 *                  *
58
 *      Handling of out of context errors   *
59
 *                  *
60
 ************************************************************************/
61
62
/**
63
 * xmlGenericErrorDefaultFunc:
64
 * @ctx:  an error context
65
 * @msg:  the message to display/transmit
66
 * @...:  extra parameters for the message display
67
 *
68
 * Default handler for out of context error messages.
69
 */
70
void XMLCDECL
71
0
xmlGenericErrorDefaultFunc(void *ctx ATTRIBUTE_UNUSED, const char *msg, ...) {
72
0
    va_list args;
73
74
0
    if (xmlGenericErrorContext == NULL)
75
0
  xmlGenericErrorContext = (void *) stderr;
76
77
0
    va_start(args, msg);
78
0
    vfprintf((FILE *)xmlGenericErrorContext, msg, args);
79
0
    va_end(args);
80
0
}
81
82
/**
83
 * initGenericErrorDefaultFunc:
84
 * @handler:  the handler
85
 *
86
 * Set or reset (if NULL) the default handler for generic errors
87
 * to the builtin error function.
88
 */
89
void
90
initGenericErrorDefaultFunc(xmlGenericErrorFunc * handler)
91
1
{
92
1
    if (handler == NULL)
93
1
        xmlGenericError = xmlGenericErrorDefaultFunc;
94
0
    else
95
0
        xmlGenericError = (*handler);
96
1
}
97
98
/**
99
 * xmlSetGenericErrorFunc:
100
 * @ctx:  the new error handling context
101
 * @handler:  the new handler function
102
 *
103
 * Function to reset the handler and the error context for out of
104
 * context error messages.
105
 * This simply means that @handler will be called for subsequent
106
 * error messages while not parsing nor validating. And @ctx will
107
 * be passed as first argument to @handler
108
 * One can simply force messages to be emitted to another FILE * than
109
 * stderr by setting @ctx to this file handle and @handler to NULL.
110
 * For multi-threaded applications, this must be set separately for each thread.
111
 */
112
void
113
36.6k
xmlSetGenericErrorFunc(void *ctx, xmlGenericErrorFunc handler) {
114
36.6k
    xmlGenericErrorContext = ctx;
115
36.6k
    if (handler != NULL)
116
36.6k
  xmlGenericError = handler;
117
0
    else
118
0
  xmlGenericError = xmlGenericErrorDefaultFunc;
119
36.6k
}
120
121
/**
122
 * xmlSetStructuredErrorFunc:
123
 * @ctx:  the new error handling context
124
 * @handler:  the new handler function
125
 *
126
 * Function to reset the handler and the error context for out of
127
 * context structured error messages.
128
 * This simply means that @handler will be called for subsequent
129
 * error messages while not parsing nor validating. And @ctx will
130
 * be passed as first argument to @handler
131
 * For multi-threaded applications, this must be set separately for each thread.
132
 */
133
void
134
36.6k
xmlSetStructuredErrorFunc(void *ctx, xmlStructuredErrorFunc handler) {
135
36.6k
    xmlStructuredErrorContext = ctx;
136
36.6k
    xmlStructuredError = handler;
137
36.6k
}
138
139
/************************************************************************
140
 *                  *
141
 *      Handling of parsing errors      *
142
 *                  *
143
 ************************************************************************/
144
145
/**
146
 * xmlParserPrintFileInfo:
147
 * @input:  an xmlParserInputPtr input
148
 *
149
 * Displays the associated file and line information for the current input
150
 */
151
152
void
153
0
xmlParserPrintFileInfo(xmlParserInputPtr input) {
154
0
    if (input != NULL) {
155
0
  if (input->filename)
156
0
      xmlGenericError(xmlGenericErrorContext,
157
0
        "%s:%d: ", input->filename,
158
0
        input->line);
159
0
  else
160
0
      xmlGenericError(xmlGenericErrorContext,
161
0
        "Entity: line %d: ", input->line);
162
0
    }
163
0
}
164
165
/**
166
 * xmlParserPrintFileContext:
167
 * @input:  an xmlParserInputPtr input
168
 *
169
 * Displays current context within the input content for error tracking
170
 */
171
172
static void
173
xmlParserPrintFileContextInternal(xmlParserInputPtr input ,
174
0
    xmlGenericErrorFunc channel, void *data ) {
175
0
    const xmlChar *cur, *base;
176
0
    unsigned int n, col;  /* GCC warns if signed, because compared with sizeof() */
177
0
    xmlChar  content[81]; /* space for 80 chars + line terminator */
178
0
    xmlChar *ctnt;
179
180
0
    if ((input == NULL) || (input->cur == NULL))
181
0
        return;
182
183
0
    cur = input->cur;
184
0
    base = input->base;
185
    /* skip backwards over any end-of-lines */
186
0
    while ((cur > base) && ((*(cur) == '\n') || (*(cur) == '\r'))) {
187
0
  cur--;
188
0
    }
189
0
    n = 0;
190
    /* search backwards for beginning-of-line (to max buff size) */
191
0
    while ((n++ < (sizeof(content)-1)) && (cur > base) &&
192
0
     (*(cur) != '\n') && (*(cur) != '\r'))
193
0
        cur--;
194
0
    if ((*(cur) == '\n') || (*(cur) == '\r')) cur++;
195
    /* calculate the error position in terms of the current position */
196
0
    col = input->cur - cur;
197
    /* search forward for end-of-line (to max buff size) */
198
0
    n = 0;
199
0
    ctnt = content;
200
    /* copy selected text to our buffer */
201
0
    while ((*cur != 0) && (*(cur) != '\n') &&
202
0
     (*(cur) != '\r') && (n < sizeof(content)-1)) {
203
0
    *ctnt++ = *cur++;
204
0
  n++;
205
0
    }
206
0
    *ctnt = 0;
207
    /* print out the selected text */
208
0
    channel(data ,"%s\n", content);
209
    /* create blank line with problem pointer */
210
0
    n = 0;
211
0
    ctnt = content;
212
    /* (leave buffer space for pointer + line terminator) */
213
0
    while ((n<col) && (n++ < sizeof(content)-2) && (*ctnt != 0)) {
214
0
  if (*(ctnt) != '\t')
215
0
      *(ctnt) = ' ';
216
0
  ctnt++;
217
0
    }
218
0
    *ctnt++ = '^';
219
0
    *ctnt = 0;
220
0
    channel(data ,"%s\n", content);
221
0
}
222
223
/**
224
 * xmlParserPrintFileContext:
225
 * @input:  an xmlParserInputPtr input
226
 *
227
 * Displays current context within the input content for error tracking
228
 */
229
void
230
0
xmlParserPrintFileContext(xmlParserInputPtr input) {
231
0
   xmlParserPrintFileContextInternal(input, xmlGenericError,
232
0
                                     xmlGenericErrorContext);
233
0
}
234
235
/**
236
 * xmlReportError:
237
 * @err: the error
238
 * @ctx: the parser context or NULL
239
 * @str: the formatted error message
240
 *
241
 * Report an error with its context, replace the 4 old error/warning
242
 * routines.
243
 */
244
static void
245
xmlReportError(xmlErrorPtr err, xmlParserCtxtPtr ctxt, const char *str,
246
               xmlGenericErrorFunc channel, void *data)
247
0
{
248
0
    char *file = NULL;
249
0
    int line = 0;
250
0
    int code = -1;
251
0
    int domain;
252
0
    const xmlChar *name = NULL;
253
0
    xmlNodePtr node;
254
0
    xmlErrorLevel level;
255
0
    xmlParserInputPtr input = NULL;
256
0
    xmlParserInputPtr cur = NULL;
257
258
0
    if (err == NULL)
259
0
        return;
260
261
0
    if (channel == NULL) {
262
0
  channel = xmlGenericError;
263
0
  data = xmlGenericErrorContext;
264
0
    }
265
0
    file = err->file;
266
0
    line = err->line;
267
0
    code = err->code;
268
0
    domain = err->domain;
269
0
    level = err->level;
270
0
    node = err->node;
271
272
0
    if (code == XML_ERR_OK)
273
0
        return;
274
275
0
    if ((node != NULL) && (node->type == XML_ELEMENT_NODE))
276
0
        name = node->name;
277
278
    /*
279
     * Maintain the compatibility with the legacy error handling
280
     */
281
0
    if (ctxt != NULL) {
282
0
        input = ctxt->input;
283
0
        if ((input != NULL) && (input->filename == NULL) &&
284
0
            (ctxt->inputNr > 1)) {
285
0
            cur = input;
286
0
            input = ctxt->inputTab[ctxt->inputNr - 2];
287
0
        }
288
0
        if (input != NULL) {
289
0
            if (input->filename)
290
0
                channel(data, "%s:%d: ", input->filename, input->line);
291
0
            else if ((line != 0) && (domain == XML_FROM_PARSER))
292
0
                channel(data, "Entity: line %d: ", input->line);
293
0
        }
294
0
    } else {
295
0
        if (file != NULL)
296
0
            channel(data, "%s:%d: ", file, line);
297
0
        else if ((line != 0) &&
298
0
           ((domain == XML_FROM_PARSER) || (domain == XML_FROM_SCHEMASV)||
299
0
      (domain == XML_FROM_SCHEMASP)||(domain == XML_FROM_DTD) ||
300
0
      (domain == XML_FROM_RELAXNGP)||(domain == XML_FROM_RELAXNGV)))
301
0
            channel(data, "Entity: line %d: ", line);
302
0
    }
303
0
    if (name != NULL) {
304
0
        channel(data, "element %s: ", name);
305
0
    }
306
0
    switch (domain) {
307
0
        case XML_FROM_PARSER:
308
0
            channel(data, "parser ");
309
0
            break;
310
0
        case XML_FROM_NAMESPACE:
311
0
            channel(data, "namespace ");
312
0
            break;
313
0
        case XML_FROM_DTD:
314
0
        case XML_FROM_VALID:
315
0
            channel(data, "validity ");
316
0
            break;
317
0
        case XML_FROM_HTML:
318
0
            channel(data, "HTML parser ");
319
0
            break;
320
0
        case XML_FROM_MEMORY:
321
0
            channel(data, "memory ");
322
0
            break;
323
0
        case XML_FROM_OUTPUT:
324
0
            channel(data, "output ");
325
0
            break;
326
0
        case XML_FROM_IO:
327
0
            channel(data, "I/O ");
328
0
            break;
329
0
        case XML_FROM_XINCLUDE:
330
0
            channel(data, "XInclude ");
331
0
            break;
332
0
        case XML_FROM_XPATH:
333
0
            channel(data, "XPath ");
334
0
            break;
335
0
        case XML_FROM_XPOINTER:
336
0
            channel(data, "parser ");
337
0
            break;
338
0
        case XML_FROM_REGEXP:
339
0
            channel(data, "regexp ");
340
0
            break;
341
0
        case XML_FROM_MODULE:
342
0
            channel(data, "module ");
343
0
            break;
344
0
        case XML_FROM_SCHEMASV:
345
0
            channel(data, "Schemas validity ");
346
0
            break;
347
0
        case XML_FROM_SCHEMASP:
348
0
            channel(data, "Schemas parser ");
349
0
            break;
350
0
        case XML_FROM_RELAXNGP:
351
0
            channel(data, "Relax-NG parser ");
352
0
            break;
353
0
        case XML_FROM_RELAXNGV:
354
0
            channel(data, "Relax-NG validity ");
355
0
            break;
356
0
        case XML_FROM_CATALOG:
357
0
            channel(data, "Catalog ");
358
0
            break;
359
0
        case XML_FROM_C14N:
360
0
            channel(data, "C14N ");
361
0
            break;
362
0
        case XML_FROM_XSLT:
363
0
            channel(data, "XSLT ");
364
0
            break;
365
0
        case XML_FROM_I18N:
366
0
            channel(data, "encoding ");
367
0
            break;
368
0
        case XML_FROM_SCHEMATRONV:
369
0
            channel(data, "schematron ");
370
0
            break;
371
0
        case XML_FROM_BUFFER:
372
0
            channel(data, "internal buffer ");
373
0
            break;
374
0
        case XML_FROM_URI:
375
0
            channel(data, "URI ");
376
0
            break;
377
0
        default:
378
0
            break;
379
0
    }
380
0
    switch (level) {
381
0
        case XML_ERR_NONE:
382
0
            channel(data, ": ");
383
0
            break;
384
0
        case XML_ERR_WARNING:
385
0
            channel(data, "warning : ");
386
0
            break;
387
0
        case XML_ERR_ERROR:
388
0
            channel(data, "error : ");
389
0
            break;
390
0
        case XML_ERR_FATAL:
391
0
            channel(data, "error : ");
392
0
            break;
393
0
    }
394
0
    if (str != NULL) {
395
0
        int len;
396
0
  len = xmlStrlen((const xmlChar *)str);
397
0
  if ((len > 0) && (str[len - 1] != '\n'))
398
0
      channel(data, "%s\n", str);
399
0
  else
400
0
      channel(data, "%s", str);
401
0
    } else {
402
0
        channel(data, "%s\n", "out of memory error");
403
0
    }
404
405
0
    if (ctxt != NULL) {
406
0
        xmlParserPrintFileContextInternal(input, channel, data);
407
0
        if (cur != NULL) {
408
0
            if (cur->filename)
409
0
                channel(data, "%s:%d: \n", cur->filename, cur->line);
410
0
            else if ((line != 0) && (domain == XML_FROM_PARSER))
411
0
                channel(data, "Entity: line %d: \n", cur->line);
412
0
            xmlParserPrintFileContextInternal(cur, channel, data);
413
0
        }
414
0
    }
415
0
    if ((domain == XML_FROM_XPATH) && (err->str1 != NULL) &&
416
0
        (err->int1 < 100) &&
417
0
  (err->int1 < xmlStrlen((const xmlChar *)err->str1))) {
418
0
  xmlChar buf[150];
419
0
  int i;
420
421
0
  channel(data, "%s\n", err->str1);
422
0
  for (i=0;i < err->int1;i++)
423
0
       buf[i] = ' ';
424
0
  buf[i++] = '^';
425
0
  buf[i] = 0;
426
0
  channel(data, "%s\n", buf);
427
0
    }
428
0
}
429
430
/**
431
 * __xmlRaiseError:
432
 * @schannel: the structured callback channel
433
 * @channel: the old callback channel
434
 * @data: the callback data
435
 * @ctx: the parser context or NULL
436
 * @ctx: the parser context or NULL
437
 * @domain: the domain for the error
438
 * @code: the code for the error
439
 * @level: the xmlErrorLevel for the error
440
 * @file: the file source of the error (or NULL)
441
 * @line: the line of the error or 0 if N/A
442
 * @str1: extra string info
443
 * @str2: extra string info
444
 * @str3: extra string info
445
 * @int1: extra int info
446
 * @col: column number of the error or 0 if N/A
447
 * @msg:  the message to display/transmit
448
 * @...:  extra parameters for the message display
449
 *
450
 * Update the appropriate global or contextual error structure,
451
 * then forward the error message down the parser or generic
452
 * error callback handler
453
 */
454
void XMLCDECL
455
__xmlRaiseError(xmlStructuredErrorFunc schannel,
456
              xmlGenericErrorFunc channel, void *data, void *ctx,
457
              void *nod, int domain, int code, xmlErrorLevel level,
458
              const char *file, int line, const char *str1,
459
              const char *str2, const char *str3, int int1, int col,
460
        const char *msg, ...)
461
1.08M
{
462
1.08M
    xmlParserCtxtPtr ctxt = NULL;
463
1.08M
    xmlNodePtr node = (xmlNodePtr) nod;
464
1.08M
    char *str = NULL;
465
1.08M
    xmlParserInputPtr input = NULL;
466
1.08M
    xmlErrorPtr to = &xmlLastError;
467
1.08M
    xmlNodePtr baseptr = NULL;
468
469
1.08M
    if (code == XML_ERR_OK)
470
0
        return;
471
1.08M
    if ((xmlGetWarningsDefaultValue == 0) && (level == XML_ERR_WARNING))
472
0
        return;
473
1.08M
    if ((domain == XML_FROM_PARSER) || (domain == XML_FROM_HTML) ||
474
1.08M
        (domain == XML_FROM_DTD) || (domain == XML_FROM_NAMESPACE) ||
475
1.08M
  (domain == XML_FROM_IO) || (domain == XML_FROM_VALID)) {
476
1.08M
  ctxt = (xmlParserCtxtPtr) ctx;
477
1.08M
  if ((schannel == NULL) && (ctxt != NULL) && (ctxt->sax != NULL) &&
478
1.08M
      (ctxt->sax->initialized == XML_SAX2_MAGIC) &&
479
1.08M
      (ctxt->sax->serror != NULL)) {
480
0
      schannel = ctxt->sax->serror;
481
0
      data = ctxt->userData;
482
0
  }
483
1.08M
    }
484
    /*
485
     * Check if structured error handler set
486
     */
487
1.08M
    if (schannel == NULL) {
488
1.08M
  schannel = xmlStructuredError;
489
  /*
490
   * if user has defined handler, change data ptr to user's choice
491
   */
492
1.08M
  if (schannel != NULL)
493
1.08M
      data = xmlStructuredErrorContext;
494
1.08M
    }
495
    /*
496
     * Formatting the message
497
     */
498
1.08M
    if (msg == NULL) {
499
0
        str = (char *) xmlStrdup(BAD_CAST "No error message provided");
500
1.08M
    } else {
501
1.08M
        XML_GET_VAR_STR(msg, str);
502
1.08M
    }
503
504
    /*
505
     * specific processing if a parser context is provided
506
     */
507
1.08M
    if (ctxt != NULL) {
508
1.08M
        if (file == NULL) {
509
1.08M
            input = ctxt->input;
510
1.08M
            if ((input != NULL) && (input->filename == NULL) &&
511
1.08M
                (ctxt->inputNr > 1)) {
512
0
                input = ctxt->inputTab[ctxt->inputNr - 2];
513
0
            }
514
1.08M
            if (input != NULL) {
515
1.08M
                file = input->filename;
516
1.08M
                line = input->line;
517
1.08M
                col = input->col;
518
1.08M
            }
519
1.08M
        }
520
1.08M
        to = &ctxt->lastError;
521
1.08M
    } else if ((node != NULL) && (file == NULL)) {
522
0
  int i;
523
524
0
  if ((node->doc != NULL) && (node->doc->URL != NULL)) {
525
0
      baseptr = node;
526
/*      file = (const char *) node->doc->URL; */
527
0
  }
528
0
  for (i = 0;
529
0
       ((i < 10) && (node != NULL) && (node->type != XML_ELEMENT_NODE));
530
0
       i++)
531
0
       node = node->parent;
532
0
        if ((baseptr == NULL) && (node != NULL) &&
533
0
      (node->doc != NULL) && (node->doc->URL != NULL))
534
0
      baseptr = node;
535
536
0
  if ((node != NULL) && (node->type == XML_ELEMENT_NODE))
537
0
      line = node->line;
538
0
  if ((line == 0) || (line == 65535))
539
0
      line = xmlGetLineNo(node);
540
0
    }
541
542
    /*
543
     * Save the information about the error
544
     */
545
1.08M
    xmlResetError(to);
546
1.08M
    to->domain = domain;
547
1.08M
    to->code = code;
548
1.08M
    to->message = str;
549
1.08M
    to->level = level;
550
1.08M
    if (file != NULL)
551
0
        to->file = (char *) xmlStrdup((const xmlChar *) file);
552
1.08M
    else if (baseptr != NULL) {
553
0
#ifdef LIBXML_XINCLUDE_ENABLED
554
  /*
555
   * We check if the error is within an XInclude section and,
556
   * if so, attempt to print out the href of the XInclude instead
557
   * of the usual "base" (doc->URL) for the node (bug 152623).
558
   */
559
0
        xmlNodePtr prev = baseptr;
560
0
        char *href = NULL;
561
0
  int inclcount = 0;
562
0
  while (prev != NULL) {
563
0
      if (prev->prev == NULL)
564
0
          prev = prev->parent;
565
0
      else {
566
0
          prev = prev->prev;
567
0
    if (prev->type == XML_XINCLUDE_START) {
568
0
        if (inclcount > 0) {
569
0
                        --inclcount;
570
0
                    } else {
571
0
                        href = (char *) xmlGetProp(prev, BAD_CAST "href");
572
0
                        if (href != NULL)
573
0
                break;
574
0
                    }
575
0
    } else if (prev->type == XML_XINCLUDE_END)
576
0
        inclcount++;
577
0
      }
578
0
  }
579
0
        if (href != NULL)
580
0
            to->file = href;
581
0
  else
582
0
#endif
583
0
      to->file = (char *) xmlStrdup(baseptr->doc->URL);
584
0
  if ((to->file == NULL) && (node != NULL) && (node->doc != NULL)) {
585
0
      to->file = (char *) xmlStrdup(node->doc->URL);
586
0
  }
587
0
    }
588
1.08M
    to->line = line;
589
1.08M
    if (str1 != NULL)
590
296k
        to->str1 = (char *) xmlStrdup((const xmlChar *) str1);
591
1.08M
    if (str2 != NULL)
592
29.1k
        to->str2 = (char *) xmlStrdup((const xmlChar *) str2);
593
1.08M
    if (str3 != NULL)
594
10.7k
        to->str3 = (char *) xmlStrdup((const xmlChar *) str3);
595
1.08M
    to->int1 = int1;
596
1.08M
    to->int2 = col;
597
1.08M
    to->node = node;
598
1.08M
    to->ctxt = ctx;
599
600
1.08M
    if (to != &xmlLastError)
601
1.08M
        xmlCopyError(to,&xmlLastError);
602
603
1.08M
    if (schannel != NULL) {
604
1.08M
  schannel(data, to);
605
1.08M
  return;
606
1.08M
    }
607
608
    /*
609
     * Find the callback channel if channel param is NULL
610
     */
611
0
    if ((ctxt != NULL) && (channel == NULL) &&
612
0
        (xmlStructuredError == NULL) && (ctxt->sax != NULL)) {
613
0
        if (level == XML_ERR_WARNING)
614
0
      channel = ctxt->sax->warning;
615
0
        else
616
0
      channel = ctxt->sax->error;
617
0
  data = ctxt->userData;
618
0
    } else if (channel == NULL) {
619
0
  channel = xmlGenericError;
620
0
  if (ctxt != NULL) {
621
0
      data = ctxt;
622
0
  } else {
623
0
      data = xmlGenericErrorContext;
624
0
  }
625
0
    }
626
0
    if (channel == NULL)
627
0
        return;
628
629
0
    if ((channel == xmlParserError) ||
630
0
        (channel == xmlParserWarning) ||
631
0
  (channel == xmlParserValidityError) ||
632
0
  (channel == xmlParserValidityWarning))
633
0
  xmlReportError(to, ctxt, str, NULL, NULL);
634
0
    else if (((void(*)(void)) channel == (void(*)(void)) fprintf) ||
635
0
             (channel == xmlGenericErrorDefaultFunc))
636
0
  xmlReportError(to, ctxt, str, channel, data);
637
0
    else
638
0
  channel(data, "%s", str);
639
0
}
640
641
/**
642
 * __xmlSimpleError:
643
 * @domain: where the error comes from
644
 * @code: the error code
645
 * @node: the context node
646
 * @extra:  extra information
647
 *
648
 * Handle an out of memory condition
649
 */
650
void
651
__xmlSimpleError(int domain, int code, xmlNodePtr node,
652
                 const char *msg, const char *extra)
653
293
{
654
655
293
    if (code == XML_ERR_NO_MEMORY) {
656
0
  if (extra)
657
0
      __xmlRaiseError(NULL, NULL, NULL, NULL, node, domain,
658
0
          XML_ERR_NO_MEMORY, XML_ERR_FATAL, NULL, 0, extra,
659
0
          NULL, NULL, 0, 0,
660
0
          "Memory allocation failed : %s\n", extra);
661
0
  else
662
0
      __xmlRaiseError(NULL, NULL, NULL, NULL, node, domain,
663
0
          XML_ERR_NO_MEMORY, XML_ERR_FATAL, NULL, 0, NULL,
664
0
          NULL, NULL, 0, 0, "Memory allocation failed\n");
665
293
    } else {
666
293
  __xmlRaiseError(NULL, NULL, NULL, NULL, node, domain,
667
293
      code, XML_ERR_ERROR, NULL, 0, extra,
668
293
      NULL, NULL, 0, 0, msg, extra);
669
293
    }
670
293
}
671
/**
672
 * xmlParserError:
673
 * @ctx:  an XML parser context
674
 * @msg:  the message to display/transmit
675
 * @...:  extra parameters for the message display
676
 *
677
 * Display and format an error messages, gives file, line, position and
678
 * extra parameters.
679
 */
680
void XMLCDECL
681
xmlParserError(void *ctx, const char *msg, ...)
682
0
{
683
0
    xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
684
0
    xmlParserInputPtr input = NULL;
685
0
    xmlParserInputPtr cur = NULL;
686
0
    char * str;
687
688
0
    if (ctxt != NULL) {
689
0
  input = ctxt->input;
690
0
  if ((input != NULL) && (input->filename == NULL) &&
691
0
      (ctxt->inputNr > 1)) {
692
0
      cur = input;
693
0
      input = ctxt->inputTab[ctxt->inputNr - 2];
694
0
  }
695
0
  xmlParserPrintFileInfo(input);
696
0
    }
697
698
0
    xmlGenericError(xmlGenericErrorContext, "error: ");
699
0
    XML_GET_VAR_STR(msg, str);
700
0
    xmlGenericError(xmlGenericErrorContext, "%s", str);
701
0
    if (str != NULL)
702
0
  xmlFree(str);
703
704
0
    if (ctxt != NULL) {
705
0
  xmlParserPrintFileContext(input);
706
0
  if (cur != NULL) {
707
0
      xmlParserPrintFileInfo(cur);
708
0
      xmlGenericError(xmlGenericErrorContext, "\n");
709
0
      xmlParserPrintFileContext(cur);
710
0
  }
711
0
    }
712
0
}
713
714
/**
715
 * xmlParserWarning:
716
 * @ctx:  an XML parser context
717
 * @msg:  the message to display/transmit
718
 * @...:  extra parameters for the message display
719
 *
720
 * Display and format a warning messages, gives file, line, position and
721
 * extra parameters.
722
 */
723
void XMLCDECL
724
xmlParserWarning(void *ctx, const char *msg, ...)
725
0
{
726
0
    xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
727
0
    xmlParserInputPtr input = NULL;
728
0
    xmlParserInputPtr cur = NULL;
729
0
    char * str;
730
731
0
    if (ctxt != NULL) {
732
0
  input = ctxt->input;
733
0
  if ((input != NULL) && (input->filename == NULL) &&
734
0
      (ctxt->inputNr > 1)) {
735
0
      cur = input;
736
0
      input = ctxt->inputTab[ctxt->inputNr - 2];
737
0
  }
738
0
  xmlParserPrintFileInfo(input);
739
0
    }
740
741
0
    xmlGenericError(xmlGenericErrorContext, "warning: ");
742
0
    XML_GET_VAR_STR(msg, str);
743
0
    xmlGenericError(xmlGenericErrorContext, "%s", str);
744
0
    if (str != NULL)
745
0
  xmlFree(str);
746
747
0
    if (ctxt != NULL) {
748
0
  xmlParserPrintFileContext(input);
749
0
  if (cur != NULL) {
750
0
      xmlParserPrintFileInfo(cur);
751
0
      xmlGenericError(xmlGenericErrorContext, "\n");
752
0
      xmlParserPrintFileContext(cur);
753
0
  }
754
0
    }
755
0
}
756
757
/************************************************************************
758
 *                  *
759
 *      Handling of validation errors     *
760
 *                  *
761
 ************************************************************************/
762
763
/**
764
 * xmlParserValidityError:
765
 * @ctx:  an XML parser context
766
 * @msg:  the message to display/transmit
767
 * @...:  extra parameters for the message display
768
 *
769
 * Display and format an validity error messages, gives file,
770
 * line, position and extra parameters.
771
 */
772
void XMLCDECL
773
xmlParserValidityError(void *ctx, const char *msg, ...)
774
0
{
775
0
    xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
776
0
    xmlParserInputPtr input = NULL;
777
0
    char * str;
778
0
    int len = xmlStrlen((const xmlChar *) msg);
779
0
    static int had_info = 0;
780
781
0
    if ((len > 1) && (msg[len - 2] != ':')) {
782
0
  if (ctxt != NULL) {
783
0
      input = ctxt->input;
784
0
      if ((input->filename == NULL) && (ctxt->inputNr > 1))
785
0
    input = ctxt->inputTab[ctxt->inputNr - 2];
786
787
0
      if (had_info == 0) {
788
0
    xmlParserPrintFileInfo(input);
789
0
      }
790
0
  }
791
0
  xmlGenericError(xmlGenericErrorContext, "validity error: ");
792
0
  had_info = 0;
793
0
    } else {
794
0
  had_info = 1;
795
0
    }
796
797
0
    XML_GET_VAR_STR(msg, str);
798
0
    xmlGenericError(xmlGenericErrorContext, "%s", str);
799
0
    if (str != NULL)
800
0
  xmlFree(str);
801
802
0
    if ((ctxt != NULL) && (input != NULL)) {
803
0
  xmlParserPrintFileContext(input);
804
0
    }
805
0
}
806
807
/**
808
 * xmlParserValidityWarning:
809
 * @ctx:  an XML parser context
810
 * @msg:  the message to display/transmit
811
 * @...:  extra parameters for the message display
812
 *
813
 * Display and format a validity warning messages, gives file, line,
814
 * position and extra parameters.
815
 */
816
void XMLCDECL
817
xmlParserValidityWarning(void *ctx, const char *msg, ...)
818
0
{
819
0
    xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
820
0
    xmlParserInputPtr input = NULL;
821
0
    char * str;
822
0
    int len = xmlStrlen((const xmlChar *) msg);
823
824
0
    if ((ctxt != NULL) && (len != 0) && (msg[len - 1] != ':')) {
825
0
  input = ctxt->input;
826
0
  if ((input->filename == NULL) && (ctxt->inputNr > 1))
827
0
      input = ctxt->inputTab[ctxt->inputNr - 2];
828
829
0
  xmlParserPrintFileInfo(input);
830
0
    }
831
832
0
    xmlGenericError(xmlGenericErrorContext, "validity warning: ");
833
0
    XML_GET_VAR_STR(msg, str);
834
0
    xmlGenericError(xmlGenericErrorContext, "%s", str);
835
0
    if (str != NULL)
836
0
  xmlFree(str);
837
838
0
    if (ctxt != NULL) {
839
0
  xmlParserPrintFileContext(input);
840
0
    }
841
0
}
842
843
844
/************************************************************************
845
 *                  *
846
 *      Extended Error Handling       *
847
 *                  *
848
 ************************************************************************/
849
850
/**
851
 * xmlGetLastError:
852
 *
853
 * Get the last global error registered. This is per thread if compiled
854
 * with thread support.
855
 *
856
 * Returns NULL if no error occurred or a pointer to the error
857
 */
858
xmlErrorPtr
859
xmlGetLastError(void)
860
0
{
861
0
    if (xmlLastError.code == XML_ERR_OK)
862
0
        return (NULL);
863
0
    return (&xmlLastError);
864
0
}
865
866
/**
867
 * xmlResetError:
868
 * @err: pointer to the error.
869
 *
870
 * Cleanup the error.
871
 */
872
void
873
xmlResetError(xmlErrorPtr err)
874
1.08M
{
875
1.08M
    if (err == NULL)
876
0
        return;
877
1.08M
    if (err->code == XML_ERR_OK)
878
17.4k
        return;
879
1.07M
    if (err->message != NULL)
880
1.07M
        xmlFree(err->message);
881
1.07M
    if (err->file != NULL)
882
0
        xmlFree(err->file);
883
1.07M
    if (err->str1 != NULL)
884
286k
        xmlFree(err->str1);
885
1.07M
    if (err->str2 != NULL)
886
29.0k
        xmlFree(err->str2);
887
1.07M
    if (err->str3 != NULL)
888
10.7k
        xmlFree(err->str3);
889
1.07M
    memset(err, 0, sizeof(xmlError));
890
1.07M
    err->code = XML_ERR_OK;
891
1.07M
}
892
893
/**
894
 * xmlResetLastError:
895
 *
896
 * Cleanup the last global error registered. For parsing error
897
 * this does not change the well-formedness result.
898
 */
899
void
900
xmlResetLastError(void)
901
0
{
902
0
    if (xmlLastError.code == XML_ERR_OK)
903
0
        return;
904
0
    xmlResetError(&xmlLastError);
905
0
}
906
907
/**
908
 * xmlCtxtGetLastError:
909
 * @ctx:  an XML parser context
910
 *
911
 * Get the last parsing error registered.
912
 *
913
 * Returns NULL if no error occurred or a pointer to the error
914
 */
915
xmlErrorPtr
916
xmlCtxtGetLastError(void *ctx)
917
0
{
918
0
    xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
919
920
0
    if (ctxt == NULL)
921
0
        return (NULL);
922
0
    if (ctxt->lastError.code == XML_ERR_OK)
923
0
        return (NULL);
924
0
    return (&ctxt->lastError);
925
0
}
926
927
/**
928
 * xmlCtxtResetLastError:
929
 * @ctx:  an XML parser context
930
 *
931
 * Cleanup the last global error registered. For parsing error
932
 * this does not change the well-formedness result.
933
 */
934
void
935
xmlCtxtResetLastError(void *ctx)
936
0
{
937
0
    xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
938
939
0
    if (ctxt == NULL)
940
0
        return;
941
0
    ctxt->errNo = XML_ERR_OK;
942
0
    if (ctxt->lastError.code == XML_ERR_OK)
943
0
        return;
944
0
    xmlResetError(&ctxt->lastError);
945
0
}
946
947
/**
948
 * xmlCopyError:
949
 * @from:  a source error
950
 * @to:  a target error
951
 *
952
 * Save the original error to the new place.
953
 *
954
 * Returns 0 in case of success and -1 in case of error.
955
 */
956
int
957
1.08M
xmlCopyError(xmlErrorPtr from, xmlErrorPtr to) {
958
1.08M
    char *message, *file, *str1, *str2, *str3;
959
960
1.08M
    if ((from == NULL) || (to == NULL))
961
0
        return(-1);
962
963
1.08M
    message = (char *) xmlStrdup((xmlChar *) from->message);
964
1.08M
    file = (char *) xmlStrdup ((xmlChar *) from->file);
965
1.08M
    str1 = (char *) xmlStrdup ((xmlChar *) from->str1);
966
1.08M
    str2 = (char *) xmlStrdup ((xmlChar *) from->str2);
967
1.08M
    str3 = (char *) xmlStrdup ((xmlChar *) from->str3);
968
969
1.08M
    if (to->message != NULL)
970
1.08M
        xmlFree(to->message);
971
1.08M
    if (to->file != NULL)
972
0
        xmlFree(to->file);
973
1.08M
    if (to->str1 != NULL)
974
295k
        xmlFree(to->str1);
975
1.08M
    if (to->str2 != NULL)
976
29.1k
        xmlFree(to->str2);
977
1.08M
    if (to->str3 != NULL)
978
10.7k
        xmlFree(to->str3);
979
1.08M
    to->domain = from->domain;
980
1.08M
    to->code = from->code;
981
1.08M
    to->level = from->level;
982
1.08M
    to->line = from->line;
983
1.08M
    to->node = from->node;
984
1.08M
    to->int1 = from->int1;
985
1.08M
    to->int2 = from->int2;
986
1.08M
    to->node = from->node;
987
1.08M
    to->ctxt = from->ctxt;
988
1.08M
    to->message = message;
989
1.08M
    to->file = file;
990
1.08M
    to->str1 = str1;
991
1.08M
    to->str2 = str2;
992
1.08M
    to->str3 = str3;
993
994
1.08M
    return 0;
995
1.08M
}
996