xref: /freebsd/contrib/expat/tests/handlers.c (revision f126890ac5386406dadf7c4cfa9566cbb56537c5)
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 */
63 const void *g_handler_data = NULL;
64 /* Count of the number of times the comment handler has been invoked */
65 int g_comment_count = 0;
66 /* Count of the number of skipped entities */
67 int g_skip_count = 0;
68 /* Count of the number of times the XML declaration handler is invoked */
69 int g_xdecl_count = 0;
70 
71 /* Start/End Element Handlers */
72 
73 void XMLCALL
74 start_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 
80 void XMLCALL
81 end_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 
87 void XMLCALL
88 start_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 
96 void XMLCALL
97 end_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 
103 void XMLCALL
104 counting_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 
157 void XMLCALL
158 suspending_end_handler(void *userData, const XML_Char *s) {
159   UNUSED_P(s);
160   XML_StopParser((XML_Parser)userData, 1);
161 }
162 
163 void XMLCALL
164 start_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 */
179 int g_triplet_start_flag = XML_FALSE;
180 int g_triplet_end_flag = XML_FALSE;
181 
182 void XMLCALL
183 triplet_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 */
204 void XMLCALL
205 triplet_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 
216 void XMLCALL
217 overwrite_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 
230 void XMLCALL
231 overwrite_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 
238 void XMLCALL
239 start_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 
249 void XMLCALL
250 start_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 
257 void XMLCALL
258 start_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 
266 void XMLCALL
267 end_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 
279 int XMLCALL
280 UnknownEncodingHandler(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 
295 static void
296 dummy_release(void *data) {
297   UNUSED_P(data);
298 }
299 
300 int XMLCALL
301 UnrecognisedEncodingHandler(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 
311 int XMLCALL
312 unknown_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 
328 static int XMLCALL
329 failing_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 
336 static int XMLCALL
337 prefix_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 
346 int XMLCALL
347 MiscEncodingHandler(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 
393 int XMLCALL
394 long_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 
410 int XMLCALL
411 external_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 
436 int XMLCALL
437 external_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 
463 int XMLCALL
464 external_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 
491 int XMLCALL
492 external_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 
503 int XMLCALL
504 external_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 
548 void XMLCALL
549 entity_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 
562 int XMLCALL
563 external_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 
586 void XMLCALL
587 entity_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 
598 int XMLCALL
599 external_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 
635 int XMLCALL
636 external_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 
672 int XMLCALL
673 external_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 
690 int XMLCALL
691 external_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 
711 int XMLCALL
712 external_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 
734 int XMLCALL
735 external_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 
757 int XMLCALL
758 external_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 
785 int XMLCALL
786 external_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 
810 int XMLCALL
811 external_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 
836 int XMLCALL
837 external_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 
877 int XMLCALL
878 external_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 
898 int XMLCALL
899 external_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 
924 int XMLCALL
925 external_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 
950 int XMLCALL
951 external_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 
996 int XMLCALL
997 external_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 
1033 int XMLCALL
1034 external_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 
1070 int XMLCALL
1071 external_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 
1097 int XMLCALL
1098 external_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 
1126 int XMLCALL
1127 external_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 
1151 int XMLCALL
1152 external_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 
1178 int XMLCALL
1179 external_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 
1206 int XMLCALL
1207 external_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 
1233 int XMLCALL
1234 external_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 
1264 int XMLCALL
1265 external_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 
1296 int XMLCALL
1297 external_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 
1353 int XMLCALL
1354 external_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 
1391 int XMLCALL
1392 external_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 
1420 int XMLCALL
1421 external_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 
1448 int XMLCALL
1449 external_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 
1468 int XMLCALL
1469 external_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
1498 int
1499 accounting_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 
1533 int XMLCALL
1534 reject_not_standalone_handler(void *userData) {
1535   UNUSED_P(userData);
1536   return XML_STATUS_ERROR;
1537 }
1538 
1539 int XMLCALL
1540 accept_not_standalone_handler(void *userData) {
1541   UNUSED_P(userData);
1542   return XML_STATUS_OK;
1543 }
1544 
1545 /* Attribute List handlers */
1546 void XMLCALL
1547 verify_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 
1569 void XMLCALL
1570 clearing_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 
1579 void XMLCALL
1580 parser_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 
1610 void XMLCALL
1611 cr_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 
1621 void XMLCALL
1622 rsqb_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 
1629 void XMLCALL
1630 byte_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 
1657 void XMLCALL
1658 ext2_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 
1665 static void
1666 record_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 
1675 void XMLCALL
1676 record_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 
1681 void XMLCALL
1682 record_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 
1688 void XMLCALL
1689 record_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 
1694 void XMLCALL
1695 record_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 
1702 void XMLCALL
1703 record_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 
1709 void XMLCALL
1710 record_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 
1717 const 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 */
1727 static const XML_Char *entity_name_to_match = NULL;
1728 static const XML_Char *entity_value_to_match = NULL;
1729 static int entity_match_flag = ENTITY_MATCH_NOT_FOUND;
1730 
1731 void XMLCALL
1732 param_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 
1761 void
1762 param_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 
1768 int
1769 get_param_entity_match_flag(void) {
1770   return entity_match_flag;
1771 }
1772 
1773 /* Misc handlers */
1774 
1775 void XMLCALL
1776 xml_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 
1787 void XMLCALL
1788 param_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 
1797 void XMLCALL
1798 data_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 
1809 void XMLCALL
1810 selective_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 
1827 void XMLCALL
1828 suspending_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 
1834 void XMLCALL
1835 element_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 
1843 void XMLCALL
1844 accumulate_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 
1854 void XMLCALL
1855 accumulate_comment(void *userData, const XML_Char *data) {
1856   CharData *storage = (CharData *)userData;
1857 
1858   CharData_AppendXMLChars(storage, data, -1);
1859 }
1860 
1861 void XMLCALL
1862 accumulate_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 
1883 void XMLCALL
1884 accumulate_char_data(void *userData, const XML_Char *s, int len) {
1885   CharData *const storage = (CharData *)userData;
1886   CharData_AppendXMLChars(storage, s, len);
1887 }
1888 
1889 void XMLCALL
1890 accumulate_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 
1913 void XMLCALL
1914 checking_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 
1927 void XMLCALL
1928 accumulate_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