xref: /freebsd/contrib/expat/tests/runtests.c (revision a2464ee12761660f50d0b6f59f233949ebcacc87)
1 /* Run 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-2022 Sebastian Pipping <sebastian@pipping.org>
14    Copyright (c) 2017-2018 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      Dong-hee Na <donghee.na@python.org>
21    Licensed under the MIT license:
22 
23    Permission is  hereby granted,  free of charge,  to any  person obtaining
24    a  copy  of  this  software   and  associated  documentation  files  (the
25    "Software"),  to  deal in  the  Software  without restriction,  including
26    without  limitation the  rights  to use,  copy,  modify, merge,  publish,
27    distribute, sublicense, and/or sell copies of the Software, and to permit
28    persons  to whom  the Software  is  furnished to  do so,  subject to  the
29    following conditions:
30 
31    The above copyright  notice and this permission notice  shall be included
32    in all copies or substantial portions of the Software.
33 
34    THE  SOFTWARE  IS  PROVIDED  "AS  IS",  WITHOUT  WARRANTY  OF  ANY  KIND,
35    EXPRESS  OR IMPLIED,  INCLUDING  BUT  NOT LIMITED  TO  THE WARRANTIES  OF
36    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
37    NO EVENT SHALL THE AUTHORS OR  COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
38    DAMAGES OR  OTHER LIABILITY, WHETHER  IN AN  ACTION OF CONTRACT,  TORT OR
39    OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
40    USE OR OTHER DEALINGS IN THE SOFTWARE.
41 */
42 
43 #include <expat_config.h>
44 
45 #if defined(NDEBUG)
46 #  undef NDEBUG /* because test suite relies on assert(...) at the moment */
47 #endif
48 
49 #include <assert.h>
50 #include <stdlib.h>
51 #include <stdio.h>
52 #include <string.h>
53 #include <stddef.h> /* ptrdiff_t */
54 #include <ctype.h>
55 #include <limits.h>
56 #include <stdint.h> /* intptr_t uint64_t */
57 
58 #if ! defined(__cplusplus)
59 #  include <stdbool.h>
60 #endif
61 
62 #include "expat.h"
63 #include "chardata.h"
64 #include "structdata.h"
65 #include "internal.h"
66 #include "minicheck.h"
67 #include "memcheck.h"
68 #include "siphash.h"
69 #include "ascii.h" /* for ASCII_xxx */
70 
71 #ifdef XML_LARGE_SIZE
72 #  define XML_FMT_INT_MOD "ll"
73 #else
74 #  define XML_FMT_INT_MOD "l"
75 #endif
76 
77 #ifdef XML_UNICODE_WCHAR_T
78 #  define XML_FMT_CHAR "lc"
79 #  define XML_FMT_STR "ls"
80 #  include <wchar.h>
81 #  define xcstrlen(s) wcslen(s)
82 #  define xcstrcmp(s, t) wcscmp((s), (t))
83 #  define xcstrncmp(s, t, n) wcsncmp((s), (t), (n))
84 #  define XCS(s) _XCS(s)
85 #  define _XCS(s) L##s
86 #else
87 #  ifdef XML_UNICODE
88 #    error "No support for UTF-16 character without wchar_t in tests"
89 #  else
90 #    define XML_FMT_CHAR "c"
91 #    define XML_FMT_STR "s"
92 #    define xcstrlen(s) strlen(s)
93 #    define xcstrcmp(s, t) strcmp((s), (t))
94 #    define xcstrncmp(s, t, n) strncmp((s), (t), (n))
95 #    define XCS(s) s
96 #  endif /* XML_UNICODE */
97 #endif   /* XML_UNICODE_WCHAR_T */
98 
99 static XML_Parser g_parser = NULL;
100 
101 static void
102 tcase_add_test__ifdef_xml_dtd(TCase *tc, tcase_test_function test) {
103 #ifdef XML_DTD
104   tcase_add_test(tc, test);
105 #else
106   UNUSED_P(tc);
107   UNUSED_P(test);
108 #endif
109 }
110 
111 static void
112 basic_setup(void) {
113   g_parser = XML_ParserCreate(NULL);
114   if (g_parser == NULL)
115     fail("Parser not created.");
116 }
117 
118 static void
119 basic_teardown(void) {
120   if (g_parser != NULL) {
121     XML_ParserFree(g_parser);
122     g_parser = NULL;
123   }
124 }
125 
126 /* Generate a failure using the parser state to create an error message;
127    this should be used when the parser reports an error we weren't
128    expecting.
129 */
130 static void
131 _xml_failure(XML_Parser parser, const char *file, int line) {
132   char buffer[1024];
133   enum XML_Error err = XML_GetErrorCode(parser);
134   sprintf(buffer,
135           "    %d: %" XML_FMT_STR " (line %" XML_FMT_INT_MOD
136           "u, offset %" XML_FMT_INT_MOD "u)\n    reported from %s, line %d\n",
137           err, XML_ErrorString(err), XML_GetCurrentLineNumber(parser),
138           XML_GetCurrentColumnNumber(parser), file, line);
139   _fail_unless(0, file, line, buffer);
140 }
141 
142 static enum XML_Status
143 _XML_Parse_SINGLE_BYTES(XML_Parser parser, const char *s, int len,
144                         int isFinal) {
145   enum XML_Status res = XML_STATUS_ERROR;
146   int offset = 0;
147 
148   if (len == 0) {
149     return XML_Parse(parser, s, len, isFinal);
150   }
151 
152   for (; offset < len; offset++) {
153     const int innerIsFinal = (offset == len - 1) && isFinal;
154     const char c = s[offset]; /* to help out-of-bounds detection */
155     res = XML_Parse(parser, &c, sizeof(char), innerIsFinal);
156     if (res != XML_STATUS_OK) {
157       return res;
158     }
159   }
160   return res;
161 }
162 
163 #define xml_failure(parser) _xml_failure((parser), __FILE__, __LINE__)
164 
165 static void
166 _expect_failure(const char *text, enum XML_Error errorCode,
167                 const char *errorMessage, const char *file, int lineno) {
168   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
169       == XML_STATUS_OK)
170     /* Hackish use of _fail_unless() macro, but let's us report
171        the right filename and line number. */
172     _fail_unless(0, file, lineno, errorMessage);
173   if (XML_GetErrorCode(g_parser) != errorCode)
174     _xml_failure(g_parser, file, lineno);
175 }
176 
177 #define expect_failure(text, errorCode, errorMessage)                          \
178   _expect_failure((text), (errorCode), (errorMessage), __FILE__, __LINE__)
179 
180 /* Dummy handlers for when we need to set a handler to tickle a bug,
181    but it doesn't need to do anything.
182 */
183 static unsigned long dummy_handler_flags = 0;
184 
185 #define DUMMY_START_DOCTYPE_HANDLER_FLAG (1UL << 0)
186 #define DUMMY_END_DOCTYPE_HANDLER_FLAG (1UL << 1)
187 #define DUMMY_ENTITY_DECL_HANDLER_FLAG (1UL << 2)
188 #define DUMMY_NOTATION_DECL_HANDLER_FLAG (1UL << 3)
189 #define DUMMY_ELEMENT_DECL_HANDLER_FLAG (1UL << 4)
190 #define DUMMY_ATTLIST_DECL_HANDLER_FLAG (1UL << 5)
191 #define DUMMY_COMMENT_HANDLER_FLAG (1UL << 6)
192 #define DUMMY_PI_HANDLER_FLAG (1UL << 7)
193 #define DUMMY_START_ELEMENT_HANDLER_FLAG (1UL << 8)
194 #define DUMMY_START_CDATA_HANDLER_FLAG (1UL << 9)
195 #define DUMMY_END_CDATA_HANDLER_FLAG (1UL << 10)
196 #define DUMMY_UNPARSED_ENTITY_DECL_HANDLER_FLAG (1UL << 11)
197 #define DUMMY_START_NS_DECL_HANDLER_FLAG (1UL << 12)
198 #define DUMMY_END_NS_DECL_HANDLER_FLAG (1UL << 13)
199 #define DUMMY_START_DOCTYPE_DECL_HANDLER_FLAG (1UL << 14)
200 #define DUMMY_END_DOCTYPE_DECL_HANDLER_FLAG (1UL << 15)
201 #define DUMMY_SKIP_HANDLER_FLAG (1UL << 16)
202 #define DUMMY_DEFAULT_HANDLER_FLAG (1UL << 17)
203 
204 static void XMLCALL
205 dummy_xdecl_handler(void *userData, const XML_Char *version,
206                     const XML_Char *encoding, int standalone) {
207   UNUSED_P(userData);
208   UNUSED_P(version);
209   UNUSED_P(encoding);
210   UNUSED_P(standalone);
211 }
212 
213 static void XMLCALL
214 dummy_start_doctype_handler(void *userData, const XML_Char *doctypeName,
215                             const XML_Char *sysid, const XML_Char *pubid,
216                             int has_internal_subset) {
217   UNUSED_P(userData);
218   UNUSED_P(doctypeName);
219   UNUSED_P(sysid);
220   UNUSED_P(pubid);
221   UNUSED_P(has_internal_subset);
222   dummy_handler_flags |= DUMMY_START_DOCTYPE_HANDLER_FLAG;
223 }
224 
225 static void XMLCALL
226 dummy_end_doctype_handler(void *userData) {
227   UNUSED_P(userData);
228   dummy_handler_flags |= DUMMY_END_DOCTYPE_HANDLER_FLAG;
229 }
230 
231 static void XMLCALL
232 dummy_entity_decl_handler(void *userData, const XML_Char *entityName,
233                           int is_parameter_entity, const XML_Char *value,
234                           int value_length, const XML_Char *base,
235                           const XML_Char *systemId, const XML_Char *publicId,
236                           const XML_Char *notationName) {
237   UNUSED_P(userData);
238   UNUSED_P(entityName);
239   UNUSED_P(is_parameter_entity);
240   UNUSED_P(value);
241   UNUSED_P(value_length);
242   UNUSED_P(base);
243   UNUSED_P(systemId);
244   UNUSED_P(publicId);
245   UNUSED_P(notationName);
246   dummy_handler_flags |= DUMMY_ENTITY_DECL_HANDLER_FLAG;
247 }
248 
249 static void XMLCALL
250 dummy_notation_decl_handler(void *userData, const XML_Char *notationName,
251                             const XML_Char *base, const XML_Char *systemId,
252                             const XML_Char *publicId) {
253   UNUSED_P(userData);
254   UNUSED_P(notationName);
255   UNUSED_P(base);
256   UNUSED_P(systemId);
257   UNUSED_P(publicId);
258   dummy_handler_flags |= DUMMY_NOTATION_DECL_HANDLER_FLAG;
259 }
260 
261 static void XMLCALL
262 dummy_element_decl_handler(void *userData, const XML_Char *name,
263                            XML_Content *model) {
264   UNUSED_P(userData);
265   UNUSED_P(name);
266   /* The content model must be freed by the handler.  Unfortunately
267    * we cannot pass the parser as the userData because this is used
268    * with other handlers that require other userData.
269    */
270   XML_FreeContentModel(g_parser, model);
271   dummy_handler_flags |= DUMMY_ELEMENT_DECL_HANDLER_FLAG;
272 }
273 
274 static void XMLCALL
275 dummy_attlist_decl_handler(void *userData, const XML_Char *elname,
276                            const XML_Char *attname, const XML_Char *att_type,
277                            const XML_Char *dflt, int isrequired) {
278   UNUSED_P(userData);
279   UNUSED_P(elname);
280   UNUSED_P(attname);
281   UNUSED_P(att_type);
282   UNUSED_P(dflt);
283   UNUSED_P(isrequired);
284   dummy_handler_flags |= DUMMY_ATTLIST_DECL_HANDLER_FLAG;
285 }
286 
287 static void XMLCALL
288 dummy_comment_handler(void *userData, const XML_Char *data) {
289   UNUSED_P(userData);
290   UNUSED_P(data);
291   dummy_handler_flags |= DUMMY_COMMENT_HANDLER_FLAG;
292 }
293 
294 static void XMLCALL
295 dummy_pi_handler(void *userData, const XML_Char *target, const XML_Char *data) {
296   UNUSED_P(userData);
297   UNUSED_P(target);
298   UNUSED_P(data);
299   dummy_handler_flags |= DUMMY_PI_HANDLER_FLAG;
300 }
301 
302 static void XMLCALL
303 dummy_start_element(void *userData, const XML_Char *name,
304                     const XML_Char **atts) {
305   UNUSED_P(userData);
306   UNUSED_P(name);
307   UNUSED_P(atts);
308   dummy_handler_flags |= DUMMY_START_ELEMENT_HANDLER_FLAG;
309 }
310 
311 static void XMLCALL
312 dummy_end_element(void *userData, const XML_Char *name) {
313   UNUSED_P(userData);
314   UNUSED_P(name);
315 }
316 
317 static void XMLCALL
318 dummy_start_cdata_handler(void *userData) {
319   UNUSED_P(userData);
320   dummy_handler_flags |= DUMMY_START_CDATA_HANDLER_FLAG;
321 }
322 
323 static void XMLCALL
324 dummy_end_cdata_handler(void *userData) {
325   UNUSED_P(userData);
326   dummy_handler_flags |= DUMMY_END_CDATA_HANDLER_FLAG;
327 }
328 
329 static void XMLCALL
330 dummy_cdata_handler(void *userData, const XML_Char *s, int len) {
331   UNUSED_P(userData);
332   UNUSED_P(s);
333   UNUSED_P(len);
334 }
335 
336 static void XMLCALL
337 dummy_start_namespace_decl_handler(void *userData, const XML_Char *prefix,
338                                    const XML_Char *uri) {
339   UNUSED_P(userData);
340   UNUSED_P(prefix);
341   UNUSED_P(uri);
342   dummy_handler_flags |= DUMMY_START_NS_DECL_HANDLER_FLAG;
343 }
344 
345 static void XMLCALL
346 dummy_end_namespace_decl_handler(void *userData, const XML_Char *prefix) {
347   UNUSED_P(userData);
348   UNUSED_P(prefix);
349   dummy_handler_flags |= DUMMY_END_NS_DECL_HANDLER_FLAG;
350 }
351 
352 /* This handler is obsolete, but while the code exists we should
353  * ensure that dealing with the handler is covered by tests.
354  */
355 static void XMLCALL
356 dummy_unparsed_entity_decl_handler(void *userData, const XML_Char *entityName,
357                                    const XML_Char *base,
358                                    const XML_Char *systemId,
359                                    const XML_Char *publicId,
360                                    const XML_Char *notationName) {
361   UNUSED_P(userData);
362   UNUSED_P(entityName);
363   UNUSED_P(base);
364   UNUSED_P(systemId);
365   UNUSED_P(publicId);
366   UNUSED_P(notationName);
367   dummy_handler_flags |= DUMMY_UNPARSED_ENTITY_DECL_HANDLER_FLAG;
368 }
369 
370 static void XMLCALL
371 dummy_default_handler(void *userData, const XML_Char *s, int len) {
372   UNUSED_P(userData);
373   UNUSED_P(s);
374   UNUSED_P(len);
375 }
376 
377 static void XMLCALL
378 dummy_start_doctype_decl_handler(void *userData, const XML_Char *doctypeName,
379                                  const XML_Char *sysid, const XML_Char *pubid,
380                                  int has_internal_subset) {
381   UNUSED_P(userData);
382   UNUSED_P(doctypeName);
383   UNUSED_P(sysid);
384   UNUSED_P(pubid);
385   UNUSED_P(has_internal_subset);
386   dummy_handler_flags |= DUMMY_START_DOCTYPE_DECL_HANDLER_FLAG;
387 }
388 
389 static void XMLCALL
390 dummy_end_doctype_decl_handler(void *userData) {
391   UNUSED_P(userData);
392   dummy_handler_flags |= DUMMY_END_DOCTYPE_DECL_HANDLER_FLAG;
393 }
394 
395 static void XMLCALL
396 dummy_skip_handler(void *userData, const XML_Char *entityName,
397                    int is_parameter_entity) {
398   UNUSED_P(userData);
399   UNUSED_P(entityName);
400   UNUSED_P(is_parameter_entity);
401   dummy_handler_flags |= DUMMY_SKIP_HANDLER_FLAG;
402 }
403 
404 /* Useful external entity handler */
405 typedef struct ExtOption {
406   const XML_Char *system_id;
407   const char *parse_text;
408 } ExtOption;
409 
410 static int XMLCALL
411 external_entity_optioner(XML_Parser parser, const XML_Char *context,
412                          const XML_Char *base, const XML_Char *systemId,
413                          const XML_Char *publicId) {
414   ExtOption *options = (ExtOption *)XML_GetUserData(parser);
415   XML_Parser ext_parser;
416 
417   UNUSED_P(base);
418   UNUSED_P(publicId);
419   while (options->parse_text != NULL) {
420     if (! xcstrcmp(systemId, options->system_id)) {
421       enum XML_Status rc;
422       ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
423       if (ext_parser == NULL)
424         return XML_STATUS_ERROR;
425       rc = _XML_Parse_SINGLE_BYTES(ext_parser, options->parse_text,
426                                    (int)strlen(options->parse_text), XML_TRUE);
427       XML_ParserFree(ext_parser);
428       return rc;
429     }
430     options++;
431   }
432   fail("No suitable option found");
433   return XML_STATUS_ERROR;
434 }
435 
436 /*
437  * Parameter entity evaluation support.
438  */
439 #define ENTITY_MATCH_FAIL (-1)
440 #define ENTITY_MATCH_NOT_FOUND (0)
441 #define ENTITY_MATCH_SUCCESS (1)
442 static const XML_Char *entity_name_to_match = NULL;
443 static const XML_Char *entity_value_to_match = NULL;
444 static int entity_match_flag = ENTITY_MATCH_NOT_FOUND;
445 
446 static void XMLCALL
447 param_entity_match_handler(void *userData, const XML_Char *entityName,
448                            int is_parameter_entity, const XML_Char *value,
449                            int value_length, const XML_Char *base,
450                            const XML_Char *systemId, const XML_Char *publicId,
451                            const XML_Char *notationName) {
452   UNUSED_P(userData);
453   UNUSED_P(base);
454   UNUSED_P(systemId);
455   UNUSED_P(publicId);
456   UNUSED_P(notationName);
457   if (! is_parameter_entity || entity_name_to_match == NULL
458       || entity_value_to_match == NULL) {
459     return;
460   }
461   if (! xcstrcmp(entityName, entity_name_to_match)) {
462     /* The cast here is safe because we control the horizontal and
463      * the vertical, and we therefore know our strings are never
464      * going to overflow an int.
465      */
466     if (value_length != (int)xcstrlen(entity_value_to_match)
467         || xcstrncmp(value, entity_value_to_match, value_length)) {
468       entity_match_flag = ENTITY_MATCH_FAIL;
469     } else {
470       entity_match_flag = ENTITY_MATCH_SUCCESS;
471     }
472   }
473   /* Else leave the match flag alone */
474 }
475 
476 /*
477  * Character & encoding tests.
478  */
479 
480 START_TEST(test_nul_byte) {
481   char text[] = "<doc>\0</doc>";
482 
483   /* test that a NUL byte (in US-ASCII data) is an error */
484   if (_XML_Parse_SINGLE_BYTES(g_parser, text, sizeof(text) - 1, XML_TRUE)
485       == XML_STATUS_OK)
486     fail("Parser did not report error on NUL-byte.");
487   if (XML_GetErrorCode(g_parser) != XML_ERROR_INVALID_TOKEN)
488     xml_failure(g_parser);
489 }
490 END_TEST
491 
492 START_TEST(test_u0000_char) {
493   /* test that a NUL byte (in US-ASCII data) is an error */
494   expect_failure("<doc>&#0;</doc>", XML_ERROR_BAD_CHAR_REF,
495                  "Parser did not report error on NUL-byte.");
496 }
497 END_TEST
498 
499 START_TEST(test_siphash_self) {
500   if (! sip24_valid())
501     fail("SipHash self-test failed");
502 }
503 END_TEST
504 
505 START_TEST(test_siphash_spec) {
506   /* https://131002.net/siphash/siphash.pdf (page 19, "Test values") */
507   const char message[] = "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09"
508                          "\x0a\x0b\x0c\x0d\x0e";
509   const size_t len = sizeof(message) - 1;
510   const uint64_t expected = _SIP_ULL(0xa129ca61U, 0x49be45e5U);
511   struct siphash state;
512   struct sipkey key;
513 
514   sip_tokey(&key, "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09"
515                   "\x0a\x0b\x0c\x0d\x0e\x0f");
516   sip24_init(&state, &key);
517 
518   /* Cover spread across calls */
519   sip24_update(&state, message, 4);
520   sip24_update(&state, message + 4, len - 4);
521 
522   /* Cover null length */
523   sip24_update(&state, message, 0);
524 
525   if (sip24_final(&state) != expected)
526     fail("sip24_final failed spec test\n");
527 
528   /* Cover wrapper */
529   if (siphash24(message, len, &key) != expected)
530     fail("siphash24 failed spec test\n");
531 }
532 END_TEST
533 
534 START_TEST(test_bom_utf8) {
535   /* This test is really just making sure we don't core on a UTF-8 BOM. */
536   const char *text = "\357\273\277<e/>";
537 
538   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
539       == XML_STATUS_ERROR)
540     xml_failure(g_parser);
541 }
542 END_TEST
543 
544 START_TEST(test_bom_utf16_be) {
545   char text[] = "\376\377\0<\0e\0/\0>";
546 
547   if (_XML_Parse_SINGLE_BYTES(g_parser, text, sizeof(text) - 1, XML_TRUE)
548       == XML_STATUS_ERROR)
549     xml_failure(g_parser);
550 }
551 END_TEST
552 
553 START_TEST(test_bom_utf16_le) {
554   char text[] = "\377\376<\0e\0/\0>\0";
555 
556   if (_XML_Parse_SINGLE_BYTES(g_parser, text, sizeof(text) - 1, XML_TRUE)
557       == XML_STATUS_ERROR)
558     xml_failure(g_parser);
559 }
560 END_TEST
561 
562 /* Parse whole buffer at once to exercise a different code path */
563 START_TEST(test_nobom_utf16_le) {
564   char text[] = " \0<\0e\0/\0>\0";
565 
566   if (XML_Parse(g_parser, text, sizeof(text) - 1, XML_TRUE) == XML_STATUS_ERROR)
567     xml_failure(g_parser);
568 }
569 END_TEST
570 
571 static void XMLCALL
572 accumulate_characters(void *userData, const XML_Char *s, int len) {
573   CharData_AppendXMLChars((CharData *)userData, s, len);
574 }
575 
576 static void XMLCALL
577 accumulate_attribute(void *userData, const XML_Char *name,
578                      const XML_Char **atts) {
579   CharData *storage = (CharData *)userData;
580   UNUSED_P(name);
581   /* Check there are attributes to deal with */
582   if (atts == NULL)
583     return;
584 
585   while (storage->count < 0 && atts[0] != NULL) {
586     /* "accumulate" the value of the first attribute we see */
587     CharData_AppendXMLChars(storage, atts[1], -1);
588     atts += 2;
589   }
590 }
591 
592 static void
593 _run_character_check(const char *text, const XML_Char *expected,
594                      const char *file, int line) {
595   CharData storage;
596 
597   CharData_Init(&storage);
598   XML_SetUserData(g_parser, &storage);
599   XML_SetCharacterDataHandler(g_parser, accumulate_characters);
600   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
601       == XML_STATUS_ERROR)
602     _xml_failure(g_parser, file, line);
603   CharData_CheckXMLChars(&storage, expected);
604 }
605 
606 #define run_character_check(text, expected)                                    \
607   _run_character_check(text, expected, __FILE__, __LINE__)
608 
609 static void
610 _run_attribute_check(const char *text, const XML_Char *expected,
611                      const char *file, int line) {
612   CharData storage;
613 
614   CharData_Init(&storage);
615   XML_SetUserData(g_parser, &storage);
616   XML_SetStartElementHandler(g_parser, accumulate_attribute);
617   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
618       == XML_STATUS_ERROR)
619     _xml_failure(g_parser, file, line);
620   CharData_CheckXMLChars(&storage, expected);
621 }
622 
623 #define run_attribute_check(text, expected)                                    \
624   _run_attribute_check(text, expected, __FILE__, __LINE__)
625 
626 typedef struct ExtTest {
627   const char *parse_text;
628   const XML_Char *encoding;
629   CharData *storage;
630 } ExtTest;
631 
632 static void XMLCALL
633 ext_accumulate_characters(void *userData, const XML_Char *s, int len) {
634   ExtTest *test_data = (ExtTest *)userData;
635   accumulate_characters(test_data->storage, s, len);
636 }
637 
638 static void
639 _run_ext_character_check(const char *text, ExtTest *test_data,
640                          const XML_Char *expected, const char *file, int line) {
641   CharData *const storage = (CharData *)malloc(sizeof(CharData));
642 
643   CharData_Init(storage);
644   test_data->storage = storage;
645   XML_SetUserData(g_parser, test_data);
646   XML_SetCharacterDataHandler(g_parser, ext_accumulate_characters);
647   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
648       == XML_STATUS_ERROR)
649     _xml_failure(g_parser, file, line);
650   CharData_CheckXMLChars(storage, expected);
651 
652   free(storage);
653 }
654 
655 #define run_ext_character_check(text, test_data, expected)                     \
656   _run_ext_character_check(text, test_data, expected, __FILE__, __LINE__)
657 
658 /* Regression test for SF bug #491986. */
659 START_TEST(test_danish_latin1) {
660   const char *text = "<?xml version='1.0' encoding='iso-8859-1'?>\n"
661                      "<e>J\xF8rgen \xE6\xF8\xE5\xC6\xD8\xC5</e>";
662 #ifdef XML_UNICODE
663   const XML_Char *expected
664       = XCS("J\x00f8rgen \x00e6\x00f8\x00e5\x00c6\x00d8\x00c5");
665 #else
666   const XML_Char *expected
667       = XCS("J\xC3\xB8rgen \xC3\xA6\xC3\xB8\xC3\xA5\xC3\x86\xC3\x98\xC3\x85");
668 #endif
669   run_character_check(text, expected);
670 }
671 END_TEST
672 
673 /* Regression test for SF bug #514281. */
674 START_TEST(test_french_charref_hexidecimal) {
675   const char *text = "<?xml version='1.0' encoding='iso-8859-1'?>\n"
676                      "<doc>&#xE9;&#xE8;&#xE0;&#xE7;&#xEA;&#xC8;</doc>";
677 #ifdef XML_UNICODE
678   const XML_Char *expected = XCS("\x00e9\x00e8\x00e0\x00e7\x00ea\x00c8");
679 #else
680   const XML_Char *expected
681       = XCS("\xC3\xA9\xC3\xA8\xC3\xA0\xC3\xA7\xC3\xAA\xC3\x88");
682 #endif
683   run_character_check(text, expected);
684 }
685 END_TEST
686 
687 START_TEST(test_french_charref_decimal) {
688   const char *text = "<?xml version='1.0' encoding='iso-8859-1'?>\n"
689                      "<doc>&#233;&#232;&#224;&#231;&#234;&#200;</doc>";
690 #ifdef XML_UNICODE
691   const XML_Char *expected = XCS("\x00e9\x00e8\x00e0\x00e7\x00ea\x00c8");
692 #else
693   const XML_Char *expected
694       = XCS("\xC3\xA9\xC3\xA8\xC3\xA0\xC3\xA7\xC3\xAA\xC3\x88");
695 #endif
696   run_character_check(text, expected);
697 }
698 END_TEST
699 
700 START_TEST(test_french_latin1) {
701   const char *text = "<?xml version='1.0' encoding='iso-8859-1'?>\n"
702                      "<doc>\xE9\xE8\xE0\xE7\xEa\xC8</doc>";
703 #ifdef XML_UNICODE
704   const XML_Char *expected = XCS("\x00e9\x00e8\x00e0\x00e7\x00ea\x00c8");
705 #else
706   const XML_Char *expected
707       = XCS("\xC3\xA9\xC3\xA8\xC3\xA0\xC3\xA7\xC3\xAA\xC3\x88");
708 #endif
709   run_character_check(text, expected);
710 }
711 END_TEST
712 
713 START_TEST(test_french_utf8) {
714   const char *text = "<?xml version='1.0' encoding='utf-8'?>\n"
715                      "<doc>\xC3\xA9</doc>";
716 #ifdef XML_UNICODE
717   const XML_Char *expected = XCS("\x00e9");
718 #else
719   const XML_Char *expected = XCS("\xC3\xA9");
720 #endif
721   run_character_check(text, expected);
722 }
723 END_TEST
724 
725 /* Regression test for SF bug #600479.
726    XXX There should be a test that exercises all legal XML Unicode
727    characters as PCDATA and attribute value content, and XML Name
728    characters as part of element and attribute names.
729 */
730 START_TEST(test_utf8_false_rejection) {
731   const char *text = "<doc>\xEF\xBA\xBF</doc>";
732 #ifdef XML_UNICODE
733   const XML_Char *expected = XCS("\xfebf");
734 #else
735   const XML_Char *expected = XCS("\xEF\xBA\xBF");
736 #endif
737   run_character_check(text, expected);
738 }
739 END_TEST
740 
741 /* Regression test for SF bug #477667.
742    This test assures that any 8-bit character followed by a 7-bit
743    character will not be mistakenly interpreted as a valid UTF-8
744    sequence.
745 */
746 START_TEST(test_illegal_utf8) {
747   char text[100];
748   int i;
749 
750   for (i = 128; i <= 255; ++i) {
751     sprintf(text, "<e>%ccd</e>", i);
752     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
753         == XML_STATUS_OK) {
754       sprintf(text, "expected token error for '%c' (ordinal %d) in UTF-8 text",
755               i, i);
756       fail(text);
757     } else if (XML_GetErrorCode(g_parser) != XML_ERROR_INVALID_TOKEN)
758       xml_failure(g_parser);
759     /* Reset the parser since we use the same parser repeatedly. */
760     XML_ParserReset(g_parser, NULL);
761   }
762 }
763 END_TEST
764 
765 /* Examples, not masks: */
766 #define UTF8_LEAD_1 "\x7f" /* 0b01111111 */
767 #define UTF8_LEAD_2 "\xdf" /* 0b11011111 */
768 #define UTF8_LEAD_3 "\xef" /* 0b11101111 */
769 #define UTF8_LEAD_4 "\xf7" /* 0b11110111 */
770 #define UTF8_FOLLOW "\xbf" /* 0b10111111 */
771 
772 START_TEST(test_utf8_auto_align) {
773   struct TestCase {
774     ptrdiff_t expectedMovementInChars;
775     const char *input;
776   };
777 
778   struct TestCase cases[] = {
779       {00, ""},
780 
781       {00, UTF8_LEAD_1},
782 
783       {-1, UTF8_LEAD_2},
784       {00, UTF8_LEAD_2 UTF8_FOLLOW},
785 
786       {-1, UTF8_LEAD_3},
787       {-2, UTF8_LEAD_3 UTF8_FOLLOW},
788       {00, UTF8_LEAD_3 UTF8_FOLLOW UTF8_FOLLOW},
789 
790       {-1, UTF8_LEAD_4},
791       {-2, UTF8_LEAD_4 UTF8_FOLLOW},
792       {-3, UTF8_LEAD_4 UTF8_FOLLOW UTF8_FOLLOW},
793       {00, UTF8_LEAD_4 UTF8_FOLLOW UTF8_FOLLOW UTF8_FOLLOW},
794   };
795 
796   size_t i = 0;
797   bool success = true;
798   for (; i < sizeof(cases) / sizeof(*cases); i++) {
799     const char *fromLim = cases[i].input + strlen(cases[i].input);
800     const char *const fromLimInitially = fromLim;
801     ptrdiff_t actualMovementInChars;
802 
803     _INTERNAL_trim_to_complete_utf8_characters(cases[i].input, &fromLim);
804 
805     actualMovementInChars = (fromLim - fromLimInitially);
806     if (actualMovementInChars != cases[i].expectedMovementInChars) {
807       size_t j = 0;
808       success = false;
809       printf("[-] UTF-8 case %2u: Expected movement by %2d chars"
810              ", actually moved by %2d chars: \"",
811              (unsigned)(i + 1), (int)cases[i].expectedMovementInChars,
812              (int)actualMovementInChars);
813       for (; j < strlen(cases[i].input); j++) {
814         printf("\\x%02x", (unsigned char)cases[i].input[j]);
815       }
816       printf("\"\n");
817     }
818   }
819 
820   if (! success) {
821     fail("UTF-8 auto-alignment is not bullet-proof\n");
822   }
823 }
824 END_TEST
825 
826 START_TEST(test_utf16) {
827   /* <?xml version="1.0" encoding="UTF-16"?>
828    *  <doc a='123'>some {A} text</doc>
829    *
830    * where {A} is U+FF21, FULLWIDTH LATIN CAPITAL LETTER A
831    */
832   char text[]
833       = "\000<\000?\000x\000m\000\154\000 \000v\000e\000r\000s\000i\000o"
834         "\000n\000=\000'\0001\000.\000\060\000'\000 \000e\000n\000c\000o"
835         "\000d\000i\000n\000g\000=\000'\000U\000T\000F\000-\0001\000\066"
836         "\000'\000?\000>\000\n"
837         "\000<\000d\000o\000c\000 \000a\000=\000'\0001\0002\0003\000'\000>"
838         "\000s\000o\000m\000e\000 \xff\x21\000 \000t\000e\000x\000t\000"
839         "<\000/\000d\000o\000c\000>";
840 #ifdef XML_UNICODE
841   const XML_Char *expected = XCS("some \xff21 text");
842 #else
843   const XML_Char *expected = XCS("some \357\274\241 text");
844 #endif
845   CharData storage;
846 
847   CharData_Init(&storage);
848   XML_SetUserData(g_parser, &storage);
849   XML_SetCharacterDataHandler(g_parser, accumulate_characters);
850   if (_XML_Parse_SINGLE_BYTES(g_parser, text, sizeof(text) - 1, XML_TRUE)
851       == XML_STATUS_ERROR)
852     xml_failure(g_parser);
853   CharData_CheckXMLChars(&storage, expected);
854 }
855 END_TEST
856 
857 START_TEST(test_utf16_le_epilog_newline) {
858   unsigned int first_chunk_bytes = 17;
859   char text[] = "\xFF\xFE"                  /* BOM */
860                 "<\000e\000/\000>\000"      /* document element */
861                 "\r\000\n\000\r\000\n\000"; /* epilog */
862 
863   if (first_chunk_bytes >= sizeof(text) - 1)
864     fail("bad value of first_chunk_bytes");
865   if (_XML_Parse_SINGLE_BYTES(g_parser, text, first_chunk_bytes, XML_FALSE)
866       == XML_STATUS_ERROR)
867     xml_failure(g_parser);
868   else {
869     enum XML_Status rc;
870     rc = _XML_Parse_SINGLE_BYTES(g_parser, text + first_chunk_bytes,
871                                  sizeof(text) - first_chunk_bytes - 1,
872                                  XML_TRUE);
873     if (rc == XML_STATUS_ERROR)
874       xml_failure(g_parser);
875   }
876 }
877 END_TEST
878 
879 /* Test that an outright lie in the encoding is faulted */
880 START_TEST(test_not_utf16) {
881   const char *text = "<?xml version='1.0' encoding='utf-16'?>"
882                      "<doc>Hi</doc>";
883 
884   /* Use a handler to provoke the appropriate code paths */
885   XML_SetXmlDeclHandler(g_parser, dummy_xdecl_handler);
886   expect_failure(text, XML_ERROR_INCORRECT_ENCODING,
887                  "UTF-16 declared in UTF-8 not faulted");
888 }
889 END_TEST
890 
891 /* Test that an unknown encoding is rejected */
892 START_TEST(test_bad_encoding) {
893   const char *text = "<doc>Hi</doc>";
894 
895   if (! XML_SetEncoding(g_parser, XCS("unknown-encoding")))
896     fail("XML_SetEncoding failed");
897   expect_failure(text, XML_ERROR_UNKNOWN_ENCODING,
898                  "Unknown encoding not faulted");
899 }
900 END_TEST
901 
902 /* Regression test for SF bug #481609, #774028. */
903 START_TEST(test_latin1_umlauts) {
904   const char *text
905       = "<?xml version='1.0' encoding='iso-8859-1'?>\n"
906         "<e a='\xE4 \xF6 \xFC &#228; &#246; &#252; &#x00E4; &#x0F6; &#xFC; >'\n"
907         "  >\xE4 \xF6 \xFC &#228; &#246; &#252; &#x00E4; &#x0F6; &#xFC; ></e>";
908 #ifdef XML_UNICODE
909   /* Expected results in UTF-16 */
910   const XML_Char *expected = XCS("\x00e4 \x00f6 \x00fc ")
911       XCS("\x00e4 \x00f6 \x00fc ") XCS("\x00e4 \x00f6 \x00fc >");
912 #else
913   /* Expected results in UTF-8 */
914   const XML_Char *expected = XCS("\xC3\xA4 \xC3\xB6 \xC3\xBC ")
915       XCS("\xC3\xA4 \xC3\xB6 \xC3\xBC ") XCS("\xC3\xA4 \xC3\xB6 \xC3\xBC >");
916 #endif
917 
918   run_character_check(text, expected);
919   XML_ParserReset(g_parser, NULL);
920   run_attribute_check(text, expected);
921   /* Repeat with a default handler */
922   XML_ParserReset(g_parser, NULL);
923   XML_SetDefaultHandler(g_parser, dummy_default_handler);
924   run_character_check(text, expected);
925   XML_ParserReset(g_parser, NULL);
926   XML_SetDefaultHandler(g_parser, dummy_default_handler);
927   run_attribute_check(text, expected);
928 }
929 END_TEST
930 
931 /* Test that an element name with a 4-byte UTF-8 character is rejected */
932 START_TEST(test_long_utf8_character) {
933   const char *text
934       = "<?xml version='1.0' encoding='utf-8'?>\n"
935         /* 0xf0 0x90 0x80 0x80 = U+10000, the first Linear B character */
936         "<do\xf0\x90\x80\x80/>";
937   expect_failure(text, XML_ERROR_INVALID_TOKEN,
938                  "4-byte UTF-8 character in element name not faulted");
939 }
940 END_TEST
941 
942 /* Test that a long latin-1 attribute (too long to convert in one go)
943  * is correctly converted
944  */
945 START_TEST(test_long_latin1_attribute) {
946   const char *text
947       = "<?xml version='1.0' encoding='iso-8859-1'?>\n"
948         "<doc att='"
949         /* 64 characters per line */
950         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
951         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
952         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
953         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
954         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
955         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
956         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
957         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
958         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
959         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
960         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
961         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
962         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
963         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
964         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
965         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
966         /* Last character splits across a buffer boundary */
967         "\xe4'>\n</doc>";
968 
969   const XML_Char *expected =
970       /* 64 characters per line */
971       /* clang-format off */
972         XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
973         XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
974         XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
975         XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
976         XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
977         XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
978         XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
979         XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
980         XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
981         XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
982         XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
983         XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
984         XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
985         XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
986         XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
987         XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO")
988   /* clang-format on */
989 #ifdef XML_UNICODE
990                                                   XCS("\x00e4");
991 #else
992                                                   XCS("\xc3\xa4");
993 #endif
994 
995   run_attribute_check(text, expected);
996 }
997 END_TEST
998 
999 /* Test that a long ASCII attribute (too long to convert in one go)
1000  * is correctly converted
1001  */
1002 START_TEST(test_long_ascii_attribute) {
1003   const char *text
1004       = "<?xml version='1.0' encoding='us-ascii'?>\n"
1005         "<doc att='"
1006         /* 64 characters per line */
1007         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1008         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1009         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1010         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1011         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1012         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1013         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1014         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1015         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1016         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1017         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1018         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1019         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1020         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1021         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1022         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1023         "01234'>\n</doc>";
1024   const XML_Char *expected =
1025       /* 64 characters per line */
1026       /* clang-format off */
1027         XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
1028         XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
1029         XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
1030         XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
1031         XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
1032         XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
1033         XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
1034         XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
1035         XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
1036         XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
1037         XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
1038         XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
1039         XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
1040         XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
1041         XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
1042         XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
1043         XCS("01234");
1044   /* clang-format on */
1045 
1046   run_attribute_check(text, expected);
1047 }
1048 END_TEST
1049 
1050 /* Regression test #1 for SF bug #653180. */
1051 START_TEST(test_line_number_after_parse) {
1052   const char *text = "<tag>\n"
1053                      "\n"
1054                      "\n</tag>";
1055   XML_Size lineno;
1056 
1057   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_FALSE)
1058       == XML_STATUS_ERROR)
1059     xml_failure(g_parser);
1060   lineno = XML_GetCurrentLineNumber(g_parser);
1061   if (lineno != 4) {
1062     char buffer[100];
1063     sprintf(buffer, "expected 4 lines, saw %" XML_FMT_INT_MOD "u", lineno);
1064     fail(buffer);
1065   }
1066 }
1067 END_TEST
1068 
1069 /* Regression test #2 for SF bug #653180. */
1070 START_TEST(test_column_number_after_parse) {
1071   const char *text = "<tag></tag>";
1072   XML_Size colno;
1073 
1074   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_FALSE)
1075       == XML_STATUS_ERROR)
1076     xml_failure(g_parser);
1077   colno = XML_GetCurrentColumnNumber(g_parser);
1078   if (colno != 11) {
1079     char buffer[100];
1080     sprintf(buffer, "expected 11 columns, saw %" XML_FMT_INT_MOD "u", colno);
1081     fail(buffer);
1082   }
1083 }
1084 END_TEST
1085 
1086 #define STRUCT_START_TAG 0
1087 #define STRUCT_END_TAG 1
1088 static void XMLCALL
1089 start_element_event_handler2(void *userData, const XML_Char *name,
1090                              const XML_Char **attr) {
1091   StructData *storage = (StructData *)userData;
1092   UNUSED_P(attr);
1093   StructData_AddItem(storage, name, XML_GetCurrentColumnNumber(g_parser),
1094                      XML_GetCurrentLineNumber(g_parser), STRUCT_START_TAG);
1095 }
1096 
1097 static void XMLCALL
1098 end_element_event_handler2(void *userData, const XML_Char *name) {
1099   StructData *storage = (StructData *)userData;
1100   StructData_AddItem(storage, name, XML_GetCurrentColumnNumber(g_parser),
1101                      XML_GetCurrentLineNumber(g_parser), STRUCT_END_TAG);
1102 }
1103 
1104 /* Regression test #3 for SF bug #653180. */
1105 START_TEST(test_line_and_column_numbers_inside_handlers) {
1106   const char *text = "<a>\n"      /* Unix end-of-line */
1107                      "  <b>\r\n"  /* Windows end-of-line */
1108                      "    <c/>\r" /* Mac OS end-of-line */
1109                      "  </b>\n"
1110                      "  <d>\n"
1111                      "    <f/>\n"
1112                      "  </d>\n"
1113                      "</a>";
1114   const StructDataEntry expected[]
1115       = {{XCS("a"), 0, 1, STRUCT_START_TAG}, {XCS("b"), 2, 2, STRUCT_START_TAG},
1116          {XCS("c"), 4, 3, STRUCT_START_TAG}, {XCS("c"), 8, 3, STRUCT_END_TAG},
1117          {XCS("b"), 2, 4, STRUCT_END_TAG},   {XCS("d"), 2, 5, STRUCT_START_TAG},
1118          {XCS("f"), 4, 6, STRUCT_START_TAG}, {XCS("f"), 8, 6, STRUCT_END_TAG},
1119          {XCS("d"), 2, 7, STRUCT_END_TAG},   {XCS("a"), 0, 8, STRUCT_END_TAG}};
1120   const int expected_count = sizeof(expected) / sizeof(StructDataEntry);
1121   StructData storage;
1122 
1123   StructData_Init(&storage);
1124   XML_SetUserData(g_parser, &storage);
1125   XML_SetStartElementHandler(g_parser, start_element_event_handler2);
1126   XML_SetEndElementHandler(g_parser, end_element_event_handler2);
1127   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
1128       == XML_STATUS_ERROR)
1129     xml_failure(g_parser);
1130 
1131   StructData_CheckItems(&storage, expected, expected_count);
1132   StructData_Dispose(&storage);
1133 }
1134 END_TEST
1135 
1136 /* Regression test #4 for SF bug #653180. */
1137 START_TEST(test_line_number_after_error) {
1138   const char *text = "<a>\n"
1139                      "  <b>\n"
1140                      "  </a>"; /* missing </b> */
1141   XML_Size lineno;
1142   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_FALSE)
1143       != XML_STATUS_ERROR)
1144     fail("Expected a parse error");
1145 
1146   lineno = XML_GetCurrentLineNumber(g_parser);
1147   if (lineno != 3) {
1148     char buffer[100];
1149     sprintf(buffer, "expected 3 lines, saw %" XML_FMT_INT_MOD "u", lineno);
1150     fail(buffer);
1151   }
1152 }
1153 END_TEST
1154 
1155 /* Regression test #5 for SF bug #653180. */
1156 START_TEST(test_column_number_after_error) {
1157   const char *text = "<a>\n"
1158                      "  <b>\n"
1159                      "  </a>"; /* missing </b> */
1160   XML_Size colno;
1161   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_FALSE)
1162       != XML_STATUS_ERROR)
1163     fail("Expected a parse error");
1164 
1165   colno = XML_GetCurrentColumnNumber(g_parser);
1166   if (colno != 4) {
1167     char buffer[100];
1168     sprintf(buffer, "expected 4 columns, saw %" XML_FMT_INT_MOD "u", colno);
1169     fail(buffer);
1170   }
1171 }
1172 END_TEST
1173 
1174 /* Regression test for SF bug #478332. */
1175 START_TEST(test_really_long_lines) {
1176   /* This parses an input line longer than INIT_DATA_BUF_SIZE
1177      characters long (defined to be 1024 in xmlparse.c).  We take a
1178      really cheesy approach to building the input buffer, because
1179      this avoids writing bugs in buffer-filling code.
1180   */
1181   const char *text
1182       = "<e>"
1183         /* 64 chars */
1184         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1185         /* until we have at least 1024 characters on the line: */
1186         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1187         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1188         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1189         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1190         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1191         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1192         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1193         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1194         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1195         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1196         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1197         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1198         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1199         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1200         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1201         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1202         "</e>";
1203   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
1204       == XML_STATUS_ERROR)
1205     xml_failure(g_parser);
1206 }
1207 END_TEST
1208 
1209 /* Test cdata processing across a buffer boundary */
1210 START_TEST(test_really_long_encoded_lines) {
1211   /* As above, except that we want to provoke an output buffer
1212    * overflow with a non-trivial encoding.  For this we need to pass
1213    * the whole cdata in one go, not byte-by-byte.
1214    */
1215   void *buffer;
1216   const char *text
1217       = "<?xml version='1.0' encoding='iso-8859-1'?>"
1218         "<e>"
1219         /* 64 chars */
1220         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1221         /* until we have at least 1024 characters on the line: */
1222         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1223         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1224         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1225         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1226         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1227         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1228         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1229         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1230         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1231         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1232         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1233         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1234         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1235         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1236         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1237         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1238         "</e>";
1239   int parse_len = (int)strlen(text);
1240 
1241   /* Need a cdata handler to provoke the code path we want to test */
1242   XML_SetCharacterDataHandler(g_parser, dummy_cdata_handler);
1243   buffer = XML_GetBuffer(g_parser, parse_len);
1244   if (buffer == NULL)
1245     fail("Could not allocate parse buffer");
1246   assert(buffer != NULL);
1247   memcpy(buffer, text, parse_len);
1248   if (XML_ParseBuffer(g_parser, parse_len, XML_TRUE) == XML_STATUS_ERROR)
1249     xml_failure(g_parser);
1250 }
1251 END_TEST
1252 
1253 /*
1254  * Element event tests.
1255  */
1256 
1257 static void XMLCALL
1258 start_element_event_handler(void *userData, const XML_Char *name,
1259                             const XML_Char **atts) {
1260   UNUSED_P(atts);
1261   CharData_AppendXMLChars((CharData *)userData, name, -1);
1262 }
1263 
1264 static void XMLCALL
1265 end_element_event_handler(void *userData, const XML_Char *name) {
1266   CharData *storage = (CharData *)userData;
1267   CharData_AppendXMLChars(storage, XCS("/"), 1);
1268   CharData_AppendXMLChars(storage, name, -1);
1269 }
1270 
1271 START_TEST(test_end_element_events) {
1272   const char *text = "<a><b><c/></b><d><f/></d></a>";
1273   const XML_Char *expected = XCS("/c/b/f/d/a");
1274   CharData storage;
1275 
1276   CharData_Init(&storage);
1277   XML_SetUserData(g_parser, &storage);
1278   XML_SetEndElementHandler(g_parser, end_element_event_handler);
1279   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
1280       == XML_STATUS_ERROR)
1281     xml_failure(g_parser);
1282   CharData_CheckXMLChars(&storage, expected);
1283 }
1284 END_TEST
1285 
1286 /*
1287  * Attribute tests.
1288  */
1289 
1290 /* Helpers used by the following test; this checks any "attr" and "refs"
1291    attributes to make sure whitespace has been normalized.
1292 
1293    Return true if whitespace has been normalized in a string, using
1294    the rules for attribute value normalization.  The 'is_cdata' flag
1295    is needed since CDATA attributes don't need to have multiple
1296    whitespace characters collapsed to a single space, while other
1297    attribute data types do.  (Section 3.3.3 of the recommendation.)
1298 */
1299 static int
1300 is_whitespace_normalized(const XML_Char *s, int is_cdata) {
1301   int blanks = 0;
1302   int at_start = 1;
1303   while (*s) {
1304     if (*s == XCS(' '))
1305       ++blanks;
1306     else if (*s == XCS('\t') || *s == XCS('\n') || *s == XCS('\r'))
1307       return 0;
1308     else {
1309       if (at_start) {
1310         at_start = 0;
1311         if (blanks && ! is_cdata)
1312           /* illegal leading blanks */
1313           return 0;
1314       } else if (blanks > 1 && ! is_cdata)
1315         return 0;
1316       blanks = 0;
1317     }
1318     ++s;
1319   }
1320   if (blanks && ! is_cdata)
1321     return 0;
1322   return 1;
1323 }
1324 
1325 /* Check the attribute whitespace checker: */
1326 static void
1327 testhelper_is_whitespace_normalized(void) {
1328   assert(is_whitespace_normalized(XCS("abc"), 0));
1329   assert(is_whitespace_normalized(XCS("abc"), 1));
1330   assert(is_whitespace_normalized(XCS("abc def ghi"), 0));
1331   assert(is_whitespace_normalized(XCS("abc def ghi"), 1));
1332   assert(! is_whitespace_normalized(XCS(" abc def ghi"), 0));
1333   assert(is_whitespace_normalized(XCS(" abc def ghi"), 1));
1334   assert(! is_whitespace_normalized(XCS("abc  def ghi"), 0));
1335   assert(is_whitespace_normalized(XCS("abc  def ghi"), 1));
1336   assert(! is_whitespace_normalized(XCS("abc def ghi "), 0));
1337   assert(is_whitespace_normalized(XCS("abc def ghi "), 1));
1338   assert(! is_whitespace_normalized(XCS(" "), 0));
1339   assert(is_whitespace_normalized(XCS(" "), 1));
1340   assert(! is_whitespace_normalized(XCS("\t"), 0));
1341   assert(! is_whitespace_normalized(XCS("\t"), 1));
1342   assert(! is_whitespace_normalized(XCS("\n"), 0));
1343   assert(! is_whitespace_normalized(XCS("\n"), 1));
1344   assert(! is_whitespace_normalized(XCS("\r"), 0));
1345   assert(! is_whitespace_normalized(XCS("\r"), 1));
1346   assert(! is_whitespace_normalized(XCS("abc\t def"), 1));
1347 }
1348 
1349 static void XMLCALL
1350 check_attr_contains_normalized_whitespace(void *userData, const XML_Char *name,
1351                                           const XML_Char **atts) {
1352   int i;
1353   UNUSED_P(userData);
1354   UNUSED_P(name);
1355   for (i = 0; atts[i] != NULL; i += 2) {
1356     const XML_Char *attrname = atts[i];
1357     const XML_Char *value = atts[i + 1];
1358     if (xcstrcmp(XCS("attr"), attrname) == 0
1359         || xcstrcmp(XCS("ents"), attrname) == 0
1360         || xcstrcmp(XCS("refs"), attrname) == 0) {
1361       if (! is_whitespace_normalized(value, 0)) {
1362         char buffer[256];
1363         sprintf(buffer,
1364                 "attribute value not normalized: %" XML_FMT_STR
1365                 "='%" XML_FMT_STR "'",
1366                 attrname, value);
1367         fail(buffer);
1368       }
1369     }
1370   }
1371 }
1372 
1373 START_TEST(test_attr_whitespace_normalization) {
1374   const char *text
1375       = "<!DOCTYPE doc [\n"
1376         "  <!ATTLIST doc\n"
1377         "            attr NMTOKENS #REQUIRED\n"
1378         "            ents ENTITIES #REQUIRED\n"
1379         "            refs IDREFS   #REQUIRED>\n"
1380         "]>\n"
1381         "<doc attr='    a  b c\t\td\te\t' refs=' id-1   \t  id-2\t\t'  \n"
1382         "     ents=' ent-1   \t\r\n"
1383         "            ent-2  ' >\n"
1384         "  <e id='id-1'/>\n"
1385         "  <e id='id-2'/>\n"
1386         "</doc>";
1387 
1388   XML_SetStartElementHandler(g_parser,
1389                              check_attr_contains_normalized_whitespace);
1390   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
1391       == XML_STATUS_ERROR)
1392     xml_failure(g_parser);
1393 }
1394 END_TEST
1395 
1396 /*
1397  * XML declaration tests.
1398  */
1399 
1400 START_TEST(test_xmldecl_misplaced) {
1401   expect_failure("\n"
1402                  "<?xml version='1.0'?>\n"
1403                  "<a/>",
1404                  XML_ERROR_MISPLACED_XML_PI,
1405                  "failed to report misplaced XML declaration");
1406 }
1407 END_TEST
1408 
1409 START_TEST(test_xmldecl_invalid) {
1410   expect_failure("<?xml version='1.0' \xc3\xa7?>\n<doc/>", XML_ERROR_XML_DECL,
1411                  "Failed to report invalid XML declaration");
1412 }
1413 END_TEST
1414 
1415 START_TEST(test_xmldecl_missing_attr) {
1416   expect_failure("<?xml ='1.0'?>\n<doc/>\n", XML_ERROR_XML_DECL,
1417                  "Failed to report missing XML declaration attribute");
1418 }
1419 END_TEST
1420 
1421 START_TEST(test_xmldecl_missing_value) {
1422   expect_failure("<?xml version='1.0' encoding='us-ascii' standalone?>\n"
1423                  "<doc/>",
1424                  XML_ERROR_XML_DECL,
1425                  "Failed to report missing attribute value");
1426 }
1427 END_TEST
1428 
1429 /* Regression test for SF bug #584832. */
1430 static int XMLCALL
1431 UnknownEncodingHandler(void *data, const XML_Char *encoding,
1432                        XML_Encoding *info) {
1433   UNUSED_P(data);
1434   if (xcstrcmp(encoding, XCS("unsupported-encoding")) == 0) {
1435     int i;
1436     for (i = 0; i < 256; ++i)
1437       info->map[i] = i;
1438     info->data = NULL;
1439     info->convert = NULL;
1440     info->release = NULL;
1441     return XML_STATUS_OK;
1442   }
1443   return XML_STATUS_ERROR;
1444 }
1445 
1446 START_TEST(test_unknown_encoding_internal_entity) {
1447   const char *text = "<?xml version='1.0' encoding='unsupported-encoding'?>\n"
1448                      "<!DOCTYPE test [<!ENTITY foo 'bar'>]>\n"
1449                      "<test a='&foo;'/>";
1450 
1451   XML_SetUnknownEncodingHandler(g_parser, UnknownEncodingHandler, NULL);
1452   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
1453       == XML_STATUS_ERROR)
1454     xml_failure(g_parser);
1455 }
1456 END_TEST
1457 
1458 /* Test unrecognised encoding handler */
1459 static void
1460 dummy_release(void *data) {
1461   UNUSED_P(data);
1462 }
1463 
1464 static int XMLCALL
1465 UnrecognisedEncodingHandler(void *data, const XML_Char *encoding,
1466                             XML_Encoding *info) {
1467   UNUSED_P(data);
1468   UNUSED_P(encoding);
1469   info->data = NULL;
1470   info->convert = NULL;
1471   info->release = dummy_release;
1472   return XML_STATUS_ERROR;
1473 }
1474 
1475 START_TEST(test_unrecognised_encoding_internal_entity) {
1476   const char *text = "<?xml version='1.0' encoding='unsupported-encoding'?>\n"
1477                      "<!DOCTYPE test [<!ENTITY foo 'bar'>]>\n"
1478                      "<test a='&foo;'/>";
1479 
1480   XML_SetUnknownEncodingHandler(g_parser, UnrecognisedEncodingHandler, NULL);
1481   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
1482       != XML_STATUS_ERROR)
1483     fail("Unrecognised encoding not rejected");
1484 }
1485 END_TEST
1486 
1487 /* Regression test for SF bug #620106. */
1488 static int XMLCALL
1489 external_entity_loader(XML_Parser parser, const XML_Char *context,
1490                        const XML_Char *base, const XML_Char *systemId,
1491                        const XML_Char *publicId) {
1492   ExtTest *test_data = (ExtTest *)XML_GetUserData(parser);
1493   XML_Parser extparser;
1494 
1495   UNUSED_P(base);
1496   UNUSED_P(systemId);
1497   UNUSED_P(publicId);
1498   extparser = XML_ExternalEntityParserCreate(parser, context, NULL);
1499   if (extparser == NULL)
1500     fail("Could not create external entity parser.");
1501   if (test_data->encoding != NULL) {
1502     if (! XML_SetEncoding(extparser, test_data->encoding))
1503       fail("XML_SetEncoding() ignored for external entity");
1504   }
1505   if (_XML_Parse_SINGLE_BYTES(extparser, test_data->parse_text,
1506                               (int)strlen(test_data->parse_text), XML_TRUE)
1507       == XML_STATUS_ERROR) {
1508     xml_failure(extparser);
1509     return XML_STATUS_ERROR;
1510   }
1511   XML_ParserFree(extparser);
1512   return XML_STATUS_OK;
1513 }
1514 
1515 START_TEST(test_ext_entity_set_encoding) {
1516   const char *text = "<!DOCTYPE doc [\n"
1517                      "  <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n"
1518                      "]>\n"
1519                      "<doc>&en;</doc>";
1520   ExtTest test_data
1521       = {/* This text says it's an unsupported encoding, but it's really
1522             UTF-8, which we tell Expat using XML_SetEncoding().
1523          */
1524          "<?xml encoding='iso-8859-3'?>\xC3\xA9", XCS("utf-8"), NULL};
1525 #ifdef XML_UNICODE
1526   const XML_Char *expected = XCS("\x00e9");
1527 #else
1528   const XML_Char *expected = XCS("\xc3\xa9");
1529 #endif
1530 
1531   XML_SetExternalEntityRefHandler(g_parser, external_entity_loader);
1532   run_ext_character_check(text, &test_data, expected);
1533 }
1534 END_TEST
1535 
1536 /* Test external entities with no handler */
1537 START_TEST(test_ext_entity_no_handler) {
1538   const char *text = "<!DOCTYPE doc [\n"
1539                      "  <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n"
1540                      "]>\n"
1541                      "<doc>&en;</doc>";
1542 
1543   XML_SetDefaultHandler(g_parser, dummy_default_handler);
1544   run_character_check(text, XCS(""));
1545 }
1546 END_TEST
1547 
1548 /* Test UTF-8 BOM is accepted */
1549 START_TEST(test_ext_entity_set_bom) {
1550   const char *text = "<!DOCTYPE doc [\n"
1551                      "  <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n"
1552                      "]>\n"
1553                      "<doc>&en;</doc>";
1554   ExtTest test_data = {"\xEF\xBB\xBF" /* BOM */
1555                        "<?xml encoding='iso-8859-3'?>"
1556                        "\xC3\xA9",
1557                        XCS("utf-8"), NULL};
1558 #ifdef XML_UNICODE
1559   const XML_Char *expected = XCS("\x00e9");
1560 #else
1561   const XML_Char *expected = XCS("\xc3\xa9");
1562 #endif
1563 
1564   XML_SetExternalEntityRefHandler(g_parser, external_entity_loader);
1565   run_ext_character_check(text, &test_data, expected);
1566 }
1567 END_TEST
1568 
1569 /* Test that bad encodings are faulted */
1570 typedef struct ext_faults {
1571   const char *parse_text;
1572   const char *fail_text;
1573   const XML_Char *encoding;
1574   enum XML_Error error;
1575 } ExtFaults;
1576 
1577 static int XMLCALL
1578 external_entity_faulter(XML_Parser parser, const XML_Char *context,
1579                         const XML_Char *base, const XML_Char *systemId,
1580                         const XML_Char *publicId) {
1581   XML_Parser ext_parser;
1582   ExtFaults *fault = (ExtFaults *)XML_GetUserData(parser);
1583 
1584   UNUSED_P(base);
1585   UNUSED_P(systemId);
1586   UNUSED_P(publicId);
1587   ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
1588   if (ext_parser == NULL)
1589     fail("Could not create external entity parser");
1590   if (fault->encoding != NULL) {
1591     if (! XML_SetEncoding(ext_parser, fault->encoding))
1592       fail("XML_SetEncoding failed");
1593   }
1594   if (_XML_Parse_SINGLE_BYTES(ext_parser, fault->parse_text,
1595                               (int)strlen(fault->parse_text), XML_TRUE)
1596       != XML_STATUS_ERROR)
1597     fail(fault->fail_text);
1598   if (XML_GetErrorCode(ext_parser) != fault->error)
1599     xml_failure(ext_parser);
1600 
1601   XML_ParserFree(ext_parser);
1602   return XML_STATUS_ERROR;
1603 }
1604 
1605 START_TEST(test_ext_entity_bad_encoding) {
1606   const char *text = "<!DOCTYPE doc [\n"
1607                      "  <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n"
1608                      "]>\n"
1609                      "<doc>&en;</doc>";
1610   ExtFaults fault
1611       = {"<?xml encoding='iso-8859-3'?>u", "Unsupported encoding not faulted",
1612          XCS("unknown"), XML_ERROR_UNKNOWN_ENCODING};
1613 
1614   XML_SetExternalEntityRefHandler(g_parser, external_entity_faulter);
1615   XML_SetUserData(g_parser, &fault);
1616   expect_failure(text, XML_ERROR_EXTERNAL_ENTITY_HANDLING,
1617                  "Bad encoding should not have been accepted");
1618 }
1619 END_TEST
1620 
1621 /* Try handing an invalid encoding to an external entity parser */
1622 START_TEST(test_ext_entity_bad_encoding_2) {
1623   const char *text = "<?xml version='1.0' encoding='us-ascii'?>\n"
1624                      "<!DOCTYPE doc SYSTEM 'foo'>\n"
1625                      "<doc>&entity;</doc>";
1626   ExtFaults fault
1627       = {"<!ELEMENT doc (#PCDATA)*>", "Unknown encoding not faulted",
1628          XCS("unknown-encoding"), XML_ERROR_UNKNOWN_ENCODING};
1629 
1630   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
1631   XML_SetExternalEntityRefHandler(g_parser, external_entity_faulter);
1632   XML_SetUserData(g_parser, &fault);
1633   expect_failure(text, XML_ERROR_EXTERNAL_ENTITY_HANDLING,
1634                  "Bad encoding not faulted in external entity handler");
1635 }
1636 END_TEST
1637 
1638 /* Test that no error is reported for unknown entities if we don't
1639    read an external subset.  This was fixed in Expat 1.95.5.
1640 */
1641 START_TEST(test_wfc_undeclared_entity_unread_external_subset) {
1642   const char *text = "<!DOCTYPE doc SYSTEM 'foo'>\n"
1643                      "<doc>&entity;</doc>";
1644 
1645   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
1646       == XML_STATUS_ERROR)
1647     xml_failure(g_parser);
1648 }
1649 END_TEST
1650 
1651 /* Test that an error is reported for unknown entities if we don't
1652    have an external subset.
1653 */
1654 START_TEST(test_wfc_undeclared_entity_no_external_subset) {
1655   expect_failure("<doc>&entity;</doc>", XML_ERROR_UNDEFINED_ENTITY,
1656                  "Parser did not report undefined entity w/out a DTD.");
1657 }
1658 END_TEST
1659 
1660 /* Test that an error is reported for unknown entities if we don't
1661    read an external subset, but have been declared standalone.
1662 */
1663 START_TEST(test_wfc_undeclared_entity_standalone) {
1664   const char *text
1665       = "<?xml version='1.0' encoding='us-ascii' standalone='yes'?>\n"
1666         "<!DOCTYPE doc SYSTEM 'foo'>\n"
1667         "<doc>&entity;</doc>";
1668 
1669   expect_failure(text, XML_ERROR_UNDEFINED_ENTITY,
1670                  "Parser did not report undefined entity (standalone).");
1671 }
1672 END_TEST
1673 
1674 /* Test that an error is reported for unknown entities if we have read
1675    an external subset, and standalone is true.
1676 */
1677 START_TEST(test_wfc_undeclared_entity_with_external_subset_standalone) {
1678   const char *text
1679       = "<?xml version='1.0' encoding='us-ascii' standalone='yes'?>\n"
1680         "<!DOCTYPE doc SYSTEM 'foo'>\n"
1681         "<doc>&entity;</doc>";
1682   ExtTest test_data = {"<!ELEMENT doc (#PCDATA)*>", NULL, NULL};
1683 
1684   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
1685   XML_SetUserData(g_parser, &test_data);
1686   XML_SetExternalEntityRefHandler(g_parser, external_entity_loader);
1687   expect_failure(text, XML_ERROR_UNDEFINED_ENTITY,
1688                  "Parser did not report undefined entity (external DTD).");
1689 }
1690 END_TEST
1691 
1692 /* Test that external entity handling is not done if the parsing flag
1693  * is set to UNLESS_STANDALONE
1694  */
1695 START_TEST(test_entity_with_external_subset_unless_standalone) {
1696   const char *text
1697       = "<?xml version='1.0' encoding='us-ascii' standalone='yes'?>\n"
1698         "<!DOCTYPE doc SYSTEM 'foo'>\n"
1699         "<doc>&entity;</doc>";
1700   ExtTest test_data = {"<!ENTITY entity 'bar'>", NULL, NULL};
1701 
1702   XML_SetParamEntityParsing(g_parser,
1703                             XML_PARAM_ENTITY_PARSING_UNLESS_STANDALONE);
1704   XML_SetUserData(g_parser, &test_data);
1705   XML_SetExternalEntityRefHandler(g_parser, external_entity_loader);
1706   expect_failure(text, XML_ERROR_UNDEFINED_ENTITY,
1707                  "Parser did not report undefined entity");
1708 }
1709 END_TEST
1710 
1711 /* Test that no error is reported for unknown entities if we have read
1712    an external subset, and standalone is false.
1713 */
1714 START_TEST(test_wfc_undeclared_entity_with_external_subset) {
1715   const char *text = "<?xml version='1.0' encoding='us-ascii'?>\n"
1716                      "<!DOCTYPE doc SYSTEM 'foo'>\n"
1717                      "<doc>&entity;</doc>";
1718   ExtTest test_data = {"<!ELEMENT doc (#PCDATA)*>", NULL, NULL};
1719 
1720   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
1721   XML_SetExternalEntityRefHandler(g_parser, external_entity_loader);
1722   run_ext_character_check(text, &test_data, XCS(""));
1723 }
1724 END_TEST
1725 
1726 /* Test that an error is reported if our NotStandalone handler fails */
1727 static int XMLCALL
1728 reject_not_standalone_handler(void *userData) {
1729   UNUSED_P(userData);
1730   return XML_STATUS_ERROR;
1731 }
1732 
1733 START_TEST(test_not_standalone_handler_reject) {
1734   const char *text = "<?xml version='1.0' encoding='us-ascii'?>\n"
1735                      "<!DOCTYPE doc SYSTEM 'foo'>\n"
1736                      "<doc>&entity;</doc>";
1737   ExtTest test_data = {"<!ELEMENT doc (#PCDATA)*>", NULL, NULL};
1738 
1739   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
1740   XML_SetUserData(g_parser, &test_data);
1741   XML_SetExternalEntityRefHandler(g_parser, external_entity_loader);
1742   XML_SetNotStandaloneHandler(g_parser, reject_not_standalone_handler);
1743   expect_failure(text, XML_ERROR_NOT_STANDALONE,
1744                  "NotStandalone handler failed to reject");
1745 
1746   /* Try again but without external entity handling */
1747   XML_ParserReset(g_parser, NULL);
1748   XML_SetNotStandaloneHandler(g_parser, reject_not_standalone_handler);
1749   expect_failure(text, XML_ERROR_NOT_STANDALONE,
1750                  "NotStandalone handler failed to reject");
1751 }
1752 END_TEST
1753 
1754 /* Test that no error is reported if our NotStandalone handler succeeds */
1755 static int XMLCALL
1756 accept_not_standalone_handler(void *userData) {
1757   UNUSED_P(userData);
1758   return XML_STATUS_OK;
1759 }
1760 
1761 START_TEST(test_not_standalone_handler_accept) {
1762   const char *text = "<?xml version='1.0' encoding='us-ascii'?>\n"
1763                      "<!DOCTYPE doc SYSTEM 'foo'>\n"
1764                      "<doc>&entity;</doc>";
1765   ExtTest test_data = {"<!ELEMENT doc (#PCDATA)*>", NULL, NULL};
1766 
1767   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
1768   XML_SetExternalEntityRefHandler(g_parser, external_entity_loader);
1769   XML_SetNotStandaloneHandler(g_parser, accept_not_standalone_handler);
1770   run_ext_character_check(text, &test_data, XCS(""));
1771 
1772   /* Repeat without the external entity handler */
1773   XML_ParserReset(g_parser, NULL);
1774   XML_SetNotStandaloneHandler(g_parser, accept_not_standalone_handler);
1775   run_character_check(text, XCS(""));
1776 }
1777 END_TEST
1778 
1779 START_TEST(test_wfc_no_recursive_entity_refs) {
1780   const char *text = "<!DOCTYPE doc [\n"
1781                      "  <!ENTITY entity '&#38;entity;'>\n"
1782                      "]>\n"
1783                      "<doc>&entity;</doc>";
1784 
1785   expect_failure(text, XML_ERROR_RECURSIVE_ENTITY_REF,
1786                  "Parser did not report recursive entity reference.");
1787 }
1788 END_TEST
1789 
1790 /* Test incomplete external entities are faulted */
1791 START_TEST(test_ext_entity_invalid_parse) {
1792   const char *text = "<!DOCTYPE doc [\n"
1793                      "  <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n"
1794                      "]>\n"
1795                      "<doc>&en;</doc>";
1796   const ExtFaults faults[]
1797       = {{"<", "Incomplete element declaration not faulted", NULL,
1798           XML_ERROR_UNCLOSED_TOKEN},
1799          {"<\xe2\x82", /* First two bytes of a three-byte char */
1800           "Incomplete character not faulted", NULL, XML_ERROR_PARTIAL_CHAR},
1801          {"<tag>\xe2\x82", "Incomplete character in CDATA not faulted", NULL,
1802           XML_ERROR_PARTIAL_CHAR},
1803          {NULL, NULL, NULL, XML_ERROR_NONE}};
1804   const ExtFaults *fault = faults;
1805 
1806   for (; fault->parse_text != NULL; fault++) {
1807     XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
1808     XML_SetExternalEntityRefHandler(g_parser, external_entity_faulter);
1809     XML_SetUserData(g_parser, (void *)fault);
1810     expect_failure(text, XML_ERROR_EXTERNAL_ENTITY_HANDLING,
1811                    "Parser did not report external entity error");
1812     XML_ParserReset(g_parser, NULL);
1813   }
1814 }
1815 END_TEST
1816 
1817 /* Regression test for SF bug #483514. */
1818 START_TEST(test_dtd_default_handling) {
1819   const char *text = "<!DOCTYPE doc [\n"
1820                      "<!ENTITY e SYSTEM 'http://example.org/e'>\n"
1821                      "<!NOTATION n SYSTEM 'http://example.org/n'>\n"
1822                      "<!ELEMENT doc EMPTY>\n"
1823                      "<!ATTLIST doc a CDATA #IMPLIED>\n"
1824                      "<?pi in dtd?>\n"
1825                      "<!--comment in dtd-->\n"
1826                      "]><doc/>";
1827 
1828   XML_SetDefaultHandler(g_parser, accumulate_characters);
1829   XML_SetStartDoctypeDeclHandler(g_parser, dummy_start_doctype_handler);
1830   XML_SetEndDoctypeDeclHandler(g_parser, dummy_end_doctype_handler);
1831   XML_SetEntityDeclHandler(g_parser, dummy_entity_decl_handler);
1832   XML_SetNotationDeclHandler(g_parser, dummy_notation_decl_handler);
1833   XML_SetElementDeclHandler(g_parser, dummy_element_decl_handler);
1834   XML_SetAttlistDeclHandler(g_parser, dummy_attlist_decl_handler);
1835   XML_SetProcessingInstructionHandler(g_parser, dummy_pi_handler);
1836   XML_SetCommentHandler(g_parser, dummy_comment_handler);
1837   XML_SetStartCdataSectionHandler(g_parser, dummy_start_cdata_handler);
1838   XML_SetEndCdataSectionHandler(g_parser, dummy_end_cdata_handler);
1839   run_character_check(text, XCS("\n\n\n\n\n\n\n<doc/>"));
1840 }
1841 END_TEST
1842 
1843 /* Test handling of attribute declarations */
1844 typedef struct AttTest {
1845   const char *definition;
1846   const XML_Char *element_name;
1847   const XML_Char *attr_name;
1848   const XML_Char *attr_type;
1849   const XML_Char *default_value;
1850   int is_required;
1851 } AttTest;
1852 
1853 static void XMLCALL
1854 verify_attlist_decl_handler(void *userData, const XML_Char *element_name,
1855                             const XML_Char *attr_name,
1856                             const XML_Char *attr_type,
1857                             const XML_Char *default_value, int is_required) {
1858   AttTest *at = (AttTest *)userData;
1859 
1860   if (xcstrcmp(element_name, at->element_name))
1861     fail("Unexpected element name in attribute declaration");
1862   if (xcstrcmp(attr_name, at->attr_name))
1863     fail("Unexpected attribute name in attribute declaration");
1864   if (xcstrcmp(attr_type, at->attr_type))
1865     fail("Unexpected attribute type in attribute declaration");
1866   if ((default_value == NULL && at->default_value != NULL)
1867       || (default_value != NULL && at->default_value == NULL)
1868       || (default_value != NULL && xcstrcmp(default_value, at->default_value)))
1869     fail("Unexpected default value in attribute declaration");
1870   if (is_required != at->is_required)
1871     fail("Requirement mismatch in attribute declaration");
1872 }
1873 
1874 START_TEST(test_dtd_attr_handling) {
1875   const char *prolog = "<!DOCTYPE doc [\n"
1876                        "<!ELEMENT doc EMPTY>\n";
1877   AttTest attr_data[]
1878       = {{"<!ATTLIST doc a ( one | two | three ) #REQUIRED>\n"
1879           "]>"
1880           "<doc a='two'/>",
1881           XCS("doc"), XCS("a"),
1882           XCS("(one|two|three)"), /* Extraneous spaces will be removed */
1883           NULL, XML_TRUE},
1884          {"<!NOTATION foo SYSTEM 'http://example.org/foo'>\n"
1885           "<!ATTLIST doc a NOTATION (foo) #IMPLIED>\n"
1886           "]>"
1887           "<doc/>",
1888           XCS("doc"), XCS("a"), XCS("NOTATION(foo)"), NULL, XML_FALSE},
1889          {"<!ATTLIST doc a NOTATION (foo) 'bar'>\n"
1890           "]>"
1891           "<doc/>",
1892           XCS("doc"), XCS("a"), XCS("NOTATION(foo)"), XCS("bar"), XML_FALSE},
1893          {"<!ATTLIST doc a CDATA '\xdb\xb2'>\n"
1894           "]>"
1895           "<doc/>",
1896           XCS("doc"), XCS("a"), XCS("CDATA"),
1897 #ifdef XML_UNICODE
1898           XCS("\x06f2"),
1899 #else
1900           XCS("\xdb\xb2"),
1901 #endif
1902           XML_FALSE},
1903          {NULL, NULL, NULL, NULL, NULL, XML_FALSE}};
1904   AttTest *test;
1905 
1906   for (test = attr_data; test->definition != NULL; test++) {
1907     XML_SetAttlistDeclHandler(g_parser, verify_attlist_decl_handler);
1908     XML_SetUserData(g_parser, test);
1909     if (_XML_Parse_SINGLE_BYTES(g_parser, prolog, (int)strlen(prolog),
1910                                 XML_FALSE)
1911         == XML_STATUS_ERROR)
1912       xml_failure(g_parser);
1913     if (_XML_Parse_SINGLE_BYTES(g_parser, test->definition,
1914                                 (int)strlen(test->definition), XML_TRUE)
1915         == XML_STATUS_ERROR)
1916       xml_failure(g_parser);
1917     XML_ParserReset(g_parser, NULL);
1918   }
1919 }
1920 END_TEST
1921 
1922 /* See related SF bug #673791.
1923    When namespace processing is enabled, setting the namespace URI for
1924    a prefix is not allowed; this test ensures that it *is* allowed
1925    when namespace processing is not enabled.
1926    (See Namespaces in XML, section 2.)
1927 */
1928 START_TEST(test_empty_ns_without_namespaces) {
1929   const char *text = "<doc xmlns:prefix='http://example.org/'>\n"
1930                      "  <e xmlns:prefix=''/>\n"
1931                      "</doc>";
1932 
1933   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
1934       == XML_STATUS_ERROR)
1935     xml_failure(g_parser);
1936 }
1937 END_TEST
1938 
1939 /* Regression test for SF bug #824420.
1940    Checks that an xmlns:prefix attribute set in an attribute's default
1941    value isn't misinterpreted.
1942 */
1943 START_TEST(test_ns_in_attribute_default_without_namespaces) {
1944   const char *text = "<!DOCTYPE e:element [\n"
1945                      "  <!ATTLIST e:element\n"
1946                      "    xmlns:e CDATA 'http://example.org/'>\n"
1947                      "      ]>\n"
1948                      "<e:element/>";
1949 
1950   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
1951       == XML_STATUS_ERROR)
1952     xml_failure(g_parser);
1953 }
1954 END_TEST
1955 
1956 static const char *long_character_data_text
1957     = "<?xml version='1.0' encoding='iso-8859-1'?><s>"
1958       "012345678901234567890123456789012345678901234567890123456789"
1959       "012345678901234567890123456789012345678901234567890123456789"
1960       "012345678901234567890123456789012345678901234567890123456789"
1961       "012345678901234567890123456789012345678901234567890123456789"
1962       "012345678901234567890123456789012345678901234567890123456789"
1963       "012345678901234567890123456789012345678901234567890123456789"
1964       "012345678901234567890123456789012345678901234567890123456789"
1965       "012345678901234567890123456789012345678901234567890123456789"
1966       "012345678901234567890123456789012345678901234567890123456789"
1967       "012345678901234567890123456789012345678901234567890123456789"
1968       "012345678901234567890123456789012345678901234567890123456789"
1969       "012345678901234567890123456789012345678901234567890123456789"
1970       "012345678901234567890123456789012345678901234567890123456789"
1971       "012345678901234567890123456789012345678901234567890123456789"
1972       "012345678901234567890123456789012345678901234567890123456789"
1973       "012345678901234567890123456789012345678901234567890123456789"
1974       "012345678901234567890123456789012345678901234567890123456789"
1975       "012345678901234567890123456789012345678901234567890123456789"
1976       "012345678901234567890123456789012345678901234567890123456789"
1977       "012345678901234567890123456789012345678901234567890123456789"
1978       "</s>";
1979 
1980 static XML_Bool resumable = XML_FALSE;
1981 
1982 static void
1983 clearing_aborting_character_handler(void *userData, const XML_Char *s,
1984                                     int len) {
1985   UNUSED_P(userData);
1986   UNUSED_P(s);
1987   UNUSED_P(len);
1988   XML_StopParser(g_parser, resumable);
1989   XML_SetCharacterDataHandler(g_parser, NULL);
1990 }
1991 
1992 /* Regression test for SF bug #1515266: missing check of stopped
1993    parser in doContext() 'for' loop. */
1994 START_TEST(test_stop_parser_between_char_data_calls) {
1995   /* The sample data must be big enough that there are two calls to
1996      the character data handler from within the inner "for" loop of
1997      the XML_TOK_DATA_CHARS case in doContent(), and the character
1998      handler must stop the parser and clear the character data
1999      handler.
2000   */
2001   const char *text = long_character_data_text;
2002 
2003   XML_SetCharacterDataHandler(g_parser, clearing_aborting_character_handler);
2004   resumable = XML_FALSE;
2005   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
2006       != XML_STATUS_ERROR)
2007     xml_failure(g_parser);
2008   if (XML_GetErrorCode(g_parser) != XML_ERROR_ABORTED)
2009     xml_failure(g_parser);
2010 }
2011 END_TEST
2012 
2013 /* Regression test for SF bug #1515266: missing check of stopped
2014    parser in doContext() 'for' loop. */
2015 START_TEST(test_suspend_parser_between_char_data_calls) {
2016   /* The sample data must be big enough that there are two calls to
2017      the character data handler from within the inner "for" loop of
2018      the XML_TOK_DATA_CHARS case in doContent(), and the character
2019      handler must stop the parser and clear the character data
2020      handler.
2021   */
2022   const char *text = long_character_data_text;
2023 
2024   XML_SetCharacterDataHandler(g_parser, clearing_aborting_character_handler);
2025   resumable = XML_TRUE;
2026   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
2027       != XML_STATUS_SUSPENDED)
2028     xml_failure(g_parser);
2029   if (XML_GetErrorCode(g_parser) != XML_ERROR_NONE)
2030     xml_failure(g_parser);
2031   /* Try parsing directly */
2032   if (XML_Parse(g_parser, text, (int)strlen(text), XML_TRUE)
2033       != XML_STATUS_ERROR)
2034     fail("Attempt to continue parse while suspended not faulted");
2035   if (XML_GetErrorCode(g_parser) != XML_ERROR_SUSPENDED)
2036     fail("Suspended parse not faulted with correct error");
2037 }
2038 END_TEST
2039 
2040 static XML_Bool abortable = XML_FALSE;
2041 
2042 static void
2043 parser_stop_character_handler(void *userData, const XML_Char *s, int len) {
2044   UNUSED_P(userData);
2045   UNUSED_P(s);
2046   UNUSED_P(len);
2047   XML_StopParser(g_parser, resumable);
2048   XML_SetCharacterDataHandler(g_parser, NULL);
2049   if (! resumable) {
2050     /* Check that aborting an aborted parser is faulted */
2051     if (XML_StopParser(g_parser, XML_FALSE) != XML_STATUS_ERROR)
2052       fail("Aborting aborted parser not faulted");
2053     if (XML_GetErrorCode(g_parser) != XML_ERROR_FINISHED)
2054       xml_failure(g_parser);
2055   } else if (abortable) {
2056     /* Check that aborting a suspended parser works */
2057     if (XML_StopParser(g_parser, XML_FALSE) == XML_STATUS_ERROR)
2058       xml_failure(g_parser);
2059   } else {
2060     /* Check that suspending a suspended parser works */
2061     if (XML_StopParser(g_parser, XML_TRUE) != XML_STATUS_ERROR)
2062       fail("Suspending suspended parser not faulted");
2063     if (XML_GetErrorCode(g_parser) != XML_ERROR_SUSPENDED)
2064       xml_failure(g_parser);
2065   }
2066 }
2067 
2068 /* Test repeated calls to XML_StopParser are handled correctly */
2069 START_TEST(test_repeated_stop_parser_between_char_data_calls) {
2070   const char *text = long_character_data_text;
2071 
2072   XML_SetCharacterDataHandler(g_parser, parser_stop_character_handler);
2073   resumable = XML_FALSE;
2074   abortable = XML_FALSE;
2075   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
2076       != XML_STATUS_ERROR)
2077     fail("Failed to double-stop parser");
2078 
2079   XML_ParserReset(g_parser, NULL);
2080   XML_SetCharacterDataHandler(g_parser, parser_stop_character_handler);
2081   resumable = XML_TRUE;
2082   abortable = XML_FALSE;
2083   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
2084       != XML_STATUS_SUSPENDED)
2085     fail("Failed to double-suspend parser");
2086 
2087   XML_ParserReset(g_parser, NULL);
2088   XML_SetCharacterDataHandler(g_parser, parser_stop_character_handler);
2089   resumable = XML_TRUE;
2090   abortable = XML_TRUE;
2091   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
2092       != XML_STATUS_ERROR)
2093     fail("Failed to suspend-abort parser");
2094 }
2095 END_TEST
2096 
2097 START_TEST(test_good_cdata_ascii) {
2098   const char *text = "<a><![CDATA[<greeting>Hello, world!</greeting>]]></a>";
2099   const XML_Char *expected = XCS("<greeting>Hello, world!</greeting>");
2100 
2101   CharData storage;
2102   CharData_Init(&storage);
2103   XML_SetUserData(g_parser, &storage);
2104   XML_SetCharacterDataHandler(g_parser, accumulate_characters);
2105   /* Add start and end handlers for coverage */
2106   XML_SetStartCdataSectionHandler(g_parser, dummy_start_cdata_handler);
2107   XML_SetEndCdataSectionHandler(g_parser, dummy_end_cdata_handler);
2108 
2109   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
2110       == XML_STATUS_ERROR)
2111     xml_failure(g_parser);
2112   CharData_CheckXMLChars(&storage, expected);
2113 
2114   /* Try again, this time with a default handler */
2115   XML_ParserReset(g_parser, NULL);
2116   CharData_Init(&storage);
2117   XML_SetUserData(g_parser, &storage);
2118   XML_SetCharacterDataHandler(g_parser, accumulate_characters);
2119   XML_SetDefaultHandler(g_parser, dummy_default_handler);
2120 
2121   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
2122       == XML_STATUS_ERROR)
2123     xml_failure(g_parser);
2124   CharData_CheckXMLChars(&storage, expected);
2125 }
2126 END_TEST
2127 
2128 START_TEST(test_good_cdata_utf16) {
2129   /* Test data is:
2130    *   <?xml version='1.0' encoding='utf-16'?>
2131    *   <a><![CDATA[hello]]></a>
2132    */
2133   const char text[]
2134       = "\0<\0?\0x\0m\0l\0"
2135         " \0v\0e\0r\0s\0i\0o\0n\0=\0'\0\x31\0.\0\x30\0'\0"
2136         " \0e\0n\0c\0o\0d\0i\0n\0g\0=\0'\0u\0t\0f\0-\0"
2137         "1\0"
2138         "6\0'"
2139         "\0?\0>\0\n"
2140         "\0<\0a\0>\0<\0!\0[\0C\0D\0A\0T\0A\0[\0h\0e\0l\0l\0o\0]\0]\0>\0<\0/\0a\0>";
2141   const XML_Char *expected = XCS("hello");
2142 
2143   CharData storage;
2144   CharData_Init(&storage);
2145   XML_SetUserData(g_parser, &storage);
2146   XML_SetCharacterDataHandler(g_parser, accumulate_characters);
2147 
2148   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE)
2149       == XML_STATUS_ERROR)
2150     xml_failure(g_parser);
2151   CharData_CheckXMLChars(&storage, expected);
2152 }
2153 END_TEST
2154 
2155 START_TEST(test_good_cdata_utf16_le) {
2156   /* Test data is:
2157    *   <?xml version='1.0' encoding='utf-16'?>
2158    *   <a><![CDATA[hello]]></a>
2159    */
2160   const char text[]
2161       = "<\0?\0x\0m\0l\0"
2162         " \0v\0e\0r\0s\0i\0o\0n\0=\0'\0\x31\0.\0\x30\0'\0"
2163         " \0e\0n\0c\0o\0d\0i\0n\0g\0=\0'\0u\0t\0f\0-\0"
2164         "1\0"
2165         "6\0'"
2166         "\0?\0>\0\n"
2167         "\0<\0a\0>\0<\0!\0[\0C\0D\0A\0T\0A\0[\0h\0e\0l\0l\0o\0]\0]\0>\0<\0/\0a\0>\0";
2168   const XML_Char *expected = XCS("hello");
2169 
2170   CharData storage;
2171   CharData_Init(&storage);
2172   XML_SetUserData(g_parser, &storage);
2173   XML_SetCharacterDataHandler(g_parser, accumulate_characters);
2174 
2175   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE)
2176       == XML_STATUS_ERROR)
2177     xml_failure(g_parser);
2178   CharData_CheckXMLChars(&storage, expected);
2179 }
2180 END_TEST
2181 
2182 /* Test UTF16 conversion of a long cdata string */
2183 
2184 /* 16 characters: handy macro to reduce visual clutter */
2185 #define A_TO_P_IN_UTF16 "\0A\0B\0C\0D\0E\0F\0G\0H\0I\0J\0K\0L\0M\0N\0O\0P"
2186 
2187 START_TEST(test_long_cdata_utf16) {
2188   /* Test data is:
2189    * <?xlm version='1.0' encoding='utf-16'?>
2190    * <a><![CDATA[
2191    * ABCDEFGHIJKLMNOP
2192    * ]]></a>
2193    */
2194   const char text[]
2195       = "\0<\0?\0x\0m\0l\0 "
2196         "\0v\0e\0r\0s\0i\0o\0n\0=\0'\0\x31\0.\0\x30\0'\0 "
2197         "\0e\0n\0c\0o\0d\0i\0n\0g\0=\0'\0u\0t\0f\0-\0\x31\0\x36\0'\0?\0>"
2198         "\0<\0a\0>\0<\0!\0[\0C\0D\0A\0T\0A\0["
2199       /* 64 characters per line */
2200       /* clang-format off */
2201         A_TO_P_IN_UTF16  A_TO_P_IN_UTF16  A_TO_P_IN_UTF16  A_TO_P_IN_UTF16
2202         A_TO_P_IN_UTF16  A_TO_P_IN_UTF16  A_TO_P_IN_UTF16  A_TO_P_IN_UTF16
2203         A_TO_P_IN_UTF16  A_TO_P_IN_UTF16  A_TO_P_IN_UTF16  A_TO_P_IN_UTF16
2204         A_TO_P_IN_UTF16  A_TO_P_IN_UTF16  A_TO_P_IN_UTF16  A_TO_P_IN_UTF16
2205         A_TO_P_IN_UTF16  A_TO_P_IN_UTF16  A_TO_P_IN_UTF16  A_TO_P_IN_UTF16
2206         A_TO_P_IN_UTF16  A_TO_P_IN_UTF16  A_TO_P_IN_UTF16  A_TO_P_IN_UTF16
2207         A_TO_P_IN_UTF16  A_TO_P_IN_UTF16  A_TO_P_IN_UTF16  A_TO_P_IN_UTF16
2208         A_TO_P_IN_UTF16  A_TO_P_IN_UTF16  A_TO_P_IN_UTF16  A_TO_P_IN_UTF16
2209         A_TO_P_IN_UTF16  A_TO_P_IN_UTF16  A_TO_P_IN_UTF16  A_TO_P_IN_UTF16
2210         A_TO_P_IN_UTF16  A_TO_P_IN_UTF16  A_TO_P_IN_UTF16  A_TO_P_IN_UTF16
2211         A_TO_P_IN_UTF16  A_TO_P_IN_UTF16  A_TO_P_IN_UTF16  A_TO_P_IN_UTF16
2212         A_TO_P_IN_UTF16  A_TO_P_IN_UTF16  A_TO_P_IN_UTF16  A_TO_P_IN_UTF16
2213         A_TO_P_IN_UTF16  A_TO_P_IN_UTF16  A_TO_P_IN_UTF16  A_TO_P_IN_UTF16
2214         A_TO_P_IN_UTF16  A_TO_P_IN_UTF16  A_TO_P_IN_UTF16  A_TO_P_IN_UTF16
2215         A_TO_P_IN_UTF16  A_TO_P_IN_UTF16  A_TO_P_IN_UTF16  A_TO_P_IN_UTF16
2216         A_TO_P_IN_UTF16  A_TO_P_IN_UTF16  A_TO_P_IN_UTF16  A_TO_P_IN_UTF16
2217         A_TO_P_IN_UTF16
2218         /* clang-format on */
2219         "\0]\0]\0>\0<\0/\0a\0>";
2220   const XML_Char *expected =
2221       /* clang-format off */
2222         XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
2223         XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
2224         XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
2225         XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
2226         XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
2227         XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
2228         XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
2229         XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
2230         XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
2231         XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
2232         XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
2233         XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
2234         XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
2235         XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
2236         XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
2237         XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
2238         XCS("ABCDEFGHIJKLMNOP");
2239   /* clang-format on */
2240   CharData storage;
2241   void *buffer;
2242 
2243   CharData_Init(&storage);
2244   XML_SetUserData(g_parser, &storage);
2245   XML_SetCharacterDataHandler(g_parser, accumulate_characters);
2246   buffer = XML_GetBuffer(g_parser, sizeof(text) - 1);
2247   if (buffer == NULL)
2248     fail("Could not allocate parse buffer");
2249   assert(buffer != NULL);
2250   memcpy(buffer, text, sizeof(text) - 1);
2251   if (XML_ParseBuffer(g_parser, sizeof(text) - 1, XML_TRUE) == XML_STATUS_ERROR)
2252     xml_failure(g_parser);
2253   CharData_CheckXMLChars(&storage, expected);
2254 }
2255 END_TEST
2256 
2257 /* Test handling of multiple unit UTF-16 characters */
2258 START_TEST(test_multichar_cdata_utf16) {
2259   /* Test data is:
2260    *   <?xml version='1.0' encoding='utf-16'?>
2261    *   <a><![CDATA[{MINIM}{CROTCHET}]]></a>
2262    *
2263    * where {MINIM} is U+1d15e (a minim or half-note)
2264    *   UTF-16: 0xd834 0xdd5e
2265    *   UTF-8:  0xf0 0x9d 0x85 0x9e
2266    * and {CROTCHET} is U+1d15f (a crotchet or quarter-note)
2267    *   UTF-16: 0xd834 0xdd5f
2268    *   UTF-8:  0xf0 0x9d 0x85 0x9f
2269    */
2270   const char text[] = "\0<\0?\0x\0m\0l\0"
2271                       " \0v\0e\0r\0s\0i\0o\0n\0=\0'\0\x31\0.\0\x30\0'\0"
2272                       " \0e\0n\0c\0o\0d\0i\0n\0g\0=\0'\0u\0t\0f\0-\0"
2273                       "1\0"
2274                       "6\0'"
2275                       "\0?\0>\0\n"
2276                       "\0<\0a\0>\0<\0!\0[\0C\0D\0A\0T\0A\0["
2277                       "\xd8\x34\xdd\x5e\xd8\x34\xdd\x5f"
2278                       "\0]\0]\0>\0<\0/\0a\0>";
2279 #ifdef XML_UNICODE
2280   const XML_Char *expected = XCS("\xd834\xdd5e\xd834\xdd5f");
2281 #else
2282   const XML_Char *expected = XCS("\xf0\x9d\x85\x9e\xf0\x9d\x85\x9f");
2283 #endif
2284   CharData storage;
2285 
2286   CharData_Init(&storage);
2287   XML_SetUserData(g_parser, &storage);
2288   XML_SetCharacterDataHandler(g_parser, accumulate_characters);
2289 
2290   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE)
2291       == XML_STATUS_ERROR)
2292     xml_failure(g_parser);
2293   CharData_CheckXMLChars(&storage, expected);
2294 }
2295 END_TEST
2296 
2297 /* Test that an element name with a UTF-16 surrogate pair is rejected */
2298 START_TEST(test_utf16_bad_surrogate_pair) {
2299   /* Test data is:
2300    *   <?xml version='1.0' encoding='utf-16'?>
2301    *   <a><![CDATA[{BADLINB}]]></a>
2302    *
2303    * where {BADLINB} is U+10000 (the first Linear B character)
2304    * with the UTF-16 surrogate pair in the wrong order, i.e.
2305    *   0xdc00 0xd800
2306    */
2307   const char text[] = "\0<\0?\0x\0m\0l\0"
2308                       " \0v\0e\0r\0s\0i\0o\0n\0=\0'\0\x31\0.\0\x30\0'\0"
2309                       " \0e\0n\0c\0o\0d\0i\0n\0g\0=\0'\0u\0t\0f\0-\0"
2310                       "1\0"
2311                       "6\0'"
2312                       "\0?\0>\0\n"
2313                       "\0<\0a\0>\0<\0!\0[\0C\0D\0A\0T\0A\0["
2314                       "\xdc\x00\xd8\x00"
2315                       "\0]\0]\0>\0<\0/\0a\0>";
2316 
2317   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE)
2318       != XML_STATUS_ERROR)
2319     fail("Reversed UTF-16 surrogate pair not faulted");
2320   if (XML_GetErrorCode(g_parser) != XML_ERROR_INVALID_TOKEN)
2321     xml_failure(g_parser);
2322 }
2323 END_TEST
2324 
2325 START_TEST(test_bad_cdata) {
2326   struct CaseData {
2327     const char *text;
2328     enum XML_Error expectedError;
2329   };
2330 
2331   struct CaseData cases[]
2332       = {{"<a><", XML_ERROR_UNCLOSED_TOKEN},
2333          {"<a><!", XML_ERROR_UNCLOSED_TOKEN},
2334          {"<a><![", XML_ERROR_UNCLOSED_TOKEN},
2335          {"<a><![C", XML_ERROR_UNCLOSED_TOKEN},
2336          {"<a><![CD", XML_ERROR_UNCLOSED_TOKEN},
2337          {"<a><![CDA", XML_ERROR_UNCLOSED_TOKEN},
2338          {"<a><![CDAT", XML_ERROR_UNCLOSED_TOKEN},
2339          {"<a><![CDATA", XML_ERROR_UNCLOSED_TOKEN},
2340 
2341          {"<a><![CDATA[", XML_ERROR_UNCLOSED_CDATA_SECTION},
2342          {"<a><![CDATA[]", XML_ERROR_UNCLOSED_CDATA_SECTION},
2343          {"<a><![CDATA[]]", XML_ERROR_UNCLOSED_CDATA_SECTION},
2344 
2345          {"<a><!<a/>", XML_ERROR_INVALID_TOKEN},
2346          {"<a><![<a/>", XML_ERROR_UNCLOSED_TOKEN},  /* ?! */
2347          {"<a><![C<a/>", XML_ERROR_UNCLOSED_TOKEN}, /* ?! */
2348          {"<a><![CD<a/>", XML_ERROR_INVALID_TOKEN},
2349          {"<a><![CDA<a/>", XML_ERROR_INVALID_TOKEN},
2350          {"<a><![CDAT<a/>", XML_ERROR_INVALID_TOKEN},
2351          {"<a><![CDATA<a/>", XML_ERROR_INVALID_TOKEN},
2352 
2353          {"<a><![CDATA[<a/>", XML_ERROR_UNCLOSED_CDATA_SECTION},
2354          {"<a><![CDATA[]<a/>", XML_ERROR_UNCLOSED_CDATA_SECTION},
2355          {"<a><![CDATA[]]<a/>", XML_ERROR_UNCLOSED_CDATA_SECTION}};
2356 
2357   size_t i = 0;
2358   for (; i < sizeof(cases) / sizeof(struct CaseData); i++) {
2359     const enum XML_Status actualStatus = _XML_Parse_SINGLE_BYTES(
2360         g_parser, cases[i].text, (int)strlen(cases[i].text), XML_TRUE);
2361     const enum XML_Error actualError = XML_GetErrorCode(g_parser);
2362 
2363     assert(actualStatus == XML_STATUS_ERROR);
2364 
2365     if (actualError != cases[i].expectedError) {
2366       char message[100];
2367       sprintf(message,
2368               "Expected error %d but got error %d for case %u: \"%s\"\n",
2369               cases[i].expectedError, actualError, (unsigned int)i + 1,
2370               cases[i].text);
2371       fail(message);
2372     }
2373 
2374     XML_ParserReset(g_parser, NULL);
2375   }
2376 }
2377 END_TEST
2378 
2379 /* Test failures in UTF-16 CDATA */
2380 START_TEST(test_bad_cdata_utf16) {
2381   struct CaseData {
2382     size_t text_bytes;
2383     const char *text;
2384     enum XML_Error expected_error;
2385   };
2386 
2387   const char prolog[] = "\0<\0?\0x\0m\0l\0"
2388                         " \0v\0e\0r\0s\0i\0o\0n\0=\0'\0\x31\0.\0\x30\0'\0"
2389                         " \0e\0n\0c\0o\0d\0i\0n\0g\0=\0'\0u\0t\0f\0-\0"
2390                         "1\0"
2391                         "6\0'"
2392                         "\0?\0>\0\n"
2393                         "\0<\0a\0>";
2394   struct CaseData cases[] = {
2395       {1, "\0", XML_ERROR_UNCLOSED_TOKEN},
2396       {2, "\0<", XML_ERROR_UNCLOSED_TOKEN},
2397       {3, "\0<\0", XML_ERROR_UNCLOSED_TOKEN},
2398       {4, "\0<\0!", XML_ERROR_UNCLOSED_TOKEN},
2399       {5, "\0<\0!\0", XML_ERROR_UNCLOSED_TOKEN},
2400       {6, "\0<\0!\0[", XML_ERROR_UNCLOSED_TOKEN},
2401       {7, "\0<\0!\0[\0", XML_ERROR_UNCLOSED_TOKEN},
2402       {8, "\0<\0!\0[\0C", XML_ERROR_UNCLOSED_TOKEN},
2403       {9, "\0<\0!\0[\0C\0", XML_ERROR_UNCLOSED_TOKEN},
2404       {10, "\0<\0!\0[\0C\0D", XML_ERROR_UNCLOSED_TOKEN},
2405       {11, "\0<\0!\0[\0C\0D\0", XML_ERROR_UNCLOSED_TOKEN},
2406       {12, "\0<\0!\0[\0C\0D\0A", XML_ERROR_UNCLOSED_TOKEN},
2407       {13, "\0<\0!\0[\0C\0D\0A\0", XML_ERROR_UNCLOSED_TOKEN},
2408       {14, "\0<\0!\0[\0C\0D\0A\0T", XML_ERROR_UNCLOSED_TOKEN},
2409       {15, "\0<\0!\0[\0C\0D\0A\0T\0", XML_ERROR_UNCLOSED_TOKEN},
2410       {16, "\0<\0!\0[\0C\0D\0A\0T\0A", XML_ERROR_UNCLOSED_TOKEN},
2411       {17, "\0<\0!\0[\0C\0D\0A\0T\0A\0", XML_ERROR_UNCLOSED_TOKEN},
2412       {18, "\0<\0!\0[\0C\0D\0A\0T\0A\0[", XML_ERROR_UNCLOSED_CDATA_SECTION},
2413       {19, "\0<\0!\0[\0C\0D\0A\0T\0A\0[\0", XML_ERROR_UNCLOSED_CDATA_SECTION},
2414       {20, "\0<\0!\0[\0C\0D\0A\0T\0A\0[\0Z", XML_ERROR_UNCLOSED_CDATA_SECTION},
2415       /* Now add a four-byte UTF-16 character */
2416       {21, "\0<\0!\0[\0C\0D\0A\0T\0A\0[\0Z\xd8",
2417        XML_ERROR_UNCLOSED_CDATA_SECTION},
2418       {22, "\0<\0!\0[\0C\0D\0A\0T\0A\0[\0Z\xd8\x34", XML_ERROR_PARTIAL_CHAR},
2419       {23, "\0<\0!\0[\0C\0D\0A\0T\0A\0[\0Z\xd8\x34\xdd",
2420        XML_ERROR_PARTIAL_CHAR},
2421       {24, "\0<\0!\0[\0C\0D\0A\0T\0A\0[\0Z\xd8\x34\xdd\x5e",
2422        XML_ERROR_UNCLOSED_CDATA_SECTION}};
2423   size_t i;
2424 
2425   for (i = 0; i < sizeof(cases) / sizeof(struct CaseData); i++) {
2426     enum XML_Status actual_status;
2427     enum XML_Error actual_error;
2428 
2429     if (_XML_Parse_SINGLE_BYTES(g_parser, prolog, (int)sizeof(prolog) - 1,
2430                                 XML_FALSE)
2431         == XML_STATUS_ERROR)
2432       xml_failure(g_parser);
2433     actual_status = _XML_Parse_SINGLE_BYTES(g_parser, cases[i].text,
2434                                             (int)cases[i].text_bytes, XML_TRUE);
2435     assert(actual_status == XML_STATUS_ERROR);
2436     actual_error = XML_GetErrorCode(g_parser);
2437     if (actual_error != cases[i].expected_error) {
2438       char message[1024];
2439 
2440       sprintf(message,
2441               "Expected error %d (%" XML_FMT_STR "), got %d (%" XML_FMT_STR
2442               ") for case %lu\n",
2443               cases[i].expected_error, XML_ErrorString(cases[i].expected_error),
2444               actual_error, XML_ErrorString(actual_error),
2445               (long unsigned)(i + 1));
2446       fail(message);
2447     }
2448     XML_ParserReset(g_parser, NULL);
2449   }
2450 }
2451 END_TEST
2452 
2453 static const char *long_cdata_text
2454     = "<s><![CDATA["
2455       "012345678901234567890123456789012345678901234567890123456789"
2456       "012345678901234567890123456789012345678901234567890123456789"
2457       "012345678901234567890123456789012345678901234567890123456789"
2458       "012345678901234567890123456789012345678901234567890123456789"
2459       "012345678901234567890123456789012345678901234567890123456789"
2460       "012345678901234567890123456789012345678901234567890123456789"
2461       "012345678901234567890123456789012345678901234567890123456789"
2462       "012345678901234567890123456789012345678901234567890123456789"
2463       "012345678901234567890123456789012345678901234567890123456789"
2464       "012345678901234567890123456789012345678901234567890123456789"
2465       "012345678901234567890123456789012345678901234567890123456789"
2466       "012345678901234567890123456789012345678901234567890123456789"
2467       "012345678901234567890123456789012345678901234567890123456789"
2468       "012345678901234567890123456789012345678901234567890123456789"
2469       "012345678901234567890123456789012345678901234567890123456789"
2470       "012345678901234567890123456789012345678901234567890123456789"
2471       "012345678901234567890123456789012345678901234567890123456789"
2472       "012345678901234567890123456789012345678901234567890123456789"
2473       "012345678901234567890123456789012345678901234567890123456789"
2474       "012345678901234567890123456789012345678901234567890123456789"
2475       "]]></s>";
2476 
2477 /* Test stopping the parser in cdata handler */
2478 START_TEST(test_stop_parser_between_cdata_calls) {
2479   const char *text = long_cdata_text;
2480 
2481   XML_SetCharacterDataHandler(g_parser, clearing_aborting_character_handler);
2482   resumable = XML_FALSE;
2483   expect_failure(text, XML_ERROR_ABORTED, "Parse not aborted in CDATA handler");
2484 }
2485 END_TEST
2486 
2487 /* Test suspending the parser in cdata handler */
2488 START_TEST(test_suspend_parser_between_cdata_calls) {
2489   const char *text = long_cdata_text;
2490   enum XML_Status result;
2491 
2492   XML_SetCharacterDataHandler(g_parser, clearing_aborting_character_handler);
2493   resumable = XML_TRUE;
2494   result = _XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE);
2495   if (result != XML_STATUS_SUSPENDED) {
2496     if (result == XML_STATUS_ERROR)
2497       xml_failure(g_parser);
2498     fail("Parse not suspended in CDATA handler");
2499   }
2500   if (XML_GetErrorCode(g_parser) != XML_ERROR_NONE)
2501     xml_failure(g_parser);
2502 }
2503 END_TEST
2504 
2505 /* Test memory allocation functions */
2506 START_TEST(test_memory_allocation) {
2507   char *buffer = (char *)XML_MemMalloc(g_parser, 256);
2508   char *p;
2509 
2510   if (buffer == NULL) {
2511     fail("Allocation failed");
2512   } else {
2513     /* Try writing to memory; some OSes try to cheat! */
2514     buffer[0] = 'T';
2515     buffer[1] = 'E';
2516     buffer[2] = 'S';
2517     buffer[3] = 'T';
2518     buffer[4] = '\0';
2519     if (strcmp(buffer, "TEST") != 0) {
2520       fail("Memory not writable");
2521     } else {
2522       p = (char *)XML_MemRealloc(g_parser, buffer, 512);
2523       if (p == NULL) {
2524         fail("Reallocation failed");
2525       } else {
2526         /* Write again, just to be sure */
2527         buffer = p;
2528         buffer[0] = 'V';
2529         if (strcmp(buffer, "VEST") != 0) {
2530           fail("Reallocated memory not writable");
2531         }
2532       }
2533     }
2534     XML_MemFree(g_parser, buffer);
2535   }
2536 }
2537 END_TEST
2538 
2539 static void XMLCALL
2540 record_default_handler(void *userData, const XML_Char *s, int len) {
2541   UNUSED_P(s);
2542   UNUSED_P(len);
2543   CharData_AppendXMLChars((CharData *)userData, XCS("D"), 1);
2544 }
2545 
2546 static void XMLCALL
2547 record_cdata_handler(void *userData, const XML_Char *s, int len) {
2548   UNUSED_P(s);
2549   UNUSED_P(len);
2550   CharData_AppendXMLChars((CharData *)userData, XCS("C"), 1);
2551   XML_DefaultCurrent(g_parser);
2552 }
2553 
2554 static void XMLCALL
2555 record_cdata_nodefault_handler(void *userData, const XML_Char *s, int len) {
2556   UNUSED_P(s);
2557   UNUSED_P(len);
2558   CharData_AppendXMLChars((CharData *)userData, XCS("c"), 1);
2559 }
2560 
2561 static void XMLCALL
2562 record_skip_handler(void *userData, const XML_Char *entityName,
2563                     int is_parameter_entity) {
2564   UNUSED_P(entityName);
2565   CharData_AppendXMLChars((CharData *)userData,
2566                           is_parameter_entity ? XCS("E") : XCS("e"), 1);
2567 }
2568 
2569 /* Test XML_DefaultCurrent() passes handling on correctly */
2570 START_TEST(test_default_current) {
2571   const char *text = "<doc>hell]</doc>";
2572   const char *entity_text = "<!DOCTYPE doc [\n"
2573                             "<!ENTITY entity '&#37;'>\n"
2574                             "]>\n"
2575                             "<doc>&entity;</doc>";
2576   CharData storage;
2577 
2578   XML_SetDefaultHandler(g_parser, record_default_handler);
2579   XML_SetCharacterDataHandler(g_parser, record_cdata_handler);
2580   CharData_Init(&storage);
2581   XML_SetUserData(g_parser, &storage);
2582   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
2583       == XML_STATUS_ERROR)
2584     xml_failure(g_parser);
2585   CharData_CheckXMLChars(&storage, XCS("DCDCDCDCDCDD"));
2586 
2587   /* Again, without the defaulting */
2588   XML_ParserReset(g_parser, NULL);
2589   XML_SetDefaultHandler(g_parser, record_default_handler);
2590   XML_SetCharacterDataHandler(g_parser, record_cdata_nodefault_handler);
2591   CharData_Init(&storage);
2592   XML_SetUserData(g_parser, &storage);
2593   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
2594       == XML_STATUS_ERROR)
2595     xml_failure(g_parser);
2596   CharData_CheckXMLChars(&storage, XCS("DcccccD"));
2597 
2598   /* Now with an internal entity to complicate matters */
2599   XML_ParserReset(g_parser, NULL);
2600   XML_SetDefaultHandler(g_parser, record_default_handler);
2601   XML_SetCharacterDataHandler(g_parser, record_cdata_handler);
2602   CharData_Init(&storage);
2603   XML_SetUserData(g_parser, &storage);
2604   if (_XML_Parse_SINGLE_BYTES(g_parser, entity_text, (int)strlen(entity_text),
2605                               XML_TRUE)
2606       == XML_STATUS_ERROR)
2607     xml_failure(g_parser);
2608   /* The default handler suppresses the entity */
2609   CharData_CheckXMLChars(&storage, XCS("DDDDDDDDDDDDDDDDDDD"));
2610 
2611   /* Again, with a skip handler */
2612   XML_ParserReset(g_parser, NULL);
2613   XML_SetDefaultHandler(g_parser, record_default_handler);
2614   XML_SetCharacterDataHandler(g_parser, record_cdata_handler);
2615   XML_SetSkippedEntityHandler(g_parser, record_skip_handler);
2616   CharData_Init(&storage);
2617   XML_SetUserData(g_parser, &storage);
2618   if (_XML_Parse_SINGLE_BYTES(g_parser, entity_text, (int)strlen(entity_text),
2619                               XML_TRUE)
2620       == XML_STATUS_ERROR)
2621     xml_failure(g_parser);
2622   /* The default handler suppresses the entity */
2623   CharData_CheckXMLChars(&storage, XCS("DDDDDDDDDDDDDDDDDeD"));
2624 
2625   /* This time, allow the entity through */
2626   XML_ParserReset(g_parser, NULL);
2627   XML_SetDefaultHandlerExpand(g_parser, record_default_handler);
2628   XML_SetCharacterDataHandler(g_parser, record_cdata_handler);
2629   CharData_Init(&storage);
2630   XML_SetUserData(g_parser, &storage);
2631   if (_XML_Parse_SINGLE_BYTES(g_parser, entity_text, (int)strlen(entity_text),
2632                               XML_TRUE)
2633       == XML_STATUS_ERROR)
2634     xml_failure(g_parser);
2635   CharData_CheckXMLChars(&storage, XCS("DDDDDDDDDDDDDDDDDCDD"));
2636 
2637   /* Finally, without passing the cdata to the default handler */
2638   XML_ParserReset(g_parser, NULL);
2639   XML_SetDefaultHandlerExpand(g_parser, record_default_handler);
2640   XML_SetCharacterDataHandler(g_parser, record_cdata_nodefault_handler);
2641   CharData_Init(&storage);
2642   XML_SetUserData(g_parser, &storage);
2643   if (_XML_Parse_SINGLE_BYTES(g_parser, entity_text, (int)strlen(entity_text),
2644                               XML_TRUE)
2645       == XML_STATUS_ERROR)
2646     xml_failure(g_parser);
2647   CharData_CheckXMLChars(&storage, XCS("DDDDDDDDDDDDDDDDDcD"));
2648 }
2649 END_TEST
2650 
2651 /* Test DTD element parsing code paths */
2652 START_TEST(test_dtd_elements) {
2653   const char *text = "<!DOCTYPE doc [\n"
2654                      "<!ELEMENT doc (chapter)>\n"
2655                      "<!ELEMENT chapter (#PCDATA)>\n"
2656                      "]>\n"
2657                      "<doc><chapter>Wombats are go</chapter></doc>";
2658 
2659   XML_SetElementDeclHandler(g_parser, dummy_element_decl_handler);
2660   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
2661       == XML_STATUS_ERROR)
2662     xml_failure(g_parser);
2663 }
2664 END_TEST
2665 
2666 static void XMLCALL
2667 element_decl_check_model(void *userData, const XML_Char *name,
2668                          XML_Content *model) {
2669   UNUSED_P(userData);
2670   uint32_t errorFlags = 0;
2671 
2672   /* Expected model array structure is this:
2673    * [0] (type 6, quant 0)
2674    *   [1] (type 5, quant 0)
2675    *     [3] (type 4, quant 0, name "bar")
2676    *     [4] (type 4, quant 0, name "foo")
2677    *     [5] (type 4, quant 3, name "xyz")
2678    *   [2] (type 4, quant 2, name "zebra")
2679    */
2680   errorFlags |= ((xcstrcmp(name, XCS("junk")) == 0) ? 0 : (1u << 0));
2681   errorFlags |= ((model != NULL) ? 0 : (1u << 1));
2682 
2683   errorFlags |= ((model[0].type == XML_CTYPE_SEQ) ? 0 : (1u << 2));
2684   errorFlags |= ((model[0].quant == XML_CQUANT_NONE) ? 0 : (1u << 3));
2685   errorFlags |= ((model[0].numchildren == 2) ? 0 : (1u << 4));
2686   errorFlags |= ((model[0].children == &model[1]) ? 0 : (1u << 5));
2687   errorFlags |= ((model[0].name == NULL) ? 0 : (1u << 6));
2688 
2689   errorFlags |= ((model[1].type == XML_CTYPE_CHOICE) ? 0 : (1u << 7));
2690   errorFlags |= ((model[1].quant == XML_CQUANT_NONE) ? 0 : (1u << 8));
2691   errorFlags |= ((model[1].numchildren == 3) ? 0 : (1u << 9));
2692   errorFlags |= ((model[1].children == &model[3]) ? 0 : (1u << 10));
2693   errorFlags |= ((model[1].name == NULL) ? 0 : (1u << 11));
2694 
2695   errorFlags |= ((model[2].type == XML_CTYPE_NAME) ? 0 : (1u << 12));
2696   errorFlags |= ((model[2].quant == XML_CQUANT_REP) ? 0 : (1u << 13));
2697   errorFlags |= ((model[2].numchildren == 0) ? 0 : (1u << 14));
2698   errorFlags |= ((model[2].children == NULL) ? 0 : (1u << 15));
2699   errorFlags |= ((xcstrcmp(model[2].name, XCS("zebra")) == 0) ? 0 : (1u << 16));
2700 
2701   errorFlags |= ((model[3].type == XML_CTYPE_NAME) ? 0 : (1u << 17));
2702   errorFlags |= ((model[3].quant == XML_CQUANT_NONE) ? 0 : (1u << 18));
2703   errorFlags |= ((model[3].numchildren == 0) ? 0 : (1u << 19));
2704   errorFlags |= ((model[3].children == NULL) ? 0 : (1u << 20));
2705   errorFlags |= ((xcstrcmp(model[3].name, XCS("bar")) == 0) ? 0 : (1u << 21));
2706 
2707   errorFlags |= ((model[4].type == XML_CTYPE_NAME) ? 0 : (1u << 22));
2708   errorFlags |= ((model[4].quant == XML_CQUANT_NONE) ? 0 : (1u << 23));
2709   errorFlags |= ((model[4].numchildren == 0) ? 0 : (1u << 24));
2710   errorFlags |= ((model[4].children == NULL) ? 0 : (1u << 25));
2711   errorFlags |= ((xcstrcmp(model[4].name, XCS("foo")) == 0) ? 0 : (1u << 26));
2712 
2713   errorFlags |= ((model[5].type == XML_CTYPE_NAME) ? 0 : (1u << 27));
2714   errorFlags |= ((model[5].quant == XML_CQUANT_PLUS) ? 0 : (1u << 28));
2715   errorFlags |= ((model[5].numchildren == 0) ? 0 : (1u << 29));
2716   errorFlags |= ((model[5].children == NULL) ? 0 : (1u << 30));
2717   errorFlags |= ((xcstrcmp(model[5].name, XCS("xyz")) == 0) ? 0 : (1u << 31));
2718 
2719   XML_SetUserData(g_parser, (void *)(uintptr_t)errorFlags);
2720   XML_FreeContentModel(g_parser, model);
2721 }
2722 
2723 START_TEST(test_dtd_elements_nesting) {
2724   // Payload inspired by a test in Perl's XML::Parser
2725   const char *text = "<!DOCTYPE foo [\n"
2726                      "<!ELEMENT junk ((bar|foo|xyz+), zebra*)>\n"
2727                      "]>\n"
2728                      "<foo/>";
2729 
2730   XML_SetUserData(g_parser, (void *)(uintptr_t)-1);
2731 
2732   XML_SetElementDeclHandler(g_parser, element_decl_check_model);
2733   if (XML_Parse(g_parser, text, (int)strlen(text), XML_TRUE)
2734       == XML_STATUS_ERROR)
2735     xml_failure(g_parser);
2736 
2737   if ((uint32_t)(uintptr_t)XML_GetUserData(g_parser) != 0)
2738     fail("Element declaration model regression detected");
2739 }
2740 END_TEST
2741 
2742 /* Test foreign DTD handling */
2743 START_TEST(test_set_foreign_dtd) {
2744   const char *text1 = "<?xml version='1.0' encoding='us-ascii'?>\n";
2745   const char *text2 = "<doc>&entity;</doc>";
2746   ExtTest test_data = {"<!ELEMENT doc (#PCDATA)*>", NULL, NULL};
2747 
2748   /* Check hash salt is passed through too */
2749   XML_SetHashSalt(g_parser, 0x12345678);
2750   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
2751   XML_SetUserData(g_parser, &test_data);
2752   XML_SetExternalEntityRefHandler(g_parser, external_entity_loader);
2753   /* Add a default handler to exercise more code paths */
2754   XML_SetDefaultHandler(g_parser, dummy_default_handler);
2755   if (XML_UseForeignDTD(g_parser, XML_TRUE) != XML_ERROR_NONE)
2756     fail("Could not set foreign DTD");
2757   if (_XML_Parse_SINGLE_BYTES(g_parser, text1, (int)strlen(text1), XML_FALSE)
2758       == XML_STATUS_ERROR)
2759     xml_failure(g_parser);
2760 
2761   /* Ensure that trying to set the DTD after parsing has started
2762    * is faulted, even if it's the same setting.
2763    */
2764   if (XML_UseForeignDTD(g_parser, XML_TRUE)
2765       != XML_ERROR_CANT_CHANGE_FEATURE_ONCE_PARSING)
2766     fail("Failed to reject late foreign DTD setting");
2767   /* Ditto for the hash salt */
2768   if (XML_SetHashSalt(g_parser, 0x23456789))
2769     fail("Failed to reject late hash salt change");
2770 
2771   /* Now finish the parse */
2772   if (_XML_Parse_SINGLE_BYTES(g_parser, text2, (int)strlen(text2), XML_TRUE)
2773       == XML_STATUS_ERROR)
2774     xml_failure(g_parser);
2775 }
2776 END_TEST
2777 
2778 /* Test foreign DTD handling with a failing NotStandalone handler */
2779 START_TEST(test_foreign_dtd_not_standalone) {
2780   const char *text = "<?xml version='1.0' encoding='us-ascii'?>\n"
2781                      "<doc>&entity;</doc>";
2782   ExtTest test_data = {"<!ELEMENT doc (#PCDATA)*>", NULL, NULL};
2783 
2784   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
2785   XML_SetUserData(g_parser, &test_data);
2786   XML_SetExternalEntityRefHandler(g_parser, external_entity_loader);
2787   XML_SetNotStandaloneHandler(g_parser, reject_not_standalone_handler);
2788   if (XML_UseForeignDTD(g_parser, XML_TRUE) != XML_ERROR_NONE)
2789     fail("Could not set foreign DTD");
2790   expect_failure(text, XML_ERROR_NOT_STANDALONE,
2791                  "NotStandalonehandler failed to reject");
2792 }
2793 END_TEST
2794 
2795 /* Test invalid character in a foreign DTD is faulted */
2796 START_TEST(test_invalid_foreign_dtd) {
2797   const char *text = "<?xml version='1.0' encoding='us-ascii'?>\n"
2798                      "<doc>&entity;</doc>";
2799   ExtFaults test_data
2800       = {"$", "Dollar not faulted", NULL, XML_ERROR_INVALID_TOKEN};
2801 
2802   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
2803   XML_SetUserData(g_parser, &test_data);
2804   XML_SetExternalEntityRefHandler(g_parser, external_entity_faulter);
2805   XML_UseForeignDTD(g_parser, XML_TRUE);
2806   expect_failure(text, XML_ERROR_EXTERNAL_ENTITY_HANDLING,
2807                  "Bad DTD should not have been accepted");
2808 }
2809 END_TEST
2810 
2811 /* Test foreign DTD use with a doctype */
2812 START_TEST(test_foreign_dtd_with_doctype) {
2813   const char *text1 = "<?xml version='1.0' encoding='us-ascii'?>\n"
2814                       "<!DOCTYPE doc [<!ENTITY entity 'hello world'>]>\n";
2815   const char *text2 = "<doc>&entity;</doc>";
2816   ExtTest test_data = {"<!ELEMENT doc (#PCDATA)*>", NULL, NULL};
2817 
2818   /* Check hash salt is passed through too */
2819   XML_SetHashSalt(g_parser, 0x12345678);
2820   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
2821   XML_SetUserData(g_parser, &test_data);
2822   XML_SetExternalEntityRefHandler(g_parser, external_entity_loader);
2823   /* Add a default handler to exercise more code paths */
2824   XML_SetDefaultHandler(g_parser, dummy_default_handler);
2825   if (XML_UseForeignDTD(g_parser, XML_TRUE) != XML_ERROR_NONE)
2826     fail("Could not set foreign DTD");
2827   if (_XML_Parse_SINGLE_BYTES(g_parser, text1, (int)strlen(text1), XML_FALSE)
2828       == XML_STATUS_ERROR)
2829     xml_failure(g_parser);
2830 
2831   /* Ensure that trying to set the DTD after parsing has started
2832    * is faulted, even if it's the same setting.
2833    */
2834   if (XML_UseForeignDTD(g_parser, XML_TRUE)
2835       != XML_ERROR_CANT_CHANGE_FEATURE_ONCE_PARSING)
2836     fail("Failed to reject late foreign DTD setting");
2837   /* Ditto for the hash salt */
2838   if (XML_SetHashSalt(g_parser, 0x23456789))
2839     fail("Failed to reject late hash salt change");
2840 
2841   /* Now finish the parse */
2842   if (_XML_Parse_SINGLE_BYTES(g_parser, text2, (int)strlen(text2), XML_TRUE)
2843       == XML_STATUS_ERROR)
2844     xml_failure(g_parser);
2845 }
2846 END_TEST
2847 
2848 /* Test XML_UseForeignDTD with no external subset present */
2849 static int XMLCALL
2850 external_entity_null_loader(XML_Parser parser, const XML_Char *context,
2851                             const XML_Char *base, const XML_Char *systemId,
2852                             const XML_Char *publicId) {
2853   UNUSED_P(parser);
2854   UNUSED_P(context);
2855   UNUSED_P(base);
2856   UNUSED_P(systemId);
2857   UNUSED_P(publicId);
2858   return XML_STATUS_OK;
2859 }
2860 
2861 START_TEST(test_foreign_dtd_without_external_subset) {
2862   const char *text = "<!DOCTYPE doc [<!ENTITY foo 'bar'>]>\n"
2863                      "<doc>&foo;</doc>";
2864 
2865   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
2866   XML_SetUserData(g_parser, NULL);
2867   XML_SetExternalEntityRefHandler(g_parser, external_entity_null_loader);
2868   XML_UseForeignDTD(g_parser, XML_TRUE);
2869   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
2870       == XML_STATUS_ERROR)
2871     xml_failure(g_parser);
2872 }
2873 END_TEST
2874 
2875 START_TEST(test_empty_foreign_dtd) {
2876   const char *text = "<?xml version='1.0' encoding='us-ascii'?>\n"
2877                      "<doc>&entity;</doc>";
2878 
2879   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
2880   XML_SetExternalEntityRefHandler(g_parser, external_entity_null_loader);
2881   XML_UseForeignDTD(g_parser, XML_TRUE);
2882   expect_failure(text, XML_ERROR_UNDEFINED_ENTITY,
2883                  "Undefined entity not faulted");
2884 }
2885 END_TEST
2886 
2887 /* Test XML Base is set and unset appropriately */
2888 START_TEST(test_set_base) {
2889   const XML_Char *old_base;
2890   const XML_Char *new_base = XCS("/local/file/name.xml");
2891 
2892   old_base = XML_GetBase(g_parser);
2893   if (XML_SetBase(g_parser, new_base) != XML_STATUS_OK)
2894     fail("Unable to set base");
2895   if (xcstrcmp(XML_GetBase(g_parser), new_base) != 0)
2896     fail("Base setting not correct");
2897   if (XML_SetBase(g_parser, NULL) != XML_STATUS_OK)
2898     fail("Unable to NULL base");
2899   if (XML_GetBase(g_parser) != NULL)
2900     fail("Base setting not nulled");
2901   XML_SetBase(g_parser, old_base);
2902 }
2903 END_TEST
2904 
2905 /* Test attribute counts, indexing, etc */
2906 typedef struct attrInfo {
2907   const XML_Char *name;
2908   const XML_Char *value;
2909 } AttrInfo;
2910 
2911 typedef struct elementInfo {
2912   const XML_Char *name;
2913   int attr_count;
2914   const XML_Char *id_name;
2915   AttrInfo *attributes;
2916 } ElementInfo;
2917 
2918 static void XMLCALL
2919 counting_start_element_handler(void *userData, const XML_Char *name,
2920                                const XML_Char **atts) {
2921   ElementInfo *info = (ElementInfo *)userData;
2922   AttrInfo *attr;
2923   int count, id, i;
2924 
2925   while (info->name != NULL) {
2926     if (! xcstrcmp(name, info->name))
2927       break;
2928     info++;
2929   }
2930   if (info->name == NULL)
2931     fail("Element not recognised");
2932   /* The attribute count is twice what you might expect.  It is a
2933    * count of items in atts, an array which contains alternating
2934    * attribute names and attribute values.  For the naive user this
2935    * is possibly a little unexpected, but it is what the
2936    * documentation in expat.h tells us to expect.
2937    */
2938   count = XML_GetSpecifiedAttributeCount(g_parser);
2939   if (info->attr_count * 2 != count) {
2940     fail("Not got expected attribute count");
2941     return;
2942   }
2943   id = XML_GetIdAttributeIndex(g_parser);
2944   if (id == -1 && info->id_name != NULL) {
2945     fail("ID not present");
2946     return;
2947   }
2948   if (id != -1 && xcstrcmp(atts[id], info->id_name)) {
2949     fail("ID does not have the correct name");
2950     return;
2951   }
2952   for (i = 0; i < info->attr_count; i++) {
2953     attr = info->attributes;
2954     while (attr->name != NULL) {
2955       if (! xcstrcmp(atts[0], attr->name))
2956         break;
2957       attr++;
2958     }
2959     if (attr->name == NULL) {
2960       fail("Attribute not recognised");
2961       return;
2962     }
2963     if (xcstrcmp(atts[1], attr->value)) {
2964       fail("Attribute has wrong value");
2965       return;
2966     }
2967     /* Remember, two entries in atts per attribute (see above) */
2968     atts += 2;
2969   }
2970 }
2971 
2972 START_TEST(test_attributes) {
2973   const char *text = "<!DOCTYPE doc [\n"
2974                      "<!ELEMENT doc (tag)>\n"
2975                      "<!ATTLIST doc id ID #REQUIRED>\n"
2976                      "]>"
2977                      "<doc a='1' id='one' b='2'>"
2978                      "<tag c='3'/>"
2979                      "</doc>";
2980   AttrInfo doc_info[] = {{XCS("a"), XCS("1")},
2981                          {XCS("b"), XCS("2")},
2982                          {XCS("id"), XCS("one")},
2983                          {NULL, NULL}};
2984   AttrInfo tag_info[] = {{XCS("c"), XCS("3")}, {NULL, NULL}};
2985   ElementInfo info[] = {{XCS("doc"), 3, XCS("id"), NULL},
2986                         {XCS("tag"), 1, NULL, NULL},
2987                         {NULL, 0, NULL, NULL}};
2988   info[0].attributes = doc_info;
2989   info[1].attributes = tag_info;
2990 
2991   XML_SetStartElementHandler(g_parser, counting_start_element_handler);
2992   XML_SetUserData(g_parser, info);
2993   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
2994       == XML_STATUS_ERROR)
2995     xml_failure(g_parser);
2996 }
2997 END_TEST
2998 
2999 /* Test reset works correctly in the middle of processing an internal
3000  * entity.  Exercises some obscure code in XML_ParserReset().
3001  */
3002 START_TEST(test_reset_in_entity) {
3003   const char *text = "<!DOCTYPE doc [\n"
3004                      "<!ENTITY wombat 'wom'>\n"
3005                      "<!ENTITY entity 'hi &wom; there'>\n"
3006                      "]>\n"
3007                      "<doc>&entity;</doc>";
3008   XML_ParsingStatus status;
3009 
3010   resumable = XML_TRUE;
3011   XML_SetCharacterDataHandler(g_parser, clearing_aborting_character_handler);
3012   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_FALSE)
3013       == XML_STATUS_ERROR)
3014     xml_failure(g_parser);
3015   XML_GetParsingStatus(g_parser, &status);
3016   if (status.parsing != XML_SUSPENDED)
3017     fail("Parsing status not SUSPENDED");
3018   XML_ParserReset(g_parser, NULL);
3019   XML_GetParsingStatus(g_parser, &status);
3020   if (status.parsing != XML_INITIALIZED)
3021     fail("Parsing status doesn't reset to INITIALIZED");
3022 }
3023 END_TEST
3024 
3025 /* Test that resume correctly passes through parse errors */
3026 START_TEST(test_resume_invalid_parse) {
3027   const char *text = "<doc>Hello</doc"; /* Missing closing wedge */
3028 
3029   resumable = XML_TRUE;
3030   XML_SetCharacterDataHandler(g_parser, clearing_aborting_character_handler);
3031   if (XML_Parse(g_parser, text, (int)strlen(text), XML_TRUE)
3032       == XML_STATUS_ERROR)
3033     xml_failure(g_parser);
3034   if (XML_ResumeParser(g_parser) == XML_STATUS_OK)
3035     fail("Resumed invalid parse not faulted");
3036   if (XML_GetErrorCode(g_parser) != XML_ERROR_UNCLOSED_TOKEN)
3037     fail("Invalid parse not correctly faulted");
3038 }
3039 END_TEST
3040 
3041 /* Test that re-suspended parses are correctly passed through */
3042 START_TEST(test_resume_resuspended) {
3043   const char *text = "<doc>Hello<meep/>world</doc>";
3044 
3045   resumable = XML_TRUE;
3046   XML_SetCharacterDataHandler(g_parser, clearing_aborting_character_handler);
3047   if (XML_Parse(g_parser, text, (int)strlen(text), XML_TRUE)
3048       == XML_STATUS_ERROR)
3049     xml_failure(g_parser);
3050   resumable = XML_TRUE;
3051   XML_SetCharacterDataHandler(g_parser, clearing_aborting_character_handler);
3052   if (XML_ResumeParser(g_parser) != XML_STATUS_SUSPENDED)
3053     fail("Resumption not suspended");
3054   /* This one should succeed and finish up */
3055   if (XML_ResumeParser(g_parser) != XML_STATUS_OK)
3056     xml_failure(g_parser);
3057 }
3058 END_TEST
3059 
3060 /* Test that CDATA shows up correctly through a default handler */
3061 START_TEST(test_cdata_default) {
3062   const char *text = "<doc><![CDATA[Hello\nworld]]></doc>";
3063   const XML_Char *expected = XCS("<doc><![CDATA[Hello\nworld]]></doc>");
3064   CharData storage;
3065 
3066   CharData_Init(&storage);
3067   XML_SetUserData(g_parser, &storage);
3068   XML_SetDefaultHandler(g_parser, accumulate_characters);
3069 
3070   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
3071       == XML_STATUS_ERROR)
3072     xml_failure(g_parser);
3073   CharData_CheckXMLChars(&storage, expected);
3074 }
3075 END_TEST
3076 
3077 /* Test resetting a subordinate parser does exactly nothing */
3078 static int XMLCALL
3079 external_entity_resetter(XML_Parser parser, const XML_Char *context,
3080                          const XML_Char *base, const XML_Char *systemId,
3081                          const XML_Char *publicId) {
3082   const char *text = "<!ELEMENT doc (#PCDATA)*>";
3083   XML_Parser ext_parser;
3084   XML_ParsingStatus status;
3085 
3086   UNUSED_P(base);
3087   UNUSED_P(systemId);
3088   UNUSED_P(publicId);
3089   ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
3090   if (ext_parser == NULL)
3091     fail("Could not create external entity parser");
3092   XML_GetParsingStatus(ext_parser, &status);
3093   if (status.parsing != XML_INITIALIZED) {
3094     fail("Parsing status is not INITIALIZED");
3095     return XML_STATUS_ERROR;
3096   }
3097   if (_XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE)
3098       == XML_STATUS_ERROR) {
3099     xml_failure(parser);
3100     return XML_STATUS_ERROR;
3101   }
3102   XML_GetParsingStatus(ext_parser, &status);
3103   if (status.parsing != XML_FINISHED) {
3104     fail("Parsing status is not FINISHED");
3105     return XML_STATUS_ERROR;
3106   }
3107   /* Check we can't parse here */
3108   if (XML_Parse(ext_parser, text, (int)strlen(text), XML_TRUE)
3109       != XML_STATUS_ERROR)
3110     fail("Parsing when finished not faulted");
3111   if (XML_GetErrorCode(ext_parser) != XML_ERROR_FINISHED)
3112     fail("Parsing when finished faulted with wrong code");
3113   XML_ParserReset(ext_parser, NULL);
3114   XML_GetParsingStatus(ext_parser, &status);
3115   if (status.parsing != XML_FINISHED) {
3116     fail("Parsing status not still FINISHED");
3117     return XML_STATUS_ERROR;
3118   }
3119   XML_ParserFree(ext_parser);
3120   return XML_STATUS_OK;
3121 }
3122 
3123 START_TEST(test_subordinate_reset) {
3124   const char *text = "<?xml version='1.0' encoding='us-ascii'?>\n"
3125                      "<!DOCTYPE doc SYSTEM 'foo'>\n"
3126                      "<doc>&entity;</doc>";
3127 
3128   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
3129   XML_SetExternalEntityRefHandler(g_parser, external_entity_resetter);
3130   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
3131       == XML_STATUS_ERROR)
3132     xml_failure(g_parser);
3133 }
3134 END_TEST
3135 
3136 /* Test suspending a subordinate parser */
3137 
3138 static void XMLCALL
3139 entity_suspending_decl_handler(void *userData, const XML_Char *name,
3140                                XML_Content *model) {
3141   XML_Parser ext_parser = (XML_Parser)userData;
3142 
3143   UNUSED_P(name);
3144   if (XML_StopParser(ext_parser, XML_TRUE) != XML_STATUS_ERROR)
3145     fail("Attempting to suspend a subordinate parser not faulted");
3146   if (XML_GetErrorCode(ext_parser) != XML_ERROR_SUSPEND_PE)
3147     fail("Suspending subordinate parser get wrong code");
3148   XML_SetElementDeclHandler(ext_parser, NULL);
3149   XML_FreeContentModel(g_parser, model);
3150 }
3151 
3152 static int XMLCALL
3153 external_entity_suspender(XML_Parser parser, const XML_Char *context,
3154                           const XML_Char *base, const XML_Char *systemId,
3155                           const XML_Char *publicId) {
3156   const char *text = "<!ELEMENT doc (#PCDATA)*>";
3157   XML_Parser ext_parser;
3158 
3159   UNUSED_P(base);
3160   UNUSED_P(systemId);
3161   UNUSED_P(publicId);
3162   ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
3163   if (ext_parser == NULL)
3164     fail("Could not create external entity parser");
3165   XML_SetElementDeclHandler(ext_parser, entity_suspending_decl_handler);
3166   XML_SetUserData(ext_parser, ext_parser);
3167   if (_XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE)
3168       == XML_STATUS_ERROR) {
3169     xml_failure(ext_parser);
3170     return XML_STATUS_ERROR;
3171   }
3172   XML_ParserFree(ext_parser);
3173   return XML_STATUS_OK;
3174 }
3175 
3176 START_TEST(test_subordinate_suspend) {
3177   const char *text = "<?xml version='1.0' encoding='us-ascii'?>\n"
3178                      "<!DOCTYPE doc SYSTEM 'foo'>\n"
3179                      "<doc>&entity;</doc>";
3180 
3181   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
3182   XML_SetExternalEntityRefHandler(g_parser, external_entity_suspender);
3183   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
3184       == XML_STATUS_ERROR)
3185     xml_failure(g_parser);
3186 }
3187 END_TEST
3188 
3189 /* Test suspending a subordinate parser from an XML declaration */
3190 /* Increases code coverage of the tests */
3191 static void XMLCALL
3192 entity_suspending_xdecl_handler(void *userData, const XML_Char *version,
3193                                 const XML_Char *encoding, int standalone) {
3194   XML_Parser ext_parser = (XML_Parser)userData;
3195 
3196   UNUSED_P(version);
3197   UNUSED_P(encoding);
3198   UNUSED_P(standalone);
3199   XML_StopParser(ext_parser, resumable);
3200   XML_SetXmlDeclHandler(ext_parser, NULL);
3201 }
3202 
3203 static int XMLCALL
3204 external_entity_suspend_xmldecl(XML_Parser parser, const XML_Char *context,
3205                                 const XML_Char *base, const XML_Char *systemId,
3206                                 const XML_Char *publicId) {
3207   const char *text = "<?xml version='1.0' encoding='us-ascii'?>";
3208   XML_Parser ext_parser;
3209   XML_ParsingStatus status;
3210   enum XML_Status rc;
3211 
3212   UNUSED_P(base);
3213   UNUSED_P(systemId);
3214   UNUSED_P(publicId);
3215   ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
3216   if (ext_parser == NULL)
3217     fail("Could not create external entity parser");
3218   XML_SetXmlDeclHandler(ext_parser, entity_suspending_xdecl_handler);
3219   XML_SetUserData(ext_parser, ext_parser);
3220   rc = _XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE);
3221   XML_GetParsingStatus(ext_parser, &status);
3222   if (resumable) {
3223     if (rc == XML_STATUS_ERROR)
3224       xml_failure(ext_parser);
3225     if (status.parsing != XML_SUSPENDED)
3226       fail("Ext Parsing status not SUSPENDED");
3227   } else {
3228     if (rc != XML_STATUS_ERROR)
3229       fail("Ext parsing not aborted");
3230     if (XML_GetErrorCode(ext_parser) != XML_ERROR_ABORTED)
3231       xml_failure(ext_parser);
3232     if (status.parsing != XML_FINISHED)
3233       fail("Ext Parsing status not FINISHED");
3234   }
3235 
3236   XML_ParserFree(ext_parser);
3237   return XML_STATUS_OK;
3238 }
3239 
3240 START_TEST(test_subordinate_xdecl_suspend) {
3241   const char *text
3242       = "<!DOCTYPE doc [\n"
3243         "  <!ENTITY entity SYSTEM 'http://example.org/dummy.ent'>\n"
3244         "]>\n"
3245         "<doc>&entity;</doc>";
3246 
3247   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
3248   XML_SetExternalEntityRefHandler(g_parser, external_entity_suspend_xmldecl);
3249   resumable = XML_TRUE;
3250   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
3251       == XML_STATUS_ERROR)
3252     xml_failure(g_parser);
3253 }
3254 END_TEST
3255 
3256 START_TEST(test_subordinate_xdecl_abort) {
3257   const char *text
3258       = "<!DOCTYPE doc [\n"
3259         "  <!ENTITY entity SYSTEM 'http://example.org/dummy.ent'>\n"
3260         "]>\n"
3261         "<doc>&entity;</doc>";
3262 
3263   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
3264   XML_SetExternalEntityRefHandler(g_parser, external_entity_suspend_xmldecl);
3265   resumable = XML_FALSE;
3266   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
3267       == XML_STATUS_ERROR)
3268     xml_failure(g_parser);
3269 }
3270 END_TEST
3271 
3272 /* Test external entity fault handling with suspension */
3273 static int XMLCALL
3274 external_entity_suspending_faulter(XML_Parser parser, const XML_Char *context,
3275                                    const XML_Char *base,
3276                                    const XML_Char *systemId,
3277                                    const XML_Char *publicId) {
3278   XML_Parser ext_parser;
3279   ExtFaults *fault = (ExtFaults *)XML_GetUserData(parser);
3280   void *buffer;
3281   int parse_len = (int)strlen(fault->parse_text);
3282 
3283   UNUSED_P(base);
3284   UNUSED_P(systemId);
3285   UNUSED_P(publicId);
3286   ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
3287   if (ext_parser == NULL)
3288     fail("Could not create external entity parser");
3289   XML_SetXmlDeclHandler(ext_parser, entity_suspending_xdecl_handler);
3290   XML_SetUserData(ext_parser, ext_parser);
3291   resumable = XML_TRUE;
3292   buffer = XML_GetBuffer(ext_parser, parse_len);
3293   if (buffer == NULL)
3294     fail("Could not allocate parse buffer");
3295   assert(buffer != NULL);
3296   memcpy(buffer, fault->parse_text, parse_len);
3297   if (XML_ParseBuffer(ext_parser, parse_len, XML_FALSE) != XML_STATUS_SUSPENDED)
3298     fail("XML declaration did not suspend");
3299   if (XML_ResumeParser(ext_parser) != XML_STATUS_OK)
3300     xml_failure(ext_parser);
3301   if (XML_ParseBuffer(ext_parser, 0, XML_TRUE) != XML_STATUS_ERROR)
3302     fail(fault->fail_text);
3303   if (XML_GetErrorCode(ext_parser) != fault->error)
3304     xml_failure(ext_parser);
3305 
3306   XML_ParserFree(ext_parser);
3307   return XML_STATUS_ERROR;
3308 }
3309 
3310 START_TEST(test_ext_entity_invalid_suspended_parse) {
3311   const char *text = "<!DOCTYPE doc [\n"
3312                      "  <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n"
3313                      "]>\n"
3314                      "<doc>&en;</doc>";
3315   ExtFaults faults[]
3316       = {{"<?xml version='1.0' encoding='us-ascii'?><",
3317           "Incomplete element declaration not faulted", NULL,
3318           XML_ERROR_UNCLOSED_TOKEN},
3319          {/* First two bytes of a three-byte char */
3320           "<?xml version='1.0' encoding='utf-8'?>\xe2\x82",
3321           "Incomplete character not faulted", NULL, XML_ERROR_PARTIAL_CHAR},
3322          {NULL, NULL, NULL, XML_ERROR_NONE}};
3323   ExtFaults *fault;
3324 
3325   for (fault = &faults[0]; fault->parse_text != NULL; fault++) {
3326     XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
3327     XML_SetExternalEntityRefHandler(g_parser,
3328                                     external_entity_suspending_faulter);
3329     XML_SetUserData(g_parser, fault);
3330     expect_failure(text, XML_ERROR_EXTERNAL_ENTITY_HANDLING,
3331                    "Parser did not report external entity error");
3332     XML_ParserReset(g_parser, NULL);
3333   }
3334 }
3335 END_TEST
3336 
3337 /* Test setting an explicit encoding */
3338 START_TEST(test_explicit_encoding) {
3339   const char *text1 = "<doc>Hello ";
3340   const char *text2 = " World</doc>";
3341 
3342   /* Just check that we can set the encoding to NULL before starting */
3343   if (XML_SetEncoding(g_parser, NULL) != XML_STATUS_OK)
3344     fail("Failed to initialise encoding to NULL");
3345   /* Say we are UTF-8 */
3346   if (XML_SetEncoding(g_parser, XCS("utf-8")) != XML_STATUS_OK)
3347     fail("Failed to set explicit encoding");
3348   if (_XML_Parse_SINGLE_BYTES(g_parser, text1, (int)strlen(text1), XML_FALSE)
3349       == XML_STATUS_ERROR)
3350     xml_failure(g_parser);
3351   /* Try to switch encodings mid-parse */
3352   if (XML_SetEncoding(g_parser, XCS("us-ascii")) != XML_STATUS_ERROR)
3353     fail("Allowed encoding change");
3354   if (_XML_Parse_SINGLE_BYTES(g_parser, text2, (int)strlen(text2), XML_TRUE)
3355       == XML_STATUS_ERROR)
3356     xml_failure(g_parser);
3357   /* Try now the parse is over */
3358   if (XML_SetEncoding(g_parser, NULL) != XML_STATUS_OK)
3359     fail("Failed to unset encoding");
3360 }
3361 END_TEST
3362 
3363 /* Test handling of trailing CR (rather than newline) */
3364 static void XMLCALL
3365 cr_cdata_handler(void *userData, const XML_Char *s, int len) {
3366   int *pfound = (int *)userData;
3367 
3368   /* Internal processing turns the CR into a newline for the
3369    * character data handler, but not for the default handler
3370    */
3371   if (len == 1 && (*s == XCS('\n') || *s == XCS('\r')))
3372     *pfound = 1;
3373 }
3374 
3375 START_TEST(test_trailing_cr) {
3376   const char *text = "<doc>\r";
3377   int found_cr;
3378 
3379   /* Try with a character handler, for code coverage */
3380   XML_SetCharacterDataHandler(g_parser, cr_cdata_handler);
3381   XML_SetUserData(g_parser, &found_cr);
3382   found_cr = 0;
3383   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
3384       == XML_STATUS_OK)
3385     fail("Failed to fault unclosed doc");
3386   if (found_cr == 0)
3387     fail("Did not catch the carriage return");
3388   XML_ParserReset(g_parser, NULL);
3389 
3390   /* Now with a default handler instead */
3391   XML_SetDefaultHandler(g_parser, cr_cdata_handler);
3392   XML_SetUserData(g_parser, &found_cr);
3393   found_cr = 0;
3394   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
3395       == XML_STATUS_OK)
3396     fail("Failed to fault unclosed doc");
3397   if (found_cr == 0)
3398     fail("Did not catch default carriage return");
3399 }
3400 END_TEST
3401 
3402 /* Test trailing CR in an external entity parse */
3403 static int XMLCALL
3404 external_entity_cr_catcher(XML_Parser parser, const XML_Char *context,
3405                            const XML_Char *base, const XML_Char *systemId,
3406                            const XML_Char *publicId) {
3407   const char *text = "\r";
3408   XML_Parser ext_parser;
3409 
3410   UNUSED_P(base);
3411   UNUSED_P(systemId);
3412   UNUSED_P(publicId);
3413   ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
3414   if (ext_parser == NULL)
3415     fail("Could not create external entity parser");
3416   XML_SetCharacterDataHandler(ext_parser, cr_cdata_handler);
3417   if (_XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE)
3418       == XML_STATUS_ERROR)
3419     xml_failure(ext_parser);
3420   XML_ParserFree(ext_parser);
3421   return XML_STATUS_OK;
3422 }
3423 
3424 static int XMLCALL
3425 external_entity_bad_cr_catcher(XML_Parser parser, const XML_Char *context,
3426                                const XML_Char *base, const XML_Char *systemId,
3427                                const XML_Char *publicId) {
3428   const char *text = "<tag>\r";
3429   XML_Parser ext_parser;
3430 
3431   UNUSED_P(base);
3432   UNUSED_P(systemId);
3433   UNUSED_P(publicId);
3434   ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
3435   if (ext_parser == NULL)
3436     fail("Could not create external entity parser");
3437   XML_SetCharacterDataHandler(ext_parser, cr_cdata_handler);
3438   if (_XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE)
3439       == XML_STATUS_OK)
3440     fail("Async entity error not caught");
3441   if (XML_GetErrorCode(ext_parser) != XML_ERROR_ASYNC_ENTITY)
3442     xml_failure(ext_parser);
3443   XML_ParserFree(ext_parser);
3444   return XML_STATUS_OK;
3445 }
3446 
3447 START_TEST(test_ext_entity_trailing_cr) {
3448   const char *text = "<!DOCTYPE doc [\n"
3449                      "  <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n"
3450                      "]>\n"
3451                      "<doc>&en;</doc>";
3452   int found_cr;
3453 
3454   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
3455   XML_SetExternalEntityRefHandler(g_parser, external_entity_cr_catcher);
3456   XML_SetUserData(g_parser, &found_cr);
3457   found_cr = 0;
3458   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
3459       != XML_STATUS_OK)
3460     xml_failure(g_parser);
3461   if (found_cr == 0)
3462     fail("No carriage return found");
3463   XML_ParserReset(g_parser, NULL);
3464 
3465   /* Try again with a different trailing CR */
3466   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
3467   XML_SetExternalEntityRefHandler(g_parser, external_entity_bad_cr_catcher);
3468   XML_SetUserData(g_parser, &found_cr);
3469   found_cr = 0;
3470   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
3471       != XML_STATUS_OK)
3472     xml_failure(g_parser);
3473   if (found_cr == 0)
3474     fail("No carriage return found");
3475 }
3476 END_TEST
3477 
3478 /* Test handling of trailing square bracket */
3479 static void XMLCALL
3480 rsqb_handler(void *userData, const XML_Char *s, int len) {
3481   int *pfound = (int *)userData;
3482 
3483   if (len == 1 && *s == XCS(']'))
3484     *pfound = 1;
3485 }
3486 
3487 START_TEST(test_trailing_rsqb) {
3488   const char *text8 = "<doc>]";
3489   const char text16[] = "\xFF\xFE<\000d\000o\000c\000>\000]\000";
3490   int found_rsqb;
3491   int text8_len = (int)strlen(text8);
3492 
3493   XML_SetCharacterDataHandler(g_parser, rsqb_handler);
3494   XML_SetUserData(g_parser, &found_rsqb);
3495   found_rsqb = 0;
3496   if (_XML_Parse_SINGLE_BYTES(g_parser, text8, text8_len, XML_TRUE)
3497       == XML_STATUS_OK)
3498     fail("Failed to fault unclosed doc");
3499   if (found_rsqb == 0)
3500     fail("Did not catch the right square bracket");
3501 
3502   /* Try again with a different encoding */
3503   XML_ParserReset(g_parser, NULL);
3504   XML_SetCharacterDataHandler(g_parser, rsqb_handler);
3505   XML_SetUserData(g_parser, &found_rsqb);
3506   found_rsqb = 0;
3507   if (_XML_Parse_SINGLE_BYTES(g_parser, text16, (int)sizeof(text16) - 1,
3508                               XML_TRUE)
3509       == XML_STATUS_OK)
3510     fail("Failed to fault unclosed doc");
3511   if (found_rsqb == 0)
3512     fail("Did not catch the right square bracket");
3513 
3514   /* And finally with a default handler */
3515   XML_ParserReset(g_parser, NULL);
3516   XML_SetDefaultHandler(g_parser, rsqb_handler);
3517   XML_SetUserData(g_parser, &found_rsqb);
3518   found_rsqb = 0;
3519   if (_XML_Parse_SINGLE_BYTES(g_parser, text16, (int)sizeof(text16) - 1,
3520                               XML_TRUE)
3521       == XML_STATUS_OK)
3522     fail("Failed to fault unclosed doc");
3523   if (found_rsqb == 0)
3524     fail("Did not catch the right square bracket");
3525 }
3526 END_TEST
3527 
3528 /* Test trailing right square bracket in an external entity parse */
3529 static int XMLCALL
3530 external_entity_rsqb_catcher(XML_Parser parser, const XML_Char *context,
3531                              const XML_Char *base, const XML_Char *systemId,
3532                              const XML_Char *publicId) {
3533   const char *text = "<tag>]";
3534   XML_Parser ext_parser;
3535 
3536   UNUSED_P(base);
3537   UNUSED_P(systemId);
3538   UNUSED_P(publicId);
3539   ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
3540   if (ext_parser == NULL)
3541     fail("Could not create external entity parser");
3542   XML_SetCharacterDataHandler(ext_parser, rsqb_handler);
3543   if (_XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE)
3544       != XML_STATUS_ERROR)
3545     fail("Async entity error not caught");
3546   if (XML_GetErrorCode(ext_parser) != XML_ERROR_ASYNC_ENTITY)
3547     xml_failure(ext_parser);
3548   XML_ParserFree(ext_parser);
3549   return XML_STATUS_OK;
3550 }
3551 
3552 START_TEST(test_ext_entity_trailing_rsqb) {
3553   const char *text = "<!DOCTYPE doc [\n"
3554                      "  <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n"
3555                      "]>\n"
3556                      "<doc>&en;</doc>";
3557   int found_rsqb;
3558 
3559   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
3560   XML_SetExternalEntityRefHandler(g_parser, external_entity_rsqb_catcher);
3561   XML_SetUserData(g_parser, &found_rsqb);
3562   found_rsqb = 0;
3563   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
3564       != XML_STATUS_OK)
3565     xml_failure(g_parser);
3566   if (found_rsqb == 0)
3567     fail("No right square bracket found");
3568 }
3569 END_TEST
3570 
3571 /* Test CDATA handling in an external entity */
3572 static int XMLCALL
3573 external_entity_good_cdata_ascii(XML_Parser parser, const XML_Char *context,
3574                                  const XML_Char *base, const XML_Char *systemId,
3575                                  const XML_Char *publicId) {
3576   const char *text = "<a><![CDATA[<greeting>Hello, world!</greeting>]]></a>";
3577   const XML_Char *expected = XCS("<greeting>Hello, world!</greeting>");
3578   CharData storage;
3579   XML_Parser ext_parser;
3580 
3581   UNUSED_P(base);
3582   UNUSED_P(systemId);
3583   UNUSED_P(publicId);
3584   CharData_Init(&storage);
3585   ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
3586   if (ext_parser == NULL)
3587     fail("Could not create external entity parser");
3588   XML_SetUserData(ext_parser, &storage);
3589   XML_SetCharacterDataHandler(ext_parser, accumulate_characters);
3590 
3591   if (_XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE)
3592       == XML_STATUS_ERROR)
3593     xml_failure(ext_parser);
3594   CharData_CheckXMLChars(&storage, expected);
3595 
3596   XML_ParserFree(ext_parser);
3597   return XML_STATUS_OK;
3598 }
3599 
3600 START_TEST(test_ext_entity_good_cdata) {
3601   const char *text = "<!DOCTYPE doc [\n"
3602                      "  <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n"
3603                      "]>\n"
3604                      "<doc>&en;</doc>";
3605 
3606   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
3607   XML_SetExternalEntityRefHandler(g_parser, external_entity_good_cdata_ascii);
3608   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
3609       != XML_STATUS_OK)
3610     xml_failure(g_parser);
3611 }
3612 END_TEST
3613 
3614 /* Test user parameter settings */
3615 /* Variable holding the expected handler userData */
3616 static void *handler_data = NULL;
3617 /* Count of the number of times the comment handler has been invoked */
3618 static int comment_count = 0;
3619 /* Count of the number of skipped entities */
3620 static int skip_count = 0;
3621 /* Count of the number of times the XML declaration handler is invoked */
3622 static int xdecl_count = 0;
3623 
3624 static void XMLCALL
3625 xml_decl_handler(void *userData, const XML_Char *version,
3626                  const XML_Char *encoding, int standalone) {
3627   UNUSED_P(version);
3628   UNUSED_P(encoding);
3629   if (userData != handler_data)
3630     fail("User data (xml decl) not correctly set");
3631   if (standalone != -1)
3632     fail("Standalone not flagged as not present in XML decl");
3633   xdecl_count++;
3634 }
3635 
3636 static void XMLCALL
3637 param_check_skip_handler(void *userData, const XML_Char *entityName,
3638                          int is_parameter_entity) {
3639   UNUSED_P(entityName);
3640   UNUSED_P(is_parameter_entity);
3641   if (userData != handler_data)
3642     fail("User data (skip) not correctly set");
3643   skip_count++;
3644 }
3645 
3646 static void XMLCALL
3647 data_check_comment_handler(void *userData, const XML_Char *data) {
3648   UNUSED_P(data);
3649   /* Check that the userData passed through is what we expect */
3650   if (userData != handler_data)
3651     fail("User data (parser) not correctly set");
3652   /* Check that the user data in the parser is appropriate */
3653   if (XML_GetUserData(userData) != (void *)1)
3654     fail("User data in parser not correctly set");
3655   comment_count++;
3656 }
3657 
3658 static int XMLCALL
3659 external_entity_param_checker(XML_Parser parser, const XML_Char *context,
3660                               const XML_Char *base, const XML_Char *systemId,
3661                               const XML_Char *publicId) {
3662   const char *text = "<!-- Subordinate parser -->\n"
3663                      "<!ELEMENT doc (#PCDATA)*>";
3664   XML_Parser ext_parser;
3665 
3666   UNUSED_P(base);
3667   UNUSED_P(systemId);
3668   UNUSED_P(publicId);
3669   ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
3670   if (ext_parser == NULL)
3671     fail("Could not create external entity parser");
3672   handler_data = ext_parser;
3673   if (_XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE)
3674       == XML_STATUS_ERROR) {
3675     xml_failure(parser);
3676     return XML_STATUS_ERROR;
3677   }
3678   handler_data = parser;
3679   XML_ParserFree(ext_parser);
3680   return XML_STATUS_OK;
3681 }
3682 
3683 START_TEST(test_user_parameters) {
3684   const char *text = "<?xml version='1.0' encoding='us-ascii'?>\n"
3685                      "<!-- Primary parse -->\n"
3686                      "<!DOCTYPE doc SYSTEM 'foo'>\n"
3687                      "<doc>&entity;";
3688   const char *epilog = "<!-- Back to primary parser -->\n"
3689                        "</doc>";
3690 
3691   comment_count = 0;
3692   skip_count = 0;
3693   xdecl_count = 0;
3694   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
3695   XML_SetXmlDeclHandler(g_parser, xml_decl_handler);
3696   XML_SetExternalEntityRefHandler(g_parser, external_entity_param_checker);
3697   XML_SetCommentHandler(g_parser, data_check_comment_handler);
3698   XML_SetSkippedEntityHandler(g_parser, param_check_skip_handler);
3699   XML_UseParserAsHandlerArg(g_parser);
3700   XML_SetUserData(g_parser, (void *)1);
3701   handler_data = g_parser;
3702   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_FALSE)
3703       == XML_STATUS_ERROR)
3704     xml_failure(g_parser);
3705   if (comment_count != 2)
3706     fail("Comment handler not invoked enough times");
3707   /* Ensure we can't change policy mid-parse */
3708   if (XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_NEVER))
3709     fail("Changed param entity parsing policy while parsing");
3710   if (_XML_Parse_SINGLE_BYTES(g_parser, epilog, (int)strlen(epilog), XML_TRUE)
3711       == XML_STATUS_ERROR)
3712     xml_failure(g_parser);
3713   if (comment_count != 3)
3714     fail("Comment handler not invoked enough times");
3715   if (skip_count != 1)
3716     fail("Skip handler not invoked enough times");
3717   if (xdecl_count != 1)
3718     fail("XML declaration handler not invoked");
3719 }
3720 END_TEST
3721 
3722 /* Test that an explicit external entity handler argument replaces
3723  * the parser as the first argument.
3724  *
3725  * We do not call the first parameter to the external entity handler
3726  * 'parser' for once, since the first time the handler is called it
3727  * will actually be a text string.  We need to be able to access the
3728  * global 'parser' variable to create our external entity parser from,
3729  * since there are code paths we need to ensure get executed.
3730  */
3731 static int XMLCALL
3732 external_entity_ref_param_checker(XML_Parser parameter, const XML_Char *context,
3733                                   const XML_Char *base,
3734                                   const XML_Char *systemId,
3735                                   const XML_Char *publicId) {
3736   const char *text = "<!ELEMENT doc (#PCDATA)*>";
3737   XML_Parser ext_parser;
3738 
3739   UNUSED_P(base);
3740   UNUSED_P(systemId);
3741   UNUSED_P(publicId);
3742   if ((void *)parameter != handler_data)
3743     fail("External entity ref handler parameter not correct");
3744 
3745   /* Here we use the global 'parser' variable */
3746   ext_parser = XML_ExternalEntityParserCreate(g_parser, context, NULL);
3747   if (ext_parser == NULL)
3748     fail("Could not create external entity parser");
3749   if (_XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE)
3750       == XML_STATUS_ERROR)
3751     xml_failure(ext_parser);
3752 
3753   XML_ParserFree(ext_parser);
3754   return XML_STATUS_OK;
3755 }
3756 
3757 START_TEST(test_ext_entity_ref_parameter) {
3758   const char *text = "<?xml version='1.0' encoding='us-ascii'?>\n"
3759                      "<!DOCTYPE doc SYSTEM 'foo'>\n"
3760                      "<doc>&entity;</doc>";
3761 
3762   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
3763   XML_SetExternalEntityRefHandler(g_parser, external_entity_ref_param_checker);
3764   /* Set a handler arg that is not NULL and not parser (which is
3765    * what NULL would cause to be passed.
3766    */
3767   XML_SetExternalEntityRefHandlerArg(g_parser, (void *)text);
3768   handler_data = (void *)text;
3769   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
3770       == XML_STATUS_ERROR)
3771     xml_failure(g_parser);
3772 
3773   /* Now try again with unset args */
3774   XML_ParserReset(g_parser, NULL);
3775   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
3776   XML_SetExternalEntityRefHandler(g_parser, external_entity_ref_param_checker);
3777   XML_SetExternalEntityRefHandlerArg(g_parser, NULL);
3778   handler_data = (void *)g_parser;
3779   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
3780       == XML_STATUS_ERROR)
3781     xml_failure(g_parser);
3782 }
3783 END_TEST
3784 
3785 /* Test the parsing of an empty string */
3786 START_TEST(test_empty_parse) {
3787   const char *text = "<doc></doc>";
3788   const char *partial = "<doc>";
3789 
3790   if (XML_Parse(g_parser, NULL, 0, XML_FALSE) == XML_STATUS_ERROR)
3791     fail("Parsing empty string faulted");
3792   if (XML_Parse(g_parser, NULL, 0, XML_TRUE) != XML_STATUS_ERROR)
3793     fail("Parsing final empty string not faulted");
3794   if (XML_GetErrorCode(g_parser) != XML_ERROR_NO_ELEMENTS)
3795     fail("Parsing final empty string faulted for wrong reason");
3796 
3797   /* Now try with valid text before the empty end */
3798   XML_ParserReset(g_parser, NULL);
3799   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_FALSE)
3800       == XML_STATUS_ERROR)
3801     xml_failure(g_parser);
3802   if (XML_Parse(g_parser, NULL, 0, XML_TRUE) == XML_STATUS_ERROR)
3803     fail("Parsing final empty string faulted");
3804 
3805   /* Now try with invalid text before the empty end */
3806   XML_ParserReset(g_parser, NULL);
3807   if (_XML_Parse_SINGLE_BYTES(g_parser, partial, (int)strlen(partial),
3808                               XML_FALSE)
3809       == XML_STATUS_ERROR)
3810     xml_failure(g_parser);
3811   if (XML_Parse(g_parser, NULL, 0, XML_TRUE) != XML_STATUS_ERROR)
3812     fail("Parsing final incomplete empty string not faulted");
3813 }
3814 END_TEST
3815 
3816 /* Test odd corners of the XML_GetBuffer interface */
3817 static enum XML_Status
3818 get_feature(enum XML_FeatureEnum feature_id, long *presult) {
3819   const XML_Feature *feature = XML_GetFeatureList();
3820 
3821   if (feature == NULL)
3822     return XML_STATUS_ERROR;
3823   for (; feature->feature != XML_FEATURE_END; feature++) {
3824     if (feature->feature == feature_id) {
3825       *presult = feature->value;
3826       return XML_STATUS_OK;
3827     }
3828   }
3829   return XML_STATUS_ERROR;
3830 }
3831 
3832 /* Having an element name longer than 1024 characters exercises some
3833  * of the pool allocation code in the parser that otherwise does not
3834  * get executed.  The count at the end of the line is the number of
3835  * characters (bytes) in the element name by that point.x
3836  */
3837 static const char *get_buffer_test_text
3838     = "<documentwitharidiculouslylongelementnametotease"  /* 0x030 */
3839       "aparticularcorneroftheallocationinXML_GetBuffers"  /* 0x060 */
3840       "othatwecanimprovethecoverageyetagain012345678901"  /* 0x090 */
3841       "123456789abcdef0123456789abcdef0123456789abcdef0"  /* 0x0c0 */
3842       "123456789abcdef0123456789abcdef0123456789abcdef0"  /* 0x0f0 */
3843       "123456789abcdef0123456789abcdef0123456789abcdef0"  /* 0x120 */
3844       "123456789abcdef0123456789abcdef0123456789abcdef0"  /* 0x150 */
3845       "123456789abcdef0123456789abcdef0123456789abcdef0"  /* 0x180 */
3846       "123456789abcdef0123456789abcdef0123456789abcdef0"  /* 0x1b0 */
3847       "123456789abcdef0123456789abcdef0123456789abcdef0"  /* 0x1e0 */
3848       "123456789abcdef0123456789abcdef0123456789abcdef0"  /* 0x210 */
3849       "123456789abcdef0123456789abcdef0123456789abcdef0"  /* 0x240 */
3850       "123456789abcdef0123456789abcdef0123456789abcdef0"  /* 0x270 */
3851       "123456789abcdef0123456789abcdef0123456789abcdef0"  /* 0x2a0 */
3852       "123456789abcdef0123456789abcdef0123456789abcdef0"  /* 0x2d0 */
3853       "123456789abcdef0123456789abcdef0123456789abcdef0"  /* 0x300 */
3854       "123456789abcdef0123456789abcdef0123456789abcdef0"  /* 0x330 */
3855       "123456789abcdef0123456789abcdef0123456789abcdef0"  /* 0x360 */
3856       "123456789abcdef0123456789abcdef0123456789abcdef0"  /* 0x390 */
3857       "123456789abcdef0123456789abcdef0123456789abcdef0"  /* 0x3c0 */
3858       "123456789abcdef0123456789abcdef0123456789abcdef0"  /* 0x3f0 */
3859       "123456789abcdef0123456789abcdef0123456789>\n<ef0"; /* 0x420 */
3860 
3861 /* Test odd corners of the XML_GetBuffer interface */
3862 START_TEST(test_get_buffer_1) {
3863   const char *text = get_buffer_test_text;
3864   void *buffer;
3865   long context_bytes;
3866 
3867   /* Attempt to allocate a negative length buffer */
3868   if (XML_GetBuffer(g_parser, -12) != NULL)
3869     fail("Negative length buffer not failed");
3870 
3871   /* Now get a small buffer and extend it past valid length */
3872   buffer = XML_GetBuffer(g_parser, 1536);
3873   if (buffer == NULL)
3874     fail("1.5K buffer failed");
3875   assert(buffer != NULL);
3876   memcpy(buffer, text, strlen(text));
3877   if (XML_ParseBuffer(g_parser, (int)strlen(text), XML_FALSE)
3878       == XML_STATUS_ERROR)
3879     xml_failure(g_parser);
3880   if (XML_GetBuffer(g_parser, INT_MAX) != NULL)
3881     fail("INT_MAX buffer not failed");
3882 
3883   /* Now try extending it a more reasonable but still too large
3884    * amount.  The allocator in XML_GetBuffer() doubles the buffer
3885    * size until it exceeds the requested amount or INT_MAX.  If it
3886    * exceeds INT_MAX, it rejects the request, so we want a request
3887    * between INT_MAX and INT_MAX/2.  A gap of 1K seems comfortable,
3888    * with an extra byte just to ensure that the request is off any
3889    * boundary.  The request will be inflated internally by
3890    * XML_CONTEXT_BYTES (if defined), so we subtract that from our
3891    * request.
3892    */
3893   if (get_feature(XML_FEATURE_CONTEXT_BYTES, &context_bytes) != XML_STATUS_OK)
3894     context_bytes = 0;
3895   if (XML_GetBuffer(g_parser, INT_MAX - (context_bytes + 1025)) != NULL)
3896     fail("INT_MAX- buffer not failed");
3897 
3898   /* Now try extending it a carefully crafted amount */
3899   if (XML_GetBuffer(g_parser, 1000) == NULL)
3900     fail("1000 buffer failed");
3901 }
3902 END_TEST
3903 
3904 /* Test more corners of the XML_GetBuffer interface */
3905 START_TEST(test_get_buffer_2) {
3906   const char *text = get_buffer_test_text;
3907   void *buffer;
3908 
3909   /* Now get a decent buffer */
3910   buffer = XML_GetBuffer(g_parser, 1536);
3911   if (buffer == NULL)
3912     fail("1.5K buffer failed");
3913   assert(buffer != NULL);
3914   memcpy(buffer, text, strlen(text));
3915   if (XML_ParseBuffer(g_parser, (int)strlen(text), XML_FALSE)
3916       == XML_STATUS_ERROR)
3917     xml_failure(g_parser);
3918 
3919   /* Extend it, to catch a different code path */
3920   if (XML_GetBuffer(g_parser, 1024) == NULL)
3921     fail("1024 buffer failed");
3922 }
3923 END_TEST
3924 
3925 /* Test for signed integer overflow CVE-2022-23852 */
3926 #if defined(XML_CONTEXT_BYTES)
3927 START_TEST(test_get_buffer_3_overflow) {
3928   XML_Parser parser = XML_ParserCreate(NULL);
3929   assert(parser != NULL);
3930 
3931   const char *const text = "\n";
3932   const int expectedKeepValue = (int)strlen(text);
3933 
3934   // After this call, variable "keep" in XML_GetBuffer will
3935   // have value expectedKeepValue
3936   if (XML_Parse(parser, text, (int)strlen(text), XML_FALSE /* isFinal */)
3937       == XML_STATUS_ERROR)
3938     xml_failure(parser);
3939 
3940   assert(expectedKeepValue > 0);
3941   if (XML_GetBuffer(parser, INT_MAX - expectedKeepValue + 1) != NULL)
3942     fail("enlarging buffer not failed");
3943 
3944   XML_ParserFree(parser);
3945 }
3946 END_TEST
3947 #endif // defined(XML_CONTEXT_BYTES)
3948 
3949 /* Test position information macros */
3950 START_TEST(test_byte_info_at_end) {
3951   const char *text = "<doc></doc>";
3952 
3953   if (XML_GetCurrentByteIndex(g_parser) != -1
3954       || XML_GetCurrentByteCount(g_parser) != 0)
3955     fail("Byte index/count incorrect at start of parse");
3956   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
3957       == XML_STATUS_ERROR)
3958     xml_failure(g_parser);
3959   /* At end, the count will be zero and the index the end of string */
3960   if (XML_GetCurrentByteCount(g_parser) != 0)
3961     fail("Terminal byte count incorrect");
3962   if (XML_GetCurrentByteIndex(g_parser) != (XML_Index)strlen(text))
3963     fail("Terminal byte index incorrect");
3964 }
3965 END_TEST
3966 
3967 /* Test position information from errors */
3968 #define PRE_ERROR_STR "<doc></"
3969 #define POST_ERROR_STR "wombat></doc>"
3970 START_TEST(test_byte_info_at_error) {
3971   const char *text = PRE_ERROR_STR POST_ERROR_STR;
3972 
3973   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
3974       == XML_STATUS_OK)
3975     fail("Syntax error not faulted");
3976   if (XML_GetCurrentByteCount(g_parser) != 0)
3977     fail("Error byte count incorrect");
3978   if (XML_GetCurrentByteIndex(g_parser) != strlen(PRE_ERROR_STR))
3979     fail("Error byte index incorrect");
3980 }
3981 END_TEST
3982 #undef PRE_ERROR_STR
3983 #undef POST_ERROR_STR
3984 
3985 /* Test position information in handler */
3986 typedef struct ByteTestData {
3987   int start_element_len;
3988   int cdata_len;
3989   int total_string_len;
3990 } ByteTestData;
3991 
3992 static void
3993 byte_character_handler(void *userData, const XML_Char *s, int len) {
3994 #ifdef XML_CONTEXT_BYTES
3995   int offset, size;
3996   const char *buffer;
3997   ByteTestData *data = (ByteTestData *)userData;
3998 
3999   UNUSED_P(s);
4000   buffer = XML_GetInputContext(g_parser, &offset, &size);
4001   if (buffer == NULL)
4002     fail("Failed to get context buffer");
4003   if (offset != data->start_element_len)
4004     fail("Context offset in unexpected position");
4005   if (len != data->cdata_len)
4006     fail("CDATA length reported incorrectly");
4007   if (size != data->total_string_len)
4008     fail("Context size is not full buffer");
4009   if (XML_GetCurrentByteIndex(g_parser) != offset)
4010     fail("Character byte index incorrect");
4011   if (XML_GetCurrentByteCount(g_parser) != len)
4012     fail("Character byte count incorrect");
4013 #else
4014   UNUSED_P(s);
4015   UNUSED_P(userData);
4016   UNUSED_P(len);
4017 #endif
4018 }
4019 
4020 #define START_ELEMENT "<e>"
4021 #define CDATA_TEXT "Hello"
4022 #define END_ELEMENT "</e>"
4023 START_TEST(test_byte_info_at_cdata) {
4024   const char *text = START_ELEMENT CDATA_TEXT END_ELEMENT;
4025   int offset, size;
4026   ByteTestData data;
4027 
4028   /* Check initial context is empty */
4029   if (XML_GetInputContext(g_parser, &offset, &size) != NULL)
4030     fail("Unexpected context at start of parse");
4031 
4032   data.start_element_len = (int)strlen(START_ELEMENT);
4033   data.cdata_len = (int)strlen(CDATA_TEXT);
4034   data.total_string_len = (int)strlen(text);
4035   XML_SetCharacterDataHandler(g_parser, byte_character_handler);
4036   XML_SetUserData(g_parser, &data);
4037   if (XML_Parse(g_parser, text, (int)strlen(text), XML_TRUE) != XML_STATUS_OK)
4038     xml_failure(g_parser);
4039 }
4040 END_TEST
4041 #undef START_ELEMENT
4042 #undef CDATA_TEXT
4043 #undef END_ELEMENT
4044 
4045 /* Test predefined entities are correctly recognised */
4046 START_TEST(test_predefined_entities) {
4047   const char *text = "<doc>&lt;&gt;&amp;&quot;&apos;</doc>";
4048   const XML_Char *expected = XCS("<doc>&lt;&gt;&amp;&quot;&apos;</doc>");
4049   const XML_Char *result = XCS("<>&\"'");
4050   CharData storage;
4051 
4052   XML_SetDefaultHandler(g_parser, accumulate_characters);
4053   /* run_character_check uses XML_SetCharacterDataHandler(), which
4054    * unfortunately heads off a code path that we need to exercise.
4055    */
4056   CharData_Init(&storage);
4057   XML_SetUserData(g_parser, &storage);
4058   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
4059       == XML_STATUS_ERROR)
4060     xml_failure(g_parser);
4061   /* The default handler doesn't translate the entities */
4062   CharData_CheckXMLChars(&storage, expected);
4063 
4064   /* Now try again and check the translation */
4065   XML_ParserReset(g_parser, NULL);
4066   run_character_check(text, result);
4067 }
4068 END_TEST
4069 
4070 /* Regression test that an invalid tag in an external parameter
4071  * reference in an external DTD is correctly faulted.
4072  *
4073  * Only a few specific tags are legal in DTDs ignoring comments and
4074  * processing instructions, all of which begin with an exclamation
4075  * mark.  "<el/>" is not one of them, so the parser should raise an
4076  * error on encountering it.
4077  */
4078 static int XMLCALL
4079 external_entity_param(XML_Parser parser, const XML_Char *context,
4080                       const XML_Char *base, const XML_Char *systemId,
4081                       const XML_Char *publicId) {
4082   const char *text1 = "<!ELEMENT doc EMPTY>\n"
4083                       "<!ENTITY % e1 SYSTEM '004-2.ent'>\n"
4084                       "<!ENTITY % e2 '%e1;'>\n"
4085                       "%e1;\n";
4086   const char *text2 = "<!ELEMENT el EMPTY>\n"
4087                       "<el/>\n";
4088   XML_Parser ext_parser;
4089 
4090   UNUSED_P(base);
4091   UNUSED_P(publicId);
4092   if (systemId == NULL)
4093     return XML_STATUS_OK;
4094 
4095   ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
4096   if (ext_parser == NULL)
4097     fail("Could not create external entity parser");
4098 
4099   if (! xcstrcmp(systemId, XCS("004-1.ent"))) {
4100     if (_XML_Parse_SINGLE_BYTES(ext_parser, text1, (int)strlen(text1), XML_TRUE)
4101         != XML_STATUS_ERROR)
4102       fail("Inner DTD with invalid tag not rejected");
4103     if (XML_GetErrorCode(ext_parser) != XML_ERROR_EXTERNAL_ENTITY_HANDLING)
4104       xml_failure(ext_parser);
4105   } else if (! xcstrcmp(systemId, XCS("004-2.ent"))) {
4106     if (_XML_Parse_SINGLE_BYTES(ext_parser, text2, (int)strlen(text2), XML_TRUE)
4107         != XML_STATUS_ERROR)
4108       fail("Invalid tag in external param not rejected");
4109     if (XML_GetErrorCode(ext_parser) != XML_ERROR_SYNTAX)
4110       xml_failure(ext_parser);
4111   } else {
4112     fail("Unknown system ID");
4113   }
4114 
4115   XML_ParserFree(ext_parser);
4116   return XML_STATUS_ERROR;
4117 }
4118 
4119 START_TEST(test_invalid_tag_in_dtd) {
4120   const char *text = "<!DOCTYPE doc SYSTEM '004-1.ent'>\n"
4121                      "<doc></doc>\n";
4122 
4123   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
4124   XML_SetExternalEntityRefHandler(g_parser, external_entity_param);
4125   expect_failure(text, XML_ERROR_EXTERNAL_ENTITY_HANDLING,
4126                  "Invalid tag IN DTD external param not rejected");
4127 }
4128 END_TEST
4129 
4130 /* Test entities not quite the predefined ones are not mis-recognised */
4131 START_TEST(test_not_predefined_entities) {
4132   const char *text[] = {"<doc>&pt;</doc>", "<doc>&amo;</doc>",
4133                         "<doc>&quid;</doc>", "<doc>&apod;</doc>", NULL};
4134   int i = 0;
4135 
4136   while (text[i] != NULL) {
4137     expect_failure(text[i], XML_ERROR_UNDEFINED_ENTITY,
4138                    "Undefined entity not rejected");
4139     XML_ParserReset(g_parser, NULL);
4140     i++;
4141   }
4142 }
4143 END_TEST
4144 
4145 /* Test conditional inclusion (IGNORE) */
4146 static int XMLCALL
4147 external_entity_load_ignore(XML_Parser parser, const XML_Char *context,
4148                             const XML_Char *base, const XML_Char *systemId,
4149                             const XML_Char *publicId) {
4150   const char *text = "<![IGNORE[<!ELEMENT e (#PCDATA)*>]]>";
4151   XML_Parser ext_parser;
4152 
4153   UNUSED_P(base);
4154   UNUSED_P(systemId);
4155   UNUSED_P(publicId);
4156   ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
4157   if (ext_parser == NULL)
4158     fail("Could not create external entity parser");
4159   if (_XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE)
4160       == XML_STATUS_ERROR)
4161     xml_failure(parser);
4162 
4163   XML_ParserFree(ext_parser);
4164   return XML_STATUS_OK;
4165 }
4166 
4167 START_TEST(test_ignore_section) {
4168   const char *text = "<!DOCTYPE doc SYSTEM 'foo'>\n"
4169                      "<doc><e>&entity;</e></doc>";
4170   const XML_Char *expected
4171       = XCS("<![IGNORE[<!ELEMENT e (#PCDATA)*>]]>\n&entity;");
4172   CharData storage;
4173 
4174   CharData_Init(&storage);
4175   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
4176   XML_SetUserData(g_parser, &storage);
4177   XML_SetExternalEntityRefHandler(g_parser, external_entity_load_ignore);
4178   XML_SetDefaultHandler(g_parser, accumulate_characters);
4179   XML_SetStartDoctypeDeclHandler(g_parser, dummy_start_doctype_handler);
4180   XML_SetEndDoctypeDeclHandler(g_parser, dummy_end_doctype_handler);
4181   XML_SetElementDeclHandler(g_parser, dummy_element_decl_handler);
4182   XML_SetStartElementHandler(g_parser, dummy_start_element);
4183   XML_SetEndElementHandler(g_parser, dummy_end_element);
4184   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
4185       == XML_STATUS_ERROR)
4186     xml_failure(g_parser);
4187   CharData_CheckXMLChars(&storage, expected);
4188 }
4189 END_TEST
4190 
4191 static int XMLCALL
4192 external_entity_load_ignore_utf16(XML_Parser parser, const XML_Char *context,
4193                                   const XML_Char *base,
4194                                   const XML_Char *systemId,
4195                                   const XML_Char *publicId) {
4196   const char text[] =
4197       /* <![IGNORE[<!ELEMENT e (#PCDATA)*>]]> */
4198       "<\0!\0[\0I\0G\0N\0O\0R\0E\0[\0"
4199       "<\0!\0E\0L\0E\0M\0E\0N\0T\0 \0e\0 \0"
4200       "(\0#\0P\0C\0D\0A\0T\0A\0)\0*\0>\0]\0]\0>\0";
4201   XML_Parser ext_parser;
4202 
4203   UNUSED_P(base);
4204   UNUSED_P(systemId);
4205   UNUSED_P(publicId);
4206   ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
4207   if (ext_parser == NULL)
4208     fail("Could not create external entity parser");
4209   if (_XML_Parse_SINGLE_BYTES(ext_parser, text, (int)sizeof(text) - 1, XML_TRUE)
4210       == XML_STATUS_ERROR)
4211     xml_failure(parser);
4212 
4213   XML_ParserFree(ext_parser);
4214   return XML_STATUS_OK;
4215 }
4216 
4217 START_TEST(test_ignore_section_utf16) {
4218   const char text[] =
4219       /* <!DOCTYPE d SYSTEM 's'> */
4220       "<\0!\0D\0O\0C\0T\0Y\0P\0E\0 \0d\0 "
4221       "\0S\0Y\0S\0T\0E\0M\0 \0'\0s\0'\0>\0\n\0"
4222       /* <d><e>&en;</e></d> */
4223       "<\0d\0>\0<\0e\0>\0&\0e\0n\0;\0<\0/\0e\0>\0<\0/\0d\0>\0";
4224   const XML_Char *expected = XCS("<![IGNORE[<!ELEMENT e (#PCDATA)*>]]>\n&en;");
4225   CharData storage;
4226 
4227   CharData_Init(&storage);
4228   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
4229   XML_SetUserData(g_parser, &storage);
4230   XML_SetExternalEntityRefHandler(g_parser, external_entity_load_ignore_utf16);
4231   XML_SetDefaultHandler(g_parser, accumulate_characters);
4232   XML_SetStartDoctypeDeclHandler(g_parser, dummy_start_doctype_handler);
4233   XML_SetEndDoctypeDeclHandler(g_parser, dummy_end_doctype_handler);
4234   XML_SetElementDeclHandler(g_parser, dummy_element_decl_handler);
4235   XML_SetStartElementHandler(g_parser, dummy_start_element);
4236   XML_SetEndElementHandler(g_parser, dummy_end_element);
4237   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE)
4238       == XML_STATUS_ERROR)
4239     xml_failure(g_parser);
4240   CharData_CheckXMLChars(&storage, expected);
4241 }
4242 END_TEST
4243 
4244 static int XMLCALL
4245 external_entity_load_ignore_utf16_be(XML_Parser parser, const XML_Char *context,
4246                                      const XML_Char *base,
4247                                      const XML_Char *systemId,
4248                                      const XML_Char *publicId) {
4249   const char text[] =
4250       /* <![IGNORE[<!ELEMENT e (#PCDATA)*>]]> */
4251       "\0<\0!\0[\0I\0G\0N\0O\0R\0E\0["
4252       "\0<\0!\0E\0L\0E\0M\0E\0N\0T\0 \0e\0 "
4253       "\0(\0#\0P\0C\0D\0A\0T\0A\0)\0*\0>\0]\0]\0>";
4254   XML_Parser ext_parser;
4255 
4256   UNUSED_P(base);
4257   UNUSED_P(systemId);
4258   UNUSED_P(publicId);
4259   ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
4260   if (ext_parser == NULL)
4261     fail("Could not create external entity parser");
4262   if (_XML_Parse_SINGLE_BYTES(ext_parser, text, (int)sizeof(text) - 1, XML_TRUE)
4263       == XML_STATUS_ERROR)
4264     xml_failure(parser);
4265 
4266   XML_ParserFree(ext_parser);
4267   return XML_STATUS_OK;
4268 }
4269 
4270 START_TEST(test_ignore_section_utf16_be) {
4271   const char text[] =
4272       /* <!DOCTYPE d SYSTEM 's'> */
4273       "\0<\0!\0D\0O\0C\0T\0Y\0P\0E\0 \0d\0 "
4274       "\0S\0Y\0S\0T\0E\0M\0 \0'\0s\0'\0>\0\n"
4275       /* <d><e>&en;</e></d> */
4276       "\0<\0d\0>\0<\0e\0>\0&\0e\0n\0;\0<\0/\0e\0>\0<\0/\0d\0>";
4277   const XML_Char *expected = XCS("<![IGNORE[<!ELEMENT e (#PCDATA)*>]]>\n&en;");
4278   CharData storage;
4279 
4280   CharData_Init(&storage);
4281   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
4282   XML_SetUserData(g_parser, &storage);
4283   XML_SetExternalEntityRefHandler(g_parser,
4284                                   external_entity_load_ignore_utf16_be);
4285   XML_SetDefaultHandler(g_parser, accumulate_characters);
4286   XML_SetStartDoctypeDeclHandler(g_parser, dummy_start_doctype_handler);
4287   XML_SetEndDoctypeDeclHandler(g_parser, dummy_end_doctype_handler);
4288   XML_SetElementDeclHandler(g_parser, dummy_element_decl_handler);
4289   XML_SetStartElementHandler(g_parser, dummy_start_element);
4290   XML_SetEndElementHandler(g_parser, dummy_end_element);
4291   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE)
4292       == XML_STATUS_ERROR)
4293     xml_failure(g_parser);
4294   CharData_CheckXMLChars(&storage, expected);
4295 }
4296 END_TEST
4297 
4298 /* Test mis-formatted conditional exclusion */
4299 START_TEST(test_bad_ignore_section) {
4300   const char *text = "<!DOCTYPE doc SYSTEM 'foo'>\n"
4301                      "<doc><e>&entity;</e></doc>";
4302   ExtFaults faults[]
4303       = {{"<![IGNORE[<!ELEM", "Broken-off declaration not faulted", NULL,
4304           XML_ERROR_SYNTAX},
4305          {"<![IGNORE[\x01]]>", "Invalid XML character not faulted", NULL,
4306           XML_ERROR_INVALID_TOKEN},
4307          {/* FIrst two bytes of a three-byte char */
4308           "<![IGNORE[\xe2\x82", "Partial XML character not faulted", NULL,
4309           XML_ERROR_PARTIAL_CHAR},
4310          {NULL, NULL, NULL, XML_ERROR_NONE}};
4311   ExtFaults *fault;
4312 
4313   for (fault = &faults[0]; fault->parse_text != NULL; fault++) {
4314     XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
4315     XML_SetExternalEntityRefHandler(g_parser, external_entity_faulter);
4316     XML_SetUserData(g_parser, fault);
4317     expect_failure(text, XML_ERROR_EXTERNAL_ENTITY_HANDLING,
4318                    "Incomplete IGNORE section not failed");
4319     XML_ParserReset(g_parser, NULL);
4320   }
4321 }
4322 END_TEST
4323 
4324 /* Test recursive parsing */
4325 static int XMLCALL
4326 external_entity_valuer(XML_Parser parser, const XML_Char *context,
4327                        const XML_Char *base, const XML_Char *systemId,
4328                        const XML_Char *publicId) {
4329   const char *text1 = "<!ELEMENT doc EMPTY>\n"
4330                       "<!ENTITY % e1 SYSTEM '004-2.ent'>\n"
4331                       "<!ENTITY % e2 '%e1;'>\n"
4332                       "%e1;\n";
4333   XML_Parser ext_parser;
4334 
4335   UNUSED_P(base);
4336   UNUSED_P(publicId);
4337   if (systemId == NULL)
4338     return XML_STATUS_OK;
4339   ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
4340   if (ext_parser == NULL)
4341     fail("Could not create external entity parser");
4342   if (! xcstrcmp(systemId, XCS("004-1.ent"))) {
4343     if (_XML_Parse_SINGLE_BYTES(ext_parser, text1, (int)strlen(text1), XML_TRUE)
4344         == XML_STATUS_ERROR)
4345       xml_failure(ext_parser);
4346   } else if (! xcstrcmp(systemId, XCS("004-2.ent"))) {
4347     ExtFaults *fault = (ExtFaults *)XML_GetUserData(parser);
4348     enum XML_Status status;
4349     enum XML_Error error;
4350 
4351     status = _XML_Parse_SINGLE_BYTES(ext_parser, fault->parse_text,
4352                                      (int)strlen(fault->parse_text), XML_TRUE);
4353     if (fault->error == XML_ERROR_NONE) {
4354       if (status == XML_STATUS_ERROR)
4355         xml_failure(ext_parser);
4356     } else {
4357       if (status != XML_STATUS_ERROR)
4358         fail(fault->fail_text);
4359       error = XML_GetErrorCode(ext_parser);
4360       if (error != fault->error
4361           && (fault->error != XML_ERROR_XML_DECL
4362               || error != XML_ERROR_TEXT_DECL))
4363         xml_failure(ext_parser);
4364     }
4365   }
4366 
4367   XML_ParserFree(ext_parser);
4368   return XML_STATUS_OK;
4369 }
4370 
4371 START_TEST(test_external_entity_values) {
4372   const char *text = "<!DOCTYPE doc SYSTEM '004-1.ent'>\n"
4373                      "<doc></doc>\n";
4374   ExtFaults data_004_2[] = {
4375       {"<!ATTLIST doc a1 CDATA 'value'>", NULL, NULL, XML_ERROR_NONE},
4376       {"<!ATTLIST $doc a1 CDATA 'value'>", "Invalid token not faulted", NULL,
4377        XML_ERROR_INVALID_TOKEN},
4378       {"'wombat", "Unterminated string not faulted", NULL,
4379        XML_ERROR_UNCLOSED_TOKEN},
4380       {"\xe2\x82", "Partial UTF-8 character not faulted", NULL,
4381        XML_ERROR_PARTIAL_CHAR},
4382       {"<?xml version='1.0' encoding='utf-8'?>\n", NULL, NULL, XML_ERROR_NONE},
4383       {"<?xml?>", "Malformed XML declaration not faulted", NULL,
4384        XML_ERROR_XML_DECL},
4385       {/* UTF-8 BOM */
4386        "\xEF\xBB\xBF<!ATTLIST doc a1 CDATA 'value'>", NULL, NULL,
4387        XML_ERROR_NONE},
4388       {"<?xml version='1.0' encoding='utf-8'?>\n$",
4389        "Invalid token after text declaration not faulted", NULL,
4390        XML_ERROR_INVALID_TOKEN},
4391       {"<?xml version='1.0' encoding='utf-8'?>\n'wombat",
4392        "Unterminated string after text decl not faulted", NULL,
4393        XML_ERROR_UNCLOSED_TOKEN},
4394       {"<?xml version='1.0' encoding='utf-8'?>\n\xe2\x82",
4395        "Partial UTF-8 character after text decl not faulted", NULL,
4396        XML_ERROR_PARTIAL_CHAR},
4397       {"%e1;", "Recursive parameter entity not faulted", NULL,
4398        XML_ERROR_RECURSIVE_ENTITY_REF},
4399       {NULL, NULL, NULL, XML_ERROR_NONE}};
4400   int i;
4401 
4402   for (i = 0; data_004_2[i].parse_text != NULL; i++) {
4403     XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
4404     XML_SetExternalEntityRefHandler(g_parser, external_entity_valuer);
4405     XML_SetUserData(g_parser, &data_004_2[i]);
4406     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
4407         == XML_STATUS_ERROR)
4408       xml_failure(g_parser);
4409     XML_ParserReset(g_parser, NULL);
4410   }
4411 }
4412 END_TEST
4413 
4414 /* Test the recursive parse interacts with a not standalone handler */
4415 static int XMLCALL
4416 external_entity_not_standalone(XML_Parser parser, const XML_Char *context,
4417                                const XML_Char *base, const XML_Char *systemId,
4418                                const XML_Char *publicId) {
4419   const char *text1 = "<!ELEMENT doc EMPTY>\n"
4420                       "<!ENTITY % e1 SYSTEM 'bar'>\n"
4421                       "%e1;\n";
4422   const char *text2 = "<!ATTLIST doc a1 CDATA 'value'>";
4423   XML_Parser ext_parser;
4424 
4425   UNUSED_P(base);
4426   UNUSED_P(publicId);
4427   if (systemId == NULL)
4428     return XML_STATUS_OK;
4429   ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
4430   if (ext_parser == NULL)
4431     fail("Could not create external entity parser");
4432   if (! xcstrcmp(systemId, XCS("foo"))) {
4433     XML_SetNotStandaloneHandler(ext_parser, reject_not_standalone_handler);
4434     if (_XML_Parse_SINGLE_BYTES(ext_parser, text1, (int)strlen(text1), XML_TRUE)
4435         != XML_STATUS_ERROR)
4436       fail("Expected not standalone rejection");
4437     if (XML_GetErrorCode(ext_parser) != XML_ERROR_NOT_STANDALONE)
4438       xml_failure(ext_parser);
4439     XML_SetNotStandaloneHandler(ext_parser, NULL);
4440     XML_ParserFree(ext_parser);
4441     return XML_STATUS_ERROR;
4442   } else if (! xcstrcmp(systemId, XCS("bar"))) {
4443     if (_XML_Parse_SINGLE_BYTES(ext_parser, text2, (int)strlen(text2), XML_TRUE)
4444         == XML_STATUS_ERROR)
4445       xml_failure(ext_parser);
4446   }
4447 
4448   XML_ParserFree(ext_parser);
4449   return XML_STATUS_OK;
4450 }
4451 
4452 START_TEST(test_ext_entity_not_standalone) {
4453   const char *text = "<!DOCTYPE doc SYSTEM 'foo'>\n"
4454                      "<doc></doc>";
4455 
4456   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
4457   XML_SetExternalEntityRefHandler(g_parser, external_entity_not_standalone);
4458   expect_failure(text, XML_ERROR_EXTERNAL_ENTITY_HANDLING,
4459                  "Standalone rejection not caught");
4460 }
4461 END_TEST
4462 
4463 static int XMLCALL
4464 external_entity_value_aborter(XML_Parser parser, const XML_Char *context,
4465                               const XML_Char *base, const XML_Char *systemId,
4466                               const XML_Char *publicId) {
4467   const char *text1 = "<!ELEMENT doc EMPTY>\n"
4468                       "<!ENTITY % e1 SYSTEM '004-2.ent'>\n"
4469                       "<!ENTITY % e2 '%e1;'>\n"
4470                       "%e1;\n";
4471   const char *text2 = "<?xml version='1.0' encoding='utf-8'?>";
4472   XML_Parser ext_parser;
4473 
4474   UNUSED_P(base);
4475   UNUSED_P(publicId);
4476   if (systemId == NULL)
4477     return XML_STATUS_OK;
4478   ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
4479   if (ext_parser == NULL)
4480     fail("Could not create external entity parser");
4481   if (! xcstrcmp(systemId, XCS("004-1.ent"))) {
4482     if (_XML_Parse_SINGLE_BYTES(ext_parser, text1, (int)strlen(text1), XML_TRUE)
4483         == XML_STATUS_ERROR)
4484       xml_failure(ext_parser);
4485   }
4486   if (! xcstrcmp(systemId, XCS("004-2.ent"))) {
4487     XML_SetXmlDeclHandler(ext_parser, entity_suspending_xdecl_handler);
4488     XML_SetUserData(ext_parser, ext_parser);
4489     if (_XML_Parse_SINGLE_BYTES(ext_parser, text2, (int)strlen(text2), XML_TRUE)
4490         != XML_STATUS_ERROR)
4491       fail("Aborted parse not faulted");
4492     if (XML_GetErrorCode(ext_parser) != XML_ERROR_ABORTED)
4493       xml_failure(ext_parser);
4494   }
4495 
4496   XML_ParserFree(ext_parser);
4497   return XML_STATUS_OK;
4498 }
4499 
4500 START_TEST(test_ext_entity_value_abort) {
4501   const char *text = "<!DOCTYPE doc SYSTEM '004-1.ent'>\n"
4502                      "<doc></doc>\n";
4503 
4504   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
4505   XML_SetExternalEntityRefHandler(g_parser, external_entity_value_aborter);
4506   resumable = XML_FALSE;
4507   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
4508       == XML_STATUS_ERROR)
4509     xml_failure(g_parser);
4510 }
4511 END_TEST
4512 
4513 START_TEST(test_bad_public_doctype) {
4514   const char *text = "<?xml version='1.0' encoding='utf-8'?>\n"
4515                      "<!DOCTYPE doc PUBLIC '{BadName}' 'test'>\n"
4516                      "<doc></doc>";
4517 
4518   /* Setting a handler provokes a particular code path */
4519   XML_SetDoctypeDeclHandler(g_parser, dummy_start_doctype_handler,
4520                             dummy_end_doctype_handler);
4521   expect_failure(text, XML_ERROR_PUBLICID, "Bad Public ID not failed");
4522 }
4523 END_TEST
4524 
4525 /* Test based on ibm/valid/P32/ibm32v04.xml */
4526 START_TEST(test_attribute_enum_value) {
4527   const char *text = "<?xml version='1.0' standalone='no'?>\n"
4528                      "<!DOCTYPE animal SYSTEM 'test.dtd'>\n"
4529                      "<animal>This is a \n    <a/>  \n\nyellow tiger</animal>";
4530   ExtTest dtd_data
4531       = {"<!ELEMENT animal (#PCDATA|a)*>\n"
4532          "<!ELEMENT a EMPTY>\n"
4533          "<!ATTLIST animal xml:space (default|preserve) 'preserve'>",
4534          NULL, NULL};
4535   const XML_Char *expected = XCS("This is a \n      \n\nyellow tiger");
4536 
4537   XML_SetExternalEntityRefHandler(g_parser, external_entity_loader);
4538   XML_SetUserData(g_parser, &dtd_data);
4539   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
4540   /* An attribute list handler provokes a different code path */
4541   XML_SetAttlistDeclHandler(g_parser, dummy_attlist_decl_handler);
4542   run_ext_character_check(text, &dtd_data, expected);
4543 }
4544 END_TEST
4545 
4546 /* Slightly bizarrely, the library seems to silently ignore entity
4547  * definitions for predefined entities, even when they are wrong.  The
4548  * language of the XML 1.0 spec is somewhat unhelpful as to what ought
4549  * to happen, so this is currently treated as acceptable.
4550  */
4551 START_TEST(test_predefined_entity_redefinition) {
4552   const char *text = "<!DOCTYPE doc [\n"
4553                      "<!ENTITY apos 'foo'>\n"
4554                      "]>\n"
4555                      "<doc>&apos;</doc>";
4556   run_character_check(text, XCS("'"));
4557 }
4558 END_TEST
4559 
4560 /* Test that the parser stops processing the DTD after an unresolved
4561  * parameter entity is encountered.
4562  */
4563 START_TEST(test_dtd_stop_processing) {
4564   const char *text = "<!DOCTYPE doc [\n"
4565                      "%foo;\n"
4566                      "<!ENTITY bar 'bas'>\n"
4567                      "]><doc/>";
4568 
4569   XML_SetEntityDeclHandler(g_parser, dummy_entity_decl_handler);
4570   dummy_handler_flags = 0;
4571   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
4572       == XML_STATUS_ERROR)
4573     xml_failure(g_parser);
4574   if (dummy_handler_flags != 0)
4575     fail("DTD processing still going after undefined PE");
4576 }
4577 END_TEST
4578 
4579 /* Test public notations with no system ID */
4580 START_TEST(test_public_notation_no_sysid) {
4581   const char *text = "<!DOCTYPE doc [\n"
4582                      "<!NOTATION note PUBLIC 'foo'>\n"
4583                      "<!ELEMENT doc EMPTY>\n"
4584                      "]>\n<doc/>";
4585 
4586   dummy_handler_flags = 0;
4587   XML_SetNotationDeclHandler(g_parser, dummy_notation_decl_handler);
4588   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
4589       == XML_STATUS_ERROR)
4590     xml_failure(g_parser);
4591   if (dummy_handler_flags != DUMMY_NOTATION_DECL_HANDLER_FLAG)
4592     fail("Notation declaration handler not called");
4593 }
4594 END_TEST
4595 
4596 static void XMLCALL
4597 record_element_start_handler(void *userData, const XML_Char *name,
4598                              const XML_Char **atts) {
4599   UNUSED_P(atts);
4600   CharData_AppendXMLChars((CharData *)userData, name, (int)xcstrlen(name));
4601 }
4602 
4603 START_TEST(test_nested_groups) {
4604   const char *text
4605       = "<!DOCTYPE doc [\n"
4606         "<!ELEMENT doc "
4607         /* Sixteen elements per line */
4608         "(e,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,"
4609         "(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?"
4610         "))))))))))))))))))))))))))))))))>\n"
4611         "<!ELEMENT e EMPTY>"
4612         "]>\n"
4613         "<doc><e/></doc>";
4614   CharData storage;
4615 
4616   CharData_Init(&storage);
4617   XML_SetElementDeclHandler(g_parser, dummy_element_decl_handler);
4618   XML_SetStartElementHandler(g_parser, record_element_start_handler);
4619   XML_SetUserData(g_parser, &storage);
4620   dummy_handler_flags = 0;
4621   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
4622       == XML_STATUS_ERROR)
4623     xml_failure(g_parser);
4624   CharData_CheckXMLChars(&storage, XCS("doce"));
4625   if (dummy_handler_flags != DUMMY_ELEMENT_DECL_HANDLER_FLAG)
4626     fail("Element handler not fired");
4627 }
4628 END_TEST
4629 
4630 START_TEST(test_group_choice) {
4631   const char *text = "<!DOCTYPE doc [\n"
4632                      "<!ELEMENT doc (a|b|c)+>\n"
4633                      "<!ELEMENT a EMPTY>\n"
4634                      "<!ELEMENT b (#PCDATA)>\n"
4635                      "<!ELEMENT c ANY>\n"
4636                      "]>\n"
4637                      "<doc>\n"
4638                      "<a/>\n"
4639                      "<b attr='foo'>This is a foo</b>\n"
4640                      "<c></c>\n"
4641                      "</doc>\n";
4642 
4643   XML_SetElementDeclHandler(g_parser, dummy_element_decl_handler);
4644   dummy_handler_flags = 0;
4645   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
4646       == XML_STATUS_ERROR)
4647     xml_failure(g_parser);
4648   if (dummy_handler_flags != DUMMY_ELEMENT_DECL_HANDLER_FLAG)
4649     fail("Element handler flag not raised");
4650 }
4651 END_TEST
4652 
4653 static int XMLCALL
4654 external_entity_public(XML_Parser parser, const XML_Char *context,
4655                        const XML_Char *base, const XML_Char *systemId,
4656                        const XML_Char *publicId) {
4657   const char *text1 = (const char *)XML_GetUserData(parser);
4658   const char *text2 = "<!ATTLIST doc a CDATA 'value'>";
4659   const char *text = NULL;
4660   XML_Parser ext_parser;
4661   int parse_res;
4662 
4663   UNUSED_P(base);
4664   ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
4665   if (ext_parser == NULL)
4666     return XML_STATUS_ERROR;
4667   if (systemId != NULL && ! xcstrcmp(systemId, XCS("http://example.org/"))) {
4668     text = text1;
4669   } else if (publicId != NULL && ! xcstrcmp(publicId, XCS("foo"))) {
4670     text = text2;
4671   } else
4672     fail("Unexpected parameters to external entity parser");
4673   assert(text != NULL);
4674   parse_res
4675       = _XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE);
4676   XML_ParserFree(ext_parser);
4677   return parse_res;
4678 }
4679 
4680 START_TEST(test_standalone_parameter_entity) {
4681   const char *text = "<?xml version='1.0' standalone='yes'?>\n"
4682                      "<!DOCTYPE doc SYSTEM 'http://example.org/' [\n"
4683                      "<!ENTITY % entity '<!ELEMENT doc (#PCDATA)>'>\n"
4684                      "%entity;\n"
4685                      "]>\n"
4686                      "<doc></doc>";
4687   char dtd_data[] = "<!ENTITY % e1 'foo'>\n";
4688 
4689   XML_SetUserData(g_parser, dtd_data);
4690   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
4691   XML_SetExternalEntityRefHandler(g_parser, external_entity_public);
4692   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
4693       == XML_STATUS_ERROR)
4694     xml_failure(g_parser);
4695 }
4696 END_TEST
4697 
4698 /* Test skipping of parameter entity in an external DTD */
4699 /* Derived from ibm/invalid/P69/ibm69i01.xml */
4700 START_TEST(test_skipped_parameter_entity) {
4701   const char *text = "<?xml version='1.0'?>\n"
4702                      "<!DOCTYPE root SYSTEM 'http://example.org/dtd.ent' [\n"
4703                      "<!ELEMENT root (#PCDATA|a)* >\n"
4704                      "]>\n"
4705                      "<root></root>";
4706   ExtTest dtd_data = {"%pe2;", NULL, NULL};
4707 
4708   XML_SetExternalEntityRefHandler(g_parser, external_entity_loader);
4709   XML_SetUserData(g_parser, &dtd_data);
4710   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
4711   XML_SetSkippedEntityHandler(g_parser, dummy_skip_handler);
4712   dummy_handler_flags = 0;
4713   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
4714       == XML_STATUS_ERROR)
4715     xml_failure(g_parser);
4716   if (dummy_handler_flags != DUMMY_SKIP_HANDLER_FLAG)
4717     fail("Skip handler not executed");
4718 }
4719 END_TEST
4720 
4721 /* Test recursive parameter entity definition rejected in external DTD */
4722 START_TEST(test_recursive_external_parameter_entity) {
4723   const char *text = "<?xml version='1.0'?>\n"
4724                      "<!DOCTYPE root SYSTEM 'http://example.org/dtd.ent' [\n"
4725                      "<!ELEMENT root (#PCDATA|a)* >\n"
4726                      "]>\n"
4727                      "<root></root>";
4728   ExtFaults dtd_data = {"<!ENTITY % pe2 '&#37;pe2;'>\n%pe2;",
4729                         "Recursive external parameter entity not faulted", NULL,
4730                         XML_ERROR_RECURSIVE_ENTITY_REF};
4731 
4732   XML_SetExternalEntityRefHandler(g_parser, external_entity_faulter);
4733   XML_SetUserData(g_parser, &dtd_data);
4734   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
4735   expect_failure(text, XML_ERROR_EXTERNAL_ENTITY_HANDLING,
4736                  "Recursive external parameter not spotted");
4737 }
4738 END_TEST
4739 
4740 /* Test undefined parameter entity in external entity handler */
4741 static int XMLCALL
4742 external_entity_devaluer(XML_Parser parser, const XML_Char *context,
4743                          const XML_Char *base, const XML_Char *systemId,
4744                          const XML_Char *publicId) {
4745   const char *text = "<!ELEMENT doc EMPTY>\n"
4746                      "<!ENTITY % e1 SYSTEM 'bar'>\n"
4747                      "%e1;\n";
4748   XML_Parser ext_parser;
4749   intptr_t clear_handler = (intptr_t)XML_GetUserData(parser);
4750 
4751   UNUSED_P(base);
4752   UNUSED_P(publicId);
4753   if (systemId == NULL || ! xcstrcmp(systemId, XCS("bar")))
4754     return XML_STATUS_OK;
4755   if (xcstrcmp(systemId, XCS("foo")))
4756     fail("Unexpected system ID");
4757   ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
4758   if (ext_parser == NULL)
4759     fail("Could note create external entity parser");
4760   if (clear_handler)
4761     XML_SetExternalEntityRefHandler(ext_parser, NULL);
4762   if (_XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE)
4763       == XML_STATUS_ERROR)
4764     xml_failure(ext_parser);
4765 
4766   XML_ParserFree(ext_parser);
4767   return XML_STATUS_OK;
4768 }
4769 
4770 START_TEST(test_undefined_ext_entity_in_external_dtd) {
4771   const char *text = "<!DOCTYPE doc SYSTEM 'foo'>\n"
4772                      "<doc></doc>\n";
4773 
4774   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
4775   XML_SetExternalEntityRefHandler(g_parser, external_entity_devaluer);
4776   XML_SetUserData(g_parser, (void *)(intptr_t)XML_FALSE);
4777   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
4778       == XML_STATUS_ERROR)
4779     xml_failure(g_parser);
4780 
4781   /* Now repeat without the external entity ref handler invoking
4782    * another copy of itself.
4783    */
4784   XML_ParserReset(g_parser, NULL);
4785   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
4786   XML_SetExternalEntityRefHandler(g_parser, external_entity_devaluer);
4787   XML_SetUserData(g_parser, (void *)(intptr_t)XML_TRUE);
4788   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
4789       == XML_STATUS_ERROR)
4790     xml_failure(g_parser);
4791 }
4792 END_TEST
4793 
4794 static void XMLCALL
4795 aborting_xdecl_handler(void *userData, const XML_Char *version,
4796                        const XML_Char *encoding, int standalone) {
4797   UNUSED_P(userData);
4798   UNUSED_P(version);
4799   UNUSED_P(encoding);
4800   UNUSED_P(standalone);
4801   XML_StopParser(g_parser, resumable);
4802   XML_SetXmlDeclHandler(g_parser, NULL);
4803 }
4804 
4805 /* Test suspending the parse on receiving an XML declaration works */
4806 START_TEST(test_suspend_xdecl) {
4807   const char *text = long_character_data_text;
4808 
4809   XML_SetXmlDeclHandler(g_parser, aborting_xdecl_handler);
4810   resumable = XML_TRUE;
4811   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
4812       != XML_STATUS_SUSPENDED)
4813     xml_failure(g_parser);
4814   if (XML_GetErrorCode(g_parser) != XML_ERROR_NONE)
4815     xml_failure(g_parser);
4816   /* Attempt to start a new parse while suspended */
4817   if (XML_Parse(g_parser, text, (int)strlen(text), XML_TRUE)
4818       != XML_STATUS_ERROR)
4819     fail("Attempt to parse while suspended not faulted");
4820   if (XML_GetErrorCode(g_parser) != XML_ERROR_SUSPENDED)
4821     fail("Suspended parse not faulted with correct error");
4822 }
4823 END_TEST
4824 
4825 /* Test aborting the parse in an epilog works */
4826 static void XMLCALL
4827 selective_aborting_default_handler(void *userData, const XML_Char *s, int len) {
4828   const XML_Char *match = (const XML_Char *)userData;
4829 
4830   if (match == NULL
4831       || (xcstrlen(match) == (unsigned)len && ! xcstrncmp(match, s, len))) {
4832     XML_StopParser(g_parser, resumable);
4833     XML_SetDefaultHandler(g_parser, NULL);
4834   }
4835 }
4836 
4837 START_TEST(test_abort_epilog) {
4838   const char *text = "<doc></doc>\n\r\n";
4839   XML_Char match[] = XCS("\r");
4840 
4841   XML_SetDefaultHandler(g_parser, selective_aborting_default_handler);
4842   XML_SetUserData(g_parser, match);
4843   resumable = XML_FALSE;
4844   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
4845       != XML_STATUS_ERROR)
4846     fail("Abort not triggered");
4847   if (XML_GetErrorCode(g_parser) != XML_ERROR_ABORTED)
4848     xml_failure(g_parser);
4849 }
4850 END_TEST
4851 
4852 /* Test a different code path for abort in the epilog */
4853 START_TEST(test_abort_epilog_2) {
4854   const char *text = "<doc></doc>\n";
4855   XML_Char match[] = XCS("\n");
4856 
4857   XML_SetDefaultHandler(g_parser, selective_aborting_default_handler);
4858   XML_SetUserData(g_parser, match);
4859   resumable = XML_FALSE;
4860   expect_failure(text, XML_ERROR_ABORTED, "Abort not triggered");
4861 }
4862 END_TEST
4863 
4864 /* Test suspension from the epilog */
4865 START_TEST(test_suspend_epilog) {
4866   const char *text = "<doc></doc>\n";
4867   XML_Char match[] = XCS("\n");
4868 
4869   XML_SetDefaultHandler(g_parser, selective_aborting_default_handler);
4870   XML_SetUserData(g_parser, match);
4871   resumable = XML_TRUE;
4872   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
4873       != XML_STATUS_SUSPENDED)
4874     xml_failure(g_parser);
4875 }
4876 END_TEST
4877 
4878 static void XMLCALL
4879 suspending_end_handler(void *userData, const XML_Char *s) {
4880   UNUSED_P(s);
4881   XML_StopParser((XML_Parser)userData, 1);
4882 }
4883 
4884 START_TEST(test_suspend_in_sole_empty_tag) {
4885   const char *text = "<doc/>";
4886   enum XML_Status rc;
4887 
4888   XML_SetEndElementHandler(g_parser, suspending_end_handler);
4889   XML_SetUserData(g_parser, g_parser);
4890   rc = _XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE);
4891   if (rc == XML_STATUS_ERROR)
4892     xml_failure(g_parser);
4893   else if (rc != XML_STATUS_SUSPENDED)
4894     fail("Suspend not triggered");
4895   rc = XML_ResumeParser(g_parser);
4896   if (rc == XML_STATUS_ERROR)
4897     xml_failure(g_parser);
4898   else if (rc != XML_STATUS_OK)
4899     fail("Resume failed");
4900 }
4901 END_TEST
4902 
4903 START_TEST(test_unfinished_epilog) {
4904   const char *text = "<doc></doc><";
4905 
4906   expect_failure(text, XML_ERROR_UNCLOSED_TOKEN,
4907                  "Incomplete epilog entry not faulted");
4908 }
4909 END_TEST
4910 
4911 START_TEST(test_partial_char_in_epilog) {
4912   const char *text = "<doc></doc>\xe2\x82";
4913 
4914   /* First check that no fault is raised if the parse is not finished */
4915   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_FALSE)
4916       == XML_STATUS_ERROR)
4917     xml_failure(g_parser);
4918   /* Now check that it is faulted once we finish */
4919   if (XML_ParseBuffer(g_parser, 0, XML_TRUE) != XML_STATUS_ERROR)
4920     fail("Partial character in epilog not faulted");
4921   if (XML_GetErrorCode(g_parser) != XML_ERROR_PARTIAL_CHAR)
4922     xml_failure(g_parser);
4923 }
4924 END_TEST
4925 
4926 START_TEST(test_hash_collision) {
4927   /* For full coverage of the lookup routine, we need to ensure a
4928    * hash collision even though we can only tell that we have one
4929    * through breakpoint debugging or coverage statistics.  The
4930    * following will cause a hash collision on machines with a 64-bit
4931    * long type; others will have to experiment.  The full coverage
4932    * tests invoked from qa.sh usually provide a hash collision, but
4933    * not always.  This is an attempt to provide insurance.
4934    */
4935 #define COLLIDING_HASH_SALT (unsigned long)_SIP_ULL(0xffffffffU, 0xff99fc90U)
4936   const char *text
4937       = "<doc>\n"
4938         "<a1/><a2/><a3/><a4/><a5/><a6/><a7/><a8/>\n"
4939         "<b1></b1><b2 attr='foo'>This is a foo</b2><b3></b3><b4></b4>\n"
4940         "<b5></b5><b6></b6><b7></b7><b8></b8>\n"
4941         "<c1/><c2/><c3/><c4/><c5/><c6/><c7/><c8/>\n"
4942         "<d1/><d2/><d3/><d4/><d5/><d6/><d7/>\n"
4943         "<d8>This triggers the table growth and collides with b2</d8>\n"
4944         "</doc>\n";
4945 
4946   XML_SetHashSalt(g_parser, COLLIDING_HASH_SALT);
4947   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
4948       == XML_STATUS_ERROR)
4949     xml_failure(g_parser);
4950 }
4951 END_TEST
4952 #undef COLLIDING_HASH_SALT
4953 
4954 /* Test resuming a parse suspended in entity substitution */
4955 static void XMLCALL
4956 start_element_suspender(void *userData, const XML_Char *name,
4957                         const XML_Char **atts) {
4958   UNUSED_P(userData);
4959   UNUSED_P(atts);
4960   if (! xcstrcmp(name, XCS("suspend")))
4961     XML_StopParser(g_parser, XML_TRUE);
4962   if (! xcstrcmp(name, XCS("abort")))
4963     XML_StopParser(g_parser, XML_FALSE);
4964 }
4965 
4966 START_TEST(test_suspend_resume_internal_entity) {
4967   const char *text
4968       = "<!DOCTYPE doc [\n"
4969         "<!ENTITY foo '<suspend>Hi<suspend>Ho</suspend></suspend>'>\n"
4970         "]>\n"
4971         "<doc>&foo;</doc>\n";
4972   const XML_Char *expected1 = XCS("Hi");
4973   const XML_Char *expected2 = XCS("HiHo");
4974   CharData storage;
4975 
4976   CharData_Init(&storage);
4977   XML_SetStartElementHandler(g_parser, start_element_suspender);
4978   XML_SetCharacterDataHandler(g_parser, accumulate_characters);
4979   XML_SetUserData(g_parser, &storage);
4980   if (XML_Parse(g_parser, text, (int)strlen(text), XML_TRUE)
4981       != XML_STATUS_SUSPENDED)
4982     xml_failure(g_parser);
4983   CharData_CheckXMLChars(&storage, XCS(""));
4984   if (XML_ResumeParser(g_parser) != XML_STATUS_SUSPENDED)
4985     xml_failure(g_parser);
4986   CharData_CheckXMLChars(&storage, expected1);
4987   if (XML_ResumeParser(g_parser) != XML_STATUS_OK)
4988     xml_failure(g_parser);
4989   CharData_CheckXMLChars(&storage, expected2);
4990 }
4991 END_TEST
4992 
4993 void
4994 suspending_comment_handler(void *userData, const XML_Char *data) {
4995   UNUSED_P(data);
4996   XML_Parser parser = (XML_Parser)userData;
4997   XML_StopParser(parser, XML_TRUE);
4998 }
4999 
5000 START_TEST(test_suspend_resume_internal_entity_issue_629) {
5001   const char *const text
5002       = "<!DOCTYPE a [<!ENTITY e '<!--COMMENT-->a'>]><a>&e;<b>\n"
5003         "<"
5004         "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
5005         "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
5006         "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
5007         "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
5008         "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
5009         "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
5010         "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
5011         "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
5012         "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
5013         "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
5014         "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
5015         "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
5016         "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
5017         "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
5018         "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
5019         "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
5020         "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
5021         "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
5022         "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
5023         "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
5024         "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
5025         "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
5026         "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
5027         "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
5028         "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
5029         "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
5030         "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
5031         "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
5032         "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
5033         "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
5034         "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
5035         "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
5036         "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
5037         "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
5038         "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
5039         "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
5040         "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
5041         "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
5042         "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
5043         "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
5044         "/>"
5045         "</b></a>";
5046   const size_t firstChunkSizeBytes = 54;
5047 
5048   XML_Parser parser = XML_ParserCreate(NULL);
5049   XML_SetUserData(parser, parser);
5050   XML_SetCommentHandler(parser, suspending_comment_handler);
5051 
5052   if (XML_Parse(parser, text, (int)firstChunkSizeBytes, XML_FALSE)
5053       != XML_STATUS_SUSPENDED)
5054     xml_failure(parser);
5055   if (XML_ResumeParser(parser) != XML_STATUS_OK)
5056     xml_failure(parser);
5057   if (XML_Parse(parser, text + firstChunkSizeBytes,
5058                 (int)(strlen(text) - firstChunkSizeBytes), XML_TRUE)
5059       != XML_STATUS_OK)
5060     xml_failure(parser);
5061   XML_ParserFree(parser);
5062 }
5063 END_TEST
5064 
5065 /* Test syntax error is caught at parse resumption */
5066 START_TEST(test_resume_entity_with_syntax_error) {
5067   const char *text = "<!DOCTYPE doc [\n"
5068                      "<!ENTITY foo '<suspend>Hi</wombat>'>\n"
5069                      "]>\n"
5070                      "<doc>&foo;</doc>\n";
5071 
5072   XML_SetStartElementHandler(g_parser, start_element_suspender);
5073   if (XML_Parse(g_parser, text, (int)strlen(text), XML_TRUE)
5074       != XML_STATUS_SUSPENDED)
5075     xml_failure(g_parser);
5076   if (XML_ResumeParser(g_parser) != XML_STATUS_ERROR)
5077     fail("Syntax error in entity not faulted");
5078   if (XML_GetErrorCode(g_parser) != XML_ERROR_TAG_MISMATCH)
5079     xml_failure(g_parser);
5080 }
5081 END_TEST
5082 
5083 /* Test suspending and resuming in a parameter entity substitution */
5084 static void XMLCALL
5085 element_decl_suspender(void *userData, const XML_Char *name,
5086                        XML_Content *model) {
5087   UNUSED_P(userData);
5088   UNUSED_P(name);
5089   XML_StopParser(g_parser, XML_TRUE);
5090   XML_FreeContentModel(g_parser, model);
5091 }
5092 
5093 START_TEST(test_suspend_resume_parameter_entity) {
5094   const char *text = "<!DOCTYPE doc [\n"
5095                      "<!ENTITY % foo '<!ELEMENT doc (#PCDATA)*>'>\n"
5096                      "%foo;\n"
5097                      "]>\n"
5098                      "<doc>Hello, world</doc>";
5099   const XML_Char *expected = XCS("Hello, world");
5100   CharData storage;
5101 
5102   CharData_Init(&storage);
5103   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
5104   XML_SetElementDeclHandler(g_parser, element_decl_suspender);
5105   XML_SetCharacterDataHandler(g_parser, accumulate_characters);
5106   XML_SetUserData(g_parser, &storage);
5107   if (XML_Parse(g_parser, text, (int)strlen(text), XML_TRUE)
5108       != XML_STATUS_SUSPENDED)
5109     xml_failure(g_parser);
5110   CharData_CheckXMLChars(&storage, XCS(""));
5111   if (XML_ResumeParser(g_parser) != XML_STATUS_OK)
5112     xml_failure(g_parser);
5113   CharData_CheckXMLChars(&storage, expected);
5114 }
5115 END_TEST
5116 
5117 /* Test attempting to use parser after an error is faulted */
5118 START_TEST(test_restart_on_error) {
5119   const char *text = "<$doc><doc></doc>";
5120 
5121   if (XML_Parse(g_parser, text, (int)strlen(text), XML_TRUE)
5122       != XML_STATUS_ERROR)
5123     fail("Invalid tag name not faulted");
5124   if (XML_GetErrorCode(g_parser) != XML_ERROR_INVALID_TOKEN)
5125     xml_failure(g_parser);
5126   if (XML_Parse(g_parser, NULL, 0, XML_TRUE) != XML_STATUS_ERROR)
5127     fail("Restarting invalid parse not faulted");
5128   if (XML_GetErrorCode(g_parser) != XML_ERROR_INVALID_TOKEN)
5129     xml_failure(g_parser);
5130 }
5131 END_TEST
5132 
5133 /* Test that angle brackets in an attribute default value are faulted */
5134 START_TEST(test_reject_lt_in_attribute_value) {
5135   const char *text = "<!DOCTYPE doc [<!ATTLIST doc a CDATA '<bar>'>]>\n"
5136                      "<doc></doc>";
5137 
5138   expect_failure(text, XML_ERROR_INVALID_TOKEN,
5139                  "Bad attribute default not faulted");
5140 }
5141 END_TEST
5142 
5143 START_TEST(test_reject_unfinished_param_in_att_value) {
5144   const char *text = "<!DOCTYPE doc [<!ATTLIST doc a CDATA '&foo'>]>\n"
5145                      "<doc></doc>";
5146 
5147   expect_failure(text, XML_ERROR_INVALID_TOKEN,
5148                  "Bad attribute default not faulted");
5149 }
5150 END_TEST
5151 
5152 START_TEST(test_trailing_cr_in_att_value) {
5153   const char *text = "<doc a='value\r'/>";
5154 
5155   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
5156       == XML_STATUS_ERROR)
5157     xml_failure(g_parser);
5158 }
5159 END_TEST
5160 
5161 /* Try parsing a general entity within a parameter entity in a
5162  * standalone internal DTD.  Covers a corner case in the parser.
5163  */
5164 START_TEST(test_standalone_internal_entity) {
5165   const char *text = "<?xml version='1.0' standalone='yes' ?>\n"
5166                      "<!DOCTYPE doc [\n"
5167                      "  <!ELEMENT doc (#PCDATA)>\n"
5168                      "  <!ENTITY % pe '<!ATTLIST doc att2 CDATA \"&ge;\">'>\n"
5169                      "  <!ENTITY ge 'AttDefaultValue'>\n"
5170                      "  %pe;\n"
5171                      "]>\n"
5172                      "<doc att2='any'/>";
5173 
5174   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
5175   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
5176       == XML_STATUS_ERROR)
5177     xml_failure(g_parser);
5178 }
5179 END_TEST
5180 
5181 /* Test that a reference to an unknown external entity is skipped */
5182 START_TEST(test_skipped_external_entity) {
5183   const char *text = "<!DOCTYPE doc SYSTEM 'http://example.org/'>\n"
5184                      "<doc></doc>\n";
5185   ExtTest test_data = {"<!ELEMENT doc EMPTY>\n"
5186                        "<!ENTITY % e2 '%e1;'>\n",
5187                        NULL, NULL};
5188 
5189   XML_SetUserData(g_parser, &test_data);
5190   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
5191   XML_SetExternalEntityRefHandler(g_parser, external_entity_loader);
5192   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
5193       == XML_STATUS_ERROR)
5194     xml_failure(g_parser);
5195 }
5196 END_TEST
5197 
5198 /* Test a different form of unknown external entity */
5199 typedef struct ext_hdlr_data {
5200   const char *parse_text;
5201   XML_ExternalEntityRefHandler handler;
5202 } ExtHdlrData;
5203 
5204 static int XMLCALL
5205 external_entity_oneshot_loader(XML_Parser parser, const XML_Char *context,
5206                                const XML_Char *base, const XML_Char *systemId,
5207                                const XML_Char *publicId) {
5208   ExtHdlrData *test_data = (ExtHdlrData *)XML_GetUserData(parser);
5209   XML_Parser ext_parser;
5210 
5211   UNUSED_P(base);
5212   UNUSED_P(systemId);
5213   UNUSED_P(publicId);
5214   ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
5215   if (ext_parser == NULL)
5216     fail("Could not create external entity parser.");
5217   /* Use the requested entity parser for further externals */
5218   XML_SetExternalEntityRefHandler(ext_parser, test_data->handler);
5219   if (_XML_Parse_SINGLE_BYTES(ext_parser, test_data->parse_text,
5220                               (int)strlen(test_data->parse_text), XML_TRUE)
5221       == XML_STATUS_ERROR) {
5222     xml_failure(ext_parser);
5223   }
5224 
5225   XML_ParserFree(ext_parser);
5226   return XML_STATUS_OK;
5227 }
5228 
5229 START_TEST(test_skipped_null_loaded_ext_entity) {
5230   const char *text = "<!DOCTYPE doc SYSTEM 'http://example.org/one.ent'>\n"
5231                      "<doc />";
5232   ExtHdlrData test_data
5233       = {"<!ENTITY % pe1 SYSTEM 'http://example.org/two.ent'>\n"
5234          "<!ENTITY % pe2 '%pe1;'>\n"
5235          "%pe2;\n",
5236          external_entity_null_loader};
5237 
5238   XML_SetUserData(g_parser, &test_data);
5239   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
5240   XML_SetExternalEntityRefHandler(g_parser, external_entity_oneshot_loader);
5241   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
5242       == XML_STATUS_ERROR)
5243     xml_failure(g_parser);
5244 }
5245 END_TEST
5246 
5247 START_TEST(test_skipped_unloaded_ext_entity) {
5248   const char *text = "<!DOCTYPE doc SYSTEM 'http://example.org/one.ent'>\n"
5249                      "<doc />";
5250   ExtHdlrData test_data
5251       = {"<!ENTITY % pe1 SYSTEM 'http://example.org/two.ent'>\n"
5252          "<!ENTITY % pe2 '%pe1;'>\n"
5253          "%pe2;\n",
5254          NULL};
5255 
5256   XML_SetUserData(g_parser, &test_data);
5257   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
5258   XML_SetExternalEntityRefHandler(g_parser, external_entity_oneshot_loader);
5259   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
5260       == XML_STATUS_ERROR)
5261     xml_failure(g_parser);
5262 }
5263 END_TEST
5264 
5265 /* Test that a parameter entity value ending with a carriage return
5266  * has it translated internally into a newline.
5267  */
5268 START_TEST(test_param_entity_with_trailing_cr) {
5269 #define PARAM_ENTITY_NAME "pe"
5270 #define PARAM_ENTITY_CORE_VALUE "<!ATTLIST doc att CDATA \"default\">"
5271   const char *text = "<!DOCTYPE doc SYSTEM 'http://example.org/'>\n"
5272                      "<doc/>";
5273   ExtTest test_data
5274       = {"<!ENTITY % " PARAM_ENTITY_NAME " '" PARAM_ENTITY_CORE_VALUE "\r'>\n"
5275          "%" PARAM_ENTITY_NAME ";\n",
5276          NULL, NULL};
5277 
5278   XML_SetUserData(g_parser, &test_data);
5279   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
5280   XML_SetExternalEntityRefHandler(g_parser, external_entity_loader);
5281   XML_SetEntityDeclHandler(g_parser, param_entity_match_handler);
5282   entity_name_to_match = XCS(PARAM_ENTITY_NAME);
5283   entity_value_to_match = XCS(PARAM_ENTITY_CORE_VALUE) XCS("\n");
5284   entity_match_flag = ENTITY_MATCH_NOT_FOUND;
5285   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
5286       == XML_STATUS_ERROR)
5287     xml_failure(g_parser);
5288   if (entity_match_flag == ENTITY_MATCH_FAIL)
5289     fail("Parameter entity CR->NEWLINE conversion failed");
5290   else if (entity_match_flag == ENTITY_MATCH_NOT_FOUND)
5291     fail("Parameter entity not parsed");
5292 }
5293 #undef PARAM_ENTITY_NAME
5294 #undef PARAM_ENTITY_CORE_VALUE
5295 END_TEST
5296 
5297 START_TEST(test_invalid_character_entity) {
5298   const char *text = "<!DOCTYPE doc [\n"
5299                      "  <!ENTITY entity '&#x110000;'>\n"
5300                      "]>\n"
5301                      "<doc>&entity;</doc>";
5302 
5303   expect_failure(text, XML_ERROR_BAD_CHAR_REF,
5304                  "Out of range character reference not faulted");
5305 }
5306 END_TEST
5307 
5308 START_TEST(test_invalid_character_entity_2) {
5309   const char *text = "<!DOCTYPE doc [\n"
5310                      "  <!ENTITY entity '&#xg0;'>\n"
5311                      "]>\n"
5312                      "<doc>&entity;</doc>";
5313 
5314   expect_failure(text, XML_ERROR_INVALID_TOKEN,
5315                  "Out of range character reference not faulted");
5316 }
5317 END_TEST
5318 
5319 START_TEST(test_invalid_character_entity_3) {
5320   const char text[] =
5321       /* <!DOCTYPE doc [\n */
5322       "\0<\0!\0D\0O\0C\0T\0Y\0P\0E\0 \0d\0o\0c\0 \0[\0\n"
5323       /* U+0E04 = KHO KHWAI
5324        * U+0E08 = CHO CHAN */
5325       /* <!ENTITY entity '&\u0e04\u0e08;'>\n */
5326       "\0<\0!\0E\0N\0T\0I\0T\0Y\0 \0e\0n\0t\0i\0t\0y\0 "
5327       "\0'\0&\x0e\x04\x0e\x08\0;\0'\0>\0\n"
5328       /* ]>\n */
5329       "\0]\0>\0\n"
5330       /* <doc>&entity;</doc> */
5331       "\0<\0d\0o\0c\0>\0&\0e\0n\0t\0i\0t\0y\0;\0<\0/\0d\0o\0c\0>";
5332 
5333   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE)
5334       != XML_STATUS_ERROR)
5335     fail("Invalid start of entity name not faulted");
5336   if (XML_GetErrorCode(g_parser) != XML_ERROR_UNDEFINED_ENTITY)
5337     xml_failure(g_parser);
5338 }
5339 END_TEST
5340 
5341 START_TEST(test_invalid_character_entity_4) {
5342   const char *text = "<!DOCTYPE doc [\n"
5343                      "  <!ENTITY entity '&#1114112;'>\n" /* = &#x110000 */
5344                      "]>\n"
5345                      "<doc>&entity;</doc>";
5346 
5347   expect_failure(text, XML_ERROR_BAD_CHAR_REF,
5348                  "Out of range character reference not faulted");
5349 }
5350 END_TEST
5351 
5352 /* Test that processing instructions are picked up by a default handler */
5353 START_TEST(test_pi_handled_in_default) {
5354   const char *text = "<?test processing instruction?>\n<doc/>";
5355   const XML_Char *expected = XCS("<?test processing instruction?>\n<doc/>");
5356   CharData storage;
5357 
5358   CharData_Init(&storage);
5359   XML_SetDefaultHandler(g_parser, accumulate_characters);
5360   XML_SetUserData(g_parser, &storage);
5361   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
5362       == XML_STATUS_ERROR)
5363     xml_failure(g_parser);
5364   CharData_CheckXMLChars(&storage, expected);
5365 }
5366 END_TEST
5367 
5368 /* Test that comments are picked up by a default handler */
5369 START_TEST(test_comment_handled_in_default) {
5370   const char *text = "<!-- This is a comment -->\n<doc/>";
5371   const XML_Char *expected = XCS("<!-- This is a comment -->\n<doc/>");
5372   CharData storage;
5373 
5374   CharData_Init(&storage);
5375   XML_SetDefaultHandler(g_parser, accumulate_characters);
5376   XML_SetUserData(g_parser, &storage);
5377   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
5378       == XML_STATUS_ERROR)
5379     xml_failure(g_parser);
5380   CharData_CheckXMLChars(&storage, expected);
5381 }
5382 END_TEST
5383 
5384 /* Test PIs that look almost but not quite like XML declarations */
5385 static void XMLCALL
5386 accumulate_pi_characters(void *userData, const XML_Char *target,
5387                          const XML_Char *data) {
5388   CharData *storage = (CharData *)userData;
5389 
5390   CharData_AppendXMLChars(storage, target, -1);
5391   CharData_AppendXMLChars(storage, XCS(": "), 2);
5392   CharData_AppendXMLChars(storage, data, -1);
5393   CharData_AppendXMLChars(storage, XCS("\n"), 1);
5394 }
5395 
5396 START_TEST(test_pi_yml) {
5397   const char *text = "<?yml something like data?><doc/>";
5398   const XML_Char *expected = XCS("yml: something like data\n");
5399   CharData storage;
5400 
5401   CharData_Init(&storage);
5402   XML_SetProcessingInstructionHandler(g_parser, accumulate_pi_characters);
5403   XML_SetUserData(g_parser, &storage);
5404   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
5405       == XML_STATUS_ERROR)
5406     xml_failure(g_parser);
5407   CharData_CheckXMLChars(&storage, expected);
5408 }
5409 END_TEST
5410 
5411 START_TEST(test_pi_xnl) {
5412   const char *text = "<?xnl nothing like data?><doc/>";
5413   const XML_Char *expected = XCS("xnl: nothing like data\n");
5414   CharData storage;
5415 
5416   CharData_Init(&storage);
5417   XML_SetProcessingInstructionHandler(g_parser, accumulate_pi_characters);
5418   XML_SetUserData(g_parser, &storage);
5419   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
5420       == XML_STATUS_ERROR)
5421     xml_failure(g_parser);
5422   CharData_CheckXMLChars(&storage, expected);
5423 }
5424 END_TEST
5425 
5426 START_TEST(test_pi_xmm) {
5427   const char *text = "<?xmm everything like data?><doc/>";
5428   const XML_Char *expected = XCS("xmm: everything like data\n");
5429   CharData storage;
5430 
5431   CharData_Init(&storage);
5432   XML_SetProcessingInstructionHandler(g_parser, accumulate_pi_characters);
5433   XML_SetUserData(g_parser, &storage);
5434   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
5435       == XML_STATUS_ERROR)
5436     xml_failure(g_parser);
5437   CharData_CheckXMLChars(&storage, expected);
5438 }
5439 END_TEST
5440 
5441 START_TEST(test_utf16_pi) {
5442   const char text[] =
5443       /* <?{KHO KHWAI}{CHO CHAN}?>
5444        * where {KHO KHWAI} = U+0E04
5445        * and   {CHO CHAN}  = U+0E08
5446        */
5447       "<\0?\0\x04\x0e\x08\x0e?\0>\0"
5448       /* <q/> */
5449       "<\0q\0/\0>\0";
5450 #ifdef XML_UNICODE
5451   const XML_Char *expected = XCS("\x0e04\x0e08: \n");
5452 #else
5453   const XML_Char *expected = XCS("\xe0\xb8\x84\xe0\xb8\x88: \n");
5454 #endif
5455   CharData storage;
5456 
5457   CharData_Init(&storage);
5458   XML_SetProcessingInstructionHandler(g_parser, accumulate_pi_characters);
5459   XML_SetUserData(g_parser, &storage);
5460   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE)
5461       == XML_STATUS_ERROR)
5462     xml_failure(g_parser);
5463   CharData_CheckXMLChars(&storage, expected);
5464 }
5465 END_TEST
5466 
5467 START_TEST(test_utf16_be_pi) {
5468   const char text[] =
5469       /* <?{KHO KHWAI}{CHO CHAN}?>
5470        * where {KHO KHWAI} = U+0E04
5471        * and   {CHO CHAN}  = U+0E08
5472        */
5473       "\0<\0?\x0e\x04\x0e\x08\0?\0>"
5474       /* <q/> */
5475       "\0<\0q\0/\0>";
5476 #ifdef XML_UNICODE
5477   const XML_Char *expected = XCS("\x0e04\x0e08: \n");
5478 #else
5479   const XML_Char *expected = XCS("\xe0\xb8\x84\xe0\xb8\x88: \n");
5480 #endif
5481   CharData storage;
5482 
5483   CharData_Init(&storage);
5484   XML_SetProcessingInstructionHandler(g_parser, accumulate_pi_characters);
5485   XML_SetUserData(g_parser, &storage);
5486   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE)
5487       == XML_STATUS_ERROR)
5488     xml_failure(g_parser);
5489   CharData_CheckXMLChars(&storage, expected);
5490 }
5491 END_TEST
5492 
5493 /* Test that comments can be picked up and translated */
5494 static void XMLCALL
5495 accumulate_comment(void *userData, const XML_Char *data) {
5496   CharData *storage = (CharData *)userData;
5497 
5498   CharData_AppendXMLChars(storage, data, -1);
5499 }
5500 
5501 START_TEST(test_utf16_be_comment) {
5502   const char text[] =
5503       /* <!-- Comment A --> */
5504       "\0<\0!\0-\0-\0 \0C\0o\0m\0m\0e\0n\0t\0 \0A\0 \0-\0-\0>\0\n"
5505       /* <doc/> */
5506       "\0<\0d\0o\0c\0/\0>";
5507   const XML_Char *expected = XCS(" Comment A ");
5508   CharData storage;
5509 
5510   CharData_Init(&storage);
5511   XML_SetCommentHandler(g_parser, accumulate_comment);
5512   XML_SetUserData(g_parser, &storage);
5513   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE)
5514       == XML_STATUS_ERROR)
5515     xml_failure(g_parser);
5516   CharData_CheckXMLChars(&storage, expected);
5517 }
5518 END_TEST
5519 
5520 START_TEST(test_utf16_le_comment) {
5521   const char text[] =
5522       /* <!-- Comment B --> */
5523       "<\0!\0-\0-\0 \0C\0o\0m\0m\0e\0n\0t\0 \0B\0 \0-\0-\0>\0\n\0"
5524       /* <doc/> */
5525       "<\0d\0o\0c\0/\0>\0";
5526   const XML_Char *expected = XCS(" Comment B ");
5527   CharData storage;
5528 
5529   CharData_Init(&storage);
5530   XML_SetCommentHandler(g_parser, accumulate_comment);
5531   XML_SetUserData(g_parser, &storage);
5532   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE)
5533       == XML_STATUS_ERROR)
5534     xml_failure(g_parser);
5535   CharData_CheckXMLChars(&storage, expected);
5536 }
5537 END_TEST
5538 
5539 /* Test that the unknown encoding handler with map entries that expect
5540  * conversion but no conversion function is faulted
5541  */
5542 static int XMLCALL
5543 failing_converter(void *data, const char *s) {
5544   UNUSED_P(data);
5545   UNUSED_P(s);
5546   /* Always claim to have failed */
5547   return -1;
5548 }
5549 
5550 static int XMLCALL
5551 prefix_converter(void *data, const char *s) {
5552   UNUSED_P(data);
5553   /* If the first byte is 0xff, raise an error */
5554   if (s[0] == (char)-1)
5555     return -1;
5556   /* Just add the low bits of the first byte to the second */
5557   return (s[1] + (s[0] & 0x7f)) & 0x01ff;
5558 }
5559 
5560 static int XMLCALL
5561 MiscEncodingHandler(void *data, const XML_Char *encoding, XML_Encoding *info) {
5562   int i;
5563   int high_map = -2; /* Assume a 2-byte sequence */
5564 
5565   if (! xcstrcmp(encoding, XCS("invalid-9"))
5566       || ! xcstrcmp(encoding, XCS("ascii-like"))
5567       || ! xcstrcmp(encoding, XCS("invalid-len"))
5568       || ! xcstrcmp(encoding, XCS("invalid-a"))
5569       || ! xcstrcmp(encoding, XCS("invalid-surrogate"))
5570       || ! xcstrcmp(encoding, XCS("invalid-high")))
5571     high_map = -1;
5572 
5573   for (i = 0; i < 128; ++i)
5574     info->map[i] = i;
5575   for (; i < 256; ++i)
5576     info->map[i] = high_map;
5577 
5578   /* If required, put an invalid value in the ASCII entries */
5579   if (! xcstrcmp(encoding, XCS("invalid-9")))
5580     info->map[9] = 5;
5581   /* If required, have a top-bit set character starts a 5-byte sequence */
5582   if (! xcstrcmp(encoding, XCS("invalid-len")))
5583     info->map[0x81] = -5;
5584   /* If required, make a top-bit set character a valid ASCII character */
5585   if (! xcstrcmp(encoding, XCS("invalid-a")))
5586     info->map[0x82] = 'a';
5587   /* If required, give a top-bit set character a forbidden value,
5588    * what would otherwise be the first of a surrogate pair.
5589    */
5590   if (! xcstrcmp(encoding, XCS("invalid-surrogate")))
5591     info->map[0x83] = 0xd801;
5592   /* If required, give a top-bit set character too high a value */
5593   if (! xcstrcmp(encoding, XCS("invalid-high")))
5594     info->map[0x84] = 0x010101;
5595 
5596   info->data = data;
5597   info->release = NULL;
5598   if (! xcstrcmp(encoding, XCS("failing-conv")))
5599     info->convert = failing_converter;
5600   else if (! xcstrcmp(encoding, XCS("prefix-conv")))
5601     info->convert = prefix_converter;
5602   else
5603     info->convert = NULL;
5604   return XML_STATUS_OK;
5605 }
5606 
5607 START_TEST(test_missing_encoding_conversion_fn) {
5608   const char *text = "<?xml version='1.0' encoding='no-conv'?>\n"
5609                      "<doc>\x81</doc>";
5610 
5611   XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL);
5612   /* MiscEncodingHandler sets up an encoding with every top-bit-set
5613    * character introducing a two-byte sequence.  For this, it
5614    * requires a convert function.  The above function call doesn't
5615    * pass one through, so when BadEncodingHandler actually gets
5616    * called it should supply an invalid encoding.
5617    */
5618   expect_failure(text, XML_ERROR_UNKNOWN_ENCODING,
5619                  "Encoding with missing convert() not faulted");
5620 }
5621 END_TEST
5622 
5623 START_TEST(test_failing_encoding_conversion_fn) {
5624   const char *text = "<?xml version='1.0' encoding='failing-conv'?>\n"
5625                      "<doc>\x81</doc>";
5626 
5627   XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL);
5628   /* BadEncodingHandler sets up an encoding with every top-bit-set
5629    * character introducing a two-byte sequence.  For this, it
5630    * requires a convert function.  The above function call passes
5631    * one that insists all possible sequences are invalid anyway.
5632    */
5633   expect_failure(text, XML_ERROR_INVALID_TOKEN,
5634                  "Encoding with failing convert() not faulted");
5635 }
5636 END_TEST
5637 
5638 /* Test unknown encoding conversions */
5639 START_TEST(test_unknown_encoding_success) {
5640   const char *text = "<?xml version='1.0' encoding='prefix-conv'?>\n"
5641                      /* Equivalent to <eoc>Hello, world</eoc> */
5642                      "<\x81\x64\x80oc>Hello, world</\x81\x64\x80oc>";
5643 
5644   XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL);
5645   run_character_check(text, XCS("Hello, world"));
5646 }
5647 END_TEST
5648 
5649 /* Test bad name character in unknown encoding */
5650 START_TEST(test_unknown_encoding_bad_name) {
5651   const char *text = "<?xml version='1.0' encoding='prefix-conv'?>\n"
5652                      "<\xff\x64oc>Hello, world</\xff\x64oc>";
5653 
5654   XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL);
5655   expect_failure(text, XML_ERROR_INVALID_TOKEN,
5656                  "Bad name start in unknown encoding not faulted");
5657 }
5658 END_TEST
5659 
5660 /* Test bad mid-name character in unknown encoding */
5661 START_TEST(test_unknown_encoding_bad_name_2) {
5662   const char *text = "<?xml version='1.0' encoding='prefix-conv'?>\n"
5663                      "<d\xffoc>Hello, world</d\xffoc>";
5664 
5665   XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL);
5666   expect_failure(text, XML_ERROR_INVALID_TOKEN,
5667                  "Bad name in unknown encoding not faulted");
5668 }
5669 END_TEST
5670 
5671 /* Test element name that is long enough to fill the conversion buffer
5672  * in an unknown encoding, finishing with an encoded character.
5673  */
5674 START_TEST(test_unknown_encoding_long_name_1) {
5675   const char *text = "<?xml version='1.0' encoding='prefix-conv'?>\n"
5676                      "<abcdefghabcdefghabcdefghijkl\x80m\x80n\x80o\x80p>"
5677                      "Hi"
5678                      "</abcdefghabcdefghabcdefghijkl\x80m\x80n\x80o\x80p>";
5679   const XML_Char *expected = XCS("abcdefghabcdefghabcdefghijklmnop");
5680   CharData storage;
5681 
5682   CharData_Init(&storage);
5683   XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL);
5684   XML_SetStartElementHandler(g_parser, record_element_start_handler);
5685   XML_SetUserData(g_parser, &storage);
5686   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
5687       == XML_STATUS_ERROR)
5688     xml_failure(g_parser);
5689   CharData_CheckXMLChars(&storage, expected);
5690 }
5691 END_TEST
5692 
5693 /* Test element name that is long enough to fill the conversion buffer
5694  * in an unknown encoding, finishing with an simple character.
5695  */
5696 START_TEST(test_unknown_encoding_long_name_2) {
5697   const char *text = "<?xml version='1.0' encoding='prefix-conv'?>\n"
5698                      "<abcdefghabcdefghabcdefghijklmnop>"
5699                      "Hi"
5700                      "</abcdefghabcdefghabcdefghijklmnop>";
5701   const XML_Char *expected = XCS("abcdefghabcdefghabcdefghijklmnop");
5702   CharData storage;
5703 
5704   CharData_Init(&storage);
5705   XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL);
5706   XML_SetStartElementHandler(g_parser, record_element_start_handler);
5707   XML_SetUserData(g_parser, &storage);
5708   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
5709       == XML_STATUS_ERROR)
5710     xml_failure(g_parser);
5711   CharData_CheckXMLChars(&storage, expected);
5712 }
5713 END_TEST
5714 
5715 START_TEST(test_invalid_unknown_encoding) {
5716   const char *text = "<?xml version='1.0' encoding='invalid-9'?>\n"
5717                      "<doc>Hello world</doc>";
5718 
5719   XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL);
5720   expect_failure(text, XML_ERROR_UNKNOWN_ENCODING,
5721                  "Invalid unknown encoding not faulted");
5722 }
5723 END_TEST
5724 
5725 START_TEST(test_unknown_ascii_encoding_ok) {
5726   const char *text = "<?xml version='1.0' encoding='ascii-like'?>\n"
5727                      "<doc>Hello, world</doc>";
5728 
5729   XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL);
5730   run_character_check(text, XCS("Hello, world"));
5731 }
5732 END_TEST
5733 
5734 START_TEST(test_unknown_ascii_encoding_fail) {
5735   const char *text = "<?xml version='1.0' encoding='ascii-like'?>\n"
5736                      "<doc>Hello, \x80 world</doc>";
5737 
5738   XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL);
5739   expect_failure(text, XML_ERROR_INVALID_TOKEN,
5740                  "Invalid character not faulted");
5741 }
5742 END_TEST
5743 
5744 START_TEST(test_unknown_encoding_invalid_length) {
5745   const char *text = "<?xml version='1.0' encoding='invalid-len'?>\n"
5746                      "<doc>Hello, world</doc>";
5747 
5748   XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL);
5749   expect_failure(text, XML_ERROR_UNKNOWN_ENCODING,
5750                  "Invalid unknown encoding not faulted");
5751 }
5752 END_TEST
5753 
5754 START_TEST(test_unknown_encoding_invalid_topbit) {
5755   const char *text = "<?xml version='1.0' encoding='invalid-a'?>\n"
5756                      "<doc>Hello, world</doc>";
5757 
5758   XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL);
5759   expect_failure(text, XML_ERROR_UNKNOWN_ENCODING,
5760                  "Invalid unknown encoding not faulted");
5761 }
5762 END_TEST
5763 
5764 START_TEST(test_unknown_encoding_invalid_surrogate) {
5765   const char *text = "<?xml version='1.0' encoding='invalid-surrogate'?>\n"
5766                      "<doc>Hello, \x82 world</doc>";
5767 
5768   XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL);
5769   expect_failure(text, XML_ERROR_INVALID_TOKEN,
5770                  "Invalid unknown encoding not faulted");
5771 }
5772 END_TEST
5773 
5774 START_TEST(test_unknown_encoding_invalid_high) {
5775   const char *text = "<?xml version='1.0' encoding='invalid-high'?>\n"
5776                      "<doc>Hello, world</doc>";
5777 
5778   XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL);
5779   expect_failure(text, XML_ERROR_UNKNOWN_ENCODING,
5780                  "Invalid unknown encoding not faulted");
5781 }
5782 END_TEST
5783 
5784 START_TEST(test_unknown_encoding_invalid_attr_value) {
5785   const char *text = "<?xml version='1.0' encoding='prefix-conv'?>\n"
5786                      "<doc attr='\xff\x30'/>";
5787 
5788   XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL);
5789   expect_failure(text, XML_ERROR_INVALID_TOKEN,
5790                  "Invalid attribute valid not faulted");
5791 }
5792 END_TEST
5793 
5794 /* Test an external entity parser set to use latin-1 detects UTF-16
5795  * BOMs correctly.
5796  */
5797 enum ee_parse_flags { EE_PARSE_NONE = 0x00, EE_PARSE_FULL_BUFFER = 0x01 };
5798 
5799 typedef struct ExtTest2 {
5800   const char *parse_text;
5801   int parse_len;
5802   const XML_Char *encoding;
5803   CharData *storage;
5804   enum ee_parse_flags flags;
5805 } ExtTest2;
5806 
5807 static int XMLCALL
5808 external_entity_loader2(XML_Parser parser, const XML_Char *context,
5809                         const XML_Char *base, const XML_Char *systemId,
5810                         const XML_Char *publicId) {
5811   ExtTest2 *test_data = (ExtTest2 *)XML_GetUserData(parser);
5812   XML_Parser extparser;
5813 
5814   UNUSED_P(base);
5815   UNUSED_P(systemId);
5816   UNUSED_P(publicId);
5817   extparser = XML_ExternalEntityParserCreate(parser, context, NULL);
5818   if (extparser == NULL)
5819     fail("Coulr not create external entity parser");
5820   if (test_data->encoding != NULL) {
5821     if (! XML_SetEncoding(extparser, test_data->encoding))
5822       fail("XML_SetEncoding() ignored for external entity");
5823   }
5824   if (test_data->flags & EE_PARSE_FULL_BUFFER) {
5825     if (XML_Parse(extparser, test_data->parse_text, test_data->parse_len,
5826                   XML_TRUE)
5827         == XML_STATUS_ERROR) {
5828       xml_failure(extparser);
5829     }
5830   } else if (_XML_Parse_SINGLE_BYTES(extparser, test_data->parse_text,
5831                                      test_data->parse_len, XML_TRUE)
5832              == XML_STATUS_ERROR) {
5833     xml_failure(extparser);
5834   }
5835 
5836   XML_ParserFree(extparser);
5837   return XML_STATUS_OK;
5838 }
5839 
5840 /* Test that UTF-16 BOM does not select UTF-16 given explicit encoding */
5841 static void XMLCALL
5842 ext2_accumulate_characters(void *userData, const XML_Char *s, int len) {
5843   ExtTest2 *test_data = (ExtTest2 *)userData;
5844   accumulate_characters(test_data->storage, s, len);
5845 }
5846 
5847 START_TEST(test_ext_entity_latin1_utf16le_bom) {
5848   const char *text = "<!DOCTYPE doc [\n"
5849                      "  <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n"
5850                      "]>\n"
5851                      "<doc>&en;</doc>";
5852   ExtTest2 test_data
5853       = {/* If UTF-16, 0xfeff is the BOM and 0x204c is black left bullet */
5854          /* If Latin-1, 0xff = Y-diaeresis, 0xfe = lowercase thorn,
5855           *   0x4c = L and 0x20 is a space
5856           */
5857          "\xff\xfe\x4c\x20", 4, XCS("iso-8859-1"), NULL, EE_PARSE_NONE};
5858 #ifdef XML_UNICODE
5859   const XML_Char *expected = XCS("\x00ff\x00feL ");
5860 #else
5861   /* In UTF-8, y-diaeresis is 0xc3 0xbf, lowercase thorn is 0xc3 0xbe */
5862   const XML_Char *expected = XCS("\xc3\xbf\xc3\xbeL ");
5863 #endif
5864   CharData storage;
5865 
5866   CharData_Init(&storage);
5867   test_data.storage = &storage;
5868   XML_SetExternalEntityRefHandler(g_parser, external_entity_loader2);
5869   XML_SetUserData(g_parser, &test_data);
5870   XML_SetCharacterDataHandler(g_parser, ext2_accumulate_characters);
5871   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
5872       == XML_STATUS_ERROR)
5873     xml_failure(g_parser);
5874   CharData_CheckXMLChars(&storage, expected);
5875 }
5876 END_TEST
5877 
5878 START_TEST(test_ext_entity_latin1_utf16be_bom) {
5879   const char *text = "<!DOCTYPE doc [\n"
5880                      "  <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n"
5881                      "]>\n"
5882                      "<doc>&en;</doc>";
5883   ExtTest2 test_data
5884       = {/* If UTF-16, 0xfeff is the BOM and 0x204c is black left bullet */
5885          /* If Latin-1, 0xff = Y-diaeresis, 0xfe = lowercase thorn,
5886           *   0x4c = L and 0x20 is a space
5887           */
5888          "\xfe\xff\x20\x4c", 4, XCS("iso-8859-1"), NULL, EE_PARSE_NONE};
5889 #ifdef XML_UNICODE
5890   const XML_Char *expected = XCS("\x00fe\x00ff L");
5891 #else
5892   /* In UTF-8, y-diaeresis is 0xc3 0xbf, lowercase thorn is 0xc3 0xbe */
5893   const XML_Char *expected = XCS("\xc3\xbe\xc3\xbf L");
5894 #endif
5895   CharData storage;
5896 
5897   CharData_Init(&storage);
5898   test_data.storage = &storage;
5899   XML_SetExternalEntityRefHandler(g_parser, external_entity_loader2);
5900   XML_SetUserData(g_parser, &test_data);
5901   XML_SetCharacterDataHandler(g_parser, ext2_accumulate_characters);
5902   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
5903       == XML_STATUS_ERROR)
5904     xml_failure(g_parser);
5905   CharData_CheckXMLChars(&storage, expected);
5906 }
5907 END_TEST
5908 
5909 /* Parsing the full buffer rather than a byte at a time makes a
5910  * difference to the encoding scanning code, so repeat the above tests
5911  * without breaking them down by byte.
5912  */
5913 START_TEST(test_ext_entity_latin1_utf16le_bom2) {
5914   const char *text = "<!DOCTYPE doc [\n"
5915                      "  <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n"
5916                      "]>\n"
5917                      "<doc>&en;</doc>";
5918   ExtTest2 test_data
5919       = {/* If UTF-16, 0xfeff is the BOM and 0x204c is black left bullet */
5920          /* If Latin-1, 0xff = Y-diaeresis, 0xfe = lowercase thorn,
5921           *   0x4c = L and 0x20 is a space
5922           */
5923          "\xff\xfe\x4c\x20", 4, XCS("iso-8859-1"), NULL, EE_PARSE_FULL_BUFFER};
5924 #ifdef XML_UNICODE
5925   const XML_Char *expected = XCS("\x00ff\x00feL ");
5926 #else
5927   /* In UTF-8, y-diaeresis is 0xc3 0xbf, lowercase thorn is 0xc3 0xbe */
5928   const XML_Char *expected = XCS("\xc3\xbf\xc3\xbeL ");
5929 #endif
5930   CharData storage;
5931 
5932   CharData_Init(&storage);
5933   test_data.storage = &storage;
5934   XML_SetExternalEntityRefHandler(g_parser, external_entity_loader2);
5935   XML_SetUserData(g_parser, &test_data);
5936   XML_SetCharacterDataHandler(g_parser, ext2_accumulate_characters);
5937   if (XML_Parse(g_parser, text, (int)strlen(text), XML_TRUE)
5938       == XML_STATUS_ERROR)
5939     xml_failure(g_parser);
5940   CharData_CheckXMLChars(&storage, expected);
5941 }
5942 END_TEST
5943 
5944 START_TEST(test_ext_entity_latin1_utf16be_bom2) {
5945   const char *text = "<!DOCTYPE doc [\n"
5946                      "  <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n"
5947                      "]>\n"
5948                      "<doc>&en;</doc>";
5949   ExtTest2 test_data
5950       = {/* If UTF-16, 0xfeff is the BOM and 0x204c is black left bullet */
5951          /* If Latin-1, 0xff = Y-diaeresis, 0xfe = lowercase thorn,
5952           *   0x4c = L and 0x20 is a space
5953           */
5954          "\xfe\xff\x20\x4c", 4, XCS("iso-8859-1"), NULL, EE_PARSE_FULL_BUFFER};
5955 #ifdef XML_UNICODE
5956   const XML_Char *expected = XCS("\x00fe\x00ff L");
5957 #else
5958   /* In UTF-8, y-diaeresis is 0xc3 0xbf, lowercase thorn is 0xc3 0xbe */
5959   const XML_Char *expected = "\xc3\xbe\xc3\xbf L";
5960 #endif
5961   CharData storage;
5962 
5963   CharData_Init(&storage);
5964   test_data.storage = &storage;
5965   XML_SetExternalEntityRefHandler(g_parser, external_entity_loader2);
5966   XML_SetUserData(g_parser, &test_data);
5967   XML_SetCharacterDataHandler(g_parser, ext2_accumulate_characters);
5968   if (XML_Parse(g_parser, text, (int)strlen(text), XML_TRUE)
5969       == XML_STATUS_ERROR)
5970     xml_failure(g_parser);
5971   CharData_CheckXMLChars(&storage, expected);
5972 }
5973 END_TEST
5974 
5975 /* Test little-endian UTF-16 given an explicit big-endian encoding */
5976 START_TEST(test_ext_entity_utf16_be) {
5977   const char *text = "<!DOCTYPE doc [\n"
5978                      "  <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n"
5979                      "]>\n"
5980                      "<doc>&en;</doc>";
5981   ExtTest2 test_data
5982       = {"<\0e\0/\0>\0", 8, XCS("utf-16be"), NULL, EE_PARSE_NONE};
5983 #ifdef XML_UNICODE
5984   const XML_Char *expected = XCS("\x3c00\x6500\x2f00\x3e00");
5985 #else
5986   const XML_Char *expected = XCS("\xe3\xb0\x80"   /* U+3C00 */
5987                                  "\xe6\x94\x80"   /* U+6500 */
5988                                  "\xe2\xbc\x80"   /* U+2F00 */
5989                                  "\xe3\xb8\x80"); /* U+3E00 */
5990 #endif
5991   CharData storage;
5992 
5993   CharData_Init(&storage);
5994   test_data.storage = &storage;
5995   XML_SetExternalEntityRefHandler(g_parser, external_entity_loader2);
5996   XML_SetUserData(g_parser, &test_data);
5997   XML_SetCharacterDataHandler(g_parser, ext2_accumulate_characters);
5998   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
5999       == XML_STATUS_ERROR)
6000     xml_failure(g_parser);
6001   CharData_CheckXMLChars(&storage, expected);
6002 }
6003 END_TEST
6004 
6005 /* Test big-endian UTF-16 given an explicit little-endian encoding */
6006 START_TEST(test_ext_entity_utf16_le) {
6007   const char *text = "<!DOCTYPE doc [\n"
6008                      "  <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n"
6009                      "]>\n"
6010                      "<doc>&en;</doc>";
6011   ExtTest2 test_data
6012       = {"\0<\0e\0/\0>", 8, XCS("utf-16le"), NULL, EE_PARSE_NONE};
6013 #ifdef XML_UNICODE
6014   const XML_Char *expected = XCS("\x3c00\x6500\x2f00\x3e00");
6015 #else
6016   const XML_Char *expected = XCS("\xe3\xb0\x80"   /* U+3C00 */
6017                                  "\xe6\x94\x80"   /* U+6500 */
6018                                  "\xe2\xbc\x80"   /* U+2F00 */
6019                                  "\xe3\xb8\x80"); /* U+3E00 */
6020 #endif
6021   CharData storage;
6022 
6023   CharData_Init(&storage);
6024   test_data.storage = &storage;
6025   XML_SetExternalEntityRefHandler(g_parser, external_entity_loader2);
6026   XML_SetUserData(g_parser, &test_data);
6027   XML_SetCharacterDataHandler(g_parser, ext2_accumulate_characters);
6028   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
6029       == XML_STATUS_ERROR)
6030     xml_failure(g_parser);
6031   CharData_CheckXMLChars(&storage, expected);
6032 }
6033 END_TEST
6034 
6035 /* Test little-endian UTF-16 given no explicit encoding.
6036  * The existing default encoding (UTF-8) is assumed to hold without a
6037  * BOM to contradict it, so the entity value will in fact provoke an
6038  * error because 0x00 is not a valid XML character.  We parse the
6039  * whole buffer in one go rather than feeding it in byte by byte to
6040  * exercise different code paths in the initial scanning routines.
6041  */
6042 typedef struct ExtFaults2 {
6043   const char *parse_text;
6044   int parse_len;
6045   const char *fail_text;
6046   const XML_Char *encoding;
6047   enum XML_Error error;
6048 } ExtFaults2;
6049 
6050 static int XMLCALL
6051 external_entity_faulter2(XML_Parser parser, const XML_Char *context,
6052                          const XML_Char *base, const XML_Char *systemId,
6053                          const XML_Char *publicId) {
6054   ExtFaults2 *test_data = (ExtFaults2 *)XML_GetUserData(parser);
6055   XML_Parser extparser;
6056 
6057   UNUSED_P(base);
6058   UNUSED_P(systemId);
6059   UNUSED_P(publicId);
6060   extparser = XML_ExternalEntityParserCreate(parser, context, NULL);
6061   if (extparser == NULL)
6062     fail("Could not create external entity parser");
6063   if (test_data->encoding != NULL) {
6064     if (! XML_SetEncoding(extparser, test_data->encoding))
6065       fail("XML_SetEncoding() ignored for external entity");
6066   }
6067   if (XML_Parse(extparser, test_data->parse_text, test_data->parse_len,
6068                 XML_TRUE)
6069       != XML_STATUS_ERROR)
6070     fail(test_data->fail_text);
6071   if (XML_GetErrorCode(extparser) != test_data->error)
6072     xml_failure(extparser);
6073 
6074   XML_ParserFree(extparser);
6075   return XML_STATUS_ERROR;
6076 }
6077 
6078 START_TEST(test_ext_entity_utf16_unknown) {
6079   const char *text = "<!DOCTYPE doc [\n"
6080                      "  <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n"
6081                      "]>\n"
6082                      "<doc>&en;</doc>";
6083   ExtFaults2 test_data
6084       = {"a\0b\0c\0", 6, "Invalid character in entity not faulted", NULL,
6085          XML_ERROR_INVALID_TOKEN};
6086 
6087   XML_SetExternalEntityRefHandler(g_parser, external_entity_faulter2);
6088   XML_SetUserData(g_parser, &test_data);
6089   expect_failure(text, XML_ERROR_EXTERNAL_ENTITY_HANDLING,
6090                  "Invalid character should not have been accepted");
6091 }
6092 END_TEST
6093 
6094 /* Test not-quite-UTF-8 BOM (0xEF 0xBB 0xBF) */
6095 START_TEST(test_ext_entity_utf8_non_bom) {
6096   const char *text = "<!DOCTYPE doc [\n"
6097                      "  <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n"
6098                      "]>\n"
6099                      "<doc>&en;</doc>";
6100   ExtTest2 test_data
6101       = {"\xef\xbb\x80", /* Arabic letter DAD medial form, U+FEC0 */
6102          3, NULL, NULL, EE_PARSE_NONE};
6103 #ifdef XML_UNICODE
6104   const XML_Char *expected = XCS("\xfec0");
6105 #else
6106   const XML_Char *expected = XCS("\xef\xbb\x80");
6107 #endif
6108   CharData storage;
6109 
6110   CharData_Init(&storage);
6111   test_data.storage = &storage;
6112   XML_SetExternalEntityRefHandler(g_parser, external_entity_loader2);
6113   XML_SetUserData(g_parser, &test_data);
6114   XML_SetCharacterDataHandler(g_parser, ext2_accumulate_characters);
6115   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
6116       == XML_STATUS_ERROR)
6117     xml_failure(g_parser);
6118   CharData_CheckXMLChars(&storage, expected);
6119 }
6120 END_TEST
6121 
6122 /* Test that UTF-8 in a CDATA section is correctly passed through */
6123 START_TEST(test_utf8_in_cdata_section) {
6124   const char *text = "<doc><![CDATA[one \xc3\xa9 two]]></doc>";
6125 #ifdef XML_UNICODE
6126   const XML_Char *expected = XCS("one \x00e9 two");
6127 #else
6128   const XML_Char *expected = XCS("one \xc3\xa9 two");
6129 #endif
6130 
6131   run_character_check(text, expected);
6132 }
6133 END_TEST
6134 
6135 /* Test that little-endian UTF-16 in a CDATA section is handled */
6136 START_TEST(test_utf8_in_cdata_section_2) {
6137   const char *text = "<doc><![CDATA[\xc3\xa9]\xc3\xa9two]]></doc>";
6138 #ifdef XML_UNICODE
6139   const XML_Char *expected = XCS("\x00e9]\x00e9two");
6140 #else
6141   const XML_Char *expected = XCS("\xc3\xa9]\xc3\xa9two");
6142 #endif
6143 
6144   run_character_check(text, expected);
6145 }
6146 END_TEST
6147 
6148 START_TEST(test_utf8_in_start_tags) {
6149   struct test_case {
6150     bool goodName;
6151     bool goodNameStart;
6152     const char *tagName;
6153   };
6154 
6155   // The idea with the tests below is this:
6156   // We want to cover 1-, 2- and 3-byte sequences, 4-byte sequences
6157   // go to isNever and are hence not a concern.
6158   //
6159   // We start with a character that is a valid name character
6160   // (or even name-start character, see XML 1.0r4 spec) and then we flip
6161   // single bits at places where (1) the result leaves the UTF-8 encoding space
6162   // and (2) we stay in the same n-byte sequence family.
6163   //
6164   // The flipped bits are highlighted in angle brackets in comments,
6165   // e.g. "[<1>011 1001]" means we had [0011 1001] but we now flipped
6166   // the most significant bit to 1 to leave UTF-8 encoding space.
6167   struct test_case cases[] = {
6168       // 1-byte UTF-8: [0xxx xxxx]
6169       {true, true, "\x3A"},   // [0011 1010] = ASCII colon ':'
6170       {false, false, "\xBA"}, // [<1>011 1010]
6171       {true, false, "\x39"},  // [0011 1001] = ASCII nine '9'
6172       {false, false, "\xB9"}, // [<1>011 1001]
6173 
6174       // 2-byte UTF-8: [110x xxxx] [10xx xxxx]
6175       {true, true, "\xDB\xA5"},   // [1101 1011] [1010 0101] =
6176                                   // Arabic small waw U+06E5
6177       {false, false, "\x9B\xA5"}, // [1<0>01 1011] [1010 0101]
6178       {false, false, "\xDB\x25"}, // [1101 1011] [<0>010 0101]
6179       {false, false, "\xDB\xE5"}, // [1101 1011] [1<1>10 0101]
6180       {true, false, "\xCC\x81"},  // [1100 1100] [1000 0001] =
6181                                   // combining char U+0301
6182       {false, false, "\x8C\x81"}, // [1<0>00 1100] [1000 0001]
6183       {false, false, "\xCC\x01"}, // [1100 1100] [<0>000 0001]
6184       {false, false, "\xCC\xC1"}, // [1100 1100] [1<1>00 0001]
6185 
6186       // 3-byte UTF-8: [1110 xxxx] [10xx xxxx] [10xxxxxx]
6187       {true, true, "\xE0\xA4\x85"},   // [1110 0000] [1010 0100] [1000 0101] =
6188                                       // Devanagari Letter A U+0905
6189       {false, false, "\xA0\xA4\x85"}, // [1<0>10 0000] [1010 0100] [1000 0101]
6190       {false, false, "\xE0\x24\x85"}, // [1110 0000] [<0>010 0100] [1000 0101]
6191       {false, false, "\xE0\xE4\x85"}, // [1110 0000] [1<1>10 0100] [1000 0101]
6192       {false, false, "\xE0\xA4\x05"}, // [1110 0000] [1010 0100] [<0>000 0101]
6193       {false, false, "\xE0\xA4\xC5"}, // [1110 0000] [1010 0100] [1<1>00 0101]
6194       {true, false, "\xE0\xA4\x81"},  // [1110 0000] [1010 0100] [1000 0001] =
6195                                       // combining char U+0901
6196       {false, false, "\xA0\xA4\x81"}, // [1<0>10 0000] [1010 0100] [1000 0001]
6197       {false, false, "\xE0\x24\x81"}, // [1110 0000] [<0>010 0100] [1000 0001]
6198       {false, false, "\xE0\xE4\x81"}, // [1110 0000] [1<1>10 0100] [1000 0001]
6199       {false, false, "\xE0\xA4\x01"}, // [1110 0000] [1010 0100] [<0>000 0001]
6200       {false, false, "\xE0\xA4\xC1"}, // [1110 0000] [1010 0100] [1<1>00 0001]
6201   };
6202   const bool atNameStart[] = {true, false};
6203 
6204   size_t i = 0;
6205   char doc[1024];
6206   size_t failCount = 0;
6207 
6208   for (; i < sizeof(cases) / sizeof(cases[0]); i++) {
6209     size_t j = 0;
6210     for (; j < sizeof(atNameStart) / sizeof(atNameStart[0]); j++) {
6211       const bool expectedSuccess
6212           = atNameStart[j] ? cases[i].goodNameStart : cases[i].goodName;
6213       sprintf(doc, "<%s%s><!--", atNameStart[j] ? "" : "a", cases[i].tagName);
6214       XML_Parser parser = XML_ParserCreate(NULL);
6215 
6216       const enum XML_Status status
6217           = XML_Parse(parser, doc, (int)strlen(doc), /*isFinal=*/XML_FALSE);
6218 
6219       bool success = true;
6220       if ((status == XML_STATUS_OK) != expectedSuccess) {
6221         success = false;
6222       }
6223       if ((status == XML_STATUS_ERROR)
6224           && (XML_GetErrorCode(parser) != XML_ERROR_INVALID_TOKEN)) {
6225         success = false;
6226       }
6227 
6228       if (! success) {
6229         fprintf(
6230             stderr,
6231             "FAIL case %2u (%sat name start, %u-byte sequence, error code %d)\n",
6232             (unsigned)i + 1u, atNameStart[j] ? "    " : "not ",
6233             (unsigned)strlen(cases[i].tagName), XML_GetErrorCode(parser));
6234         failCount++;
6235       }
6236 
6237       XML_ParserFree(parser);
6238     }
6239   }
6240 
6241   if (failCount > 0) {
6242     fail("UTF-8 regression detected");
6243   }
6244 }
6245 END_TEST
6246 
6247 /* Test trailing spaces in elements are accepted */
6248 static void XMLCALL
6249 record_element_end_handler(void *userData, const XML_Char *name) {
6250   CharData *storage = (CharData *)userData;
6251 
6252   CharData_AppendXMLChars(storage, XCS("/"), 1);
6253   CharData_AppendXMLChars(storage, name, -1);
6254 }
6255 
6256 START_TEST(test_trailing_spaces_in_elements) {
6257   const char *text = "<doc   >Hi</doc >";
6258   const XML_Char *expected = XCS("doc/doc");
6259   CharData storage;
6260 
6261   CharData_Init(&storage);
6262   XML_SetElementHandler(g_parser, record_element_start_handler,
6263                         record_element_end_handler);
6264   XML_SetUserData(g_parser, &storage);
6265   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
6266       == XML_STATUS_ERROR)
6267     xml_failure(g_parser);
6268   CharData_CheckXMLChars(&storage, expected);
6269 }
6270 END_TEST
6271 
6272 START_TEST(test_utf16_attribute) {
6273   const char text[] =
6274       /* <d {KHO KHWAI}{CHO CHAN}='a'/>
6275        * where {KHO KHWAI} = U+0E04 = 0xe0 0xb8 0x84 in UTF-8
6276        * and   {CHO CHAN}  = U+0E08 = 0xe0 0xb8 0x88 in UTF-8
6277        */
6278       "<\0d\0 \0\x04\x0e\x08\x0e=\0'\0a\0'\0/\0>\0";
6279   const XML_Char *expected = XCS("a");
6280   CharData storage;
6281 
6282   CharData_Init(&storage);
6283   XML_SetStartElementHandler(g_parser, accumulate_attribute);
6284   XML_SetUserData(g_parser, &storage);
6285   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE)
6286       == XML_STATUS_ERROR)
6287     xml_failure(g_parser);
6288   CharData_CheckXMLChars(&storage, expected);
6289 }
6290 END_TEST
6291 
6292 START_TEST(test_utf16_second_attr) {
6293   /* <d a='1' {KHO KHWAI}{CHO CHAN}='2'/>
6294    * where {KHO KHWAI} = U+0E04 = 0xe0 0xb8 0x84 in UTF-8
6295    * and   {CHO CHAN}  = U+0E08 = 0xe0 0xb8 0x88 in UTF-8
6296    */
6297   const char text[] = "<\0d\0 \0a\0=\0'\0\x31\0'\0 \0"
6298                       "\x04\x0e\x08\x0e=\0'\0\x32\0'\0/\0>\0";
6299   const XML_Char *expected = XCS("1");
6300   CharData storage;
6301 
6302   CharData_Init(&storage);
6303   XML_SetStartElementHandler(g_parser, accumulate_attribute);
6304   XML_SetUserData(g_parser, &storage);
6305   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE)
6306       == XML_STATUS_ERROR)
6307     xml_failure(g_parser);
6308   CharData_CheckXMLChars(&storage, expected);
6309 }
6310 END_TEST
6311 
6312 START_TEST(test_attr_after_solidus) {
6313   const char *text = "<doc attr1='a' / attr2='b'>";
6314 
6315   expect_failure(text, XML_ERROR_INVALID_TOKEN, "Misplaced / not faulted");
6316 }
6317 END_TEST
6318 
6319 static void XMLCALL
6320 accumulate_entity_decl(void *userData, const XML_Char *entityName,
6321                        int is_parameter_entity, const XML_Char *value,
6322                        int value_length, const XML_Char *base,
6323                        const XML_Char *systemId, const XML_Char *publicId,
6324                        const XML_Char *notationName) {
6325   CharData *storage = (CharData *)userData;
6326 
6327   UNUSED_P(is_parameter_entity);
6328   UNUSED_P(base);
6329   UNUSED_P(systemId);
6330   UNUSED_P(publicId);
6331   UNUSED_P(notationName);
6332   CharData_AppendXMLChars(storage, entityName, -1);
6333   CharData_AppendXMLChars(storage, XCS("="), 1);
6334   CharData_AppendXMLChars(storage, value, value_length);
6335   CharData_AppendXMLChars(storage, XCS("\n"), 1);
6336 }
6337 
6338 START_TEST(test_utf16_pe) {
6339   /* <!DOCTYPE doc [
6340    * <!ENTITY % {KHO KHWAI}{CHO CHAN} '<!ELEMENT doc (#PCDATA)>'>
6341    * %{KHO KHWAI}{CHO CHAN};
6342    * ]>
6343    * <doc></doc>
6344    *
6345    * where {KHO KHWAI} = U+0E04 = 0xe0 0xb8 0x84 in UTF-8
6346    * and   {CHO CHAN}  = U+0E08 = 0xe0 0xb8 0x88 in UTF-8
6347    */
6348   const char text[] = "\0<\0!\0D\0O\0C\0T\0Y\0P\0E\0 \0d\0o\0c\0 \0[\0\n"
6349                       "\0<\0!\0E\0N\0T\0I\0T\0Y\0 \0%\0 \x0e\x04\x0e\x08\0 "
6350                       "\0'\0<\0!\0E\0L\0E\0M\0E\0N\0T\0 "
6351                       "\0d\0o\0c\0 \0(\0#\0P\0C\0D\0A\0T\0A\0)\0>\0'\0>\0\n"
6352                       "\0%\x0e\x04\x0e\x08\0;\0\n"
6353                       "\0]\0>\0\n"
6354                       "\0<\0d\0o\0c\0>\0<\0/\0d\0o\0c\0>";
6355 #ifdef XML_UNICODE
6356   const XML_Char *expected = XCS("\x0e04\x0e08=<!ELEMENT doc (#PCDATA)>\n");
6357 #else
6358   const XML_Char *expected
6359       = XCS("\xe0\xb8\x84\xe0\xb8\x88=<!ELEMENT doc (#PCDATA)>\n");
6360 #endif
6361   CharData storage;
6362 
6363   CharData_Init(&storage);
6364   XML_SetUserData(g_parser, &storage);
6365   XML_SetEntityDeclHandler(g_parser, accumulate_entity_decl);
6366   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE)
6367       == XML_STATUS_ERROR)
6368     xml_failure(g_parser);
6369   CharData_CheckXMLChars(&storage, expected);
6370 }
6371 END_TEST
6372 
6373 /* Test that duff attribute description keywords are rejected */
6374 START_TEST(test_bad_attr_desc_keyword) {
6375   const char *text = "<!DOCTYPE doc [\n"
6376                      "  <!ATTLIST doc attr CDATA #!IMPLIED>\n"
6377                      "]>\n"
6378                      "<doc />";
6379 
6380   expect_failure(text, XML_ERROR_INVALID_TOKEN,
6381                  "Bad keyword !IMPLIED not faulted");
6382 }
6383 END_TEST
6384 
6385 /* Test that an invalid attribute description keyword consisting of
6386  * UTF-16 characters with their top bytes non-zero are correctly
6387  * faulted
6388  */
6389 START_TEST(test_bad_attr_desc_keyword_utf16) {
6390   /* <!DOCTYPE d [
6391    * <!ATTLIST d a CDATA #{KHO KHWAI}{CHO CHAN}>
6392    * ]><d/>
6393    *
6394    * where {KHO KHWAI} = U+0E04 = 0xe0 0xb8 0x84 in UTF-8
6395    * and   {CHO CHAN}  = U+0E08 = 0xe0 0xb8 0x88 in UTF-8
6396    */
6397   const char text[]
6398       = "\0<\0!\0D\0O\0C\0T\0Y\0P\0E\0 \0d\0 \0[\0\n"
6399         "\0<\0!\0A\0T\0T\0L\0I\0S\0T\0 \0d\0 \0a\0 \0C\0D\0A\0T\0A\0 "
6400         "\0#\x0e\x04\x0e\x08\0>\0\n"
6401         "\0]\0>\0<\0d\0/\0>";
6402 
6403   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE)
6404       != XML_STATUS_ERROR)
6405     fail("Invalid UTF16 attribute keyword not faulted");
6406   if (XML_GetErrorCode(g_parser) != XML_ERROR_SYNTAX)
6407     xml_failure(g_parser);
6408 }
6409 END_TEST
6410 
6411 /* Test that invalid syntax in a <!DOCTYPE> is rejected.  Do this
6412  * using prefix-encoding (see above) to trigger specific code paths
6413  */
6414 START_TEST(test_bad_doctype) {
6415   const char *text = "<?xml version='1.0' encoding='prefix-conv'?>\n"
6416                      "<!DOCTYPE doc [ \x80\x44 ]><doc/>";
6417 
6418   XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL);
6419   expect_failure(text, XML_ERROR_SYNTAX,
6420                  "Invalid bytes in DOCTYPE not faulted");
6421 }
6422 END_TEST
6423 
6424 START_TEST(test_bad_doctype_utf8) {
6425   const char *text = "<!DOCTYPE \xDB\x25"
6426                      "doc><doc/>"; // [1101 1011] [<0>010 0101]
6427   expect_failure(text, XML_ERROR_INVALID_TOKEN,
6428                  "Invalid UTF-8 in DOCTYPE not faulted");
6429 }
6430 END_TEST
6431 
6432 START_TEST(test_bad_doctype_utf16) {
6433   const char text[] =
6434       /* <!DOCTYPE doc [ \x06f2 ]><doc/>
6435        *
6436        * U+06F2 = EXTENDED ARABIC-INDIC DIGIT TWO, a valid number
6437        * (name character) but not a valid letter (name start character)
6438        */
6439       "\0<\0!\0D\0O\0C\0T\0Y\0P\0E\0 \0d\0o\0c\0 \0[\0 "
6440       "\x06\xf2"
6441       "\0 \0]\0>\0<\0d\0o\0c\0/\0>";
6442 
6443   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE)
6444       != XML_STATUS_ERROR)
6445     fail("Invalid bytes in DOCTYPE not faulted");
6446   if (XML_GetErrorCode(g_parser) != XML_ERROR_SYNTAX)
6447     xml_failure(g_parser);
6448 }
6449 END_TEST
6450 
6451 START_TEST(test_bad_doctype_plus) {
6452   const char *text = "<!DOCTYPE 1+ [ <!ENTITY foo 'bar'> ]>\n"
6453                      "<1+>&foo;</1+>";
6454 
6455   expect_failure(text, XML_ERROR_INVALID_TOKEN,
6456                  "'+' in document name not faulted");
6457 }
6458 END_TEST
6459 
6460 START_TEST(test_bad_doctype_star) {
6461   const char *text = "<!DOCTYPE 1* [ <!ENTITY foo 'bar'> ]>\n"
6462                      "<1*>&foo;</1*>";
6463 
6464   expect_failure(text, XML_ERROR_INVALID_TOKEN,
6465                  "'*' in document name not faulted");
6466 }
6467 END_TEST
6468 
6469 START_TEST(test_bad_doctype_query) {
6470   const char *text = "<!DOCTYPE 1? [ <!ENTITY foo 'bar'> ]>\n"
6471                      "<1?>&foo;</1?>";
6472 
6473   expect_failure(text, XML_ERROR_INVALID_TOKEN,
6474                  "'?' in document name not faulted");
6475 }
6476 END_TEST
6477 
6478 START_TEST(test_unknown_encoding_bad_ignore) {
6479   const char *text = "<?xml version='1.0' encoding='prefix-conv'?>"
6480                      "<!DOCTYPE doc SYSTEM 'foo'>"
6481                      "<doc><e>&entity;</e></doc>";
6482   ExtFaults fault = {"<![IGNORE[<!ELEMENT \xffG (#PCDATA)*>]]>",
6483                      "Invalid character not faulted", XCS("prefix-conv"),
6484                      XML_ERROR_INVALID_TOKEN};
6485 
6486   XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL);
6487   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
6488   XML_SetExternalEntityRefHandler(g_parser, external_entity_faulter);
6489   XML_SetUserData(g_parser, &fault);
6490   expect_failure(text, XML_ERROR_EXTERNAL_ENTITY_HANDLING,
6491                  "Bad IGNORE section with unknown encoding not failed");
6492 }
6493 END_TEST
6494 
6495 START_TEST(test_entity_in_utf16_be_attr) {
6496   const char text[] =
6497       /* <e a='&#228; &#x00E4;'></e> */
6498       "\0<\0e\0 \0a\0=\0'\0&\0#\0\x32\0\x32\0\x38\0;\0 "
6499       "\0&\0#\0x\0\x30\0\x30\0E\0\x34\0;\0'\0>\0<\0/\0e\0>";
6500 #ifdef XML_UNICODE
6501   const XML_Char *expected = XCS("\x00e4 \x00e4");
6502 #else
6503   const XML_Char *expected = XCS("\xc3\xa4 \xc3\xa4");
6504 #endif
6505   CharData storage;
6506 
6507   CharData_Init(&storage);
6508   XML_SetUserData(g_parser, &storage);
6509   XML_SetStartElementHandler(g_parser, accumulate_attribute);
6510   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE)
6511       == XML_STATUS_ERROR)
6512     xml_failure(g_parser);
6513   CharData_CheckXMLChars(&storage, expected);
6514 }
6515 END_TEST
6516 
6517 START_TEST(test_entity_in_utf16_le_attr) {
6518   const char text[] =
6519       /* <e a='&#228; &#x00E4;'></e> */
6520       "<\0e\0 \0a\0=\0'\0&\0#\0\x32\0\x32\0\x38\0;\0 \0"
6521       "&\0#\0x\0\x30\0\x30\0E\0\x34\0;\0'\0>\0<\0/\0e\0>\0";
6522 #ifdef XML_UNICODE
6523   const XML_Char *expected = XCS("\x00e4 \x00e4");
6524 #else
6525   const XML_Char *expected = XCS("\xc3\xa4 \xc3\xa4");
6526 #endif
6527   CharData storage;
6528 
6529   CharData_Init(&storage);
6530   XML_SetUserData(g_parser, &storage);
6531   XML_SetStartElementHandler(g_parser, accumulate_attribute);
6532   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE)
6533       == XML_STATUS_ERROR)
6534     xml_failure(g_parser);
6535   CharData_CheckXMLChars(&storage, expected);
6536 }
6537 END_TEST
6538 
6539 START_TEST(test_entity_public_utf16_be) {
6540   const char text[] =
6541       /* <!DOCTYPE d [ */
6542       "\0<\0!\0D\0O\0C\0T\0Y\0P\0E\0 \0d\0 \0[\0\n"
6543       /* <!ENTITY % e PUBLIC 'foo' 'bar.ent'> */
6544       "\0<\0!\0E\0N\0T\0I\0T\0Y\0 \0%\0 \0e\0 \0P\0U\0B\0L\0I\0C\0 "
6545       "\0'\0f\0o\0o\0'\0 \0'\0b\0a\0r\0.\0e\0n\0t\0'\0>\0\n"
6546       /* %e; */
6547       "\0%\0e\0;\0\n"
6548       /* ]> */
6549       "\0]\0>\0\n"
6550       /* <d>&j;</d> */
6551       "\0<\0d\0>\0&\0j\0;\0<\0/\0d\0>";
6552   ExtTest2 test_data = {/* <!ENTITY j 'baz'> */
6553                         "\0<\0!\0E\0N\0T\0I\0T\0Y\0 \0j\0 \0'\0b\0a\0z\0'\0>",
6554                         34, NULL, NULL, EE_PARSE_NONE};
6555   const XML_Char *expected = XCS("baz");
6556   CharData storage;
6557 
6558   CharData_Init(&storage);
6559   test_data.storage = &storage;
6560   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
6561   XML_SetExternalEntityRefHandler(g_parser, external_entity_loader2);
6562   XML_SetUserData(g_parser, &test_data);
6563   XML_SetCharacterDataHandler(g_parser, ext2_accumulate_characters);
6564   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE)
6565       == XML_STATUS_ERROR)
6566     xml_failure(g_parser);
6567   CharData_CheckXMLChars(&storage, expected);
6568 }
6569 END_TEST
6570 
6571 START_TEST(test_entity_public_utf16_le) {
6572   const char text[] =
6573       /* <!DOCTYPE d [ */
6574       "<\0!\0D\0O\0C\0T\0Y\0P\0E\0 \0d\0 \0[\0\n\0"
6575       /* <!ENTITY % e PUBLIC 'foo' 'bar.ent'> */
6576       "<\0!\0E\0N\0T\0I\0T\0Y\0 \0%\0 \0e\0 \0P\0U\0B\0L\0I\0C\0 \0"
6577       "'\0f\0o\0o\0'\0 \0'\0b\0a\0r\0.\0e\0n\0t\0'\0>\0\n\0"
6578       /* %e; */
6579       "%\0e\0;\0\n\0"
6580       /* ]> */
6581       "]\0>\0\n\0"
6582       /* <d>&j;</d> */
6583       "<\0d\0>\0&\0j\0;\0<\0/\0d\0>\0";
6584   ExtTest2 test_data = {/* <!ENTITY j 'baz'> */
6585                         "<\0!\0E\0N\0T\0I\0T\0Y\0 \0j\0 \0'\0b\0a\0z\0'\0>\0",
6586                         34, NULL, NULL, EE_PARSE_NONE};
6587   const XML_Char *expected = XCS("baz");
6588   CharData storage;
6589 
6590   CharData_Init(&storage);
6591   test_data.storage = &storage;
6592   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
6593   XML_SetExternalEntityRefHandler(g_parser, external_entity_loader2);
6594   XML_SetUserData(g_parser, &test_data);
6595   XML_SetCharacterDataHandler(g_parser, ext2_accumulate_characters);
6596   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE)
6597       == XML_STATUS_ERROR)
6598     xml_failure(g_parser);
6599   CharData_CheckXMLChars(&storage, expected);
6600 }
6601 END_TEST
6602 
6603 /* Test that a doctype with neither an internal nor external subset is
6604  * faulted
6605  */
6606 START_TEST(test_short_doctype) {
6607   const char *text = "<!DOCTYPE doc></doc>";
6608   expect_failure(text, XML_ERROR_INVALID_TOKEN,
6609                  "DOCTYPE without subset not rejected");
6610 }
6611 END_TEST
6612 
6613 START_TEST(test_short_doctype_2) {
6614   const char *text = "<!DOCTYPE doc PUBLIC></doc>";
6615   expect_failure(text, XML_ERROR_SYNTAX,
6616                  "DOCTYPE without Public ID not rejected");
6617 }
6618 END_TEST
6619 
6620 START_TEST(test_short_doctype_3) {
6621   const char *text = "<!DOCTYPE doc SYSTEM></doc>";
6622   expect_failure(text, XML_ERROR_SYNTAX,
6623                  "DOCTYPE without System ID not rejected");
6624 }
6625 END_TEST
6626 
6627 START_TEST(test_long_doctype) {
6628   const char *text = "<!DOCTYPE doc PUBLIC 'foo' 'bar' 'baz'></doc>";
6629   expect_failure(text, XML_ERROR_SYNTAX, "DOCTYPE with extra ID not rejected");
6630 }
6631 END_TEST
6632 
6633 START_TEST(test_bad_entity) {
6634   const char *text = "<!DOCTYPE doc [\n"
6635                      "  <!ENTITY foo PUBLIC>\n"
6636                      "]>\n"
6637                      "<doc/>";
6638   expect_failure(text, XML_ERROR_SYNTAX,
6639                  "ENTITY without Public ID is not rejected");
6640 }
6641 END_TEST
6642 
6643 /* Test unquoted value is faulted */
6644 START_TEST(test_bad_entity_2) {
6645   const char *text = "<!DOCTYPE doc [\n"
6646                      "  <!ENTITY % foo bar>\n"
6647                      "]>\n"
6648                      "<doc/>";
6649   expect_failure(text, XML_ERROR_SYNTAX,
6650                  "ENTITY without Public ID is not rejected");
6651 }
6652 END_TEST
6653 
6654 START_TEST(test_bad_entity_3) {
6655   const char *text = "<!DOCTYPE doc [\n"
6656                      "  <!ENTITY % foo PUBLIC>\n"
6657                      "]>\n"
6658                      "<doc/>";
6659   expect_failure(text, XML_ERROR_SYNTAX,
6660                  "Parameter ENTITY without Public ID is not rejected");
6661 }
6662 END_TEST
6663 
6664 START_TEST(test_bad_entity_4) {
6665   const char *text = "<!DOCTYPE doc [\n"
6666                      "  <!ENTITY % foo SYSTEM>\n"
6667                      "]>\n"
6668                      "<doc/>";
6669   expect_failure(text, XML_ERROR_SYNTAX,
6670                  "Parameter ENTITY without Public ID is not rejected");
6671 }
6672 END_TEST
6673 
6674 START_TEST(test_bad_notation) {
6675   const char *text = "<!DOCTYPE doc [\n"
6676                      "  <!NOTATION n SYSTEM>\n"
6677                      "]>\n"
6678                      "<doc/>";
6679   expect_failure(text, XML_ERROR_SYNTAX,
6680                  "Notation without System ID is not rejected");
6681 }
6682 END_TEST
6683 
6684 /* Test for issue #11, wrongly suppressed default handler */
6685 typedef struct default_check {
6686   const XML_Char *expected;
6687   const int expectedLen;
6688   XML_Bool seen;
6689 } DefaultCheck;
6690 
6691 static void XMLCALL
6692 checking_default_handler(void *userData, const XML_Char *s, int len) {
6693   DefaultCheck *data = (DefaultCheck *)userData;
6694   int i;
6695 
6696   for (i = 0; data[i].expected != NULL; i++) {
6697     if (data[i].expectedLen == len
6698         && ! memcmp(data[i].expected, s, len * sizeof(XML_Char))) {
6699       data[i].seen = XML_TRUE;
6700       break;
6701     }
6702   }
6703 }
6704 
6705 START_TEST(test_default_doctype_handler) {
6706   const char *text = "<!DOCTYPE doc PUBLIC 'pubname' 'test.dtd' [\n"
6707                      "  <!ENTITY foo 'bar'>\n"
6708                      "]>\n"
6709                      "<doc>&foo;</doc>";
6710   DefaultCheck test_data[] = {{XCS("'pubname'"), 9, XML_FALSE},
6711                               {XCS("'test.dtd'"), 10, XML_FALSE},
6712                               {NULL, 0, XML_FALSE}};
6713   int i;
6714 
6715   XML_SetUserData(g_parser, &test_data);
6716   XML_SetDefaultHandler(g_parser, checking_default_handler);
6717   XML_SetEntityDeclHandler(g_parser, dummy_entity_decl_handler);
6718   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
6719       == XML_STATUS_ERROR)
6720     xml_failure(g_parser);
6721   for (i = 0; test_data[i].expected != NULL; i++)
6722     if (! test_data[i].seen)
6723       fail("Default handler not run for public !DOCTYPE");
6724 }
6725 END_TEST
6726 
6727 START_TEST(test_empty_element_abort) {
6728   const char *text = "<abort/>";
6729 
6730   XML_SetStartElementHandler(g_parser, start_element_suspender);
6731   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
6732       != XML_STATUS_ERROR)
6733     fail("Expected to error on abort");
6734 }
6735 END_TEST
6736 
6737 /*
6738  * Namespaces tests.
6739  */
6740 
6741 static void
6742 namespace_setup(void) {
6743   g_parser = XML_ParserCreateNS(NULL, XCS(' '));
6744   if (g_parser == NULL)
6745     fail("Parser not created.");
6746 }
6747 
6748 static void
6749 namespace_teardown(void) {
6750   basic_teardown();
6751 }
6752 
6753 /* Check that an element name and attribute name match the expected values.
6754    The expected values are passed as an array reference of string pointers
6755    provided as the userData argument; the first is the expected
6756    element name, and the second is the expected attribute name.
6757 */
6758 static int triplet_start_flag = XML_FALSE;
6759 static int triplet_end_flag = XML_FALSE;
6760 
6761 static void XMLCALL
6762 triplet_start_checker(void *userData, const XML_Char *name,
6763                       const XML_Char **atts) {
6764   XML_Char **elemstr = (XML_Char **)userData;
6765   char buffer[1024];
6766   if (xcstrcmp(elemstr[0], name) != 0) {
6767     sprintf(buffer, "unexpected start string: '%" XML_FMT_STR "'", name);
6768     fail(buffer);
6769   }
6770   if (xcstrcmp(elemstr[1], atts[0]) != 0) {
6771     sprintf(buffer, "unexpected attribute string: '%" XML_FMT_STR "'", atts[0]);
6772     fail(buffer);
6773   }
6774   triplet_start_flag = XML_TRUE;
6775 }
6776 
6777 /* Check that the element name passed to the end-element handler matches
6778    the expected value.  The expected value is passed as the first element
6779    in an array of strings passed as the userData argument.
6780 */
6781 static void XMLCALL
6782 triplet_end_checker(void *userData, const XML_Char *name) {
6783   XML_Char **elemstr = (XML_Char **)userData;
6784   if (xcstrcmp(elemstr[0], name) != 0) {
6785     char buffer[1024];
6786     sprintf(buffer, "unexpected end string: '%" XML_FMT_STR "'", name);
6787     fail(buffer);
6788   }
6789   triplet_end_flag = XML_TRUE;
6790 }
6791 
6792 START_TEST(test_return_ns_triplet) {
6793   const char *text = "<foo:e xmlns:foo='http://example.org/' bar:a='12'\n"
6794                      "       xmlns:bar='http://example.org/'>";
6795   const char *epilog = "</foo:e>";
6796   const XML_Char *elemstr[]
6797       = {XCS("http://example.org/ e foo"), XCS("http://example.org/ a bar")};
6798   XML_SetReturnNSTriplet(g_parser, XML_TRUE);
6799   XML_SetUserData(g_parser, (void *)elemstr);
6800   XML_SetElementHandler(g_parser, triplet_start_checker, triplet_end_checker);
6801   XML_SetNamespaceDeclHandler(g_parser, dummy_start_namespace_decl_handler,
6802                               dummy_end_namespace_decl_handler);
6803   triplet_start_flag = XML_FALSE;
6804   triplet_end_flag = XML_FALSE;
6805   dummy_handler_flags = 0;
6806   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_FALSE)
6807       == XML_STATUS_ERROR)
6808     xml_failure(g_parser);
6809   if (! triplet_start_flag)
6810     fail("triplet_start_checker not invoked");
6811   /* Check that unsetting "return triplets" fails while still parsing */
6812   XML_SetReturnNSTriplet(g_parser, XML_FALSE);
6813   if (_XML_Parse_SINGLE_BYTES(g_parser, epilog, (int)strlen(epilog), XML_TRUE)
6814       == XML_STATUS_ERROR)
6815     xml_failure(g_parser);
6816   if (! triplet_end_flag)
6817     fail("triplet_end_checker not invoked");
6818   if (dummy_handler_flags
6819       != (DUMMY_START_NS_DECL_HANDLER_FLAG | DUMMY_END_NS_DECL_HANDLER_FLAG))
6820     fail("Namespace handlers not called");
6821 }
6822 END_TEST
6823 
6824 static void XMLCALL
6825 overwrite_start_checker(void *userData, const XML_Char *name,
6826                         const XML_Char **atts) {
6827   CharData *storage = (CharData *)userData;
6828   CharData_AppendXMLChars(storage, XCS("start "), 6);
6829   CharData_AppendXMLChars(storage, name, -1);
6830   while (*atts != NULL) {
6831     CharData_AppendXMLChars(storage, XCS("\nattribute "), 11);
6832     CharData_AppendXMLChars(storage, *atts, -1);
6833     atts += 2;
6834   }
6835   CharData_AppendXMLChars(storage, XCS("\n"), 1);
6836 }
6837 
6838 static void XMLCALL
6839 overwrite_end_checker(void *userData, const XML_Char *name) {
6840   CharData *storage = (CharData *)userData;
6841   CharData_AppendXMLChars(storage, XCS("end "), 4);
6842   CharData_AppendXMLChars(storage, name, -1);
6843   CharData_AppendXMLChars(storage, XCS("\n"), 1);
6844 }
6845 
6846 static void
6847 run_ns_tagname_overwrite_test(const char *text, const XML_Char *result) {
6848   CharData storage;
6849   CharData_Init(&storage);
6850   XML_SetUserData(g_parser, &storage);
6851   XML_SetElementHandler(g_parser, overwrite_start_checker,
6852                         overwrite_end_checker);
6853   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
6854       == XML_STATUS_ERROR)
6855     xml_failure(g_parser);
6856   CharData_CheckXMLChars(&storage, result);
6857 }
6858 
6859 /* Regression test for SF bug #566334. */
6860 START_TEST(test_ns_tagname_overwrite) {
6861   const char *text = "<n:e xmlns:n='http://example.org/'>\n"
6862                      "  <n:f n:attr='foo'/>\n"
6863                      "  <n:g n:attr2='bar'/>\n"
6864                      "</n:e>";
6865   const XML_Char *result = XCS("start http://example.org/ e\n")
6866       XCS("start http://example.org/ f\n")
6867           XCS("attribute http://example.org/ attr\n")
6868               XCS("end http://example.org/ f\n")
6869                   XCS("start http://example.org/ g\n")
6870                       XCS("attribute http://example.org/ attr2\n")
6871                           XCS("end http://example.org/ g\n")
6872                               XCS("end http://example.org/ e\n");
6873   run_ns_tagname_overwrite_test(text, result);
6874 }
6875 END_TEST
6876 
6877 /* Regression test for SF bug #566334. */
6878 START_TEST(test_ns_tagname_overwrite_triplet) {
6879   const char *text = "<n:e xmlns:n='http://example.org/'>\n"
6880                      "  <n:f n:attr='foo'/>\n"
6881                      "  <n:g n:attr2='bar'/>\n"
6882                      "</n:e>";
6883   const XML_Char *result = XCS("start http://example.org/ e n\n")
6884       XCS("start http://example.org/ f n\n")
6885           XCS("attribute http://example.org/ attr n\n")
6886               XCS("end http://example.org/ f n\n")
6887                   XCS("start http://example.org/ g n\n")
6888                       XCS("attribute http://example.org/ attr2 n\n")
6889                           XCS("end http://example.org/ g n\n")
6890                               XCS("end http://example.org/ e n\n");
6891   XML_SetReturnNSTriplet(g_parser, XML_TRUE);
6892   run_ns_tagname_overwrite_test(text, result);
6893 }
6894 END_TEST
6895 
6896 /* Regression test for SF bug #620343. */
6897 static void XMLCALL
6898 start_element_fail(void *userData, const XML_Char *name,
6899                    const XML_Char **atts) {
6900   UNUSED_P(userData);
6901   UNUSED_P(name);
6902   UNUSED_P(atts);
6903 
6904   /* We should never get here. */
6905   fail("should never reach start_element_fail()");
6906 }
6907 
6908 static void XMLCALL
6909 start_ns_clearing_start_element(void *userData, const XML_Char *prefix,
6910                                 const XML_Char *uri) {
6911   UNUSED_P(prefix);
6912   UNUSED_P(uri);
6913   XML_SetStartElementHandler((XML_Parser)userData, NULL);
6914 }
6915 
6916 START_TEST(test_start_ns_clears_start_element) {
6917   /* This needs to use separate start/end tags; using the empty tag
6918      syntax doesn't cause the problematic path through Expat to be
6919      taken.
6920   */
6921   const char *text = "<e xmlns='http://example.org/'></e>";
6922 
6923   XML_SetStartElementHandler(g_parser, start_element_fail);
6924   XML_SetStartNamespaceDeclHandler(g_parser, start_ns_clearing_start_element);
6925   XML_SetEndNamespaceDeclHandler(g_parser, dummy_end_namespace_decl_handler);
6926   XML_UseParserAsHandlerArg(g_parser);
6927   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
6928       == XML_STATUS_ERROR)
6929     xml_failure(g_parser);
6930 }
6931 END_TEST
6932 
6933 /* Regression test for SF bug #616863. */
6934 static int XMLCALL
6935 external_entity_handler(XML_Parser parser, const XML_Char *context,
6936                         const XML_Char *base, const XML_Char *systemId,
6937                         const XML_Char *publicId) {
6938   intptr_t callno = 1 + (intptr_t)XML_GetUserData(parser);
6939   const char *text;
6940   XML_Parser p2;
6941 
6942   UNUSED_P(base);
6943   UNUSED_P(systemId);
6944   UNUSED_P(publicId);
6945   if (callno == 1)
6946     text = ("<!ELEMENT doc (e+)>\n"
6947             "<!ATTLIST doc xmlns CDATA #IMPLIED>\n"
6948             "<!ELEMENT e EMPTY>\n");
6949   else
6950     text = ("<?xml version='1.0' encoding='us-ascii'?>"
6951             "<e/>");
6952 
6953   XML_SetUserData(parser, (void *)callno);
6954   p2 = XML_ExternalEntityParserCreate(parser, context, NULL);
6955   if (_XML_Parse_SINGLE_BYTES(p2, text, (int)strlen(text), XML_TRUE)
6956       == XML_STATUS_ERROR) {
6957     xml_failure(p2);
6958     return XML_STATUS_ERROR;
6959   }
6960   XML_ParserFree(p2);
6961   return XML_STATUS_OK;
6962 }
6963 
6964 START_TEST(test_default_ns_from_ext_subset_and_ext_ge) {
6965   const char *text = "<?xml version='1.0'?>\n"
6966                      "<!DOCTYPE doc SYSTEM 'http://example.org/doc.dtd' [\n"
6967                      "  <!ENTITY en SYSTEM 'http://example.org/entity.ent'>\n"
6968                      "]>\n"
6969                      "<doc xmlns='http://example.org/ns1'>\n"
6970                      "&en;\n"
6971                      "</doc>";
6972 
6973   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
6974   XML_SetExternalEntityRefHandler(g_parser, external_entity_handler);
6975   /* We actually need to set this handler to tickle this bug. */
6976   XML_SetStartElementHandler(g_parser, dummy_start_element);
6977   XML_SetUserData(g_parser, NULL);
6978   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
6979       == XML_STATUS_ERROR)
6980     xml_failure(g_parser);
6981 }
6982 END_TEST
6983 
6984 /* Regression test #1 for SF bug #673791. */
6985 START_TEST(test_ns_prefix_with_empty_uri_1) {
6986   const char *text = "<doc xmlns:prefix='http://example.org/'>\n"
6987                      "  <e xmlns:prefix=''/>\n"
6988                      "</doc>";
6989 
6990   expect_failure(text, XML_ERROR_UNDECLARING_PREFIX,
6991                  "Did not report re-setting namespace"
6992                  " URI with prefix to ''.");
6993 }
6994 END_TEST
6995 
6996 /* Regression test #2 for SF bug #673791. */
6997 START_TEST(test_ns_prefix_with_empty_uri_2) {
6998   const char *text = "<?xml version='1.0'?>\n"
6999                      "<docelem xmlns:pre=''/>";
7000 
7001   expect_failure(text, XML_ERROR_UNDECLARING_PREFIX,
7002                  "Did not report setting namespace URI with prefix to ''.");
7003 }
7004 END_TEST
7005 
7006 /* Regression test #3 for SF bug #673791. */
7007 START_TEST(test_ns_prefix_with_empty_uri_3) {
7008   const char *text = "<!DOCTYPE doc [\n"
7009                      "  <!ELEMENT doc EMPTY>\n"
7010                      "  <!ATTLIST doc\n"
7011                      "    xmlns:prefix CDATA ''>\n"
7012                      "]>\n"
7013                      "<doc/>";
7014 
7015   expect_failure(text, XML_ERROR_UNDECLARING_PREFIX,
7016                  "Didn't report attr default setting NS w/ prefix to ''.");
7017 }
7018 END_TEST
7019 
7020 /* Regression test #4 for SF bug #673791. */
7021 START_TEST(test_ns_prefix_with_empty_uri_4) {
7022   const char *text = "<!DOCTYPE doc [\n"
7023                      "  <!ELEMENT prefix:doc EMPTY>\n"
7024                      "  <!ATTLIST prefix:doc\n"
7025                      "    xmlns:prefix CDATA 'http://example.org/'>\n"
7026                      "]>\n"
7027                      "<prefix:doc/>";
7028   /* Packaged info expected by the end element handler;
7029      the weird structuring lets us re-use the triplet_end_checker()
7030      function also used for another test. */
7031   const XML_Char *elemstr[] = {XCS("http://example.org/ doc prefix")};
7032   XML_SetReturnNSTriplet(g_parser, XML_TRUE);
7033   XML_SetUserData(g_parser, (void *)elemstr);
7034   XML_SetEndElementHandler(g_parser, triplet_end_checker);
7035   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
7036       == XML_STATUS_ERROR)
7037     xml_failure(g_parser);
7038 }
7039 END_TEST
7040 
7041 /* Test with non-xmlns prefix */
7042 START_TEST(test_ns_unbound_prefix) {
7043   const char *text = "<!DOCTYPE doc [\n"
7044                      "  <!ELEMENT prefix:doc EMPTY>\n"
7045                      "  <!ATTLIST prefix:doc\n"
7046                      "    notxmlns:prefix CDATA 'http://example.org/'>\n"
7047                      "]>\n"
7048                      "<prefix:doc/>";
7049 
7050   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
7051       != XML_STATUS_ERROR)
7052     fail("Unbound prefix incorrectly passed");
7053   if (XML_GetErrorCode(g_parser) != XML_ERROR_UNBOUND_PREFIX)
7054     xml_failure(g_parser);
7055 }
7056 END_TEST
7057 
7058 START_TEST(test_ns_default_with_empty_uri) {
7059   const char *text = "<doc xmlns='http://example.org/'>\n"
7060                      "  <e xmlns=''/>\n"
7061                      "</doc>";
7062   /* Add some handlers to exercise extra code paths */
7063   XML_SetStartNamespaceDeclHandler(g_parser,
7064                                    dummy_start_namespace_decl_handler);
7065   XML_SetEndNamespaceDeclHandler(g_parser, dummy_end_namespace_decl_handler);
7066   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
7067       == XML_STATUS_ERROR)
7068     xml_failure(g_parser);
7069 }
7070 END_TEST
7071 
7072 /* Regression test for SF bug #692964: two prefixes for one namespace. */
7073 START_TEST(test_ns_duplicate_attrs_diff_prefixes) {
7074   const char *text = "<doc xmlns:a='http://example.org/a'\n"
7075                      "     xmlns:b='http://example.org/a'\n"
7076                      "     a:a='v' b:a='v' />";
7077   expect_failure(text, XML_ERROR_DUPLICATE_ATTRIBUTE,
7078                  "did not report multiple attributes with same URI+name");
7079 }
7080 END_TEST
7081 
7082 START_TEST(test_ns_duplicate_hashes) {
7083   /* The hash of an attribute is calculated as the hash of its URI
7084    * concatenated with a space followed by its name (after the
7085    * colon).  We wish to generate attributes with the same hash
7086    * value modulo the attribute table size so that we can check that
7087    * the attribute hash table works correctly.  The attribute hash
7088    * table size will be the smallest power of two greater than the
7089    * number of attributes, but at least eight.  There is
7090    * unfortunately no programmatic way of getting the hash or the
7091    * table size at user level, but the test code coverage percentage
7092    * will drop if the hashes cease to point to the same row.
7093    *
7094    * The cunning plan is to have few enough attributes to have a
7095    * reliable table size of 8, and have the single letter attribute
7096    * names be 8 characters apart, producing a hash which will be the
7097    * same modulo 8.
7098    */
7099   const char *text = "<doc xmlns:a='http://example.org/a'\n"
7100                      "     a:a='v' a:i='w' />";
7101   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
7102       == XML_STATUS_ERROR)
7103     xml_failure(g_parser);
7104 }
7105 END_TEST
7106 
7107 /* Regression test for SF bug #695401: unbound prefix. */
7108 START_TEST(test_ns_unbound_prefix_on_attribute) {
7109   const char *text = "<doc a:attr=''/>";
7110   expect_failure(text, XML_ERROR_UNBOUND_PREFIX,
7111                  "did not report unbound prefix on attribute");
7112 }
7113 END_TEST
7114 
7115 /* Regression test for SF bug #695401: unbound prefix. */
7116 START_TEST(test_ns_unbound_prefix_on_element) {
7117   const char *text = "<a:doc/>";
7118   expect_failure(text, XML_ERROR_UNBOUND_PREFIX,
7119                  "did not report unbound prefix on element");
7120 }
7121 END_TEST
7122 
7123 /* Test that the parsing status is correctly reset by XML_ParserReset().
7124  * We usE test_return_ns_triplet() for our example parse to improve
7125  * coverage of tidying up code executed.
7126  */
7127 START_TEST(test_ns_parser_reset) {
7128   XML_ParsingStatus status;
7129 
7130   XML_GetParsingStatus(g_parser, &status);
7131   if (status.parsing != XML_INITIALIZED)
7132     fail("parsing status doesn't start INITIALIZED");
7133   test_return_ns_triplet();
7134   XML_GetParsingStatus(g_parser, &status);
7135   if (status.parsing != XML_FINISHED)
7136     fail("parsing status doesn't end FINISHED");
7137   XML_ParserReset(g_parser, NULL);
7138   XML_GetParsingStatus(g_parser, &status);
7139   if (status.parsing != XML_INITIALIZED)
7140     fail("parsing status doesn't reset to INITIALIZED");
7141 }
7142 END_TEST
7143 
7144 /* Test that long element names with namespaces are handled correctly */
7145 START_TEST(test_ns_long_element) {
7146   const char *text
7147       = "<foo:thisisalongenoughelementnametotriggerareallocation\n"
7148         " xmlns:foo='http://example.org/' bar:a='12'\n"
7149         " xmlns:bar='http://example.org/'>"
7150         "</foo:thisisalongenoughelementnametotriggerareallocation>";
7151   const XML_Char *elemstr[]
7152       = {XCS("http://example.org/")
7153              XCS(" thisisalongenoughelementnametotriggerareallocation foo"),
7154          XCS("http://example.org/ a bar")};
7155 
7156   XML_SetReturnNSTriplet(g_parser, XML_TRUE);
7157   XML_SetUserData(g_parser, (void *)elemstr);
7158   XML_SetElementHandler(g_parser, triplet_start_checker, triplet_end_checker);
7159   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
7160       == XML_STATUS_ERROR)
7161     xml_failure(g_parser);
7162 }
7163 END_TEST
7164 
7165 /* Test mixed population of prefixed and unprefixed attributes */
7166 START_TEST(test_ns_mixed_prefix_atts) {
7167   const char *text = "<e a='12' bar:b='13'\n"
7168                      " xmlns:bar='http://example.org/'>"
7169                      "</e>";
7170 
7171   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
7172       == XML_STATUS_ERROR)
7173     xml_failure(g_parser);
7174 }
7175 END_TEST
7176 
7177 /* Test having a long namespaced element name inside a short one.
7178  * This exercises some internal buffer reallocation that is shared
7179  * across elements with the same namespace URI.
7180  */
7181 START_TEST(test_ns_extend_uri_buffer) {
7182   const char *text = "<foo:e xmlns:foo='http://example.org/'>"
7183                      " <foo:thisisalongenoughnametotriggerallocationaction"
7184                      "   foo:a='12' />"
7185                      "</foo:e>";
7186   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
7187       == XML_STATUS_ERROR)
7188     xml_failure(g_parser);
7189 }
7190 END_TEST
7191 
7192 /* Test that xmlns is correctly rejected as an attribute in the xmlns
7193  * namespace, but not in other namespaces
7194  */
7195 START_TEST(test_ns_reserved_attributes) {
7196   const char *text1
7197       = "<foo:e xmlns:foo='http://example.org/' xmlns:xmlns='12' />";
7198   const char *text2
7199       = "<foo:e xmlns:foo='http://example.org/' foo:xmlns='12' />";
7200   expect_failure(text1, XML_ERROR_RESERVED_PREFIX_XMLNS,
7201                  "xmlns not rejected as an attribute");
7202   XML_ParserReset(g_parser, NULL);
7203   if (_XML_Parse_SINGLE_BYTES(g_parser, text2, (int)strlen(text2), XML_TRUE)
7204       == XML_STATUS_ERROR)
7205     xml_failure(g_parser);
7206 }
7207 END_TEST
7208 
7209 /* Test more reserved attributes */
7210 START_TEST(test_ns_reserved_attributes_2) {
7211   const char *text1 = "<foo:e xmlns:foo='http://example.org/'"
7212                       "  xmlns:xml='http://example.org/' />";
7213   const char *text2
7214       = "<foo:e xmlns:foo='http://www.w3.org/XML/1998/namespace' />";
7215   const char *text3 = "<foo:e xmlns:foo='http://www.w3.org/2000/xmlns/' />";
7216 
7217   expect_failure(text1, XML_ERROR_RESERVED_PREFIX_XML,
7218                  "xml not rejected as an attribute");
7219   XML_ParserReset(g_parser, NULL);
7220   expect_failure(text2, XML_ERROR_RESERVED_NAMESPACE_URI,
7221                  "Use of w3.org URL not faulted");
7222   XML_ParserReset(g_parser, NULL);
7223   expect_failure(text3, XML_ERROR_RESERVED_NAMESPACE_URI,
7224                  "Use of w3.org xmlns URL not faulted");
7225 }
7226 END_TEST
7227 
7228 /* Test string pool handling of namespace names of 2048 characters */
7229 /* Exercises a particular string pool growth path */
7230 START_TEST(test_ns_extremely_long_prefix) {
7231   /* C99 compilers are only required to support 4095-character
7232    * strings, so the following needs to be split in two to be safe
7233    * for all compilers.
7234    */
7235   const char *text1
7236       = "<doc "
7237         /* 64 character on each line */
7238         /* ...gives a total length of 2048 */
7239         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7240         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7241         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7242         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7243         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7244         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7245         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7246         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7247         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7248         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7249         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7250         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7251         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7252         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7253         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7254         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7255         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7256         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7257         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7258         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7259         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7260         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7261         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7262         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7263         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7264         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7265         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7266         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7267         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7268         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7269         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7270         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7271         ":a='12'";
7272   const char *text2
7273       = " xmlns:"
7274         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7275         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7276         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7277         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7278         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7279         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7280         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7281         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7282         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7283         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7284         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7285         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7286         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7287         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7288         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7289         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7290         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7291         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7292         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7293         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7294         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7295         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7296         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7297         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7298         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7299         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7300         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7301         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7302         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7303         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7304         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7305         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7306         "='foo'\n>"
7307         "</doc>";
7308 
7309   if (_XML_Parse_SINGLE_BYTES(g_parser, text1, (int)strlen(text1), XML_FALSE)
7310       == XML_STATUS_ERROR)
7311     xml_failure(g_parser);
7312   if (_XML_Parse_SINGLE_BYTES(g_parser, text2, (int)strlen(text2), XML_TRUE)
7313       == XML_STATUS_ERROR)
7314     xml_failure(g_parser);
7315 }
7316 END_TEST
7317 
7318 /* Test unknown encoding handlers in namespace setup */
7319 START_TEST(test_ns_unknown_encoding_success) {
7320   const char *text = "<?xml version='1.0' encoding='prefix-conv'?>\n"
7321                      "<foo:e xmlns:foo='http://example.org/'>Hi</foo:e>";
7322 
7323   XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL);
7324   run_character_check(text, XCS("Hi"));
7325 }
7326 END_TEST
7327 
7328 /* Test that too many colons are rejected */
7329 START_TEST(test_ns_double_colon) {
7330   const char *text = "<foo:e xmlns:foo='http://example.org/' foo:a:b='bar' />";
7331   const enum XML_Status status
7332       = _XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE);
7333 #ifdef XML_NS
7334   if ((status == XML_STATUS_OK)
7335       || (XML_GetErrorCode(g_parser) != XML_ERROR_INVALID_TOKEN)) {
7336     fail("Double colon in attribute name not faulted"
7337          " (despite active namespace support)");
7338   }
7339 #else
7340   if (status != XML_STATUS_OK) {
7341     fail("Double colon in attribute name faulted"
7342          " (despite inactive namespace support");
7343   }
7344 #endif
7345 }
7346 END_TEST
7347 
7348 START_TEST(test_ns_double_colon_element) {
7349   const char *text = "<foo:bar:e xmlns:foo='http://example.org/' />";
7350   const enum XML_Status status
7351       = _XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE);
7352 #ifdef XML_NS
7353   if ((status == XML_STATUS_OK)
7354       || (XML_GetErrorCode(g_parser) != XML_ERROR_INVALID_TOKEN)) {
7355     fail("Double colon in element name not faulted"
7356          " (despite active namespace support)");
7357   }
7358 #else
7359   if (status != XML_STATUS_OK) {
7360     fail("Double colon in element name faulted"
7361          " (despite inactive namespace support");
7362   }
7363 #endif
7364 }
7365 END_TEST
7366 
7367 /* Test that non-name characters after a colon are rejected */
7368 START_TEST(test_ns_bad_attr_leafname) {
7369   const char *text = "<foo:e xmlns:foo='http://example.org/' foo:?ar='baz' />";
7370 
7371   expect_failure(text, XML_ERROR_INVALID_TOKEN,
7372                  "Invalid character in leafname not faulted");
7373 }
7374 END_TEST
7375 
7376 START_TEST(test_ns_bad_element_leafname) {
7377   const char *text = "<foo:?oc xmlns:foo='http://example.org/' />";
7378 
7379   expect_failure(text, XML_ERROR_INVALID_TOKEN,
7380                  "Invalid character in element leafname not faulted");
7381 }
7382 END_TEST
7383 
7384 /* Test high-byte-set UTF-16 characters are valid in a leafname */
7385 START_TEST(test_ns_utf16_leafname) {
7386   const char text[] =
7387       /* <n:e xmlns:n='URI' n:{KHO KHWAI}='a' />
7388        * where {KHO KHWAI} = U+0E04 = 0xe0 0xb8 0x84 in UTF-8
7389        */
7390       "<\0n\0:\0e\0 \0x\0m\0l\0n\0s\0:\0n\0=\0'\0U\0R\0I\0'\0 \0"
7391       "n\0:\0\x04\x0e=\0'\0a\0'\0 \0/\0>\0";
7392   const XML_Char *expected = XCS("a");
7393   CharData storage;
7394 
7395   CharData_Init(&storage);
7396   XML_SetStartElementHandler(g_parser, accumulate_attribute);
7397   XML_SetUserData(g_parser, &storage);
7398   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE)
7399       == XML_STATUS_ERROR)
7400     xml_failure(g_parser);
7401   CharData_CheckXMLChars(&storage, expected);
7402 }
7403 END_TEST
7404 
7405 START_TEST(test_ns_utf16_element_leafname) {
7406   const char text[] =
7407       /* <n:{KHO KHWAI} xmlns:n='URI'/>
7408        * where {KHO KHWAI} = U+0E04 = 0xe0 0xb8 0x84 in UTF-8
7409        */
7410       "\0<\0n\0:\x0e\x04\0 \0x\0m\0l\0n\0s\0:\0n\0=\0'\0U\0R\0I\0'\0/\0>";
7411 #ifdef XML_UNICODE
7412   const XML_Char *expected = XCS("URI \x0e04");
7413 #else
7414   const XML_Char *expected = XCS("URI \xe0\xb8\x84");
7415 #endif
7416   CharData storage;
7417 
7418   CharData_Init(&storage);
7419   XML_SetStartElementHandler(g_parser, start_element_event_handler);
7420   XML_SetUserData(g_parser, &storage);
7421   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE)
7422       == XML_STATUS_ERROR)
7423     xml_failure(g_parser);
7424   CharData_CheckXMLChars(&storage, expected);
7425 }
7426 END_TEST
7427 
7428 START_TEST(test_ns_utf16_doctype) {
7429   const char text[] =
7430       /* <!DOCTYPE foo:{KHO KHWAI} [ <!ENTITY bar 'baz'> ]>\n
7431        * where {KHO KHWAI} = U+0E04 = 0xe0 0xb8 0x84 in UTF-8
7432        */
7433       "\0<\0!\0D\0O\0C\0T\0Y\0P\0E\0 \0f\0o\0o\0:\x0e\x04\0 "
7434       "\0[\0 \0<\0!\0E\0N\0T\0I\0T\0Y\0 \0b\0a\0r\0 \0'\0b\0a\0z\0'\0>\0 "
7435       "\0]\0>\0\n"
7436       /* <foo:{KHO KHWAI} xmlns:foo='URI'>&bar;</foo:{KHO KHWAI}> */
7437       "\0<\0f\0o\0o\0:\x0e\x04\0 "
7438       "\0x\0m\0l\0n\0s\0:\0f\0o\0o\0=\0'\0U\0R\0I\0'\0>"
7439       "\0&\0b\0a\0r\0;"
7440       "\0<\0/\0f\0o\0o\0:\x0e\x04\0>";
7441 #ifdef XML_UNICODE
7442   const XML_Char *expected = XCS("URI \x0e04");
7443 #else
7444   const XML_Char *expected = XCS("URI \xe0\xb8\x84");
7445 #endif
7446   CharData storage;
7447 
7448   CharData_Init(&storage);
7449   XML_SetUserData(g_parser, &storage);
7450   XML_SetStartElementHandler(g_parser, start_element_event_handler);
7451   XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL);
7452   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE)
7453       == XML_STATUS_ERROR)
7454     xml_failure(g_parser);
7455   CharData_CheckXMLChars(&storage, expected);
7456 }
7457 END_TEST
7458 
7459 START_TEST(test_ns_invalid_doctype) {
7460   const char *text = "<!DOCTYPE foo:!bad [ <!ENTITY bar 'baz' ]>\n"
7461                      "<foo:!bad>&bar;</foo:!bad>";
7462 
7463   expect_failure(text, XML_ERROR_INVALID_TOKEN,
7464                  "Invalid character in document local name not faulted");
7465 }
7466 END_TEST
7467 
7468 START_TEST(test_ns_double_colon_doctype) {
7469   const char *text = "<!DOCTYPE foo:a:doc [ <!ENTITY bar 'baz' ]>\n"
7470                      "<foo:a:doc>&bar;</foo:a:doc>";
7471 
7472   expect_failure(text, XML_ERROR_SYNTAX,
7473                  "Double colon in document name not faulted");
7474 }
7475 END_TEST
7476 
7477 START_TEST(test_ns_separator_in_uri) {
7478   struct test_case {
7479     enum XML_Status expectedStatus;
7480     const char *doc;
7481     XML_Char namesep;
7482   };
7483   struct test_case cases[] = {
7484       {XML_STATUS_OK, "<doc xmlns='one_two' />", XCS('\n')},
7485       {XML_STATUS_ERROR, "<doc xmlns='one&#x0A;two' />", XCS('\n')},
7486       {XML_STATUS_OK, "<doc xmlns='one:two' />", XCS(':')},
7487   };
7488 
7489   size_t i = 0;
7490   size_t failCount = 0;
7491   for (; i < sizeof(cases) / sizeof(cases[0]); i++) {
7492     XML_Parser parser = XML_ParserCreateNS(NULL, cases[i].namesep);
7493     XML_SetElementHandler(parser, dummy_start_element, dummy_end_element);
7494     if (XML_Parse(parser, cases[i].doc, (int)strlen(cases[i].doc),
7495                   /*isFinal*/ XML_TRUE)
7496         != cases[i].expectedStatus) {
7497       failCount++;
7498     }
7499     XML_ParserFree(parser);
7500   }
7501 
7502   if (failCount) {
7503     fail("Namespace separator handling is broken");
7504   }
7505 }
7506 END_TEST
7507 
7508 /* Control variable; the number of times duff_allocator() will successfully
7509  * allocate */
7510 #define ALLOC_ALWAYS_SUCCEED (-1)
7511 #define REALLOC_ALWAYS_SUCCEED (-1)
7512 
7513 static intptr_t allocation_count = ALLOC_ALWAYS_SUCCEED;
7514 static intptr_t reallocation_count = REALLOC_ALWAYS_SUCCEED;
7515 
7516 /* Crocked allocator for allocation failure tests */
7517 static void *
7518 duff_allocator(size_t size) {
7519   if (allocation_count == 0)
7520     return NULL;
7521   if (allocation_count != ALLOC_ALWAYS_SUCCEED)
7522     allocation_count--;
7523   return malloc(size);
7524 }
7525 
7526 /* Crocked reallocator for allocation failure tests */
7527 static void *
7528 duff_reallocator(void *ptr, size_t size) {
7529   if (reallocation_count == 0)
7530     return NULL;
7531   if (reallocation_count != REALLOC_ALWAYS_SUCCEED)
7532     reallocation_count--;
7533   return realloc(ptr, size);
7534 }
7535 
7536 /* Test that a failure to allocate the parser structure fails gracefully */
7537 START_TEST(test_misc_alloc_create_parser) {
7538   XML_Memory_Handling_Suite memsuite = {duff_allocator, realloc, free};
7539   unsigned int i;
7540   const unsigned int max_alloc_count = 10;
7541 
7542   /* Something this simple shouldn't need more than 10 allocations */
7543   for (i = 0; i < max_alloc_count; i++) {
7544     allocation_count = i;
7545     g_parser = XML_ParserCreate_MM(NULL, &memsuite, NULL);
7546     if (g_parser != NULL)
7547       break;
7548   }
7549   if (i == 0)
7550     fail("Parser unexpectedly ignored failing allocator");
7551   else if (i == max_alloc_count)
7552     fail("Parser not created with max allocation count");
7553 }
7554 END_TEST
7555 
7556 /* Test memory allocation failures for a parser with an encoding */
7557 START_TEST(test_misc_alloc_create_parser_with_encoding) {
7558   XML_Memory_Handling_Suite memsuite = {duff_allocator, realloc, free};
7559   unsigned int i;
7560   const unsigned int max_alloc_count = 10;
7561 
7562   /* Try several levels of allocation */
7563   for (i = 0; i < max_alloc_count; i++) {
7564     allocation_count = i;
7565     g_parser = XML_ParserCreate_MM(XCS("us-ascii"), &memsuite, NULL);
7566     if (g_parser != NULL)
7567       break;
7568   }
7569   if (i == 0)
7570     fail("Parser ignored failing allocator");
7571   else if (i == max_alloc_count)
7572     fail("Parser not created with max allocation count");
7573 }
7574 END_TEST
7575 
7576 /* Test that freeing a NULL parser doesn't cause an explosion.
7577  * (Not actually tested anywhere else)
7578  */
7579 START_TEST(test_misc_null_parser) {
7580   XML_ParserFree(NULL);
7581 }
7582 END_TEST
7583 
7584 /* Test that XML_ErrorString rejects out-of-range codes */
7585 START_TEST(test_misc_error_string) {
7586   if (XML_ErrorString((enum XML_Error) - 1) != NULL)
7587     fail("Negative error code not rejected");
7588   if (XML_ErrorString((enum XML_Error)100) != NULL)
7589     fail("Large error code not rejected");
7590 }
7591 END_TEST
7592 
7593 /* Test the version information is consistent */
7594 
7595 /* Since we are working in XML_LChars (potentially 16-bits), we
7596  * can't use the standard C library functions for character
7597  * manipulation and have to roll our own.
7598  */
7599 static int
7600 parse_version(const XML_LChar *version_text,
7601               XML_Expat_Version *version_struct) {
7602   if (! version_text)
7603     return XML_FALSE;
7604 
7605   while (*version_text != 0x00) {
7606     if (*version_text >= ASCII_0 && *version_text <= ASCII_9)
7607       break;
7608     version_text++;
7609   }
7610   if (*version_text == 0x00)
7611     return XML_FALSE;
7612 
7613   /* version_struct->major = strtoul(version_text, 10, &version_text) */
7614   version_struct->major = 0;
7615   while (*version_text >= ASCII_0 && *version_text <= ASCII_9) {
7616     version_struct->major
7617         = 10 * version_struct->major + (*version_text++ - ASCII_0);
7618   }
7619   if (*version_text++ != ASCII_PERIOD)
7620     return XML_FALSE;
7621 
7622   /* Now for the minor version number */
7623   version_struct->minor = 0;
7624   while (*version_text >= ASCII_0 && *version_text <= ASCII_9) {
7625     version_struct->minor
7626         = 10 * version_struct->minor + (*version_text++ - ASCII_0);
7627   }
7628   if (*version_text++ != ASCII_PERIOD)
7629     return XML_FALSE;
7630 
7631   /* Finally the micro version number */
7632   version_struct->micro = 0;
7633   while (*version_text >= ASCII_0 && *version_text <= ASCII_9) {
7634     version_struct->micro
7635         = 10 * version_struct->micro + (*version_text++ - ASCII_0);
7636   }
7637   if (*version_text != 0x00)
7638     return XML_FALSE;
7639   return XML_TRUE;
7640 }
7641 
7642 static int
7643 versions_equal(const XML_Expat_Version *first,
7644                const XML_Expat_Version *second) {
7645   return (first->major == second->major && first->minor == second->minor
7646           && first->micro == second->micro);
7647 }
7648 
7649 START_TEST(test_misc_version) {
7650   XML_Expat_Version read_version = XML_ExpatVersionInfo();
7651   /* Silence compiler warning with the following assignment */
7652   XML_Expat_Version parsed_version = {0, 0, 0};
7653   const XML_LChar *version_text = XML_ExpatVersion();
7654 
7655   if (version_text == NULL)
7656     fail("Could not obtain version text");
7657   assert(version_text != NULL);
7658   if (! parse_version(version_text, &parsed_version))
7659     fail("Unable to parse version text");
7660   if (! versions_equal(&read_version, &parsed_version))
7661     fail("Version mismatch");
7662 
7663 #if ! defined(XML_UNICODE) || defined(XML_UNICODE_WCHAR_T)
7664   if (xcstrcmp(version_text, XCS("expat_2.4.9"))) /* needs bump on releases */
7665     fail("XML_*_VERSION in expat.h out of sync?\n");
7666 #else
7667   /* If we have XML_UNICODE defined but not XML_UNICODE_WCHAR_T
7668    * then XML_LChar is defined as char, for some reason.
7669    */
7670   if (strcmp(version_text, "expat_2.2.5")) /* needs bump on releases */
7671     fail("XML_*_VERSION in expat.h out of sync?\n");
7672 #endif /* ! defined(XML_UNICODE) || defined(XML_UNICODE_WCHAR_T) */
7673 }
7674 END_TEST
7675 
7676 /* Test feature information */
7677 START_TEST(test_misc_features) {
7678   const XML_Feature *features = XML_GetFeatureList();
7679 
7680   /* Prevent problems with double-freeing parsers */
7681   g_parser = NULL;
7682   if (features == NULL) {
7683     fail("Failed to get feature information");
7684   } else {
7685     /* Loop through the features checking what we can */
7686     while (features->feature != XML_FEATURE_END) {
7687       switch (features->feature) {
7688       case XML_FEATURE_SIZEOF_XML_CHAR:
7689         if (features->value != sizeof(XML_Char))
7690           fail("Incorrect size of XML_Char");
7691         break;
7692       case XML_FEATURE_SIZEOF_XML_LCHAR:
7693         if (features->value != sizeof(XML_LChar))
7694           fail("Incorrect size of XML_LChar");
7695         break;
7696       default:
7697         break;
7698       }
7699       features++;
7700     }
7701   }
7702 }
7703 END_TEST
7704 
7705 /* Regression test for GitHub Issue #17: memory leak parsing attribute
7706  * values with mixed bound and unbound namespaces.
7707  */
7708 START_TEST(test_misc_attribute_leak) {
7709   const char *text = "<D xmlns:L=\"D\" l:a='' L:a=''/>";
7710   XML_Memory_Handling_Suite memsuite
7711       = {tracking_malloc, tracking_realloc, tracking_free};
7712 
7713   g_parser = XML_ParserCreate_MM(XCS("UTF-8"), &memsuite, XCS("\n"));
7714   expect_failure(text, XML_ERROR_UNBOUND_PREFIX, "Unbound prefixes not found");
7715   XML_ParserFree(g_parser);
7716   /* Prevent the teardown trying to double free */
7717   g_parser = NULL;
7718 
7719   if (! tracking_report())
7720     fail("Memory leak found");
7721 }
7722 END_TEST
7723 
7724 /* Test parser created for UTF-16LE is successful */
7725 START_TEST(test_misc_utf16le) {
7726   const char text[] =
7727       /* <?xml version='1.0'?><q>Hi</q> */
7728       "<\0?\0x\0m\0l\0 \0"
7729       "v\0e\0r\0s\0i\0o\0n\0=\0'\0\x31\0.\0\x30\0'\0?\0>\0"
7730       "<\0q\0>\0H\0i\0<\0/\0q\0>\0";
7731   const XML_Char *expected = XCS("Hi");
7732   CharData storage;
7733 
7734   g_parser = XML_ParserCreate(XCS("UTF-16LE"));
7735   if (g_parser == NULL)
7736     fail("Parser not created");
7737 
7738   CharData_Init(&storage);
7739   XML_SetUserData(g_parser, &storage);
7740   XML_SetCharacterDataHandler(g_parser, accumulate_characters);
7741   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE)
7742       == XML_STATUS_ERROR)
7743     xml_failure(g_parser);
7744   CharData_CheckXMLChars(&storage, expected);
7745 }
7746 END_TEST
7747 
7748 typedef struct {
7749   XML_Parser parser;
7750   int deep;
7751 } DataIssue240;
7752 
7753 static void
7754 start_element_issue_240(void *userData, const XML_Char *name,
7755                         const XML_Char **atts) {
7756   DataIssue240 *mydata = (DataIssue240 *)userData;
7757   UNUSED_P(name);
7758   UNUSED_P(atts);
7759   mydata->deep++;
7760 }
7761 
7762 static void
7763 end_element_issue_240(void *userData, const XML_Char *name) {
7764   DataIssue240 *mydata = (DataIssue240 *)userData;
7765 
7766   UNUSED_P(name);
7767   mydata->deep--;
7768   if (mydata->deep == 0) {
7769     XML_StopParser(mydata->parser, 0);
7770   }
7771 }
7772 
7773 START_TEST(test_misc_stop_during_end_handler_issue_240_1) {
7774   XML_Parser parser;
7775   DataIssue240 *mydata;
7776   enum XML_Status result;
7777   const char *const doc1 = "<doc><e1/><e><foo/></e></doc>";
7778 
7779   parser = XML_ParserCreate(NULL);
7780   XML_SetElementHandler(parser, start_element_issue_240, end_element_issue_240);
7781   mydata = (DataIssue240 *)malloc(sizeof(DataIssue240));
7782   mydata->parser = parser;
7783   mydata->deep = 0;
7784   XML_SetUserData(parser, mydata);
7785 
7786   result = XML_Parse(parser, doc1, (int)strlen(doc1), 1);
7787   XML_ParserFree(parser);
7788   free(mydata);
7789   if (result != XML_STATUS_ERROR)
7790     fail("Stopping the parser did not work as expected");
7791 }
7792 END_TEST
7793 
7794 START_TEST(test_misc_stop_during_end_handler_issue_240_2) {
7795   XML_Parser parser;
7796   DataIssue240 *mydata;
7797   enum XML_Status result;
7798   const char *const doc2 = "<doc><elem/></doc>";
7799 
7800   parser = XML_ParserCreate(NULL);
7801   XML_SetElementHandler(parser, start_element_issue_240, end_element_issue_240);
7802   mydata = (DataIssue240 *)malloc(sizeof(DataIssue240));
7803   mydata->parser = parser;
7804   mydata->deep = 0;
7805   XML_SetUserData(parser, mydata);
7806 
7807   result = XML_Parse(parser, doc2, (int)strlen(doc2), 1);
7808   XML_ParserFree(parser);
7809   free(mydata);
7810   if (result != XML_STATUS_ERROR)
7811     fail("Stopping the parser did not work as expected");
7812 }
7813 END_TEST
7814 
7815 START_TEST(test_misc_deny_internal_entity_closing_doctype_issue_317) {
7816   const char *const inputOne = "<!DOCTYPE d [\n"
7817                                "<!ENTITY % e ']><d/>'>\n"
7818                                "\n"
7819                                "%e;";
7820   const char *const inputTwo = "<!DOCTYPE d [\n"
7821                                "<!ENTITY % e1 ']><d/>'><!ENTITY % e2 '&e1;'>\n"
7822                                "\n"
7823                                "%e2;";
7824   const char *const inputThree = "<!DOCTYPE d [\n"
7825                                  "<!ENTITY % e ']><d'>\n"
7826                                  "\n"
7827                                  "%e;";
7828   const char *const inputIssue317 = "<!DOCTYPE doc [\n"
7829                                     "<!ENTITY % foo ']>\n"
7830                                     "<doc>Hell<oc (#PCDATA)*>'>\n"
7831                                     "%foo;\n"
7832                                     "]>\n"
7833                                     "<doc>Hello, world</dVc>";
7834 
7835   const char *const inputs[] = {inputOne, inputTwo, inputThree, inputIssue317};
7836   size_t inputIndex = 0;
7837 
7838   for (; inputIndex < sizeof(inputs) / sizeof(inputs[0]); inputIndex++) {
7839     XML_Parser parser;
7840     enum XML_Status parseResult;
7841     int setParamEntityResult;
7842     XML_Size lineNumber;
7843     XML_Size columnNumber;
7844     const char *const input = inputs[inputIndex];
7845 
7846     parser = XML_ParserCreate(NULL);
7847     setParamEntityResult
7848         = XML_SetParamEntityParsing(parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
7849     if (setParamEntityResult != 1)
7850       fail("Failed to set XML_PARAM_ENTITY_PARSING_ALWAYS.");
7851 
7852     parseResult = XML_Parse(parser, input, (int)strlen(input), 0);
7853     if (parseResult != XML_STATUS_ERROR) {
7854       parseResult = XML_Parse(parser, "", 0, 1);
7855       if (parseResult != XML_STATUS_ERROR) {
7856         fail("Parsing was expected to fail but succeeded.");
7857       }
7858     }
7859 
7860     if (XML_GetErrorCode(parser) != XML_ERROR_INVALID_TOKEN)
7861       fail("Error code does not match XML_ERROR_INVALID_TOKEN");
7862 
7863     lineNumber = XML_GetCurrentLineNumber(parser);
7864     if (lineNumber != 4)
7865       fail("XML_GetCurrentLineNumber does not work as expected.");
7866 
7867     columnNumber = XML_GetCurrentColumnNumber(parser);
7868     if (columnNumber != 0)
7869       fail("XML_GetCurrentColumnNumber does not work as expected.");
7870 
7871     XML_ParserFree(parser);
7872   }
7873 }
7874 END_TEST
7875 
7876 static void
7877 alloc_setup(void) {
7878   XML_Memory_Handling_Suite memsuite = {duff_allocator, duff_reallocator, free};
7879 
7880   /* Ensure the parser creation will go through */
7881   allocation_count = ALLOC_ALWAYS_SUCCEED;
7882   reallocation_count = REALLOC_ALWAYS_SUCCEED;
7883   g_parser = XML_ParserCreate_MM(NULL, &memsuite, NULL);
7884   if (g_parser == NULL)
7885     fail("Parser not created");
7886 }
7887 
7888 static void
7889 alloc_teardown(void) {
7890   basic_teardown();
7891 }
7892 
7893 /* Test the effects of allocation failures on xml declaration processing */
7894 START_TEST(test_alloc_parse_xdecl) {
7895   const char *text = "<?xml version='1.0' encoding='utf-8'?>\n"
7896                      "<doc>Hello, world</doc>";
7897   int i;
7898   const int max_alloc_count = 15;
7899 
7900   for (i = 0; i < max_alloc_count; i++) {
7901     allocation_count = i;
7902     XML_SetXmlDeclHandler(g_parser, dummy_xdecl_handler);
7903     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
7904         != XML_STATUS_ERROR)
7905       break;
7906     /* Resetting the parser is insufficient, because some memory
7907      * allocations are cached within the parser.  Instead we use
7908      * the teardown and setup routines to ensure that we have the
7909      * right sort of parser back in our hands.
7910      */
7911     alloc_teardown();
7912     alloc_setup();
7913   }
7914   if (i == 0)
7915     fail("Parse succeeded despite failing allocator");
7916   if (i == max_alloc_count)
7917     fail("Parse failed with max allocations");
7918 }
7919 END_TEST
7920 
7921 /* As above, but with an encoding big enough to cause storing the
7922  * version information to expand the string pool being used.
7923  */
7924 static int XMLCALL
7925 long_encoding_handler(void *userData, const XML_Char *encoding,
7926                       XML_Encoding *info) {
7927   int i;
7928 
7929   UNUSED_P(userData);
7930   UNUSED_P(encoding);
7931   for (i = 0; i < 256; i++)
7932     info->map[i] = i;
7933   info->data = NULL;
7934   info->convert = NULL;
7935   info->release = NULL;
7936   return XML_STATUS_OK;
7937 }
7938 
7939 START_TEST(test_alloc_parse_xdecl_2) {
7940   const char *text
7941       = "<?xml version='1.0' encoding='"
7942         /* Each line is 64 characters */
7943         "ThisIsAStupidlyLongEncodingNameIntendedToTriggerPoolGrowth123456"
7944         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7945         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7946         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7947         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7948         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7949         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7950         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7951         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7952         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7953         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7954         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7955         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7956         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7957         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7958         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMN"
7959         "'?>"
7960         "<doc>Hello, world</doc>";
7961   int i;
7962   const int max_alloc_count = 20;
7963 
7964   for (i = 0; i < max_alloc_count; i++) {
7965     allocation_count = i;
7966     XML_SetXmlDeclHandler(g_parser, dummy_xdecl_handler);
7967     XML_SetUnknownEncodingHandler(g_parser, long_encoding_handler, NULL);
7968     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
7969         != XML_STATUS_ERROR)
7970       break;
7971     /* See comment in test_alloc_parse_xdecl() */
7972     alloc_teardown();
7973     alloc_setup();
7974   }
7975   if (i == 0)
7976     fail("Parse succeeded despite failing allocator");
7977   if (i == max_alloc_count)
7978     fail("Parse failed with max allocations");
7979 }
7980 END_TEST
7981 
7982 /* Test the effects of allocation failures on a straightforward parse */
7983 START_TEST(test_alloc_parse_pi) {
7984   const char *text = "<?xml version='1.0' encoding='utf-8'?>\n"
7985                      "<?pi unknown?>\n"
7986                      "<doc>"
7987                      "Hello, world"
7988                      "</doc>";
7989   int i;
7990   const int max_alloc_count = 15;
7991 
7992   for (i = 0; i < max_alloc_count; i++) {
7993     allocation_count = i;
7994     XML_SetProcessingInstructionHandler(g_parser, dummy_pi_handler);
7995     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
7996         != XML_STATUS_ERROR)
7997       break;
7998     /* See comment in test_alloc_parse_xdecl() */
7999     alloc_teardown();
8000     alloc_setup();
8001   }
8002   if (i == 0)
8003     fail("Parse succeeded despite failing allocator");
8004   if (i == max_alloc_count)
8005     fail("Parse failed with max allocations");
8006 }
8007 END_TEST
8008 
8009 START_TEST(test_alloc_parse_pi_2) {
8010   const char *text = "<?xml version='1.0' encoding='utf-8'?>\n"
8011                      "<doc>"
8012                      "Hello, world"
8013                      "<?pi unknown?>\n"
8014                      "</doc>";
8015   int i;
8016   const int max_alloc_count = 15;
8017 
8018   for (i = 0; i < max_alloc_count; i++) {
8019     allocation_count = i;
8020     XML_SetProcessingInstructionHandler(g_parser, dummy_pi_handler);
8021     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
8022         != XML_STATUS_ERROR)
8023       break;
8024     /* See comment in test_alloc_parse_xdecl() */
8025     alloc_teardown();
8026     alloc_setup();
8027   }
8028   if (i == 0)
8029     fail("Parse succeeded despite failing allocator");
8030   if (i == max_alloc_count)
8031     fail("Parse failed with max allocations");
8032 }
8033 END_TEST
8034 
8035 START_TEST(test_alloc_parse_pi_3) {
8036   const char *text
8037       = "<?"
8038         /* 64 characters per line */
8039         "This processing instruction should be long enough to ensure that"
8040         "it triggers the growth of an internal string pool when the      "
8041         "allocator fails at a cruicial moment FGHIJKLMNOPABCDEFGHIJKLMNOP"
8042         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8043         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8044         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8045         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8046         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8047         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8048         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8049         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8050         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8051         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8052         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8053         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8054         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8055         "Q?><doc/>";
8056   int i;
8057   const int max_alloc_count = 20;
8058 
8059   for (i = 0; i < max_alloc_count; i++) {
8060     allocation_count = i;
8061     XML_SetProcessingInstructionHandler(g_parser, dummy_pi_handler);
8062     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
8063         != XML_STATUS_ERROR)
8064       break;
8065     /* See comment in test_alloc_parse_xdecl() */
8066     alloc_teardown();
8067     alloc_setup();
8068   }
8069   if (i == 0)
8070     fail("Parse succeeded despite failing allocator");
8071   if (i == max_alloc_count)
8072     fail("Parse failed with max allocations");
8073 }
8074 END_TEST
8075 
8076 START_TEST(test_alloc_parse_comment) {
8077   const char *text = "<?xml version='1.0' encoding='utf-8'?>\n"
8078                      "<!-- Test parsing this comment -->"
8079                      "<doc>Hi</doc>";
8080   int i;
8081   const int max_alloc_count = 15;
8082 
8083   for (i = 0; i < max_alloc_count; i++) {
8084     allocation_count = i;
8085     XML_SetCommentHandler(g_parser, dummy_comment_handler);
8086     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
8087         != XML_STATUS_ERROR)
8088       break;
8089     /* See comment in test_alloc_parse_xdecl() */
8090     alloc_teardown();
8091     alloc_setup();
8092   }
8093   if (i == 0)
8094     fail("Parse succeeded despite failing allocator");
8095   if (i == max_alloc_count)
8096     fail("Parse failed with max allocations");
8097 }
8098 END_TEST
8099 
8100 START_TEST(test_alloc_parse_comment_2) {
8101   const char *text = "<?xml version='1.0' encoding='utf-8'?>\n"
8102                      "<doc>"
8103                      "Hello, world"
8104                      "<!-- Parse this comment too -->"
8105                      "</doc>";
8106   int i;
8107   const int max_alloc_count = 15;
8108 
8109   for (i = 0; i < max_alloc_count; i++) {
8110     allocation_count = i;
8111     XML_SetCommentHandler(g_parser, dummy_comment_handler);
8112     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
8113         != XML_STATUS_ERROR)
8114       break;
8115     /* See comment in test_alloc_parse_xdecl() */
8116     alloc_teardown();
8117     alloc_setup();
8118   }
8119   if (i == 0)
8120     fail("Parse succeeded despite failing allocator");
8121   if (i == max_alloc_count)
8122     fail("Parse failed with max allocations");
8123 }
8124 END_TEST
8125 
8126 static int XMLCALL
8127 external_entity_duff_loader(XML_Parser parser, const XML_Char *context,
8128                             const XML_Char *base, const XML_Char *systemId,
8129                             const XML_Char *publicId) {
8130   XML_Parser new_parser;
8131   unsigned int i;
8132   const unsigned int max_alloc_count = 10;
8133 
8134   UNUSED_P(base);
8135   UNUSED_P(systemId);
8136   UNUSED_P(publicId);
8137   /* Try a few different allocation levels */
8138   for (i = 0; i < max_alloc_count; i++) {
8139     allocation_count = i;
8140     new_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
8141     if (new_parser != NULL) {
8142       XML_ParserFree(new_parser);
8143       break;
8144     }
8145   }
8146   if (i == 0)
8147     fail("External parser creation ignored failing allocator");
8148   else if (i == max_alloc_count)
8149     fail("Extern parser not created with max allocation count");
8150 
8151   /* Make sure other random allocation doesn't now fail */
8152   allocation_count = ALLOC_ALWAYS_SUCCEED;
8153 
8154   /* Make sure the failure code path is executed too */
8155   return XML_STATUS_ERROR;
8156 }
8157 
8158 /* Test that external parser creation running out of memory is
8159  * correctly reported.  Based on the external entity test cases.
8160  */
8161 START_TEST(test_alloc_create_external_parser) {
8162   const char *text = "<?xml version='1.0' encoding='us-ascii'?>\n"
8163                      "<!DOCTYPE doc SYSTEM 'foo'>\n"
8164                      "<doc>&entity;</doc>";
8165   char foo_text[] = "<!ELEMENT doc (#PCDATA)*>";
8166 
8167   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
8168   XML_SetUserData(g_parser, foo_text);
8169   XML_SetExternalEntityRefHandler(g_parser, external_entity_duff_loader);
8170   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
8171       != XML_STATUS_ERROR) {
8172     fail("External parser allocator returned success incorrectly");
8173   }
8174 }
8175 END_TEST
8176 
8177 /* More external parser memory allocation testing */
8178 START_TEST(test_alloc_run_external_parser) {
8179   const char *text = "<?xml version='1.0' encoding='us-ascii'?>\n"
8180                      "<!DOCTYPE doc SYSTEM 'foo'>\n"
8181                      "<doc>&entity;</doc>";
8182   char foo_text[] = "<!ELEMENT doc (#PCDATA)*>";
8183   unsigned int i;
8184   const unsigned int max_alloc_count = 15;
8185 
8186   for (i = 0; i < max_alloc_count; i++) {
8187     XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
8188     XML_SetUserData(g_parser, foo_text);
8189     XML_SetExternalEntityRefHandler(g_parser, external_entity_null_loader);
8190     allocation_count = i;
8191     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
8192         != XML_STATUS_ERROR)
8193       break;
8194     /* See comment in test_alloc_parse_xdecl() */
8195     alloc_teardown();
8196     alloc_setup();
8197   }
8198   if (i == 0)
8199     fail("Parsing ignored failing allocator");
8200   else if (i == max_alloc_count)
8201     fail("Parsing failed with allocation count 10");
8202 }
8203 END_TEST
8204 
8205 static int XMLCALL
8206 external_entity_dbl_handler(XML_Parser parser, const XML_Char *context,
8207                             const XML_Char *base, const XML_Char *systemId,
8208                             const XML_Char *publicId) {
8209   intptr_t callno = (intptr_t)XML_GetUserData(parser);
8210   const char *text;
8211   XML_Parser new_parser;
8212   int i;
8213   const int max_alloc_count = 20;
8214 
8215   UNUSED_P(base);
8216   UNUSED_P(systemId);
8217   UNUSED_P(publicId);
8218   if (callno == 0) {
8219     /* First time through, check how many calls to malloc occur */
8220     text = ("<!ELEMENT doc (e+)>\n"
8221             "<!ATTLIST doc xmlns CDATA #IMPLIED>\n"
8222             "<!ELEMENT e EMPTY>\n");
8223     allocation_count = 10000;
8224     new_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
8225     if (new_parser == NULL) {
8226       fail("Unable to allocate first external parser");
8227       return XML_STATUS_ERROR;
8228     }
8229     /* Stash the number of calls in the user data */
8230     XML_SetUserData(parser, (void *)(intptr_t)(10000 - allocation_count));
8231   } else {
8232     text = ("<?xml version='1.0' encoding='us-ascii'?>"
8233             "<e/>");
8234     /* Try at varying levels to exercise more code paths */
8235     for (i = 0; i < max_alloc_count; i++) {
8236       allocation_count = callno + i;
8237       new_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
8238       if (new_parser != NULL)
8239         break;
8240     }
8241     if (i == 0) {
8242       fail("Second external parser unexpectedly created");
8243       XML_ParserFree(new_parser);
8244       return XML_STATUS_ERROR;
8245     } else if (i == max_alloc_count) {
8246       fail("Second external parser not created");
8247       return XML_STATUS_ERROR;
8248     }
8249   }
8250 
8251   allocation_count = ALLOC_ALWAYS_SUCCEED;
8252   if (_XML_Parse_SINGLE_BYTES(new_parser, text, (int)strlen(text), XML_TRUE)
8253       == XML_STATUS_ERROR) {
8254     xml_failure(new_parser);
8255     return XML_STATUS_ERROR;
8256   }
8257   XML_ParserFree(new_parser);
8258   return XML_STATUS_OK;
8259 }
8260 
8261 /* Test that running out of memory in dtdCopy is correctly reported.
8262  * Based on test_default_ns_from_ext_subset_and_ext_ge()
8263  */
8264 START_TEST(test_alloc_dtd_copy_default_atts) {
8265   const char *text = "<?xml version='1.0'?>\n"
8266                      "<!DOCTYPE doc SYSTEM 'http://example.org/doc.dtd' [\n"
8267                      "  <!ENTITY en SYSTEM 'http://example.org/entity.ent'>\n"
8268                      "]>\n"
8269                      "<doc xmlns='http://example.org/ns1'>\n"
8270                      "&en;\n"
8271                      "</doc>";
8272 
8273   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
8274   XML_SetExternalEntityRefHandler(g_parser, external_entity_dbl_handler);
8275   XML_SetUserData(g_parser, NULL);
8276   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
8277       == XML_STATUS_ERROR)
8278     xml_failure(g_parser);
8279 }
8280 END_TEST
8281 
8282 static int XMLCALL
8283 external_entity_dbl_handler_2(XML_Parser parser, const XML_Char *context,
8284                               const XML_Char *base, const XML_Char *systemId,
8285                               const XML_Char *publicId) {
8286   intptr_t callno = (intptr_t)XML_GetUserData(parser);
8287   const char *text;
8288   XML_Parser new_parser;
8289   enum XML_Status rv;
8290 
8291   UNUSED_P(base);
8292   UNUSED_P(systemId);
8293   UNUSED_P(publicId);
8294   if (callno == 0) {
8295     /* Try different allocation levels for whole exercise */
8296     text = ("<!ELEMENT doc (e+)>\n"
8297             "<!ATTLIST doc xmlns CDATA #IMPLIED>\n"
8298             "<!ELEMENT e EMPTY>\n");
8299     XML_SetUserData(parser, (void *)(intptr_t)1);
8300     new_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
8301     if (new_parser == NULL)
8302       return XML_STATUS_ERROR;
8303     rv = _XML_Parse_SINGLE_BYTES(new_parser, text, (int)strlen(text), XML_TRUE);
8304   } else {
8305     /* Just run through once */
8306     text = ("<?xml version='1.0' encoding='us-ascii'?>"
8307             "<e/>");
8308     new_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
8309     if (new_parser == NULL)
8310       return XML_STATUS_ERROR;
8311     rv = _XML_Parse_SINGLE_BYTES(new_parser, text, (int)strlen(text), XML_TRUE);
8312   }
8313   XML_ParserFree(new_parser);
8314   if (rv == XML_STATUS_ERROR)
8315     return XML_STATUS_ERROR;
8316   return XML_STATUS_OK;
8317 }
8318 
8319 /* Test more external entity allocation failure paths */
8320 START_TEST(test_alloc_external_entity) {
8321   const char *text = "<?xml version='1.0'?>\n"
8322                      "<!DOCTYPE doc SYSTEM 'http://example.org/doc.dtd' [\n"
8323                      "  <!ENTITY en SYSTEM 'http://example.org/entity.ent'>\n"
8324                      "]>\n"
8325                      "<doc xmlns='http://example.org/ns1'>\n"
8326                      "&en;\n"
8327                      "</doc>";
8328   int i;
8329   const int alloc_test_max_repeats = 50;
8330 
8331   for (i = 0; i < alloc_test_max_repeats; i++) {
8332     allocation_count = -1;
8333     XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
8334     XML_SetExternalEntityRefHandler(g_parser, external_entity_dbl_handler_2);
8335     XML_SetUserData(g_parser, NULL);
8336     allocation_count = i;
8337     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
8338         == XML_STATUS_OK)
8339       break;
8340     /* See comment in test_alloc_parse_xdecl() */
8341     alloc_teardown();
8342     alloc_setup();
8343   }
8344   allocation_count = -1;
8345   if (i == 0)
8346     fail("External entity parsed despite duff allocator");
8347   if (i == alloc_test_max_repeats)
8348     fail("External entity not parsed at max allocation count");
8349 }
8350 END_TEST
8351 
8352 /* Test more allocation failure paths */
8353 static int XMLCALL
8354 external_entity_alloc_set_encoding(XML_Parser parser, const XML_Char *context,
8355                                    const XML_Char *base,
8356                                    const XML_Char *systemId,
8357                                    const XML_Char *publicId) {
8358   /* As for external_entity_loader() */
8359   const char *text = "<?xml encoding='iso-8859-3'?>"
8360                      "\xC3\xA9";
8361   XML_Parser ext_parser;
8362   enum XML_Status status;
8363 
8364   UNUSED_P(base);
8365   UNUSED_P(systemId);
8366   UNUSED_P(publicId);
8367   ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
8368   if (ext_parser == NULL)
8369     return XML_STATUS_ERROR;
8370   if (! XML_SetEncoding(ext_parser, XCS("utf-8"))) {
8371     XML_ParserFree(ext_parser);
8372     return XML_STATUS_ERROR;
8373   }
8374   status
8375       = _XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE);
8376   XML_ParserFree(ext_parser);
8377   if (status == XML_STATUS_ERROR)
8378     return XML_STATUS_ERROR;
8379   return XML_STATUS_OK;
8380 }
8381 
8382 START_TEST(test_alloc_ext_entity_set_encoding) {
8383   const char *text = "<!DOCTYPE doc [\n"
8384                      "  <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n"
8385                      "]>\n"
8386                      "<doc>&en;</doc>";
8387   int i;
8388   const int max_allocation_count = 30;
8389 
8390   for (i = 0; i < max_allocation_count; i++) {
8391     XML_SetExternalEntityRefHandler(g_parser,
8392                                     external_entity_alloc_set_encoding);
8393     allocation_count = i;
8394     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
8395         == XML_STATUS_OK)
8396       break;
8397     allocation_count = -1;
8398     /* See comment in test_alloc_parse_xdecl() */
8399     alloc_teardown();
8400     alloc_setup();
8401   }
8402   if (i == 0)
8403     fail("Encoding check succeeded despite failing allocator");
8404   if (i == max_allocation_count)
8405     fail("Encoding failed at max allocation count");
8406 }
8407 END_TEST
8408 
8409 static int XMLCALL
8410 unknown_released_encoding_handler(void *data, const XML_Char *encoding,
8411                                   XML_Encoding *info) {
8412   UNUSED_P(data);
8413   if (! xcstrcmp(encoding, XCS("unsupported-encoding"))) {
8414     int i;
8415 
8416     for (i = 0; i < 256; i++)
8417       info->map[i] = i;
8418     info->data = NULL;
8419     info->convert = NULL;
8420     info->release = dummy_release;
8421     return XML_STATUS_OK;
8422   }
8423   return XML_STATUS_ERROR;
8424 }
8425 
8426 /* Test the effects of allocation failure in internal entities.
8427  * Based on test_unknown_encoding_internal_entity
8428  */
8429 START_TEST(test_alloc_internal_entity) {
8430   const char *text = "<?xml version='1.0' encoding='unsupported-encoding'?>\n"
8431                      "<!DOCTYPE test [<!ENTITY foo 'bar'>]>\n"
8432                      "<test a='&foo;'/>";
8433   unsigned int i;
8434   const unsigned int max_alloc_count = 20;
8435 
8436   for (i = 0; i < max_alloc_count; i++) {
8437     allocation_count = i;
8438     XML_SetUnknownEncodingHandler(g_parser, unknown_released_encoding_handler,
8439                                   NULL);
8440     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
8441         != XML_STATUS_ERROR)
8442       break;
8443     /* See comment in test_alloc_parse_xdecl() */
8444     alloc_teardown();
8445     alloc_setup();
8446   }
8447   if (i == 0)
8448     fail("Internal entity worked despite failing allocations");
8449   else if (i == max_alloc_count)
8450     fail("Internal entity failed at max allocation count");
8451 }
8452 END_TEST
8453 
8454 /* Test the robustness against allocation failure of element handling
8455  * Based on test_dtd_default_handling().
8456  */
8457 START_TEST(test_alloc_dtd_default_handling) {
8458   const char *text = "<!DOCTYPE doc [\n"
8459                      "<!ENTITY e SYSTEM 'http://example.org/e'>\n"
8460                      "<!NOTATION n SYSTEM 'http://example.org/n'>\n"
8461                      "<!ENTITY e1 SYSTEM 'http://example.org/e' NDATA n>\n"
8462                      "<!ELEMENT doc (#PCDATA)>\n"
8463                      "<!ATTLIST doc a CDATA #IMPLIED>\n"
8464                      "<?pi in dtd?>\n"
8465                      "<!--comment in dtd-->\n"
8466                      "]>\n"
8467                      "<doc><![CDATA[text in doc]]></doc>";
8468   const XML_Char *expected = XCS("\n\n\n\n\n\n\n\n\n<doc>text in doc</doc>");
8469   CharData storage;
8470   int i;
8471   const int max_alloc_count = 25;
8472 
8473   for (i = 0; i < max_alloc_count; i++) {
8474     allocation_count = i;
8475     dummy_handler_flags = 0;
8476     XML_SetDefaultHandler(g_parser, accumulate_characters);
8477     XML_SetDoctypeDeclHandler(g_parser, dummy_start_doctype_handler,
8478                               dummy_end_doctype_handler);
8479     XML_SetEntityDeclHandler(g_parser, dummy_entity_decl_handler);
8480     XML_SetNotationDeclHandler(g_parser, dummy_notation_decl_handler);
8481     XML_SetElementDeclHandler(g_parser, dummy_element_decl_handler);
8482     XML_SetAttlistDeclHandler(g_parser, dummy_attlist_decl_handler);
8483     XML_SetProcessingInstructionHandler(g_parser, dummy_pi_handler);
8484     XML_SetCommentHandler(g_parser, dummy_comment_handler);
8485     XML_SetCdataSectionHandler(g_parser, dummy_start_cdata_handler,
8486                                dummy_end_cdata_handler);
8487     XML_SetUnparsedEntityDeclHandler(g_parser,
8488                                      dummy_unparsed_entity_decl_handler);
8489     CharData_Init(&storage);
8490     XML_SetUserData(g_parser, &storage);
8491     XML_SetCharacterDataHandler(g_parser, accumulate_characters);
8492     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
8493         != XML_STATUS_ERROR)
8494       break;
8495     /* See comment in test_alloc_parse_xdecl() */
8496     alloc_teardown();
8497     alloc_setup();
8498   }
8499   if (i == 0)
8500     fail("Default DTD parsed despite allocation failures");
8501   if (i == max_alloc_count)
8502     fail("Default DTD not parsed with maximum alloc count");
8503   CharData_CheckXMLChars(&storage, expected);
8504   if (dummy_handler_flags
8505       != (DUMMY_START_DOCTYPE_HANDLER_FLAG | DUMMY_END_DOCTYPE_HANDLER_FLAG
8506           | DUMMY_ENTITY_DECL_HANDLER_FLAG | DUMMY_NOTATION_DECL_HANDLER_FLAG
8507           | DUMMY_ELEMENT_DECL_HANDLER_FLAG | DUMMY_ATTLIST_DECL_HANDLER_FLAG
8508           | DUMMY_COMMENT_HANDLER_FLAG | DUMMY_PI_HANDLER_FLAG
8509           | DUMMY_START_CDATA_HANDLER_FLAG | DUMMY_END_CDATA_HANDLER_FLAG
8510           | DUMMY_UNPARSED_ENTITY_DECL_HANDLER_FLAG))
8511     fail("Not all handlers were called");
8512 }
8513 END_TEST
8514 
8515 /* Test robustness of XML_SetEncoding() with a failing allocator */
8516 START_TEST(test_alloc_explicit_encoding) {
8517   int i;
8518   const int max_alloc_count = 5;
8519 
8520   for (i = 0; i < max_alloc_count; i++) {
8521     allocation_count = i;
8522     if (XML_SetEncoding(g_parser, XCS("us-ascii")) == XML_STATUS_OK)
8523       break;
8524   }
8525   if (i == 0)
8526     fail("Encoding set despite failing allocator");
8527   else if (i == max_alloc_count)
8528     fail("Encoding not set at max allocation count");
8529 }
8530 END_TEST
8531 
8532 /* Test robustness of XML_SetBase against a failing allocator */
8533 START_TEST(test_alloc_set_base) {
8534   const XML_Char *new_base = XCS("/local/file/name.xml");
8535   int i;
8536   const int max_alloc_count = 5;
8537 
8538   for (i = 0; i < max_alloc_count; i++) {
8539     allocation_count = i;
8540     if (XML_SetBase(g_parser, new_base) == XML_STATUS_OK)
8541       break;
8542   }
8543   if (i == 0)
8544     fail("Base set despite failing allocator");
8545   else if (i == max_alloc_count)
8546     fail("Base not set with max allocation count");
8547 }
8548 END_TEST
8549 
8550 /* Test buffer extension in the face of a duff reallocator */
8551 START_TEST(test_alloc_realloc_buffer) {
8552   const char *text = get_buffer_test_text;
8553   void *buffer;
8554   int i;
8555   const int max_realloc_count = 10;
8556 
8557   /* Get a smallish buffer */
8558   for (i = 0; i < max_realloc_count; i++) {
8559     reallocation_count = i;
8560     buffer = XML_GetBuffer(g_parser, 1536);
8561     if (buffer == NULL)
8562       fail("1.5K buffer reallocation failed");
8563     assert(buffer != NULL);
8564     memcpy(buffer, text, strlen(text));
8565     if (XML_ParseBuffer(g_parser, (int)strlen(text), XML_FALSE)
8566         == XML_STATUS_OK)
8567       break;
8568     /* See comment in test_alloc_parse_xdecl() */
8569     alloc_teardown();
8570     alloc_setup();
8571   }
8572   reallocation_count = -1;
8573   if (i == 0)
8574     fail("Parse succeeded with no reallocation");
8575   else if (i == max_realloc_count)
8576     fail("Parse failed with max reallocation count");
8577 }
8578 END_TEST
8579 
8580 /* Same test for external entity parsers */
8581 static int XMLCALL
8582 external_entity_reallocator(XML_Parser parser, const XML_Char *context,
8583                             const XML_Char *base, const XML_Char *systemId,
8584                             const XML_Char *publicId) {
8585   const char *text = get_buffer_test_text;
8586   XML_Parser ext_parser;
8587   void *buffer;
8588   enum XML_Status status;
8589 
8590   UNUSED_P(base);
8591   UNUSED_P(systemId);
8592   UNUSED_P(publicId);
8593   ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
8594   if (ext_parser == NULL)
8595     fail("Could not create external entity parser");
8596 
8597   reallocation_count = (intptr_t)XML_GetUserData(parser);
8598   buffer = XML_GetBuffer(ext_parser, 1536);
8599   if (buffer == NULL)
8600     fail("Buffer allocation failed");
8601   assert(buffer != NULL);
8602   memcpy(buffer, text, strlen(text));
8603   status = XML_ParseBuffer(ext_parser, (int)strlen(text), XML_FALSE);
8604   reallocation_count = -1;
8605   XML_ParserFree(ext_parser);
8606   return (status == XML_STATUS_OK) ? XML_STATUS_OK : XML_STATUS_ERROR;
8607 }
8608 
8609 START_TEST(test_alloc_ext_entity_realloc_buffer) {
8610   const char *text = "<!DOCTYPE doc [\n"
8611                      "  <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n"
8612                      "]>\n"
8613                      "<doc>&en;</doc>";
8614   int i;
8615   const int max_realloc_count = 10;
8616 
8617   for (i = 0; i < max_realloc_count; i++) {
8618     XML_SetExternalEntityRefHandler(g_parser, external_entity_reallocator);
8619     XML_SetUserData(g_parser, (void *)(intptr_t)i);
8620     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
8621         == XML_STATUS_OK)
8622       break;
8623     /* See comment in test_alloc_parse_xdecl() */
8624     alloc_teardown();
8625     alloc_setup();
8626   }
8627   if (i == 0)
8628     fail("Succeeded with no reallocations");
8629   if (i == max_realloc_count)
8630     fail("Failed with max reallocations");
8631 }
8632 END_TEST
8633 
8634 /* Test elements with many attributes are handled correctly */
8635 START_TEST(test_alloc_realloc_many_attributes) {
8636   const char *text = "<!DOCTYPE doc [\n"
8637                      "<!ATTLIST doc za CDATA 'default'>\n"
8638                      "<!ATTLIST doc zb CDATA 'def2'>\n"
8639                      "<!ATTLIST doc zc CDATA 'def3'>\n"
8640                      "]>\n"
8641                      "<doc a='1'"
8642                      "     b='2'"
8643                      "     c='3'"
8644                      "     d='4'"
8645                      "     e='5'"
8646                      "     f='6'"
8647                      "     g='7'"
8648                      "     h='8'"
8649                      "     i='9'"
8650                      "     j='10'"
8651                      "     k='11'"
8652                      "     l='12'"
8653                      "     m='13'"
8654                      "     n='14'"
8655                      "     p='15'"
8656                      "     q='16'"
8657                      "     r='17'"
8658                      "     s='18'>"
8659                      "</doc>";
8660   int i;
8661   const int max_realloc_count = 10;
8662 
8663   for (i = 0; i < max_realloc_count; i++) {
8664     reallocation_count = i;
8665     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
8666         != XML_STATUS_ERROR)
8667       break;
8668     /* See comment in test_alloc_parse_xdecl() */
8669     alloc_teardown();
8670     alloc_setup();
8671   }
8672   if (i == 0)
8673     fail("Parse succeeded despite no reallocations");
8674   if (i == max_realloc_count)
8675     fail("Parse failed at max reallocations");
8676 }
8677 END_TEST
8678 
8679 /* Test handling of a public entity with failing allocator */
8680 START_TEST(test_alloc_public_entity_value) {
8681   const char *text = "<!DOCTYPE doc SYSTEM 'http://example.org/'>\n"
8682                      "<doc></doc>\n";
8683   char dtd_text[]
8684       = "<!ELEMENT doc EMPTY>\n"
8685         "<!ENTITY % e1 PUBLIC 'foo' 'bar.ent'>\n"
8686         "<!ENTITY % "
8687         /* Each line is 64 characters */
8688         "ThisIsAStupidlyLongParameterNameIntendedToTriggerPoolGrowth12345"
8689         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8690         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8691         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8692         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8693         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8694         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8695         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8696         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8697         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8698         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8699         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8700         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8701         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8702         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8703         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8704         " '%e1;'>\n"
8705         "%e1;\n";
8706   int i;
8707   const int max_alloc_count = 50;
8708 
8709   for (i = 0; i < max_alloc_count; i++) {
8710     allocation_count = i;
8711     dummy_handler_flags = 0;
8712     XML_SetUserData(g_parser, dtd_text);
8713     XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
8714     XML_SetExternalEntityRefHandler(g_parser, external_entity_public);
8715     /* Provoke a particular code path */
8716     XML_SetEntityDeclHandler(g_parser, dummy_entity_decl_handler);
8717     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
8718         != XML_STATUS_ERROR)
8719       break;
8720     /* See comment in test_alloc_parse_xdecl() */
8721     alloc_teardown();
8722     alloc_setup();
8723   }
8724   if (i == 0)
8725     fail("Parsing worked despite failing allocation");
8726   if (i == max_alloc_count)
8727     fail("Parsing failed at max allocation count");
8728   if (dummy_handler_flags != DUMMY_ENTITY_DECL_HANDLER_FLAG)
8729     fail("Entity declaration handler not called");
8730 }
8731 END_TEST
8732 
8733 START_TEST(test_alloc_realloc_subst_public_entity_value) {
8734   const char *text = "<!DOCTYPE doc SYSTEM 'http://example.org/'>\n"
8735                      "<doc></doc>\n";
8736   char dtd_text[]
8737       = "<!ELEMENT doc EMPTY>\n"
8738         "<!ENTITY % "
8739         /* Each line is 64 characters */
8740         "ThisIsAStupidlyLongParameterNameIntendedToTriggerPoolGrowth12345"
8741         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8742         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8743         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8744         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8745         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8746         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8747         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8748         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8749         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8750         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8751         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8752         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8753         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8754         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8755         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8756         " PUBLIC 'foo' 'bar.ent'>\n"
8757         "%ThisIsAStupidlyLongParameterNameIntendedToTriggerPoolGrowth12345"
8758         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8759         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8760         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8761         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8762         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8763         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8764         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8765         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8766         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8767         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8768         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8769         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8770         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8771         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8772         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP;";
8773   int i;
8774   const int max_realloc_count = 10;
8775 
8776   for (i = 0; i < max_realloc_count; i++) {
8777     reallocation_count = i;
8778     XML_SetUserData(g_parser, dtd_text);
8779     XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
8780     XML_SetExternalEntityRefHandler(g_parser, external_entity_public);
8781     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
8782         != XML_STATUS_ERROR)
8783       break;
8784     /* See comment in test_alloc_parse_xdecl() */
8785     alloc_teardown();
8786     alloc_setup();
8787   }
8788   if (i == 0)
8789     fail("Parsing worked despite failing reallocation");
8790   if (i == max_realloc_count)
8791     fail("Parsing failed at max reallocation count");
8792 }
8793 END_TEST
8794 
8795 START_TEST(test_alloc_parse_public_doctype) {
8796   const char *text
8797       = "<?xml version='1.0' encoding='utf-8'?>\n"
8798         "<!DOCTYPE doc PUBLIC '"
8799         /* 64 characters per line */
8800         "http://example.com/a/long/enough/name/to/trigger/pool/growth/zz/"
8801         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8802         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8803         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8804         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8805         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8806         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8807         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8808         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8809         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8810         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8811         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8812         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8813         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8814         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8815         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8816         "' 'test'>\n"
8817         "<doc></doc>";
8818   int i;
8819   const int max_alloc_count = 25;
8820 
8821   for (i = 0; i < max_alloc_count; i++) {
8822     allocation_count = i;
8823     dummy_handler_flags = 0;
8824     XML_SetDoctypeDeclHandler(g_parser, dummy_start_doctype_decl_handler,
8825                               dummy_end_doctype_decl_handler);
8826     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
8827         != XML_STATUS_ERROR)
8828       break;
8829     /* See comment in test_alloc_parse_xdecl() */
8830     alloc_teardown();
8831     alloc_setup();
8832   }
8833   if (i == 0)
8834     fail("Parse succeeded despite failing allocator");
8835   if (i == max_alloc_count)
8836     fail("Parse failed at maximum allocation count");
8837   if (dummy_handler_flags
8838       != (DUMMY_START_DOCTYPE_DECL_HANDLER_FLAG
8839           | DUMMY_END_DOCTYPE_DECL_HANDLER_FLAG))
8840     fail("Doctype handler functions not called");
8841 }
8842 END_TEST
8843 
8844 START_TEST(test_alloc_parse_public_doctype_long_name) {
8845   const char *text
8846       = "<?xml version='1.0' encoding='utf-8'?>\n"
8847         "<!DOCTYPE doc PUBLIC 'http://example.com/foo' '"
8848         /* 64 characters per line */
8849         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP"
8850         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP"
8851         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP"
8852         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP"
8853         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP"
8854         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP"
8855         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP"
8856         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP"
8857         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP"
8858         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP"
8859         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP"
8860         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP"
8861         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP"
8862         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP"
8863         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP"
8864         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP"
8865         "'>\n"
8866         "<doc></doc>";
8867   int i;
8868   const int max_alloc_count = 25;
8869 
8870   for (i = 0; i < max_alloc_count; i++) {
8871     allocation_count = i;
8872     XML_SetDoctypeDeclHandler(g_parser, dummy_start_doctype_decl_handler,
8873                               dummy_end_doctype_decl_handler);
8874     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
8875         != XML_STATUS_ERROR)
8876       break;
8877     /* See comment in test_alloc_parse_xdecl() */
8878     alloc_teardown();
8879     alloc_setup();
8880   }
8881   if (i == 0)
8882     fail("Parse succeeded despite failing allocator");
8883   if (i == max_alloc_count)
8884     fail("Parse failed at maximum allocation count");
8885 }
8886 END_TEST
8887 
8888 static int XMLCALL
8889 external_entity_alloc(XML_Parser parser, const XML_Char *context,
8890                       const XML_Char *base, const XML_Char *systemId,
8891                       const XML_Char *publicId) {
8892   const char *text = (const char *)XML_GetUserData(parser);
8893   XML_Parser ext_parser;
8894   int parse_res;
8895 
8896   UNUSED_P(base);
8897   UNUSED_P(systemId);
8898   UNUSED_P(publicId);
8899   ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
8900   if (ext_parser == NULL)
8901     return XML_STATUS_ERROR;
8902   parse_res
8903       = _XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE);
8904   XML_ParserFree(ext_parser);
8905   return parse_res;
8906 }
8907 
8908 /* Test foreign DTD handling */
8909 START_TEST(test_alloc_set_foreign_dtd) {
8910   const char *text1 = "<?xml version='1.0' encoding='us-ascii'?>\n"
8911                       "<doc>&entity;</doc>";
8912   char text2[] = "<!ELEMENT doc (#PCDATA)*>";
8913   int i;
8914   const int max_alloc_count = 25;
8915 
8916   for (i = 0; i < max_alloc_count; i++) {
8917     allocation_count = i;
8918     XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
8919     XML_SetUserData(g_parser, &text2);
8920     XML_SetExternalEntityRefHandler(g_parser, external_entity_alloc);
8921     if (XML_UseForeignDTD(g_parser, XML_TRUE) != XML_ERROR_NONE)
8922       fail("Could not set foreign DTD");
8923     if (_XML_Parse_SINGLE_BYTES(g_parser, text1, (int)strlen(text1), XML_TRUE)
8924         != XML_STATUS_ERROR)
8925       break;
8926     /* See comment in test_alloc_parse_xdecl() */
8927     alloc_teardown();
8928     alloc_setup();
8929   }
8930   if (i == 0)
8931     fail("Parse succeeded despite failing allocator");
8932   if (i == max_alloc_count)
8933     fail("Parse failed at maximum allocation count");
8934 }
8935 END_TEST
8936 
8937 /* Test based on ibm/valid/P32/ibm32v04.xml */
8938 START_TEST(test_alloc_attribute_enum_value) {
8939   const char *text = "<?xml version='1.0' standalone='no'?>\n"
8940                      "<!DOCTYPE animal SYSTEM 'test.dtd'>\n"
8941                      "<animal>This is a \n    <a/>  \n\nyellow tiger</animal>";
8942   char dtd_text[] = "<!ELEMENT animal (#PCDATA|a)*>\n"
8943                     "<!ELEMENT a EMPTY>\n"
8944                     "<!ATTLIST animal xml:space (default|preserve) 'preserve'>";
8945   int i;
8946   const int max_alloc_count = 30;
8947 
8948   for (i = 0; i < max_alloc_count; i++) {
8949     allocation_count = i;
8950     XML_SetExternalEntityRefHandler(g_parser, external_entity_alloc);
8951     XML_SetUserData(g_parser, dtd_text);
8952     XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
8953     /* An attribute list handler provokes a different code path */
8954     XML_SetAttlistDeclHandler(g_parser, dummy_attlist_decl_handler);
8955     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
8956         != XML_STATUS_ERROR)
8957       break;
8958     /* See comment in test_alloc_parse_xdecl() */
8959     alloc_teardown();
8960     alloc_setup();
8961   }
8962   if (i == 0)
8963     fail("Parse succeeded despite failing allocator");
8964   if (i == max_alloc_count)
8965     fail("Parse failed at maximum allocation count");
8966 }
8967 END_TEST
8968 
8969 /* Test attribute enums sufficient to overflow the string pool */
8970 START_TEST(test_alloc_realloc_attribute_enum_value) {
8971   const char *text = "<?xml version='1.0' standalone='no'?>\n"
8972                      "<!DOCTYPE animal SYSTEM 'test.dtd'>\n"
8973                      "<animal>This is a yellow tiger</animal>";
8974   /* We wish to define a collection of attribute enums that will
8975    * cause the string pool storing them to have to expand.  This
8976    * means more than 1024 bytes, including the parentheses and
8977    * separator bars.
8978    */
8979   char dtd_text[]
8980       = "<!ELEMENT animal (#PCDATA)*>\n"
8981         "<!ATTLIST animal thing "
8982         "(default"
8983         /* Each line is 64 characters */
8984         "|ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8985         "|BBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8986         "|CBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8987         "|DBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8988         "|EBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8989         "|FBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8990         "|GBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8991         "|HBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8992         "|IBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8993         "|JBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8994         "|KBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8995         "|LBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8996         "|MBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8997         "|NBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8998         "|OBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8999         "|PBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO)"
9000         " 'default'>";
9001   int i;
9002   const int max_realloc_count = 10;
9003 
9004   for (i = 0; i < max_realloc_count; i++) {
9005     reallocation_count = i;
9006     XML_SetExternalEntityRefHandler(g_parser, external_entity_alloc);
9007     XML_SetUserData(g_parser, dtd_text);
9008     XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
9009     /* An attribute list handler provokes a different code path */
9010     XML_SetAttlistDeclHandler(g_parser, dummy_attlist_decl_handler);
9011     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
9012         != XML_STATUS_ERROR)
9013       break;
9014     /* See comment in test_alloc_parse_xdecl() */
9015     alloc_teardown();
9016     alloc_setup();
9017   }
9018   if (i == 0)
9019     fail("Parse succeeded despite failing reallocator");
9020   if (i == max_realloc_count)
9021     fail("Parse failed at maximum reallocation count");
9022 }
9023 END_TEST
9024 
9025 /* Test attribute enums in a #IMPLIED attribute forcing pool growth */
9026 START_TEST(test_alloc_realloc_implied_attribute) {
9027   /* Forcing this particular code path is a balancing act.  The
9028    * addition of the closing parenthesis and terminal NUL must be
9029    * what pushes the string of enums over the 1024-byte limit,
9030    * otherwise a different code path will pick up the realloc.
9031    */
9032   const char *text
9033       = "<!DOCTYPE doc [\n"
9034         "<!ELEMENT doc EMPTY>\n"
9035         "<!ATTLIST doc a "
9036         /* Each line is 64 characters */
9037         "(ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
9038         "|BBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
9039         "|CBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
9040         "|DBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
9041         "|EBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
9042         "|FBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
9043         "|GBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
9044         "|HBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
9045         "|IBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
9046         "|JBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
9047         "|KBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
9048         "|LBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
9049         "|MBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
9050         "|NBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
9051         "|OBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
9052         "|PBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMN)"
9053         " #IMPLIED>\n"
9054         "]><doc/>";
9055   int i;
9056   const int max_realloc_count = 10;
9057 
9058   for (i = 0; i < max_realloc_count; i++) {
9059     reallocation_count = i;
9060     XML_SetAttlistDeclHandler(g_parser, dummy_attlist_decl_handler);
9061     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
9062         != XML_STATUS_ERROR)
9063       break;
9064     /* See comment in test_alloc_parse_xdecl() */
9065     alloc_teardown();
9066     alloc_setup();
9067   }
9068   if (i == 0)
9069     fail("Parse succeeded despite failing reallocator");
9070   if (i == max_realloc_count)
9071     fail("Parse failed at maximum reallocation count");
9072 }
9073 END_TEST
9074 
9075 /* Test attribute enums in a defaulted attribute forcing pool growth */
9076 START_TEST(test_alloc_realloc_default_attribute) {
9077   /* Forcing this particular code path is a balancing act.  The
9078    * addition of the closing parenthesis and terminal NUL must be
9079    * what pushes the string of enums over the 1024-byte limit,
9080    * otherwise a different code path will pick up the realloc.
9081    */
9082   const char *text
9083       = "<!DOCTYPE doc [\n"
9084         "<!ELEMENT doc EMPTY>\n"
9085         "<!ATTLIST doc a "
9086         /* Each line is 64 characters */
9087         "(ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
9088         "|BBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
9089         "|CBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
9090         "|DBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
9091         "|EBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
9092         "|FBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
9093         "|GBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
9094         "|HBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
9095         "|IBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
9096         "|JBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
9097         "|KBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
9098         "|LBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
9099         "|MBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
9100         "|NBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
9101         "|OBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
9102         "|PBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMN)"
9103         " 'ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO'"
9104         ">\n]><doc/>";
9105   int i;
9106   const int max_realloc_count = 10;
9107 
9108   for (i = 0; i < max_realloc_count; i++) {
9109     reallocation_count = i;
9110     XML_SetAttlistDeclHandler(g_parser, dummy_attlist_decl_handler);
9111     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
9112         != XML_STATUS_ERROR)
9113       break;
9114     /* See comment in test_alloc_parse_xdecl() */
9115     alloc_teardown();
9116     alloc_setup();
9117   }
9118   if (i == 0)
9119     fail("Parse succeeded despite failing reallocator");
9120   if (i == max_realloc_count)
9121     fail("Parse failed at maximum reallocation count");
9122 }
9123 END_TEST
9124 
9125 /* Test long notation name with dodgy allocator */
9126 START_TEST(test_alloc_notation) {
9127   const char *text
9128       = "<!DOCTYPE doc [\n"
9129         "<!NOTATION "
9130         /* Each line is 64 characters */
9131         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9132         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9133         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9134         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9135         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9136         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9137         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9138         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9139         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9140         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9141         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9142         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9143         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9144         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9145         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9146         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9147         " SYSTEM 'http://example.org/n'>\n"
9148         "<!ENTITY e SYSTEM 'http://example.org/e' NDATA "
9149         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9150         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9151         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9152         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9153         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9154         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9155         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9156         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9157         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9158         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9159         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9160         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9161         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9162         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9163         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9164         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9165         ">\n"
9166         "<!ELEMENT doc EMPTY>\n"
9167         "]>\n<doc/>";
9168   int i;
9169   const int max_alloc_count = 20;
9170 
9171   for (i = 0; i < max_alloc_count; i++) {
9172     allocation_count = i;
9173     dummy_handler_flags = 0;
9174     XML_SetNotationDeclHandler(g_parser, dummy_notation_decl_handler);
9175     XML_SetEntityDeclHandler(g_parser, dummy_entity_decl_handler);
9176     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
9177         != XML_STATUS_ERROR)
9178       break;
9179     /* See comment in test_alloc_parse_xdecl() */
9180     alloc_teardown();
9181     alloc_setup();
9182   }
9183   if (i == 0)
9184     fail("Parse succeeded despite allocation failures");
9185   if (i == max_alloc_count)
9186     fail("Parse failed at maximum allocation count");
9187   if (dummy_handler_flags
9188       != (DUMMY_ENTITY_DECL_HANDLER_FLAG | DUMMY_NOTATION_DECL_HANDLER_FLAG))
9189     fail("Entity declaration handler not called");
9190 }
9191 END_TEST
9192 
9193 /* Test public notation with dodgy allocator */
9194 START_TEST(test_alloc_public_notation) {
9195   const char *text
9196       = "<!DOCTYPE doc [\n"
9197         "<!NOTATION note PUBLIC '"
9198         /* 64 characters per line */
9199         "http://example.com/a/long/enough/name/to/trigger/pool/growth/zz/"
9200         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9201         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9202         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9203         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9204         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9205         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9206         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9207         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9208         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9209         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9210         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9211         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9212         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9213         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9214         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9215         "' 'foo'>\n"
9216         "<!ENTITY e SYSTEM 'http://example.com/e' NDATA note>\n"
9217         "<!ELEMENT doc EMPTY>\n"
9218         "]>\n<doc/>";
9219   int i;
9220   const int max_alloc_count = 20;
9221 
9222   for (i = 0; i < max_alloc_count; i++) {
9223     allocation_count = i;
9224     dummy_handler_flags = 0;
9225     XML_SetNotationDeclHandler(g_parser, dummy_notation_decl_handler);
9226     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
9227         != XML_STATUS_ERROR)
9228       break;
9229     /* See comment in test_alloc_parse_xdecl() */
9230     alloc_teardown();
9231     alloc_setup();
9232   }
9233   if (i == 0)
9234     fail("Parse succeeded despite allocation failures");
9235   if (i == max_alloc_count)
9236     fail("Parse failed at maximum allocation count");
9237   if (dummy_handler_flags != DUMMY_NOTATION_DECL_HANDLER_FLAG)
9238     fail("Notation handler not called");
9239 }
9240 END_TEST
9241 
9242 /* Test public notation with dodgy allocator */
9243 START_TEST(test_alloc_system_notation) {
9244   const char *text
9245       = "<!DOCTYPE doc [\n"
9246         "<!NOTATION note SYSTEM '"
9247         /* 64 characters per line */
9248         "http://example.com/a/long/enough/name/to/trigger/pool/growth/zz/"
9249         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9250         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9251         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9252         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9253         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9254         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9255         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9256         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9257         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9258         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9259         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9260         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9261         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9262         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9263         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9264         "'>\n"
9265         "<!ENTITY e SYSTEM 'http://example.com/e' NDATA note>\n"
9266         "<!ELEMENT doc EMPTY>\n"
9267         "]>\n<doc/>";
9268   int i;
9269   const int max_alloc_count = 20;
9270 
9271   for (i = 0; i < max_alloc_count; i++) {
9272     allocation_count = i;
9273     dummy_handler_flags = 0;
9274     XML_SetNotationDeclHandler(g_parser, dummy_notation_decl_handler);
9275     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
9276         != XML_STATUS_ERROR)
9277       break;
9278     /* See comment in test_alloc_parse_xdecl() */
9279     alloc_teardown();
9280     alloc_setup();
9281   }
9282   if (i == 0)
9283     fail("Parse succeeded despite allocation failures");
9284   if (i == max_alloc_count)
9285     fail("Parse failed at maximum allocation count");
9286   if (dummy_handler_flags != DUMMY_NOTATION_DECL_HANDLER_FLAG)
9287     fail("Notation handler not called");
9288 }
9289 END_TEST
9290 
9291 START_TEST(test_alloc_nested_groups) {
9292   const char *text
9293       = "<!DOCTYPE doc [\n"
9294         "<!ELEMENT doc "
9295         /* Sixteen elements per line */
9296         "(e,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,"
9297         "(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?"
9298         "))))))))))))))))))))))))))))))))>\n"
9299         "<!ELEMENT e EMPTY>"
9300         "]>\n"
9301         "<doc><e/></doc>";
9302   CharData storage;
9303   int i;
9304   const int max_alloc_count = 20;
9305 
9306   for (i = 0; i < max_alloc_count; i++) {
9307     allocation_count = i;
9308     CharData_Init(&storage);
9309     XML_SetElementDeclHandler(g_parser, dummy_element_decl_handler);
9310     XML_SetStartElementHandler(g_parser, record_element_start_handler);
9311     XML_SetUserData(g_parser, &storage);
9312     dummy_handler_flags = 0;
9313     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
9314         != XML_STATUS_ERROR)
9315       break;
9316     /* See comment in test_alloc_parse_xdecl() */
9317     alloc_teardown();
9318     alloc_setup();
9319   }
9320 
9321   if (i == 0)
9322     fail("Parse succeeded despite failing reallocator");
9323   if (i == max_alloc_count)
9324     fail("Parse failed at maximum reallocation count");
9325   CharData_CheckXMLChars(&storage, XCS("doce"));
9326   if (dummy_handler_flags != DUMMY_ELEMENT_DECL_HANDLER_FLAG)
9327     fail("Element handler not fired");
9328 }
9329 END_TEST
9330 
9331 START_TEST(test_alloc_realloc_nested_groups) {
9332   const char *text
9333       = "<!DOCTYPE doc [\n"
9334         "<!ELEMENT doc "
9335         /* Sixteen elements per line */
9336         "(e,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,"
9337         "(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?"
9338         "))))))))))))))))))))))))))))))))>\n"
9339         "<!ELEMENT e EMPTY>"
9340         "]>\n"
9341         "<doc><e/></doc>";
9342   CharData storage;
9343   int i;
9344   const int max_realloc_count = 10;
9345 
9346   for (i = 0; i < max_realloc_count; i++) {
9347     reallocation_count = i;
9348     CharData_Init(&storage);
9349     XML_SetElementDeclHandler(g_parser, dummy_element_decl_handler);
9350     XML_SetStartElementHandler(g_parser, record_element_start_handler);
9351     XML_SetUserData(g_parser, &storage);
9352     dummy_handler_flags = 0;
9353     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
9354         != XML_STATUS_ERROR)
9355       break;
9356     /* See comment in test_alloc_parse_xdecl() */
9357     alloc_teardown();
9358     alloc_setup();
9359   }
9360 
9361   if (i == 0)
9362     fail("Parse succeeded despite failing reallocator");
9363   if (i == max_realloc_count)
9364     fail("Parse failed at maximum reallocation count");
9365   CharData_CheckXMLChars(&storage, XCS("doce"));
9366   if (dummy_handler_flags != DUMMY_ELEMENT_DECL_HANDLER_FLAG)
9367     fail("Element handler not fired");
9368 }
9369 END_TEST
9370 
9371 START_TEST(test_alloc_large_group) {
9372   const char *text = "<!DOCTYPE doc [\n"
9373                      "<!ELEMENT doc ("
9374                      "a1|a2|a3|a4|a5|a6|a7|a8|"
9375                      "b1|b2|b3|b4|b5|b6|b7|b8|"
9376                      "c1|c2|c3|c4|c5|c6|c7|c8|"
9377                      "d1|d2|d3|d4|d5|d6|d7|d8|"
9378                      "e1"
9379                      ")+>\n"
9380                      "]>\n"
9381                      "<doc>\n"
9382                      "<a1/>\n"
9383                      "</doc>\n";
9384   int i;
9385   const int max_alloc_count = 50;
9386 
9387   for (i = 0; i < max_alloc_count; i++) {
9388     allocation_count = i;
9389     XML_SetElementDeclHandler(g_parser, dummy_element_decl_handler);
9390     dummy_handler_flags = 0;
9391     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
9392         != XML_STATUS_ERROR)
9393       break;
9394     /* See comment in test_alloc_parse_xdecl() */
9395     alloc_teardown();
9396     alloc_setup();
9397   }
9398   if (i == 0)
9399     fail("Parse succeeded despite failing allocator");
9400   if (i == max_alloc_count)
9401     fail("Parse failed at maximum allocation count");
9402   if (dummy_handler_flags != DUMMY_ELEMENT_DECL_HANDLER_FLAG)
9403     fail("Element handler flag not raised");
9404 }
9405 END_TEST
9406 
9407 START_TEST(test_alloc_realloc_group_choice) {
9408   const char *text = "<!DOCTYPE doc [\n"
9409                      "<!ELEMENT doc ("
9410                      "a1|a2|a3|a4|a5|a6|a7|a8|"
9411                      "b1|b2|b3|b4|b5|b6|b7|b8|"
9412                      "c1|c2|c3|c4|c5|c6|c7|c8|"
9413                      "d1|d2|d3|d4|d5|d6|d7|d8|"
9414                      "e1"
9415                      ")+>\n"
9416                      "]>\n"
9417                      "<doc>\n"
9418                      "<a1/>\n"
9419                      "<b2 attr='foo'>This is a foo</b2>\n"
9420                      "<c3></c3>\n"
9421                      "</doc>\n";
9422   int i;
9423   const int max_realloc_count = 10;
9424 
9425   for (i = 0; i < max_realloc_count; i++) {
9426     reallocation_count = i;
9427     XML_SetElementDeclHandler(g_parser, dummy_element_decl_handler);
9428     dummy_handler_flags = 0;
9429     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
9430         != XML_STATUS_ERROR)
9431       break;
9432     /* See comment in test_alloc_parse_xdecl() */
9433     alloc_teardown();
9434     alloc_setup();
9435   }
9436   if (i == 0)
9437     fail("Parse succeeded despite failing reallocator");
9438   if (i == max_realloc_count)
9439     fail("Parse failed at maximum reallocation count");
9440   if (dummy_handler_flags != DUMMY_ELEMENT_DECL_HANDLER_FLAG)
9441     fail("Element handler flag not raised");
9442 }
9443 END_TEST
9444 
9445 START_TEST(test_alloc_pi_in_epilog) {
9446   const char *text = "<doc></doc>\n"
9447                      "<?pi in epilog?>";
9448   int i;
9449   const int max_alloc_count = 15;
9450 
9451   for (i = 0; i < max_alloc_count; i++) {
9452     allocation_count = i;
9453     XML_SetProcessingInstructionHandler(g_parser, dummy_pi_handler);
9454     dummy_handler_flags = 0;
9455     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
9456         != XML_STATUS_ERROR)
9457       break;
9458     /* See comment in test_alloc_parse_xdecl() */
9459     alloc_teardown();
9460     alloc_setup();
9461   }
9462   if (i == 0)
9463     fail("Parse completed despite failing allocator");
9464   if (i == max_alloc_count)
9465     fail("Parse failed at maximum allocation count");
9466   if (dummy_handler_flags != DUMMY_PI_HANDLER_FLAG)
9467     fail("Processing instruction handler not invoked");
9468 }
9469 END_TEST
9470 
9471 START_TEST(test_alloc_comment_in_epilog) {
9472   const char *text = "<doc></doc>\n"
9473                      "<!-- comment in epilog -->";
9474   int i;
9475   const int max_alloc_count = 15;
9476 
9477   for (i = 0; i < max_alloc_count; i++) {
9478     allocation_count = i;
9479     XML_SetCommentHandler(g_parser, dummy_comment_handler);
9480     dummy_handler_flags = 0;
9481     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
9482         != XML_STATUS_ERROR)
9483       break;
9484     /* See comment in test_alloc_parse_xdecl() */
9485     alloc_teardown();
9486     alloc_setup();
9487   }
9488   if (i == 0)
9489     fail("Parse completed despite failing allocator");
9490   if (i == max_alloc_count)
9491     fail("Parse failed at maximum allocation count");
9492   if (dummy_handler_flags != DUMMY_COMMENT_HANDLER_FLAG)
9493     fail("Processing instruction handler not invoked");
9494 }
9495 END_TEST
9496 
9497 START_TEST(test_alloc_realloc_long_attribute_value) {
9498   const char *text
9499       = "<!DOCTYPE doc [<!ENTITY foo '"
9500         /* Each line is 64 characters */
9501         "This entity will be substituted as an attribute value, and is   "
9502         "calculated to be exactly long enough that the terminating NUL   "
9503         "that the library adds internally will trigger the string pool to"
9504         "grow. GHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9505         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9506         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9507         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9508         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9509         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9510         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9511         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9512         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9513         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9514         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9515         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9516         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9517         "'>]>\n"
9518         "<doc a='&foo;'></doc>";
9519   int i;
9520   const int max_realloc_count = 10;
9521 
9522   for (i = 0; i < max_realloc_count; i++) {
9523     reallocation_count = i;
9524     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
9525         != XML_STATUS_ERROR)
9526       break;
9527     /* See comment in test_alloc_parse_xdecl() */
9528     alloc_teardown();
9529     alloc_setup();
9530   }
9531   if (i == 0)
9532     fail("Parse succeeded despite failing reallocator");
9533   if (i == max_realloc_count)
9534     fail("Parse failed at maximum reallocation count");
9535 }
9536 END_TEST
9537 
9538 START_TEST(test_alloc_attribute_whitespace) {
9539   const char *text = "<doc a=' '></doc>";
9540   int i;
9541   const int max_alloc_count = 15;
9542 
9543   for (i = 0; i < max_alloc_count; i++) {
9544     allocation_count = i;
9545     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
9546         != XML_STATUS_ERROR)
9547       break;
9548     /* See comment in test_alloc_parse_xdecl() */
9549     alloc_teardown();
9550     alloc_setup();
9551   }
9552   if (i == 0)
9553     fail("Parse succeeded despite failing allocator");
9554   if (i == max_alloc_count)
9555     fail("Parse failed at maximum allocation count");
9556 }
9557 END_TEST
9558 
9559 START_TEST(test_alloc_attribute_predefined_entity) {
9560   const char *text = "<doc a='&amp;'></doc>";
9561   int i;
9562   const int max_alloc_count = 15;
9563 
9564   for (i = 0; i < max_alloc_count; i++) {
9565     allocation_count = i;
9566     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
9567         != XML_STATUS_ERROR)
9568       break;
9569     /* See comment in test_alloc_parse_xdecl() */
9570     alloc_teardown();
9571     alloc_setup();
9572   }
9573   if (i == 0)
9574     fail("Parse succeeded despite failing allocator");
9575   if (i == max_alloc_count)
9576     fail("Parse failed at maximum allocation count");
9577 }
9578 END_TEST
9579 
9580 /* Test that a character reference at the end of a suitably long
9581  * default value for an attribute can trigger pool growth, and recovers
9582  * if the allocator fails on it.
9583  */
9584 START_TEST(test_alloc_long_attr_default_with_char_ref) {
9585   const char *text
9586       = "<!DOCTYPE doc [<!ATTLIST doc a CDATA '"
9587         /* 64 characters per line */
9588         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9589         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9590         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9591         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9592         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9593         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9594         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9595         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9596         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9597         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9598         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9599         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9600         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9601         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9602         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9603         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHI"
9604         "&#x31;'>]>\n"
9605         "<doc/>";
9606   int i;
9607   const int max_alloc_count = 20;
9608 
9609   for (i = 0; i < max_alloc_count; i++) {
9610     allocation_count = i;
9611     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
9612         != XML_STATUS_ERROR)
9613       break;
9614     /* See comment in test_alloc_parse_xdecl() */
9615     alloc_teardown();
9616     alloc_setup();
9617   }
9618   if (i == 0)
9619     fail("Parse succeeded despite failing allocator");
9620   if (i == max_alloc_count)
9621     fail("Parse failed at maximum allocation count");
9622 }
9623 END_TEST
9624 
9625 /* Test that a long character reference substitution triggers a pool
9626  * expansion correctly for an attribute value.
9627  */
9628 START_TEST(test_alloc_long_attr_value) {
9629   const char *text
9630       = "<!DOCTYPE test [<!ENTITY foo '\n"
9631         /* 64 characters per line */
9632         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9633         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9634         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9635         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9636         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9637         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9638         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9639         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9640         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9641         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9642         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9643         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9644         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9645         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9646         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9647         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9648         "'>]>\n"
9649         "<test a='&foo;'/>";
9650   int i;
9651   const int max_alloc_count = 25;
9652 
9653   for (i = 0; i < max_alloc_count; i++) {
9654     allocation_count = i;
9655     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
9656         != XML_STATUS_ERROR)
9657       break;
9658     /* See comment in test_alloc_parse_xdecl() */
9659     alloc_teardown();
9660     alloc_setup();
9661   }
9662   if (i == 0)
9663     fail("Parse succeeded despite failing allocator");
9664   if (i == max_alloc_count)
9665     fail("Parse failed at maximum allocation count");
9666 }
9667 END_TEST
9668 
9669 /* Test that an error in a nested parameter entity substitution is
9670  * handled correctly.  It seems unlikely that the code path being
9671  * exercised can be reached purely by carefully crafted XML, but an
9672  * allocation error in the right place will definitely do it.
9673  */
9674 START_TEST(test_alloc_nested_entities) {
9675   const char *text = "<!DOCTYPE doc SYSTEM 'http://example.org/one.ent'>\n"
9676                      "<doc />";
9677   ExtFaults test_data
9678       = {"<!ENTITY % pe1 '"
9679          /* 64 characters per line */
9680          "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9681          "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9682          "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9683          "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9684          "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9685          "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9686          "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9687          "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9688          "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9689          "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9690          "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9691          "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9692          "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9693          "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9694          "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9695          "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9696          "'>\n"
9697          "<!ENTITY % pe2 '%pe1;'>\n"
9698          "%pe2;",
9699          "Memory Fail not faulted", NULL, XML_ERROR_NO_MEMORY};
9700 
9701   /* Causes an allocation error in a nested storeEntityValue() */
9702   allocation_count = 12;
9703   XML_SetUserData(g_parser, &test_data);
9704   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
9705   XML_SetExternalEntityRefHandler(g_parser, external_entity_faulter);
9706   expect_failure(text, XML_ERROR_EXTERNAL_ENTITY_HANDLING,
9707                  "Entity allocation failure not noted");
9708 }
9709 END_TEST
9710 
9711 START_TEST(test_alloc_realloc_param_entity_newline) {
9712   const char *text = "<!DOCTYPE doc SYSTEM 'http://example.org/'>\n"
9713                      "<doc/>";
9714   char dtd_text[]
9715       = "<!ENTITY % pe '<!ATTLIST doc att CDATA \""
9716         /* 64 characters per line */
9717         "This default value is carefully crafted so that the carriage    "
9718         "return right at the end of the entity string causes an internal "
9719         "string pool to have to grow.  This allows us to test the alloc  "
9720         "failure path from that point. OPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9721         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9722         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9723         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9724         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9725         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9726         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9727         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9728         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9729         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9730         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9731         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9732         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDE"
9733         "\">\n'>"
9734         "%pe;\n";
9735   int i;
9736   const int max_realloc_count = 5;
9737 
9738   for (i = 0; i < max_realloc_count; i++) {
9739     reallocation_count = i;
9740     XML_SetUserData(g_parser, dtd_text);
9741     XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
9742     XML_SetExternalEntityRefHandler(g_parser, external_entity_alloc);
9743     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
9744         != XML_STATUS_ERROR)
9745       break;
9746     /* See comment in test_alloc_parse_xdecl() */
9747     alloc_teardown();
9748     alloc_setup();
9749   }
9750   if (i == 0)
9751     fail("Parse succeeded despite failing reallocator");
9752   if (i == max_realloc_count)
9753     fail("Parse failed at maximum reallocation count");
9754 }
9755 END_TEST
9756 
9757 START_TEST(test_alloc_realloc_ce_extends_pe) {
9758   const char *text = "<!DOCTYPE doc SYSTEM 'http://example.org/'>\n"
9759                      "<doc/>";
9760   char dtd_text[]
9761       = "<!ENTITY % pe '<!ATTLIST doc att CDATA \""
9762         /* 64 characters per line */
9763         "This default value is carefully crafted so that the character   "
9764         "entity at the end causes an internal string pool to have to     "
9765         "grow.  This allows us to test the allocation failure path from  "
9766         "that point onwards. EFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9767         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9768         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9769         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9770         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9771         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9772         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9773         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9774         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9775         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9776         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9777         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9778         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFG&#x51;"
9779         "\">\n'>"
9780         "%pe;\n";
9781   int i;
9782   const int max_realloc_count = 5;
9783 
9784   for (i = 0; i < max_realloc_count; i++) {
9785     reallocation_count = i;
9786     XML_SetUserData(g_parser, dtd_text);
9787     XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
9788     XML_SetExternalEntityRefHandler(g_parser, external_entity_alloc);
9789     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
9790         != XML_STATUS_ERROR)
9791       break;
9792     /* See comment in test_alloc_parse_xdecl() */
9793     alloc_teardown();
9794     alloc_setup();
9795   }
9796   if (i == 0)
9797     fail("Parse succeeded despite failing reallocator");
9798   if (i == max_realloc_count)
9799     fail("Parse failed at maximum reallocation count");
9800 }
9801 END_TEST
9802 
9803 START_TEST(test_alloc_realloc_attributes) {
9804   const char *text = "<!DOCTYPE doc [\n"
9805                      "  <!ATTLIST doc\n"
9806                      "    a1  (a|b|c)   'a'\n"
9807                      "    a2  (foo|bar) #IMPLIED\n"
9808                      "    a3  NMTOKEN   #IMPLIED\n"
9809                      "    a4  NMTOKENS  #IMPLIED\n"
9810                      "    a5  ID        #IMPLIED\n"
9811                      "    a6  IDREF     #IMPLIED\n"
9812                      "    a7  IDREFS    #IMPLIED\n"
9813                      "    a8  ENTITY    #IMPLIED\n"
9814                      "    a9  ENTITIES  #IMPLIED\n"
9815                      "    a10 CDATA     #IMPLIED\n"
9816                      "  >]>\n"
9817                      "<doc>wombat</doc>\n";
9818   int i;
9819   const int max_realloc_count = 5;
9820 
9821   for (i = 0; i < max_realloc_count; i++) {
9822     reallocation_count = i;
9823     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
9824         != XML_STATUS_ERROR)
9825       break;
9826     /* See comment in test_alloc_parse_xdecl() */
9827     alloc_teardown();
9828     alloc_setup();
9829   }
9830 
9831   if (i == 0)
9832     fail("Parse succeeded despite failing reallocator");
9833   if (i == max_realloc_count)
9834     fail("Parse failed at maximum reallocation count");
9835 }
9836 END_TEST
9837 
9838 START_TEST(test_alloc_long_doc_name) {
9839   const char *text =
9840       /* 64 characters per line */
9841       "<LongRootElementNameThatWillCauseTheNextAllocationToExpandTheStr"
9842       "ingPoolForTheDTDQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9843       "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9844       "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9845       "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9846       "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9847       "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9848       "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9849       "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9850       "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9851       "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9852       "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9853       "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9854       "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9855       "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9856       "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9857       " a='1'/>";
9858   int i;
9859   const int max_alloc_count = 20;
9860 
9861   for (i = 0; i < max_alloc_count; i++) {
9862     allocation_count = i;
9863     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
9864         != XML_STATUS_ERROR)
9865       break;
9866     /* See comment in test_alloc_parse_xdecl() */
9867     alloc_teardown();
9868     alloc_setup();
9869   }
9870   if (i == 0)
9871     fail("Parsing worked despite failing reallocations");
9872   else if (i == max_alloc_count)
9873     fail("Parsing failed even at max reallocation count");
9874 }
9875 END_TEST
9876 
9877 START_TEST(test_alloc_long_base) {
9878   const char *text = "<!DOCTYPE doc [\n"
9879                      "  <!ENTITY e SYSTEM 'foo'>\n"
9880                      "]>\n"
9881                      "<doc>&e;</doc>";
9882   char entity_text[] = "Hello world";
9883   const XML_Char *base =
9884       /* 64 characters per line */
9885       /* clang-format off */
9886         XCS("LongBaseURI/that/will/overflow/an/internal/buffer/and/cause/it/t")
9887         XCS("o/have/to/grow/PQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/")
9888         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/")
9889         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/")
9890         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/")
9891         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/")
9892         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/")
9893         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/")
9894         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/")
9895         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/")
9896         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/")
9897         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/")
9898         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/")
9899         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/")
9900         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/")
9901         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/");
9902   /* clang-format on */
9903   int i;
9904   const int max_alloc_count = 25;
9905 
9906   for (i = 0; i < max_alloc_count; i++) {
9907     allocation_count = i;
9908     XML_SetUserData(g_parser, entity_text);
9909     XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
9910     XML_SetExternalEntityRefHandler(g_parser, external_entity_alloc);
9911     if (XML_SetBase(g_parser, base) == XML_STATUS_ERROR) {
9912       XML_ParserReset(g_parser, NULL);
9913       continue;
9914     }
9915     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
9916         != XML_STATUS_ERROR)
9917       break;
9918     /* See comment in test_alloc_parse_xdecl() */
9919     alloc_teardown();
9920     alloc_setup();
9921   }
9922   if (i == 0)
9923     fail("Parsing worked despite failing allocations");
9924   else if (i == max_alloc_count)
9925     fail("Parsing failed even at max allocation count");
9926 }
9927 END_TEST
9928 
9929 START_TEST(test_alloc_long_public_id) {
9930   const char *text
9931       = "<!DOCTYPE doc [\n"
9932         "  <!ENTITY e PUBLIC '"
9933         /* 64 characters per line */
9934         "LongPublicIDThatShouldResultInAnInternalStringPoolGrowingAtASpec"
9935         "ificMomentKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9936         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9937         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9938         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9939         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9940         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9941         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9942         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9943         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9944         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9945         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9946         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9947         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9948         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9949         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9950         "' 'bar'>\n"
9951         "]>\n"
9952         "<doc>&e;</doc>";
9953   char entity_text[] = "Hello world";
9954   int i;
9955   const int max_alloc_count = 40;
9956 
9957   for (i = 0; i < max_alloc_count; i++) {
9958     allocation_count = i;
9959     XML_SetUserData(g_parser, entity_text);
9960     XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
9961     XML_SetExternalEntityRefHandler(g_parser, external_entity_alloc);
9962     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
9963         != XML_STATUS_ERROR)
9964       break;
9965     /* See comment in test_alloc_parse_xdecl() */
9966     alloc_teardown();
9967     alloc_setup();
9968   }
9969   if (i == 0)
9970     fail("Parsing worked despite failing allocations");
9971   else if (i == max_alloc_count)
9972     fail("Parsing failed even at max allocation count");
9973 }
9974 END_TEST
9975 
9976 START_TEST(test_alloc_long_entity_value) {
9977   const char *text
9978       = "<!DOCTYPE doc [\n"
9979         "  <!ENTITY e1 '"
9980         /* 64 characters per line */
9981         "Long entity value that should provoke a string pool to grow whil"
9982         "e setting up to parse the external entity below. xyz0123456789AB"
9983         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9984         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9985         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9986         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9987         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9988         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9989         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9990         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9991         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9992         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9993         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9994         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9995         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9996         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9997         "'>\n"
9998         "  <!ENTITY e2 SYSTEM 'bar'>\n"
9999         "]>\n"
10000         "<doc>&e2;</doc>";
10001   char entity_text[] = "Hello world";
10002   int i;
10003   const int max_alloc_count = 40;
10004 
10005   for (i = 0; i < max_alloc_count; i++) {
10006     allocation_count = i;
10007     XML_SetUserData(g_parser, entity_text);
10008     XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
10009     XML_SetExternalEntityRefHandler(g_parser, external_entity_alloc);
10010     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
10011         != XML_STATUS_ERROR)
10012       break;
10013     /* See comment in test_alloc_parse_xdecl() */
10014     alloc_teardown();
10015     alloc_setup();
10016   }
10017   if (i == 0)
10018     fail("Parsing worked despite failing allocations");
10019   else if (i == max_alloc_count)
10020     fail("Parsing failed even at max allocation count");
10021 }
10022 END_TEST
10023 
10024 START_TEST(test_alloc_long_notation) {
10025   const char *text
10026       = "<!DOCTYPE doc [\n"
10027         "  <!NOTATION note SYSTEM '"
10028         /* 64 characters per line */
10029         "ALongNotationNameThatShouldProvokeStringPoolGrowthWhileCallingAn"
10030         "ExternalEntityParserUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
10031         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
10032         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
10033         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
10034         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
10035         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
10036         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
10037         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
10038         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
10039         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
10040         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
10041         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
10042         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
10043         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
10044         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
10045         "'>\n"
10046         "  <!ENTITY e1 SYSTEM 'foo' NDATA "
10047         /* 64 characters per line */
10048         "ALongNotationNameThatShouldProvokeStringPoolGrowthWhileCallingAn"
10049         "ExternalEntityParserUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
10050         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
10051         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
10052         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
10053         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
10054         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
10055         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
10056         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
10057         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
10058         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
10059         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
10060         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
10061         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
10062         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
10063         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
10064         ">\n"
10065         "  <!ENTITY e2 SYSTEM 'bar'>\n"
10066         "]>\n"
10067         "<doc>&e2;</doc>";
10068   ExtOption options[]
10069       = {{XCS("foo"), "Entity Foo"}, {XCS("bar"), "Entity Bar"}, {NULL, NULL}};
10070   int i;
10071   const int max_alloc_count = 40;
10072 
10073   for (i = 0; i < max_alloc_count; i++) {
10074     allocation_count = i;
10075     XML_SetUserData(g_parser, options);
10076     XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
10077     XML_SetExternalEntityRefHandler(g_parser, external_entity_optioner);
10078     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
10079         != XML_STATUS_ERROR)
10080       break;
10081 
10082     /* See comment in test_alloc_parse_xdecl() */
10083     alloc_teardown();
10084     alloc_setup();
10085   }
10086   if (i == 0)
10087     fail("Parsing worked despite failing allocations");
10088   else if (i == max_alloc_count)
10089     fail("Parsing failed even at max allocation count");
10090 }
10091 END_TEST
10092 
10093 static void
10094 nsalloc_setup(void) {
10095   XML_Memory_Handling_Suite memsuite = {duff_allocator, duff_reallocator, free};
10096   XML_Char ns_sep[2] = {' ', '\0'};
10097 
10098   /* Ensure the parser creation will go through */
10099   allocation_count = ALLOC_ALWAYS_SUCCEED;
10100   reallocation_count = REALLOC_ALWAYS_SUCCEED;
10101   g_parser = XML_ParserCreate_MM(NULL, &memsuite, ns_sep);
10102   if (g_parser == NULL)
10103     fail("Parser not created");
10104 }
10105 
10106 static void
10107 nsalloc_teardown(void) {
10108   basic_teardown();
10109 }
10110 
10111 /* Test the effects of allocation failure in simple namespace parsing.
10112  * Based on test_ns_default_with_empty_uri()
10113  */
10114 START_TEST(test_nsalloc_xmlns) {
10115   const char *text = "<doc xmlns='http://example.org/'>\n"
10116                      "  <e xmlns=''/>\n"
10117                      "</doc>";
10118   unsigned int i;
10119   const unsigned int max_alloc_count = 30;
10120 
10121   for (i = 0; i < max_alloc_count; i++) {
10122     allocation_count = i;
10123     /* Exercise more code paths with a default handler */
10124     XML_SetDefaultHandler(g_parser, dummy_default_handler);
10125     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
10126         != XML_STATUS_ERROR)
10127       break;
10128     /* Resetting the parser is insufficient, because some memory
10129      * allocations are cached within the parser.  Instead we use
10130      * the teardown and setup routines to ensure that we have the
10131      * right sort of parser back in our hands.
10132      */
10133     nsalloc_teardown();
10134     nsalloc_setup();
10135   }
10136   if (i == 0)
10137     fail("Parsing worked despite failing allocations");
10138   else if (i == max_alloc_count)
10139     fail("Parsing failed even at maximum allocation count");
10140 }
10141 END_TEST
10142 
10143 /* Test XML_ParseBuffer interface with namespace and a dicky allocator */
10144 START_TEST(test_nsalloc_parse_buffer) {
10145   const char *text = "<doc>Hello</doc>";
10146   void *buffer;
10147 
10148   /* Try a parse before the start of the world */
10149   /* (Exercises new code path) */
10150   if (XML_ParseBuffer(g_parser, 0, XML_FALSE) != XML_STATUS_ERROR)
10151     fail("Pre-init XML_ParseBuffer not faulted");
10152   if (XML_GetErrorCode(g_parser) != XML_ERROR_NO_BUFFER)
10153     fail("Pre-init XML_ParseBuffer faulted for wrong reason");
10154 
10155   buffer = XML_GetBuffer(g_parser, 1 /* any small number greater than 0 */);
10156   if (buffer == NULL)
10157     fail("Could not acquire parse buffer");
10158 
10159   allocation_count = 0;
10160   if (XML_ParseBuffer(g_parser, 0, XML_FALSE) != XML_STATUS_ERROR)
10161     fail("Pre-init XML_ParseBuffer not faulted");
10162   if (XML_GetErrorCode(g_parser) != XML_ERROR_NO_MEMORY)
10163     fail("Pre-init XML_ParseBuffer faulted for wrong reason");
10164 
10165   /* Now with actual memory allocation */
10166   allocation_count = ALLOC_ALWAYS_SUCCEED;
10167   if (XML_ParseBuffer(g_parser, 0, XML_FALSE) != XML_STATUS_OK)
10168     xml_failure(g_parser);
10169 
10170   /* Check that resuming an unsuspended parser is faulted */
10171   if (XML_ResumeParser(g_parser) != XML_STATUS_ERROR)
10172     fail("Resuming unsuspended parser not faulted");
10173   if (XML_GetErrorCode(g_parser) != XML_ERROR_NOT_SUSPENDED)
10174     xml_failure(g_parser);
10175 
10176   /* Get the parser into suspended state */
10177   XML_SetCharacterDataHandler(g_parser, clearing_aborting_character_handler);
10178   resumable = XML_TRUE;
10179   buffer = XML_GetBuffer(g_parser, (int)strlen(text));
10180   if (buffer == NULL)
10181     fail("Could not acquire parse buffer");
10182   assert(buffer != NULL);
10183   memcpy(buffer, text, strlen(text));
10184   if (XML_ParseBuffer(g_parser, (int)strlen(text), XML_TRUE)
10185       != XML_STATUS_SUSPENDED)
10186     xml_failure(g_parser);
10187   if (XML_GetErrorCode(g_parser) != XML_ERROR_NONE)
10188     xml_failure(g_parser);
10189   if (XML_ParseBuffer(g_parser, (int)strlen(text), XML_TRUE)
10190       != XML_STATUS_ERROR)
10191     fail("Suspended XML_ParseBuffer not faulted");
10192   if (XML_GetErrorCode(g_parser) != XML_ERROR_SUSPENDED)
10193     xml_failure(g_parser);
10194   if (XML_GetBuffer(g_parser, (int)strlen(text)) != NULL)
10195     fail("Suspended XML_GetBuffer not faulted");
10196 
10197   /* Get it going again and complete the world */
10198   XML_SetCharacterDataHandler(g_parser, NULL);
10199   if (XML_ResumeParser(g_parser) != XML_STATUS_OK)
10200     xml_failure(g_parser);
10201   if (XML_ParseBuffer(g_parser, (int)strlen(text), XML_TRUE)
10202       != XML_STATUS_ERROR)
10203     fail("Post-finishing XML_ParseBuffer not faulted");
10204   if (XML_GetErrorCode(g_parser) != XML_ERROR_FINISHED)
10205     xml_failure(g_parser);
10206   if (XML_GetBuffer(g_parser, (int)strlen(text)) != NULL)
10207     fail("Post-finishing XML_GetBuffer not faulted");
10208 }
10209 END_TEST
10210 
10211 /* Check handling of long prefix names (pool growth) */
10212 START_TEST(test_nsalloc_long_prefix) {
10213   const char *text
10214       = "<"
10215         /* 64 characters per line */
10216         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10217         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10218         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10219         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10220         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10221         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10222         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10223         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10224         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10225         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10226         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10227         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10228         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10229         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10230         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10231         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10232         ":foo xmlns:"
10233         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10234         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10235         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10236         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10237         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10238         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10239         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10240         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10241         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10242         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10243         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10244         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10245         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10246         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10247         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10248         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10249         "='http://example.org/'>"
10250         "</"
10251         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10252         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10253         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10254         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10255         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10256         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10257         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10258         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10259         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10260         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10261         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10262         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10263         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10264         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10265         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10266         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10267         ":foo>";
10268   int i;
10269   const int max_alloc_count = 40;
10270 
10271   for (i = 0; i < max_alloc_count; i++) {
10272     allocation_count = i;
10273     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
10274         != XML_STATUS_ERROR)
10275       break;
10276     /* See comment in test_nsalloc_xmlns() */
10277     nsalloc_teardown();
10278     nsalloc_setup();
10279   }
10280   if (i == 0)
10281     fail("Parsing worked despite failing allocations");
10282   else if (i == max_alloc_count)
10283     fail("Parsing failed even at max allocation count");
10284 }
10285 END_TEST
10286 
10287 /* Check handling of long uri names (pool growth) */
10288 START_TEST(test_nsalloc_long_uri) {
10289   const char *text
10290       = "<foo:e xmlns:foo='http://example.org/"
10291         /* 64 characters per line */
10292         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10293         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10294         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10295         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10296         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10297         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10298         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10299         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10300         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10301         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10302         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10303         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10304         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10305         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10306         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10307         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10308         "' bar:a='12'\n"
10309         "xmlns:bar='http://example.org/"
10310         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10311         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10312         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10313         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10314         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10315         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10316         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10317         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10318         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10319         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10320         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10321         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10322         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10323         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10324         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10325         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10326         "'>"
10327         "</foo:e>";
10328   int i;
10329   const int max_alloc_count = 40;
10330 
10331   for (i = 0; i < max_alloc_count; i++) {
10332     allocation_count = i;
10333     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
10334         != XML_STATUS_ERROR)
10335       break;
10336     /* See comment in test_nsalloc_xmlns() */
10337     nsalloc_teardown();
10338     nsalloc_setup();
10339   }
10340   if (i == 0)
10341     fail("Parsing worked despite failing allocations");
10342   else if (i == max_alloc_count)
10343     fail("Parsing failed even at max allocation count");
10344 }
10345 END_TEST
10346 
10347 /* Test handling of long attribute names with prefixes */
10348 START_TEST(test_nsalloc_long_attr) {
10349   const char *text
10350       = "<foo:e xmlns:foo='http://example.org/' bar:"
10351         /* 64 characters per line */
10352         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10353         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10354         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10355         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10356         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10357         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10358         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10359         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10360         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10361         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10362         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10363         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10364         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10365         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10366         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10367         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10368         "='12'\n"
10369         "xmlns:bar='http://example.org/'>"
10370         "</foo:e>";
10371   int i;
10372   const int max_alloc_count = 40;
10373 
10374   for (i = 0; i < max_alloc_count; i++) {
10375     allocation_count = i;
10376     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
10377         != XML_STATUS_ERROR)
10378       break;
10379     /* See comment in test_nsalloc_xmlns() */
10380     nsalloc_teardown();
10381     nsalloc_setup();
10382   }
10383   if (i == 0)
10384     fail("Parsing worked despite failing allocations");
10385   else if (i == max_alloc_count)
10386     fail("Parsing failed even at max allocation count");
10387 }
10388 END_TEST
10389 
10390 /* Test handling of an attribute name with a long namespace prefix */
10391 START_TEST(test_nsalloc_long_attr_prefix) {
10392   const char *text
10393       = "<foo:e xmlns:foo='http://example.org/' "
10394         /* 64 characters per line */
10395         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10396         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10397         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10398         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10399         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10400         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10401         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10402         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10403         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10404         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10405         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10406         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10407         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10408         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10409         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10410         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10411         ":a='12'\n"
10412         "xmlns:"
10413         /* 64 characters per line */
10414         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10415         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10416         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10417         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10418         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10419         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10420         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10421         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10422         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10423         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10424         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10425         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10426         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10427         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10428         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10429         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10430         "='http://example.org/'>"
10431         "</foo:e>";
10432   const XML_Char *elemstr[] = {
10433       /* clang-format off */
10434         XCS("http://example.org/ e foo"),
10435         XCS("http://example.org/ a ")
10436         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ")
10437         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ")
10438         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ")
10439         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ")
10440         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ")
10441         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ")
10442         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ")
10443         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ")
10444         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ")
10445         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ")
10446         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ")
10447         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ")
10448         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ")
10449         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ")
10450         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ")
10451         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ")
10452       /* clang-format on */
10453   };
10454   int i;
10455   const int max_alloc_count = 40;
10456 
10457   for (i = 0; i < max_alloc_count; i++) {
10458     allocation_count = i;
10459     XML_SetReturnNSTriplet(g_parser, XML_TRUE);
10460     XML_SetUserData(g_parser, (void *)elemstr);
10461     XML_SetElementHandler(g_parser, triplet_start_checker, triplet_end_checker);
10462     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
10463         != XML_STATUS_ERROR)
10464       break;
10465     /* See comment in test_nsalloc_xmlns() */
10466     nsalloc_teardown();
10467     nsalloc_setup();
10468   }
10469   if (i == 0)
10470     fail("Parsing worked despite failing allocations");
10471   else if (i == max_alloc_count)
10472     fail("Parsing failed even at max allocation count");
10473 }
10474 END_TEST
10475 
10476 /* Test attribute handling in the face of a dodgy reallocator */
10477 START_TEST(test_nsalloc_realloc_attributes) {
10478   const char *text = "<foo:e xmlns:foo='http://example.org/' bar:a='12'\n"
10479                      "       xmlns:bar='http://example.org/'>"
10480                      "</foo:e>";
10481   int i;
10482   const int max_realloc_count = 10;
10483 
10484   for (i = 0; i < max_realloc_count; i++) {
10485     reallocation_count = i;
10486     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
10487         != XML_STATUS_ERROR)
10488       break;
10489     /* See comment in test_nsalloc_xmlns() */
10490     nsalloc_teardown();
10491     nsalloc_setup();
10492   }
10493   if (i == 0)
10494     fail("Parsing worked despite failing reallocations");
10495   else if (i == max_realloc_count)
10496     fail("Parsing failed at max reallocation count");
10497 }
10498 END_TEST
10499 
10500 /* Test long element names with namespaces under a failing allocator */
10501 START_TEST(test_nsalloc_long_element) {
10502   const char *text
10503       = "<foo:thisisalongenoughelementnametotriggerareallocation\n"
10504         " xmlns:foo='http://example.org/' bar:a='12'\n"
10505         " xmlns:bar='http://example.org/'>"
10506         "</foo:thisisalongenoughelementnametotriggerareallocation>";
10507   const XML_Char *elemstr[]
10508       = {XCS("http://example.org/")
10509              XCS(" thisisalongenoughelementnametotriggerareallocation foo"),
10510          XCS("http://example.org/ a bar")};
10511   int i;
10512   const int max_alloc_count = 30;
10513 
10514   for (i = 0; i < max_alloc_count; i++) {
10515     allocation_count = i;
10516     XML_SetReturnNSTriplet(g_parser, XML_TRUE);
10517     XML_SetUserData(g_parser, (void *)elemstr);
10518     XML_SetElementHandler(g_parser, triplet_start_checker, triplet_end_checker);
10519     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
10520         != XML_STATUS_ERROR)
10521       break;
10522     /* See comment in test_nsalloc_xmlns() */
10523     nsalloc_teardown();
10524     nsalloc_setup();
10525   }
10526   if (i == 0)
10527     fail("Parsing worked despite failing reallocations");
10528   else if (i == max_alloc_count)
10529     fail("Parsing failed at max reallocation count");
10530 }
10531 END_TEST
10532 
10533 /* Test the effects of reallocation failure when reassigning a
10534  * binding.
10535  *
10536  * XML_ParserReset does not free the BINDING structures used by a
10537  * parser, but instead adds them to an internal free list to be reused
10538  * as necessary.  Likewise the URI buffers allocated for the binding
10539  * aren't freed, but kept attached to their existing binding.  If the
10540  * new binding has a longer URI, it will need reallocation.  This test
10541  * provokes that reallocation, and tests the control path if it fails.
10542  */
10543 START_TEST(test_nsalloc_realloc_binding_uri) {
10544   const char *first = "<doc xmlns='http://example.org/'>\n"
10545                       "  <e xmlns='' />\n"
10546                       "</doc>";
10547   const char *second
10548       = "<doc xmlns='http://example.org/long/enough/URI/to/reallocate/'>\n"
10549         "  <e xmlns='' />\n"
10550         "</doc>";
10551   unsigned i;
10552   const unsigned max_realloc_count = 10;
10553 
10554   /* First, do a full parse that will leave bindings around */
10555   if (_XML_Parse_SINGLE_BYTES(g_parser, first, (int)strlen(first), XML_TRUE)
10556       == XML_STATUS_ERROR)
10557     xml_failure(g_parser);
10558 
10559   /* Now repeat with a longer URI and a duff reallocator */
10560   for (i = 0; i < max_realloc_count; i++) {
10561     XML_ParserReset(g_parser, NULL);
10562     reallocation_count = i;
10563     if (_XML_Parse_SINGLE_BYTES(g_parser, second, (int)strlen(second), XML_TRUE)
10564         != XML_STATUS_ERROR)
10565       break;
10566   }
10567   if (i == 0)
10568     fail("Parsing worked despite failing reallocation");
10569   else if (i == max_realloc_count)
10570     fail("Parsing failed at max reallocation count");
10571 }
10572 END_TEST
10573 
10574 /* Check handling of long prefix names (pool growth) */
10575 START_TEST(test_nsalloc_realloc_long_prefix) {
10576   const char *text
10577       = "<"
10578         /* 64 characters per line */
10579         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10580         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10581         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10582         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10583         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10584         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10585         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10586         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10587         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10588         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10589         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10590         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10591         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10592         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10593         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10594         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10595         ":foo xmlns:"
10596         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10597         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10598         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10599         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10600         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10601         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10602         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10603         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10604         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10605         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10606         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10607         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10608         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10609         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10610         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10611         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10612         "='http://example.org/'>"
10613         "</"
10614         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10615         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10616         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10617         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10618         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10619         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10620         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10621         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10622         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10623         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10624         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10625         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10626         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10627         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10628         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10629         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10630         ":foo>";
10631   int i;
10632   const int max_realloc_count = 12;
10633 
10634   for (i = 0; i < max_realloc_count; i++) {
10635     reallocation_count = i;
10636     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
10637         != XML_STATUS_ERROR)
10638       break;
10639     /* See comment in test_nsalloc_xmlns() */
10640     nsalloc_teardown();
10641     nsalloc_setup();
10642   }
10643   if (i == 0)
10644     fail("Parsing worked despite failing reallocations");
10645   else if (i == max_realloc_count)
10646     fail("Parsing failed even at max reallocation count");
10647 }
10648 END_TEST
10649 
10650 /* Check handling of even long prefix names (different code path) */
10651 START_TEST(test_nsalloc_realloc_longer_prefix) {
10652   const char *text
10653       = "<"
10654         /* 64 characters per line */
10655         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10656         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10657         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10658         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10659         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10660         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10661         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10662         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10663         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10664         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10665         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10666         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10667         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10668         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10669         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10670         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10671         "Q:foo xmlns:"
10672         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10673         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10674         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10675         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10676         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10677         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10678         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10679         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10680         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10681         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10682         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10683         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10684         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10685         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10686         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10687         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10688         "Q='http://example.org/'>"
10689         "</"
10690         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10691         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10692         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10693         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10694         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10695         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10696         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10697         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10698         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10699         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10700         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10701         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10702         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10703         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10704         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10705         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10706         "Q:foo>";
10707   int i;
10708   const int max_realloc_count = 12;
10709 
10710   for (i = 0; i < max_realloc_count; i++) {
10711     reallocation_count = i;
10712     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
10713         != XML_STATUS_ERROR)
10714       break;
10715     /* See comment in test_nsalloc_xmlns() */
10716     nsalloc_teardown();
10717     nsalloc_setup();
10718   }
10719   if (i == 0)
10720     fail("Parsing worked despite failing reallocations");
10721   else if (i == max_realloc_count)
10722     fail("Parsing failed even at max reallocation count");
10723 }
10724 END_TEST
10725 
10726 START_TEST(test_nsalloc_long_namespace) {
10727   const char *text1
10728       = "<"
10729         /* 64 characters per line */
10730         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10731         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10732         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10733         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10734         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10735         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10736         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10737         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10738         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10739         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10740         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10741         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10742         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10743         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10744         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10745         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10746         ":e xmlns:"
10747         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10748         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10749         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10750         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10751         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10752         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10753         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10754         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10755         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10756         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10757         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10758         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10759         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10760         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10761         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10762         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10763         "='http://example.org/'>\n";
10764   const char *text2
10765       = "<"
10766         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10767         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10768         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10769         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10770         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10771         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10772         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10773         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10774         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10775         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10776         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10777         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10778         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10779         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10780         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10781         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10782         ":f "
10783         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10784         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10785         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10786         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10787         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10788         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10789         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10790         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10791         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10792         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10793         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10794         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10795         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10796         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10797         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10798         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10799         ":attr='foo'/>\n"
10800         "</"
10801         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10802         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10803         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10804         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10805         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10806         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10807         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10808         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10809         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10810         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10811         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10812         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10813         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10814         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10815         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10816         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10817         ":e>";
10818   int i;
10819   const int max_alloc_count = 40;
10820 
10821   for (i = 0; i < max_alloc_count; i++) {
10822     allocation_count = i;
10823     if (_XML_Parse_SINGLE_BYTES(g_parser, text1, (int)strlen(text1), XML_FALSE)
10824             != XML_STATUS_ERROR
10825         && _XML_Parse_SINGLE_BYTES(g_parser, text2, (int)strlen(text2),
10826                                    XML_TRUE)
10827                != XML_STATUS_ERROR)
10828       break;
10829     /* See comment in test_nsalloc_xmlns() */
10830     nsalloc_teardown();
10831     nsalloc_setup();
10832   }
10833   if (i == 0)
10834     fail("Parsing worked despite failing allocations");
10835   else if (i == max_alloc_count)
10836     fail("Parsing failed even at max allocation count");
10837 }
10838 END_TEST
10839 
10840 /* Using a slightly shorter namespace name provokes allocations in
10841  * slightly different places in the code.
10842  */
10843 START_TEST(test_nsalloc_less_long_namespace) {
10844   const char *text
10845       = "<"
10846         /* 64 characters per line */
10847         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10848         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10849         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10850         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10851         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10852         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10853         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10854         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz012345678"
10855         ":e xmlns:"
10856         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10857         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10858         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10859         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10860         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10861         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10862         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10863         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz012345678"
10864         "='http://example.org/'>\n"
10865         "<"
10866         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10867         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10868         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10869         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10870         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10871         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10872         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10873         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz012345678"
10874         ":f "
10875         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10876         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10877         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10878         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10879         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10880         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10881         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10882         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz012345678"
10883         ":att='foo'/>\n"
10884         "</"
10885         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10886         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10887         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10888         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10889         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10890         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10891         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10892         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz012345678"
10893         ":e>";
10894   int i;
10895   const int max_alloc_count = 40;
10896 
10897   for (i = 0; i < max_alloc_count; i++) {
10898     allocation_count = i;
10899     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
10900         != XML_STATUS_ERROR)
10901       break;
10902     /* See comment in test_nsalloc_xmlns() */
10903     nsalloc_teardown();
10904     nsalloc_setup();
10905   }
10906   if (i == 0)
10907     fail("Parsing worked despite failing allocations");
10908   else if (i == max_alloc_count)
10909     fail("Parsing failed even at max allocation count");
10910 }
10911 END_TEST
10912 
10913 START_TEST(test_nsalloc_long_context) {
10914   const char *text
10915       = "<!DOCTYPE doc SYSTEM 'foo' [\n"
10916         "  <!ATTLIST doc baz ID #REQUIRED>\n"
10917         "  <!ENTITY en SYSTEM 'bar'>\n"
10918         "]>\n"
10919         "<doc xmlns='http://example.org/"
10920         /* 64 characters per line */
10921         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10922         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10923         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10924         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10925         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10926         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10927         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10928         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10929         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10930         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10931         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10932         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10933         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10934         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10935         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10936         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKL"
10937         "' baz='2'>\n"
10938         "&en;"
10939         "</doc>";
10940   ExtOption options[] = {
10941       {XCS("foo"), "<!ELEMENT e EMPTY>"}, {XCS("bar"), "<e/>"}, {NULL, NULL}};
10942   int i;
10943   const int max_alloc_count = 70;
10944 
10945   for (i = 0; i < max_alloc_count; i++) {
10946     allocation_count = i;
10947     XML_SetUserData(g_parser, options);
10948     XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
10949     XML_SetExternalEntityRefHandler(g_parser, external_entity_optioner);
10950     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
10951         != XML_STATUS_ERROR)
10952       break;
10953 
10954     /* See comment in test_nsalloc_xmlns() */
10955     nsalloc_teardown();
10956     nsalloc_setup();
10957   }
10958   if (i == 0)
10959     fail("Parsing worked despite failing allocations");
10960   else if (i == max_alloc_count)
10961     fail("Parsing failed even at max allocation count");
10962 }
10963 END_TEST
10964 
10965 /* This function is void; it will throw a fail() on error, so if it
10966  * returns normally it must have succeeded.
10967  */
10968 static void
10969 context_realloc_test(const char *text) {
10970   ExtOption options[] = {
10971       {XCS("foo"), "<!ELEMENT e EMPTY>"}, {XCS("bar"), "<e/>"}, {NULL, NULL}};
10972   int i;
10973   const int max_realloc_count = 6;
10974 
10975   for (i = 0; i < max_realloc_count; i++) {
10976     reallocation_count = i;
10977     XML_SetUserData(g_parser, options);
10978     XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
10979     XML_SetExternalEntityRefHandler(g_parser, external_entity_optioner);
10980     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
10981         != XML_STATUS_ERROR)
10982       break;
10983     /* See comment in test_nsalloc_xmlns() */
10984     nsalloc_teardown();
10985     nsalloc_setup();
10986   }
10987   if (i == 0)
10988     fail("Parsing worked despite failing reallocations");
10989   else if (i == max_realloc_count)
10990     fail("Parsing failed even at max reallocation count");
10991 }
10992 
10993 START_TEST(test_nsalloc_realloc_long_context) {
10994   const char *text
10995       = "<!DOCTYPE doc SYSTEM 'foo' [\n"
10996         "  <!ENTITY en SYSTEM 'bar'>\n"
10997         "]>\n"
10998         "<doc xmlns='http://example.org/"
10999         /* 64 characters per line */
11000         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11001         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11002         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11003         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11004         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11005         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11006         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11007         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11008         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11009         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11010         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11011         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11012         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11013         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11014         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11015         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKL"
11016         "'>\n"
11017         "&en;"
11018         "</doc>";
11019 
11020   context_realloc_test(text);
11021 }
11022 END_TEST
11023 
11024 START_TEST(test_nsalloc_realloc_long_context_2) {
11025   const char *text
11026       = "<!DOCTYPE doc SYSTEM 'foo' [\n"
11027         "  <!ENTITY en SYSTEM 'bar'>\n"
11028         "]>\n"
11029         "<doc xmlns='http://example.org/"
11030         /* 64 characters per line */
11031         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11032         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11033         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11034         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11035         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11036         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11037         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11038         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11039         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11040         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11041         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11042         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11043         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11044         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11045         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11046         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJK"
11047         "'>\n"
11048         "&en;"
11049         "</doc>";
11050 
11051   context_realloc_test(text);
11052 }
11053 END_TEST
11054 
11055 START_TEST(test_nsalloc_realloc_long_context_3) {
11056   const char *text
11057       = "<!DOCTYPE doc SYSTEM 'foo' [\n"
11058         "  <!ENTITY en SYSTEM 'bar'>\n"
11059         "]>\n"
11060         "<doc xmlns='http://example.org/"
11061         /* 64 characters per line */
11062         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11063         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11064         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11065         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11066         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11067         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11068         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11069         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11070         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11071         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11072         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11073         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11074         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11075         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11076         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11077         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGH"
11078         "'>\n"
11079         "&en;"
11080         "</doc>";
11081 
11082   context_realloc_test(text);
11083 }
11084 END_TEST
11085 
11086 START_TEST(test_nsalloc_realloc_long_context_4) {
11087   const char *text
11088       = "<!DOCTYPE doc SYSTEM 'foo' [\n"
11089         "  <!ENTITY en SYSTEM 'bar'>\n"
11090         "]>\n"
11091         "<doc xmlns='http://example.org/"
11092         /* 64 characters per line */
11093         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11094         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11095         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11096         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11097         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11098         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11099         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11100         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11101         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11102         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11103         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11104         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11105         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11106         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11107         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11108         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO"
11109         "'>\n"
11110         "&en;"
11111         "</doc>";
11112 
11113   context_realloc_test(text);
11114 }
11115 END_TEST
11116 
11117 START_TEST(test_nsalloc_realloc_long_context_5) {
11118   const char *text
11119       = "<!DOCTYPE doc SYSTEM 'foo' [\n"
11120         "  <!ENTITY en SYSTEM 'bar'>\n"
11121         "]>\n"
11122         "<doc xmlns='http://example.org/"
11123         /* 64 characters per line */
11124         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11125         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11126         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11127         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11128         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11129         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11130         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11131         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11132         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11133         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11134         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11135         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11136         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11137         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11138         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11139         "ABC"
11140         "'>\n"
11141         "&en;"
11142         "</doc>";
11143 
11144   context_realloc_test(text);
11145 }
11146 END_TEST
11147 
11148 START_TEST(test_nsalloc_realloc_long_context_6) {
11149   const char *text
11150       = "<!DOCTYPE doc SYSTEM 'foo' [\n"
11151         "  <!ENTITY en SYSTEM 'bar'>\n"
11152         "]>\n"
11153         "<doc xmlns='http://example.org/"
11154         /* 64 characters per line */
11155         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11156         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11157         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11158         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11159         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11160         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11161         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11162         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11163         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11164         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11165         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11166         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11167         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11168         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11169         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP"
11170         "'>\n"
11171         "&en;"
11172         "</doc>";
11173 
11174   context_realloc_test(text);
11175 }
11176 END_TEST
11177 
11178 START_TEST(test_nsalloc_realloc_long_context_7) {
11179   const char *text
11180       = "<!DOCTYPE doc SYSTEM 'foo' [\n"
11181         "  <!ENTITY en SYSTEM 'bar'>\n"
11182         "]>\n"
11183         "<doc xmlns='http://example.org/"
11184         /* 64 characters per line */
11185         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11186         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11187         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11188         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11189         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11190         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11191         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11192         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11193         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11194         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11195         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11196         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11197         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11198         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11199         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11200         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLM"
11201         "'>\n"
11202         "&en;"
11203         "</doc>";
11204 
11205   context_realloc_test(text);
11206 }
11207 END_TEST
11208 
11209 START_TEST(test_nsalloc_realloc_long_ge_name) {
11210   const char *text
11211       = "<!DOCTYPE doc SYSTEM 'foo' [\n"
11212         "  <!ENTITY "
11213         /* 64 characters per line */
11214         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11215         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11216         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11217         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11218         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11219         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11220         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11221         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11222         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11223         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11224         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11225         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11226         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11227         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11228         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11229         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11230         " SYSTEM 'bar'>\n"
11231         "]>\n"
11232         "<doc xmlns='http://example.org/baz'>\n"
11233         "&"
11234         /* 64 characters per line */
11235         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11236         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11237         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11238         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11239         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11240         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11241         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11242         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11243         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11244         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11245         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11246         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11247         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11248         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11249         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11250         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11251         ";"
11252         "</doc>";
11253   ExtOption options[] = {
11254       {XCS("foo"), "<!ELEMENT el EMPTY>"}, {XCS("bar"), "<el/>"}, {NULL, NULL}};
11255   int i;
11256   const int max_realloc_count = 10;
11257 
11258   for (i = 0; i < max_realloc_count; i++) {
11259     reallocation_count = i;
11260     XML_SetUserData(g_parser, options);
11261     XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
11262     XML_SetExternalEntityRefHandler(g_parser, external_entity_optioner);
11263     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
11264         != XML_STATUS_ERROR)
11265       break;
11266     /* See comment in test_nsalloc_xmlns() */
11267     nsalloc_teardown();
11268     nsalloc_setup();
11269   }
11270   if (i == 0)
11271     fail("Parsing worked despite failing reallocations");
11272   else if (i == max_realloc_count)
11273     fail("Parsing failed even at max reallocation count");
11274 }
11275 END_TEST
11276 
11277 /* Test that when a namespace is passed through the context mechanism
11278  * to an external entity parser, the parsers handle reallocation
11279  * failures correctly.  The prefix is exactly the right length to
11280  * provoke particular uncommon code paths.
11281  */
11282 START_TEST(test_nsalloc_realloc_long_context_in_dtd) {
11283   const char *text1
11284       = "<!DOCTYPE "
11285         /* 64 characters per line */
11286         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11287         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11288         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11289         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11290         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11291         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11292         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11293         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11294         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11295         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11296         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11297         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11298         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11299         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11300         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11301         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11302         ":doc [\n"
11303         "  <!ENTITY First SYSTEM 'foo/First'>\n"
11304         "]>\n"
11305         "<"
11306         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11307         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11308         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11309         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11310         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11311         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11312         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11313         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11314         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11315         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11316         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11317         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11318         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11319         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11320         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11321         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11322         ":doc xmlns:"
11323         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11324         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11325         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11326         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11327         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11328         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11329         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11330         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11331         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11332         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11333         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11334         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11335         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11336         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11337         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11338         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11339         "='foo/Second'>&First;";
11340   const char *text2
11341       = "</"
11342         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11343         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11344         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11345         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11346         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11347         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11348         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11349         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11350         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11351         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11352         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11353         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11354         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11355         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11356         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11357         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11358         ":doc>";
11359   ExtOption options[] = {{XCS("foo/First"), "Hello world"}, {NULL, NULL}};
11360   int i;
11361   const int max_realloc_count = 20;
11362 
11363   for (i = 0; i < max_realloc_count; i++) {
11364     reallocation_count = i;
11365     XML_SetUserData(g_parser, options);
11366     XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
11367     XML_SetExternalEntityRefHandler(g_parser, external_entity_optioner);
11368     if (_XML_Parse_SINGLE_BYTES(g_parser, text1, (int)strlen(text1), XML_FALSE)
11369             != XML_STATUS_ERROR
11370         && _XML_Parse_SINGLE_BYTES(g_parser, text2, (int)strlen(text2),
11371                                    XML_TRUE)
11372                != XML_STATUS_ERROR)
11373       break;
11374     /* See comment in test_nsalloc_xmlns() */
11375     nsalloc_teardown();
11376     nsalloc_setup();
11377   }
11378   if (i == 0)
11379     fail("Parsing worked despite failing reallocations");
11380   else if (i == max_realloc_count)
11381     fail("Parsing failed even at max reallocation count");
11382 }
11383 END_TEST
11384 
11385 START_TEST(test_nsalloc_long_default_in_ext) {
11386   const char *text
11387       = "<!DOCTYPE doc [\n"
11388         "  <!ATTLIST e a1 CDATA '"
11389         /* 64 characters per line */
11390         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11391         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11392         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11393         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11394         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11395         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11396         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11397         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11398         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11399         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11400         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11401         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11402         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11403         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11404         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11405         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11406         "'>\n"
11407         "  <!ENTITY x SYSTEM 'foo'>\n"
11408         "]>\n"
11409         "<doc>&x;</doc>";
11410   ExtOption options[] = {{XCS("foo"), "<e/>"}, {NULL, NULL}};
11411   int i;
11412   const int max_alloc_count = 50;
11413 
11414   for (i = 0; i < max_alloc_count; i++) {
11415     allocation_count = i;
11416     XML_SetUserData(g_parser, options);
11417     XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
11418     XML_SetExternalEntityRefHandler(g_parser, external_entity_optioner);
11419     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
11420         != XML_STATUS_ERROR)
11421       break;
11422 
11423     /* See comment in test_nsalloc_xmlns() */
11424     nsalloc_teardown();
11425     nsalloc_setup();
11426   }
11427   if (i == 0)
11428     fail("Parsing worked despite failing allocations");
11429   else if (i == max_alloc_count)
11430     fail("Parsing failed even at max allocation count");
11431 }
11432 END_TEST
11433 
11434 START_TEST(test_nsalloc_long_systemid_in_ext) {
11435   const char *text
11436       = "<!DOCTYPE doc SYSTEM 'foo' [\n"
11437         "  <!ENTITY en SYSTEM '"
11438         /* 64 characters per line */
11439         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11440         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11441         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11442         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11443         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11444         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11445         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11446         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11447         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11448         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11449         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11450         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11451         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11452         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11453         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11454         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11455         "'>\n"
11456         "]>\n"
11457         "<doc>&en;</doc>";
11458   ExtOption options[] = {
11459       {XCS("foo"), "<!ELEMENT e EMPTY>"},
11460       {/* clang-format off */
11461             XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/")
11462             XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/")
11463             XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/")
11464             XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/")
11465             XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/")
11466             XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/")
11467             XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/")
11468             XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/")
11469             XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/")
11470             XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/")
11471             XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/")
11472             XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/")
11473             XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/")
11474             XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/")
11475             XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/")
11476             XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"),
11477        /* clang-format on */
11478        "<e/>"},
11479       {NULL, NULL}};
11480   int i;
11481   const int max_alloc_count = 55;
11482 
11483   for (i = 0; i < max_alloc_count; i++) {
11484     allocation_count = i;
11485     XML_SetUserData(g_parser, options);
11486     XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
11487     XML_SetExternalEntityRefHandler(g_parser, external_entity_optioner);
11488     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
11489         != XML_STATUS_ERROR)
11490       break;
11491 
11492     /* See comment in test_nsalloc_xmlns() */
11493     nsalloc_teardown();
11494     nsalloc_setup();
11495   }
11496   if (i == 0)
11497     fail("Parsing worked despite failing allocations");
11498   else if (i == max_alloc_count)
11499     fail("Parsing failed even at max allocation count");
11500 }
11501 END_TEST
11502 
11503 /* Test the effects of allocation failure on parsing an element in a
11504  * namespace.  Based on test_nsalloc_long_context.
11505  */
11506 START_TEST(test_nsalloc_prefixed_element) {
11507   const char *text = "<!DOCTYPE pfx:element SYSTEM 'foo' [\n"
11508                      "  <!ATTLIST pfx:element baz ID #REQUIRED>\n"
11509                      "  <!ENTITY en SYSTEM 'bar'>\n"
11510                      "]>\n"
11511                      "<pfx:element xmlns:pfx='http://example.org/' baz='2'>\n"
11512                      "&en;"
11513                      "</pfx:element>";
11514   ExtOption options[] = {
11515       {XCS("foo"), "<!ELEMENT e EMPTY>"}, {XCS("bar"), "<e/>"}, {NULL, NULL}};
11516   int i;
11517   const int max_alloc_count = 70;
11518 
11519   for (i = 0; i < max_alloc_count; i++) {
11520     allocation_count = i;
11521     XML_SetUserData(g_parser, options);
11522     XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
11523     XML_SetExternalEntityRefHandler(g_parser, external_entity_optioner);
11524     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
11525         != XML_STATUS_ERROR)
11526       break;
11527 
11528     /* See comment in test_nsalloc_xmlns() */
11529     nsalloc_teardown();
11530     nsalloc_setup();
11531   }
11532   if (i == 0)
11533     fail("Success despite failing allocator");
11534   else if (i == max_alloc_count)
11535     fail("Failed even at full allocation count");
11536 }
11537 END_TEST
11538 
11539 #if defined(XML_DTD)
11540 typedef enum XML_Status (*XmlParseFunction)(XML_Parser, const char *, int, int);
11541 
11542 struct AccountingTestCase {
11543   const char *primaryText;
11544   const char *firstExternalText;  /* often NULL */
11545   const char *secondExternalText; /* often NULL */
11546   const unsigned long long expectedCountBytesIndirectExtra;
11547   XML_Bool singleBytesWanted;
11548 };
11549 
11550 static int
11551 accounting_external_entity_ref_handler(XML_Parser parser,
11552                                        const XML_Char *context,
11553                                        const XML_Char *base,
11554                                        const XML_Char *systemId,
11555                                        const XML_Char *publicId) {
11556   UNUSED_P(context);
11557   UNUSED_P(base);
11558   UNUSED_P(publicId);
11559 
11560   const struct AccountingTestCase *const testCase
11561       = (const struct AccountingTestCase *)XML_GetUserData(parser);
11562 
11563   const char *externalText = NULL;
11564   if (xcstrcmp(systemId, XCS("first.ent")) == 0) {
11565     externalText = testCase->firstExternalText;
11566   } else if (xcstrcmp(systemId, XCS("second.ent")) == 0) {
11567     externalText = testCase->secondExternalText;
11568   } else {
11569     assert(! "systemId is neither \"first.ent\" nor \"second.ent\"");
11570   }
11571   assert(externalText);
11572 
11573   XML_Parser entParser = XML_ExternalEntityParserCreate(parser, context, 0);
11574   assert(entParser);
11575 
11576   const XmlParseFunction xmlParseFunction
11577       = testCase->singleBytesWanted ? _XML_Parse_SINGLE_BYTES : XML_Parse;
11578 
11579   const enum XML_Status status = xmlParseFunction(
11580       entParser, externalText, (int)strlen(externalText), XML_TRUE);
11581 
11582   XML_ParserFree(entParser);
11583   return status;
11584 }
11585 
11586 START_TEST(test_accounting_precision) {
11587   const XML_Bool filled_later = XML_TRUE; /* value is arbitrary */
11588   struct AccountingTestCase cases[] = {
11589       {"<e/>", NULL, NULL, 0, 0},
11590       {"<e></e>", NULL, NULL, 0, 0},
11591 
11592       /* Attributes */
11593       {"<e k1=\"v2\" k2=\"v2\"/>", NULL, NULL, 0, filled_later},
11594       {"<e k1=\"v2\" k2=\"v2\"></e>", NULL, NULL, 0, 0},
11595       {"<p:e xmlns:p=\"https://domain.invalid/\" />", NULL, NULL, 0,
11596        filled_later},
11597       {"<e k=\"&amp;&apos;&gt;&lt;&quot;\" />", NULL, NULL,
11598        sizeof(XML_Char) * 5 /* number of predefined entities */, filled_later},
11599       {"<e1 xmlns='https://example.org/'>\n"
11600        "  <e2 xmlns=''/>\n"
11601        "</e1>",
11602        NULL, NULL, 0, filled_later},
11603 
11604       /* Text */
11605       {"<e>text</e>", NULL, NULL, 0, filled_later},
11606       {"<e1><e2>text1<e3/>text2</e2></e1>", NULL, NULL, 0, filled_later},
11607       {"<e>&amp;&apos;&gt;&lt;&quot;</e>", NULL, NULL,
11608        sizeof(XML_Char) * 5 /* number of predefined entities */, filled_later},
11609       {"<e>&#65;&#41;</e>", NULL, NULL, 0, filled_later},
11610 
11611       /* Prolog */
11612       {"<?xml version=\"1.0\"?><root/>", NULL, NULL, 0, filled_later},
11613 
11614       /* Whitespace */
11615       {"  <e1>  <e2>  </e2>  </e1>  ", NULL, NULL, 0, filled_later},
11616       {"<e1  ><e2  /></e1  >", NULL, NULL, 0, filled_later},
11617       {"<e1><e2 k = \"v\"/><e3 k = 'v'/></e1>", NULL, NULL, 0, filled_later},
11618 
11619       /* Comments */
11620       {"<!-- Comment --><e><!-- Comment --></e>", NULL, NULL, 0, filled_later},
11621 
11622       /* Processing instructions */
11623       {"<?xml-stylesheet type=\"text/xsl\" href=\"https://domain.invalid/\" media=\"all\"?><e/>",
11624        NULL, NULL, 0, filled_later},
11625       {"<?pi0?><?pi1 ?><?pi2  ?><!DOCTYPE r SYSTEM 'first.ent'><r/>",
11626        "<?pi3?><!ENTITY % e1 SYSTEM 'second.ent'><?pi4?>%e1;<?pi5?>", "<?pi6?>",
11627        0, filled_later},
11628 
11629       /* CDATA */
11630       {"<e><![CDATA[one two three]]></e>", NULL, NULL, 0, filled_later},
11631       /* The following is the essence of this OSS-Fuzz finding:
11632          https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=34302
11633          https://oss-fuzz.com/testcase-detail/4860575394955264
11634       */
11635       {"<!DOCTYPE r [\n"
11636        "<!ENTITY e \"111<![CDATA[2 <= 2]]>333\">\n"
11637        "]>\n"
11638        "<r>&e;</r>\n",
11639        NULL, NULL, sizeof(XML_Char) * strlen("111<![CDATA[2 <= 2]]>333"),
11640        filled_later},
11641 
11642       /* Conditional sections */
11643       {"<!DOCTYPE r [\n"
11644        "<!ENTITY % draft 'INCLUDE'>\n"
11645        "<!ENTITY % final 'IGNORE'>\n"
11646        "<!ENTITY % import SYSTEM \"first.ent\">\n"
11647        "%import;\n"
11648        "]>\n"
11649        "<r/>\n",
11650        "<![%draft;[<!--1-->]]>\n"
11651        "<![%final;[<!--22-->]]>",
11652        NULL, sizeof(XML_Char) * (strlen("INCLUDE") + strlen("IGNORE")),
11653        filled_later},
11654 
11655       /* General entities */
11656       {"<!DOCTYPE root [\n"
11657        "<!ENTITY nine \"123456789\">\n"
11658        "]>\n"
11659        "<root>&nine;</root>",
11660        NULL, NULL, sizeof(XML_Char) * strlen("123456789"), filled_later},
11661       {"<!DOCTYPE root [\n"
11662        "<!ENTITY nine \"123456789\">\n"
11663        "]>\n"
11664        "<root k1=\"&nine;\"/>",
11665        NULL, NULL, sizeof(XML_Char) * strlen("123456789"), filled_later},
11666       {"<!DOCTYPE root [\n"
11667        "<!ENTITY nine \"123456789\">\n"
11668        "<!ENTITY nine2 \"&nine;&nine;\">\n"
11669        "]>\n"
11670        "<root>&nine2;&nine2;&nine2;</root>",
11671        NULL, NULL,
11672        sizeof(XML_Char) * 3 /* calls to &nine2; */ * 2 /* calls to &nine; */
11673            * (strlen("&nine;") + strlen("123456789")),
11674        filled_later},
11675       {"<!DOCTYPE r [\n"
11676        "  <!ENTITY five SYSTEM 'first.ent'>\n"
11677        "]>\n"
11678        "<r>&five;</r>",
11679        "12345", NULL, 0, filled_later},
11680 
11681       /* Parameter entities */
11682       {"<!DOCTYPE r [\n"
11683        "<!ENTITY % comment \"<!---->\">\n"
11684        "%comment;\n"
11685        "]>\n"
11686        "<r/>",
11687        NULL, NULL, sizeof(XML_Char) * strlen("<!---->"), filled_later},
11688       {"<!DOCTYPE r [\n"
11689        "<!ENTITY % ninedef \"&#60;!ENTITY nine &#34;123456789&#34;&#62;\">\n"
11690        "%ninedef;\n"
11691        "]>\n"
11692        "<r>&nine;</r>",
11693        NULL, NULL,
11694        sizeof(XML_Char)
11695            * (strlen("<!ENTITY nine \"123456789\">") + strlen("123456789")),
11696        filled_later},
11697       {"<!DOCTYPE r [\n"
11698        "<!ENTITY % comment \"<!--1-->\">\n"
11699        "<!ENTITY % comment2 \"&#37;comment;<!--22-->&#37;comment;\">\n"
11700        "%comment2;\n"
11701        "]>\n"
11702        "<r/>\n",
11703        NULL, NULL,
11704        sizeof(XML_Char)
11705            * (strlen("%comment;<!--22-->%comment;") + 2 * strlen("<!--1-->")),
11706        filled_later},
11707       {"<!DOCTYPE r [\n"
11708        "  <!ENTITY % five \"12345\">\n"
11709        "  <!ENTITY % five2def \"&#60;!ENTITY five2 &#34;[&#37;five;][&#37;five;]]]]&#34;&#62;\">\n"
11710        "  %five2def;\n"
11711        "]>\n"
11712        "<r>&five2;</r>",
11713        NULL, NULL, /* from "%five2def;": */
11714        sizeof(XML_Char)
11715            * (strlen("<!ENTITY five2 \"[%five;][%five;]]]]\">")
11716               + 2 /* calls to "%five;" */ * strlen("12345")
11717               + /* from "&five2;": */ strlen("[12345][12345]]]]")),
11718        filled_later},
11719       {"<!DOCTYPE r SYSTEM \"first.ent\">\n"
11720        "<r/>",
11721        "<!ENTITY % comment '<!--1-->'>\n"
11722        "<!ENTITY % comment2 '<!--22-->%comment;<!--22-->%comment;<!--22-->'>\n"
11723        "%comment2;",
11724        NULL,
11725        sizeof(XML_Char)
11726            * (strlen("<!--22-->%comment;<!--22-->%comment;<!--22-->")
11727               + 2 /* calls to "%comment;" */ * strlen("<!---->")),
11728        filled_later},
11729       {"<!DOCTYPE r SYSTEM 'first.ent'>\n"
11730        "<r/>",
11731        "<!ENTITY % e1 PUBLIC 'foo' 'second.ent'>\n"
11732        "<!ENTITY % e2 '<!--22-->%e1;<!--22-->'>\n"
11733        "%e2;\n",
11734        "<!--1-->", sizeof(XML_Char) * strlen("<!--22--><!--1--><!--22-->"),
11735        filled_later},
11736       {
11737           "<!DOCTYPE r SYSTEM 'first.ent'>\n"
11738           "<r/>",
11739           "<!ENTITY % e1 SYSTEM 'second.ent'>\n"
11740           "<!ENTITY % e2 '%e1;'>",
11741           "<?xml version='1.0' encoding='utf-8'?>\n"
11742           "hello\n"
11743           "xml" /* without trailing newline! */,
11744           0,
11745           filled_later,
11746       },
11747       {
11748           "<!DOCTYPE r SYSTEM 'first.ent'>\n"
11749           "<r/>",
11750           "<!ENTITY % e1 SYSTEM 'second.ent'>\n"
11751           "<!ENTITY % e2 '%e1;'>",
11752           "<?xml version='1.0' encoding='utf-8'?>\n"
11753           "hello\n"
11754           "xml\n" /* with trailing newline! */,
11755           0,
11756           filled_later,
11757       },
11758       {"<!DOCTYPE doc SYSTEM 'first.ent'>\n"
11759        "<doc></doc>\n",
11760        "<!ELEMENT doc EMPTY>\n"
11761        "<!ENTITY % e1 SYSTEM 'second.ent'>\n"
11762        "<!ENTITY % e2 '%e1;'>\n"
11763        "%e1;\n",
11764        "\xEF\xBB\xBF<!ATTLIST doc a1 CDATA 'value'>" /* UTF-8 BOM */,
11765        strlen("\xEF\xBB\xBF<!ATTLIST doc a1 CDATA 'value'>"), filled_later},
11766       {"<!DOCTYPE r [\n"
11767        "  <!ENTITY five SYSTEM 'first.ent'>\n"
11768        "]>\n"
11769        "<r>&five;</r>",
11770        "\xEF\xBB\xBF" /* UTF-8 BOM */, NULL, 0, filled_later},
11771   };
11772 
11773   const size_t countCases = sizeof(cases) / sizeof(cases[0]);
11774   size_t u = 0;
11775   for (; u < countCases; u++) {
11776     size_t v = 0;
11777     for (; v < 2; v++) {
11778       const XML_Bool singleBytesWanted = (v == 0) ? XML_FALSE : XML_TRUE;
11779       const unsigned long long expectedCountBytesDirect
11780           = strlen(cases[u].primaryText);
11781       const unsigned long long expectedCountBytesIndirect
11782           = (cases[u].firstExternalText ? strlen(cases[u].firstExternalText)
11783                                         : 0)
11784             + (cases[u].secondExternalText ? strlen(cases[u].secondExternalText)
11785                                            : 0)
11786             + cases[u].expectedCountBytesIndirectExtra;
11787 
11788       XML_Parser parser = XML_ParserCreate(NULL);
11789       XML_SetParamEntityParsing(parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
11790       if (cases[u].firstExternalText) {
11791         XML_SetExternalEntityRefHandler(parser,
11792                                         accounting_external_entity_ref_handler);
11793         XML_SetUserData(parser, (void *)&cases[u]);
11794         cases[u].singleBytesWanted = singleBytesWanted;
11795       }
11796 
11797       const XmlParseFunction xmlParseFunction
11798           = singleBytesWanted ? _XML_Parse_SINGLE_BYTES : XML_Parse;
11799 
11800       enum XML_Status status
11801           = xmlParseFunction(parser, cases[u].primaryText,
11802                              (int)strlen(cases[u].primaryText), XML_TRUE);
11803       if (status != XML_STATUS_OK) {
11804         _xml_failure(parser, __FILE__, __LINE__);
11805       }
11806 
11807       const unsigned long long actualCountBytesDirect
11808           = testingAccountingGetCountBytesDirect(parser);
11809       const unsigned long long actualCountBytesIndirect
11810           = testingAccountingGetCountBytesIndirect(parser);
11811 
11812       XML_ParserFree(parser);
11813 
11814       if (actualCountBytesDirect != expectedCountBytesDirect) {
11815         fprintf(
11816             stderr,
11817             "Document " EXPAT_FMT_SIZE_T("") " of " EXPAT_FMT_SIZE_T("") ", %s: Expected " EXPAT_FMT_ULL(
11818                 "") " count direct bytes, got " EXPAT_FMT_ULL("") " instead.\n",
11819             u + 1, countCases, singleBytesWanted ? "single bytes" : "chunks",
11820             expectedCountBytesDirect, actualCountBytesDirect);
11821         fail("Count of direct bytes is off");
11822       }
11823 
11824       if (actualCountBytesIndirect != expectedCountBytesIndirect) {
11825         fprintf(
11826             stderr,
11827             "Document " EXPAT_FMT_SIZE_T("") " of " EXPAT_FMT_SIZE_T("") ", %s: Expected " EXPAT_FMT_ULL(
11828                 "") " count indirect bytes, got " EXPAT_FMT_ULL("") " instead.\n",
11829             u + 1, countCases, singleBytesWanted ? "single bytes" : "chunks",
11830             expectedCountBytesIndirect, actualCountBytesIndirect);
11831         fail("Count of indirect bytes is off");
11832       }
11833     }
11834   }
11835 }
11836 END_TEST
11837 
11838 static float
11839 portableNAN(void) {
11840   return strtof("nan", NULL);
11841 }
11842 
11843 static float
11844 portableINFINITY(void) {
11845   return strtof("infinity", NULL);
11846 }
11847 
11848 START_TEST(test_billion_laughs_attack_protection_api) {
11849   XML_Parser parserWithoutParent = XML_ParserCreate(NULL);
11850   XML_Parser parserWithParent
11851       = XML_ExternalEntityParserCreate(parserWithoutParent, NULL, NULL);
11852   if (parserWithoutParent == NULL)
11853     fail("parserWithoutParent is NULL");
11854   if (parserWithParent == NULL)
11855     fail("parserWithParent is NULL");
11856 
11857   // XML_SetBillionLaughsAttackProtectionMaximumAmplification, error cases
11858   if (XML_SetBillionLaughsAttackProtectionMaximumAmplification(NULL, 123.0f)
11859       == XML_TRUE)
11860     fail("Call with NULL parser is NOT supposed to succeed");
11861   if (XML_SetBillionLaughsAttackProtectionMaximumAmplification(parserWithParent,
11862                                                                123.0f)
11863       == XML_TRUE)
11864     fail("Call with non-root parser is NOT supposed to succeed");
11865   if (XML_SetBillionLaughsAttackProtectionMaximumAmplification(
11866           parserWithoutParent, portableNAN())
11867       == XML_TRUE)
11868     fail("Call with NaN limit is NOT supposed to succeed");
11869   if (XML_SetBillionLaughsAttackProtectionMaximumAmplification(
11870           parserWithoutParent, -1.0f)
11871       == XML_TRUE)
11872     fail("Call with negative limit is NOT supposed to succeed");
11873   if (XML_SetBillionLaughsAttackProtectionMaximumAmplification(
11874           parserWithoutParent, 0.9f)
11875       == XML_TRUE)
11876     fail("Call with positive limit <1.0 is NOT supposed to succeed");
11877 
11878   // XML_SetBillionLaughsAttackProtectionMaximumAmplification, success cases
11879   if (XML_SetBillionLaughsAttackProtectionMaximumAmplification(
11880           parserWithoutParent, 1.0f)
11881       == XML_FALSE)
11882     fail("Call with positive limit >=1.0 is supposed to succeed");
11883   if (XML_SetBillionLaughsAttackProtectionMaximumAmplification(
11884           parserWithoutParent, 123456.789f)
11885       == XML_FALSE)
11886     fail("Call with positive limit >=1.0 is supposed to succeed");
11887   if (XML_SetBillionLaughsAttackProtectionMaximumAmplification(
11888           parserWithoutParent, portableINFINITY())
11889       == XML_FALSE)
11890     fail("Call with positive limit >=1.0 is supposed to succeed");
11891 
11892   // XML_SetBillionLaughsAttackProtectionActivationThreshold, error cases
11893   if (XML_SetBillionLaughsAttackProtectionActivationThreshold(NULL, 123)
11894       == XML_TRUE)
11895     fail("Call with NULL parser is NOT supposed to succeed");
11896   if (XML_SetBillionLaughsAttackProtectionActivationThreshold(parserWithParent,
11897                                                               123)
11898       == XML_TRUE)
11899     fail("Call with non-root parser is NOT supposed to succeed");
11900 
11901   // XML_SetBillionLaughsAttackProtectionActivationThreshold, success cases
11902   if (XML_SetBillionLaughsAttackProtectionActivationThreshold(
11903           parserWithoutParent, 123)
11904       == XML_FALSE)
11905     fail("Call with non-NULL parentless parser is supposed to succeed");
11906 
11907   XML_ParserFree(parserWithParent);
11908   XML_ParserFree(parserWithoutParent);
11909 }
11910 END_TEST
11911 
11912 START_TEST(test_helper_unsigned_char_to_printable) {
11913   // Smoke test
11914   unsigned char uc = 0;
11915   for (; uc < (unsigned char)-1; uc++) {
11916     const char *const printable = unsignedCharToPrintable(uc);
11917     if (printable == NULL)
11918       fail("unsignedCharToPrintable returned NULL");
11919     if (strlen(printable) < (size_t)1)
11920       fail("unsignedCharToPrintable returned empty string");
11921   }
11922 
11923   // Two concrete samples
11924   if (strcmp(unsignedCharToPrintable('A'), "A") != 0)
11925     fail("unsignedCharToPrintable result mistaken");
11926   if (strcmp(unsignedCharToPrintable('\\'), "\\\\") != 0)
11927     fail("unsignedCharToPrintable result mistaken");
11928 }
11929 END_TEST
11930 #endif // defined(XML_DTD)
11931 
11932 static Suite *
11933 make_suite(void) {
11934   Suite *s = suite_create("basic");
11935   TCase *tc_basic = tcase_create("basic tests");
11936   TCase *tc_namespace = tcase_create("XML namespaces");
11937   TCase *tc_misc = tcase_create("miscellaneous tests");
11938   TCase *tc_alloc = tcase_create("allocation tests");
11939   TCase *tc_nsalloc = tcase_create("namespace allocation tests");
11940 #if defined(XML_DTD)
11941   TCase *tc_accounting = tcase_create("accounting tests");
11942 #endif
11943 
11944   suite_add_tcase(s, tc_basic);
11945   tcase_add_checked_fixture(tc_basic, basic_setup, basic_teardown);
11946   tcase_add_test(tc_basic, test_nul_byte);
11947   tcase_add_test(tc_basic, test_u0000_char);
11948   tcase_add_test(tc_basic, test_siphash_self);
11949   tcase_add_test(tc_basic, test_siphash_spec);
11950   tcase_add_test(tc_basic, test_bom_utf8);
11951   tcase_add_test(tc_basic, test_bom_utf16_be);
11952   tcase_add_test(tc_basic, test_bom_utf16_le);
11953   tcase_add_test(tc_basic, test_nobom_utf16_le);
11954   tcase_add_test(tc_basic, test_illegal_utf8);
11955   tcase_add_test(tc_basic, test_utf8_auto_align);
11956   tcase_add_test(tc_basic, test_utf16);
11957   tcase_add_test(tc_basic, test_utf16_le_epilog_newline);
11958   tcase_add_test(tc_basic, test_not_utf16);
11959   tcase_add_test(tc_basic, test_bad_encoding);
11960   tcase_add_test(tc_basic, test_latin1_umlauts);
11961   tcase_add_test(tc_basic, test_long_utf8_character);
11962   tcase_add_test(tc_basic, test_long_latin1_attribute);
11963   tcase_add_test(tc_basic, test_long_ascii_attribute);
11964   /* Regression test for SF bug #491986. */
11965   tcase_add_test(tc_basic, test_danish_latin1);
11966   /* Regression test for SF bug #514281. */
11967   tcase_add_test(tc_basic, test_french_charref_hexidecimal);
11968   tcase_add_test(tc_basic, test_french_charref_decimal);
11969   tcase_add_test(tc_basic, test_french_latin1);
11970   tcase_add_test(tc_basic, test_french_utf8);
11971   tcase_add_test(tc_basic, test_utf8_false_rejection);
11972   tcase_add_test(tc_basic, test_line_number_after_parse);
11973   tcase_add_test(tc_basic, test_column_number_after_parse);
11974   tcase_add_test(tc_basic, test_line_and_column_numbers_inside_handlers);
11975   tcase_add_test(tc_basic, test_line_number_after_error);
11976   tcase_add_test(tc_basic, test_column_number_after_error);
11977   tcase_add_test(tc_basic, test_really_long_lines);
11978   tcase_add_test(tc_basic, test_really_long_encoded_lines);
11979   tcase_add_test(tc_basic, test_end_element_events);
11980   tcase_add_test(tc_basic, test_attr_whitespace_normalization);
11981   tcase_add_test(tc_basic, test_xmldecl_misplaced);
11982   tcase_add_test(tc_basic, test_xmldecl_invalid);
11983   tcase_add_test(tc_basic, test_xmldecl_missing_attr);
11984   tcase_add_test(tc_basic, test_xmldecl_missing_value);
11985   tcase_add_test(tc_basic, test_unknown_encoding_internal_entity);
11986   tcase_add_test(tc_basic, test_unrecognised_encoding_internal_entity);
11987   tcase_add_test(tc_basic, test_wfc_undeclared_entity_unread_external_subset);
11988   tcase_add_test(tc_basic, test_wfc_undeclared_entity_no_external_subset);
11989   tcase_add_test(tc_basic, test_wfc_undeclared_entity_standalone);
11990   tcase_add_test(tc_basic, test_wfc_undeclared_entity_with_external_subset);
11991   tcase_add_test(tc_basic, test_not_standalone_handler_reject);
11992   tcase_add_test(tc_basic, test_not_standalone_handler_accept);
11993   tcase_add_test(tc_basic,
11994                  test_wfc_undeclared_entity_with_external_subset_standalone);
11995   tcase_add_test(tc_basic, test_entity_with_external_subset_unless_standalone);
11996   tcase_add_test(tc_basic, test_wfc_no_recursive_entity_refs);
11997   tcase_add_test__ifdef_xml_dtd(tc_basic, test_ext_entity_set_encoding);
11998   tcase_add_test__ifdef_xml_dtd(tc_basic, test_ext_entity_no_handler);
11999   tcase_add_test__ifdef_xml_dtd(tc_basic, test_ext_entity_set_bom);
12000   tcase_add_test__ifdef_xml_dtd(tc_basic, test_ext_entity_bad_encoding);
12001   tcase_add_test__ifdef_xml_dtd(tc_basic, test_ext_entity_bad_encoding_2);
12002   tcase_add_test__ifdef_xml_dtd(tc_basic, test_ext_entity_invalid_parse);
12003   tcase_add_test__ifdef_xml_dtd(tc_basic,
12004                                 test_ext_entity_invalid_suspended_parse);
12005   tcase_add_test(tc_basic, test_dtd_default_handling);
12006   tcase_add_test(tc_basic, test_dtd_attr_handling);
12007   tcase_add_test(tc_basic, test_empty_ns_without_namespaces);
12008   tcase_add_test(tc_basic, test_ns_in_attribute_default_without_namespaces);
12009   tcase_add_test(tc_basic, test_stop_parser_between_char_data_calls);
12010   tcase_add_test(tc_basic, test_suspend_parser_between_char_data_calls);
12011   tcase_add_test(tc_basic, test_repeated_stop_parser_between_char_data_calls);
12012   tcase_add_test(tc_basic, test_good_cdata_ascii);
12013   tcase_add_test(tc_basic, test_good_cdata_utf16);
12014   tcase_add_test(tc_basic, test_good_cdata_utf16_le);
12015   tcase_add_test(tc_basic, test_long_cdata_utf16);
12016   tcase_add_test(tc_basic, test_multichar_cdata_utf16);
12017   tcase_add_test(tc_basic, test_utf16_bad_surrogate_pair);
12018   tcase_add_test(tc_basic, test_bad_cdata);
12019   tcase_add_test(tc_basic, test_bad_cdata_utf16);
12020   tcase_add_test(tc_basic, test_stop_parser_between_cdata_calls);
12021   tcase_add_test(tc_basic, test_suspend_parser_between_cdata_calls);
12022   tcase_add_test(tc_basic, test_memory_allocation);
12023   tcase_add_test(tc_basic, test_default_current);
12024   tcase_add_test(tc_basic, test_dtd_elements);
12025   tcase_add_test(tc_basic, test_dtd_elements_nesting);
12026   tcase_add_test__ifdef_xml_dtd(tc_basic, test_set_foreign_dtd);
12027   tcase_add_test__ifdef_xml_dtd(tc_basic, test_foreign_dtd_not_standalone);
12028   tcase_add_test__ifdef_xml_dtd(tc_basic, test_invalid_foreign_dtd);
12029   tcase_add_test__ifdef_xml_dtd(tc_basic, test_foreign_dtd_with_doctype);
12030   tcase_add_test__ifdef_xml_dtd(tc_basic,
12031                                 test_foreign_dtd_without_external_subset);
12032   tcase_add_test__ifdef_xml_dtd(tc_basic, test_empty_foreign_dtd);
12033   tcase_add_test(tc_basic, test_set_base);
12034   tcase_add_test(tc_basic, test_attributes);
12035   tcase_add_test(tc_basic, test_reset_in_entity);
12036   tcase_add_test(tc_basic, test_resume_invalid_parse);
12037   tcase_add_test(tc_basic, test_resume_resuspended);
12038   tcase_add_test(tc_basic, test_cdata_default);
12039   tcase_add_test(tc_basic, test_subordinate_reset);
12040   tcase_add_test(tc_basic, test_subordinate_suspend);
12041   tcase_add_test(tc_basic, test_subordinate_xdecl_suspend);
12042   tcase_add_test(tc_basic, test_subordinate_xdecl_abort);
12043   tcase_add_test(tc_basic, test_explicit_encoding);
12044   tcase_add_test(tc_basic, test_trailing_cr);
12045   tcase_add_test(tc_basic, test_ext_entity_trailing_cr);
12046   tcase_add_test(tc_basic, test_trailing_rsqb);
12047   tcase_add_test(tc_basic, test_ext_entity_trailing_rsqb);
12048   tcase_add_test(tc_basic, test_ext_entity_good_cdata);
12049   tcase_add_test__ifdef_xml_dtd(tc_basic, test_user_parameters);
12050   tcase_add_test__ifdef_xml_dtd(tc_basic, test_ext_entity_ref_parameter);
12051   tcase_add_test(tc_basic, test_empty_parse);
12052   tcase_add_test(tc_basic, test_get_buffer_1);
12053   tcase_add_test(tc_basic, test_get_buffer_2);
12054 #if defined(XML_CONTEXT_BYTES)
12055   tcase_add_test(tc_basic, test_get_buffer_3_overflow);
12056 #endif
12057   tcase_add_test(tc_basic, test_byte_info_at_end);
12058   tcase_add_test(tc_basic, test_byte_info_at_error);
12059   tcase_add_test(tc_basic, test_byte_info_at_cdata);
12060   tcase_add_test(tc_basic, test_predefined_entities);
12061   tcase_add_test__ifdef_xml_dtd(tc_basic, test_invalid_tag_in_dtd);
12062   tcase_add_test(tc_basic, test_not_predefined_entities);
12063   tcase_add_test__ifdef_xml_dtd(tc_basic, test_ignore_section);
12064   tcase_add_test__ifdef_xml_dtd(tc_basic, test_ignore_section_utf16);
12065   tcase_add_test__ifdef_xml_dtd(tc_basic, test_ignore_section_utf16_be);
12066   tcase_add_test__ifdef_xml_dtd(tc_basic, test_bad_ignore_section);
12067   tcase_add_test__ifdef_xml_dtd(tc_basic, test_external_entity_values);
12068   tcase_add_test__ifdef_xml_dtd(tc_basic, test_ext_entity_not_standalone);
12069   tcase_add_test__ifdef_xml_dtd(tc_basic, test_ext_entity_value_abort);
12070   tcase_add_test(tc_basic, test_bad_public_doctype);
12071   tcase_add_test(tc_basic, test_attribute_enum_value);
12072   tcase_add_test(tc_basic, test_predefined_entity_redefinition);
12073   tcase_add_test__ifdef_xml_dtd(tc_basic, test_dtd_stop_processing);
12074   tcase_add_test(tc_basic, test_public_notation_no_sysid);
12075   tcase_add_test(tc_basic, test_nested_groups);
12076   tcase_add_test(tc_basic, test_group_choice);
12077   tcase_add_test(tc_basic, test_standalone_parameter_entity);
12078   tcase_add_test__ifdef_xml_dtd(tc_basic, test_skipped_parameter_entity);
12079   tcase_add_test__ifdef_xml_dtd(tc_basic,
12080                                 test_recursive_external_parameter_entity);
12081   tcase_add_test(tc_basic, test_undefined_ext_entity_in_external_dtd);
12082   tcase_add_test(tc_basic, test_suspend_xdecl);
12083   tcase_add_test(tc_basic, test_abort_epilog);
12084   tcase_add_test(tc_basic, test_abort_epilog_2);
12085   tcase_add_test(tc_basic, test_suspend_epilog);
12086   tcase_add_test(tc_basic, test_suspend_in_sole_empty_tag);
12087   tcase_add_test(tc_basic, test_unfinished_epilog);
12088   tcase_add_test(tc_basic, test_partial_char_in_epilog);
12089   tcase_add_test(tc_basic, test_hash_collision);
12090   tcase_add_test__ifdef_xml_dtd(tc_basic, test_suspend_resume_internal_entity);
12091   tcase_add_test__ifdef_xml_dtd(tc_basic,
12092                                 test_suspend_resume_internal_entity_issue_629);
12093   tcase_add_test__ifdef_xml_dtd(tc_basic, test_resume_entity_with_syntax_error);
12094   tcase_add_test__ifdef_xml_dtd(tc_basic, test_suspend_resume_parameter_entity);
12095   tcase_add_test(tc_basic, test_restart_on_error);
12096   tcase_add_test(tc_basic, test_reject_lt_in_attribute_value);
12097   tcase_add_test(tc_basic, test_reject_unfinished_param_in_att_value);
12098   tcase_add_test(tc_basic, test_trailing_cr_in_att_value);
12099   tcase_add_test(tc_basic, test_standalone_internal_entity);
12100   tcase_add_test(tc_basic, test_skipped_external_entity);
12101   tcase_add_test(tc_basic, test_skipped_null_loaded_ext_entity);
12102   tcase_add_test(tc_basic, test_skipped_unloaded_ext_entity);
12103   tcase_add_test__ifdef_xml_dtd(tc_basic, test_param_entity_with_trailing_cr);
12104   tcase_add_test(tc_basic, test_invalid_character_entity);
12105   tcase_add_test(tc_basic, test_invalid_character_entity_2);
12106   tcase_add_test(tc_basic, test_invalid_character_entity_3);
12107   tcase_add_test(tc_basic, test_invalid_character_entity_4);
12108   tcase_add_test(tc_basic, test_pi_handled_in_default);
12109   tcase_add_test(tc_basic, test_comment_handled_in_default);
12110   tcase_add_test(tc_basic, test_pi_yml);
12111   tcase_add_test(tc_basic, test_pi_xnl);
12112   tcase_add_test(tc_basic, test_pi_xmm);
12113   tcase_add_test(tc_basic, test_utf16_pi);
12114   tcase_add_test(tc_basic, test_utf16_be_pi);
12115   tcase_add_test(tc_basic, test_utf16_be_comment);
12116   tcase_add_test(tc_basic, test_utf16_le_comment);
12117   tcase_add_test(tc_basic, test_missing_encoding_conversion_fn);
12118   tcase_add_test(tc_basic, test_failing_encoding_conversion_fn);
12119   tcase_add_test(tc_basic, test_unknown_encoding_success);
12120   tcase_add_test(tc_basic, test_unknown_encoding_bad_name);
12121   tcase_add_test(tc_basic, test_unknown_encoding_bad_name_2);
12122   tcase_add_test(tc_basic, test_unknown_encoding_long_name_1);
12123   tcase_add_test(tc_basic, test_unknown_encoding_long_name_2);
12124   tcase_add_test(tc_basic, test_invalid_unknown_encoding);
12125   tcase_add_test(tc_basic, test_unknown_ascii_encoding_ok);
12126   tcase_add_test(tc_basic, test_unknown_ascii_encoding_fail);
12127   tcase_add_test(tc_basic, test_unknown_encoding_invalid_length);
12128   tcase_add_test(tc_basic, test_unknown_encoding_invalid_topbit);
12129   tcase_add_test(tc_basic, test_unknown_encoding_invalid_surrogate);
12130   tcase_add_test(tc_basic, test_unknown_encoding_invalid_high);
12131   tcase_add_test(tc_basic, test_unknown_encoding_invalid_attr_value);
12132   tcase_add_test(tc_basic, test_ext_entity_latin1_utf16le_bom);
12133   tcase_add_test(tc_basic, test_ext_entity_latin1_utf16be_bom);
12134   tcase_add_test(tc_basic, test_ext_entity_latin1_utf16le_bom2);
12135   tcase_add_test(tc_basic, test_ext_entity_latin1_utf16be_bom2);
12136   tcase_add_test(tc_basic, test_ext_entity_utf16_be);
12137   tcase_add_test(tc_basic, test_ext_entity_utf16_le);
12138   tcase_add_test(tc_basic, test_ext_entity_utf16_unknown);
12139   tcase_add_test(tc_basic, test_ext_entity_utf8_non_bom);
12140   tcase_add_test(tc_basic, test_utf8_in_cdata_section);
12141   tcase_add_test(tc_basic, test_utf8_in_cdata_section_2);
12142   tcase_add_test(tc_basic, test_utf8_in_start_tags);
12143   tcase_add_test(tc_basic, test_trailing_spaces_in_elements);
12144   tcase_add_test(tc_basic, test_utf16_attribute);
12145   tcase_add_test(tc_basic, test_utf16_second_attr);
12146   tcase_add_test(tc_basic, test_attr_after_solidus);
12147   tcase_add_test__ifdef_xml_dtd(tc_basic, test_utf16_pe);
12148   tcase_add_test(tc_basic, test_bad_attr_desc_keyword);
12149   tcase_add_test(tc_basic, test_bad_attr_desc_keyword_utf16);
12150   tcase_add_test(tc_basic, test_bad_doctype);
12151   tcase_add_test(tc_basic, test_bad_doctype_utf8);
12152   tcase_add_test(tc_basic, test_bad_doctype_utf16);
12153   tcase_add_test(tc_basic, test_bad_doctype_plus);
12154   tcase_add_test(tc_basic, test_bad_doctype_star);
12155   tcase_add_test(tc_basic, test_bad_doctype_query);
12156   tcase_add_test__ifdef_xml_dtd(tc_basic, test_unknown_encoding_bad_ignore);
12157   tcase_add_test(tc_basic, test_entity_in_utf16_be_attr);
12158   tcase_add_test(tc_basic, test_entity_in_utf16_le_attr);
12159   tcase_add_test__ifdef_xml_dtd(tc_basic, test_entity_public_utf16_be);
12160   tcase_add_test__ifdef_xml_dtd(tc_basic, test_entity_public_utf16_le);
12161   tcase_add_test(tc_basic, test_short_doctype);
12162   tcase_add_test(tc_basic, test_short_doctype_2);
12163   tcase_add_test(tc_basic, test_short_doctype_3);
12164   tcase_add_test(tc_basic, test_long_doctype);
12165   tcase_add_test(tc_basic, test_bad_entity);
12166   tcase_add_test(tc_basic, test_bad_entity_2);
12167   tcase_add_test(tc_basic, test_bad_entity_3);
12168   tcase_add_test(tc_basic, test_bad_entity_4);
12169   tcase_add_test(tc_basic, test_bad_notation);
12170   tcase_add_test(tc_basic, test_default_doctype_handler);
12171   tcase_add_test(tc_basic, test_empty_element_abort);
12172 
12173   suite_add_tcase(s, tc_namespace);
12174   tcase_add_checked_fixture(tc_namespace, namespace_setup, namespace_teardown);
12175   tcase_add_test(tc_namespace, test_return_ns_triplet);
12176   tcase_add_test(tc_namespace, test_ns_tagname_overwrite);
12177   tcase_add_test(tc_namespace, test_ns_tagname_overwrite_triplet);
12178   tcase_add_test(tc_namespace, test_start_ns_clears_start_element);
12179   tcase_add_test__ifdef_xml_dtd(tc_namespace,
12180                                 test_default_ns_from_ext_subset_and_ext_ge);
12181   tcase_add_test(tc_namespace, test_ns_prefix_with_empty_uri_1);
12182   tcase_add_test(tc_namespace, test_ns_prefix_with_empty_uri_2);
12183   tcase_add_test(tc_namespace, test_ns_prefix_with_empty_uri_3);
12184   tcase_add_test(tc_namespace, test_ns_prefix_with_empty_uri_4);
12185   tcase_add_test(tc_namespace, test_ns_unbound_prefix);
12186   tcase_add_test(tc_namespace, test_ns_default_with_empty_uri);
12187   tcase_add_test(tc_namespace, test_ns_duplicate_attrs_diff_prefixes);
12188   tcase_add_test(tc_namespace, test_ns_duplicate_hashes);
12189   tcase_add_test(tc_namespace, test_ns_unbound_prefix_on_attribute);
12190   tcase_add_test(tc_namespace, test_ns_unbound_prefix_on_element);
12191   tcase_add_test(tc_namespace, test_ns_parser_reset);
12192   tcase_add_test(tc_namespace, test_ns_long_element);
12193   tcase_add_test(tc_namespace, test_ns_mixed_prefix_atts);
12194   tcase_add_test(tc_namespace, test_ns_extend_uri_buffer);
12195   tcase_add_test(tc_namespace, test_ns_reserved_attributes);
12196   tcase_add_test(tc_namespace, test_ns_reserved_attributes_2);
12197   tcase_add_test(tc_namespace, test_ns_extremely_long_prefix);
12198   tcase_add_test(tc_namespace, test_ns_unknown_encoding_success);
12199   tcase_add_test(tc_namespace, test_ns_double_colon);
12200   tcase_add_test(tc_namespace, test_ns_double_colon_element);
12201   tcase_add_test(tc_namespace, test_ns_bad_attr_leafname);
12202   tcase_add_test(tc_namespace, test_ns_bad_element_leafname);
12203   tcase_add_test(tc_namespace, test_ns_utf16_leafname);
12204   tcase_add_test(tc_namespace, test_ns_utf16_element_leafname);
12205   tcase_add_test(tc_namespace, test_ns_utf16_doctype);
12206   tcase_add_test(tc_namespace, test_ns_invalid_doctype);
12207   tcase_add_test(tc_namespace, test_ns_double_colon_doctype);
12208   tcase_add_test(tc_namespace, test_ns_separator_in_uri);
12209 
12210   suite_add_tcase(s, tc_misc);
12211   tcase_add_checked_fixture(tc_misc, NULL, basic_teardown);
12212   tcase_add_test(tc_misc, test_misc_alloc_create_parser);
12213   tcase_add_test(tc_misc, test_misc_alloc_create_parser_with_encoding);
12214   tcase_add_test(tc_misc, test_misc_null_parser);
12215   tcase_add_test(tc_misc, test_misc_error_string);
12216   tcase_add_test(tc_misc, test_misc_version);
12217   tcase_add_test(tc_misc, test_misc_features);
12218   tcase_add_test(tc_misc, test_misc_attribute_leak);
12219   tcase_add_test(tc_misc, test_misc_utf16le);
12220   tcase_add_test(tc_misc, test_misc_stop_during_end_handler_issue_240_1);
12221   tcase_add_test(tc_misc, test_misc_stop_during_end_handler_issue_240_2);
12222   tcase_add_test__ifdef_xml_dtd(
12223       tc_misc, test_misc_deny_internal_entity_closing_doctype_issue_317);
12224 
12225   suite_add_tcase(s, tc_alloc);
12226   tcase_add_checked_fixture(tc_alloc, alloc_setup, alloc_teardown);
12227   tcase_add_test(tc_alloc, test_alloc_parse_xdecl);
12228   tcase_add_test(tc_alloc, test_alloc_parse_xdecl_2);
12229   tcase_add_test(tc_alloc, test_alloc_parse_pi);
12230   tcase_add_test(tc_alloc, test_alloc_parse_pi_2);
12231   tcase_add_test(tc_alloc, test_alloc_parse_pi_3);
12232   tcase_add_test(tc_alloc, test_alloc_parse_comment);
12233   tcase_add_test(tc_alloc, test_alloc_parse_comment_2);
12234   tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_create_external_parser);
12235   tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_run_external_parser);
12236   tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_dtd_copy_default_atts);
12237   tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_external_entity);
12238   tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_ext_entity_set_encoding);
12239   tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_internal_entity);
12240   tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_dtd_default_handling);
12241   tcase_add_test(tc_alloc, test_alloc_explicit_encoding);
12242   tcase_add_test(tc_alloc, test_alloc_set_base);
12243   tcase_add_test(tc_alloc, test_alloc_realloc_buffer);
12244   tcase_add_test(tc_alloc, test_alloc_ext_entity_realloc_buffer);
12245   tcase_add_test(tc_alloc, test_alloc_realloc_many_attributes);
12246   tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_public_entity_value);
12247   tcase_add_test__ifdef_xml_dtd(tc_alloc,
12248                                 test_alloc_realloc_subst_public_entity_value);
12249   tcase_add_test(tc_alloc, test_alloc_parse_public_doctype);
12250   tcase_add_test(tc_alloc, test_alloc_parse_public_doctype_long_name);
12251   tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_set_foreign_dtd);
12252   tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_attribute_enum_value);
12253   tcase_add_test__ifdef_xml_dtd(tc_alloc,
12254                                 test_alloc_realloc_attribute_enum_value);
12255   tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_realloc_implied_attribute);
12256   tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_realloc_default_attribute);
12257   tcase_add_test(tc_alloc, test_alloc_notation);
12258   tcase_add_test(tc_alloc, test_alloc_public_notation);
12259   tcase_add_test(tc_alloc, test_alloc_system_notation);
12260   tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_nested_groups);
12261   tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_realloc_nested_groups);
12262   tcase_add_test(tc_alloc, test_alloc_large_group);
12263   tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_realloc_group_choice);
12264   tcase_add_test(tc_alloc, test_alloc_pi_in_epilog);
12265   tcase_add_test(tc_alloc, test_alloc_comment_in_epilog);
12266   tcase_add_test__ifdef_xml_dtd(tc_alloc,
12267                                 test_alloc_realloc_long_attribute_value);
12268   tcase_add_test(tc_alloc, test_alloc_attribute_whitespace);
12269   tcase_add_test(tc_alloc, test_alloc_attribute_predefined_entity);
12270   tcase_add_test(tc_alloc, test_alloc_long_attr_default_with_char_ref);
12271   tcase_add_test(tc_alloc, test_alloc_long_attr_value);
12272   tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_nested_entities);
12273   tcase_add_test__ifdef_xml_dtd(tc_alloc,
12274                                 test_alloc_realloc_param_entity_newline);
12275   tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_realloc_ce_extends_pe);
12276   tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_realloc_attributes);
12277   tcase_add_test(tc_alloc, test_alloc_long_doc_name);
12278   tcase_add_test(tc_alloc, test_alloc_long_base);
12279   tcase_add_test(tc_alloc, test_alloc_long_public_id);
12280   tcase_add_test(tc_alloc, test_alloc_long_entity_value);
12281   tcase_add_test(tc_alloc, test_alloc_long_notation);
12282 
12283   suite_add_tcase(s, tc_nsalloc);
12284   tcase_add_checked_fixture(tc_nsalloc, nsalloc_setup, nsalloc_teardown);
12285   tcase_add_test(tc_nsalloc, test_nsalloc_xmlns);
12286   tcase_add_test(tc_nsalloc, test_nsalloc_parse_buffer);
12287   tcase_add_test(tc_nsalloc, test_nsalloc_long_prefix);
12288   tcase_add_test(tc_nsalloc, test_nsalloc_long_uri);
12289   tcase_add_test(tc_nsalloc, test_nsalloc_long_attr);
12290   tcase_add_test(tc_nsalloc, test_nsalloc_long_attr_prefix);
12291   tcase_add_test(tc_nsalloc, test_nsalloc_realloc_attributes);
12292   tcase_add_test(tc_nsalloc, test_nsalloc_long_element);
12293   tcase_add_test(tc_nsalloc, test_nsalloc_realloc_binding_uri);
12294   tcase_add_test(tc_nsalloc, test_nsalloc_realloc_long_prefix);
12295   tcase_add_test(tc_nsalloc, test_nsalloc_realloc_longer_prefix);
12296   tcase_add_test(tc_nsalloc, test_nsalloc_long_namespace);
12297   tcase_add_test(tc_nsalloc, test_nsalloc_less_long_namespace);
12298   tcase_add_test(tc_nsalloc, test_nsalloc_long_context);
12299   tcase_add_test(tc_nsalloc, test_nsalloc_realloc_long_context);
12300   tcase_add_test(tc_nsalloc, test_nsalloc_realloc_long_context_2);
12301   tcase_add_test(tc_nsalloc, test_nsalloc_realloc_long_context_3);
12302   tcase_add_test(tc_nsalloc, test_nsalloc_realloc_long_context_4);
12303   tcase_add_test(tc_nsalloc, test_nsalloc_realloc_long_context_5);
12304   tcase_add_test(tc_nsalloc, test_nsalloc_realloc_long_context_6);
12305   tcase_add_test(tc_nsalloc, test_nsalloc_realloc_long_context_7);
12306   tcase_add_test(tc_nsalloc, test_nsalloc_realloc_long_ge_name);
12307   tcase_add_test(tc_nsalloc, test_nsalloc_realloc_long_context_in_dtd);
12308   tcase_add_test(tc_nsalloc, test_nsalloc_long_default_in_ext);
12309   tcase_add_test(tc_nsalloc, test_nsalloc_long_systemid_in_ext);
12310   tcase_add_test(tc_nsalloc, test_nsalloc_prefixed_element);
12311 
12312 #if defined(XML_DTD)
12313   suite_add_tcase(s, tc_accounting);
12314   tcase_add_test(tc_accounting, test_accounting_precision);
12315   tcase_add_test(tc_accounting, test_billion_laughs_attack_protection_api);
12316   tcase_add_test(tc_accounting, test_helper_unsigned_char_to_printable);
12317 #endif
12318 
12319   return s;
12320 }
12321 
12322 int
12323 main(int argc, char *argv[]) {
12324   int i, nf;
12325   int verbosity = CK_NORMAL;
12326   Suite *s = make_suite();
12327   SRunner *sr = srunner_create(s);
12328 
12329   /* run the tests for internal helper functions */
12330   testhelper_is_whitespace_normalized();
12331 
12332   for (i = 1; i < argc; ++i) {
12333     char *opt = argv[i];
12334     if (strcmp(opt, "-v") == 0 || strcmp(opt, "--verbose") == 0)
12335       verbosity = CK_VERBOSE;
12336     else if (strcmp(opt, "-q") == 0 || strcmp(opt, "--quiet") == 0)
12337       verbosity = CK_SILENT;
12338     else {
12339       fprintf(stderr, "runtests: unknown option '%s'\n", opt);
12340       return 2;
12341     }
12342   }
12343   if (verbosity != CK_SILENT)
12344     printf("Expat version: %" XML_FMT_STR "\n", XML_ExpatVersion());
12345   srunner_run_all(sr, verbosity);
12346   nf = srunner_ntests_failed(sr);
12347   srunner_free(sr);
12348 
12349   return (nf == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
12350 }
12351