Coverage Report

Created: 2023-12-13 20:03

/src/libxml2/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
#include "private/error.h"
20
21
273M
#define XML_GET_VAR_STR(msg, str) {       \
22
273M
    int       size, prev_size = -1;       \
23
273M
    int       chars;            \
24
273M
    char      *larger;            \
25
273M
    va_list   ap;           \
26
273M
                \
27
273M
    str = (char *) xmlMalloc(150);        \
28
273M
    if (str != NULL) {           \
29
273M
                \
30
273M
    size = 150;             \
31
273M
                \
32
547M
    while (size < 64000) {         \
33
547M
  va_start(ap, msg);          \
34
547M
  chars = vsnprintf(str, size, msg, ap);      \
35
547M
  va_end(ap);           \
36
547M
  if ((chars > -1) && (chars < size)) {     \
37
546M
      if (prev_size == chars) {       \
38
273M
    break;            \
39
273M
      } else {           \
40
273M
    prev_size = chars;        \
41
273M
      }              \
42
546M
  }              \
43
547M
  if (chars > -1)           \
44
274M
      size += chars + 1;         \
45
274M
  else              \
46
274M
      size += 100;         \
47
274M
  if ((larger = (char *) xmlRealloc(str, size)) == NULL) {\
48
0
      break;            \
49
0
  }              \
50
274M
  str = larger;           \
51
274M
    }}                \
52
273M
}
53
54
/************************************************************************
55
 *                  *
56
 *      Handling of out of context errors   *
57
 *                  *
58
 ************************************************************************/
59
60
/**
61
 * xmlGenericErrorDefaultFunc:
62
 * @ctx:  an error context
63
 * @msg:  the message to display/transmit
64
 * @...:  extra parameters for the message display
65
 *
66
 * Default handler for out of context error messages.
67
 */
68
void XMLCDECL
69
0
xmlGenericErrorDefaultFunc(void *ctx ATTRIBUTE_UNUSED, const char *msg, ...) {
70
0
    va_list args;
71
72
0
    if (xmlGenericErrorContext == NULL)
73
0
  xmlGenericErrorContext = (void *) stderr;
74
75
0
    va_start(args, msg);
76
0
    vfprintf((FILE *)xmlGenericErrorContext, msg, args);
77
0
    va_end(args);
78
0
}
79
80
/**
81
 * initGenericErrorDefaultFunc:
82
 * @handler:  the handler
83
 *
84
 * DEPRECATED: Use xmlSetGenericErrorFunc.
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
0
{
92
0
    if (handler == NULL)
93
0
        xmlGenericError = xmlGenericErrorDefaultFunc;
94
0
    else
95
0
        xmlGenericError = (*handler);
96
0
}
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
3.75k
xmlSetGenericErrorFunc(void *ctx, xmlGenericErrorFunc handler) {
114
3.75k
    xmlGenericErrorContext = ctx;
115
3.75k
    if (handler != NULL)
116
3.75k
  xmlGenericError = handler;
117
0
    else
118
0
  xmlGenericError = xmlGenericErrorDefaultFunc;
119
3.75k
}
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
0
xmlSetStructuredErrorFunc(void *ctx, xmlStructuredErrorFunc handler) {
135
0
    xmlStructuredErrorContext = ctx;
136
0
    xmlStructuredError = handler;
137
0
}
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
63.9k
xmlParserPrintFileInfo(xmlParserInputPtr input) {
154
63.9k
    if (input != NULL) {
155
63.9k
  if (input->filename)
156
33.6k
      xmlGenericError(xmlGenericErrorContext,
157
33.6k
        "%s:%d: ", input->filename,
158
33.6k
        input->line);
159
30.2k
  else
160
30.2k
      xmlGenericError(xmlGenericErrorContext,
161
30.2k
        "Entity: line %d: ", input->line);
162
63.9k
    }
163
63.9k
}
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
143M
    xmlGenericErrorFunc channel, void *data ) {
175
143M
    const xmlChar *cur, *base;
176
143M
    unsigned int n, col;  /* GCC warns if signed, because compared with sizeof() */
