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