1/* XML handler functions for the Expat test suite
2                            __  __            _
3                         ___\ \/ /_ __   __ _| |_
4                        / _ \\  /| '_ \ / _` | __|
5                       |  __//  \| |_) | (_| | |_
6                        \___/_/\_\ .__/ \__,_|\__|
7                                 |_| XML parser
8
9   Copyright (c) 2001-2006 Fred L. Drake, Jr. <fdrake@users.sourceforge.net>
10   Copyright (c) 2003      Greg Stein <gstein@users.sourceforge.net>
11   Copyright (c) 2005-2007 Steven Solie <steven@solie.ca>
12   Copyright (c) 2005-2012 Karl Waclawek <karl@waclawek.net>
13   Copyright (c) 2016-2024 Sebastian Pipping <sebastian@pipping.org>
14   Copyright (c) 2017-2022 Rhodri James <rhodri@wildebeest.org.uk>
15   Copyright (c) 2017      Joe Orton <jorton@redhat.com>
16   Copyright (c) 2017      Jos�� Guti��rrez de la Concha <jose@zeroc.com>
17   Copyright (c) 2018      Marco Maggi <marco.maggi-ipsu@poste.it>
18   Copyright (c) 2019      David Loffredo <loffredo@steptools.com>
19   Copyright (c) 2020      Tim Gates <tim.gates@iress.com>
20   Copyright (c) 2021      Donghee Na <donghee.na@python.org>
21   Copyright (c) 2023-2024 Sony Corporation / Snild Dolkow <snild@sony.com>
22   Licensed under the MIT license:
23
24   Permission is  hereby granted,  free of charge,  to any  person obtaining
25   a  copy  of  this  software   and  associated  documentation  files  (the
26   "Software"),  to  deal in  the  Software  without restriction,  including
27   without  limitation the  rights  to use,  copy,  modify, merge,  publish,
28   distribute, sublicense, and/or sell copies of the Software, and to permit
29   persons  to whom  the Software  is  furnished to  do so,  subject to  the
30   following conditions:
31
32   The above copyright  notice and this permission notice  shall be included
33   in all copies or substantial portions of the Software.
34
35   THE  SOFTWARE  IS  PROVIDED  "AS  IS",  WITHOUT  WARRANTY  OF  ANY  KIND,
36   EXPRESS  OR IMPLIED,  INCLUDING  BUT  NOT LIMITED  TO  THE WARRANTIES  OF
37   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
38   NO EVENT SHALL THE AUTHORS OR  COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
39   DAMAGES OR  OTHER LIABILITY, WHETHER  IN AN  ACTION OF CONTRACT,  TORT OR
40   OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
41   USE OR OTHER DEALINGS IN THE SOFTWARE.
42*/
43
44#if defined(NDEBUG)
45#  undef NDEBUG /* because test suite relies on assert(...) at the moment */
46#endif
47
48#include <stdio.h>
49#include <string.h>
50#include <assert.h>
51
52#include "expat_config.h"
53
54#include "expat.h"
55#include "internal.h"
56#include "chardata.h"
57#include "structdata.h"
58#include "common.h"
59#include "handlers.h"
60
61/* Global variables for user parameter settings tests */
62/* Variable holding the expected handler userData */
63const void *g_handler_data = NULL;
64/* Count of the number of times the comment handler has been invoked */
65int g_comment_count = 0;
66/* Count of the number of skipped entities */
67int g_skip_count = 0;
68/* Count of the number of times the XML declaration handler is invoked */
69int g_xdecl_count = 0;
70
71/* Start/End Element Handlers */
72
73void XMLCALL
74start_element_event_handler(void *userData, const XML_Char *name,
75                            const XML_Char **atts) {
76  UNUSED_P(atts);
77  CharData_AppendXMLChars((CharData *)userData, name, -1);
78}
79
80void XMLCALL
81end_element_event_handler(void *userData, const XML_Char *name) {
82  CharData *storage = (CharData *)userData;
83  CharData_AppendXMLChars(storage, XCS("/"), 1);
84  CharData_AppendXMLChars(storage, name, -1);
85}
86
87void XMLCALL
88start_element_event_handler2(void *userData, const XML_Char *name,
89                             const XML_Char **attr) {
90  StructData *storage = (StructData *)userData;
91  UNUSED_P(attr);
92  StructData_AddItem(storage, name, XML_GetCurrentColumnNumber(g_parser),
93                     XML_GetCurrentLineNumber(g_parser), STRUCT_START_TAG);
94}
95
96void XMLCALL
97end_element_event_handler2(void *userData, const XML_Char *name) {
98  StructData *storage = (StructData *)userData;
99  StructData_AddItem(storage, name, XML_GetCurrentColumnNumber(g_parser),
100                     XML_GetCurrentLineNumber(g_parser), STRUCT_END_TAG);
101}
102
103void XMLCALL
104counting_start_element_handler(void *userData, const XML_Char *name,
105                               const XML_Char **atts) {
106  ElementInfo *info = (ElementInfo *)userData;
107  AttrInfo *attr;
108  int count, id, i;
109
110  while (info->name != NULL) {
111    if (! xcstrcmp(name, info->name))
112      break;
113    info++;
114  }
115  if (info->name == NULL)
116    fail("Element not recognised");
117  /* The attribute count is twice what you might expect.  It is a
118   * count of items in atts, an array which contains alternating
119   * attribute names and attribute values.  For the naive user this
120   * is possibly a little unexpected, but it is what the
121   * documentation in expat.h tells us to expect.
122   */
123  count = XML_GetSpecifiedAttributeCount(g_parser);
124  if (info->attr_count * 2 != count) {
125    fail("Not got expected attribute count");
126    return;
127  }
128  id = XML_GetIdAttributeIndex(g_parser);
129  if (id == -1 && info->id_name != NULL) {
130    fail("ID not present");
131    return;
132  }
133  if (id != -1 && xcstrcmp(atts[id], info->id_name)) {
134    fail("ID does not have the correct name");
135    return;
136  }
137  for (i = 0; i < info->attr_count; i++) {
138    attr = info->attributes;
139    while (attr->name != NULL) {
140      if (! xcstrcmp(atts[0], attr->name))
141        break;
142      attr++;
143    }
144    if (attr->name == NULL) {
145      fail("Attribute not recognised");
146      return;
147    }
148    if (xcstrcmp(atts[1], attr->value)) {
149      fail("Attribute has wrong value");
150      return;
151    }
152    /* Remember, two entries in atts per attribute (see above) */
153    atts += 2;
154  }
155}
156
157void XMLCALL
158suspending_end_handler(void *userData, const XML_Char *s) {
159  UNUSED_P(s);
160  XML_StopParser((XML_Parser)userData, 1);
161}
162
163void XMLCALL
164start_element_suspender(void *userData, const XML_Char *name,
165                        const XML_Char **atts) {
166  UNUSED_P(userData);
167  UNUSED_P(atts);
168  if (! xcstrcmp(name, XCS("suspend")))
169    XML_StopParser(g_parser, XML_TRUE);
170  if (! xcstrcmp(name, XCS("abort")))
171    XML_StopParser(g_parser, XML_FALSE);
172}
173
174/* Check that an element name and attribute name match the expected values.
175   The expected values are passed as an array reference of string pointers
176   provided as the userData argument; the first is the expected
177   element name, and the second is the expected attribute name.
178*/
179int g_triplet_start_flag = XML_FALSE;
180int g_triplet_end_flag = XML_FALSE;
181
182void XMLCALL
183triplet_start_checker(void *userData, const XML_Char *name,
184                      const XML_Char **atts) {
185  XML_Char **elemstr = (XML_Char **)userData;
186  char buffer[1024];
187  if (xcstrcmp(elemstr[0], name) != 0) {
188    snprintf(buffer, sizeof(buffer),
189             "unexpected start string: '%" XML_FMT_STR "'", name);
190    fail(buffer);
191  }
192  if (xcstrcmp(elemstr[1], atts[0]) != 0) {
193    snprintf(buffer, sizeof(buffer),
194             "unexpected attribute string: '%" XML_FMT_STR "'", atts[0]);
195    fail(buffer);
196  }
197  g_triplet_start_flag = XML_TRUE;
198}
199
200/* Check that the element name passed to the end-element handler matches
201   the expected value.  The expected value is passed as the first element
202   in an array of strings passed as the userData argument.
203*/
204void XMLCALL
205triplet_end_checker(void *userData, const XML_Char *name) {
206  XML_Char **elemstr = (XML_Char **)userData;
207  if (xcstrcmp(elemstr[0], name) != 0) {
208    char buffer[1024];
209    snprintf(buffer, sizeof(buffer),
210             "unexpected end string: '%" XML_FMT_STR "'", name);
211    fail(buffer);
212  }
213  g_triplet_end_flag = XML_TRUE;
214}
215
216void XMLCALL
217overwrite_start_checker(void *userData, const XML_Char *name,
218                        const XML_Char **atts) {
219  CharData *storage = (CharData *)userData;
220  CharData_AppendXMLChars(storage, XCS("start "), 6);
221  CharData_AppendXMLChars(storage, name, -1);
222  while (*atts != NULL) {
223    CharData_AppendXMLChars(storage, XCS("\nattribute "), 11);
224    CharData_AppendXMLChars(storage, *atts, -1);
225    atts += 2;
226  }
227  CharData_AppendXMLChars(storage, XCS("\n"), 1);
228}
229
230void XMLCALL
231overwrite_end_checker(void *userData, const XML_Char *name) {
232  CharData *storage = (CharData *)userData;
233  CharData_AppendXMLChars(storage, XCS("end "), 4);
234  CharData_AppendXMLChars(storage, name, -1);
235  CharData_AppendXMLChars(storage, XCS("\n"), 1);
236}
237
238void XMLCALL
239start_element_fail(void *userData, const XML_Char *name,
240                   const XML_Char **atts) {
241  UNUSED_P(userData);
242  UNUSED_P(name);
243  UNUSED_P(atts);
244
245  /* We should never get here. */
246  fail("should never reach start_element_fail()");
247}
248
249void XMLCALL
250start_ns_clearing_start_element(void *userData, const XML_Char *prefix,
251                                const XML_Char *uri) {
252  UNUSED_P(prefix);
253  UNUSED_P(uri);
254  XML_SetStartElementHandler((XML_Parser)userData, NULL);
255}
256
257void XMLCALL
258start_element_issue_240(void *userData, const XML_Char *name,
259                        const XML_Char **atts) {
260  DataIssue240 *mydata = (DataIssue240 *)userData;
261  UNUSED_P(name);
262  UNUSED_P(atts);
263  mydata->deep++;
264}
265
266void XMLCALL
267end_element_issue_240(void *userData, const XML_Char *name) {
268  DataIssue240 *mydata = (DataIssue240 *)userData;
269
270  UNUSED_P(name);
271  mydata->deep--;
272  if (mydata->deep == 0) {
273    XML_StopParser(mydata->parser, 0);
274  }
275}
276
277/* Text encoding handlers */
278
279int XMLCALL
280UnknownEncodingHandler(void *data, const XML_Char *encoding,
281                       XML_Encoding *info) {
282  UNUSED_P(data);
283  if (xcstrcmp(encoding, XCS("unsupported-encoding")) == 0) {
284    int i;
285    for (i = 0; i < 256; ++i)
286      info->map[i] = i;
287    info->data = NULL;
288    info->convert = NULL;
289    info->release = NULL;
290    return XML_STATUS_OK;
291  }
292  return XML_STATUS_ERROR;
293}
294
295static void
296dummy_release(void *data) {
297  UNUSED_P(data);
298}
299
300int XMLCALL
301UnrecognisedEncodingHandler(void *data, const XML_Char *encoding,
302                            XML_Encoding *info) {
303  UNUSED_P(data);
304  UNUSED_P(encoding);
305  info->data = NULL;
306  info->convert = NULL;
307  info->release = dummy_release;
308  return XML_STATUS_ERROR;
309}
310
311int XMLCALL
312unknown_released_encoding_handler(void *data, const XML_Char *encoding,
313                                  XML_Encoding *info) {
314  UNUSED_P(data);
315  if (! xcstrcmp(encoding, XCS("unsupported-encoding"))) {
316    int i;
317
318    for (i = 0; i < 256; i++)
319      info->map[i] = i;
320    info->data = NULL;
321    info->convert = NULL;
322    info->release = dummy_release;
323    return XML_STATUS_OK;
324  }
325  return XML_STATUS_ERROR;
326}
327
328static int XMLCALL
329failing_converter(void *data, const char *s) {
330  UNUSED_P(data);
331  UNUSED_P(s);
332  /* Always claim to have failed */
333  return -1;
334}
335
336static int XMLCALL
337prefix_converter(void *data, const char *s) {
338  UNUSED_P(data);
339  /* If the first byte is 0xff, raise an error */
340  if (s[0] == (char)-1)
341    return -1;
342  /* Just add the low bits of the first byte to the second */
343  return (s[1] + (s[0] & 0x7f)) & 0x01ff;
344}
345
346int XMLCALL
347MiscEncodingHandler(void *data, const XML_Char *encoding, XML_Encoding *info) {
348  int i;
349  int high_map = -2; /* Assume a 2-byte sequence */
350
351  if (! xcstrcmp(encoding, XCS("invalid-9"))
352      || ! xcstrcmp(encoding, XCS("ascii-like"))
353      || ! xcstrcmp(encoding, XCS("invalid-len"))
354      || ! xcstrcmp(encoding, XCS("invalid-a"))
355      || ! xcstrcmp(encoding, XCS("invalid-surrogate"))
356      || ! xcstrcmp(encoding, XCS("invalid-high")))
357    high_map = -1;
358
359  for (i = 0; i < 128; ++i)
360    info->map[i] = i;
361  for (; i < 256; ++i)
362    info->map[i] = high_map;
363
364  /* If required, put an invalid value in the ASCII entries */
365  if (! xcstrcmp(encoding, XCS("invalid-9")))
366    info->map[9] = 5;
367  /* If required, have a top-bit set character starts a 5-byte sequence */
368  if (! xcstrcmp(encoding, XCS("invalid-len")))
369    info->map[0x81] = -5;
370  /* If required, make a top-bit set character a valid ASCII character */
371  if (! xcstrcmp(encoding, XCS("invalid-a")))
372    info->map[0x82] = 'a';
373  /* If required, give a top-bit set character a forbidden value,
374   * what would otherwise be the first of a surrogate pair.
375   */
376  if (! xcstrcmp(encoding, XCS("invalid-surrogate")))
377    info->map[0x83] = 0xd801;
378  /* If required, give a top-bit set character too high a value */
379  if (! xcstrcmp(encoding, XCS("invalid-high")))
380    info->map[0x84] = 0x010101;
381
382  info->data = data;
383  info->release = NULL;
384  if (! xcstrcmp(encoding, XCS("failing-conv")))
385    info->convert = failing_converter;
386  else if (! xcstrcmp(encoding, XCS("prefix-conv")))
387    info->convert = prefix_converter;
388  else
389    info->convert = NULL;
390  return XML_STATUS_OK;
391}
392
393int XMLCALL
394long_encoding_handler(void *userData, const XML_Char *encoding,
395                      XML_Encoding *info) {
396  int i;
397
398  UNUSED_P(userData);
399  UNUSED_P(encoding);
400  for (i = 0; i < 256; i++)
401    info->map[i] = i;
402  info->data = NULL;
403  info->convert = NULL;
404  info->release = NULL;
405  return XML_STATUS_OK;
406}
407
408/* External Entity Handlers */
409
410int XMLCALL
411external_entity_optioner(XML_Parser parser, const XML_Char *context,
412                         const XML_Char *base, const XML_Char *systemId,
413                         const XML_Char *publicId) {
414  ExtOption *options = (ExtOption *)XML_GetUserData(parser);
415  XML_Parser ext_parser;
416
417  UNUSED_P(base);
418  UNUSED_P(publicId);
419  while (options->parse_text != NULL) {
420    if (! xcstrcmp(systemId, options->system_id)) {
421      enum XML_Status rc;
422      ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
423      if (ext_parser == NULL)
424        return XML_STATUS_ERROR;
425      rc = _XML_Parse_SINGLE_BYTES(ext_parser, options->parse_text,
426                                   (int)strlen(options->parse_text), XML_TRUE);
427      XML_ParserFree(ext_parser);
428      return rc;
429    }
430    options++;
431  }
432  fail("No suitable option found");
433  return XML_STATUS_ERROR;
434}
435
436int XMLCALL
437external_entity_loader(XML_Parser parser, const XML_Char *context,
438                       const XML_Char *base, const XML_Char *systemId,
439                       const XML_Char *publicId) {
440  ExtTest *test_data = (ExtTest *)XML_GetUserData(parser);
441  XML_Parser extparser;
442
443  UNUSED_P(base);
444  UNUSED_P(systemId);
445  UNUSED_P(publicId);
446  extparser = XML_ExternalEntityParserCreate(parser, context, NULL);
447  if (extparser == NULL)
448    fail("Could not create external entity parser.");
449  if (test_data->encoding != NULL) {
450    if (! XML_SetEncoding(extparser, test_data->encoding))
451      fail("XML_SetEncoding() ignored for external entity");
452  }
453  if (_XML_Parse_SINGLE_BYTES(extparser, test_data->parse_text,
454                              (int)strlen(test_data->parse_text), XML_TRUE)
455      == XML_STATUS_ERROR) {
456    xml_failure(extparser);
457    return XML_STATUS_ERROR;
458  }
459  XML_ParserFree(extparser);
460  return XML_STATUS_OK;
461}
462
463int XMLCALL
464external_entity_faulter(XML_Parser parser, const XML_Char *context,
465                        const XML_Char *base, const XML_Char *systemId,
466                        const XML_Char *publicId) {
467  XML_Parser ext_parser;
468  ExtFaults *fault = (ExtFaults *)XML_GetUserData(parser);
469
470  UNUSED_P(base);
471  UNUSED_P(systemId);
472  UNUSED_P(publicId);
473  ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
474  if (ext_parser == NULL)
475    fail("Could not create external entity parser");
476  if (fault->encoding != NULL) {
477    if (! XML_SetEncoding(ext_parser, fault->encoding))
478      fail("XML_SetEncoding failed");
479  }
480  if (_XML_Parse_SINGLE_BYTES(ext_parser, fault->parse_text,
481                              (int)strlen(fault->parse_text), XML_TRUE)
482      != XML_STATUS_ERROR)
483    fail(fault->fail_text);
484  if (XML_GetErrorCode(ext_parser) != fault->error)
485    xml_failure(ext_parser);
486
487  XML_ParserFree(ext_parser);
488  return XML_STATUS_ERROR;
489}
490
491int XMLCALL
492external_entity_null_loader(XML_Parser parser, const XML_Char *context,
493                            const XML_Char *base, const XML_Char *systemId,
494                            const XML_Char *publicId) {
495  UNUSED_P(parser);
496  UNUSED_P(context);
497  UNUSED_P(base);
498  UNUSED_P(systemId);
499  UNUSED_P(publicId);
500  return XML_STATUS_OK;
501}
502
503int XMLCALL
504external_entity_resetter(XML_Parser parser, const XML_Char *context,
505                         const XML_Char *base, const XML_Char *systemId,
506                         const XML_Char *publicId) {
507  const char *text = "<!ELEMENT doc (#PCDATA)*>";
508  XML_Parser ext_parser;
509  XML_ParsingStatus status;
510
511  UNUSED_P(base);
512  UNUSED_P(systemId);
513  UNUSED_P(publicId);
514  ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
515  if (ext_parser == NULL)
516    fail("Could not create external entity parser");
517  XML_GetParsingStatus(ext_parser, &status);
518  if (status.parsing != XML_INITIALIZED) {
519    fail("Parsing status is not INITIALIZED");
520    return XML_STATUS_ERROR;
521  }
522  if (_XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE)
523      == XML_STATUS_ERROR) {
524    xml_failure(parser);
525    return XML_STATUS_ERROR;
526  }
527  XML_GetParsingStatus(ext_parser, &status);
528  if (status.parsing != XML_FINISHED) {
529    fail("Parsing status is not FINISHED");
530    return XML_STATUS_ERROR;
531  }
532  /* Check we can't parse here */
533  if (_XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE)
534      != XML_STATUS_ERROR)
535    fail("Parsing when finished not faulted");
536  if (XML_GetErrorCode(ext_parser) != XML_ERROR_FINISHED)
537    fail("Parsing when finished faulted with wrong code");
538  XML_ParserReset(ext_parser, NULL);
539  XML_GetParsingStatus(ext_parser, &status);
540  if (status.parsing != XML_FINISHED) {
541    fail("Parsing status not still FINISHED");
542    return XML_STATUS_ERROR;
543  }
544  XML_ParserFree(ext_parser);
545  return XML_STATUS_OK;
546}
547
548void XMLCALL
549entity_suspending_decl_handler(void *userData, const XML_Char *name,
550                               XML_Content *model) {
551  XML_Parser ext_parser = (XML_Parser)userData;
552
553  UNUSED_P(name);
554  if (XML_StopParser(ext_parser, XML_TRUE) != XML_STATUS_ERROR)
555    fail("Attempting to suspend a subordinate parser not faulted");
556  if (XML_GetErrorCode(ext_parser) != XML_ERROR_SUSPEND_PE)
557    fail("Suspending subordinate parser get wrong code");
558  XML_SetElementDeclHandler(ext_parser, NULL);
559  XML_FreeContentModel(g_parser, model);
560}
561
562int XMLCALL
563external_entity_suspender(XML_Parser parser, const XML_Char *context,
564                          const XML_Char *base, const XML_Char *systemId,
565                          const XML_Char *publicId) {
566  const char *text = "<!ELEMENT doc (#PCDATA)*>";
567  XML_Parser ext_parser;
568
569  UNUSED_P(base);
570  UNUSED_P(systemId);
571  UNUSED_P(publicId);
572  ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
573  if (ext_parser == NULL)
574    fail("Could not create external entity parser");
575  XML_SetElementDeclHandler(ext_parser, entity_suspending_decl_handler);
576  XML_SetUserData(ext_parser, ext_parser);
577  if (_XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE)
578      == XML_STATUS_ERROR) {
579    xml_failure(ext_parser);
580    return XML_STATUS_ERROR;
581  }
582  XML_ParserFree(ext_parser);
583  return XML_STATUS_OK;
584}
585
586void XMLCALL
587entity_suspending_xdecl_handler(void *userData, const XML_Char *version,
588                                const XML_Char *encoding, int standalone) {
589  XML_Parser ext_parser = (XML_Parser)userData;
590
591  UNUSED_P(version);
592  UNUSED_P(encoding);
593  UNUSED_P(standalone);
594  XML_StopParser(ext_parser, g_resumable);
595  XML_SetXmlDeclHandler(ext_parser, NULL);
596}
597
598int XMLCALL
599external_entity_suspend_xmldecl(XML_Parser parser, const XML_Char *context,
600                                const XML_Char *base, const XML_Char *systemId,
601                                const XML_Char *publicId) {
602  const char *text = "<?xml version='1.0' encoding='us-ascii'?>";
603  XML_Parser ext_parser;
604  XML_ParsingStatus status;
605  enum XML_Status rc;
606
607  UNUSED_P(base);
608  UNUSED_P(systemId);
609  UNUSED_P(publicId);
610  ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
611  if (ext_parser == NULL)
612    fail("Could not create external entity parser");
613  XML_SetXmlDeclHandler(ext_parser, entity_suspending_xdecl_handler);
614  XML_SetUserData(ext_parser, ext_parser);
615  rc = _XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE);
616  XML_GetParsingStatus(ext_parser, &status);
617  if (g_resumable) {
618    if (rc == XML_STATUS_ERROR)
619      xml_failure(ext_parser);
620    if (status.parsing != XML_SUSPENDED)
621      fail("Ext Parsing status not SUSPENDED");
622  } else {
623    if (rc != XML_STATUS_ERROR)
624      fail("Ext parsing not aborted");
625    if (XML_GetErrorCode(ext_parser) != XML_ERROR_ABORTED)
626      xml_failure(ext_parser);
627    if (status.parsing != XML_FINISHED)
628      fail("Ext Parsing status not FINISHED");
629  }
630
631  XML_ParserFree(ext_parser);
632  return XML_STATUS_OK;
633}
634
635int XMLCALL
636external_entity_suspending_faulter(XML_Parser parser, const XML_Char *context,
637                                   const XML_Char *base,
638                                   const XML_Char *systemId,
639                                   const XML_Char *publicId) {
640  XML_Parser ext_parser;
641  ExtFaults *fault = (ExtFaults *)XML_GetUserData(parser);
642  void *buffer;
643  int parse_len = (int)strlen(fault->parse_text);
644
645  UNUSED_P(base);
646  UNUSED_P(systemId);
647  UNUSED_P(publicId);
648  ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
649  if (ext_parser == NULL)
650    fail("Could not create external entity parser");
651  XML_SetXmlDeclHandler(ext_parser, entity_suspending_xdecl_handler);
652  XML_SetUserData(ext_parser, ext_parser);
653  g_resumable = XML_TRUE;
654  buffer = XML_GetBuffer(ext_parser, parse_len);
655  if (buffer == NULL)
656    fail("Could not allocate parse buffer");
657  assert(buffer != NULL);
658  memcpy(buffer, fault->parse_text, parse_len);
659  if (XML_ParseBuffer(ext_parser, parse_len, XML_FALSE) != XML_STATUS_SUSPENDED)
660    fail("XML declaration did not suspend");
661  if (XML_ResumeParser(ext_parser) != XML_STATUS_OK)
662    xml_failure(ext_parser);
663  if (XML_ParseBuffer(ext_parser, 0, XML_TRUE) != XML_STATUS_ERROR)
664    fail(fault->fail_text);
665  if (XML_GetErrorCode(ext_parser) != fault->error)
666    xml_failure(ext_parser);
667
668  XML_ParserFree(ext_parser);
669  return XML_STATUS_ERROR;
670}
671
672int XMLCALL
673external_entity_failer__if_not_xml_ge(XML_Parser parser,
674                                      const XML_Char *context,
675                                      const XML_Char *base,
676                                      const XML_Char *systemId,
677                                      const XML_Char *publicId) {
678  UNUSED_P(parser);
679  UNUSED_P(context);
680  UNUSED_P(base);
681  UNUSED_P(systemId);
682  UNUSED_P(publicId);
683#if XML_GE == 0
684  fail(
685      "Function external_entity_suspending_failer was called despite XML_GE==0.");
686#endif
687  return XML_STATUS_OK;
688}
689
690int XMLCALL
691external_entity_cr_catcher(XML_Parser parser, const XML_Char *context,
692                           const XML_Char *base, const XML_Char *systemId,
693                           const XML_Char *publicId) {
694  const char *text = "\r";
695  XML_Parser ext_parser;
696
697  UNUSED_P(base);
698  UNUSED_P(systemId);
699  UNUSED_P(publicId);
700  ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
701  if (ext_parser == NULL)
702    fail("Could not create external entity parser");
703  XML_SetCharacterDataHandler(ext_parser, cr_cdata_handler);
704  if (_XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE)
705      == XML_STATUS_ERROR)
706    xml_failure(ext_parser);
707  XML_ParserFree(ext_parser);
708  return XML_STATUS_OK;
709}
710
711int XMLCALL
712external_entity_bad_cr_catcher(XML_Parser parser, const XML_Char *context,
713                               const XML_Char *base, const XML_Char *systemId,
714                               const XML_Char *publicId) {
715  const char *text = "<tag>\r";
716  XML_Parser ext_parser;
717
718  UNUSED_P(base);
719  UNUSED_P(systemId);
720  UNUSED_P(publicId);
721  ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
722  if (ext_parser == NULL)
723    fail("Could not create external entity parser");
724  XML_SetCharacterDataHandler(ext_parser, cr_cdata_handler);
725  if (_XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE)
726      == XML_STATUS_OK)
727    fail("Async entity error not caught");
728  if (XML_GetErrorCode(ext_parser) != XML_ERROR_ASYNC_ENTITY)
729    xml_failure(ext_parser);
730  XML_ParserFree(ext_parser);
731  return XML_STATUS_OK;
732}
733
734int XMLCALL
735external_entity_rsqb_catcher(XML_Parser parser, const XML_Char *context,
736                             const XML_Char *base, const XML_Char *systemId,
737                             const XML_Char *publicId) {
738  const char *text = "<tag>]";
739  XML_Parser ext_parser;
740
741  UNUSED_P(base);
742  UNUSED_P(systemId);
743  UNUSED_P(publicId);
744  ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
745  if (ext_parser == NULL)
746    fail("Could not create external entity parser");
747  XML_SetCharacterDataHandler(ext_parser, rsqb_handler);
748  if (_XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE)
749      != XML_STATUS_ERROR)
750    fail("Async entity error not caught");
751  if (XML_GetErrorCode(ext_parser) != XML_ERROR_ASYNC_ENTITY)
752    xml_failure(ext_parser);
753  XML_ParserFree(ext_parser);
754  return XML_STATUS_OK;
755}
756
757int XMLCALL
758external_entity_good_cdata_ascii(XML_Parser parser, const XML_Char *context,
759                                 const XML_Char *base, const XML_Char *systemId,
760                                 const XML_Char *publicId) {
761  const char *text = "<a><![CDATA[<greeting>Hello, world!</greeting>]]></a>";
762  const XML_Char *expected = XCS("<greeting>Hello, world!</greeting>");
763  CharData storage;
764  XML_Parser ext_parser;
765
766  UNUSED_P(base);
767  UNUSED_P(systemId);
768  UNUSED_P(publicId);
769  CharData_Init(&storage);
770  ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
771  if (ext_parser == NULL)
772    fail("Could not create external entity parser");
773  XML_SetUserData(ext_parser, &storage);
774  XML_SetCharacterDataHandler(ext_parser, accumulate_characters);
775
776  if (_XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE)
777      == XML_STATUS_ERROR)
778    xml_failure(ext_parser);
779  CharData_CheckXMLChars(&storage, expected);
780
781  XML_ParserFree(ext_parser);
782  return XML_STATUS_OK;
783}
784
785int XMLCALL
786external_entity_param_checker(XML_Parser parser, const XML_Char *context,
787                              const XML_Char *base, const XML_Char *systemId,
788                              const XML_Char *publicId) {
789  const char *text = "<!-- Subordinate parser -->\n"
790                     "<!ELEMENT doc (#PCDATA)*>";
791  XML_Parser ext_parser;
792
793  UNUSED_P(base);
794  UNUSED_P(systemId);
795  UNUSED_P(publicId);
796  ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
797  if (ext_parser == NULL)
798    fail("Could not create external entity parser");
799  g_handler_data = ext_parser;
800  if (_XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE)
801      == XML_STATUS_ERROR) {
802    xml_failure(parser);
803    return XML_STATUS_ERROR;
804  }
805  g_handler_data = parser;
806  XML_ParserFree(ext_parser);
807  return XML_STATUS_OK;
808}
809
810int XMLCALL
811external_entity_ref_param_checker(XML_Parser parameter, const XML_Char *context,
812                                  const XML_Char *base,
813                                  const XML_Char *systemId,
814                                  const XML_Char *publicId) {
815  const char *text = "<!ELEMENT doc (#PCDATA)*>";
816  XML_Parser ext_parser;
817
818  UNUSED_P(base);
819  UNUSED_P(systemId);
820  UNUSED_P(publicId);
821  if ((void *)parameter != g_handler_data)
822    fail("External entity ref handler parameter not correct");
823
824  /* Here we use the global 'parser' variable */
825  ext_parser = XML_ExternalEntityParserCreate(g_parser, context, NULL);
826  if (ext_parser == NULL)
827    fail("Could not create external entity parser");
828  if (_XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE)
829      == XML_STATUS_ERROR)
830    xml_failure(ext_parser);
831
832  XML_ParserFree(ext_parser);
833  return XML_STATUS_OK;
834}
835
836int XMLCALL
837external_entity_param(XML_Parser parser, const XML_Char *context,
838                      const XML_Char *base, const XML_Char *systemId,
839                      const XML_Char *publicId) {
840  const char *text1 = "<!ELEMENT doc EMPTY>\n"
841                      "<!ENTITY % e1 SYSTEM '004-2.ent'>\n"
842                      "<!ENTITY % e2 '%e1;'>\n"
843                      "%e1;\n";
844  const char *text2 = "<!ELEMENT el EMPTY>\n"
845                      "<el/>\n";
846  XML_Parser ext_parser;
847
848  UNUSED_P(base);
849  UNUSED_P(publicId);
850  if (systemId == NULL)
851    return XML_STATUS_OK;
852
853  ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
854  if (ext_parser == NULL)
855    fail("Could not create external entity parser");
856
857  if (! xcstrcmp(systemId, XCS("004-1.ent"))) {
858    if (_XML_Parse_SINGLE_BYTES(ext_parser, text1, (int)strlen(text1), XML_TRUE)
859        != XML_STATUS_ERROR)
860      fail("Inner DTD with invalid tag not rejected");
861    if (XML_GetErrorCode(ext_parser) != XML_ERROR_EXTERNAL_ENTITY_HANDLING)
862      xml_failure(ext_parser);
863  } else if (! xcstrcmp(systemId, XCS("004-2.ent"))) {
864    if (_XML_Parse_SINGLE_BYTES(ext_parser, text2, (int)strlen(text2), XML_TRUE)
865        != XML_STATUS_ERROR)
866      fail("Invalid tag in external param not rejected");
867    if (XML_GetErrorCode(ext_parser) != XML_ERROR_SYNTAX)
868      xml_failure(ext_parser);
869  } else {
870    fail("Unknown system ID");
871  }
872
873  XML_ParserFree(ext_parser);
874  return XML_STATUS_ERROR;
875}
876
877int XMLCALL
878external_entity_load_ignore(XML_Parser parser, const XML_Char *context,
879                            const XML_Char *base, const XML_Char *systemId,
880                            const XML_Char *publicId) {
881  const char *text = "<![IGNORE[<!ELEMENT e (#PCDATA)*>]]>";
882  XML_Parser ext_parser;
883
884  UNUSED_P(base);
885  UNUSED_P(systemId);
886  UNUSED_P(publicId);
887  ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
888  if (ext_parser == NULL)
889    fail("Could not create external entity parser");
890  if (_XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE)
891      == XML_STATUS_ERROR)
892    xml_failure(parser);
893
894  XML_ParserFree(ext_parser);
895  return XML_STATUS_OK;
896}
897
898int XMLCALL
899external_entity_load_ignore_utf16(XML_Parser parser, const XML_Char *context,
900                                  const XML_Char *base,
901                                  const XML_Char *systemId,
902                                  const XML_Char *publicId) {
903  const char text[] =
904      /* <![IGNORE[<!ELEMENT e (#PCDATA)*>]]> */
905      "<\0!\0[\0I\0G\0N\0O\0R\0E\0[\0"
906      "<\0!\0E\0L\0E\0M\0E\0N\0T\0 \0e\0 \0"
907      "(\0#\0P\0C\0D\0A\0T\0A\0)\0*\0>\0]\0]\0>\0";
908  XML_Parser ext_parser;
909
910  UNUSED_P(base);
911  UNUSED_P(systemId);
912  UNUSED_P(publicId);
913  ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
914  if (ext_parser == NULL)
915    fail("Could not create external entity parser");
916  if (_XML_Parse_SINGLE_BYTES(ext_parser, text, (int)sizeof(text) - 1, XML_TRUE)
917      == XML_STATUS_ERROR)
918    xml_failure(parser);
919
920  XML_ParserFree(ext_parser);
921  return XML_STATUS_OK;
922}
923
924int XMLCALL
925external_entity_load_ignore_utf16_be(XML_Parser parser, const XML_Char *context,
926                                     const XML_Char *base,
927                                     const XML_Char *systemId,
928                                     const XML_Char *publicId) {
929  const char text[] =
930      /* <![IGNORE[<!ELEMENT e (#PCDATA)*>]]> */
931      "\0<\0!\0[\0I\0G\0N\0O\0R\0E\0["
932      "\0<\0!\0E\0L\0E\0M\0E\0N\0T\0 \0e\0 "
933      "\0(\0#\0P\0C\0D\0A\0T\0A\0)\0*\0>\0]\0]\0>";
934  XML_Parser ext_parser;
935
936  UNUSED_P(base);
937  UNUSED_P(systemId);
938  UNUSED_P(publicId);
939  ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
940  if (ext_parser == NULL)
941    fail("Could not create external entity parser");
942  if (_XML_Parse_SINGLE_BYTES(ext_parser, text, (int)sizeof(text) - 1, XML_TRUE)
943      == XML_STATUS_ERROR)
944    xml_failure(parser);
945
946  XML_ParserFree(ext_parser);
947  return XML_STATUS_OK;
948}
949
950int XMLCALL
951external_entity_valuer(XML_Parser parser, const XML_Char *context,
952                       const XML_Char *base, const XML_Char *systemId,
953                       const XML_Char *publicId) {
954  const char *text1 = "<!ELEMENT doc EMPTY>\n"
955                      "<!ENTITY % e1 SYSTEM '004-2.ent'>\n"
956                      "<!ENTITY % e2 '%e1;'>\n"
957                      "%e1;\n";
958  XML_Parser ext_parser;
959
960  UNUSED_P(base);
961  UNUSED_P(publicId);
962  if (systemId == NULL)
963    return XML_STATUS_OK;
964  ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
965  if (ext_parser == NULL)
966    fail("Could not create external entity parser");
967  if (! xcstrcmp(systemId, XCS("004-1.ent"))) {
968    if (_XML_Parse_SINGLE_BYTES(ext_parser, text1, (int)strlen(text1), XML_TRUE)
969        == XML_STATUS_ERROR)
970      xml_failure(ext_parser);
971  } else if (! xcstrcmp(systemId, XCS("004-2.ent"))) {
972    ExtFaults *fault = (ExtFaults *)XML_GetUserData(parser);
973    enum XML_Status status;
974    enum XML_Error error;
975
976    status = _XML_Parse_SINGLE_BYTES(ext_parser, fault->parse_text,
977                                     (int)strlen(fault->parse_text), XML_TRUE);
978    if (fault->error == XML_ERROR_NONE) {
979      if (status == XML_STATUS_ERROR)
980        xml_failure(ext_parser);
981    } else {
982      if (status != XML_STATUS_ERROR)
983        fail(fault->fail_text);
984      error = XML_GetErrorCode(ext_parser);
985      if (error != fault->error
986          && (fault->error != XML_ERROR_XML_DECL
987              || error != XML_ERROR_TEXT_DECL))
988        xml_failure(ext_parser);
989    }
990  }
991
992  XML_ParserFree(ext_parser);
993  return XML_STATUS_OK;
994}
995
996int XMLCALL
997external_entity_not_standalone(XML_Parser parser, const XML_Char *context,
998                               const XML_Char *base, const XML_Char *systemId,
999                               const XML_Char *publicId) {
1000  const char *text1 = "<!ELEMENT doc EMPTY>\n"
1001                      "<!ENTITY % e1 SYSTEM 'bar'>\n"
1002                      "%e1;\n";
1003  const char *text2 = "<!ATTLIST doc a1 CDATA 'value'>";
1004  XML_Parser ext_parser;
1005
1006  UNUSED_P(base);
1007  UNUSED_P(publicId);
1008  if (systemId == NULL)
1009    return XML_STATUS_OK;
1010  ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
1011  if (ext_parser == NULL)
1012    fail("Could not create external entity parser");
1013  if (! xcstrcmp(systemId, XCS("foo"))) {
1014    XML_SetNotStandaloneHandler(ext_parser, reject_not_standalone_handler);
1015    if (_XML_Parse_SINGLE_BYTES(ext_parser, text1, (int)strlen(text1), XML_TRUE)
1016        != XML_STATUS_ERROR)
1017      fail("Expected not standalone rejection");
1018    if (XML_GetErrorCode(ext_parser) != XML_ERROR_NOT_STANDALONE)
1019      xml_failure(ext_parser);
1020    XML_SetNotStandaloneHandler(ext_parser, NULL);
1021    XML_ParserFree(ext_parser);
1022    return XML_STATUS_ERROR;
1023  } else if (! xcstrcmp(systemId, XCS("bar"))) {
1024    if (_XML_Parse_SINGLE_BYTES(ext_parser, text2, (int)strlen(text2), XML_TRUE)
1025        == XML_STATUS_ERROR)
1026      xml_failure(ext_parser);
1027  }
1028
1029  XML_ParserFree(ext_parser);
1030  return XML_STATUS_OK;
1031}
1032
1033int XMLCALL
1034external_entity_value_aborter(XML_Parser parser, const XML_Char *context,
1035                              const XML_Char *base, const XML_Char *systemId,
1036                              const XML_Char *publicId) {
1037  const char *text1 = "<!ELEMENT doc EMPTY>\n"
1038                      "<!ENTITY % e1 SYSTEM '004-2.ent'>\n"
1039                      "<!ENTITY % e2 '%e1;'>\n"
1040                      "%e1;\n";
1041  const char *text2 = "<?xml version='1.0' encoding='utf-8'?>";
1042  XML_Parser ext_parser;
1043
1044  UNUSED_P(base);
1045  UNUSED_P(publicId);
1046  if (systemId == NULL)
1047    return XML_STATUS_OK;
1048  ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
1049  if (ext_parser == NULL)
1050    fail("Could not create external entity parser");
1051  if (! xcstrcmp(systemId, XCS("004-1.ent"))) {
1052    if (_XML_Parse_SINGLE_BYTES(ext_parser, text1, (int)strlen(text1), XML_TRUE)
1053        == XML_STATUS_ERROR)
1054      xml_failure(ext_parser);
1055  }
1056  if (! xcstrcmp(systemId, XCS("004-2.ent"))) {
1057    XML_SetXmlDeclHandler(ext_parser, entity_suspending_xdecl_handler);
1058    XML_SetUserData(ext_parser, ext_parser);
1059    if (_XML_Parse_SINGLE_BYTES(ext_parser, text2, (int)strlen(text2), XML_TRUE)
1060        != XML_STATUS_ERROR)
1061      fail("Aborted parse not faulted");
1062    if (XML_GetErrorCode(ext_parser) != XML_ERROR_ABORTED)
1063      xml_failure(ext_parser);
1064  }
1065
1066  XML_ParserFree(ext_parser);
1067  return XML_STATUS_OK;
1068}
1069
1070int XMLCALL
1071external_entity_public(XML_Parser parser, const XML_Char *context,
1072                       const XML_Char *base, const XML_Char *systemId,
1073                       const XML_Char *publicId) {
1074  const char *text1 = (const char *)XML_GetUserData(parser);
1075  const char *text2 = "<!ATTLIST doc a CDATA 'value'>";
1076  const char *text = NULL;
1077  XML_Parser ext_parser;
1078  int parse_res;
1079
1080  UNUSED_P(base);
1081  ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
1082  if (ext_parser == NULL)
1083    return XML_STATUS_ERROR;
1084  if (systemId != NULL && ! xcstrcmp(systemId, XCS("http://example.org/"))) {
1085    text = text1;
1086  } else if (publicId != NULL && ! xcstrcmp(publicId, XCS("foo"))) {
1087    text = text2;
1088  } else
1089    fail("Unexpected parameters to external entity parser");
1090  assert(text != NULL);
1091  parse_res
1092      = _XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE);
1093  XML_ParserFree(ext_parser);
1094  return parse_res;
1095}
1096
1097int XMLCALL
1098external_entity_devaluer(XML_Parser parser, const XML_Char *context,
1099                         const XML_Char *base, const XML_Char *systemId,
1100                         const XML_Char *publicId) {
1101  const char *text = "<!ELEMENT doc EMPTY>\n"
1102                     "<!ENTITY % e1 SYSTEM 'bar'>\n"
1103                     "%e1;\n";
1104  XML_Parser ext_parser;
1105  int clear_handler_flag = (XML_GetUserData(parser) != NULL);
1106
1107  UNUSED_P(base);
1108  UNUSED_P(publicId);
1109  if (systemId == NULL || ! xcstrcmp(systemId, XCS("bar")))
1110    return XML_STATUS_OK;
1111  if (xcstrcmp(systemId, XCS("foo")))
1112    fail("Unexpected system ID");
1113  ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
1114  if (ext_parser == NULL)
1115    fail("Could note create external entity parser");
1116  if (clear_handler_flag)
1117    XML_SetExternalEntityRefHandler(ext_parser, NULL);
1118  if (_XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE)
1119      == XML_STATUS_ERROR)
1120    xml_failure(ext_parser);
1121
1122  XML_ParserFree(ext_parser);
1123  return XML_STATUS_OK;
1124}
1125
1126int XMLCALL
1127external_entity_oneshot_loader(XML_Parser parser, const XML_Char *context,
1128                               const XML_Char *base, const XML_Char *systemId,
1129                               const XML_Char *publicId) {
1130  ExtHdlrData *test_data = (ExtHdlrData *)XML_GetUserData(parser);
1131  XML_Parser ext_parser;
1132
1133  UNUSED_P(base);
1134  UNUSED_P(systemId);
1135  UNUSED_P(publicId);
1136  ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
1137  if (ext_parser == NULL)
1138    fail("Could not create external entity parser.");
1139  /* Use the requested entity parser for further externals */
1140  XML_SetExternalEntityRefHandler(ext_parser, test_data->handler);
1141  if (_XML_Parse_SINGLE_BYTES(ext_parser, test_data->parse_text,
1142                              (int)strlen(test_data->parse_text), XML_TRUE)
1143      == XML_STATUS_ERROR) {
1144    xml_failure(ext_parser);
1145  }
1146
1147  XML_ParserFree(ext_parser);
1148  return XML_STATUS_OK;
1149}
1150
1151int XMLCALL
1152external_entity_loader2(XML_Parser parser, const XML_Char *context,
1153                        const XML_Char *base, const XML_Char *systemId,
1154                        const XML_Char *publicId) {
1155  ExtTest2 *test_data = (ExtTest2 *)XML_GetUserData(parser);
1156  XML_Parser extparser;
1157
1158  UNUSED_P(base);
1159  UNUSED_P(systemId);
1160  UNUSED_P(publicId);
1161  extparser = XML_ExternalEntityParserCreate(parser, context, NULL);
1162  if (extparser == NULL)
1163    fail("Coulr not create external entity parser");
1164  if (test_data->encoding != NULL) {
1165    if (! XML_SetEncoding(extparser, test_data->encoding))
1166      fail("XML_SetEncoding() ignored for external entity");
1167  }
1168  if (_XML_Parse_SINGLE_BYTES(extparser, test_data->parse_text,
1169                              test_data->parse_len, XML_TRUE)
1170      == XML_STATUS_ERROR) {
1171    xml_failure(extparser);
1172  }
1173
1174  XML_ParserFree(extparser);
1175  return XML_STATUS_OK;
1176}
1177
1178int XMLCALL
1179external_entity_faulter2(XML_Parser parser, const XML_Char *context,
1180                         const XML_Char *base, const XML_Char *systemId,
1181                         const XML_Char *publicId) {
1182  ExtFaults2 *test_data = (ExtFaults2 *)XML_GetUserData(parser);
1183  XML_Parser extparser;
1184
1185  UNUSED_P(base);
1186  UNUSED_P(systemId);
1187  UNUSED_P(publicId);
1188  extparser = XML_ExternalEntityParserCreate(parser, context, NULL);
1189  if (extparser == NULL)
1190    fail("Could not create external entity parser");
1191  if (test_data->encoding != NULL) {
1192    if (! XML_SetEncoding(extparser, test_data->encoding))
1193      fail("XML_SetEncoding() ignored for external entity");
1194  }
1195  if (_XML_Parse_SINGLE_BYTES(extparser, test_data->parse_text,
1196                              test_data->parse_len, XML_TRUE)
1197      != XML_STATUS_ERROR)
1198    fail(test_data->fail_text);
1199  if (XML_GetErrorCode(extparser) != test_data->error)
1200    xml_failure(extparser);
1201
1202  XML_ParserFree(extparser);
1203  return XML_STATUS_ERROR;
1204}
1205
1206int XMLCALL
1207external_entity_unfinished_attlist(XML_Parser parser, const XML_Char *context,
1208                                   const XML_Char *base,
1209                                   const XML_Char *systemId,
1210                                   const XML_Char *publicId) {
1211  const char *text = "<!ELEMENT barf ANY>\n"
1212                     "<!ATTLIST barf my_attr (blah|%blah;a|foo) #REQUIRED>\n"
1213                     "<!--COMMENT-->\n";
1214  XML_Parser ext_parser;
1215
1216  UNUSED_P(base);
1217  UNUSED_P(publicId);
1218  if (systemId == NULL)
1219    return XML_STATUS_OK;
1220
1221  ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
1222  if (ext_parser == NULL)
1223    fail("Could not create external entity parser");
1224
1225  if (_XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE)
1226      == XML_STATUS_ERROR)
1227    xml_failure(ext_parser);
1228
1229  XML_ParserFree(ext_parser);
1230  return XML_STATUS_OK;
1231}
1232
1233int XMLCALL
1234external_entity_handler(XML_Parser parser, const XML_Char *context,
1235                        const XML_Char *base, const XML_Char *systemId,
1236                        const XML_Char *publicId) {
1237  void *user_data = XML_GetUserData(parser);
1238  const char *text;
1239  XML_Parser p2;
1240
1241  UNUSED_P(base);
1242  UNUSED_P(systemId);
1243  UNUSED_P(publicId);
1244  if (user_data == NULL)
1245    text = ("<!ELEMENT doc (e+)>\n"
1246            "<!ATTLIST doc xmlns CDATA #IMPLIED>\n"
1247            "<!ELEMENT e EMPTY>\n");
1248  else
1249    text = ("<?xml version='1.0' encoding='us-ascii'?>"
1250            "<e/>");
1251
1252  /* Set user data to any non-NULL value */
1253  XML_SetUserData(parser, parser);
1254  p2 = XML_ExternalEntityParserCreate(parser, context, NULL);
1255  if (_XML_Parse_SINGLE_BYTES(p2, text, (int)strlen(text), XML_TRUE)
1256      == XML_STATUS_ERROR) {
1257    xml_failure(p2);
1258    return XML_STATUS_ERROR;
1259  }
1260  XML_ParserFree(p2);
1261  return XML_STATUS_OK;
1262}
1263
1264int XMLCALL
1265external_entity_duff_loader(XML_Parser parser, const XML_Char *context,
1266                            const XML_Char *base, const XML_Char *systemId,
1267                            const XML_Char *publicId) {
1268  XML_Parser new_parser;
1269  unsigned int i;
1270  const unsigned int max_alloc_count = 10;
1271
1272  UNUSED_P(base);
1273  UNUSED_P(systemId);
1274  UNUSED_P(publicId);
1275  /* Try a few different allocation levels */
1276  for (i = 0; i < max_alloc_count; i++) {
1277    g_allocation_count = i;
1278    new_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
1279    if (new_parser != NULL) {
1280      XML_ParserFree(new_parser);
1281      break;
1282    }
1283  }
1284  if (i == 0)
1285    fail("External parser creation ignored failing allocator");
1286  else if (i == max_alloc_count)
1287    fail("Extern parser not created with max allocation count");
1288
1289  /* Make sure other random allocation doesn't now fail */
1290  g_allocation_count = ALLOC_ALWAYS_SUCCEED;
1291
1292  /* Make sure the failure code path is executed too */
1293  return XML_STATUS_ERROR;
1294}
1295
1296int XMLCALL
1297external_entity_dbl_handler(XML_Parser parser, const XML_Char *context,
1298                            const XML_Char *base, const XML_Char *systemId,
1299                            const XML_Char *publicId) {
1300  int *pcallno = (int *)XML_GetUserData(parser);
1301  int callno = *pcallno;
1302  const char *text;
1303  XML_Parser new_parser = NULL;
1304  int i;
1305  const int max_alloc_count = 20;
1306
1307  UNUSED_P(base);
1308  UNUSED_P(systemId);
1309  UNUSED_P(publicId);
1310  if (callno == 0) {
1311    /* First time through, check how many calls to malloc occur */
1312    text = ("<!ELEMENT doc (e+)>\n"
1313            "<!ATTLIST doc xmlns CDATA #IMPLIED>\n"
1314            "<!ELEMENT e EMPTY>\n");
1315    g_allocation_count = 10000;
1316    new_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
1317    if (new_parser == NULL) {
1318      fail("Unable to allocate first external parser");
1319      return XML_STATUS_ERROR;
1320    }
1321    /* Stash the number of calls in the user data */
1322    *pcallno = 10000 - g_allocation_count;
1323  } else {
1324    text = ("<?xml version='1.0' encoding='us-ascii'?>"
1325            "<e/>");
1326    /* Try at varying levels to exercise more code paths */
1327    for (i = 0; i < max_alloc_count; i++) {
1328      g_allocation_count = callno + i;
1329      new_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
1330      if (new_parser != NULL)
1331        break;
1332    }
1333    if (i == 0) {
1334      fail("Second external parser unexpectedly created");
1335      XML_ParserFree(new_parser);
1336      return XML_STATUS_ERROR;
1337    } else if (i == max_alloc_count) {
1338      fail("Second external parser not created");
1339      return XML_STATUS_ERROR;
1340    }
1341  }
1342
1343  g_allocation_count = ALLOC_ALWAYS_SUCCEED;
1344  if (_XML_Parse_SINGLE_BYTES(new_parser, text, (int)strlen(text), XML_TRUE)
1345      == XML_STATUS_ERROR) {
1346    xml_failure(new_parser);
1347    return XML_STATUS_ERROR;
1348  }
1349  XML_ParserFree(new_parser);
1350  return XML_STATUS_OK;
1351}
1352
1353int XMLCALL
1354external_entity_dbl_handler_2(XML_Parser parser, const XML_Char *context,
1355                              const XML_Char *base, const XML_Char *systemId,
1356                              const XML_Char *publicId) {
1357  int *pcallno = (int *)XML_GetUserData(parser);
1358  int callno = *pcallno;
1359  const char *text;
1360  XML_Parser new_parser;
1361  enum XML_Status rv;
1362
1363  UNUSED_P(base);
1364  UNUSED_P(systemId);
1365  UNUSED_P(publicId);
1366  if (callno == 0) {
1367    /* Try different allocation levels for whole exercise */
1368    text = ("<!ELEMENT doc (e+)>\n"
1369            "<!ATTLIST doc xmlns CDATA #IMPLIED>\n"
1370            "<!ELEMENT e EMPTY>\n");
1371    *pcallno = 1;
1372    new_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
1373    if (new_parser == NULL)
1374      return XML_STATUS_ERROR;
1375    rv = _XML_Parse_SINGLE_BYTES(new_parser, text, (int)strlen(text), XML_TRUE);
1376  } else {
1377    /* Just run through once */
1378    text = ("<?xml version='1.0' encoding='us-ascii'?>"
1379            "<e/>");
1380    new_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
1381    if (new_parser == NULL)
1382      return XML_STATUS_ERROR;
1383    rv = _XML_Parse_SINGLE_BYTES(new_parser, text, (int)strlen(text), XML_TRUE);
1384  }
1385  XML_ParserFree(new_parser);
1386  if (rv == XML_STATUS_ERROR)
1387    return XML_STATUS_ERROR;
1388  return XML_STATUS_OK;
1389}
1390
1391int XMLCALL
1392external_entity_alloc_set_encoding(XML_Parser parser, const XML_Char *context,
1393                                   const XML_Char *base,
1394                                   const XML_Char *systemId,
1395                                   const XML_Char *publicId) {
1396  /* As for external_entity_loader() */
1397  const char *text = "<?xml encoding='iso-8859-3'?>"
1398                     "\xC3\xA9";
1399  XML_Parser ext_parser;
1400  enum XML_Status status;
1401
1402  UNUSED_P(base);
1403  UNUSED_P(systemId);
1404  UNUSED_P(publicId);
1405  ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
1406  if (ext_parser == NULL)
1407    return XML_STATUS_ERROR;
1408  if (! XML_SetEncoding(ext_parser, XCS("utf-8"))) {
1409    XML_ParserFree(ext_parser);
1410    return XML_STATUS_ERROR;
1411  }
1412  status
1413      = _XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE);
1414  XML_ParserFree(ext_parser);
1415  if (status == XML_STATUS_ERROR)
1416    return XML_STATUS_ERROR;
1417  return XML_STATUS_OK;
1418}
1419
1420int XMLCALL
1421external_entity_reallocator(XML_Parser parser, const XML_Char *context,
1422                            const XML_Char *base, const XML_Char *systemId,
1423                            const XML_Char *publicId) {
1424  const char *text = get_buffer_test_text;
1425  XML_Parser ext_parser;
1426  void *buffer;
1427  enum XML_Status status;
1428
1429  UNUSED_P(base);
1430  UNUSED_P(systemId);
1431  UNUSED_P(publicId);
1432  ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
1433  if (ext_parser == NULL)
1434    fail("Could not create external entity parser");
1435
1436  g_reallocation_count = *(int *)XML_GetUserData(parser);
1437  buffer = XML_GetBuffer(ext_parser, 1536);
1438  if (buffer == NULL)
1439    fail("Buffer allocation failed");
1440  assert(buffer != NULL);
1441  memcpy(buffer, text, strlen(text));
1442  status = XML_ParseBuffer(ext_parser, (int)strlen(text), XML_FALSE);
1443  g_reallocation_count = -1;
1444  XML_ParserFree(ext_parser);
1445  return (status == XML_STATUS_OK) ? XML_STATUS_OK : XML_STATUS_ERROR;
1446}
1447
1448int XMLCALL
1449external_entity_alloc(XML_Parser parser, const XML_Char *context,
1450                      const XML_Char *base, const XML_Char *systemId,
1451                      const XML_Char *publicId) {
1452  const char *text = (const char *)XML_GetUserData(parser);
1453  XML_Parser ext_parser;
1454  int parse_res;
1455
1456  UNUSED_P(base);
1457  UNUSED_P(systemId);
1458  UNUSED_P(publicId);
1459  ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
1460  if (ext_parser == NULL)
1461    return XML_STATUS_ERROR;
1462  parse_res
1463      = _XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE);
1464  XML_ParserFree(ext_parser);
1465  return parse_res;
1466}
1467
1468int XMLCALL
1469external_entity_parser_create_alloc_fail_handler(XML_Parser parser,
1470                                                 const XML_Char *context,
1471                                                 const XML_Char *base,
1472                                                 const XML_Char *systemId,
1473                                                 const XML_Char *publicId) {
1474  UNUSED_P(base);
1475  UNUSED_P(systemId);
1476  UNUSED_P(publicId);
1477
1478  if (context != NULL)
1479    fail("Unexpected non-NULL context");
1480
1481  // The following number intends to fail the upcoming allocation in line
1482  // "parser->m_protocolEncodingName = copyString(encodingName,
1483  // &(parser->m_mem));" in function parserInit.
1484  g_allocation_count = 3;
1485
1486  const XML_Char *const encodingName = XCS("UTF-8"); // needs something non-NULL
1487  const XML_Parser ext_parser
1488      = XML_ExternalEntityParserCreate(parser, context, encodingName);
1489  if (ext_parser != NULL)
1490    fail(
1491        "Call to XML_ExternalEntityParserCreate was expected to fail out-of-memory");
1492
1493  g_allocation_count = ALLOC_ALWAYS_SUCCEED;
1494  return XML_STATUS_ERROR;
1495}
1496
1497#if XML_GE == 1
1498int
1499accounting_external_entity_ref_handler(XML_Parser parser,
1500                                       const XML_Char *context,
1501                                       const XML_Char *base,
1502                                       const XML_Char *systemId,
1503                                       const XML_Char *publicId) {
1504  UNUSED_P(base);
1505  UNUSED_P(publicId);
1506
1507  const struct AccountingTestCase *const testCase
1508      = (const struct AccountingTestCase *)XML_GetUserData(parser);
1509
1510  const char *externalText = NULL;
1511  if (xcstrcmp(systemId, XCS("first.ent")) == 0) {
1512    externalText = testCase->firstExternalText;
1513  } else if (xcstrcmp(systemId, XCS("second.ent")) == 0) {
1514    externalText = testCase->secondExternalText;
1515  } else {
1516    assert(! "systemId is neither \"first.ent\" nor \"second.ent\"");
1517  }
1518  assert(externalText);
1519
1520  XML_Parser entParser = XML_ExternalEntityParserCreate(parser, context, 0);
1521  assert(entParser);
1522
1523  const enum XML_Status status = _XML_Parse_SINGLE_BYTES(
1524      entParser, externalText, (int)strlen(externalText), XML_TRUE);
1525
1526  XML_ParserFree(entParser);
1527  return status;
1528}
1529#endif /* XML_GE == 1 */
1530
1531/* NotStandalone handlers */
1532
1533int XMLCALL
1534reject_not_standalone_handler(void *userData) {
1535  UNUSED_P(userData);
1536  return XML_STATUS_ERROR;
1537}
1538
1539int XMLCALL
1540accept_not_standalone_handler(void *userData) {
1541  UNUSED_P(userData);
1542  return XML_STATUS_OK;
1543}
1544
1545/* Attribute List handlers */
1546void XMLCALL
1547verify_attlist_decl_handler(void *userData, const XML_Char *element_name,
1548                            const XML_Char *attr_name,
1549                            const XML_Char *attr_type,
1550                            const XML_Char *default_value, int is_required) {
1551  AttTest *at = (AttTest *)userData;
1552
1553  if (xcstrcmp(element_name, at->element_name))
1554    fail("Unexpected element name in attribute declaration");
1555  if (xcstrcmp(attr_name, at->attr_name))
1556    fail("Unexpected attribute name in attribute declaration");
1557  if (xcstrcmp(attr_type, at->attr_type))
1558    fail("Unexpected attribute type in attribute declaration");
1559  if ((default_value == NULL && at->default_value != NULL)
1560      || (default_value != NULL && at->default_value == NULL)
1561      || (default_value != NULL && xcstrcmp(default_value, at->default_value)))
1562    fail("Unexpected default value in attribute declaration");
1563  if (is_required != at->is_required)
1564    fail("Requirement mismatch in attribute declaration");
1565}
1566
1567/* Character Data handlers */
1568
1569void XMLCALL
1570clearing_aborting_character_handler(void *userData, const XML_Char *s,
1571                                    int len) {
1572  UNUSED_P(userData);
1573  UNUSED_P(s);
1574  UNUSED_P(len);
1575  XML_StopParser(g_parser, g_resumable);
1576  XML_SetCharacterDataHandler(g_parser, NULL);
1577}
1578
1579void XMLCALL
1580parser_stop_character_handler(void *userData, const XML_Char *s, int len) {
1581  UNUSED_P(userData);
1582  UNUSED_P(s);
1583  UNUSED_P(len);
1584  XML_ParsingStatus status;
1585  XML_GetParsingStatus(g_parser, &status);
1586  if (status.parsing == XML_FINISHED) {
1587    return; // the parser was stopped by a previous call to this handler.
1588  }
1589  XML_StopParser(g_parser, g_resumable);
1590  XML_SetCharacterDataHandler(g_parser, NULL);
1591  if (! g_resumable) {
1592    /* Check that aborting an aborted parser is faulted */
1593    if (XML_StopParser(g_parser, XML_FALSE) != XML_STATUS_ERROR)
1594      fail("Aborting aborted parser not faulted");
1595    if (XML_GetErrorCode(g_parser) != XML_ERROR_FINISHED)
1596      xml_failure(g_parser);
1597  } else if (g_abortable) {
1598    /* Check that aborting a suspended parser works */
1599    if (XML_StopParser(g_parser, XML_FALSE) == XML_STATUS_ERROR)
1600      xml_failure(g_parser);
1601  } else {
1602    /* Check that suspending a suspended parser works */
1603    if (XML_StopParser(g_parser, XML_TRUE) != XML_STATUS_ERROR)
1604      fail("Suspending suspended parser not faulted");
1605    if (XML_GetErrorCode(g_parser) != XML_ERROR_SUSPENDED)
1606      xml_failure(g_parser);
1607  }
1608}
1609
1610void XMLCALL
1611cr_cdata_handler(void *userData, const XML_Char *s, int len) {
1612  int *pfound = (int *)userData;
1613
1614  /* Internal processing turns the CR into a newline for the
1615   * character data handler, but not for the default handler
1616   */
1617  if (len == 1 && (*s == XCS('\n') || *s == XCS('\r')))
1618    *pfound = 1;
1619}
1620
1621void XMLCALL
1622rsqb_handler(void *userData, const XML_Char *s, int len) {
1623  int *pfound = (int *)userData;
1624
1625  if (len == 1 && *s == XCS(']'))
1626    *pfound = 1;
1627}
1628
1629void XMLCALL
1630byte_character_handler(void *userData, const XML_Char *s, int len) {
1631#if XML_CONTEXT_BYTES > 0
1632  int offset, size;
1633  const char *buffer;
1634  ByteTestData *data = (ByteTestData *)userData;
1635
1636  UNUSED_P(s);
1637  buffer = XML_GetInputContext(g_parser, &offset, &size);
1638  if (buffer == NULL)
1639    fail("Failed to get context buffer");
1640  if (offset != data->start_element_len)
1641    fail("Context offset in unexpected position");
1642  if (len != data->cdata_len)
1643    fail("CDATA length reported incorrectly");
1644  if (size != data->total_string_len)
1645    fail("Context size is not full buffer");
1646  if (XML_GetCurrentByteIndex(g_parser) != offset)
1647    fail("Character byte index incorrect");
1648  if (XML_GetCurrentByteCount(g_parser) != len)
1649    fail("Character byte count incorrect");
1650#else
1651  UNUSED_P(s);
1652  UNUSED_P(userData);
1653  UNUSED_P(len);
1654#endif
1655}
1656
1657void XMLCALL
1658ext2_accumulate_characters(void *userData, const XML_Char *s, int len) {
1659  ExtTest2 *test_data = (ExtTest2 *)userData;
1660  accumulate_characters(test_data->storage, s, len);
1661}
1662
1663/* Handlers that record their function name and int arg. */
1664
1665static void
1666record_call(struct handler_record_list *const rec, const char *funcname,
1667            const int arg) {
1668  const int max_entries = sizeof(rec->entries) / sizeof(rec->entries[0]);
1669  assert_true(rec->count < max_entries);
1670  struct handler_record_entry *const e = &rec->entries[rec->count++];
1671  e->name = funcname;
1672  e->arg = arg;
1673}
1674
1675void XMLCALL
1676record_default_handler(void *userData, const XML_Char *s, int len) {
1677  UNUSED_P(s);
1678  record_call((struct handler_record_list *)userData, __func__, len);
1679}
1680
1681void XMLCALL
1682record_cdata_handler(void *userData, const XML_Char *s, int len) {
1683  UNUSED_P(s);
1684  record_call((struct handler_record_list *)userData, __func__, len);
1685  XML_DefaultCurrent(g_parser);
1686}
1687
1688void XMLCALL
1689record_cdata_nodefault_handler(void *userData, const XML_Char *s, int len) {
1690  UNUSED_P(s);
1691  record_call((struct handler_record_list *)userData, __func__, len);
1692}
1693
1694void XMLCALL
1695record_skip_handler(void *userData, const XML_Char *entityName,
1696                    int is_parameter_entity) {
1697  UNUSED_P(entityName);
1698  record_call((struct handler_record_list *)userData, __func__,
1699              is_parameter_entity);
1700}
1701
1702void XMLCALL
1703record_element_start_handler(void *userData, const XML_Char *name,
1704                             const XML_Char **atts) {
1705  UNUSED_P(atts);
1706  CharData_AppendXMLChars((CharData *)userData, name, (int)xcstrlen(name));
1707}
1708
1709void XMLCALL
1710record_element_end_handler(void *userData, const XML_Char *name) {
1711  CharData *storage = (CharData *)userData;
1712
1713  CharData_AppendXMLChars(storage, XCS("/"), 1);
1714  CharData_AppendXMLChars(storage, name, -1);
1715}
1716
1717const struct handler_record_entry *
1718_handler_record_get(const struct handler_record_list *storage, int index,
1719                    const char *file, int line) {
1720  if (storage->count <= index) {
1721    _fail(file, line, "too few handler calls");
1722  }
1723  return &storage->entries[index];
1724}
1725
1726/* Entity Declaration Handlers */
1727static const XML_Char *entity_name_to_match = NULL;
1728static const XML_Char *entity_value_to_match = NULL;
1729static int entity_match_flag = ENTITY_MATCH_NOT_FOUND;
1730
1731void XMLCALL
1732param_entity_match_handler(void *userData, const XML_Char *entityName,
1733                           int is_parameter_entity, const XML_Char *value,
1734                           int value_length, const XML_Char *base,
1735                           const XML_Char *systemId, const XML_Char *publicId,
1736                           const XML_Char *notationName) {
1737  UNUSED_P(userData);
1738  UNUSED_P(base);
1739  UNUSED_P(systemId);
1740  UNUSED_P(publicId);
1741  UNUSED_P(notationName);
1742  if (! is_parameter_entity || entity_name_to_match == NULL
1743      || entity_value_to_match == NULL) {
1744    return;
1745  }
1746  if (! xcstrcmp(entityName, entity_name_to_match)) {
1747    /* The cast here is safe because we control the horizontal and
1748     * the vertical, and we therefore know our strings are never
1749     * going to overflow an int.
1750     */
1751    if (value_length != (int)xcstrlen(entity_value_to_match)
1752        || xcstrncmp(value, entity_value_to_match, value_length)) {
1753      entity_match_flag = ENTITY_MATCH_FAIL;
1754    } else {
1755      entity_match_flag = ENTITY_MATCH_SUCCESS;
1756    }
1757  }
1758  /* Else leave the match flag alone */
1759}
1760
1761void
1762param_entity_match_init(const XML_Char *name, const XML_Char *value) {
1763  entity_name_to_match = name;
1764  entity_value_to_match = value;
1765  entity_match_flag = ENTITY_MATCH_NOT_FOUND;
1766}
1767
1768int
1769get_param_entity_match_flag(void) {
1770  return entity_match_flag;
1771}
1772
1773/* Misc handlers */
1774
1775void XMLCALL
1776xml_decl_handler(void *userData, const XML_Char *version,
1777                 const XML_Char *encoding, int standalone) {
1778  UNUSED_P(version);
1779  UNUSED_P(encoding);
1780  if (userData != g_handler_data)
1781    fail("User data (xml decl) not correctly set");
1782  if (standalone != -1)
1783    fail("Standalone not flagged as not present in XML decl");
1784  g_xdecl_count++;
1785}
1786
1787void XMLCALL
1788param_check_skip_handler(void *userData, const XML_Char *entityName,
1789                         int is_parameter_entity) {
1790  UNUSED_P(entityName);
1791  UNUSED_P(is_parameter_entity);
1792  if (userData != g_handler_data)
1793    fail("User data (skip) not correctly set");
1794  g_skip_count++;
1795}
1796
1797void XMLCALL
1798data_check_comment_handler(void *userData, const XML_Char *data) {
1799  UNUSED_P(data);
1800  /* Check that the userData passed through is what we expect */
1801  if (userData != g_handler_data)
1802    fail("User data (parser) not correctly set");
1803  /* Check that the user data in the parser is appropriate */
1804  if (XML_GetUserData(userData) != (void *)1)
1805    fail("User data in parser not correctly set");
1806  g_comment_count++;
1807}
1808
1809void XMLCALL
1810selective_aborting_default_handler(void *userData, const XML_Char *s, int len) {
1811  const XML_Char trigger_char = *(const XML_Char *)userData;
1812
1813  int found = 0;
1814  for (int i = 0; i < len; ++i) {
1815    if (s[i] == trigger_char) {
1816      found = 1;
1817      break;
1818    }
1819  }
1820
1821  if (found) {
1822    XML_StopParser(g_parser, g_resumable);
1823    XML_SetDefaultHandler(g_parser, NULL);
1824  }
1825}
1826
1827void XMLCALL
1828suspending_comment_handler(void *userData, const XML_Char *data) {
1829  UNUSED_P(data);
1830  XML_Parser parser = (XML_Parser)userData;
1831  XML_StopParser(parser, XML_TRUE);
1832}
1833
1834void XMLCALL
1835element_decl_suspender(void *userData, const XML_Char *name,
1836                       XML_Content *model) {
1837  UNUSED_P(userData);
1838  UNUSED_P(name);
1839  XML_StopParser(g_parser, XML_TRUE);
1840  XML_FreeContentModel(g_parser, model);
1841}
1842
1843void XMLCALL
1844accumulate_pi_characters(void *userData, const XML_Char *target,
1845                         const XML_Char *data) {
1846  CharData *storage = (CharData *)userData;
1847
1848  CharData_AppendXMLChars(storage, target, -1);
1849  CharData_AppendXMLChars(storage, XCS(": "), 2);
1850  CharData_AppendXMLChars(storage, data, -1);
1851  CharData_AppendXMLChars(storage, XCS("\n"), 1);
1852}
1853
1854void XMLCALL
1855accumulate_comment(void *userData, const XML_Char *data) {
1856  CharData *storage = (CharData *)userData;
1857
1858  CharData_AppendXMLChars(storage, data, -1);
1859}
1860
1861void XMLCALL
1862accumulate_entity_decl(void *userData, const XML_Char *entityName,
1863                       int is_parameter_entity, const XML_Char *value,
1864                       int value_length, const XML_Char *base,
1865                       const XML_Char *systemId, const XML_Char *publicId,
1866                       const XML_Char *notationName) {
1867  CharData *storage = (CharData *)userData;
1868
1869  UNUSED_P(is_parameter_entity);
1870  UNUSED_P(base);
1871  UNUSED_P(systemId);
1872  UNUSED_P(publicId);
1873  UNUSED_P(notationName);
1874  CharData_AppendXMLChars(storage, entityName, -1);
1875  CharData_AppendXMLChars(storage, XCS("="), 1);
1876  if (value == NULL)
1877    CharData_AppendXMLChars(storage, XCS("(null)"), -1);
1878  else
1879    CharData_AppendXMLChars(storage, value, value_length);
1880  CharData_AppendXMLChars(storage, XCS("\n"), 1);
1881}
1882
1883void XMLCALL
1884accumulate_char_data(void *userData, const XML_Char *s, int len) {
1885  CharData *const storage = (CharData *)userData;
1886  CharData_AppendXMLChars(storage, s, len);
1887}
1888
1889void XMLCALL
1890accumulate_start_element(void *userData, const XML_Char *name,
1891                         const XML_Char **atts) {
1892  CharData *const storage = (CharData *)userData;
1893  CharData_AppendXMLChars(storage, XCS("("), 1);
1894  CharData_AppendXMLChars(storage, name, -1);
1895
1896  if ((atts != NULL) && (atts[0] != NULL)) {
1897    CharData_AppendXMLChars(storage, XCS("("), 1);
1898    while (atts[0] != NULL) {
1899      CharData_AppendXMLChars(storage, atts[0], -1);
1900      CharData_AppendXMLChars(storage, XCS("="), 1);
1901      CharData_AppendXMLChars(storage, atts[1], -1);
1902      atts += 2;
1903      if (atts[0] != NULL) {
1904        CharData_AppendXMLChars(storage, XCS(","), 1);
1905      }
1906    }
1907    CharData_AppendXMLChars(storage, XCS(")"), 1);
1908  }
1909
1910  CharData_AppendXMLChars(storage, XCS(")\n"), 2);
1911}
1912
1913void XMLCALL
1914checking_default_handler(void *userData, const XML_Char *s, int len) {
1915  DefaultCheck *data = (DefaultCheck *)userData;
1916  int i;
1917
1918  for (i = 0; data[i].expected != NULL; i++) {
1919    if (data[i].expectedLen == len
1920        && ! memcmp(data[i].expected, s, len * sizeof(XML_Char))) {
1921      data[i].seen = XML_TRUE;
1922      break;
1923    }
1924  }
1925}
1926
1927void XMLCALL
1928accumulate_and_suspend_comment_handler(void *userData, const XML_Char *data) {
1929  ParserPlusStorage *const parserPlusStorage = (ParserPlusStorage *)userData;
1930  accumulate_comment(parserPlusStorage->storage, data);
1931  XML_StopParser(parserPlusStorage->parser, XML_TRUE);
1932}
1933