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