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