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