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