177
143M
    xmlChar  content[81]; /* space for 80 chars + line terminator */
178
143M
    xmlChar *ctnt;
179
180
143M
    if ((input == NULL) || (input->cur == NULL))
181
0
        return;
182
183
143M
    cur = input->cur;
184
143M
    base = input->base;
185
    /* skip backwards over any end-of-lines */
186
149M
    while ((cur > base) && ((*(cur) == '\n') || (*(cur) == '\r'))) {
187
6.31M
  cur--;
188
6.31M
    }
189
143M
    n = 0;
190
    /* search backwards for beginning-of-line (to max buff size) */
191
8.89G
    while ((n++ < (sizeof(content)-1)) && (cur > base) &&
192
8.89G
     (*(cur) != '\n') && (*(cur) != '\r'))
193
8.75G
        cur--;
194
143M
    if ((*(cur) == '\n') || (*(cur) == '\r')) cur++;
195
    /* calculate the error position in terms of the current position */
196
143M
    col = input->cur - cur;
197
    /* search forward for end-of-line (to max buff size) */
198
143M
    n = 0;
199
143M
    ctnt = content;
200
    /* copy selected text to our buffer */
201
9.95G
    while ((*cur != 0) && (*(cur) != '\n') &&
202
9.95G
     (*(cur) != '\r') && (n < sizeof(content)-1)) {
203
9.81G
    *ctnt++ = *cur++;
204
9.81G
  n++;
205
9.81G
    }
206
143M
    *ctnt = 0;
207
    /* print out the selected text */
208
143M
    channel(data ,"%s\n", content);
209
    /* create blank line with problem pointer */
210
143M
    n = 0;
211
143M
    ctnt = content;
212
    /* (leave buffer space for pointer + line terminator) */
213
8.76G
    while ((n<col) && (n++ < sizeof(content)-2) && (*ctnt != 0)) {
214
8.61G
  if (*(ctnt) != '\t')
215
8.60G
      *(ctnt) = ' ';
216
8.61G
  ctnt++;
217
8.61G
    }
218
143M
    *ctnt++ = '^';
219
143M
    *ctnt = 0;
220
143M
    channel(data ,"%s\n", content);
