xref: /freebsd/contrib/expat/tests/alloc_tests.c (revision 5ca8e32633c4ffbbcd6762e5888b6a4ba0708c6c)
1 /* Tests in the "allocation" test case 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-2023 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      Sony Corporation / Snild Dolkow <snild@sony.com>
22    Licensed under the MIT license:
23 
24    Permission is  hereby granted,  free of charge,  to any  person obtaining
25    a  copy  of  this  software   and  associated  documentation  files  (the
26    "Software"),  to  deal in  the  Software  without restriction,  including
27    without  limitation the  rights  to use,  copy,  modify, merge,  publish,
28    distribute, sublicense, and/or sell copies of the Software, and to permit
29    persons  to whom  the Software  is  furnished to  do so,  subject to  the
30    following conditions:
31 
32    The above copyright  notice and this permission notice  shall be included
33    in all copies or substantial portions of the Software.
34 
35    THE  SOFTWARE  IS  PROVIDED  "AS  IS",  WITHOUT  WARRANTY  OF  ANY  KIND,
36    EXPRESS  OR IMPLIED,  INCLUDING  BUT  NOT LIMITED  TO  THE WARRANTIES  OF
37    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
38    NO EVENT SHALL THE AUTHORS OR  COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
39    DAMAGES OR  OTHER LIABILITY, WHETHER  IN AN  ACTION OF CONTRACT,  TORT OR
40    OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
41    USE OR OTHER DEALINGS IN THE SOFTWARE.
42 */
43 
44 #if defined(NDEBUG)
45 #  undef NDEBUG /* because test suite relies on assert(...) at the moment */
46 #endif
47 
48 #include <string.h>
49 #include <assert.h>
50 
51 #include "expat.h"
52 #include "common.h"
53 #include "minicheck.h"
54 #include "dummy.h"
55 #include "handlers.h"
56 #include "alloc_tests.h"
57 
58 static void
59 alloc_setup(void) {
60   XML_Memory_Handling_Suite memsuite = {duff_allocator, duff_reallocator, free};
61 
62   /* Ensure the parser creation will go through */
63   g_allocation_count = ALLOC_ALWAYS_SUCCEED;
64   g_reallocation_count = REALLOC_ALWAYS_SUCCEED;
65   g_parser = XML_ParserCreate_MM(NULL, &memsuite, NULL);
66   if (g_parser == NULL)
67     fail("Parser not created");
68 }
69 
70 static void
71 alloc_teardown(void) {
72   basic_teardown();
73 }
74 
75 /* Test the effects of allocation failures on xml declaration processing */
76 START_TEST(test_alloc_parse_xdecl) {
77   const char *text = "<?xml version='1.0' encoding='utf-8'?>\n"
78                      "<doc>Hello, world</doc>";
79   int i;
80   const int max_alloc_count = 15;
81 
82   for (i = 0; i < max_alloc_count; i++) {
83     g_allocation_count = i;
84     XML_SetXmlDeclHandler(g_parser, dummy_xdecl_handler);
85     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
86         != XML_STATUS_ERROR)
87       break;
88     /* Resetting the parser is insufficient, because some memory
89      * allocations are cached within the parser.  Instead we use
90      * the teardown and setup routines to ensure that we have the
91      * right sort of parser back in our hands.
92      */
93     alloc_teardown();
94     alloc_setup();
95   }
96   if (i == 0)
97     fail("Parse succeeded despite failing allocator");
98   if (i == max_alloc_count)
99     fail("Parse failed with max allocations");
100 }
101 END_TEST
102 
103 /* As above, but with an encoding big enough to cause storing the
104  * version information to expand the string pool being used.
105  */
106 START_TEST(test_alloc_parse_xdecl_2) {
107   const char *text
108       = "<?xml version='1.0' encoding='"
109         /* Each line is 64 characters */
110         "ThisIsAStupidlyLongEncodingNameIntendedToTriggerPoolGrowth123456"
111         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
112         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
113         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
114         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
115         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
116         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
117         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
118         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
119         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
120         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
121         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
122         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
123         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
124         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
125         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMN"
126         "'?>"
127         "<doc>Hello, world</doc>";
128   int i;
129   const int max_alloc_count = 20;
130 
131   for (i = 0; i < max_alloc_count; i++) {
132     g_allocation_count = i;
133     XML_SetXmlDeclHandler(g_parser, dummy_xdecl_handler);
134     XML_SetUnknownEncodingHandler(g_parser, long_encoding_handler, NULL);
135     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
136         != XML_STATUS_ERROR)
137       break;
138     /* See comment in test_alloc_parse_xdecl() */
139     alloc_teardown();
140     alloc_setup();
141   }
142   if (i == 0)
143     fail("Parse succeeded despite failing allocator");
144   if (i == max_alloc_count)
145     fail("Parse failed with max allocations");
146 }
147 END_TEST
148 
149 /* Test the effects of allocation failures on a straightforward parse */
150 START_TEST(test_alloc_parse_pi) {
151   const char *text = "<?xml version='1.0' encoding='utf-8'?>\n"
152                      "<?pi unknown?>\n"
153                      "<doc>"
154                      "Hello, world"
155                      "</doc>";
156   int i;
157   const int max_alloc_count = 15;
158 
159   for (i = 0; i < max_alloc_count; i++) {
160     g_allocation_count = i;
161     XML_SetProcessingInstructionHandler(g_parser, dummy_pi_handler);
162     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
163         != XML_STATUS_ERROR)
164       break;
165     /* See comment in test_alloc_parse_xdecl() */
166     alloc_teardown();
167     alloc_setup();
168   }
169   if (i == 0)
170     fail("Parse succeeded despite failing allocator");
171   if (i == max_alloc_count)
172     fail("Parse failed with max allocations");
173 }
174 END_TEST
175 
176 START_TEST(test_alloc_parse_pi_2) {
177   const char *text = "<?xml version='1.0' encoding='utf-8'?>\n"
178                      "<doc>"
179                      "Hello, world"
180                      "<?pi unknown?>\n"
181                      "</doc>";
182   int i;
183   const int max_alloc_count = 15;
184 
185   for (i = 0; i < max_alloc_count; i++) {
186     g_allocation_count = i;
187     XML_SetProcessingInstructionHandler(g_parser, dummy_pi_handler);
188     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
189         != XML_STATUS_ERROR)
190       break;
191     /* See comment in test_alloc_parse_xdecl() */
192     alloc_teardown();
193     alloc_setup();
194   }
195   if (i == 0)
196     fail("Parse succeeded despite failing allocator");
197   if (i == max_alloc_count)
198     fail("Parse failed with max allocations");
199 }
200 END_TEST
201 
202 START_TEST(test_alloc_parse_pi_3) {
203   const char *text
204       = "<?"
205         /* 64 characters per line */
206         "This processing instruction should be long enough to ensure that"
207         "it triggers the growth of an internal string pool when the      "
208         "allocator fails at a cruicial moment FGHIJKLMNOPABCDEFGHIJKLMNOP"
209         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
210         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
211         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
212         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
213         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
214         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
215         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
216         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
217         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
218         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
219         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
220         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
221         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
222         "Q?><doc/>";
223   int i;
224   const int max_alloc_count = 20;
225 
226   for (i = 0; i < max_alloc_count; i++) {
227     g_allocation_count = i;
228     XML_SetProcessingInstructionHandler(g_parser, dummy_pi_handler);
229     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
230         != XML_STATUS_ERROR)
231       break;
232     /* See comment in test_alloc_parse_xdecl() */
233     alloc_teardown();
234     alloc_setup();
235   }
236   if (i == 0)
237     fail("Parse succeeded despite failing allocator");
238   if (i == max_alloc_count)
239     fail("Parse failed with max allocations");
240 }
241 END_TEST
242 
243 START_TEST(test_alloc_parse_comment) {
244   const char *text = "<?xml version='1.0' encoding='utf-8'?>\n"
245                      "<!-- Test parsing this comment -->"
246                      "<doc>Hi</doc>";
247   int i;
248   const int max_alloc_count = 15;
249 
250   for (i = 0; i < max_alloc_count; i++) {
251     g_allocation_count = i;
252     XML_SetCommentHandler(g_parser, dummy_comment_handler);
253     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
254         != XML_STATUS_ERROR)
255       break;
256     /* See comment in test_alloc_parse_xdecl() */
257     alloc_teardown();
258     alloc_setup();
259   }
260   if (i == 0)
261     fail("Parse succeeded despite failing allocator");
262   if (i == max_alloc_count)
263     fail("Parse failed with max allocations");
264 }
265 END_TEST
266 
267 START_TEST(test_alloc_parse_comment_2) {
268   const char *text = "<?xml version='1.0' encoding='utf-8'?>\n"
269                      "<doc>"
270                      "Hello, world"
271                      "<!-- Parse this comment too -->"
272                      "</doc>";
273   int i;
274   const int max_alloc_count = 15;
275 
276   for (i = 0; i < max_alloc_count; i++) {
277     g_allocation_count = i;
278     XML_SetCommentHandler(g_parser, dummy_comment_handler);
279     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
280         != XML_STATUS_ERROR)
281       break;
282     /* See comment in test_alloc_parse_xdecl() */
283     alloc_teardown();
284     alloc_setup();
285   }
286   if (i == 0)
287     fail("Parse succeeded despite failing allocator");
288   if (i == max_alloc_count)
289     fail("Parse failed with max allocations");
290 }
291 END_TEST
292 
293 /* Test that external parser creation running out of memory is
294  * correctly reported.  Based on the external entity test cases.
295  */
296 START_TEST(test_alloc_create_external_parser) {
297   const char *text = "<?xml version='1.0' encoding='us-ascii'?>\n"
298                      "<!DOCTYPE doc SYSTEM 'foo'>\n"
299                      "<doc>&entity;</doc>";
300   char foo_text[] = "<!ELEMENT doc (#PCDATA)*>";
301 
302   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
303   XML_SetUserData(g_parser, foo_text);
304   XML_SetExternalEntityRefHandler(g_parser, external_entity_duff_loader);
305   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
306       != XML_STATUS_ERROR) {
307     fail("External parser allocator returned success incorrectly");
308   }
309 }
310 END_TEST
311 
312 /* More external parser memory allocation testing */
313 START_TEST(test_alloc_run_external_parser) {
314   const char *text = "<?xml version='1.0' encoding='us-ascii'?>\n"
315                      "<!DOCTYPE doc SYSTEM 'foo'>\n"
316                      "<doc>&entity;</doc>";
317   char foo_text[] = "<!ELEMENT doc (#PCDATA)*>";
318   unsigned int i;
319   const unsigned int max_alloc_count = 15;
320 
321   for (i = 0; i < max_alloc_count; i++) {
322     XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
323     XML_SetUserData(g_parser, foo_text);
324     XML_SetExternalEntityRefHandler(g_parser, external_entity_null_loader);
325     g_allocation_count = i;
326     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
327         != XML_STATUS_ERROR)
328       break;
329     /* See comment in test_alloc_parse_xdecl() */
330     alloc_teardown();
331     alloc_setup();
332   }
333   if (i == 0)
334     fail("Parsing ignored failing allocator");
335   else if (i == max_alloc_count)
336     fail("Parsing failed with allocation count 10");
337 }
338 END_TEST
339 
340 /* Test that running out of memory in dtdCopy is correctly reported.
341  * Based on test_default_ns_from_ext_subset_and_ext_ge()
342  */
343 START_TEST(test_alloc_dtd_copy_default_atts) {
344   const char *text = "<?xml version='1.0'?>\n"
345                      "<!DOCTYPE doc SYSTEM 'http://example.org/doc.dtd' [\n"
346                      "  <!ENTITY en SYSTEM 'http://example.org/entity.ent'>\n"
347                      "]>\n"
348                      "<doc xmlns='http://example.org/ns1'>\n"
349                      "&en;\n"
350                      "</doc>";
351   int callno = 0;
352 
353   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
354   XML_SetExternalEntityRefHandler(g_parser, external_entity_dbl_handler);
355   XML_SetUserData(g_parser, &callno);
356   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
357       == XML_STATUS_ERROR)
358     xml_failure(g_parser);
359 }
360 END_TEST
361 
362 /* Test more external entity allocation failure paths */
363 START_TEST(test_alloc_external_entity) {
364   const char *text = "<?xml version='1.0'?>\n"
365                      "<!DOCTYPE doc SYSTEM 'http://example.org/doc.dtd' [\n"
366                      "  <!ENTITY en SYSTEM 'http://example.org/entity.ent'>\n"
367                      "]>\n"
368                      "<doc xmlns='http://example.org/ns1'>\n"
369                      "&en;\n"
370                      "</doc>";
371   int i;
372   const int alloc_test_max_repeats = 50;
373   int callno = 0;
374 
375   for (i = 0; i < alloc_test_max_repeats; i++) {
376     g_allocation_count = -1;
377     XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
378     XML_SetExternalEntityRefHandler(g_parser, external_entity_dbl_handler_2);
379     callno = 0;
380     XML_SetUserData(g_parser, &callno);
381     g_allocation_count = i;
382     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
383         == XML_STATUS_OK)
384       break;
385     /* See comment in test_alloc_parse_xdecl() */
386     alloc_teardown();
387     alloc_setup();
388   }
389   g_allocation_count = -1;
390   if (i == 0)
391     fail("External entity parsed despite duff allocator");
392   if (i == alloc_test_max_repeats)
393     fail("External entity not parsed at max allocation count");
394 }
395 END_TEST
396 
397 /* Test more allocation failure paths */
398 START_TEST(test_alloc_ext_entity_set_encoding) {
399   const char *text = "<!DOCTYPE doc [\n"
400                      "  <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n"
401                      "]>\n"
402                      "<doc>&en;</doc>";
403   int i;
404   const int max_allocation_count = 30;
405 
406   for (i = 0; i < max_allocation_count; i++) {
407     XML_SetExternalEntityRefHandler(g_parser,
408                                     external_entity_alloc_set_encoding);
409     g_allocation_count = i;
410     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
411         == XML_STATUS_OK)
412       break;
413     g_allocation_count = -1;
414     /* See comment in test_alloc_parse_xdecl() */
415     alloc_teardown();
416     alloc_setup();
417   }
418   if (i == 0)
419     fail("Encoding check succeeded despite failing allocator");
420   if (i == max_allocation_count)
421     fail("Encoding failed at max allocation count");
422 }
423 END_TEST
424 
425 /* Test the effects of allocation failure in internal entities.
426  * Based on test_unknown_encoding_internal_entity
427  */
428 START_TEST(test_alloc_internal_entity) {
429   const char *text = "<?xml version='1.0' encoding='unsupported-encoding'?>\n"
430                      "<!DOCTYPE test [<!ENTITY foo 'bar'>]>\n"
431                      "<test a='&foo;'/>";
432   unsigned int i;
433   const unsigned int max_alloc_count = 20;
434 
435   for (i = 0; i < max_alloc_count; i++) {
436     g_allocation_count = i;
437     XML_SetUnknownEncodingHandler(g_parser, unknown_released_encoding_handler,
438                                   NULL);
439     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
440         != XML_STATUS_ERROR)
441       break;
442     /* See comment in test_alloc_parse_xdecl() */
443     alloc_teardown();
444     alloc_setup();
445   }
446   if (i == 0)
447     fail("Internal entity worked despite failing allocations");
448   else if (i == max_alloc_count)
449     fail("Internal entity failed at max allocation count");
450 }
451 END_TEST
452 
453 /* Test the robustness against allocation failure of element handling
454  * Based on test_dtd_default_handling().
455  */
456 START_TEST(test_alloc_dtd_default_handling) {
457   const char *text = "<!DOCTYPE doc [\n"
458                      "<!ENTITY e SYSTEM 'http://example.org/e'>\n"
459                      "<!NOTATION n SYSTEM 'http://example.org/n'>\n"
460                      "<!ENTITY e1 SYSTEM 'http://example.org/e' NDATA n>\n"
461                      "<!ELEMENT doc (#PCDATA)>\n"
462                      "<!ATTLIST doc a CDATA #IMPLIED>\n"
463                      "<?pi in dtd?>\n"
464                      "<!--comment in dtd-->\n"
465                      "]>\n"
466                      "<doc><![CDATA[text in doc]]></doc>";
467   const XML_Char *expected = XCS("\n\n\n\n\n\n\n\n\n<doc>text in doc</doc>");
468   CharData storage;
469   int i;
470   const int max_alloc_count = 25;
471 
472   for (i = 0; i < max_alloc_count; i++) {
473     g_allocation_count = i;
474     init_dummy_handlers();
475     XML_SetDefaultHandler(g_parser, accumulate_characters);
476     XML_SetDoctypeDeclHandler(g_parser, dummy_start_doctype_handler,
477                               dummy_end_doctype_handler);
478     XML_SetEntityDeclHandler(g_parser, dummy_entity_decl_handler);
479     XML_SetNotationDeclHandler(g_parser, dummy_notation_decl_handler);
480     XML_SetElementDeclHandler(g_parser, dummy_element_decl_handler);
481     XML_SetAttlistDeclHandler(g_parser, dummy_attlist_decl_handler);
482     XML_SetProcessingInstructionHandler(g_parser, dummy_pi_handler);
483     XML_SetCommentHandler(g_parser, dummy_comment_handler);
484     XML_SetCdataSectionHandler(g_parser, dummy_start_cdata_handler,
485                                dummy_end_cdata_handler);
486     XML_SetUnparsedEntityDeclHandler(g_parser,
487                                      dummy_unparsed_entity_decl_handler);
488     CharData_Init(&storage);
489     XML_SetUserData(g_parser, &storage);
490     XML_SetCharacterDataHandler(g_parser, accumulate_characters);
491     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
492         != XML_STATUS_ERROR)
493       break;
494     /* See comment in test_alloc_parse_xdecl() */
495     alloc_teardown();
496     alloc_setup();
497   }
498   if (i == 0)
499     fail("Default DTD parsed despite allocation failures");
500   if (i == max_alloc_count)
501     fail("Default DTD not parsed with maximum alloc count");
502   CharData_CheckXMLChars(&storage, expected);
503   if (get_dummy_handler_flags()
504       != (DUMMY_START_DOCTYPE_HANDLER_FLAG | DUMMY_END_DOCTYPE_HANDLER_FLAG
505           | DUMMY_ENTITY_DECL_HANDLER_FLAG | DUMMY_NOTATION_DECL_HANDLER_FLAG
506           | DUMMY_ELEMENT_DECL_HANDLER_FLAG | DUMMY_ATTLIST_DECL_HANDLER_FLAG
507           | DUMMY_COMMENT_HANDLER_FLAG | DUMMY_PI_HANDLER_FLAG
508           | DUMMY_START_CDATA_HANDLER_FLAG | DUMMY_END_CDATA_HANDLER_FLAG
509           | DUMMY_UNPARSED_ENTITY_DECL_HANDLER_FLAG))
510     fail("Not all handlers were called");
511 }
512 END_TEST
513 
514 /* Test robustness of XML_SetEncoding() with a failing allocator */
515 START_TEST(test_alloc_explicit_encoding) {
516   int i;
517   const int max_alloc_count = 5;
518 
519   for (i = 0; i < max_alloc_count; i++) {
520     g_allocation_count = i;
521     if (XML_SetEncoding(g_parser, XCS("us-ascii")) == XML_STATUS_OK)
522       break;
523   }
524   if (i == 0)
525     fail("Encoding set despite failing allocator");
526   else if (i == max_alloc_count)
527     fail("Encoding not set at max allocation count");
528 }
529 END_TEST
530 
531 /* Test robustness of XML_SetBase against a failing allocator */
532 START_TEST(test_alloc_set_base) {
533   const XML_Char *new_base = XCS("/local/file/name.xml");
534   int i;
535   const int max_alloc_count = 5;
536 
537   for (i = 0; i < max_alloc_count; i++) {
538     g_allocation_count = i;
539     if (XML_SetBase(g_parser, new_base) == XML_STATUS_OK)
540       break;
541   }
542   if (i == 0)
543     fail("Base set despite failing allocator");
544   else if (i == max_alloc_count)
545     fail("Base not set with max allocation count");
546 }
547 END_TEST
548 
549 /* Test buffer extension in the face of a duff reallocator */
550 START_TEST(test_alloc_realloc_buffer) {
551   const char *text = get_buffer_test_text;
552   void *buffer;
553   int i;
554   const int max_realloc_count = 10;
555 
556   /* Get a smallish buffer */
557   for (i = 0; i < max_realloc_count; i++) {
558     g_reallocation_count = i;
559     buffer = XML_GetBuffer(g_parser, 1536);
560     if (buffer == NULL)
561       fail("1.5K buffer reallocation failed");
562     assert(buffer != NULL);
563     memcpy(buffer, text, strlen(text));
564     if (XML_ParseBuffer(g_parser, (int)strlen(text), XML_FALSE)
565         == XML_STATUS_OK)
566       break;
567     /* See comment in test_alloc_parse_xdecl() */
568     alloc_teardown();
569     alloc_setup();
570   }
571   g_reallocation_count = -1;
572   if (i == 0)
573     fail("Parse succeeded with no reallocation");
574   else if (i == max_realloc_count)
575     fail("Parse failed with max reallocation count");
576 }
577 END_TEST
578 
579 /* Same test for external entity parsers */
580 START_TEST(test_alloc_ext_entity_realloc_buffer) {
581   const char *text = "<!DOCTYPE doc [\n"
582                      "  <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n"
583                      "]>\n"
584                      "<doc>&en;</doc>";
585   int i;
586   const int max_realloc_count = 10;
587 
588   for (i = 0; i < max_realloc_count; i++) {
589     XML_SetExternalEntityRefHandler(g_parser, external_entity_reallocator);
590     XML_SetUserData(g_parser, &i);
591     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
592         == XML_STATUS_OK)
593       break;
594     /* See comment in test_alloc_parse_xdecl() */
595     alloc_teardown();
596     alloc_setup();
597   }
598   if (i == 0)
599     fail("Succeeded with no reallocations");
600   if (i == max_realloc_count)
601     fail("Failed with max reallocations");
602 }
603 END_TEST
604 
605 /* Test elements with many attributes are handled correctly */
606 START_TEST(test_alloc_realloc_many_attributes) {
607   const char *text = "<!DOCTYPE doc [\n"
608                      "<!ATTLIST doc za CDATA 'default'>\n"
609                      "<!ATTLIST doc zb CDATA 'def2'>\n"
610                      "<!ATTLIST doc zc CDATA 'def3'>\n"
611                      "]>\n"
612                      "<doc a='1'"
613                      "     b='2'"
614                      "     c='3'"
615                      "     d='4'"
616                      "     e='5'"
617                      "     f='6'"
618                      "     g='7'"
619                      "     h='8'"
620                      "     i='9'"
621                      "     j='10'"
622                      "     k='11'"
623                      "     l='12'"
624                      "     m='13'"
625                      "     n='14'"
626                      "     p='15'"
627                      "     q='16'"
628                      "     r='17'"
629                      "     s='18'>"
630                      "</doc>";
631   int i;
632   const int max_realloc_count = 10;
633 
634   for (i = 0; i < max_realloc_count; i++) {
635     g_reallocation_count = i;
636     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
637         != XML_STATUS_ERROR)
638       break;
639     /* See comment in test_alloc_parse_xdecl() */
640     alloc_teardown();
641     alloc_setup();
642   }
643   if (i == 0)
644     fail("Parse succeeded despite no reallocations");
645   if (i == max_realloc_count)
646     fail("Parse failed at max reallocations");
647 }
648 END_TEST
649 
650 /* Test handling of a public entity with failing allocator */
651 START_TEST(test_alloc_public_entity_value) {
652   const char *text = "<!DOCTYPE doc SYSTEM 'http://example.org/'>\n"
653                      "<doc></doc>\n";
654   char dtd_text[]
655       = "<!ELEMENT doc EMPTY>\n"
656         "<!ENTITY % e1 PUBLIC 'foo' 'bar.ent'>\n"
657         "<!ENTITY % "
658         /* Each line is 64 characters */
659         "ThisIsAStupidlyLongParameterNameIntendedToTriggerPoolGrowth12345"
660         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
661         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
662         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
663         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
664         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
665         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
666         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
667         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
668         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
669         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
670         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
671         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
672         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
673         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
674         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
675         " '%e1;'>\n"
676         "%e1;\n";
677   int i;
678   const int max_alloc_count = 50;
679 
680   for (i = 0; i < max_alloc_count; i++) {
681     g_allocation_count = i;
682     init_dummy_handlers();
683     XML_SetUserData(g_parser, dtd_text);
684     XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
685     XML_SetExternalEntityRefHandler(g_parser, external_entity_public);
686     /* Provoke a particular code path */
687     XML_SetEntityDeclHandler(g_parser, dummy_entity_decl_handler);
688     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
689         != XML_STATUS_ERROR)
690       break;
691     /* See comment in test_alloc_parse_xdecl() */
692     alloc_teardown();
693     alloc_setup();
694   }
695   if (i == 0)
696     fail("Parsing worked despite failing allocation");
697   if (i == max_alloc_count)
698     fail("Parsing failed at max allocation count");
699   if (get_dummy_handler_flags() != DUMMY_ENTITY_DECL_HANDLER_FLAG)
700     fail("Entity declaration handler not called");
701 }
702 END_TEST
703 
704 START_TEST(test_alloc_realloc_subst_public_entity_value) {
705   const char *text = "<!DOCTYPE doc SYSTEM 'http://example.org/'>\n"
706                      "<doc></doc>\n";
707   char dtd_text[]
708       = "<!ELEMENT doc EMPTY>\n"
709         "<!ENTITY % "
710         /* Each line is 64 characters */
711         "ThisIsAStupidlyLongParameterNameIntendedToTriggerPoolGrowth12345"
712         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
713         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
714         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
715         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
716         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
717         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
718         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
719         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
720         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
721         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
722         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
723         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
724         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
725         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
726         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
727         " PUBLIC 'foo' 'bar.ent'>\n"
728         "%ThisIsAStupidlyLongParameterNameIntendedToTriggerPoolGrowth12345"
729         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
730         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
731         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
732         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
733         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
734         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
735         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
736         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
737         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
738         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
739         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
740         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
741         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
742         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
743         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP;";
744   int i;
745   const int max_realloc_count = 10;
746 
747   for (i = 0; i < max_realloc_count; i++) {
748     g_reallocation_count = i;
749     XML_SetUserData(g_parser, dtd_text);
750     XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
751     XML_SetExternalEntityRefHandler(g_parser, external_entity_public);
752     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
753         != XML_STATUS_ERROR)
754       break;
755     /* See comment in test_alloc_parse_xdecl() */
756     alloc_teardown();
757     alloc_setup();
758   }
759   if (i == 0)
760     fail("Parsing worked despite failing reallocation");
761   if (i == max_realloc_count)
762     fail("Parsing failed at max reallocation count");
763 }
764 END_TEST
765 
766 START_TEST(test_alloc_parse_public_doctype) {
767   const char *text
768       = "<?xml version='1.0' encoding='utf-8'?>\n"
769         "<!DOCTYPE doc PUBLIC '"
770         /* 64 characters per line */
771         "http://example.com/a/long/enough/name/to/trigger/pool/growth/zz/"
772         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
773         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
774         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
775         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
776         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
777         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
778         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
779         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
780         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
781         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
782         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
783         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
784         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
785         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
786         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
787         "' 'test'>\n"
788         "<doc></doc>";
789   int i;
790   const int max_alloc_count = 25;
791 
792   for (i = 0; i < max_alloc_count; i++) {
793     g_allocation_count = i;
794     init_dummy_handlers();
795     XML_SetDoctypeDeclHandler(g_parser, dummy_start_doctype_decl_handler,
796                               dummy_end_doctype_decl_handler);
797     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
798         != XML_STATUS_ERROR)
799       break;
800     /* See comment in test_alloc_parse_xdecl() */
801     alloc_teardown();
802     alloc_setup();
803   }
804   if (i == 0)
805     fail("Parse succeeded despite failing allocator");
806   if (i == max_alloc_count)
807     fail("Parse failed at maximum allocation count");
808   if (get_dummy_handler_flags()
809       != (DUMMY_START_DOCTYPE_DECL_HANDLER_FLAG
810           | DUMMY_END_DOCTYPE_DECL_HANDLER_FLAG))
811     fail("Doctype handler functions not called");
812 }
813 END_TEST
814 
815 START_TEST(test_alloc_parse_public_doctype_long_name) {
816   const char *text
817       = "<?xml version='1.0' encoding='utf-8'?>\n"
818         "<!DOCTYPE doc PUBLIC 'http://example.com/foo' '"
819         /* 64 characters per line */
820         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP"
821         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP"
822         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP"
823         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP"
824         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP"
825         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP"
826         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP"
827         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP"
828         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP"
829         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP"
830         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP"
831         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP"
832         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP"
833         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP"
834         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP"
835         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP"
836         "'>\n"
837         "<doc></doc>";
838   int i;
839   const int max_alloc_count = 25;
840 
841   for (i = 0; i < max_alloc_count; i++) {
842     g_allocation_count = i;
843     XML_SetDoctypeDeclHandler(g_parser, dummy_start_doctype_decl_handler,
844                               dummy_end_doctype_decl_handler);
845     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
846         != XML_STATUS_ERROR)
847       break;
848     /* See comment in test_alloc_parse_xdecl() */
849     alloc_teardown();
850     alloc_setup();
851   }
852   if (i == 0)
853     fail("Parse succeeded despite failing allocator");
854   if (i == max_alloc_count)
855     fail("Parse failed at maximum allocation count");
856 }
857 END_TEST
858 
859 /* Test foreign DTD handling */
860 START_TEST(test_alloc_set_foreign_dtd) {
861   const char *text1 = "<?xml version='1.0' encoding='us-ascii'?>\n"
862                       "<doc>&entity;</doc>";
863   char text2[] = "<!ELEMENT doc (#PCDATA)*>";
864   int i;
865   const int max_alloc_count = 25;
866 
867   for (i = 0; i < max_alloc_count; i++) {
868     g_allocation_count = i;
869     XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
870     XML_SetUserData(g_parser, &text2);
871     XML_SetExternalEntityRefHandler(g_parser, external_entity_alloc);
872     if (XML_UseForeignDTD(g_parser, XML_TRUE) != XML_ERROR_NONE)
873       fail("Could not set foreign DTD");
874     if (_XML_Parse_SINGLE_BYTES(g_parser, text1, (int)strlen(text1), XML_TRUE)
875         != XML_STATUS_ERROR)
876       break;
877     /* See comment in test_alloc_parse_xdecl() */
878     alloc_teardown();
879     alloc_setup();
880   }
881   if (i == 0)
882     fail("Parse succeeded despite failing allocator");
883   if (i == max_alloc_count)
884     fail("Parse failed at maximum allocation count");
885 }
886 END_TEST
887 
888 /* Test based on ibm/valid/P32/ibm32v04.xml */
889 START_TEST(test_alloc_attribute_enum_value) {
890   const char *text = "<?xml version='1.0' standalone='no'?>\n"
891                      "<!DOCTYPE animal SYSTEM 'test.dtd'>\n"
892                      "<animal>This is a \n    <a/>  \n\nyellow tiger</animal>";
893   char dtd_text[] = "<!ELEMENT animal (#PCDATA|a)*>\n"
894                     "<!ELEMENT a EMPTY>\n"
895                     "<!ATTLIST animal xml:space (default|preserve) 'preserve'>";
896   int i;
897   const int max_alloc_count = 30;
898 
899   for (i = 0; i < max_alloc_count; i++) {
900     g_allocation_count = i;
901     XML_SetExternalEntityRefHandler(g_parser, external_entity_alloc);
902     XML_SetUserData(g_parser, dtd_text);
903     XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
904     /* An attribute list handler provokes a different code path */
905     XML_SetAttlistDeclHandler(g_parser, dummy_attlist_decl_handler);
906     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
907         != XML_STATUS_ERROR)
908       break;
909     /* See comment in test_alloc_parse_xdecl() */
910     alloc_teardown();
911     alloc_setup();
912   }
913   if (i == 0)
914     fail("Parse succeeded despite failing allocator");
915   if (i == max_alloc_count)
916     fail("Parse failed at maximum allocation count");
917 }
918 END_TEST
919 
920 /* Test attribute enums sufficient to overflow the string pool */
921 START_TEST(test_alloc_realloc_attribute_enum_value) {
922   const char *text = "<?xml version='1.0' standalone='no'?>\n"
923                      "<!DOCTYPE animal SYSTEM 'test.dtd'>\n"
924                      "<animal>This is a yellow tiger</animal>";
925   /* We wish to define a collection of attribute enums that will
926    * cause the string pool storing them to have to expand.  This
927    * means more than 1024 bytes, including the parentheses and
928    * separator bars.
929    */
930   char dtd_text[]
931       = "<!ELEMENT animal (#PCDATA)*>\n"
932         "<!ATTLIST animal thing "
933         "(default"
934         /* Each line is 64 characters */
935         "|ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
936         "|BBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
937         "|CBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
938         "|DBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
939         "|EBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
940         "|FBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
941         "|GBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
942         "|HBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
943         "|IBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
944         "|JBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
945         "|KBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
946         "|LBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
947         "|MBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
948         "|NBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
949         "|OBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
950         "|PBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO)"
951         " 'default'>";
952   int i;
953   const int max_realloc_count = 10;
954 
955   for (i = 0; i < max_realloc_count; i++) {
956     g_reallocation_count = i;
957     XML_SetExternalEntityRefHandler(g_parser, external_entity_alloc);
958     XML_SetUserData(g_parser, dtd_text);
959     XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
960     /* An attribute list handler provokes a different code path */
961     XML_SetAttlistDeclHandler(g_parser, dummy_attlist_decl_handler);
962     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
963         != XML_STATUS_ERROR)
964       break;
965     /* See comment in test_alloc_parse_xdecl() */
966     alloc_teardown();
967     alloc_setup();
968   }
969   if (i == 0)
970     fail("Parse succeeded despite failing reallocator");
971   if (i == max_realloc_count)
972     fail("Parse failed at maximum reallocation count");
973 }
974 END_TEST
975 
976 /* Test attribute enums in a #IMPLIED attribute forcing pool growth */
977 START_TEST(test_alloc_realloc_implied_attribute) {
978   /* Forcing this particular code path is a balancing act.  The
979    * addition of the closing parenthesis and terminal NUL must be
980    * what pushes the string of enums over the 1024-byte limit,
981    * otherwise a different code path will pick up the realloc.
982    */
983   const char *text
984       = "<!DOCTYPE doc [\n"
985         "<!ELEMENT doc EMPTY>\n"
986         "<!ATTLIST doc a "
987         /* Each line is 64 characters */
988         "(ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
989         "|BBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
990         "|CBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
991         "|DBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
992         "|EBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
993         "|FBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
994         "|GBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
995         "|HBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
996         "|IBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
997         "|JBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
998         "|KBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
999         "|LBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
1000         "|MBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
1001         "|NBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
1002         "|OBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
1003         "|PBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMN)"
1004         " #IMPLIED>\n"
1005         "]><doc/>";
1006   int i;
1007   const int max_realloc_count = 10;
1008 
1009   for (i = 0; i < max_realloc_count; i++) {
1010     g_reallocation_count = i;
1011     XML_SetAttlistDeclHandler(g_parser, dummy_attlist_decl_handler);
1012     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
1013         != XML_STATUS_ERROR)
1014       break;
1015     /* See comment in test_alloc_parse_xdecl() */
1016     alloc_teardown();
1017     alloc_setup();
1018   }
1019   if (i == 0)
1020     fail("Parse succeeded despite failing reallocator");
1021   if (i == max_realloc_count)
1022     fail("Parse failed at maximum reallocation count");
1023 }
1024 END_TEST
1025 
1026 /* Test attribute enums in a defaulted attribute forcing pool growth */
1027 START_TEST(test_alloc_realloc_default_attribute) {
1028   /* Forcing this particular code path is a balancing act.  The
1029    * addition of the closing parenthesis and terminal NUL must be
1030    * what pushes the string of enums over the 1024-byte limit,
1031    * otherwise a different code path will pick up the realloc.
1032    */
1033   const char *text
1034       = "<!DOCTYPE doc [\n"
1035         "<!ELEMENT doc EMPTY>\n"
1036         "<!ATTLIST doc a "
1037         /* Each line is 64 characters */
1038         "(ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
1039         "|BBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
1040         "|CBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
1041         "|DBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
1042         "|EBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
1043         "|FBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
1044         "|GBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
1045         "|HBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
1046         "|IBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
1047         "|JBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
1048         "|KBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
1049         "|LBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
1050         "|MBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
1051         "|NBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
1052         "|OBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
1053         "|PBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMN)"
1054         " 'ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO'"
1055         ">\n]><doc/>";
1056   int i;
1057   const int max_realloc_count = 10;
1058 
1059   for (i = 0; i < max_realloc_count; i++) {
1060     g_reallocation_count = i;
1061     XML_SetAttlistDeclHandler(g_parser, dummy_attlist_decl_handler);
1062     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
1063         != XML_STATUS_ERROR)
1064       break;
1065     /* See comment in test_alloc_parse_xdecl() */
1066     alloc_teardown();
1067     alloc_setup();
1068   }
1069   if (i == 0)
1070     fail("Parse succeeded despite failing reallocator");
1071   if (i == max_realloc_count)
1072     fail("Parse failed at maximum reallocation count");
1073 }
1074 END_TEST
1075 
1076 /* Test long notation name with dodgy allocator */
1077 START_TEST(test_alloc_notation) {
1078   const char *text
1079       = "<!DOCTYPE doc [\n"
1080         "<!NOTATION "
1081         /* Each line is 64 characters */
1082         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1083         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1084         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1085         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1086         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1087         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1088         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1089         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1090         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1091         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1092         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1093         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1094         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1095         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1096         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1097         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1098         " SYSTEM 'http://example.org/n'>\n"
1099         "<!ENTITY e SYSTEM 'http://example.org/e' NDATA "
1100         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1101         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1102         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1103         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1104         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1105         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1106         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1107         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1108         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1109         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1110         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1111         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1112         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1113         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1114         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1115         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1116         ">\n"
1117         "<!ELEMENT doc EMPTY>\n"
1118         "]>\n<doc/>";
1119   int i;
1120   const int max_alloc_count = 20;
1121 
1122   for (i = 0; i < max_alloc_count; i++) {
1123     g_allocation_count = i;
1124     init_dummy_handlers();
1125     XML_SetNotationDeclHandler(g_parser, dummy_notation_decl_handler);
1126     XML_SetEntityDeclHandler(g_parser, dummy_entity_decl_handler);
1127     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
1128         != XML_STATUS_ERROR)
1129       break;
1130     /* See comment in test_alloc_parse_xdecl() */
1131     alloc_teardown();
1132     alloc_setup();
1133   }
1134   if (i == 0)
1135     fail("Parse succeeded despite allocation failures");
1136   if (i == max_alloc_count)
1137     fail("Parse failed at maximum allocation count");
1138   if (get_dummy_handler_flags()
1139       != (DUMMY_ENTITY_DECL_HANDLER_FLAG | DUMMY_NOTATION_DECL_HANDLER_FLAG))
1140     fail("Entity declaration handler not called");
1141 }
1142 END_TEST
1143 
1144 /* Test public notation with dodgy allocator */
1145 START_TEST(test_alloc_public_notation) {
1146   const char *text
1147       = "<!DOCTYPE doc [\n"
1148         "<!NOTATION note PUBLIC '"
1149         /* 64 characters per line */
1150         "http://example.com/a/long/enough/name/to/trigger/pool/growth/zz/"
1151         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
1152         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
1153         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
1154         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
1155         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
1156         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
1157         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
1158         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
1159         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
1160         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
1161         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
1162         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
1163         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
1164         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
1165         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
1166         "' 'foo'>\n"
1167         "<!ENTITY e SYSTEM 'http://example.com/e' NDATA note>\n"
1168         "<!ELEMENT doc EMPTY>\n"
1169         "]>\n<doc/>";
1170   int i;
1171   const int max_alloc_count = 20;
1172 
1173   for (i = 0; i < max_alloc_count; i++) {
1174     g_allocation_count = i;
1175     init_dummy_handlers();
1176     XML_SetNotationDeclHandler(g_parser, dummy_notation_decl_handler);
1177     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
1178         != XML_STATUS_ERROR)
1179       break;
1180     /* See comment in test_alloc_parse_xdecl() */
1181     alloc_teardown();
1182     alloc_setup();
1183   }
1184   if (i == 0)
1185     fail("Parse succeeded despite allocation failures");
1186   if (i == max_alloc_count)
1187     fail("Parse failed at maximum allocation count");
1188   if (get_dummy_handler_flags() != DUMMY_NOTATION_DECL_HANDLER_FLAG)
1189     fail("Notation handler not called");
1190 }
1191 END_TEST
1192 
1193 /* Test public notation with dodgy allocator */
1194 START_TEST(test_alloc_system_notation) {
1195   const char *text
1196       = "<!DOCTYPE doc [\n"
1197         "<!NOTATION note SYSTEM '"
1198         /* 64 characters per line */
1199         "http://example.com/a/long/enough/name/to/trigger/pool/growth/zz/"
1200         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
1201         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
1202         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
1203         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
1204         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
1205         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
1206         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
1207         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
1208         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
1209         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
1210         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
1211         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
1212         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
1213         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
1214         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
1215         "'>\n"
1216         "<!ENTITY e SYSTEM 'http://example.com/e' NDATA note>\n"
1217         "<!ELEMENT doc EMPTY>\n"
1218         "]>\n<doc/>";
1219   int i;
1220   const int max_alloc_count = 20;
1221 
1222   for (i = 0; i < max_alloc_count; i++) {
1223     g_allocation_count = i;
1224     init_dummy_handlers();
1225     XML_SetNotationDeclHandler(g_parser, dummy_notation_decl_handler);
1226     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
1227         != XML_STATUS_ERROR)
1228       break;
1229     /* See comment in test_alloc_parse_xdecl() */
1230     alloc_teardown();
1231     alloc_setup();
1232   }
1233   if (i == 0)
1234     fail("Parse succeeded despite allocation failures");
1235   if (i == max_alloc_count)
1236     fail("Parse failed at maximum allocation count");
1237   if (get_dummy_handler_flags() != DUMMY_NOTATION_DECL_HANDLER_FLAG)
1238     fail("Notation handler not called");
1239 }
1240 END_TEST
1241 
1242 START_TEST(test_alloc_nested_groups) {
1243   const char *text
1244       = "<!DOCTYPE doc [\n"
1245         "<!ELEMENT doc "
1246         /* Sixteen elements per line */
1247         "(e,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,"
1248         "(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?"
1249         "))))))))))))))))))))))))))))))))>\n"
1250         "<!ELEMENT e EMPTY>"
1251         "]>\n"
1252         "<doc><e/></doc>";
1253   CharData storage;
1254   int i;
1255   const int max_alloc_count = 20;
1256 
1257   for (i = 0; i < max_alloc_count; i++) {
1258     g_allocation_count = i;
1259     CharData_Init(&storage);
1260     XML_SetElementDeclHandler(g_parser, dummy_element_decl_handler);
1261     XML_SetStartElementHandler(g_parser, record_element_start_handler);
1262     XML_SetUserData(g_parser, &storage);
1263     init_dummy_handlers();
1264     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
1265         != XML_STATUS_ERROR)
1266       break;
1267     /* See comment in test_alloc_parse_xdecl() */
1268     alloc_teardown();
1269     alloc_setup();
1270   }
1271 
1272   if (i == 0)
1273     fail("Parse succeeded despite failing reallocator");
1274   if (i == max_alloc_count)
1275     fail("Parse failed at maximum reallocation count");
1276   CharData_CheckXMLChars(&storage, XCS("doce"));
1277   if (get_dummy_handler_flags() != DUMMY_ELEMENT_DECL_HANDLER_FLAG)
1278     fail("Element handler not fired");
1279 }
1280 END_TEST
1281 
1282 START_TEST(test_alloc_realloc_nested_groups) {
1283   const char *text
1284       = "<!DOCTYPE doc [\n"
1285         "<!ELEMENT doc "
1286         /* Sixteen elements per line */
1287         "(e,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,"
1288         "(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?"
1289         "))))))))))))))))))))))))))))))))>\n"
1290         "<!ELEMENT e EMPTY>"
1291         "]>\n"
1292         "<doc><e/></doc>";
1293   CharData storage;
1294   int i;
1295   const int max_realloc_count = 10;
1296 
1297   for (i = 0; i < max_realloc_count; i++) {
1298     g_reallocation_count = i;
1299     CharData_Init(&storage);
1300     XML_SetElementDeclHandler(g_parser, dummy_element_decl_handler);
1301     XML_SetStartElementHandler(g_parser, record_element_start_handler);
1302     XML_SetUserData(g_parser, &storage);
1303     init_dummy_handlers();
1304     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
1305         != XML_STATUS_ERROR)
1306       break;
1307     /* See comment in test_alloc_parse_xdecl() */
1308     alloc_teardown();
1309     alloc_setup();
1310   }
1311 
1312   if (i == 0)
1313     fail("Parse succeeded despite failing reallocator");
1314   if (i == max_realloc_count)
1315     fail("Parse failed at maximum reallocation count");
1316   CharData_CheckXMLChars(&storage, XCS("doce"));
1317   if (get_dummy_handler_flags() != DUMMY_ELEMENT_DECL_HANDLER_FLAG)
1318     fail("Element handler not fired");
1319 }
1320 END_TEST
1321 
1322 START_TEST(test_alloc_large_group) {
1323   const char *text = "<!DOCTYPE doc [\n"
1324                      "<!ELEMENT doc ("
1325                      "a1|a2|a3|a4|a5|a6|a7|a8|"
1326                      "b1|b2|b3|b4|b5|b6|b7|b8|"
1327                      "c1|c2|c3|c4|c5|c6|c7|c8|"
1328                      "d1|d2|d3|d4|d5|d6|d7|d8|"
1329                      "e1"
1330                      ")+>\n"
1331                      "]>\n"
1332                      "<doc>\n"
1333                      "<a1/>\n"
1334                      "</doc>\n";
1335   int i;
1336   const int max_alloc_count = 50;
1337 
1338   for (i = 0; i < max_alloc_count; i++) {
1339     g_allocation_count = i;
1340     XML_SetElementDeclHandler(g_parser, dummy_element_decl_handler);
1341     init_dummy_handlers();
1342     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
1343         != XML_STATUS_ERROR)
1344       break;
1345     /* See comment in test_alloc_parse_xdecl() */
1346     alloc_teardown();
1347     alloc_setup();
1348   }
1349   if (i == 0)
1350     fail("Parse succeeded despite failing allocator");
1351   if (i == max_alloc_count)
1352     fail("Parse failed at maximum allocation count");
1353   if (get_dummy_handler_flags() != DUMMY_ELEMENT_DECL_HANDLER_FLAG)
1354     fail("Element handler flag not raised");
1355 }
1356 END_TEST
1357 
1358 START_TEST(test_alloc_realloc_group_choice) {
1359   const char *text = "<!DOCTYPE doc [\n"
1360                      "<!ELEMENT doc ("
1361                      "a1|a2|a3|a4|a5|a6|a7|a8|"
1362                      "b1|b2|b3|b4|b5|b6|b7|b8|"
1363                      "c1|c2|c3|c4|c5|c6|c7|c8|"
1364                      "d1|d2|d3|d4|d5|d6|d7|d8|"
1365                      "e1"
1366                      ")+>\n"
1367                      "]>\n"
1368                      "<doc>\n"
1369                      "<a1/>\n"
1370                      "<b2 attr='foo'>This is a foo</b2>\n"
1371                      "<c3></c3>\n"
1372                      "</doc>\n";
1373   int i;
1374   const int max_realloc_count = 10;
1375 
1376   for (i = 0; i < max_realloc_count; i++) {
1377     g_reallocation_count = i;
1378     XML_SetElementDeclHandler(g_parser, dummy_element_decl_handler);
1379     init_dummy_handlers();
1380     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
1381         != XML_STATUS_ERROR)
1382       break;
1383     /* See comment in test_alloc_parse_xdecl() */
1384     alloc_teardown();
1385     alloc_setup();
1386   }
1387   if (i == 0)
1388     fail("Parse succeeded despite failing reallocator");
1389   if (i == max_realloc_count)
1390     fail("Parse failed at maximum reallocation count");
1391   if (get_dummy_handler_flags() != DUMMY_ELEMENT_DECL_HANDLER_FLAG)
1392     fail("Element handler flag not raised");
1393 }
1394 END_TEST
1395 
1396 START_TEST(test_alloc_pi_in_epilog) {
1397   const char *text = "<doc></doc>\n"
1398                      "<?pi in epilog?>";
1399   int i;
1400   const int max_alloc_count = 15;
1401 
1402   for (i = 0; i < max_alloc_count; i++) {
1403     g_allocation_count = i;
1404     XML_SetProcessingInstructionHandler(g_parser, dummy_pi_handler);
1405     init_dummy_handlers();
1406     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
1407         != XML_STATUS_ERROR)
1408       break;
1409     /* See comment in test_alloc_parse_xdecl() */
1410     alloc_teardown();
1411     alloc_setup();
1412   }
1413   if (i == 0)
1414     fail("Parse completed despite failing allocator");
1415   if (i == max_alloc_count)
1416     fail("Parse failed at maximum allocation count");
1417   if (get_dummy_handler_flags() != DUMMY_PI_HANDLER_FLAG)
1418     fail("Processing instruction handler not invoked");
1419 }
1420 END_TEST
1421 
1422 START_TEST(test_alloc_comment_in_epilog) {
1423   const char *text = "<doc></doc>\n"
1424                      "<!-- comment in epilog -->";
1425   int i;
1426   const int max_alloc_count = 15;
1427 
1428   for (i = 0; i < max_alloc_count; i++) {
1429     g_allocation_count = i;
1430     XML_SetCommentHandler(g_parser, dummy_comment_handler);
1431     init_dummy_handlers();
1432     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
1433         != XML_STATUS_ERROR)
1434       break;
1435     /* See comment in test_alloc_parse_xdecl() */
1436     alloc_teardown();
1437     alloc_setup();
1438   }
1439   if (i == 0)
1440     fail("Parse completed despite failing allocator");
1441   if (i == max_alloc_count)
1442     fail("Parse failed at maximum allocation count");
1443   if (get_dummy_handler_flags() != DUMMY_COMMENT_HANDLER_FLAG)
1444     fail("Processing instruction handler not invoked");
1445 }
1446 END_TEST
1447 
1448 START_TEST(test_alloc_realloc_long_attribute_value) {
1449   const char *text
1450       = "<!DOCTYPE doc [<!ENTITY foo '"
1451         /* Each line is 64 characters */
1452         "This entity will be substituted as an attribute value, and is   "
1453         "calculated to be exactly long enough that the terminating NUL   "
1454         "that the library adds internally will trigger the string pool to"
1455         "grow. GHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1456         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1457         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1458         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1459         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1460         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1461         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1462         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1463         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1464         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1465         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1466         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1467         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1468         "'>]>\n"
1469         "<doc a='&foo;'></doc>";
1470   int i;
1471   const int max_realloc_count = 10;
1472 
1473   for (i = 0; i < max_realloc_count; i++) {
1474     g_reallocation_count = i;
1475     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
1476         != XML_STATUS_ERROR)
1477       break;
1478     /* See comment in test_alloc_parse_xdecl() */
1479     alloc_teardown();
1480     alloc_setup();
1481   }
1482   if (i == 0)
1483     fail("Parse succeeded despite failing reallocator");
1484   if (i == max_realloc_count)
1485     fail("Parse failed at maximum reallocation count");
1486 }
1487 END_TEST
1488 
1489 START_TEST(test_alloc_attribute_whitespace) {
1490   const char *text = "<doc a=' '></doc>";
1491   int i;
1492   const int max_alloc_count = 15;
1493 
1494   for (i = 0; i < max_alloc_count; i++) {
1495     g_allocation_count = i;
1496     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
1497         != XML_STATUS_ERROR)
1498       break;
1499     /* See comment in test_alloc_parse_xdecl() */
1500     alloc_teardown();
1501     alloc_setup();
1502   }
1503   if (i == 0)
1504     fail("Parse succeeded despite failing allocator");
1505   if (i == max_alloc_count)
1506     fail("Parse failed at maximum allocation count");
1507 }
1508 END_TEST
1509 
1510 START_TEST(test_alloc_attribute_predefined_entity) {
1511   const char *text = "<doc a='&amp;'></doc>";
1512   int i;
1513   const int max_alloc_count = 15;
1514 
1515   for (i = 0; i < max_alloc_count; i++) {
1516     g_allocation_count = i;
1517     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
1518         != XML_STATUS_ERROR)
1519       break;
1520     /* See comment in test_alloc_parse_xdecl() */
1521     alloc_teardown();
1522     alloc_setup();
1523   }
1524   if (i == 0)
1525     fail("Parse succeeded despite failing allocator");
1526   if (i == max_alloc_count)
1527     fail("Parse failed at maximum allocation count");
1528 }
1529 END_TEST
1530 
1531 /* Test that a character reference at the end of a suitably long
1532  * default value for an attribute can trigger pool growth, and recovers
1533  * if the allocator fails on it.
1534  */
1535 START_TEST(test_alloc_long_attr_default_with_char_ref) {
1536   const char *text
1537       = "<!DOCTYPE doc [<!ATTLIST doc a CDATA '"
1538         /* 64 characters per line */
1539         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1540         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1541         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1542         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1543         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1544         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1545         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1546         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1547         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1548         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1549         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1550         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1551         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1552         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1553         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1554         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHI"
1555         "&#x31;'>]>\n"
1556         "<doc/>";
1557   int i;
1558   const int max_alloc_count = 20;
1559 
1560   for (i = 0; i < max_alloc_count; i++) {
1561     g_allocation_count = i;
1562     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
1563         != XML_STATUS_ERROR)
1564       break;
1565     /* See comment in test_alloc_parse_xdecl() */
1566     alloc_teardown();
1567     alloc_setup();
1568   }
1569   if (i == 0)
1570     fail("Parse succeeded despite failing allocator");
1571   if (i == max_alloc_count)
1572     fail("Parse failed at maximum allocation count");
1573 }
1574 END_TEST
1575 
1576 /* Test that a long character reference substitution triggers a pool
1577  * expansion correctly for an attribute value.
1578  */
1579 START_TEST(test_alloc_long_attr_value) {
1580   const char *text
1581       = "<!DOCTYPE test [<!ENTITY foo '\n"
1582         /* 64 characters per line */
1583         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1584         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1585         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1586         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1587         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1588         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1589         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1590         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1591         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1592         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1593         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1594         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1595         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1596         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1597         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1598         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1599         "'>]>\n"
1600         "<test a='&foo;'/>";
1601   int i;
1602   const int max_alloc_count = 25;
1603 
1604   for (i = 0; i < max_alloc_count; i++) {
1605     g_allocation_count = i;
1606     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
1607         != XML_STATUS_ERROR)
1608       break;
1609     /* See comment in test_alloc_parse_xdecl() */
1610     alloc_teardown();
1611     alloc_setup();
1612   }
1613   if (i == 0)
1614     fail("Parse succeeded despite failing allocator");
1615   if (i == max_alloc_count)
1616     fail("Parse failed at maximum allocation count");
1617 }
1618 END_TEST
1619 
1620 /* Test that an error in a nested parameter entity substitution is
1621  * handled correctly.  It seems unlikely that the code path being
1622  * exercised can be reached purely by carefully crafted XML, but an
1623  * allocation error in the right place will definitely do it.
1624  */
1625 START_TEST(test_alloc_nested_entities) {
1626   const char *text = "<!DOCTYPE doc SYSTEM 'http://example.org/one.ent'>\n"
1627                      "<doc />";
1628   ExtFaults test_data
1629       = {"<!ENTITY % pe1 '"
1630          /* 64 characters per line */
1631          "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1632          "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1633          "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1634          "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1635          "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1636          "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1637          "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1638          "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1639          "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1640          "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1641          "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1642          "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1643          "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1644          "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1645          "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1646          "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1647          "'>\n"
1648          "<!ENTITY % pe2 '%pe1;'>\n"
1649          "<!ENTITY % pe3 '%pe2;'>",
1650          "Memory Fail not faulted", NULL, XML_ERROR_NO_MEMORY};
1651 
1652   /* Causes an allocation error in a nested storeEntityValue() */
1653   g_allocation_count = 12;
1654   XML_SetUserData(g_parser, &test_data);
1655   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
1656   XML_SetExternalEntityRefHandler(g_parser, external_entity_faulter);
1657   expect_failure(text, XML_ERROR_EXTERNAL_ENTITY_HANDLING,
1658                  "Entity allocation failure not noted");
1659 }
1660 END_TEST
1661 
1662 START_TEST(test_alloc_realloc_param_entity_newline) {
1663   const char *text = "<!DOCTYPE doc SYSTEM 'http://example.org/'>\n"
1664                      "<doc/>";
1665   char dtd_text[]
1666       = "<!ENTITY % pe '<!ATTLIST doc att CDATA \""
1667         /* 64 characters per line */
1668         "This default value is carefully crafted so that the carriage    "
1669         "return right at the end of the entity string causes an internal "
1670         "string pool to have to grow.  This allows us to test the alloc  "
1671         "failure path from that point. OPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1672         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1673         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1674         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1675         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1676         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1677         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1678         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1679         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1680         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1681         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1682         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1683         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDE"
1684         "\">\n'>"
1685         "%pe;\n";
1686   int i;
1687   const int max_realloc_count = 5;
1688 
1689   for (i = 0; i < max_realloc_count; i++) {
1690     g_reallocation_count = i;
1691     XML_SetUserData(g_parser, dtd_text);
1692     XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
1693     XML_SetExternalEntityRefHandler(g_parser, external_entity_alloc);
1694     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
1695         != XML_STATUS_ERROR)
1696       break;
1697     /* See comment in test_alloc_parse_xdecl() */
1698     alloc_teardown();
1699     alloc_setup();
1700   }
1701   if (i == 0)
1702     fail("Parse succeeded despite failing reallocator");
1703   if (i == max_realloc_count)
1704     fail("Parse failed at maximum reallocation count");
1705 }
1706 END_TEST
1707 
1708 START_TEST(test_alloc_realloc_ce_extends_pe) {
1709   const char *text = "<!DOCTYPE doc SYSTEM 'http://example.org/'>\n"
1710                      "<doc/>";
1711   char dtd_text[]
1712       = "<!ENTITY % pe '<!ATTLIST doc att CDATA \""
1713         /* 64 characters per line */
1714         "This default value is carefully crafted so that the character   "
1715         "entity at the end causes an internal string pool to have to     "
1716         "grow.  This allows us to test the allocation failure path from  "
1717         "that point onwards. EFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1718         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1719         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1720         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1721         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1722         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1723         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1724         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1725         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1726         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1727         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1728         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1729         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFG&#x51;"
1730         "\">\n'>"
1731         "%pe;\n";
1732   int i;
1733   const int max_realloc_count = 5;
1734 
1735   for (i = 0; i < max_realloc_count; i++) {
1736     g_reallocation_count = i;
1737     XML_SetUserData(g_parser, dtd_text);
1738     XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
1739     XML_SetExternalEntityRefHandler(g_parser, external_entity_alloc);
1740     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
1741         != XML_STATUS_ERROR)
1742       break;
1743     /* See comment in test_alloc_parse_xdecl() */
1744     alloc_teardown();
1745     alloc_setup();
1746   }
1747   if (i == 0)
1748     fail("Parse succeeded despite failing reallocator");
1749   if (i == max_realloc_count)
1750     fail("Parse failed at maximum reallocation count");
1751 }
1752 END_TEST
1753 
1754 START_TEST(test_alloc_realloc_attributes) {
1755   const char *text = "<!DOCTYPE doc [\n"
1756                      "  <!ATTLIST doc\n"
1757                      "    a1  (a|b|c)   'a'\n"
1758                      "    a2  (foo|bar) #IMPLIED\n"
1759                      "    a3  NMTOKEN   #IMPLIED\n"
1760                      "    a4  NMTOKENS  #IMPLIED\n"
1761                      "    a5  ID        #IMPLIED\n"
1762                      "    a6  IDREF     #IMPLIED\n"
1763                      "    a7  IDREFS    #IMPLIED\n"
1764                      "    a8  ENTITY    #IMPLIED\n"
1765                      "    a9  ENTITIES  #IMPLIED\n"
1766                      "    a10 CDATA     #IMPLIED\n"
1767                      "  >]>\n"
1768                      "<doc>wombat</doc>\n";
1769   int i;
1770   const int max_realloc_count = 5;
1771 
1772   for (i = 0; i < max_realloc_count; i++) {
1773     g_reallocation_count = i;
1774     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
1775         != XML_STATUS_ERROR)
1776       break;
1777     /* See comment in test_alloc_parse_xdecl() */
1778     alloc_teardown();
1779     alloc_setup();
1780   }
1781 
1782   if (i == 0)
1783     fail("Parse succeeded despite failing reallocator");
1784   if (i == max_realloc_count)
1785     fail("Parse failed at maximum reallocation count");
1786 }
1787 END_TEST
1788 
1789 START_TEST(test_alloc_long_doc_name) {
1790   const char *text =
1791       /* 64 characters per line */
1792       "<LongRootElementNameThatWillCauseTheNextAllocationToExpandTheStr"
1793       "ingPoolForTheDTDQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
1794       "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
1795       "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
1796       "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
1797       "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
1798       "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
1799       "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
1800       "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
1801       "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
1802       "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
1803       "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
1804       "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
1805       "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
1806       "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
1807       "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
1808       " a='1'/>";
1809   int i;
1810   const int max_alloc_count = 20;
1811 
1812   for (i = 0; i < max_alloc_count; i++) {
1813     g_allocation_count = i;
1814     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
1815         != XML_STATUS_ERROR)
1816       break;
1817     /* See comment in test_alloc_parse_xdecl() */
1818     alloc_teardown();
1819     alloc_setup();
1820   }
1821   if (i == 0)
1822     fail("Parsing worked despite failing reallocations");
1823   else if (i == max_alloc_count)
1824     fail("Parsing failed even at max reallocation count");
1825 }
1826 END_TEST
1827 
1828 START_TEST(test_alloc_long_base) {
1829   const char *text = "<!DOCTYPE doc [\n"
1830                      "  <!ENTITY e SYSTEM 'foo'>\n"
1831                      "]>\n"
1832                      "<doc>&e;</doc>";
1833   char entity_text[] = "Hello world";
1834   const XML_Char *base =
1835       /* 64 characters per line */
1836       /* clang-format off */
1837         XCS("LongBaseURI/that/will/overflow/an/internal/buffer/and/cause/it/t")
1838         XCS("o/have/to/grow/PQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/")
1839         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/")
1840         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/")
1841         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/")
1842         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/")
1843         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/")
1844         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/")
1845         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/")
1846         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/")
1847         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/")
1848         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/")
1849         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/")
1850         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/")
1851         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/")
1852         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/");
1853   /* clang-format on */
1854   int i;
1855   const int max_alloc_count = 25;
1856 
1857   for (i = 0; i < max_alloc_count; i++) {
1858     g_allocation_count = i;
1859     XML_SetUserData(g_parser, entity_text);
1860     XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
1861     XML_SetExternalEntityRefHandler(g_parser, external_entity_alloc);
1862     if (XML_SetBase(g_parser, base) == XML_STATUS_ERROR) {
1863       XML_ParserReset(g_parser, NULL);
1864       continue;
1865     }
1866     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
1867         != XML_STATUS_ERROR)
1868       break;
1869     /* See comment in test_alloc_parse_xdecl() */
1870     alloc_teardown();
1871     alloc_setup();
1872   }
1873   if (i == 0)
1874     fail("Parsing worked despite failing allocations");
1875   else if (i == max_alloc_count)
1876     fail("Parsing failed even at max allocation count");
1877 }
1878 END_TEST
1879 
1880 START_TEST(test_alloc_long_public_id) {
1881   const char *text
1882       = "<!DOCTYPE doc [\n"
1883         "  <!ENTITY e PUBLIC '"
1884         /* 64 characters per line */
1885         "LongPublicIDThatShouldResultInAnInternalStringPoolGrowingAtASpec"
1886         "ificMomentKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
1887         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
1888         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
1889         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
1890         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
1891         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
1892         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
1893         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
1894         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
1895         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
1896         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
1897         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
1898         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
1899         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
1900         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
1901         "' 'bar'>\n"
1902         "]>\n"
1903         "<doc>&e;</doc>";
1904   char entity_text[] = "Hello world";
1905   int i;
1906   const int max_alloc_count = 40;
1907 
1908   for (i = 0; i < max_alloc_count; i++) {
1909     g_allocation_count = i;
1910     XML_SetUserData(g_parser, entity_text);
1911     XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
1912     XML_SetExternalEntityRefHandler(g_parser, external_entity_alloc);
1913     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
1914         != XML_STATUS_ERROR)
1915       break;
1916     /* See comment in test_alloc_parse_xdecl() */
1917     alloc_teardown();
1918     alloc_setup();
1919   }
1920   if (i == 0)
1921     fail("Parsing worked despite failing allocations");
1922   else if (i == max_alloc_count)
1923     fail("Parsing failed even at max allocation count");
1924 }
1925 END_TEST
1926 
1927 START_TEST(test_alloc_long_entity_value) {
1928   const char *text
1929       = "<!DOCTYPE doc [\n"
1930         "  <!ENTITY e1 '"
1931         /* 64 characters per line */
1932         "Long entity value that should provoke a string pool to grow whil"
1933         "e setting up to parse the external entity below. xyz0123456789AB"
1934         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
1935         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
1936         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
1937         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
1938         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
1939         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
1940         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
1941         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
1942         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
1943         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
1944         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
1945         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
1946         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
1947         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
1948         "'>\n"
1949         "  <!ENTITY e2 SYSTEM 'bar'>\n"
1950         "]>\n"
1951         "<doc>&e2;</doc>";
1952   char entity_text[] = "Hello world";
1953   int i;
1954   const int max_alloc_count = 40;
1955 
1956   for (i = 0; i < max_alloc_count; i++) {
1957     g_allocation_count = i;
1958     XML_SetUserData(g_parser, entity_text);
1959     XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
1960     XML_SetExternalEntityRefHandler(g_parser, external_entity_alloc);
1961     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
1962         != XML_STATUS_ERROR)
1963       break;
1964     /* See comment in test_alloc_parse_xdecl() */
1965     alloc_teardown();
1966     alloc_setup();
1967   }
1968   if (i == 0)
1969     fail("Parsing worked despite failing allocations");
1970   else if (i == max_alloc_count)
1971     fail("Parsing failed even at max allocation count");
1972 }
1973 END_TEST
1974 
1975 START_TEST(test_alloc_long_notation) {
1976   const char *text
1977       = "<!DOCTYPE doc [\n"
1978         "  <!NOTATION note SYSTEM '"
1979         /* 64 characters per line */
1980         "ALongNotationNameThatShouldProvokeStringPoolGrowthWhileCallingAn"
1981         "ExternalEntityParserUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
1982         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
1983         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
1984         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
1985         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
1986         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
1987         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
1988         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
1989         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
1990         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
1991         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
1992         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
1993         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
1994         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
1995         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
1996         "'>\n"
1997         "  <!ENTITY e1 SYSTEM 'foo' NDATA "
1998         /* 64 characters per line */
1999         "ALongNotationNameThatShouldProvokeStringPoolGrowthWhileCallingAn"
2000         "ExternalEntityParserUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
2001         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
2002         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
2003         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
2004         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
2005         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
2006         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
2007         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
2008         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
2009         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
2010         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
2011         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
2012         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
2013         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
2014         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
2015         ">\n"
2016         "  <!ENTITY e2 SYSTEM 'bar'>\n"
2017         "]>\n"
2018         "<doc>&e2;</doc>";
2019   ExtOption options[]
2020       = {{XCS("foo"), "Entity Foo"}, {XCS("bar"), "Entity Bar"}, {NULL, NULL}};
2021   int i;
2022   const int max_alloc_count = 40;
2023 
2024   for (i = 0; i < max_alloc_count; i++) {
2025     g_allocation_count = i;
2026     XML_SetUserData(g_parser, options);
2027     XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
2028     XML_SetExternalEntityRefHandler(g_parser, external_entity_optioner);
2029     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
2030         != XML_STATUS_ERROR)
2031       break;
2032 
2033     /* See comment in test_alloc_parse_xdecl() */
2034     alloc_teardown();
2035     alloc_setup();
2036   }
2037   if (i == 0)
2038     fail("Parsing worked despite failing allocations");
2039   else if (i == max_alloc_count)
2040     fail("Parsing failed even at max allocation count");
2041 }
2042 END_TEST
2043 
2044 START_TEST(test_alloc_reset_after_external_entity_parser_create_fail) {
2045   const char *const text = "<!DOCTYPE doc SYSTEM 'foo'><doc/>";
2046 
2047   XML_SetExternalEntityRefHandler(
2048       g_parser, external_entity_parser_create_alloc_fail_handler);
2049   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
2050 
2051   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
2052       != XML_STATUS_ERROR)
2053     fail("Call to parse was expected to fail");
2054 
2055   if (XML_GetErrorCode(g_parser) != XML_ERROR_EXTERNAL_ENTITY_HANDLING)
2056     fail("Call to parse was expected to fail from the external entity handler");
2057 
2058   XML_ParserReset(g_parser, NULL);
2059 }
2060 END_TEST
2061 
2062 void
2063 make_alloc_test_case(Suite *s) {
2064   TCase *tc_alloc = tcase_create("allocation tests");
2065 
2066   suite_add_tcase(s, tc_alloc);
2067   tcase_add_checked_fixture(tc_alloc, alloc_setup, alloc_teardown);
2068 
2069   tcase_add_test(tc_alloc, test_alloc_parse_xdecl);
2070   tcase_add_test(tc_alloc, test_alloc_parse_xdecl_2);
2071   tcase_add_test(tc_alloc, test_alloc_parse_pi);
2072   tcase_add_test(tc_alloc, test_alloc_parse_pi_2);
2073   tcase_add_test(tc_alloc, test_alloc_parse_pi_3);
2074   tcase_add_test(tc_alloc, test_alloc_parse_comment);
2075   tcase_add_test(tc_alloc, test_alloc_parse_comment_2);
2076   tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_create_external_parser);
2077   tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_run_external_parser);
2078   tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_dtd_copy_default_atts);
2079   tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_external_entity);
2080   tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_ext_entity_set_encoding);
2081   tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_internal_entity);
2082   tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_dtd_default_handling);
2083   tcase_add_test(tc_alloc, test_alloc_explicit_encoding);
2084   tcase_add_test(tc_alloc, test_alloc_set_base);
2085   tcase_add_test(tc_alloc, test_alloc_realloc_buffer);
2086   tcase_add_test__if_xml_ge(tc_alloc, test_alloc_ext_entity_realloc_buffer);
2087   tcase_add_test(tc_alloc, test_alloc_realloc_many_attributes);
2088   tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_public_entity_value);
2089   tcase_add_test__ifdef_xml_dtd(tc_alloc,
2090                                 test_alloc_realloc_subst_public_entity_value);
2091   tcase_add_test(tc_alloc, test_alloc_parse_public_doctype);
2092   tcase_add_test(tc_alloc, test_alloc_parse_public_doctype_long_name);
2093   tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_set_foreign_dtd);
2094   tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_attribute_enum_value);
2095   tcase_add_test__ifdef_xml_dtd(tc_alloc,
2096                                 test_alloc_realloc_attribute_enum_value);
2097   tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_realloc_implied_attribute);
2098   tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_realloc_default_attribute);
2099   tcase_add_test__if_xml_ge(tc_alloc, test_alloc_notation);
2100   tcase_add_test(tc_alloc, test_alloc_public_notation);
2101   tcase_add_test(tc_alloc, test_alloc_system_notation);
2102   tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_nested_groups);
2103   tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_realloc_nested_groups);
2104   tcase_add_test(tc_alloc, test_alloc_large_group);
2105   tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_realloc_group_choice);
2106   tcase_add_test(tc_alloc, test_alloc_pi_in_epilog);
2107   tcase_add_test(tc_alloc, test_alloc_comment_in_epilog);
2108   tcase_add_test__ifdef_xml_dtd(tc_alloc,
2109                                 test_alloc_realloc_long_attribute_value);
2110   tcase_add_test(tc_alloc, test_alloc_attribute_whitespace);
2111   tcase_add_test(tc_alloc, test_alloc_attribute_predefined_entity);
2112   tcase_add_test(tc_alloc, test_alloc_long_attr_default_with_char_ref);
2113   tcase_add_test__if_xml_ge(tc_alloc, test_alloc_long_attr_value);
2114   tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_nested_entities);
2115   tcase_add_test__ifdef_xml_dtd(tc_alloc,
2116                                 test_alloc_realloc_param_entity_newline);
2117   tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_realloc_ce_extends_pe);
2118   tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_realloc_attributes);
2119   tcase_add_test(tc_alloc, test_alloc_long_doc_name);
2120   tcase_add_test__if_xml_ge(tc_alloc, test_alloc_long_base);
2121   tcase_add_test__if_xml_ge(tc_alloc, test_alloc_long_public_id);
2122   tcase_add_test__if_xml_ge(tc_alloc, test_alloc_long_entity_value);
2123   tcase_add_test__if_xml_ge(tc_alloc, test_alloc_long_notation);
2124 
2125   tcase_add_test__ifdef_xml_dtd(
2126       tc_alloc, test_alloc_reset_after_external_entity_parser_create_fail);
2127 }
2128