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