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