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
520M
#define XML_GET_VAR_STR(msg, str) {       \
22
520M
    int       size, prev_size = -1;       \
23
520M
    int       chars;            \
24
520M
    char      *larger;            \
25
520M
    va_list   ap;           \
26
520M
                \
27
520M
    str = (char *) xmlMalloc(150);        \
28
520M
    if (str != NULL) {           \
29
520M
                \
30
520M
    size = 150;             \
31
520M
                \
32
1.04G
    while (size < 64000) {         \
33
1.04G
  va_start(ap, msg);          \
34
1.04G
  chars = vsnprintf(str, size, msg, ap);      \
35
1.04G
  va_end(ap);           \
36
1.04G
  if ((chars > -1) && (chars < size)) {     \
37
1.04G
      if (prev_size == chars) {       \
38
520M
    break;            \
39
520M
      } else {           \
40
520M
    prev_size = chars;        \
41
520M
      }              \
42
1.04G
  }              \
43
1.04G
  if (chars > -1)           \
44
520M
      size += chars + 1;         \
45
520M
  else              \
46
520M
      size += 100;         \
47
520M
  if ((larger = (char *) xmlRealloc(str, size)) == NULL) {\
48
0
      break;            \
49
0
  }              \
50
520M
  str = larger;           \
51
520M
    }}                \
