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