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