52
520M
}
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
9.77k
xmlSetGenericErrorFunc(void *ctx, xmlGenericErrorFunc handler) {
114
9.77k
    xmlGenericErrorContext = ctx;
115
9.77k
    if (handler != NULL)
116
9.77k
  xmlGenericError = handler;
117
0
    else
118
0
  xmlGenericError = xmlGenericErrorDefaultFunc;
119
9.77k
}
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
97.3k
xmlParserPrintFileInfo(xmlParserInputPtr input) {
154
97.3k
    if (input != NULL) {
155
97.3k
  if (input->filename)
156
19.9k
      xmlGenericError(xmlGenericErrorContext,
157
19.9k
        "%s:%d: ", input->filename,
158
19.9k
        input->line);
159
77.3k
  else
160
77.3k
      xmlGenericError(xmlGenericErrorContext,
161
77.3k
        "Entity: line %d: ", input->line);
162
97.3k
    }
163
97.3k
}
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
67.7M
    xmlGenericErrorFunc channel, void *data ) {
175
67.7M
    const xmlChar *cur, *base;
176
67.7M
    unsigned int n, col;  /* GCC warns if signed, because compared with sizeof() */
177
67.7M
    xmlChar  content[81]; /* space for 80 chars + line terminator */
178
67.7M
    xmlChar *ctnt;
179
180
67.7M
    if ((input == NULL) || (input->cur == NULL))
181
0
        return;
182
183
67.7M
    cur = input->cur;
184
67.7M
    base = input->base;
185
    /* skip backwards over any end-of-lines */
186
74.4M
    while ((cur > base) && ((*(cur) == '\n') || (*(cur) == '\r'))) {
187
6.66M
  cur--;
188
6.66M
    }
189
67.7M
    n = 0;
190
    /* search backwards for beginning-of-line (to max buff size) */
191
3.36G
    while ((n++ < (sizeof(content)-1)) && (cur > base) &&
192
3.36G
     (*(cur) != '\n') && (*(cur) != '\r'))
193
3.29G
        cur--;
194
67.7M
    if ((*(cur) == '\n') || (*(cur) == '\r')) cur++;
195
    /* calculate the error position in terms of the current position */
196
67.7M
    col = input->cur - cur;
197
    /* search forward for end-of-line (to max buff size) */
198
67.7M
    n = 0;
199
67.7M
    ctnt = content;
200
    /* copy selected text to our buffer */
201
4.01G
    while ((*cur != 0) && (*(cur) != '\n') &&
202
4.01G
     (*(cur) != '\r') && (n < sizeof(content)-1)) {
203
3.94G
    *ctnt++ = *cur++;
204
3.94G
  n++;
205
3.94G
    }
206
67.7M
    *ctnt = 0;
207
    /* print out the selected text */
208
67.7M
    channel(data ,"%s\n", content);
209
    /* create blank line with problem pointer */
210
67.7M
    n = 0;
211
67.7M
    ctnt = content;
212
    /* (leave buffer space for pointer + line terminator) */
213
3.30G
    while ((n<col) && (n++ < sizeof(content)-2) && (*ctnt != 0)) {
214
3.23G
  if (*(ctnt) != '\t')
215
3.22G
      *(ctnt) = ' ';
216
3.23G
  ctnt++;
217
3.23G
    }
218
67.7M
    *ctnt++ = '^';
219
67.7M
    *ctnt = 0;
220
67.7M
    channel(data ,"%s\n", content);
221
67.7M
}
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
97.3k
xmlParserPrintFileContext(xmlParserInputPtr input) {
231
97.3k
   xmlParserPrintFileContextInternal(input, xmlGenericError,
232
97.3k
                                     xmlGenericErrorContext);
233
97.3k
}
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
64.5M
{
248
64.5M
    char *file = NULL;
249
64.5M
    int line = 0;
250
64.5M
    int code = -1;
251
64.5M
    int domain;
252
64.5M
    const xmlChar *name = NULL;
253
64.5M
    xmlNodePtr node;
254
64.5M
    xmlErrorLevel level;
255
64.5M
    xmlParserInputPtr input = NULL;
256
64.5M
    xmlParserInputPtr cur = NULL;
257
258
64.5M
    if (err == NULL)
259
0
        return;
260
261
64.5M
    if (channel == NULL) {
262
64.5M
  channel = xmlGenericError;
263
64.5M
  data = xmlGenericErrorContext;
264
64.5M
    }
265
64.5M
    file = err->file;
266
64.5M
    line = err->line;
267
64.5M
    code = err->code;
268
64.5M
    domain = err->domain;
269
64.5M
    level = err->level;
270
64.5M
    node = err->node;
271
272
64.5M
    if (code == XML_ERR_OK)
273
0
        return;
274
275
64.5M
    if ((node != NULL) && (node->type == XML_ELEMENT_NODE))
276
1.63M
        name = node->name;
277
278
    /*
279
     * Maintain the compatibility with the legacy error handling
280
     */
281
64.5M
    if (ctxt != NULL) {
282
63.4M
        input = ctxt->input;
283
63.4M
        if ((input != NULL) && (input->filename == NULL) &&
284
63.4M
            (ctxt->inputNr > 1)) {
285
4.22M
            cur = input;
286
4.22M
            input = ctxt->inputTab[ctxt->inputNr - 2];
287
4.22M
        }
288
63.4M
        if (input != NULL) {
289
63.4M
            if (input->filename)
290
18.2M
                channel(data, "%s:%d: ", input->filename, input->line);
291
45.1M
            else if ((line != 0) && (domain == XML_FROM_PARSER))
292
41.0M
                channel(data, "Entity: line %d: ", input->line);
293
63.4M
        }
294
63.4M
    } else {
295
1.17M
        if (file != NULL)
296
763k
            channel(data, "%s:%d: ", file, line);
297
416k
        else if ((line != 0) &&
298
416k
           ((domain == XML_FROM_PARSER) || (domain == XML_FROM_SCHEMASV)||
299
416k
      (domain == XML_FROM_SCHEMASP)||(domain == XML_FROM_DTD) ||
300
416k
      (domain == XML_FROM_RELAXNGP)||(domain == XML_FROM_RELAXNGV)))
301
0
            channel(data, "Entity: line %d: ", line);
302
1.17M
    }
303
64.5M
    if (name != NULL) {
304
1.63M
        channel(data, "element %s: ", name);
305
1.63M
    }
306
64.5M
    switch (domain) {
307
58.1M
        case XML_FROM_PARSER:
308
58.1M
            channel(data, "parser ");
309
58.1M
            break;
310
1.42M
        case XML_FROM_NAMESPACE:
311
1.42M
            channel(data, "namespace ");
312
1.42M
            break;
313
115k
        case XML_FROM_DTD:
314
4.99M
        case XML_FROM_VALID:
315
4.99M
            channel(data, "validity ");
316
4.99M
            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
64.5M
    }
380
64.5M
    switch (level) {
381
0
        case XML_ERR_NONE:
382
0
            channel(data, ": ");
383
0
            break;
384
3.63M
        case XML_ERR_WARNING:
385
3.63M
            channel(data, "warning : ");
386
3.63M
            break;
387
3.68M
        case XML_ERR_ERROR:
388
3.68M
            channel(data, "error : ");
389
3.68M
            break;
390
57.2M
        case XML_ERR_FATAL:
391
57.2M
            channel(data, "error : ");
392
57.2M
            break;
393
64.5M
    }
394
64.5M
    if (str != NULL) {
395
64.5M
        int len;
396
64.5M
  len = xmlStrlen((const xmlChar *)str);
397
64.5M
  if ((len > 0) && (str[len - 1] != '\n'))
398
67.8k
      channel(data, "%s\n", str);
399
64.5M
  else
400
64.5M
      channel(data, "%s", str);
401
64.5M
    } else {
402
0
        channel(data, "%s\n", "out of memory error");
403
0
    }
404
405
64.5M
    if (ctxt != NULL) {
406
63.4M
        xmlParserPrintFileContextInternal(input, channel, data);
407
63.4M
        if (cur != NULL) {
408
4.22M
            if (cur->filename)
409
0
                channel(data, "%s:%d: \n", cur->filename, cur->line);
410
4.22M
            else if ((line != 0) && (domain == XML_FROM_PARSER))
411
1.04M
                channel(data, "Entity: line %d: \n", cur->line);
412
4.22M
            xmlParserPrintFileContextInternal(cur, channel, data);
413
4.22M
        }
414
63.4M
    }
415
64.5M
    if ((domain == XML_FROM_XPATH) && (err->str1 != NULL) &&
416
64.5M
        (err->int1 < 100) &&
417
64.5M
  (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
64.5M
}
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
520M
{
462
520M
    xmlParserCtxtPtr ctxt = NULL;
463
520M
    xmlNodePtr node = (xmlNodePtr) nod;
464
520M
    char *str = NULL;
465
520M
    xmlParserInputPtr input = NULL;
466
520M
    xmlErrorPtr to = &xmlLastError;
467
520M
    xmlNodePtr baseptr = NULL;
468
469
520M
    if (code == XML_ERR_OK)
470
0
        return;
471
520M
    if ((xmlGetWarningsDefaultValue == 0) && (level == XML_ERR_WARNING))
472
0
        return;
473
520M
    if ((domain == XML_FROM_PARSER) || (domain == XML_FROM_HTML) ||
474
520M
        (domain == XML_FROM_DTD) || (domain == XML_FROM_NAMESPACE) ||
475
520M
  (domain == XML_FROM_IO) || (domain == XML_FROM_VALID)) {
476
210M
  ctxt = (xmlParserCtxtPtr) ctx;
477
210M
  if ((schannel == NULL) && (ctxt != NULL) && (ctxt->sax != NULL) &&
478
210M
      (ctxt->sax->initialized == XML_SAX2_MAGIC) &&
479
210M
      (ctxt->sax->serror != NULL)) {
480
0
      schannel = ctxt->sax->serror;
481
0
      data = ctxt->userData;
482
0
  }
483
210M
    }
484
    /*
485
     * Check if structured error handler set
486
     */
487
520M
    if (schannel == NULL) {
488
520M
  schannel = xmlStructuredError;
489
  /*
490
   * if user has defined handler, change data ptr to user's choice
491
   */
492
520M
  if (schannel != NULL)
493
0
      data = xmlStructuredErrorContext;
494
520M
    }
495
    /*
496
     * Formatting the message
497
     */
498
520M
    if (msg == NULL) {
499
0
        str = (char *) xmlStrdup(BAD_CAST "No error message provided");
500
520M
    } else {
501
520M
        XML_GET_VAR_STR(msg, str);
502
520M
    }
503
504
    /*
505
     * specific processing if a parser context is provided
506
     */
507
520M
    if (ctxt != NULL) {
508
205M
        if (file == NULL) {
509
205M
            input = ctxt->input;
510
205M
            if ((input != NULL) && (input->filename == NULL) &&
511
205M
                (ctxt->inputNr > 1)) {
512
7.60M
                input = ctxt->inputTab[ctxt->inputNr - 2];
513
7.60M
            }
514
205M
            if (input != NULL) {
515
205M
                file = input->filename;
516
205M
                line = input->line;
517
205M
                col = input->col;
518
205M
            }
519
205M
        }
520
205M
        to = &ctxt->lastError;
521
314M
    } else if ((node != NULL) && (file == NULL)) {
522
148M
  int i;
523
524
148M
  if ((node->doc != NULL) && (node->doc->URL != NULL)) {
525
146M
      baseptr = node;
526
/*      file = (const char *) node->doc->URL; */
527
146M
  }
528
148M
  for (i = 0;
529
291M
       ((i < 10) && (node != NULL) && (node->type != XML_ELEMENT_NODE));
530
148M
       i++)
531
143M
       node = node->parent;
532
148M
        if ((baseptr == NULL) && (node != NULL) &&
533
148M
      (node->doc != NULL) && (node->doc->URL != NULL))
534
0
      baseptr = node;
535
536
148M
  if ((node != NULL) && (node->type == XML_ELEMENT_NODE))
537
148M
      line = node->line;
538
148M
  if ((line == 0) || (line == 65535))
539
83.7k
      line = xmlGetLineNo(node);
540
148M
    }
541
542
    /*
543
     * Save the information about the error
544
     */
545
520M
    xmlResetError(to);
546
520M
    to->domain = domain;
547
520M
    to->code = code;
548
520M
    to->message = str;
549
520M
    to->level = level;
550
520M
    if (file != NULL)
551
37.0M
        to->file = (char *) xmlStrdup((const xmlChar *) file);
552
483M
    else if (baseptr != NULL) {
553
146M
#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
146M
        xmlNodePtr prev = baseptr;
560
146M
        char *href = NULL;
561
146M
  int inclcount = 0;
562
69.9G
  while (prev != NULL) {
563
69.7G
      if (prev->prev == NULL)
564
5.35G
          prev = prev->parent;
565
64.4G
      else {
566
64.4G
          prev = prev->prev;
567
64.4G
    if (prev->type == XML_XINCLUDE_START) {
568
1.08G
        if (inclcount > 0) {
569
736M
                        --inclcount;
570
736M
                    } else {
571
351M
                        href = (char *) xmlGetProp(prev, BAD_CAST "href");
572
351M
                        if (href != NULL)
573
0
                break;
574
351M
                    }
575
63.3G
    } else if (prev->type == XML_XINCLUDE_END)
576
736M
        inclcount++;
577
64.4G
      }
578
69.7G
  }
579
146M
        if (href != NULL)
580
0
            to->file = href;
581
146M
  else
582
146M
#endif
583
146M
      to->file = (char *) xmlStrdup(baseptr->doc->URL);
584
146M
  if ((to->file == NULL) && (node != NULL) && (node->doc != NULL)) {
585
0
      to->file = (char *) xmlStrdup(node->doc->URL);
586
0
  }
587
146M
    }
588
520M
    to->line = line;
589
520M
    if (str1 != NULL)
590
44.8M
        to->str1 = (char *) xmlStrdup((const xmlChar *) str1);
591
520M
    if (str2 != NULL)
592
12.0M
        to->str2 = (char *) xmlStrdup((const xmlChar *) str2);
593
520M
    if (str3 != NULL)
594
429k
        to->str3 = (char *) xmlStrdup((const xmlChar *) str3);
595
520M
    to->int1 = int1;
596
520M
    to->int2 = col;
597
520M
    to->node = node;
598
520M
    to->ctxt = ctx;
599
600
520M
    if (to != &xmlLastError)
601
205M
        xmlCopyError(to,&xmlLastError);
602
603
520M
    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
520M
    if ((ctxt != NULL) && (channel == NULL) &&
612
520M
        (xmlStructuredError == NULL) && (ctxt->sax != NULL)) {
613
201M
        if (level == XML_ERR_WARNING)
614
4.15M
      channel = ctxt->sax->warning;
615
197M
        else
616
197M
      channel = ctxt->sax->error;
617
201M
  data = ctxt->userData;
618
319M
    } else if (channel == NULL) {
619
313M
  channel = xmlGenericError;
620
313M
  if (ctxt != NULL) {
621
0
      data = ctxt;
622
313M
  } else {
623
313M
      data = xmlGenericErrorContext;
624
313M
  }
625
313M
    }
626
520M
    if (channel == NULL)
627
142M
        return;
628
629
378M
    if ((channel == xmlParserError) ||
630
378M
        (channel == xmlParserWarning) ||
631
378M
  (channel == xmlParserValidityError) ||
632
378M
  (channel == xmlParserValidityWarning))
633
64.5M
  xmlReportError(to, ctxt, str, NULL, NULL);
634
313M
    else if (((void(*)(void)) channel == (void(*)(void)) fprintf) ||
635
313M
             (channel == xmlGenericErrorDefaultFunc))
636
0
  xmlReportError(to, ctxt, str, channel, data);
637
313M
    else
638
313M
  channel(data, "%s", str);
639
378M
}
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
308M
{
654
655
308M
    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
308M
    } else {
666
308M
  __xmlRaiseError(NULL, NULL, NULL, NULL, node, domain,
667
308M
      code, XML_ERR_ERROR, NULL, 0, extra,
668
308M
      NULL, NULL, 0, 0, msg, extra);
669
308M
    }
670
308M
}
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
95.9k
{
726
95.9k
    xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
727
95.9k
    xmlParserInputPtr input = NULL;
728
95.9k
    xmlParserInputPtr cur = NULL;
729
95.9k
    char * str;
730
731
95.9k
    if (ctxt != NULL) {
732
95.9k
  input = ctxt->input;
733
95.9k
  if ((input != NULL) && (input->filename == NULL) &&
734
95.9k
      (ctxt->inputNr > 1)) {
735
1.35k
      cur = input;
736
1.35k
      input = ctxt->inputTab[ctxt->inputNr - 2];
737
1.35k
  }
738
95.9k
  xmlParserPrintFileInfo(input);
739
95.9k
    }
740
741
95.9k
    xmlGenericError(xmlGenericErrorContext, "warning: ");
742
95.9k
    XML_GET_VAR_STR(msg, str);
743
95.9k
    xmlGenericError(xmlGenericErrorContext, "%s", str);
744
95.9k
    if (str != NULL)
745
95.9k
  xmlFree(str);
746
747
95.9k
    if (ctxt != NULL) {
748
95.9k
  xmlParserPrintFileContext(input);
749
95.9k
  if (cur != NULL) {
750
1.35k
      xmlParserPrintFileInfo(cur);
751
1.35k
      xmlGenericError(xmlGenericErrorContext, "\n");
752
1.35k
      xmlParserPrintFileContext(cur);
753
1.35k
  }
754
95.9k
    }
755
95.9k
}
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
521M
{
875
521M
    if (err == NULL)
876
0
        return;
877
521M
    if (err->code == XML_ERR_OK)
878
2.26M
        return;
879
519M
    if (err->message != NULL)
880
518M
        xmlFree(err->message);
881
519M
    if (err->file != NULL)
882
182M
        xmlFree(err->file);
883
519M
    if (err->str1 != NULL)
884
44.5M
        xmlFree(err->str1);
885
519M
    if (err->str2 != NULL)
886
11.6M
        xmlFree(err->str2);
887
519M
    if (err->str3 != NULL)
888
422k
        xmlFree(err->str3);
889
519M
    memset(err, 0, sizeof(xmlError));
890
519M
    err->code = XML_ERR_OK;
891
519M
}
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
434k
{
902
434k
    if (xmlLastError.code == XML_ERR_OK)
903
17.5k
        return;
904
417k
    xmlResetError(&xmlLastError);
905
417k
}
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
208M
xmlCopyError(xmlErrorPtr from, xmlErrorPtr to) {
958
208M
    char *message, *file, *str1, *str2, *str3;
959
960
208M
    if ((from == NULL) || (to == NULL))
961
0
        return(-1);
962
963
208M
    message = (char *) xmlStrdup((xmlChar *) from->message);
964
208M
    file = (char *) xmlStrdup ((xmlChar *) from->file);
965
208M
    str1 = (char *) xmlStrdup ((xmlChar *) from->str1);
966
208M
    str2 = (char *) xmlStrdup ((xmlChar *) from->str2);
967
208M
    str3 = (char *) xmlStrdup ((xmlChar *) from->str3);
968
969
208M
    if (to->message != NULL)
970
206M
        xmlFree(to->message);
971
208M
    if (to->file != NULL)
972
37.1M
        xmlFree(to->file);
973
208M
    if (to->str1 != NULL)
974
39.2M
        xmlFree(to->str1);
975
208M
    if (to->str2 != NULL)
976
10.0M
        xmlFree(to->str2);
977
208M
    if (to->str3 != NULL)
978
366k
        xmlFree(to->str3);
979
208M
    to->domain = from->domain;
980
208M
    to->code = from->code;
981
208M
    to->level = from->level;
982
208M
    to->line = from->line;
983
208M
    to->node = from->node;
984
208M
    to->int1 = from->int1;
985
208M
    to->int2 = from->int2;
986
208M
    to->node = from->node;
987
208M
    to->ctxt = from->ctxt;
988
208M
    to->message = message;
989
208M
    to->file = file;
990
208M
    to->str1 = str1;
991
208M
    to->str2 = str2;
992
208M
    to->str3 = str3;
993
994
208M
    return 0;
995
208M
}
996