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