221
143M
}
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
63.9k
xmlParserPrintFileContext(xmlParserInputPtr input) {
231
63.9k
   xmlParserPrintFileContextInternal(input, xmlGenericError,
232
63.9k
                                     xmlGenericErrorContext);
233
63.9k
}
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
142M
{
248
142M
    char *file = NULL;
249
142M
    int line = 0;
250
142M
    int code = -1;
251
142M
    int domain;
252
142M
    const xmlChar *name = NULL;
253
142M
    xmlNodePtr node;
254
142M
    xmlErrorLevel level;
255
142M
    xmlParserInputPtr input = NULL;
256
142M
    xmlParserInputPtr cur = NULL;
257
258
142M
    if (err == NULL)
259
0
        return;
260
261
142M
    if (channel == NULL) {
262
142M
  channel = xmlGenericError;
263
142M
  data = xmlGenericErrorContext;
264
142M
    }
265
142M
    file = err->file;
266
142M
    line = err->line;
267
142M
    code = err->code;
268
142M
    domain = err->domain;
269
142M
    level = err->level;
270
142M
    node = err->node;
271
272
142M
    if (code == XML_ERR_OK)
273
0
        return;
274
275
142M
    if ((node != NULL) && (node->type == XML_ELEMENT_NODE))
276
3.68M
        name = node->name;
277
278
    /*
279
     * Maintain the compatibility with the legacy error handling
280
     */
281
142M
    if (ctxt != NULL) {
282
138M
        input = ctxt->input;
283
138M
        if ((input != NULL) && (input->filename == NULL) &&
284
138M
            (ctxt->inputNr > 1)) {
285
4.02M
            cur = input;
286
4.02M
            input = ctxt->inputTab[ctxt->inputNr - 2];
287
4.02M
        }
288
138M
        if (input != NULL) {
289
138M
            if (input->filename)
290
10.9M
                channel(data, "%s:%d: ", input->filename, input->line);
291
128M
            else if ((line != 0) && (domain == XML_FROM_PARSER))
292
124M
                channel(data, "Entity: line %d: ", input->line);
293
138M
        }
294
138M
    } else {
295
3.08M
        if (file != NULL)
296
2.06M
            channel(data, "%s:%d: ", file, line);
297
1.02M
        else if ((line != 0) &&
298
1.02M
           ((domain == XML_FROM_PARSER) || (domain == XML_FROM_SCHEMASV)||
299
1.02M
      (domain == XML_FROM_SCHEMASP)||(domain == XML_FROM_DTD) ||
300
1.02M
      (domain == XML_FROM_RELAXNGP)||(domain == XML_FROM_RELAXNGV)))
301
0
            channel(data, "Entity: line %d: ", line);
302
3.08M
    }
303
142M
    if (name != NULL) {
304
3.68M
        channel(data, "element %s: ", name);
305
3.68M
    }
306
142M
    switch (domain) {
307
134M
        case XML_FROM_PARSER:
308
134M
            channel(data, "parser ");
309
134M
            break;
310
2.22M
        case XML_FROM_NAMESPACE:
311
2.22M
            channel(data, "namespace ");
312
2.22M
            break;
313
207k
        case XML_FROM_DTD:
314
5.40M
        case XML_FROM_VALID:
315
5.40M
            channel(data, "validity ");
316
5.40M
            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
142M
    }
380
142M
    switch (level) {
381
0
        case XML_ERR_NONE:
382
0
            channel(data, ": ");
383
0
            break;
384
2.82M
        case XML_ERR_WARNING:
385
2.82M
            channel(data, "warning : ");
386
2.82M
            break;
387
5.60M
        case XML_ERR_ERROR:
388
5.60M
            channel(data, "error : ");
389
5.60M
            break;
390
133M
        case XML_ERR_FATAL:
391
133M
            channel(data, "error : ");
392
133M
            break;
393
142M
    }
394
142M
    if (str != NULL) {
395
142M
        int len;
396
142M
  len = xmlStrlen((const xmlChar *)str);
397
142M
  if ((len > 0) && (str[len - 1] != '\n'))
398
61.5k
      channel(data, "%s\n", str);
399
142M
  else
400
142M
      channel(data, "%s", str);
401
142M
    } else {
402
0
        channel(data, "%s\n", "out of memory error");
403
0
    }
404
405
142M
    if (ctxt != NULL) {
406
138M
        xmlParserPrintFileContextInternal(input, channel, data);
407
138M
        if (cur != NULL) {
408
4.02M
            if (cur->filename)
409
0
                channel(data, "%s:%d: \n", cur->filename, cur->line);
410
4.02M
            else if ((line != 0) && (domain == XML_FROM_PARSER))
411
2.60M
                channel(data, "Entity: line %d: \n", cur->line);
412
4.02M
            xmlParserPrintFileContextInternal(cur, channel, data);
413
4.02M
        }
414
138M
    }
415
142M
    if ((domain == XML_FROM_XPATH) && (err->str1 != NULL) &&
416
142M
        (err->int1 < 100) &&
417
142M
  (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
142M
}
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
273M
{
462
273M
    xmlParserCtxtPtr ctxt = NULL;
463
273M
    xmlNodePtr node = (xmlNodePtr) nod;
464
273M
    char *str = NULL;
465
273M
    xmlParserInputPtr input = NULL;
466
273M
    xmlErrorPtr to = &xmlLastError;
467
273M
    xmlNodePtr baseptr = NULL;
468
469
273M
    if (code == XML_ERR_OK)
470
0
        return;
471
273M
    if ((xmlGetWarningsDefaultValue == 0) && (level == XML_ERR_WARNING))
472
0
        return;
473
273M
    if ((domain == XML_FROM_PARSER) || (domain == XML_FROM_HTML) ||
474
273M
        (domain == XML_FROM_DTD) || (domain == XML_FROM_NAMESPACE) ||
475
273M
  (domain == XML_FROM_IO) || (domain == XML_FROM_VALID)) {
476
213M
  ctxt = (xmlParserCtxtPtr) ctx;
477
213M
  if ((schannel == NULL) && (ctxt != NULL) && (ctxt->sax != NULL) &&
478
213M
      (ctxt->sax->initialized == XML_SAX2_MAGIC) &&
479
213M
      (ctxt->sax->serror != NULL)) {
480
0
      schannel = ctxt->sax->serror;
481
0
      data = ctxt->userData;
482
0
  }
483
213M
    }
484
    /*
485
     * Check if structured error handler set
486
     */
487
273M
    if (schannel == NULL) {
488
273M
  schannel = xmlStructuredError;
489
  /*
490
   * if user has defined handler, change data ptr to user's choice
491
   */
492
273M
  if (schannel != NULL)
493
0
      data = xmlStructuredErrorContext;
494
273M
    }
495
    /*
496
     * Formatting the message
497
     */
498
273M
    if (msg == NULL) {
499
0
        str = (char *) xmlStrdup(BAD_CAST "No error message provided");
500
273M
    } else {
501
273M
        XML_GET_VAR_STR(msg, str);
502
273M
    }
503
504
    /*
505
     * specific processing if a parser context is provided
506
     */
507
273M
    if (ctxt != NULL) {
508
206M
        if (file == NULL) {
509
206M
            input = ctxt->input;
510
206M
            if ((input != NULL) && (input->filename == NULL) &&
511
206M
                (ctxt->inputNr > 1)) {
512
14.0M
                input = ctxt->inputTab[ctxt->inputNr - 2];
513
14.0M
            }
514
206M
            if (input != NULL) {
515
206M
                file = input->filename;
516
206M
                line = input->line;
517
206M
                col = input->col;
518
206M
            }
519
206M
        }
520
206M
        to = &ctxt->lastError;
521
206M
    } else if ((node != NULL) && (file == NULL)) {
522
65.7M
  int i;
523
524
65.7M
  if ((node->doc != NULL) && (node->doc->URL != NULL)) {
525
63.3M
      baseptr = node;
526
/*      file = (const char *) node->doc->URL; */
527
63.3M
  }
528
65.7M
  for (i = 0;
529
123M
       ((i < 10) && (node != NULL) && (node->type != XML_ELEMENT_NODE));
530
65.7M
       i++)
531
58.2M
       node = node->parent;
532
65.7M
        if ((baseptr == NULL) && (node != NULL) &&
533
65.7M
      (node->doc != NULL) && (node->doc->URL != NULL))
534
0
      baseptr = node;
535
536
65.7M
  if ((node != NULL) && (node->type == XML_ELEMENT_NODE))
537
65.4M
      line = node->line;
538
65.7M
  if ((line == 0) || (line == 65535))
539
447k
      line = xmlGetLineNo(node);
540
65.7M
    }
541
542
    /*
543
     * Save the information about the error
544
     */
545
273M
    xmlResetError(to);
546
273M
    to->domain = domain;
547
273M
    to->code = code;
548
273M
    to->message = str;
549
273M
    to->level = level;
550
273M
    if (file != NULL)
551
25.1M
        to->file = (char *) xmlStrdup((const xmlChar *) file);
552
248M
    else if (baseptr != NULL) {
553
63.3M
#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
63.3M
        xmlNodePtr prev = baseptr;
560
63.3M
        char *href = NULL;
561
63.3M
  int inclcount = 0;
562
6.77G
  while (prev != NULL) {
563
6.71G
      if (prev->prev == NULL)
564
1.20G
          prev = prev->parent;
565
5.50G
      else {
566
5.50G
          prev = prev->prev;
567
5.50G
    if (prev->type == XML_XINCLUDE_START) {
568
188M
        if (inclcount > 0) {
569
117M
                        --inclcount;
570
117M
                    } else {
571
71.5M
                        href = (char *) xmlGetProp(prev, BAD_CAST "href");
572
71.5M
                        if (href != NULL)
573
0
                break;
574
71.5M
                    }
575
5.31G
    } else if (prev->type == XML_XINCLUDE_END)
576
117M
        inclcount++;
577
5.50G
      }
578
6.71G
  }
579
63.3M
        if (href != NULL)
580
0
            to->file = href;
581
63.3M
  else
582
63.3M
#endif
583
63.3M
      to->file = (char *) xmlStrdup(baseptr->doc->URL);
584
63.3M
  if ((to->file == NULL) && (node != NULL) && (node->doc != NULL)) {
585
0
      to->file = (char *) xmlStrdup(node->doc->URL);
586
0
  }
587
63.3M
    }
588
273M
    to->line = line;
589
273M
    if (str1 != NULL)
590
49.7M
        to->str1 = (char *) xmlStrdup((const xmlChar *) str1);
591
273M
    if (str2 != NULL)
592
14.9M
        to->str2 = (char *) xmlStrdup((const xmlChar *) str2);
593
273M
    if (str3 != NULL)
594
774k
        to->str3 = (char *) xmlStrdup((const xmlChar *) str3);
595
273M
    to->int1 = int1;
596
273M
    to->int2 = col;
597
273M
    to->node = node;
598
273M
    to->ctxt = ctx;
599
600
273M
    if (to != &xmlLastError)
601
206M
        xmlCopyError(to,&xmlLastError);
602
603
273M
    if (schannel != NULL) {
604
0
  schannel(data, to);
605
0
  return;
606
0
    }
607
608
    /*
609
     * Find the callback channel if channel param is NULL
610
     */
611
273M
    if ((ctxt != NULL) && (channel == NULL) &&
612
273M
        (xmlStructuredError == NULL) && (ctxt->sax != NULL)) {
613
203M
        if (level == XML_ERR_WARNING)
614
6.56M
      channel = ctxt->sax->warning;
615
196M
        else
616
196M
      channel = ctxt->sax->error;
617
203M
  data = ctxt->userData;
618
203M
    } else if (channel == NULL) {
619
63.9M
  channel = xmlGenericError;
620
63.9M
  if (ctxt != NULL) {
621
0
      data = ctxt;
622
63.9M
  } else {
623
63.9M
      data = xmlGenericErrorContext;
624
63.9M
  }
625
63.9M
    }
626
273M
    if (channel == NULL)
627
67.4M
        return;
628
629
205M
    if ((channel == xmlParserError) ||
630
205M
        (channel == xmlParserWarning) ||
631
205M
  (channel == xmlParserValidityError) ||
632
205M
  (channel == xmlParserValidityWarning))
633
142M
  xmlReportError(to, ctxt, str, NULL, NULL);
634
63.9M
    else if (((void(*)(void)) channel == (void(*)(void)) fprintf) ||
635
63.9M
             (channel == xmlGenericErrorDefaultFunc))
636
0
  xmlReportError(to, ctxt, str, channel, data);
637
63.9M
    else
638
63.9M
  channel(data, "%s", str);
639
205M
}
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
59.0M
{
654
655
59.0M
    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
59.0M
    } else {
666
59.0M
  __xmlRaiseError(NULL, NULL, NULL, NULL, node, domain,
667
59.0M
      code, XML_ERR_ERROR, NULL, 0, extra,
668
59.0M
      NULL, NULL, 0, 0, msg, extra);
669
59.0M
    }
670
59.0M
}
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
63.4k
{
726
63.4k
    xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
727
63.4k
    xmlParserInputPtr input = NULL;
728
63.4k
    xmlParserInputPtr cur = NULL;
729
63.4k
    char * str;
730
731
63.4k
    if (ctxt != NULL) {
732
63.4k
  input = ctxt->input;
733
63.4k
  if ((input != NULL) && (input->filename == NULL) &&
734
63.4k
      (ctxt->inputNr > 1)) {
735
492
      cur = input;
736
492
      input = ctxt->inputTab[ctxt->inputNr - 2];
737
492
  }
738
63.4k
  xmlParserPrintFileInfo(input);
739
63.4k
    }
740
741
63.4k
    xmlGenericError(xmlGenericErrorContext, "warning: ");
742
63.4k
    XML_GET_VAR_STR(msg, str);
743
63.4k
    xmlGenericError(xmlGenericErrorContext, "%s", str);
744
63.4k
    if (str != NULL)
745
63.4k
  xmlFree(str);
746
747
63.4k
    if (ctxt != NULL) {
748
63.4k
  xmlParserPrintFileContext(input);
749
63.4k
  if (cur != NULL) {
750
492
      xmlParserPrintFileInfo(cur);
751
492
      xmlGenericError(xmlGenericErrorContext, "\n");
752
492
      xmlParserPrintFileContext(cur);
753
492
  }
754
63.4k
    }
755
63.4k
}
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
273M
{
875
273M
    if (err == NULL)
876
0
        return;
877
273M
    if (err->code == XML_ERR_OK)
878
2.44M
        return;
879
271M
    if (err->message != NULL)
880
271M
        xmlFree(err->message);
881
271M
    if (err->file != NULL)
882
86.6M
        xmlFree(err->file);
883
271M
    if (err->str1 != NULL)
884
47.9M
        xmlFree(err->str1);
885
271M
    if (err->str2 != NULL)
886
14.6M
        xmlFree(err->str2);
887
271M
    if (err->str3 != NULL)
888
746k
        xmlFree(err->str3);
889
271M
    memset(err, 0, sizeof(xmlError));
890
271M
    err->code = XML_ERR_OK;
891
271M
}
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
298k
{
902
298k
    if (xmlLastError.code == XML_ERR_OK)
903
13.5k
        return;
904
284k
    xmlResetError(&xmlLastError);
905
284k
}
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
209M
xmlCopyError(xmlErrorPtr from, xmlErrorPtr to) {
958
209M
    char *message, *file, *str1, *str2, *str3;
959
960
209M
    if ((from == NULL) || (to == NULL))
961
0
        return(-1);
962
963
209M
    message = (char *) xmlStrdup((xmlChar *) from->message);
964
209M
    file = (char *) xmlStrdup ((xmlChar *) from->file);
965
209M
    str1 = (char *) xmlStrdup ((xmlChar *) from->str1);
966
209M
    str2 = (char *) xmlStrdup ((xmlChar *) from->str2);
967
209M
    str3 = (char *) xmlStrdup ((xmlChar *) from->str3);
968
969
209M
    if (to->message != NULL)
970
207M
        xmlFree(to->message);
971
209M
    if (to->file != NULL)
972
26.4M
        xmlFree(to->file);
973
209M
    if (to->str1 != NULL)
974
43.0M
        xmlFree(to->str1);
975
209M
    if (to->str2 != NULL)
976
11.4M
        xmlFree(to->str2);
977
209M
    if (to->str3 != NULL)
978
787k
        xmlFree(to->str3);
979
209M
    to->domain = from->domain;
980
209M
    to->code = from->code;
981
209M
    to->level = from->level;
982
209M
    to->line = from->line;
983
209M
    to->node = from->node;
984
209M
    to->int1 = from->int1;
985
209M
    to->int2 = from->int2;
986
209M
    to->node = from->node;
987
209M
    to->ctxt = from->ctxt;
988
209M
    to->message = message;
989
209M
    to->file = file;
990
209M
    to->str1 = str1;
991
209M
    to->str2 = str2;
992
209M
    to->str3 = str3;
993
994
209M
    return 0;
995
209M
}
996