xref: /freebsd/contrib/expat/tests/handlers.c (revision 908f215e80fa482aa953c39afa6bb516f561fc00)
14543ef51SXin LI /* XML handler functions for the Expat test suite
24543ef51SXin LI                             __  __            _
34543ef51SXin LI                          ___\ \/ /_ __   __ _| |_
44543ef51SXin LI                         / _ \\  /| '_ \ / _` | __|
54543ef51SXin LI                        |  __//  \| |_) | (_| | |_
64543ef51SXin LI                         \___/_/\_\ .__/ \__,_|\__|
74543ef51SXin LI                                  |_| XML parser
84543ef51SXin LI 
94543ef51SXin LI    Copyright (c) 2001-2006 Fred L. Drake, Jr. <fdrake@users.sourceforge.net>
104543ef51SXin LI    Copyright (c) 2003      Greg Stein <gstein@users.sourceforge.net>
114543ef51SXin LI    Copyright (c) 2005-2007 Steven Solie <steven@solie.ca>
124543ef51SXin LI    Copyright (c) 2005-2012 Karl Waclawek <karl@waclawek.net>
134543ef51SXin LI    Copyright (c) 2016-2024 Sebastian Pipping <sebastian@pipping.org>
144543ef51SXin LI    Copyright (c) 2017-2022 Rhodri James <rhodri@wildebeest.org.uk>
154543ef51SXin LI    Copyright (c) 2017      Joe Orton <jorton@redhat.com>
164543ef51SXin LI    Copyright (c) 2017      José Gutiérrez de la Concha <jose@zeroc.com>
174543ef51SXin LI    Copyright (c) 2018      Marco Maggi <marco.maggi-ipsu@poste.it>
184543ef51SXin LI    Copyright (c) 2019      David Loffredo <loffredo@steptools.com>
194543ef51SXin LI    Copyright (c) 2020      Tim Gates <tim.gates@iress.com>
204543ef51SXin LI    Copyright (c) 2021      Donghee Na <donghee.na@python.org>
214543ef51SXin LI    Copyright (c) 2023-2024 Sony Corporation / Snild Dolkow <snild@sony.com>
224543ef51SXin LI    Licensed under the MIT license:
234543ef51SXin LI 
244543ef51SXin LI    Permission is  hereby granted,  free of charge,  to any  person obtaining
254543ef51SXin LI    a  copy  of  this  software   and  associated  documentation  files  (the
264543ef51SXin LI    "Software"),  to  deal in  the  Software  without restriction,  including
274543ef51SXin LI    without  limitation the  rights  to use,  copy,  modify, merge,  publish,
284543ef51SXin LI    distribute, sublicense, and/or sell copies of the Software, and to permit
294543ef51SXin LI    persons  to whom  the Software  is  furnished to  do so,  subject to  the
304543ef51SXin LI    following conditions:
314543ef51SXin LI 
324543ef51SXin LI    The above copyright  notice and this permission notice  shall be included
334543ef51SXin LI    in all copies or substantial portions of the Software.
344543ef51SXin LI 
354543ef51SXin LI    THE  SOFTWARE  IS  PROVIDED  "AS  IS",  WITHOUT  WARRANTY  OF  ANY  KIND,
364543ef51SXin LI    EXPRESS  OR IMPLIED,  INCLUDING  BUT  NOT LIMITED  TO  THE WARRANTIES  OF
374543ef51SXin LI    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
384543ef51SXin LI    NO EVENT SHALL THE AUTHORS OR  COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
394543ef51SXin LI    DAMAGES OR  OTHER LIABILITY, WHETHER  IN AN  ACTION OF CONTRACT,  TORT OR
404543ef51SXin LI    OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
414543ef51SXin LI    USE OR OTHER DEALINGS IN THE SOFTWARE.
424543ef51SXin LI */
434543ef51SXin LI 
444543ef51SXin LI #if defined(NDEBUG)
454543ef51SXin LI #  undef NDEBUG /* because test suite relies on assert(...) at the moment */
464543ef51SXin LI #endif
474543ef51SXin LI 
484543ef51SXin LI #include <stdio.h>
494543ef51SXin LI #include <string.h>
504543ef51SXin LI #include <assert.h>
514543ef51SXin LI 
524543ef51SXin LI #include "expat_config.h"
534543ef51SXin LI 
544543ef51SXin LI #include "expat.h"
554543ef51SXin LI #include "internal.h"
564543ef51SXin LI #include "chardata.h"
574543ef51SXin LI #include "structdata.h"
584543ef51SXin LI #include "common.h"
594543ef51SXin LI #include "handlers.h"
604543ef51SXin LI 
614543ef51SXin LI /* Global variables for user parameter settings tests */
624543ef51SXin LI /* Variable holding the expected handler userData */
634543ef51SXin LI const void *g_handler_data = NULL;
644543ef51SXin LI /* Count of the number of times the comment handler has been invoked */
654543ef51SXin LI int g_comment_count = 0;
664543ef51SXin LI /* Count of the number of skipped entities */
674543ef51SXin LI int g_skip_count = 0;
684543ef51SXin LI /* Count of the number of times the XML declaration handler is invoked */
694543ef51SXin LI int g_xdecl_count = 0;
704543ef51SXin LI 
714543ef51SXin LI /* Start/End Element Handlers */
724543ef51SXin LI 
734543ef51SXin LI void XMLCALL
744543ef51SXin LI start_element_event_handler(void *userData, const XML_Char *name,
754543ef51SXin LI                             const XML_Char **atts) {
764543ef51SXin LI   UNUSED_P(atts);
774543ef51SXin LI   CharData_AppendXMLChars((CharData *)userData, name, -1);
784543ef51SXin LI }
794543ef51SXin LI 
804543ef51SXin LI void XMLCALL
814543ef51SXin LI end_element_event_handler(void *userData, const XML_Char *name) {
824543ef51SXin LI   CharData *storage = (CharData *)userData;
834543ef51SXin LI   CharData_AppendXMLChars(storage, XCS("/"), 1);
844543ef51SXin LI   CharData_AppendXMLChars(storage, name, -1);
854543ef51SXin LI }
864543ef51SXin LI 
874543ef51SXin LI void XMLCALL
884543ef51SXin LI start_element_event_handler2(void *userData, const XML_Char *name,
894543ef51SXin LI                              const XML_Char **attr) {
904543ef51SXin LI   StructData *storage = (StructData *)userData;
914543ef51SXin LI   UNUSED_P(attr);
924543ef51SXin LI   StructData_AddItem(storage, name, XML_GetCurrentColumnNumber(g_parser),
934543ef51SXin LI                      XML_GetCurrentLineNumber(g_parser), STRUCT_START_TAG);
944543ef51SXin LI }
954543ef51SXin LI 
964543ef51SXin LI void XMLCALL
974543ef51SXin LI end_element_event_handler2(void *userData, const XML_Char *name) {
984543ef51SXin LI   StructData *storage = (StructData *)userData;
994543ef51SXin LI   StructData_AddItem(storage, name, XML_GetCurrentColumnNumber(g_parser),
1004543ef51SXin LI                      XML_GetCurrentLineNumber(g_parser), STRUCT_END_TAG);
1014543ef51SXin LI }
1024543ef51SXin LI 
1034543ef51SXin LI void XMLCALL
1044543ef51SXin LI counting_start_element_handler(void *userData, const XML_Char *name,
1054543ef51SXin LI                                const XML_Char **atts) {
106*908f215eSXin LI   ParserAndElementInfo *const parserAndElementInfos
107*908f215eSXin LI       = (ParserAndElementInfo *)userData;
108*908f215eSXin LI   ElementInfo *info = parserAndElementInfos->info;
1094543ef51SXin LI   AttrInfo *attr;
1104543ef51SXin LI   int count, id, i;
1114543ef51SXin LI 
1124543ef51SXin LI   while (info->name != NULL) {
1134543ef51SXin LI     if (! xcstrcmp(name, info->name))
1144543ef51SXin LI       break;
1154543ef51SXin LI     info++;
1164543ef51SXin LI   }
1174543ef51SXin LI   if (info->name == NULL)
1184543ef51SXin LI     fail("Element not recognised");
1194543ef51SXin LI   /* The attribute count is twice what you might expect.  It is a
1204543ef51SXin LI    * count of items in atts, an array which contains alternating
1214543ef51SXin LI    * attribute names and attribute values.  For the naive user this
1224543ef51SXin LI    * is possibly a little unexpected, but it is what the
1234543ef51SXin LI    * documentation in expat.h tells us to expect.
1244543ef51SXin LI    */
125*908f215eSXin LI   count = XML_GetSpecifiedAttributeCount(parserAndElementInfos->parser);
1264543ef51SXin LI   if (info->attr_count * 2 != count) {
1274543ef51SXin LI     fail("Not got expected attribute count");
1284543ef51SXin LI     return;
1294543ef51SXin LI   }
130*908f215eSXin LI   id = XML_GetIdAttributeIndex(parserAndElementInfos->parser);
1314543ef51SXin LI   if (id == -1 && info->id_name != NULL) {
1324543ef51SXin LI     fail("ID not present");
1334543ef51SXin LI     return;
1344543ef51SXin LI   }
1354543ef51SXin LI   if (id != -1 && xcstrcmp(atts[id], info->id_name)) {
1364543ef51SXin LI     fail("ID does not have the correct name");
1374543ef51SXin LI     return;
1384543ef51SXin LI   }
1394543ef51SXin LI   for (i = 0; i < info->attr_count; i++) {
1404543ef51SXin LI     attr = info->attributes;
1414543ef51SXin LI     while (attr->name != NULL) {
1424543ef51SXin LI       if (! xcstrcmp(atts[0], attr->name))
1434543ef51SXin LI         break;
1444543ef51SXin LI       attr++;
1454543ef51SXin LI     }
1464543ef51SXin LI     if (attr->name == NULL) {
1474543ef51SXin LI       fail("Attribute not recognised");
1484543ef51SXin LI       return;
1494543ef51SXin LI     }
1504543ef51SXin LI     if (xcstrcmp(atts[1], attr->value)) {
1514543ef51SXin LI       fail("Attribute has wrong value");
1524543ef51SXin LI       return;
1534543ef51SXin LI     }
1544543ef51SXin LI     /* Remember, two entries in atts per attribute (see above) */
1554543ef51SXin LI     atts += 2;
1564543ef51SXin LI   }
1574543ef51SXin LI }
1584543ef51SXin LI 
1594543ef51SXin LI void XMLCALL
1604543ef51SXin LI suspending_end_handler(void *userData, const XML_Char *s) {
1614543ef51SXin LI   UNUSED_P(s);
1624543ef51SXin LI   XML_StopParser((XML_Parser)userData, 1);
1634543ef51SXin LI }
1644543ef51SXin LI 
1654543ef51SXin LI void XMLCALL
1664543ef51SXin LI start_element_suspender(void *userData, const XML_Char *name,
1674543ef51SXin LI                         const XML_Char **atts) {
1684543ef51SXin LI   UNUSED_P(userData);
1694543ef51SXin LI   UNUSED_P(atts);
1704543ef51SXin LI   if (! xcstrcmp(name, XCS("suspend")))
1714543ef51SXin LI     XML_StopParser(g_parser, XML_TRUE);
1724543ef51SXin LI   if (! xcstrcmp(name, XCS("abort")))
1734543ef51SXin LI     XML_StopParser(g_parser, XML_FALSE);
1744543ef51SXin LI }
1754543ef51SXin LI 
1764543ef51SXin LI /* Check that an element name and attribute name match the expected values.
1774543ef51SXin LI    The expected values are passed as an array reference of string pointers
1784543ef51SXin LI    provided as the userData argument; the first is the expected
1794543ef51SXin LI    element name, and the second is the expected attribute name.
1804543ef51SXin LI */
1814543ef51SXin LI int g_triplet_start_flag = XML_FALSE;
1824543ef51SXin LI int g_triplet_end_flag = XML_FALSE;
1834543ef51SXin LI 
1844543ef51SXin LI void XMLCALL
1854543ef51SXin LI triplet_start_checker(void *userData, const XML_Char *name,
1864543ef51SXin LI                       const XML_Char **atts) {
1874543ef51SXin LI   XML_Char **elemstr = (XML_Char **)userData;
1884543ef51SXin LI   char buffer[1024];
1894543ef51SXin LI   if (xcstrcmp(elemstr[0], name) != 0) {
1904543ef51SXin LI     snprintf(buffer, sizeof(buffer),
1914543ef51SXin LI              "unexpected start string: '%" XML_FMT_STR "'", name);
1924543ef51SXin LI     fail(buffer);
1934543ef51SXin LI   }
1944543ef51SXin LI   if (xcstrcmp(elemstr[1], atts[0]) != 0) {
1954543ef51SXin LI     snprintf(buffer, sizeof(buffer),
1964543ef51SXin LI              "unexpected attribute string: '%" XML_FMT_STR "'", atts[0]);
1974543ef51SXin LI     fail(buffer);
1984543ef51SXin LI   }
1994543ef51SXin LI   g_triplet_start_flag = XML_TRUE;
2004543ef51SXin LI }
2014543ef51SXin LI 
2024543ef51SXin LI /* Check that the element name passed to the end-element handler matches
2034543ef51SXin LI    the expected value.  The expected value is passed as the first element
2044543ef51SXin LI    in an array of strings passed as the userData argument.
2054543ef51SXin LI */
2064543ef51SXin LI void XMLCALL
2074543ef51SXin LI triplet_end_checker(void *userData, const XML_Char *name) {
2084543ef51SXin LI   XML_Char **elemstr = (XML_Char **)userData;
2094543ef51SXin LI   if (xcstrcmp(elemstr[0], name) != 0) {
2104543ef51SXin LI     char buffer[1024];
2114543ef51SXin LI     snprintf(buffer, sizeof(buffer),
2124543ef51SXin LI              "unexpected end string: '%" XML_FMT_STR "'", name);
2134543ef51SXin LI     fail(buffer);
2144543ef51SXin LI   }
2154543ef51SXin LI   g_triplet_end_flag = XML_TRUE;
2164543ef51SXin LI }
2174543ef51SXin LI 
2184543ef51SXin LI void XMLCALL
2194543ef51SXin LI overwrite_start_checker(void *userData, const XML_Char *name,
2204543ef51SXin LI                         const XML_Char **atts) {
2214543ef51SXin LI   CharData *storage = (CharData *)userData;
2224543ef51SXin LI   CharData_AppendXMLChars(storage, XCS("start "), 6);
2234543ef51SXin LI   CharData_AppendXMLChars(storage, name, -1);
2244543ef51SXin LI   while (*atts != NULL) {
2254543ef51SXin LI     CharData_AppendXMLChars(storage, XCS("\nattribute "), 11);
2264543ef51SXin LI     CharData_AppendXMLChars(storage, *atts, -1);
2274543ef51SXin LI     atts += 2;
2284543ef51SXin LI   }
2294543ef51SXin LI   CharData_AppendXMLChars(storage, XCS("\n"), 1);
2304543ef51SXin LI }
2314543ef51SXin LI 
2324543ef51SXin LI void XMLCALL
2334543ef51SXin LI overwrite_end_checker(void *userData, const XML_Char *name) {
2344543ef51SXin LI   CharData *storage = (CharData *)userData;
2354543ef51SXin LI   CharData_AppendXMLChars(storage, XCS("end "), 4);
2364543ef51SXin LI   CharData_AppendXMLChars(storage, name, -1);
2374543ef51SXin LI   CharData_AppendXMLChars(storage, XCS("\n"), 1);
2384543ef51SXin LI }
2394543ef51SXin LI 
2404543ef51SXin LI void XMLCALL
2414543ef51SXin LI start_element_fail(void *userData, const XML_Char *name,
2424543ef51SXin LI                    const XML_Char **atts) {
2434543ef51SXin LI   UNUSED_P(userData);
2444543ef51SXin LI   UNUSED_P(name);
2454543ef51SXin LI   UNUSED_P(atts);
2464543ef51SXin LI 
2474543ef51SXin LI   /* We should never get here. */
2484543ef51SXin LI   fail("should never reach start_element_fail()");
2494543ef51SXin LI }
2504543ef51SXin LI 
2514543ef51SXin LI void XMLCALL
2524543ef51SXin LI start_ns_clearing_start_element(void *userData, const XML_Char *prefix,
2534543ef51SXin LI                                 const XML_Char *uri) {
2544543ef51SXin LI   UNUSED_P(prefix);
2554543ef51SXin LI   UNUSED_P(uri);
2564543ef51SXin LI   XML_SetStartElementHandler((XML_Parser)userData, NULL);
2574543ef51SXin LI }
2584543ef51SXin LI 
2594543ef51SXin LI void XMLCALL
2604543ef51SXin LI start_element_issue_240(void *userData, const XML_Char *name,
2614543ef51SXin LI                         const XML_Char **atts) {
2624543ef51SXin LI   DataIssue240 *mydata = (DataIssue240 *)userData;
2634543ef51SXin LI   UNUSED_P(name);
2644543ef51SXin LI   UNUSED_P(atts);
2654543ef51SXin LI   mydata->deep++;
2664543ef51SXin LI }
2674543ef51SXin LI 
2684543ef51SXin LI void XMLCALL
2694543ef51SXin LI end_element_issue_240(void *userData, const XML_Char *name) {
2704543ef51SXin LI   DataIssue240 *mydata = (DataIssue240 *)userData;
2714543ef51SXin LI 
2724543ef51SXin LI   UNUSED_P(name);
2734543ef51SXin LI   mydata->deep--;
2744543ef51SXin LI   if (mydata->deep == 0) {
2754543ef51SXin LI     XML_StopParser(mydata->parser, 0);
2764543ef51SXin LI   }
2774543ef51SXin LI }
2784543ef51SXin LI 
2794543ef51SXin LI /* Text encoding handlers */
2804543ef51SXin LI 
2814543ef51SXin LI int XMLCALL
2824543ef51SXin LI UnknownEncodingHandler(void *data, const XML_Char *encoding,
2834543ef51SXin LI                        XML_Encoding *info) {
2844543ef51SXin LI   UNUSED_P(data);
2854543ef51SXin LI   if (xcstrcmp(encoding, XCS("unsupported-encoding")) == 0) {
2864543ef51SXin LI     int i;
2874543ef51SXin LI     for (i = 0; i < 256; ++i)
2884543ef51SXin LI       info->map[i] = i;
2894543ef51SXin LI     info->data = NULL;
2904543ef51SXin LI     info->convert = NULL;
2914543ef51SXin LI     info->release = NULL;
2924543ef51SXin LI     return XML_STATUS_OK;
2934543ef51SXin LI   }
2944543ef51SXin LI   return XML_STATUS_ERROR;
2954543ef51SXin LI }
2964543ef51SXin LI 
2974543ef51SXin LI static void
2984543ef51SXin LI dummy_release(void *data) {
2994543ef51SXin LI   UNUSED_P(data);
3004543ef51SXin LI }
3014543ef51SXin LI 
3024543ef51SXin LI int XMLCALL
3034543ef51SXin LI UnrecognisedEncodingHandler(void *data, const XML_Char *encoding,
3044543ef51SXin LI                             XML_Encoding *info) {
3054543ef51SXin LI   UNUSED_P(data);
3064543ef51SXin LI   UNUSED_P(encoding);
3074543ef51SXin LI   info->data = NULL;
3084543ef51SXin LI   info->convert = NULL;
3094543ef51SXin LI   info->release = dummy_release;
3104543ef51SXin LI   return XML_STATUS_ERROR;
3114543ef51SXin LI }
3124543ef51SXin LI 
3134543ef51SXin LI int XMLCALL
3144543ef51SXin LI unknown_released_encoding_handler(void *data, const XML_Char *encoding,
3154543ef51SXin LI                                   XML_Encoding *info) {
3164543ef51SXin LI   UNUSED_P(data);
3174543ef51SXin LI   if (! xcstrcmp(encoding, XCS("unsupported-encoding"))) {
3184543ef51SXin LI     int i;
3194543ef51SXin LI 
3204543ef51SXin LI     for (i = 0; i < 256; i++)
3214543ef51SXin LI       info->map[i] = i;
3224543ef51SXin LI     info->data = NULL;
3234543ef51SXin LI     info->convert = NULL;
3244543ef51SXin LI     info->release = dummy_release;
3254543ef51SXin LI     return XML_STATUS_OK;
3264543ef51SXin LI   }
3274543ef51SXin LI   return XML_STATUS_ERROR;
3284543ef51SXin LI }
3294543ef51SXin LI 
3304543ef51SXin LI static int XMLCALL
3314543ef51SXin LI failing_converter(void *data, const char *s) {
3324543ef51SXin LI   UNUSED_P(data);
3334543ef51SXin LI   UNUSED_P(s);
3344543ef51SXin LI   /* Always claim to have failed */
3354543ef51SXin LI   return -1;
3364543ef51SXin LI }
3374543ef51SXin LI 
3384543ef51SXin LI static int XMLCALL
3394543ef51SXin LI prefix_converter(void *data, const char *s) {
3404543ef51SXin LI   UNUSED_P(data);
3414543ef51SXin LI   /* If the first byte is 0xff, raise an error */
3424543ef51SXin LI   if (s[0] == (char)-1)
3434543ef51SXin LI     return -1;
3444543ef51SXin LI   /* Just add the low bits of the first byte to the second */
3454543ef51SXin LI   return (s[1] + (s[0] & 0x7f)) & 0x01ff;
3464543ef51SXin LI }
3474543ef51SXin LI 
3484543ef51SXin LI int XMLCALL
3494543ef51SXin LI MiscEncodingHandler(void *data, const XML_Char *encoding, XML_Encoding *info) {
3504543ef51SXin LI   int i;
3514543ef51SXin LI   int high_map = -2; /* Assume a 2-byte sequence */
3524543ef51SXin LI 
3534543ef51SXin LI   if (! xcstrcmp(encoding, XCS("invalid-9"))
3544543ef51SXin LI       || ! xcstrcmp(encoding, XCS("ascii-like"))
3554543ef51SXin LI       || ! xcstrcmp(encoding, XCS("invalid-len"))
3564543ef51SXin LI       || ! xcstrcmp(encoding, XCS("invalid-a"))
3574543ef51SXin LI       || ! xcstrcmp(encoding, XCS("invalid-surrogate"))
3584543ef51SXin LI       || ! xcstrcmp(encoding, XCS("invalid-high")))
3594543ef51SXin LI     high_map = -1;
3604543ef51SXin LI 
3614543ef51SXin LI   for (i = 0; i < 128; ++i)
3624543ef51SXin LI     info->map[i] = i;
3634543ef51SXin LI   for (; i < 256; ++i)
3644543ef51SXin LI     info->map[i] = high_map;
3654543ef51SXin LI 
3664543ef51SXin LI   /* If required, put an invalid value in the ASCII entries */
3674543ef51SXin LI   if (! xcstrcmp(encoding, XCS("invalid-9")))
3684543ef51SXin LI     info->map[9] = 5;
3694543ef51SXin LI   /* If required, have a top-bit set character starts a 5-byte sequence */
3704543ef51SXin LI   if (! xcstrcmp(encoding, XCS("invalid-len")))
3714543ef51SXin LI     info->map[0x81] = -5;
3724543ef51SXin LI   /* If required, make a top-bit set character a valid ASCII character */
3734543ef51SXin LI   if (! xcstrcmp(encoding, XCS("invalid-a")))
3744543ef51SXin LI     info->map[0x82] = 'a';
3754543ef51SXin LI   /* If required, give a top-bit set character a forbidden value,
3764543ef51SXin LI    * what would otherwise be the first of a surrogate pair.
3774543ef51SXin LI    */
3784543ef51SXin LI   if (! xcstrcmp(encoding, XCS("invalid-surrogate")))
3794543ef51SXin LI     info->map[0x83] = 0xd801;
3804543ef51SXin LI   /* If required, give a top-bit set character too high a value */
3814543ef51SXin LI   if (! xcstrcmp(encoding, XCS("invalid-high")))
3824543ef51SXin LI     info->map[0x84] = 0x010101;
3834543ef51SXin LI 
3844543ef51SXin LI   info->data = data;
3854543ef51SXin LI   info->release = NULL;
3864543ef51SXin LI   if (! xcstrcmp(encoding, XCS("failing-conv")))
3874543ef51SXin LI     info->convert = failing_converter;
3884543ef51SXin LI   else if (! xcstrcmp(encoding, XCS("prefix-conv")))
3894543ef51SXin LI     info->convert = prefix_converter;
3904543ef51SXin LI   else
3914543ef51SXin LI     info->convert = NULL;
3924543ef51SXin LI   return XML_STATUS_OK;
3934543ef51SXin LI }
3944543ef51SXin LI 
3954543ef51SXin LI int XMLCALL
3964543ef51SXin LI long_encoding_handler(void *userData, const XML_Char *encoding,
3974543ef51SXin LI                       XML_Encoding *info) {
3984543ef51SXin LI   int i;
3994543ef51SXin LI 
4004543ef51SXin LI   UNUSED_P(userData);
4014543ef51SXin LI   UNUSED_P(encoding);
4024543ef51SXin LI   for (i = 0; i < 256; i++)
4034543ef51SXin LI     info->map[i] = i;
4044543ef51SXin LI   info->data = NULL;
4054543ef51SXin LI   info->convert = NULL;
4064543ef51SXin LI   info->release = NULL;
4074543ef51SXin LI   return XML_STATUS_OK;
4084543ef51SXin LI }
4094543ef51SXin LI 
4104543ef51SXin LI /* External Entity Handlers */
4114543ef51SXin LI 
4124543ef51SXin LI int XMLCALL
4134543ef51SXin LI external_entity_optioner(XML_Parser parser, const XML_Char *context,
4144543ef51SXin LI                          const XML_Char *base, const XML_Char *systemId,
4154543ef51SXin LI                          const XML_Char *publicId) {
4164543ef51SXin LI   ExtOption *options = (ExtOption *)XML_GetUserData(parser);
4174543ef51SXin LI   XML_Parser ext_parser;
4184543ef51SXin LI 
4194543ef51SXin LI   UNUSED_P(base);
4204543ef51SXin LI   UNUSED_P(publicId);
4214543ef51SXin LI   while (options->parse_text != NULL) {
4224543ef51SXin LI     if (! xcstrcmp(systemId, options->system_id)) {
4234543ef51SXin LI       enum XML_Status rc;
4244543ef51SXin LI       ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
4254543ef51SXin LI       if (ext_parser == NULL)
4264543ef51SXin LI         return XML_STATUS_ERROR;
4274543ef51SXin LI       rc = _XML_Parse_SINGLE_BYTES(ext_parser, options->parse_text,
4284543ef51SXin LI                                    (int)strlen(options->parse_text), XML_TRUE);
4294543ef51SXin LI       XML_ParserFree(ext_parser);
4304543ef51SXin LI       return rc;
4314543ef51SXin LI     }
4324543ef51SXin LI     options++;
4334543ef51SXin LI   }
4344543ef51SXin LI   fail("No suitable option found");
4354543ef51SXin LI   return XML_STATUS_ERROR;
4364543ef51SXin LI }
4374543ef51SXin LI 
4384543ef51SXin LI int XMLCALL
4394543ef51SXin LI external_entity_loader(XML_Parser parser, const XML_Char *context,
4404543ef51SXin LI                        const XML_Char *base, const XML_Char *systemId,
4414543ef51SXin LI                        const XML_Char *publicId) {
4424543ef51SXin LI   ExtTest *test_data = (ExtTest *)XML_GetUserData(parser);
4434543ef51SXin LI   XML_Parser extparser;
4444543ef51SXin LI 
4454543ef51SXin LI   UNUSED_P(base);
4464543ef51SXin LI   UNUSED_P(systemId);
4474543ef51SXin LI   UNUSED_P(publicId);
4484543ef51SXin LI   extparser = XML_ExternalEntityParserCreate(parser, context, NULL);
4494543ef51SXin LI   if (extparser == NULL)
4504543ef51SXin LI     fail("Could not create external entity parser.");
4514543ef51SXin LI   if (test_data->encoding != NULL) {
4524543ef51SXin LI     if (! XML_SetEncoding(extparser, test_data->encoding))
4534543ef51SXin LI       fail("XML_SetEncoding() ignored for external entity");
4544543ef51SXin LI   }
4554543ef51SXin LI   if (_XML_Parse_SINGLE_BYTES(extparser, test_data->parse_text,
4564543ef51SXin LI                               (int)strlen(test_data->parse_text), XML_TRUE)
4574543ef51SXin LI       == XML_STATUS_ERROR) {
4584543ef51SXin LI     xml_failure(extparser);
4594543ef51SXin LI     return XML_STATUS_ERROR;
4604543ef51SXin LI   }
4614543ef51SXin LI   XML_ParserFree(extparser);
4624543ef51SXin LI   return XML_STATUS_OK;
4634543ef51SXin LI }
4644543ef51SXin LI 
4654543ef51SXin LI int XMLCALL
4664543ef51SXin LI external_entity_faulter(XML_Parser parser, const XML_Char *context,
4674543ef51SXin LI                         const XML_Char *base, const XML_Char *systemId,
4684543ef51SXin LI                         const XML_Char *publicId) {
4694543ef51SXin LI   XML_Parser ext_parser;
4704543ef51SXin LI   ExtFaults *fault = (ExtFaults *)XML_GetUserData(parser);
4714543ef51SXin LI 
4724543ef51SXin LI   UNUSED_P(base);
4734543ef51SXin LI   UNUSED_P(systemId);
4744543ef51SXin LI   UNUSED_P(publicId);
4754543ef51SXin LI   ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
4764543ef51SXin LI   if (ext_parser == NULL)
4774543ef51SXin LI     fail("Could not create external entity parser");
4784543ef51SXin LI   if (fault->encoding != NULL) {
4794543ef51SXin LI     if (! XML_SetEncoding(ext_parser, fault->encoding))
4804543ef51SXin LI       fail("XML_SetEncoding failed");
4814543ef51SXin LI   }
4824543ef51SXin LI   if (_XML_Parse_SINGLE_BYTES(ext_parser, fault->parse_text,
4834543ef51SXin LI                               (int)strlen(fault->parse_text), XML_TRUE)
4844543ef51SXin LI       != XML_STATUS_ERROR)
4854543ef51SXin LI     fail(fault->fail_text);
4864543ef51SXin LI   if (XML_GetErrorCode(ext_parser) != fault->error)
4874543ef51SXin LI     xml_failure(ext_parser);
4884543ef51SXin LI 
4894543ef51SXin LI   XML_ParserFree(ext_parser);
4904543ef51SXin LI   return XML_STATUS_ERROR;
4914543ef51SXin LI }
4924543ef51SXin LI 
4934543ef51SXin LI int XMLCALL
4944543ef51SXin LI external_entity_null_loader(XML_Parser parser, const XML_Char *context,
4954543ef51SXin LI                             const XML_Char *base, const XML_Char *systemId,
4964543ef51SXin LI                             const XML_Char *publicId) {
4974543ef51SXin LI   UNUSED_P(parser);
4984543ef51SXin LI   UNUSED_P(context);
4994543ef51SXin LI   UNUSED_P(base);
5004543ef51SXin LI   UNUSED_P(systemId);
5014543ef51SXin LI   UNUSED_P(publicId);
5024543ef51SXin LI   return XML_STATUS_OK;
5034543ef51SXin LI }
5044543ef51SXin LI 
5054543ef51SXin LI int XMLCALL
5064543ef51SXin LI external_entity_resetter(XML_Parser parser, const XML_Char *context,
5074543ef51SXin LI                          const XML_Char *base, const XML_Char *systemId,
5084543ef51SXin LI                          const XML_Char *publicId) {
5094543ef51SXin LI   const char *text = "<!ELEMENT doc (#PCDATA)*>";
5104543ef51SXin LI   XML_Parser ext_parser;
5114543ef51SXin LI   XML_ParsingStatus status;
5124543ef51SXin LI 
5134543ef51SXin LI   UNUSED_P(base);
5144543ef51SXin LI   UNUSED_P(systemId);
5154543ef51SXin LI   UNUSED_P(publicId);
5164543ef51SXin LI   ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
5174543ef51SXin LI   if (ext_parser == NULL)
5184543ef51SXin LI     fail("Could not create external entity parser");
5194543ef51SXin LI   XML_GetParsingStatus(ext_parser, &status);
5204543ef51SXin LI   if (status.parsing != XML_INITIALIZED) {
5214543ef51SXin LI     fail("Parsing status is not INITIALIZED");
5224543ef51SXin LI     return XML_STATUS_ERROR;
5234543ef51SXin LI   }
5244543ef51SXin LI   if (_XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE)
5254543ef51SXin LI       == XML_STATUS_ERROR) {
5264543ef51SXin LI     xml_failure(parser);
5274543ef51SXin LI     return XML_STATUS_ERROR;
5284543ef51SXin LI   }
5294543ef51SXin LI   XML_GetParsingStatus(ext_parser, &status);
5304543ef51SXin LI   if (status.parsing != XML_FINISHED) {
5314543ef51SXin LI     fail("Parsing status is not FINISHED");
5324543ef51SXin LI     return XML_STATUS_ERROR;
5334543ef51SXin LI   }
5344543ef51SXin LI   /* Check we can't parse here */
5354543ef51SXin LI   if (_XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE)
5364543ef51SXin LI       != XML_STATUS_ERROR)
5374543ef51SXin LI     fail("Parsing when finished not faulted");
5384543ef51SXin LI   if (XML_GetErrorCode(ext_parser) != XML_ERROR_FINISHED)
5394543ef51SXin LI     fail("Parsing when finished faulted with wrong code");
5404543ef51SXin LI   XML_ParserReset(ext_parser, NULL);
5414543ef51SXin LI   XML_GetParsingStatus(ext_parser, &status);
5424543ef51SXin LI   if (status.parsing != XML_FINISHED) {
5434543ef51SXin LI     fail("Parsing status not still FINISHED");
5444543ef51SXin LI     return XML_STATUS_ERROR;
5454543ef51SXin LI   }
5464543ef51SXin LI   XML_ParserFree(ext_parser);
5474543ef51SXin LI   return XML_STATUS_OK;
5484543ef51SXin LI }
5494543ef51SXin LI 
5504543ef51SXin LI void XMLCALL
5514543ef51SXin LI entity_suspending_decl_handler(void *userData, const XML_Char *name,
5524543ef51SXin LI                                XML_Content *model) {
5534543ef51SXin LI   XML_Parser ext_parser = (XML_Parser)userData;
5544543ef51SXin LI 
5554543ef51SXin LI   UNUSED_P(name);
5564543ef51SXin LI   if (XML_StopParser(ext_parser, XML_TRUE) != XML_STATUS_ERROR)
5574543ef51SXin LI     fail("Attempting to suspend a subordinate parser not faulted");
5584543ef51SXin LI   if (XML_GetErrorCode(ext_parser) != XML_ERROR_SUSPEND_PE)
5594543ef51SXin LI     fail("Suspending subordinate parser get wrong code");
5604543ef51SXin LI   XML_SetElementDeclHandler(ext_parser, NULL);
5614543ef51SXin LI   XML_FreeContentModel(g_parser, model);
5624543ef51SXin LI }
5634543ef51SXin LI 
5644543ef51SXin LI int XMLCALL
5654543ef51SXin LI external_entity_suspender(XML_Parser parser, const XML_Char *context,
5664543ef51SXin LI                           const XML_Char *base, const XML_Char *systemId,
5674543ef51SXin LI                           const XML_Char *publicId) {
5684543ef51SXin LI   const char *text = "<!ELEMENT doc (#PCDATA)*>";
5694543ef51SXin LI   XML_Parser ext_parser;
5704543ef51SXin LI 
5714543ef51SXin LI   UNUSED_P(base);
5724543ef51SXin LI   UNUSED_P(systemId);
5734543ef51SXin LI   UNUSED_P(publicId);
5744543ef51SXin LI   ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
5754543ef51SXin LI   if (ext_parser == NULL)
5764543ef51SXin LI     fail("Could not create external entity parser");
5774543ef51SXin LI   XML_SetElementDeclHandler(ext_parser, entity_suspending_decl_handler);
5784543ef51SXin LI   XML_SetUserData(ext_parser, ext_parser);
5794543ef51SXin LI   if (_XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE)
5804543ef51SXin LI       == XML_STATUS_ERROR) {
5814543ef51SXin LI     xml_failure(ext_parser);
5824543ef51SXin LI     return XML_STATUS_ERROR;
5834543ef51SXin LI   }
5844543ef51SXin LI   XML_ParserFree(ext_parser);
5854543ef51SXin LI   return XML_STATUS_OK;
5864543ef51SXin LI }
5874543ef51SXin LI 
5884543ef51SXin LI void XMLCALL
5894543ef51SXin LI entity_suspending_xdecl_handler(void *userData, const XML_Char *version,
5904543ef51SXin LI                                 const XML_Char *encoding, int standalone) {
5914543ef51SXin LI   XML_Parser ext_parser = (XML_Parser)userData;
5924543ef51SXin LI 
5934543ef51SXin LI   UNUSED_P(version);
5944543ef51SXin LI   UNUSED_P(encoding);
5954543ef51SXin LI   UNUSED_P(standalone);
5964543ef51SXin LI   XML_StopParser(ext_parser, g_resumable);
5974543ef51SXin LI   XML_SetXmlDeclHandler(ext_parser, NULL);
5984543ef51SXin LI }
5994543ef51SXin LI 
6004543ef51SXin LI int XMLCALL
6014543ef51SXin LI external_entity_suspend_xmldecl(XML_Parser parser, const XML_Char *context,
6024543ef51SXin LI                                 const XML_Char *base, const XML_Char *systemId,
6034543ef51SXin LI                                 const XML_Char *publicId) {
6044543ef51SXin LI   const char *text = "<?xml version='1.0' encoding='us-ascii'?>";
6054543ef51SXin LI   XML_Parser ext_parser;
6064543ef51SXin LI   XML_ParsingStatus status;
6074543ef51SXin LI   enum XML_Status rc;
6084543ef51SXin LI 
6094543ef51SXin LI   UNUSED_P(base);
6104543ef51SXin LI   UNUSED_P(systemId);
6114543ef51SXin LI   UNUSED_P(publicId);
6124543ef51SXin LI   ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
6134543ef51SXin LI   if (ext_parser == NULL)
6144543ef51SXin LI     fail("Could not create external entity parser");
6154543ef51SXin LI   XML_SetXmlDeclHandler(ext_parser, entity_suspending_xdecl_handler);
6164543ef51SXin LI   XML_SetUserData(ext_parser, ext_parser);
6174543ef51SXin LI   rc = _XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE);
6184543ef51SXin LI   XML_GetParsingStatus(ext_parser, &status);
6194543ef51SXin LI   if (g_resumable) {
6204543ef51SXin LI     if (rc == XML_STATUS_ERROR)
6214543ef51SXin LI       xml_failure(ext_parser);
6224543ef51SXin LI     if (status.parsing != XML_SUSPENDED)
6234543ef51SXin LI       fail("Ext Parsing status not SUSPENDED");
6244543ef51SXin LI   } else {
6254543ef51SXin LI     if (rc != XML_STATUS_ERROR)
6264543ef51SXin LI       fail("Ext parsing not aborted");
6274543ef51SXin LI     if (XML_GetErrorCode(ext_parser) != XML_ERROR_ABORTED)
6284543ef51SXin LI       xml_failure(ext_parser);
6294543ef51SXin LI     if (status.parsing != XML_FINISHED)
6304543ef51SXin LI       fail("Ext Parsing status not FINISHED");
6314543ef51SXin LI   }
6324543ef51SXin LI 
6334543ef51SXin LI   XML_ParserFree(ext_parser);
6344543ef51SXin LI   return XML_STATUS_OK;
6354543ef51SXin LI }
6364543ef51SXin LI 
6374543ef51SXin LI int XMLCALL
6384543ef51SXin LI external_entity_suspending_faulter(XML_Parser parser, const XML_Char *context,
6394543ef51SXin LI                                    const XML_Char *base,
6404543ef51SXin LI                                    const XML_Char *systemId,
6414543ef51SXin LI                                    const XML_Char *publicId) {
6424543ef51SXin LI   XML_Parser ext_parser;
6434543ef51SXin LI   ExtFaults *fault = (ExtFaults *)XML_GetUserData(parser);
6444543ef51SXin LI   void *buffer;
6454543ef51SXin LI   int parse_len = (int)strlen(fault->parse_text);
6464543ef51SXin LI 
6474543ef51SXin LI   UNUSED_P(base);
6484543ef51SXin LI   UNUSED_P(systemId);
6494543ef51SXin LI   UNUSED_P(publicId);
6504543ef51SXin LI   ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
6514543ef51SXin LI   if (ext_parser == NULL)
6524543ef51SXin LI     fail("Could not create external entity parser");
6534543ef51SXin LI   XML_SetXmlDeclHandler(ext_parser, entity_suspending_xdecl_handler);
6544543ef51SXin LI   XML_SetUserData(ext_parser, ext_parser);
6554543ef51SXin LI   g_resumable = XML_TRUE;
6564543ef51SXin LI   buffer = XML_GetBuffer(ext_parser, parse_len);
6574543ef51SXin LI   if (buffer == NULL)
6584543ef51SXin LI     fail("Could not allocate parse buffer");
6594543ef51SXin LI   assert(buffer != NULL);
6604543ef51SXin LI   memcpy(buffer, fault->parse_text, parse_len);
6614543ef51SXin LI   if (XML_ParseBuffer(ext_parser, parse_len, XML_FALSE) != XML_STATUS_SUSPENDED)
6624543ef51SXin LI     fail("XML declaration did not suspend");
6634543ef51SXin LI   if (XML_ResumeParser(ext_parser) != XML_STATUS_OK)
6644543ef51SXin LI     xml_failure(ext_parser);
6654543ef51SXin LI   if (XML_ParseBuffer(ext_parser, 0, XML_TRUE) != XML_STATUS_ERROR)
6664543ef51SXin LI     fail(fault->fail_text);
6674543ef51SXin LI   if (XML_GetErrorCode(ext_parser) != fault->error)
6684543ef51SXin LI     xml_failure(ext_parser);
6694543ef51SXin LI 
6704543ef51SXin LI   XML_ParserFree(ext_parser);
6714543ef51SXin LI   return XML_STATUS_ERROR;
6724543ef51SXin LI }
6734543ef51SXin LI 
6744543ef51SXin LI int XMLCALL
6754543ef51SXin LI external_entity_failer__if_not_xml_ge(XML_Parser parser,
6764543ef51SXin LI                                       const XML_Char *context,
6774543ef51SXin LI                                       const XML_Char *base,
6784543ef51SXin LI                                       const XML_Char *systemId,
6794543ef51SXin LI                                       const XML_Char *publicId) {
6804543ef51SXin LI   UNUSED_P(parser);
6814543ef51SXin LI   UNUSED_P(context);
6824543ef51SXin LI   UNUSED_P(base);
6834543ef51SXin LI   UNUSED_P(systemId);
6844543ef51SXin LI   UNUSED_P(publicId);
6854543ef51SXin LI #if XML_GE == 0
6864543ef51SXin LI   fail(
6874543ef51SXin LI       "Function external_entity_suspending_failer was called despite XML_GE==0.");
6884543ef51SXin LI #endif
6894543ef51SXin LI   return XML_STATUS_OK;
6904543ef51SXin LI }
6914543ef51SXin LI 
6924543ef51SXin LI int XMLCALL
6934543ef51SXin LI external_entity_cr_catcher(XML_Parser parser, const XML_Char *context,
6944543ef51SXin LI                            const XML_Char *base, const XML_Char *systemId,
6954543ef51SXin LI                            const XML_Char *publicId) {
6964543ef51SXin LI   const char *text = "\r";
6974543ef51SXin LI   XML_Parser ext_parser;
6984543ef51SXin LI 
6994543ef51SXin LI   UNUSED_P(base);
7004543ef51SXin LI   UNUSED_P(systemId);
7014543ef51SXin LI   UNUSED_P(publicId);
7024543ef51SXin LI   ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
7034543ef51SXin LI   if (ext_parser == NULL)
7044543ef51SXin LI     fail("Could not create external entity parser");
7054543ef51SXin LI   XML_SetCharacterDataHandler(ext_parser, cr_cdata_handler);
7064543ef51SXin LI   if (_XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE)
7074543ef51SXin LI       == XML_STATUS_ERROR)
7084543ef51SXin LI     xml_failure(ext_parser);
7094543ef51SXin LI   XML_ParserFree(ext_parser);
7104543ef51SXin LI   return XML_STATUS_OK;
7114543ef51SXin LI }
7124543ef51SXin LI 
7134543ef51SXin LI int XMLCALL
7144543ef51SXin LI external_entity_bad_cr_catcher(XML_Parser parser, const XML_Char *context,
7154543ef51SXin LI                                const XML_Char *base, const XML_Char *systemId,
7164543ef51SXin LI                                const XML_Char *publicId) {
7174543ef51SXin LI   const char *text = "<tag>\r";
7184543ef51SXin LI   XML_Parser ext_parser;
7194543ef51SXin LI 
7204543ef51SXin LI   UNUSED_P(base);
7214543ef51SXin LI   UNUSED_P(systemId);
7224543ef51SXin LI   UNUSED_P(publicId);
7234543ef51SXin LI   ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
7244543ef51SXin LI   if (ext_parser == NULL)
7254543ef51SXin LI     fail("Could not create external entity parser");
7264543ef51SXin LI   XML_SetCharacterDataHandler(ext_parser, cr_cdata_handler);
7274543ef51SXin LI   if (_XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE)
7284543ef51SXin LI       == XML_STATUS_OK)
7294543ef51SXin LI     fail("Async entity error not caught");
7304543ef51SXin LI   if (XML_GetErrorCode(ext_parser) != XML_ERROR_ASYNC_ENTITY)
7314543ef51SXin LI     xml_failure(ext_parser);
7324543ef51SXin LI   XML_ParserFree(ext_parser);
7334543ef51SXin LI   return XML_STATUS_OK;
7344543ef51SXin LI }
7354543ef51SXin LI 
7364543ef51SXin LI int XMLCALL
7374543ef51SXin LI external_entity_rsqb_catcher(XML_Parser parser, const XML_Char *context,
7384543ef51SXin LI                              const XML_Char *base, const XML_Char *systemId,
7394543ef51SXin LI                              const XML_Char *publicId) {
7404543ef51SXin LI   const char *text = "<tag>]";
7414543ef51SXin LI   XML_Parser ext_parser;
7424543ef51SXin LI 
7434543ef51SXin LI   UNUSED_P(base);
7444543ef51SXin LI   UNUSED_P(systemId);
7454543ef51SXin LI   UNUSED_P(publicId);
7464543ef51SXin LI   ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
7474543ef51SXin LI   if (ext_parser == NULL)
7484543ef51SXin LI     fail("Could not create external entity parser");
7494543ef51SXin LI   XML_SetCharacterDataHandler(ext_parser, rsqb_handler);
7504543ef51SXin LI   if (_XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE)
7514543ef51SXin LI       != XML_STATUS_ERROR)
7524543ef51SXin LI     fail("Async entity error not caught");
7534543ef51SXin LI   if (XML_GetErrorCode(ext_parser) != XML_ERROR_ASYNC_ENTITY)
7544543ef51SXin LI     xml_failure(ext_parser);
7554543ef51SXin LI   XML_ParserFree(ext_parser);
7564543ef51SXin LI   return XML_STATUS_OK;
7574543ef51SXin LI }
7584543ef51SXin LI 
7594543ef51SXin LI int XMLCALL
7604543ef51SXin LI external_entity_good_cdata_ascii(XML_Parser parser, const XML_Char *context,
7614543ef51SXin LI                                  const XML_Char *base, const XML_Char *systemId,
7624543ef51SXin LI                                  const XML_Char *publicId) {
7634543ef51SXin LI   const char *text = "<a><![CDATA[<greeting>Hello, world!</greeting>]]></a>";
7644543ef51SXin LI   const XML_Char *expected = XCS("<greeting>Hello, world!</greeting>");
7654543ef51SXin LI   CharData storage;
7664543ef51SXin LI   XML_Parser ext_parser;
7674543ef51SXin LI 
7684543ef51SXin LI   UNUSED_P(base);
7694543ef51SXin LI   UNUSED_P(systemId);
7704543ef51SXin LI   UNUSED_P(publicId);
7714543ef51SXin LI   CharData_Init(&storage);
7724543ef51SXin LI   ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
7734543ef51SXin LI   if (ext_parser == NULL)
7744543ef51SXin LI     fail("Could not create external entity parser");
7754543ef51SXin LI   XML_SetUserData(ext_parser, &storage);
7764543ef51SXin LI   XML_SetCharacterDataHandler(ext_parser, accumulate_characters);
7774543ef51SXin LI 
7784543ef51SXin LI   if (_XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE)
7794543ef51SXin LI       == XML_STATUS_ERROR)
7804543ef51SXin LI     xml_failure(ext_parser);
7814543ef51SXin LI   CharData_CheckXMLChars(&storage, expected);
7824543ef51SXin LI 
7834543ef51SXin LI   XML_ParserFree(ext_parser);
7844543ef51SXin LI   return XML_STATUS_OK;
7854543ef51SXin LI }
7864543ef51SXin LI 
7874543ef51SXin LI int XMLCALL
7884543ef51SXin LI external_entity_param_checker(XML_Parser parser, const XML_Char *context,
7894543ef51SXin LI                               const XML_Char *base, const XML_Char *systemId,
7904543ef51SXin LI                               const XML_Char *publicId) {
7914543ef51SXin LI   const char *text = "<!-- Subordinate parser -->\n"
7924543ef51SXin LI                      "<!ELEMENT doc (#PCDATA)*>";
7934543ef51SXin LI   XML_Parser ext_parser;
7944543ef51SXin LI 
7954543ef51SXin LI   UNUSED_P(base);
7964543ef51SXin LI   UNUSED_P(systemId);
7974543ef51SXin LI   UNUSED_P(publicId);
7984543ef51SXin LI   ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
7994543ef51SXin LI   if (ext_parser == NULL)
8004543ef51SXin LI     fail("Could not create external entity parser");
8014543ef51SXin LI   g_handler_data = ext_parser;
8024543ef51SXin LI   if (_XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE)
8034543ef51SXin LI       == XML_STATUS_ERROR) {
8044543ef51SXin LI     xml_failure(parser);
8054543ef51SXin LI     return XML_STATUS_ERROR;
8064543ef51SXin LI   }
8074543ef51SXin LI   g_handler_data = parser;
8084543ef51SXin LI   XML_ParserFree(ext_parser);
8094543ef51SXin LI   return XML_STATUS_OK;
8104543ef51SXin LI }
8114543ef51SXin LI 
8124543ef51SXin LI int XMLCALL
8134543ef51SXin LI external_entity_ref_param_checker(XML_Parser parameter, const XML_Char *context,
8144543ef51SXin LI                                   const XML_Char *base,
8154543ef51SXin LI                                   const XML_Char *systemId,
8164543ef51SXin LI                                   const XML_Char *publicId) {
8174543ef51SXin LI   const char *text = "<!ELEMENT doc (#PCDATA)*>";
8184543ef51SXin LI   XML_Parser ext_parser;
8194543ef51SXin LI 
8204543ef51SXin LI   UNUSED_P(base);
8214543ef51SXin LI   UNUSED_P(systemId);
8224543ef51SXin LI   UNUSED_P(publicId);
8234543ef51SXin LI   if ((void *)parameter != g_handler_data)
8244543ef51SXin LI     fail("External entity ref handler parameter not correct");
8254543ef51SXin LI 
8264543ef51SXin LI   /* Here we use the global 'parser' variable */
8274543ef51SXin LI   ext_parser = XML_ExternalEntityParserCreate(g_parser, context, NULL);
8284543ef51SXin LI   if (ext_parser == NULL)
8294543ef51SXin LI     fail("Could not create external entity parser");
8304543ef51SXin LI   if (_XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE)
8314543ef51SXin LI       == XML_STATUS_ERROR)
8324543ef51SXin LI     xml_failure(ext_parser);
8334543ef51SXin LI 
8344543ef51SXin LI   XML_ParserFree(ext_parser);
8354543ef51SXin LI   return XML_STATUS_OK;
8364543ef51SXin LI }
8374543ef51SXin LI 
8384543ef51SXin LI int XMLCALL
8394543ef51SXin LI external_entity_param(XML_Parser parser, const XML_Char *context,
8404543ef51SXin LI                       const XML_Char *base, const XML_Char *systemId,
8414543ef51SXin LI                       const XML_Char *publicId) {
8424543ef51SXin LI   const char *text1 = "<!ELEMENT doc EMPTY>\n"
8434543ef51SXin LI                       "<!ENTITY % e1 SYSTEM '004-2.ent'>\n"
8444543ef51SXin LI                       "<!ENTITY % e2 '%e1;'>\n"
8454543ef51SXin LI                       "%e1;\n";
8464543ef51SXin LI   const char *text2 = "<!ELEMENT el EMPTY>\n"
8474543ef51SXin LI                       "<el/>\n";
8484543ef51SXin LI   XML_Parser ext_parser;
8494543ef51SXin LI 
8504543ef51SXin LI   UNUSED_P(base);
8514543ef51SXin LI   UNUSED_P(publicId);
8524543ef51SXin LI   if (systemId == NULL)
8534543ef51SXin LI     return XML_STATUS_OK;
8544543ef51SXin LI 
8554543ef51SXin LI   ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
8564543ef51SXin LI   if (ext_parser == NULL)
8574543ef51SXin LI     fail("Could not create external entity parser");
8584543ef51SXin LI 
8594543ef51SXin LI   if (! xcstrcmp(systemId, XCS("004-1.ent"))) {
8604543ef51SXin LI     if (_XML_Parse_SINGLE_BYTES(ext_parser, text1, (int)strlen(text1), XML_TRUE)
8614543ef51SXin LI         != XML_STATUS_ERROR)
8624543ef51SXin LI       fail("Inner DTD with invalid tag not rejected");
8634543ef51SXin LI     if (XML_GetErrorCode(ext_parser) != XML_ERROR_EXTERNAL_ENTITY_HANDLING)
8644543ef51SXin LI       xml_failure(ext_parser);
8654543ef51SXin LI   } else if (! xcstrcmp(systemId, XCS("004-2.ent"))) {
8664543ef51SXin LI     if (_XML_Parse_SINGLE_BYTES(ext_parser, text2, (int)strlen(text2), XML_TRUE)
8674543ef51SXin LI         != XML_STATUS_ERROR)
8684543ef51SXin LI       fail("Invalid tag in external param not rejected");
8694543ef51SXin LI     if (XML_GetErrorCode(ext_parser) != XML_ERROR_SYNTAX)
8704543ef51SXin LI       xml_failure(ext_parser);
8714543ef51SXin LI   } else {
8724543ef51SXin LI     fail("Unknown system ID");
8734543ef51SXin LI   }
8744543ef51SXin LI 
8754543ef51SXin LI   XML_ParserFree(ext_parser);
8764543ef51SXin LI   return XML_STATUS_ERROR;
8774543ef51SXin LI }
8784543ef51SXin LI 
8794543ef51SXin LI int XMLCALL
8804543ef51SXin LI external_entity_load_ignore(XML_Parser parser, const XML_Char *context,
8814543ef51SXin LI                             const XML_Char *base, const XML_Char *systemId,
8824543ef51SXin LI                             const XML_Char *publicId) {
8834543ef51SXin LI   const char *text = "<![IGNORE[<!ELEMENT e (#PCDATA)*>]]>";
8844543ef51SXin LI   XML_Parser ext_parser;
8854543ef51SXin LI 
8864543ef51SXin LI   UNUSED_P(base);
8874543ef51SXin LI   UNUSED_P(systemId);
8884543ef51SXin LI   UNUSED_P(publicId);
8894543ef51SXin LI   ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
8904543ef51SXin LI   if (ext_parser == NULL)
8914543ef51SXin LI     fail("Could not create external entity parser");
8924543ef51SXin LI   if (_XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE)
8934543ef51SXin LI       == XML_STATUS_ERROR)
8944543ef51SXin LI     xml_failure(parser);
8954543ef51SXin LI 
8964543ef51SXin LI   XML_ParserFree(ext_parser);
8974543ef51SXin LI   return XML_STATUS_OK;
8984543ef51SXin LI }
8994543ef51SXin LI 
9004543ef51SXin LI int XMLCALL
9014543ef51SXin LI external_entity_load_ignore_utf16(XML_Parser parser, const XML_Char *context,
9024543ef51SXin LI                                   const XML_Char *base,
9034543ef51SXin LI                                   const XML_Char *systemId,
9044543ef51SXin LI                                   const XML_Char *publicId) {
9054543ef51SXin LI   const char text[] =
9064543ef51SXin LI       /* <![IGNORE[<!ELEMENT e (#PCDATA)*>]]> */
9074543ef51SXin LI       "<\0!\0[\0I\0G\0N\0O\0R\0E\0[\0"
9084543ef51SXin LI       "<\0!\0E\0L\0E\0M\0E\0N\0T\0 \0e\0 \0"
9094543ef51SXin LI       "(\0#\0P\0C\0D\0A\0T\0A\0)\0*\0>\0]\0]\0>\0";
9104543ef51SXin LI   XML_Parser ext_parser;
9114543ef51SXin LI 
9124543ef51SXin LI   UNUSED_P(base);
9134543ef51SXin LI   UNUSED_P(systemId);
9144543ef51SXin LI   UNUSED_P(publicId);
9154543ef51SXin LI   ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
9164543ef51SXin LI   if (ext_parser == NULL)
9174543ef51SXin LI     fail("Could not create external entity parser");
9184543ef51SXin LI   if (_XML_Parse_SINGLE_BYTES(ext_parser, text, (int)sizeof(text) - 1, XML_TRUE)
9194543ef51SXin LI       == XML_STATUS_ERROR)
9204543ef51SXin LI     xml_failure(parser);
9214543ef51SXin LI 
9224543ef51SXin LI   XML_ParserFree(ext_parser);
9234543ef51SXin LI   return XML_STATUS_OK;
9244543ef51SXin LI }
9254543ef51SXin LI 
9264543ef51SXin LI int XMLCALL
9274543ef51SXin LI external_entity_load_ignore_utf16_be(XML_Parser parser, const XML_Char *context,
9284543ef51SXin LI                                      const XML_Char *base,
9294543ef51SXin LI                                      const XML_Char *systemId,
9304543ef51SXin LI                                      const XML_Char *publicId) {
9314543ef51SXin LI   const char text[] =
9324543ef51SXin LI       /* <![IGNORE[<!ELEMENT e (#PCDATA)*>]]> */
9334543ef51SXin LI       "\0<\0!\0[\0I\0G\0N\0O\0R\0E\0["
9344543ef51SXin LI       "\0<\0!\0E\0L\0E\0M\0E\0N\0T\0 \0e\0 "
9354543ef51SXin LI       "\0(\0#\0P\0C\0D\0A\0T\0A\0)\0*\0>\0]\0]\0>";
9364543ef51SXin LI   XML_Parser ext_parser;
9374543ef51SXin LI 
9384543ef51SXin LI   UNUSED_P(base);
9394543ef51SXin LI   UNUSED_P(systemId);
9404543ef51SXin LI   UNUSED_P(publicId);
9414543ef51SXin LI   ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
9424543ef51SXin LI   if (ext_parser == NULL)
9434543ef51SXin LI     fail("Could not create external entity parser");
9444543ef51SXin LI   if (_XML_Parse_SINGLE_BYTES(ext_parser, text, (int)sizeof(text) - 1, XML_TRUE)
9454543ef51SXin LI       == XML_STATUS_ERROR)
9464543ef51SXin LI     xml_failure(parser);
9474543ef51SXin LI 
9484543ef51SXin LI   XML_ParserFree(ext_parser);
9494543ef51SXin LI   return XML_STATUS_OK;
9504543ef51SXin LI }
9514543ef51SXin LI 
9524543ef51SXin LI int XMLCALL
9534543ef51SXin LI external_entity_valuer(XML_Parser parser, const XML_Char *context,
9544543ef51SXin LI                        const XML_Char *base, const XML_Char *systemId,
9554543ef51SXin LI                        const XML_Char *publicId) {
9564543ef51SXin LI   const char *text1 = "<!ELEMENT doc EMPTY>\n"
9574543ef51SXin LI                       "<!ENTITY % e1 SYSTEM '004-2.ent'>\n"
9584543ef51SXin LI                       "<!ENTITY % e2 '%e1;'>\n"
9594543ef51SXin LI                       "%e1;\n";
9604543ef51SXin LI   XML_Parser ext_parser;
9614543ef51SXin LI 
9624543ef51SXin LI   UNUSED_P(base);
9634543ef51SXin LI   UNUSED_P(publicId);
9644543ef51SXin LI   if (systemId == NULL)
9654543ef51SXin LI     return XML_STATUS_OK;
9664543ef51SXin LI   ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
9674543ef51SXin LI   if (ext_parser == NULL)
9684543ef51SXin LI     fail("Could not create external entity parser");
9694543ef51SXin LI   if (! xcstrcmp(systemId, XCS("004-1.ent"))) {
9704543ef51SXin LI     if (_XML_Parse_SINGLE_BYTES(ext_parser, text1, (int)strlen(text1), XML_TRUE)
9714543ef51SXin LI         == XML_STATUS_ERROR)
9724543ef51SXin LI       xml_failure(ext_parser);
9734543ef51SXin LI   } else if (! xcstrcmp(systemId, XCS("004-2.ent"))) {
9744543ef51SXin LI     ExtFaults *fault = (ExtFaults *)XML_GetUserData(parser);
9754543ef51SXin LI     enum XML_Status status;
9764543ef51SXin LI     enum XML_Error error;
9774543ef51SXin LI 
9784543ef51SXin LI     status = _XML_Parse_SINGLE_BYTES(ext_parser, fault->parse_text,
9794543ef51SXin LI                                      (int)strlen(fault->parse_text), XML_TRUE);
9804543ef51SXin LI     if (fault->error == XML_ERROR_NONE) {
9814543ef51SXin LI       if (status == XML_STATUS_ERROR)
9824543ef51SXin LI         xml_failure(ext_parser);
9834543ef51SXin LI     } else {
9844543ef51SXin LI       if (status != XML_STATUS_ERROR)
9854543ef51SXin LI         fail(fault->fail_text);
9864543ef51SXin LI       error = XML_GetErrorCode(ext_parser);
9874543ef51SXin LI       if (error != fault->error
9884543ef51SXin LI           && (fault->error != XML_ERROR_XML_DECL
9894543ef51SXin LI               || error != XML_ERROR_TEXT_DECL))
9904543ef51SXin LI         xml_failure(ext_parser);
9914543ef51SXin LI     }
9924543ef51SXin LI   }
9934543ef51SXin LI 
9944543ef51SXin LI   XML_ParserFree(ext_parser);
9954543ef51SXin LI   return XML_STATUS_OK;
9964543ef51SXin LI }
9974543ef51SXin LI 
9984543ef51SXin LI int XMLCALL
9994543ef51SXin LI external_entity_not_standalone(XML_Parser parser, const XML_Char *context,
10004543ef51SXin LI                                const XML_Char *base, const XML_Char *systemId,
10014543ef51SXin LI                                const XML_Char *publicId) {
10024543ef51SXin LI   const char *text1 = "<!ELEMENT doc EMPTY>\n"
10034543ef51SXin LI                       "<!ENTITY % e1 SYSTEM 'bar'>\n"
10044543ef51SXin LI                       "%e1;\n";
10054543ef51SXin LI   const char *text2 = "<!ATTLIST doc a1 CDATA 'value'>";
10064543ef51SXin LI   XML_Parser ext_parser;
10074543ef51SXin LI 
10084543ef51SXin LI   UNUSED_P(base);
10094543ef51SXin LI   UNUSED_P(publicId);
10104543ef51SXin LI   if (systemId == NULL)
10114543ef51SXin LI     return XML_STATUS_OK;
10124543ef51SXin LI   ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
10134543ef51SXin LI   if (ext_parser == NULL)
10144543ef51SXin LI     fail("Could not create external entity parser");
10154543ef51SXin LI   if (! xcstrcmp(systemId, XCS("foo"))) {
10164543ef51SXin LI     XML_SetNotStandaloneHandler(ext_parser, reject_not_standalone_handler);
10174543ef51SXin LI     if (_XML_Parse_SINGLE_BYTES(ext_parser, text1, (int)strlen(text1), XML_TRUE)
10184543ef51SXin LI         != XML_STATUS_ERROR)
10194543ef51SXin LI       fail("Expected not standalone rejection");
10204543ef51SXin LI     if (XML_GetErrorCode(ext_parser) != XML_ERROR_NOT_STANDALONE)
10214543ef51SXin LI       xml_failure(ext_parser);
10224543ef51SXin LI     XML_SetNotStandaloneHandler(ext_parser, NULL);
10234543ef51SXin LI     XML_ParserFree(ext_parser);
10244543ef51SXin LI     return XML_STATUS_ERROR;
10254543ef51SXin LI   } else if (! xcstrcmp(systemId, XCS("bar"))) {
10264543ef51SXin LI     if (_XML_Parse_SINGLE_BYTES(ext_parser, text2, (int)strlen(text2), XML_TRUE)
10274543ef51SXin LI         == XML_STATUS_ERROR)
10284543ef51SXin LI       xml_failure(ext_parser);
10294543ef51SXin LI   }
10304543ef51SXin LI 
10314543ef51SXin LI   XML_ParserFree(ext_parser);
10324543ef51SXin LI   return XML_STATUS_OK;
10334543ef51SXin LI }
10344543ef51SXin LI 
10354543ef51SXin LI int XMLCALL
10364543ef51SXin LI external_entity_value_aborter(XML_Parser parser, const XML_Char *context,
10374543ef51SXin LI                               const XML_Char *base, const XML_Char *systemId,
10384543ef51SXin LI                               const XML_Char *publicId) {
10394543ef51SXin LI   const char *text1 = "<!ELEMENT doc EMPTY>\n"
10404543ef51SXin LI                       "<!ENTITY % e1 SYSTEM '004-2.ent'>\n"
10414543ef51SXin LI                       "<!ENTITY % e2 '%e1;'>\n"
10424543ef51SXin LI                       "%e1;\n";
10434543ef51SXin LI   const char *text2 = "<?xml version='1.0' encoding='utf-8'?>";
10444543ef51SXin LI   XML_Parser ext_parser;
10454543ef51SXin LI 
10464543ef51SXin LI   UNUSED_P(base);
10474543ef51SXin LI   UNUSED_P(publicId);
10484543ef51SXin LI   if (systemId == NULL)
10494543ef51SXin LI     return XML_STATUS_OK;
10504543ef51SXin LI   ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
10514543ef51SXin LI   if (ext_parser == NULL)
10524543ef51SXin LI     fail("Could not create external entity parser");
10534543ef51SXin LI   if (! xcstrcmp(systemId, XCS("004-1.ent"))) {
10544543ef51SXin LI     if (_XML_Parse_SINGLE_BYTES(ext_parser, text1, (int)strlen(text1), XML_TRUE)
10554543ef51SXin LI         == XML_STATUS_ERROR)
10564543ef51SXin LI       xml_failure(ext_parser);
10574543ef51SXin LI   }
10584543ef51SXin LI   if (! xcstrcmp(systemId, XCS("004-2.ent"))) {
10594543ef51SXin LI     XML_SetXmlDeclHandler(ext_parser, entity_suspending_xdecl_handler);
10604543ef51SXin LI     XML_SetUserData(ext_parser, ext_parser);
10614543ef51SXin LI     if (_XML_Parse_SINGLE_BYTES(ext_parser, text2, (int)strlen(text2), XML_TRUE)
10624543ef51SXin LI         != XML_STATUS_ERROR)
10634543ef51SXin LI       fail("Aborted parse not faulted");
10644543ef51SXin LI     if (XML_GetErrorCode(ext_parser) != XML_ERROR_ABORTED)
10654543ef51SXin LI       xml_failure(ext_parser);
10664543ef51SXin LI   }
10674543ef51SXin LI 
10684543ef51SXin LI   XML_ParserFree(ext_parser);
10694543ef51SXin LI   return XML_STATUS_OK;
10704543ef51SXin LI }
10714543ef51SXin LI 
10724543ef51SXin LI int XMLCALL
10734543ef51SXin LI external_entity_public(XML_Parser parser, const XML_Char *context,
10744543ef51SXin LI                        const XML_Char *base, const XML_Char *systemId,
10754543ef51SXin LI                        const XML_Char *publicId) {
10764543ef51SXin LI   const char *text1 = (const char *)XML_GetUserData(parser);
10774543ef51SXin LI   const char *text2 = "<!ATTLIST doc a CDATA 'value'>";
10784543ef51SXin LI   const char *text = NULL;
10794543ef51SXin LI   XML_Parser ext_parser;
10804543ef51SXin LI   int parse_res;
10814543ef51SXin LI 
10824543ef51SXin LI   UNUSED_P(base);
10834543ef51SXin LI   ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
10844543ef51SXin LI   if (ext_parser == NULL)
10854543ef51SXin LI     return XML_STATUS_ERROR;
10864543ef51SXin LI   if (systemId != NULL && ! xcstrcmp(systemId, XCS("http://example.org/"))) {
10874543ef51SXin LI     text = text1;
10884543ef51SXin LI   } else if (publicId != NULL && ! xcstrcmp(publicId, XCS("foo"))) {
10894543ef51SXin LI     text = text2;
10904543ef51SXin LI   } else
10914543ef51SXin LI     fail("Unexpected parameters to external entity parser");
10924543ef51SXin LI   assert(text != NULL);
10934543ef51SXin LI   parse_res
10944543ef51SXin LI       = _XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE);
10954543ef51SXin LI   XML_ParserFree(ext_parser);
10964543ef51SXin LI   return parse_res;
10974543ef51SXin LI }
10984543ef51SXin LI 
10994543ef51SXin LI int XMLCALL
11004543ef51SXin LI external_entity_devaluer(XML_Parser parser, const XML_Char *context,
11014543ef51SXin LI                          const XML_Char *base, const XML_Char *systemId,
11024543ef51SXin LI                          const XML_Char *publicId) {
11034543ef51SXin LI   const char *text = "<!ELEMENT doc EMPTY>\n"
11044543ef51SXin LI                      "<!ENTITY % e1 SYSTEM 'bar'>\n"
11054543ef51SXin LI                      "%e1;\n";
11064543ef51SXin LI   XML_Parser ext_parser;
11074543ef51SXin LI   int clear_handler_flag = (XML_GetUserData(parser) != NULL);
11084543ef51SXin LI 
11094543ef51SXin LI   UNUSED_P(base);
11104543ef51SXin LI   UNUSED_P(publicId);
11114543ef51SXin LI   if (systemId == NULL || ! xcstrcmp(systemId, XCS("bar")))
11124543ef51SXin LI     return XML_STATUS_OK;
11134543ef51SXin LI   if (xcstrcmp(systemId, XCS("foo")))
11144543ef51SXin LI     fail("Unexpected system ID");
11154543ef51SXin LI   ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
11164543ef51SXin LI   if (ext_parser == NULL)
11174543ef51SXin LI     fail("Could note create external entity parser");
11184543ef51SXin LI   if (clear_handler_flag)
11194543ef51SXin LI     XML_SetExternalEntityRefHandler(ext_parser, NULL);
11204543ef51SXin LI   if (_XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE)
11214543ef51SXin LI       == XML_STATUS_ERROR)
11224543ef51SXin LI     xml_failure(ext_parser);
11234543ef51SXin LI 
11244543ef51SXin LI   XML_ParserFree(ext_parser);
11254543ef51SXin LI   return XML_STATUS_OK;
11264543ef51SXin LI }
11274543ef51SXin LI 
11284543ef51SXin LI int XMLCALL
11294543ef51SXin LI external_entity_oneshot_loader(XML_Parser parser, const XML_Char *context,
11304543ef51SXin LI                                const XML_Char *base, const XML_Char *systemId,
11314543ef51SXin LI                                const XML_Char *publicId) {
11324543ef51SXin LI   ExtHdlrData *test_data = (ExtHdlrData *)XML_GetUserData(parser);
11334543ef51SXin LI   XML_Parser ext_parser;
11344543ef51SXin LI 
11354543ef51SXin LI   UNUSED_P(base);
11364543ef51SXin LI   UNUSED_P(systemId);
11374543ef51SXin LI   UNUSED_P(publicId);
11384543ef51SXin LI   ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
11394543ef51SXin LI   if (ext_parser == NULL)
11404543ef51SXin LI     fail("Could not create external entity parser.");
11414543ef51SXin LI   /* Use the requested entity parser for further externals */
11424543ef51SXin LI   XML_SetExternalEntityRefHandler(ext_parser, test_data->handler);
11434543ef51SXin LI   if (_XML_Parse_SINGLE_BYTES(ext_parser, test_data->parse_text,
11444543ef51SXin LI                               (int)strlen(test_data->parse_text), XML_TRUE)
11454543ef51SXin LI       == XML_STATUS_ERROR) {
11464543ef51SXin LI     xml_failure(ext_parser);
11474543ef51SXin LI   }
11484543ef51SXin LI 
11494543ef51SXin LI   XML_ParserFree(ext_parser);
11504543ef51SXin LI   return XML_STATUS_OK;
11514543ef51SXin LI }
11524543ef51SXin LI 
11534543ef51SXin LI int XMLCALL
11544543ef51SXin LI external_entity_loader2(XML_Parser parser, const XML_Char *context,
11554543ef51SXin LI                         const XML_Char *base, const XML_Char *systemId,
11564543ef51SXin LI                         const XML_Char *publicId) {
11574543ef51SXin LI   ExtTest2 *test_data = (ExtTest2 *)XML_GetUserData(parser);
11584543ef51SXin LI   XML_Parser extparser;
11594543ef51SXin LI 
11604543ef51SXin LI   UNUSED_P(base);
11614543ef51SXin LI   UNUSED_P(systemId);
11624543ef51SXin LI   UNUSED_P(publicId);
11634543ef51SXin LI   extparser = XML_ExternalEntityParserCreate(parser, context, NULL);
11644543ef51SXin LI   if (extparser == NULL)
11654543ef51SXin LI     fail("Coulr not create external entity parser");
11664543ef51SXin LI   if (test_data->encoding != NULL) {
11674543ef51SXin LI     if (! XML_SetEncoding(extparser, test_data->encoding))
11684543ef51SXin LI       fail("XML_SetEncoding() ignored for external entity");
11694543ef51SXin LI   }
11704543ef51SXin LI   if (_XML_Parse_SINGLE_BYTES(extparser, test_data->parse_text,
11714543ef51SXin LI                               test_data->parse_len, XML_TRUE)
11724543ef51SXin LI       == XML_STATUS_ERROR) {
11734543ef51SXin LI     xml_failure(extparser);
11744543ef51SXin LI   }
11754543ef51SXin LI 
11764543ef51SXin LI   XML_ParserFree(extparser);
11774543ef51SXin LI   return XML_STATUS_OK;
11784543ef51SXin LI }
11794543ef51SXin LI 
11804543ef51SXin LI int XMLCALL
11814543ef51SXin LI external_entity_faulter2(XML_Parser parser, const XML_Char *context,
11824543ef51SXin LI                          const XML_Char *base, const XML_Char *systemId,
11834543ef51SXin LI                          const XML_Char *publicId) {
11844543ef51SXin LI   ExtFaults2 *test_data = (ExtFaults2 *)XML_GetUserData(parser);
11854543ef51SXin LI   XML_Parser extparser;
11864543ef51SXin LI 
11874543ef51SXin LI   UNUSED_P(base);
11884543ef51SXin LI   UNUSED_P(systemId);
11894543ef51SXin LI   UNUSED_P(publicId);
11904543ef51SXin LI   extparser = XML_ExternalEntityParserCreate(parser, context, NULL);
11914543ef51SXin LI   if (extparser == NULL)
11924543ef51SXin LI     fail("Could not create external entity parser");
11934543ef51SXin LI   if (test_data->encoding != NULL) {
11944543ef51SXin LI     if (! XML_SetEncoding(extparser, test_data->encoding))
11954543ef51SXin LI       fail("XML_SetEncoding() ignored for external entity");
11964543ef51SXin LI   }
11974543ef51SXin LI   if (_XML_Parse_SINGLE_BYTES(extparser, test_data->parse_text,
11984543ef51SXin LI                               test_data->parse_len, XML_TRUE)
11994543ef51SXin LI       != XML_STATUS_ERROR)
12004543ef51SXin LI     fail(test_data->fail_text);
12014543ef51SXin LI   if (XML_GetErrorCode(extparser) != test_data->error)
12024543ef51SXin LI     xml_failure(extparser);
12034543ef51SXin LI 
12044543ef51SXin LI   XML_ParserFree(extparser);
12054543ef51SXin LI   return XML_STATUS_ERROR;
12064543ef51SXin LI }
12074543ef51SXin LI 
12084543ef51SXin LI int XMLCALL
12094543ef51SXin LI external_entity_unfinished_attlist(XML_Parser parser, const XML_Char *context,
12104543ef51SXin LI                                    const XML_Char *base,
12114543ef51SXin LI                                    const XML_Char *systemId,
12124543ef51SXin LI                                    const XML_Char *publicId) {
12134543ef51SXin LI   const char *text = "<!ELEMENT barf ANY>\n"
12144543ef51SXin LI                      "<!ATTLIST barf my_attr (blah|%blah;a|foo) #REQUIRED>\n"
12154543ef51SXin LI                      "<!--COMMENT-->\n";
12164543ef51SXin LI   XML_Parser ext_parser;
12174543ef51SXin LI 
12184543ef51SXin LI   UNUSED_P(base);
12194543ef51SXin LI   UNUSED_P(publicId);
12204543ef51SXin LI   if (systemId == NULL)
12214543ef51SXin LI     return XML_STATUS_OK;
12224543ef51SXin LI 
12234543ef51SXin LI   ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
12244543ef51SXin LI   if (ext_parser == NULL)
12254543ef51SXin LI     fail("Could not create external entity parser");
12264543ef51SXin LI 
12274543ef51SXin LI   if (_XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE)
12284543ef51SXin LI       == XML_STATUS_ERROR)
12294543ef51SXin LI     xml_failure(ext_parser);
12304543ef51SXin LI 
12314543ef51SXin LI   XML_ParserFree(ext_parser);
12324543ef51SXin LI   return XML_STATUS_OK;
12334543ef51SXin LI }
12344543ef51SXin LI 
12354543ef51SXin LI int XMLCALL
12364543ef51SXin LI external_entity_handler(XML_Parser parser, const XML_Char *context,
12374543ef51SXin LI                         const XML_Char *base, const XML_Char *systemId,
12384543ef51SXin LI                         const XML_Char *publicId) {
12394543ef51SXin LI   void *user_data = XML_GetUserData(parser);
12404543ef51SXin LI   const char *text;
12414543ef51SXin LI   XML_Parser p2;
12424543ef51SXin LI 
12434543ef51SXin LI   UNUSED_P(base);
12444543ef51SXin LI   UNUSED_P(systemId);
12454543ef51SXin LI   UNUSED_P(publicId);
12464543ef51SXin LI   if (user_data == NULL)
12474543ef51SXin LI     text = ("<!ELEMENT doc (e+)>\n"
12484543ef51SXin LI             "<!ATTLIST doc xmlns CDATA #IMPLIED>\n"
12494543ef51SXin LI             "<!ELEMENT e EMPTY>\n");
12504543ef51SXin LI   else
12514543ef51SXin LI     text = ("<?xml version='1.0' encoding='us-ascii'?>"
12524543ef51SXin LI             "<e/>");
12534543ef51SXin LI 
12544543ef51SXin LI   /* Set user data to any non-NULL value */
12554543ef51SXin LI   XML_SetUserData(parser, parser);
12564543ef51SXin LI   p2 = XML_ExternalEntityParserCreate(parser, context, NULL);
12574543ef51SXin LI   if (_XML_Parse_SINGLE_BYTES(p2, text, (int)strlen(text), XML_TRUE)
12584543ef51SXin LI       == XML_STATUS_ERROR) {
12594543ef51SXin LI     xml_failure(p2);
12604543ef51SXin LI     return XML_STATUS_ERROR;
12614543ef51SXin LI   }
12624543ef51SXin LI   XML_ParserFree(p2);
12634543ef51SXin LI   return XML_STATUS_OK;
12644543ef51SXin LI }
12654543ef51SXin LI 
12664543ef51SXin LI int XMLCALL
12674543ef51SXin LI external_entity_duff_loader(XML_Parser parser, const XML_Char *context,
12684543ef51SXin LI                             const XML_Char *base, const XML_Char *systemId,
12694543ef51SXin LI                             const XML_Char *publicId) {
12704543ef51SXin LI   XML_Parser new_parser;
12714543ef51SXin LI   unsigned int i;
12724543ef51SXin LI   const unsigned int max_alloc_count = 10;
12734543ef51SXin LI 
12744543ef51SXin LI   UNUSED_P(base);
12754543ef51SXin LI   UNUSED_P(systemId);
12764543ef51SXin LI   UNUSED_P(publicId);
12774543ef51SXin LI   /* Try a few different allocation levels */
12784543ef51SXin LI   for (i = 0; i < max_alloc_count; i++) {
12794543ef51SXin LI     g_allocation_count = i;
12804543ef51SXin LI     new_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
12814543ef51SXin LI     if (new_parser != NULL) {
12824543ef51SXin LI       XML_ParserFree(new_parser);
12834543ef51SXin LI       break;
12844543ef51SXin LI     }
12854543ef51SXin LI   }
12864543ef51SXin LI   if (i == 0)
12874543ef51SXin LI     fail("External parser creation ignored failing allocator");
12884543ef51SXin LI   else if (i == max_alloc_count)
12894543ef51SXin LI     fail("Extern parser not created with max allocation count");
12904543ef51SXin LI 
12914543ef51SXin LI   /* Make sure other random allocation doesn't now fail */
12924543ef51SXin LI   g_allocation_count = ALLOC_ALWAYS_SUCCEED;
12934543ef51SXin LI 
12944543ef51SXin LI   /* Make sure the failure code path is executed too */
12954543ef51SXin LI   return XML_STATUS_ERROR;
12964543ef51SXin LI }
12974543ef51SXin LI 
12984543ef51SXin LI int XMLCALL
12994543ef51SXin LI external_entity_dbl_handler(XML_Parser parser, const XML_Char *context,
13004543ef51SXin LI                             const XML_Char *base, const XML_Char *systemId,
13014543ef51SXin LI                             const XML_Char *publicId) {
13024543ef51SXin LI   int *pcallno = (int *)XML_GetUserData(parser);
13034543ef51SXin LI   int callno = *pcallno;
13044543ef51SXin LI   const char *text;
13054543ef51SXin LI   XML_Parser new_parser = NULL;
13064543ef51SXin LI   int i;
13074543ef51SXin LI   const int max_alloc_count = 20;
13084543ef51SXin LI 
13094543ef51SXin LI   UNUSED_P(base);
13104543ef51SXin LI   UNUSED_P(systemId);
13114543ef51SXin LI   UNUSED_P(publicId);
13124543ef51SXin LI   if (callno == 0) {
13134543ef51SXin LI     /* First time through, check how many calls to malloc occur */
13144543ef51SXin LI     text = ("<!ELEMENT doc (e+)>\n"
13154543ef51SXin LI             "<!ATTLIST doc xmlns CDATA #IMPLIED>\n"
13164543ef51SXin LI             "<!ELEMENT e EMPTY>\n");
13174543ef51SXin LI     g_allocation_count = 10000;
13184543ef51SXin LI     new_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
13194543ef51SXin LI     if (new_parser == NULL) {
13204543ef51SXin LI       fail("Unable to allocate first external parser");
13214543ef51SXin LI       return XML_STATUS_ERROR;
13224543ef51SXin LI     }
13234543ef51SXin LI     /* Stash the number of calls in the user data */
13244543ef51SXin LI     *pcallno = 10000 - g_allocation_count;
13254543ef51SXin LI   } else {
13264543ef51SXin LI     text = ("<?xml version='1.0' encoding='us-ascii'?>"
13274543ef51SXin LI             "<e/>");
13284543ef51SXin LI     /* Try at varying levels to exercise more code paths */
13294543ef51SXin LI     for (i = 0; i < max_alloc_count; i++) {
13304543ef51SXin LI       g_allocation_count = callno + i;
13314543ef51SXin LI       new_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
13324543ef51SXin LI       if (new_parser != NULL)
13334543ef51SXin LI         break;
13344543ef51SXin LI     }
13354543ef51SXin LI     if (i == 0) {
13364543ef51SXin LI       fail("Second external parser unexpectedly created");
13374543ef51SXin LI       XML_ParserFree(new_parser);
13384543ef51SXin LI       return XML_STATUS_ERROR;
13394543ef51SXin LI     } else if (i == max_alloc_count) {
13404543ef51SXin LI       fail("Second external parser not created");
13414543ef51SXin LI       return XML_STATUS_ERROR;
13424543ef51SXin LI     }
13434543ef51SXin LI   }
13444543ef51SXin LI 
13454543ef51SXin LI   g_allocation_count = ALLOC_ALWAYS_SUCCEED;
13464543ef51SXin LI   if (_XML_Parse_SINGLE_BYTES(new_parser, text, (int)strlen(text), XML_TRUE)
13474543ef51SXin LI       == XML_STATUS_ERROR) {
13484543ef51SXin LI     xml_failure(new_parser);
13494543ef51SXin LI     return XML_STATUS_ERROR;
13504543ef51SXin LI   }
13514543ef51SXin LI   XML_ParserFree(new_parser);
13524543ef51SXin LI   return XML_STATUS_OK;
13534543ef51SXin LI }
13544543ef51SXin LI 
13554543ef51SXin LI int XMLCALL
13564543ef51SXin LI external_entity_dbl_handler_2(XML_Parser parser, const XML_Char *context,
13574543ef51SXin LI                               const XML_Char *base, const XML_Char *systemId,
13584543ef51SXin LI                               const XML_Char *publicId) {
13594543ef51SXin LI   int *pcallno = (int *)XML_GetUserData(parser);
13604543ef51SXin LI   int callno = *pcallno;
13614543ef51SXin LI   const char *text;
13624543ef51SXin LI   XML_Parser new_parser;
13634543ef51SXin LI   enum XML_Status rv;
13644543ef51SXin LI 
13654543ef51SXin LI   UNUSED_P(base);
13664543ef51SXin LI   UNUSED_P(systemId);
13674543ef51SXin LI   UNUSED_P(publicId);
13684543ef51SXin LI   if (callno == 0) {
13694543ef51SXin LI     /* Try different allocation levels for whole exercise */
13704543ef51SXin LI     text = ("<!ELEMENT doc (e+)>\n"
13714543ef51SXin LI             "<!ATTLIST doc xmlns CDATA #IMPLIED>\n"
13724543ef51SXin LI             "<!ELEMENT e EMPTY>\n");
13734543ef51SXin LI     *pcallno = 1;
13744543ef51SXin LI     new_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
13754543ef51SXin LI     if (new_parser == NULL)
13764543ef51SXin LI       return XML_STATUS_ERROR;
13774543ef51SXin LI     rv = _XML_Parse_SINGLE_BYTES(new_parser, text, (int)strlen(text), XML_TRUE);
13784543ef51SXin LI   } else {
13794543ef51SXin LI     /* Just run through once */
13804543ef51SXin LI     text = ("<?xml version='1.0' encoding='us-ascii'?>"
13814543ef51SXin LI             "<e/>");
13824543ef51SXin LI     new_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
13834543ef51SXin LI     if (new_parser == NULL)
13844543ef51SXin LI       return XML_STATUS_ERROR;
13854543ef51SXin LI     rv = _XML_Parse_SINGLE_BYTES(new_parser, text, (int)strlen(text), XML_TRUE);
13864543ef51SXin LI   }
13874543ef51SXin LI   XML_ParserFree(new_parser);
13884543ef51SXin LI   if (rv == XML_STATUS_ERROR)
13894543ef51SXin LI     return XML_STATUS_ERROR;
13904543ef51SXin LI   return XML_STATUS_OK;
13914543ef51SXin LI }
13924543ef51SXin LI 
13934543ef51SXin LI int XMLCALL
13944543ef51SXin LI external_entity_alloc_set_encoding(XML_Parser parser, const XML_Char *context,
13954543ef51SXin LI                                    const XML_Char *base,
13964543ef51SXin LI                                    const XML_Char *systemId,
13974543ef51SXin LI                                    const XML_Char *publicId) {
13984543ef51SXin LI   /* As for external_entity_loader() */
13994543ef51SXin LI   const char *text = "<?xml encoding='iso-8859-3'?>"
14004543ef51SXin LI                      "\xC3\xA9";
14014543ef51SXin LI   XML_Parser ext_parser;
14024543ef51SXin LI   enum XML_Status status;
14034543ef51SXin LI 
14044543ef51SXin LI   UNUSED_P(base);
14054543ef51SXin LI   UNUSED_P(systemId);
14064543ef51SXin LI   UNUSED_P(publicId);
14074543ef51SXin LI   ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
14084543ef51SXin LI   if (ext_parser == NULL)
14094543ef51SXin LI     return XML_STATUS_ERROR;
14104543ef51SXin LI   if (! XML_SetEncoding(ext_parser, XCS("utf-8"))) {
14114543ef51SXin LI     XML_ParserFree(ext_parser);
14124543ef51SXin LI     return XML_STATUS_ERROR;
14134543ef51SXin LI   }
14144543ef51SXin LI   status
14154543ef51SXin LI       = _XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE);
14164543ef51SXin LI   XML_ParserFree(ext_parser);
14174543ef51SXin LI   if (status == XML_STATUS_ERROR)
14184543ef51SXin LI     return XML_STATUS_ERROR;
14194543ef51SXin LI   return XML_STATUS_OK;
14204543ef51SXin LI }
14214543ef51SXin LI 
14224543ef51SXin LI int XMLCALL
14234543ef51SXin LI external_entity_reallocator(XML_Parser parser, const XML_Char *context,
14244543ef51SXin LI                             const XML_Char *base, const XML_Char *systemId,
14254543ef51SXin LI                             const XML_Char *publicId) {
14264543ef51SXin LI   const char *text = get_buffer_test_text;
14274543ef51SXin LI   XML_Parser ext_parser;
14284543ef51SXin LI   void *buffer;
14294543ef51SXin LI   enum XML_Status status;
14304543ef51SXin LI 
14314543ef51SXin LI   UNUSED_P(base);
14324543ef51SXin LI   UNUSED_P(systemId);
14334543ef51SXin LI   UNUSED_P(publicId);
14344543ef51SXin LI   ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
14354543ef51SXin LI   if (ext_parser == NULL)
14364543ef51SXin LI     fail("Could not create external entity parser");
14374543ef51SXin LI 
14384543ef51SXin LI   g_reallocation_count = *(int *)XML_GetUserData(parser);
14394543ef51SXin LI   buffer = XML_GetBuffer(ext_parser, 1536);
14404543ef51SXin LI   if (buffer == NULL)
14414543ef51SXin LI     fail("Buffer allocation failed");
14424543ef51SXin LI   assert(buffer != NULL);
14434543ef51SXin LI   memcpy(buffer, text, strlen(text));
14444543ef51SXin LI   status = XML_ParseBuffer(ext_parser, (int)strlen(text), XML_FALSE);
14454543ef51SXin LI   g_reallocation_count = -1;
14464543ef51SXin LI   XML_ParserFree(ext_parser);
14474543ef51SXin LI   return (status == XML_STATUS_OK) ? XML_STATUS_OK : XML_STATUS_ERROR;
14484543ef51SXin LI }
14494543ef51SXin LI 
14504543ef51SXin LI int XMLCALL
14514543ef51SXin LI external_entity_alloc(XML_Parser parser, const XML_Char *context,
14524543ef51SXin LI                       const XML_Char *base, const XML_Char *systemId,
14534543ef51SXin LI                       const XML_Char *publicId) {
14544543ef51SXin LI   const char *text = (const char *)XML_GetUserData(parser);
14554543ef51SXin LI   XML_Parser ext_parser;
14564543ef51SXin LI   int parse_res;
14574543ef51SXin LI 
14584543ef51SXin LI   UNUSED_P(base);
14594543ef51SXin LI   UNUSED_P(systemId);
14604543ef51SXin LI   UNUSED_P(publicId);
14614543ef51SXin LI   ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
14624543ef51SXin LI   if (ext_parser == NULL)
14634543ef51SXin LI     return XML_STATUS_ERROR;
14644543ef51SXin LI   parse_res
14654543ef51SXin LI       = _XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE);
14664543ef51SXin LI   XML_ParserFree(ext_parser);
14674543ef51SXin LI   return parse_res;
14684543ef51SXin LI }
14694543ef51SXin LI 
14704543ef51SXin LI int XMLCALL
14714543ef51SXin LI external_entity_parser_create_alloc_fail_handler(XML_Parser parser,
14724543ef51SXin LI                                                  const XML_Char *context,
14734543ef51SXin LI                                                  const XML_Char *base,
14744543ef51SXin LI                                                  const XML_Char *systemId,
14754543ef51SXin LI                                                  const XML_Char *publicId) {
14764543ef51SXin LI   UNUSED_P(base);
14774543ef51SXin LI   UNUSED_P(systemId);
14784543ef51SXin LI   UNUSED_P(publicId);
14794543ef51SXin LI 
14804543ef51SXin LI   if (context != NULL)
14814543ef51SXin LI     fail("Unexpected non-NULL context");
14824543ef51SXin LI 
14834543ef51SXin LI   // The following number intends to fail the upcoming allocation in line
14844543ef51SXin LI   // "parser->m_protocolEncodingName = copyString(encodingName,
14854543ef51SXin LI   // &(parser->m_mem));" in function parserInit.
14864543ef51SXin LI   g_allocation_count = 3;
14874543ef51SXin LI 
14884543ef51SXin LI   const XML_Char *const encodingName = XCS("UTF-8"); // needs something non-NULL
14894543ef51SXin LI   const XML_Parser ext_parser
14904543ef51SXin LI       = XML_ExternalEntityParserCreate(parser, context, encodingName);
14914543ef51SXin LI   if (ext_parser != NULL)
14924543ef51SXin LI     fail(
14934543ef51SXin LI         "Call to XML_ExternalEntityParserCreate was expected to fail out-of-memory");
14944543ef51SXin LI 
14954543ef51SXin LI   g_allocation_count = ALLOC_ALWAYS_SUCCEED;
14964543ef51SXin LI   return XML_STATUS_ERROR;
14974543ef51SXin LI }
14984543ef51SXin LI 
14994543ef51SXin LI #if XML_GE == 1
15004543ef51SXin LI int
15014543ef51SXin LI accounting_external_entity_ref_handler(XML_Parser parser,
15024543ef51SXin LI                                        const XML_Char *context,
15034543ef51SXin LI                                        const XML_Char *base,
15044543ef51SXin LI                                        const XML_Char *systemId,
15054543ef51SXin LI                                        const XML_Char *publicId) {
15064543ef51SXin LI   UNUSED_P(base);
15074543ef51SXin LI   UNUSED_P(publicId);
15084543ef51SXin LI 
15094543ef51SXin LI   const struct AccountingTestCase *const testCase
15104543ef51SXin LI       = (const struct AccountingTestCase *)XML_GetUserData(parser);
15114543ef51SXin LI 
15124543ef51SXin LI   const char *externalText = NULL;
15134543ef51SXin LI   if (xcstrcmp(systemId, XCS("first.ent")) == 0) {
15144543ef51SXin LI     externalText = testCase->firstExternalText;
15154543ef51SXin LI   } else if (xcstrcmp(systemId, XCS("second.ent")) == 0) {
15164543ef51SXin LI     externalText = testCase->secondExternalText;
15174543ef51SXin LI   } else {
15184543ef51SXin LI     assert(! "systemId is neither \"first.ent\" nor \"second.ent\"");
15194543ef51SXin LI   }
15204543ef51SXin LI   assert(externalText);
15214543ef51SXin LI 
15224543ef51SXin LI   XML_Parser entParser = XML_ExternalEntityParserCreate(parser, context, 0);
15234543ef51SXin LI   assert(entParser);
15244543ef51SXin LI 
15254543ef51SXin LI   const enum XML_Status status = _XML_Parse_SINGLE_BYTES(
15264543ef51SXin LI       entParser, externalText, (int)strlen(externalText), XML_TRUE);
15274543ef51SXin LI 
15284543ef51SXin LI   XML_ParserFree(entParser);
15294543ef51SXin LI   return status;
15304543ef51SXin LI }
15314543ef51SXin LI #endif /* XML_GE == 1 */
15324543ef51SXin LI 
15334543ef51SXin LI /* NotStandalone handlers */
15344543ef51SXin LI 
15354543ef51SXin LI int XMLCALL
15364543ef51SXin LI reject_not_standalone_handler(void *userData) {
15374543ef51SXin LI   UNUSED_P(userData);
15384543ef51SXin LI   return XML_STATUS_ERROR;
15394543ef51SXin LI }
15404543ef51SXin LI 
15414543ef51SXin LI int XMLCALL
15424543ef51SXin LI accept_not_standalone_handler(void *userData) {
15434543ef51SXin LI   UNUSED_P(userData);
15444543ef51SXin LI   return XML_STATUS_OK;
15454543ef51SXin LI }
15464543ef51SXin LI 
15474543ef51SXin LI /* Attribute List handlers */
15484543ef51SXin LI void XMLCALL
15494543ef51SXin LI verify_attlist_decl_handler(void *userData, const XML_Char *element_name,
15504543ef51SXin LI                             const XML_Char *attr_name,
15514543ef51SXin LI                             const XML_Char *attr_type,
15524543ef51SXin LI                             const XML_Char *default_value, int is_required) {
15534543ef51SXin LI   AttTest *at = (AttTest *)userData;
15544543ef51SXin LI 
15554543ef51SXin LI   if (xcstrcmp(element_name, at->element_name))
15564543ef51SXin LI     fail("Unexpected element name in attribute declaration");
15574543ef51SXin LI   if (xcstrcmp(attr_name, at->attr_name))
15584543ef51SXin LI     fail("Unexpected attribute name in attribute declaration");
15594543ef51SXin LI   if (xcstrcmp(attr_type, at->attr_type))
15604543ef51SXin LI     fail("Unexpected attribute type in attribute declaration");
15614543ef51SXin LI   if ((default_value == NULL && at->default_value != NULL)
15624543ef51SXin LI       || (default_value != NULL && at->default_value == NULL)
15634543ef51SXin LI       || (default_value != NULL && xcstrcmp(default_value, at->default_value)))
15644543ef51SXin LI     fail("Unexpected default value in attribute declaration");
15654543ef51SXin LI   if (is_required != at->is_required)
15664543ef51SXin LI     fail("Requirement mismatch in attribute declaration");
15674543ef51SXin LI }
15684543ef51SXin LI 
15694543ef51SXin LI /* Character Data handlers */
15704543ef51SXin LI 
15714543ef51SXin LI void XMLCALL
15724543ef51SXin LI clearing_aborting_character_handler(void *userData, const XML_Char *s,
15734543ef51SXin LI                                     int len) {
15744543ef51SXin LI   UNUSED_P(userData);
15754543ef51SXin LI   UNUSED_P(s);
15764543ef51SXin LI   UNUSED_P(len);
15774543ef51SXin LI   XML_StopParser(g_parser, g_resumable);
15784543ef51SXin LI   XML_SetCharacterDataHandler(g_parser, NULL);
15794543ef51SXin LI }
15804543ef51SXin LI 
15814543ef51SXin LI void XMLCALL
15824543ef51SXin LI parser_stop_character_handler(void *userData, const XML_Char *s, int len) {
15834543ef51SXin LI   UNUSED_P(userData);
15844543ef51SXin LI   UNUSED_P(s);
15854543ef51SXin LI   UNUSED_P(len);
15864543ef51SXin LI   XML_ParsingStatus status;
15874543ef51SXin LI   XML_GetParsingStatus(g_parser, &status);
15884543ef51SXin LI   if (status.parsing == XML_FINISHED) {
15894543ef51SXin LI     return; // the parser was stopped by a previous call to this handler.
15904543ef51SXin LI   }
15914543ef51SXin LI   XML_StopParser(g_parser, g_resumable);
15924543ef51SXin LI   XML_SetCharacterDataHandler(g_parser, NULL);
15934543ef51SXin LI   if (! g_resumable) {
15944543ef51SXin LI     /* Check that aborting an aborted parser is faulted */
15954543ef51SXin LI     if (XML_StopParser(g_parser, XML_FALSE) != XML_STATUS_ERROR)
15964543ef51SXin LI       fail("Aborting aborted parser not faulted");
15974543ef51SXin LI     if (XML_GetErrorCode(g_parser) != XML_ERROR_FINISHED)
15984543ef51SXin LI       xml_failure(g_parser);
15994543ef51SXin LI   } else if (g_abortable) {
16004543ef51SXin LI     /* Check that aborting a suspended parser works */
16014543ef51SXin LI     if (XML_StopParser(g_parser, XML_FALSE) == XML_STATUS_ERROR)
16024543ef51SXin LI       xml_failure(g_parser);
16034543ef51SXin LI   } else {
16044543ef51SXin LI     /* Check that suspending a suspended parser works */
16054543ef51SXin LI     if (XML_StopParser(g_parser, XML_TRUE) != XML_STATUS_ERROR)
16064543ef51SXin LI       fail("Suspending suspended parser not faulted");
16074543ef51SXin LI     if (XML_GetErrorCode(g_parser) != XML_ERROR_SUSPENDED)
16084543ef51SXin LI       xml_failure(g_parser);
16094543ef51SXin LI   }
16104543ef51SXin LI }
16114543ef51SXin LI 
16124543ef51SXin LI void XMLCALL
16134543ef51SXin LI cr_cdata_handler(void *userData, const XML_Char *s, int len) {
16144543ef51SXin LI   int *pfound = (int *)userData;
16154543ef51SXin LI 
16164543ef51SXin LI   /* Internal processing turns the CR into a newline for the
16174543ef51SXin LI    * character data handler, but not for the default handler
16184543ef51SXin LI    */
16194543ef51SXin LI   if (len == 1 && (*s == XCS('\n') || *s == XCS('\r')))
16204543ef51SXin LI     *pfound = 1;
16214543ef51SXin LI }
16224543ef51SXin LI 
16234543ef51SXin LI void XMLCALL
16244543ef51SXin LI rsqb_handler(void *userData, const XML_Char *s, int len) {
16254543ef51SXin LI   int *pfound = (int *)userData;
16264543ef51SXin LI 
16274543ef51SXin LI   if (len == 1 && *s == XCS(']'))
16284543ef51SXin LI     *pfound = 1;
16294543ef51SXin LI }
16304543ef51SXin LI 
16314543ef51SXin LI void XMLCALL
16324543ef51SXin LI byte_character_handler(void *userData, const XML_Char *s, int len) {
16334543ef51SXin LI #if XML_CONTEXT_BYTES > 0
16344543ef51SXin LI   int offset, size;
16354543ef51SXin LI   const char *buffer;
16364543ef51SXin LI   ByteTestData *data = (ByteTestData *)userData;
16374543ef51SXin LI 
16384543ef51SXin LI   UNUSED_P(s);
16394543ef51SXin LI   buffer = XML_GetInputContext(g_parser, &offset, &size);
16404543ef51SXin LI   if (buffer == NULL)
16414543ef51SXin LI     fail("Failed to get context buffer");
16424543ef51SXin LI   if (offset != data->start_element_len)
16434543ef51SXin LI     fail("Context offset in unexpected position");
16444543ef51SXin LI   if (len != data->cdata_len)
16454543ef51SXin LI     fail("CDATA length reported incorrectly");
16464543ef51SXin LI   if (size != data->total_string_len)
16474543ef51SXin LI     fail("Context size is not full buffer");
16484543ef51SXin LI   if (XML_GetCurrentByteIndex(g_parser) != offset)
16494543ef51SXin LI     fail("Character byte index incorrect");
16504543ef51SXin LI   if (XML_GetCurrentByteCount(g_parser) != len)
16514543ef51SXin LI     fail("Character byte count incorrect");
16524543ef51SXin LI #else
16534543ef51SXin LI   UNUSED_P(s);
16544543ef51SXin LI   UNUSED_P(userData);
16554543ef51SXin LI   UNUSED_P(len);
16564543ef51SXin LI #endif
16574543ef51SXin LI }
16584543ef51SXin LI 
16594543ef51SXin LI void XMLCALL
16604543ef51SXin LI ext2_accumulate_characters(void *userData, const XML_Char *s, int len) {
16614543ef51SXin LI   ExtTest2 *test_data = (ExtTest2 *)userData;
16624543ef51SXin LI   accumulate_characters(test_data->storage, s, len);
16634543ef51SXin LI }
16644543ef51SXin LI 
16654543ef51SXin LI /* Handlers that record their function name and int arg. */
16664543ef51SXin LI 
16674543ef51SXin LI static void
16684543ef51SXin LI record_call(struct handler_record_list *const rec, const char *funcname,
16694543ef51SXin LI             const int arg) {
16704543ef51SXin LI   const int max_entries = sizeof(rec->entries) / sizeof(rec->entries[0]);
16714543ef51SXin LI   assert_true(rec->count < max_entries);
16724543ef51SXin LI   struct handler_record_entry *const e = &rec->entries[rec->count++];
16734543ef51SXin LI   e->name = funcname;
16744543ef51SXin LI   e->arg = arg;
16754543ef51SXin LI }
16764543ef51SXin LI 
16774543ef51SXin LI void XMLCALL
16784543ef51SXin LI record_default_handler(void *userData, const XML_Char *s, int len) {
16794543ef51SXin LI   UNUSED_P(s);
16804543ef51SXin LI   record_call((struct handler_record_list *)userData, __func__, len);
16814543ef51SXin LI }
16824543ef51SXin LI 
16834543ef51SXin LI void XMLCALL
16844543ef51SXin LI record_cdata_handler(void *userData, const XML_Char *s, int len) {
16854543ef51SXin LI   UNUSED_P(s);
16864543ef51SXin LI   record_call((struct handler_record_list *)userData, __func__, len);
16874543ef51SXin LI   XML_DefaultCurrent(g_parser);
16884543ef51SXin LI }
16894543ef51SXin LI 
16904543ef51SXin LI void XMLCALL
16914543ef51SXin LI record_cdata_nodefault_handler(void *userData, const XML_Char *s, int len) {
16924543ef51SXin LI   UNUSED_P(s);
16934543ef51SXin LI   record_call((struct handler_record_list *)userData, __func__, len);
16944543ef51SXin LI }
16954543ef51SXin LI 
16964543ef51SXin LI void XMLCALL
16974543ef51SXin LI record_skip_handler(void *userData, const XML_Char *entityName,
16984543ef51SXin LI                     int is_parameter_entity) {
16994543ef51SXin LI   UNUSED_P(entityName);
17004543ef51SXin LI   record_call((struct handler_record_list *)userData, __func__,
17014543ef51SXin LI               is_parameter_entity);
17024543ef51SXin LI }
17034543ef51SXin LI 
17044543ef51SXin LI void XMLCALL
17054543ef51SXin LI record_element_start_handler(void *userData, const XML_Char *name,
17064543ef51SXin LI                              const XML_Char **atts) {
17074543ef51SXin LI   UNUSED_P(atts);
17084543ef51SXin LI   CharData_AppendXMLChars((CharData *)userData, name, (int)xcstrlen(name));
17094543ef51SXin LI }
17104543ef51SXin LI 
17114543ef51SXin LI void XMLCALL
17124543ef51SXin LI record_element_end_handler(void *userData, const XML_Char *name) {
17134543ef51SXin LI   CharData *storage = (CharData *)userData;
17144543ef51SXin LI 
17154543ef51SXin LI   CharData_AppendXMLChars(storage, XCS("/"), 1);
17164543ef51SXin LI   CharData_AppendXMLChars(storage, name, -1);
17174543ef51SXin LI }
17184543ef51SXin LI 
17194543ef51SXin LI const struct handler_record_entry *
17204543ef51SXin LI _handler_record_get(const struct handler_record_list *storage, int index,
17214543ef51SXin LI                     const char *file, int line) {
17224543ef51SXin LI   if (storage->count <= index) {
17234543ef51SXin LI     _fail(file, line, "too few handler calls");
17244543ef51SXin LI   }
17254543ef51SXin LI   return &storage->entries[index];
17264543ef51SXin LI }
17274543ef51SXin LI 
17284543ef51SXin LI /* Entity Declaration Handlers */
17294543ef51SXin LI static const XML_Char *entity_name_to_match = NULL;
17304543ef51SXin LI static const XML_Char *entity_value_to_match = NULL;
17314543ef51SXin LI static int entity_match_flag = ENTITY_MATCH_NOT_FOUND;
17324543ef51SXin LI 
17334543ef51SXin LI void XMLCALL
17344543ef51SXin LI param_entity_match_handler(void *userData, const XML_Char *entityName,
17354543ef51SXin LI                            int is_parameter_entity, const XML_Char *value,
17364543ef51SXin LI                            int value_length, const XML_Char *base,
17374543ef51SXin LI                            const XML_Char *systemId, const XML_Char *publicId,
17384543ef51SXin LI                            const XML_Char *notationName) {
17394543ef51SXin LI   UNUSED_P(userData);
17404543ef51SXin LI   UNUSED_P(base);
17414543ef51SXin LI   UNUSED_P(systemId);
17424543ef51SXin LI   UNUSED_P(publicId);
17434543ef51SXin LI   UNUSED_P(notationName);
17444543ef51SXin LI   if (! is_parameter_entity || entity_name_to_match == NULL
17454543ef51SXin LI       || entity_value_to_match == NULL) {
17464543ef51SXin LI     return;
17474543ef51SXin LI   }
17484543ef51SXin LI   if (! xcstrcmp(entityName, entity_name_to_match)) {
17494543ef51SXin LI     /* The cast here is safe because we control the horizontal and
17504543ef51SXin LI      * the vertical, and we therefore know our strings are never
17514543ef51SXin LI      * going to overflow an int.
17524543ef51SXin LI      */
17534543ef51SXin LI     if (value_length != (int)xcstrlen(entity_value_to_match)
17544543ef51SXin LI         || xcstrncmp(value, entity_value_to_match, value_length)) {
17554543ef51SXin LI       entity_match_flag = ENTITY_MATCH_FAIL;
17564543ef51SXin LI     } else {
17574543ef51SXin LI       entity_match_flag = ENTITY_MATCH_SUCCESS;
17584543ef51SXin LI     }
17594543ef51SXin LI   }
17604543ef51SXin LI   /* Else leave the match flag alone */
17614543ef51SXin LI }
17624543ef51SXin LI 
17634543ef51SXin LI void
17644543ef51SXin LI param_entity_match_init(const XML_Char *name, const XML_Char *value) {
17654543ef51SXin LI   entity_name_to_match = name;
17664543ef51SXin LI   entity_value_to_match = value;
17674543ef51SXin LI   entity_match_flag = ENTITY_MATCH_NOT_FOUND;
17684543ef51SXin LI }
17694543ef51SXin LI 
17704543ef51SXin LI int
17714543ef51SXin LI get_param_entity_match_flag(void) {
17724543ef51SXin LI   return entity_match_flag;
17734543ef51SXin LI }
17744543ef51SXin LI 
17754543ef51SXin LI /* Misc handlers */
17764543ef51SXin LI 
17774543ef51SXin LI void XMLCALL
17784543ef51SXin LI xml_decl_handler(void *userData, const XML_Char *version,
17794543ef51SXin LI                  const XML_Char *encoding, int standalone) {
17804543ef51SXin LI   UNUSED_P(version);
17814543ef51SXin LI   UNUSED_P(encoding);
17824543ef51SXin LI   if (userData != g_handler_data)
17834543ef51SXin LI     fail("User data (xml decl) not correctly set");
17844543ef51SXin LI   if (standalone != -1)
17854543ef51SXin LI     fail("Standalone not flagged as not present in XML decl");
17864543ef51SXin LI   g_xdecl_count++;
17874543ef51SXin LI }
17884543ef51SXin LI 
17894543ef51SXin LI void XMLCALL
17904543ef51SXin LI param_check_skip_handler(void *userData, const XML_Char *entityName,
17914543ef51SXin LI                          int is_parameter_entity) {
17924543ef51SXin LI   UNUSED_P(entityName);
17934543ef51SXin LI   UNUSED_P(is_parameter_entity);
17944543ef51SXin LI   if (userData != g_handler_data)
17954543ef51SXin LI     fail("User data (skip) not correctly set");
17964543ef51SXin LI   g_skip_count++;
17974543ef51SXin LI }
17984543ef51SXin LI 
17994543ef51SXin LI void XMLCALL
18004543ef51SXin LI data_check_comment_handler(void *userData, const XML_Char *data) {
18014543ef51SXin LI   UNUSED_P(data);
18024543ef51SXin LI   /* Check that the userData passed through is what we expect */
18034543ef51SXin LI   if (userData != g_handler_data)
18044543ef51SXin LI     fail("User data (parser) not correctly set");
18054543ef51SXin LI   /* Check that the user data in the parser is appropriate */
18064543ef51SXin LI   if (XML_GetUserData(userData) != (void *)1)
18074543ef51SXin LI     fail("User data in parser not correctly set");
18084543ef51SXin LI   g_comment_count++;
18094543ef51SXin LI }
18104543ef51SXin LI 
18114543ef51SXin LI void XMLCALL
18124543ef51SXin LI selective_aborting_default_handler(void *userData, const XML_Char *s, int len) {
18134543ef51SXin LI   const XML_Char trigger_char = *(const XML_Char *)userData;
18144543ef51SXin LI 
18154543ef51SXin LI   int found = 0;
18164543ef51SXin LI   for (int i = 0; i < len; ++i) {
18174543ef51SXin LI     if (s[i] == trigger_char) {
18184543ef51SXin LI       found = 1;
18194543ef51SXin LI       break;
18204543ef51SXin LI     }
18214543ef51SXin LI   }
18224543ef51SXin LI 
18234543ef51SXin LI   if (found) {
18244543ef51SXin LI     XML_StopParser(g_parser, g_resumable);
18254543ef51SXin LI     XML_SetDefaultHandler(g_parser, NULL);
18264543ef51SXin LI   }
18274543ef51SXin LI }
18284543ef51SXin LI 
18294543ef51SXin LI void XMLCALL
18304543ef51SXin LI suspending_comment_handler(void *userData, const XML_Char *data) {
18314543ef51SXin LI   UNUSED_P(data);
18324543ef51SXin LI   XML_Parser parser = (XML_Parser)userData;
18334543ef51SXin LI   XML_StopParser(parser, XML_TRUE);
18344543ef51SXin LI }
18354543ef51SXin LI 
18364543ef51SXin LI void XMLCALL
18374543ef51SXin LI element_decl_suspender(void *userData, const XML_Char *name,
18384543ef51SXin LI                        XML_Content *model) {
18394543ef51SXin LI   UNUSED_P(userData);
18404543ef51SXin LI   UNUSED_P(name);
18414543ef51SXin LI   XML_StopParser(g_parser, XML_TRUE);
18424543ef51SXin LI   XML_FreeContentModel(g_parser, model);
18434543ef51SXin LI }
18444543ef51SXin LI 
18454543ef51SXin LI void XMLCALL
18464543ef51SXin LI accumulate_pi_characters(void *userData, const XML_Char *target,
18474543ef51SXin LI                          const XML_Char *data) {
18484543ef51SXin LI   CharData *storage = (CharData *)userData;
18494543ef51SXin LI 
18504543ef51SXin LI   CharData_AppendXMLChars(storage, target, -1);
18514543ef51SXin LI   CharData_AppendXMLChars(storage, XCS(": "), 2);
18524543ef51SXin LI   CharData_AppendXMLChars(storage, data, -1);
18534543ef51SXin LI   CharData_AppendXMLChars(storage, XCS("\n"), 1);
18544543ef51SXin LI }
18554543ef51SXin LI 
18564543ef51SXin LI void XMLCALL
18574543ef51SXin LI accumulate_comment(void *userData, const XML_Char *data) {
18584543ef51SXin LI   CharData *storage = (CharData *)userData;
18594543ef51SXin LI 
18604543ef51SXin LI   CharData_AppendXMLChars(storage, data, -1);
18614543ef51SXin LI }
18624543ef51SXin LI 
18634543ef51SXin LI void XMLCALL
18644543ef51SXin LI accumulate_entity_decl(void *userData, const XML_Char *entityName,
18654543ef51SXin LI                        int is_parameter_entity, const XML_Char *value,
18664543ef51SXin LI                        int value_length, const XML_Char *base,
18674543ef51SXin LI                        const XML_Char *systemId, const XML_Char *publicId,
18684543ef51SXin LI                        const XML_Char *notationName) {
18694543ef51SXin LI   CharData *storage = (CharData *)userData;
18704543ef51SXin LI 
18714543ef51SXin LI   UNUSED_P(is_parameter_entity);
18724543ef51SXin LI   UNUSED_P(base);
18734543ef51SXin LI   UNUSED_P(systemId);
18744543ef51SXin LI   UNUSED_P(publicId);
18754543ef51SXin LI   UNUSED_P(notationName);
18764543ef51SXin LI   CharData_AppendXMLChars(storage, entityName, -1);
18774543ef51SXin LI   CharData_AppendXMLChars(storage, XCS("="), 1);
18784543ef51SXin LI   if (value == NULL)
18794543ef51SXin LI     CharData_AppendXMLChars(storage, XCS("(null)"), -1);
18804543ef51SXin LI   else
18814543ef51SXin LI     CharData_AppendXMLChars(storage, value, value_length);
18824543ef51SXin LI   CharData_AppendXMLChars(storage, XCS("\n"), 1);
18834543ef51SXin LI }
18844543ef51SXin LI 
18854543ef51SXin LI void XMLCALL
18864543ef51SXin LI accumulate_start_element(void *userData, const XML_Char *name,
18874543ef51SXin LI                          const XML_Char **atts) {
18884543ef51SXin LI   CharData *const storage = (CharData *)userData;
18894543ef51SXin LI   CharData_AppendXMLChars(storage, XCS("("), 1);
18904543ef51SXin LI   CharData_AppendXMLChars(storage, name, -1);
18914543ef51SXin LI 
18924543ef51SXin LI   if ((atts != NULL) && (atts[0] != NULL)) {
18934543ef51SXin LI     CharData_AppendXMLChars(storage, XCS("("), 1);
18944543ef51SXin LI     while (atts[0] != NULL) {
18954543ef51SXin LI       CharData_AppendXMLChars(storage, atts[0], -1);
18964543ef51SXin LI       CharData_AppendXMLChars(storage, XCS("="), 1);
18974543ef51SXin LI       CharData_AppendXMLChars(storage, atts[1], -1);
18984543ef51SXin LI       atts += 2;
18994543ef51SXin LI       if (atts[0] != NULL) {
19004543ef51SXin LI         CharData_AppendXMLChars(storage, XCS(","), 1);
19014543ef51SXin LI       }
19024543ef51SXin LI     }
19034543ef51SXin LI     CharData_AppendXMLChars(storage, XCS(")"), 1);
19044543ef51SXin LI   }
19054543ef51SXin LI 
19064543ef51SXin LI   CharData_AppendXMLChars(storage, XCS(")\n"), 2);
19074543ef51SXin LI }
19084543ef51SXin LI 
19094543ef51SXin LI void XMLCALL
1910*908f215eSXin LI accumulate_characters(void *userData, const XML_Char *s, int len) {
1911*908f215eSXin LI   CharData *const storage = (CharData *)userData;
1912*908f215eSXin LI   CharData_AppendXMLChars(storage, s, len);
1913*908f215eSXin LI }
1914*908f215eSXin LI 
1915*908f215eSXin LI void XMLCALL
1916*908f215eSXin LI accumulate_attribute(void *userData, const XML_Char *name,
1917*908f215eSXin LI                      const XML_Char **atts) {
1918*908f215eSXin LI   CharData *const storage = (CharData *)userData;
1919*908f215eSXin LI   UNUSED_P(name);
1920*908f215eSXin LI   /* Check there are attributes to deal with */
1921*908f215eSXin LI   if (atts == NULL)
1922*908f215eSXin LI     return;
1923*908f215eSXin LI 
1924*908f215eSXin LI   while (storage->count < 0 && atts[0] != NULL) {
1925*908f215eSXin LI     /* "accumulate" the value of the first attribute we see */
1926*908f215eSXin LI     CharData_AppendXMLChars(storage, atts[1], -1);
1927*908f215eSXin LI     atts += 2;
1928*908f215eSXin LI   }
1929*908f215eSXin LI }
1930*908f215eSXin LI 
1931*908f215eSXin LI void XMLCALL
1932*908f215eSXin LI ext_accumulate_characters(void *userData, const XML_Char *s, int len) {
1933*908f215eSXin LI   ExtTest *const test_data = (ExtTest *)userData;
1934*908f215eSXin LI   accumulate_characters(test_data->storage, s, len);
1935*908f215eSXin LI }
1936*908f215eSXin LI 
1937*908f215eSXin LI void XMLCALL
19384543ef51SXin LI checking_default_handler(void *userData, const XML_Char *s, int len) {
19394543ef51SXin LI   DefaultCheck *data = (DefaultCheck *)userData;
19404543ef51SXin LI   int i;
19414543ef51SXin LI 
19424543ef51SXin LI   for (i = 0; data[i].expected != NULL; i++) {
19434543ef51SXin LI     if (data[i].expectedLen == len
19444543ef51SXin LI         && ! memcmp(data[i].expected, s, len * sizeof(XML_Char))) {
19454543ef51SXin LI       data[i].seen = XML_TRUE;
19464543ef51SXin LI       break;
19474543ef51SXin LI     }
19484543ef51SXin LI   }
19494543ef51SXin LI }
19504543ef51SXin LI 
19514543ef51SXin LI void XMLCALL
19524543ef51SXin LI accumulate_and_suspend_comment_handler(void *userData, const XML_Char *data) {
19534543ef51SXin LI   ParserPlusStorage *const parserPlusStorage = (ParserPlusStorage *)userData;
19544543ef51SXin LI   accumulate_comment(parserPlusStorage->storage, data);
19554543ef51SXin LI   XML_StopParser(parserPlusStorage->parser, XML_TRUE);
19564543ef51SXin LI }
1957