xref: /freebsd/contrib/expat/tests/runtests.c (revision 4d846d26)
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-2022 Rhodri James <rhodri@wildebeest.org.uk>
15    Copyright (c) 2017      Joe Orton <jorton@redhat.com>
16    Copyright (c) 2017      José Gutiérrez de la Concha <jose@zeroc.com>
17    Copyright (c) 2018      Marco Maggi <marco.maggi-ipsu@poste.it>
18    Copyright (c) 2019      David Loffredo <loffredo@steptools.com>
19    Copyright (c) 2020      Tim Gates <tim.gates@iress.com>
20    Copyright (c) 2021      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 static void XMLCALL
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 /* Regression test for GH issue #612: unfinished m_declAttributeType
6738  * allocation in ->m_tempPool can corrupt following allocation.
6739  */
6740 static int XMLCALL
6741 external_entity_unfinished_attlist(XML_Parser parser, const XML_Char *context,
6742                                    const XML_Char *base,
6743                                    const XML_Char *systemId,
6744                                    const XML_Char *publicId) {
6745   const char *text = "<!ELEMENT barf ANY>\n"
6746                      "<!ATTLIST barf my_attr (blah|%blah;a|foo) #REQUIRED>\n"
6747                      "<!--COMMENT-->\n";
6748   XML_Parser ext_parser;
6749 
6750   UNUSED_P(base);
6751   UNUSED_P(publicId);
6752   if (systemId == NULL)
6753     return XML_STATUS_OK;
6754 
6755   ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
6756   if (ext_parser == NULL)
6757     fail("Could not create external entity parser");
6758 
6759   if (_XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE)
6760       == XML_STATUS_ERROR)
6761     xml_failure(ext_parser);
6762 
6763   XML_ParserFree(ext_parser);
6764   return XML_STATUS_OK;
6765 }
6766 
6767 START_TEST(test_pool_integrity_with_unfinished_attr) {
6768   const char *text = "<?xml version='1.0' encoding='UTF-8'?>\n"
6769                      "<!DOCTYPE foo [\n"
6770                      "<!ELEMENT foo ANY>\n"
6771                      "<!ENTITY % entp SYSTEM \"external.dtd\">\n"
6772                      "%entp;\n"
6773                      "]>\n"
6774                      "<a></a>\n";
6775   const XML_Char *expected = XCS("COMMENT");
6776   CharData storage;
6777 
6778   CharData_Init(&storage);
6779   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
6780   XML_SetExternalEntityRefHandler(g_parser, external_entity_unfinished_attlist);
6781   XML_SetAttlistDeclHandler(g_parser, dummy_attlist_decl_handler);
6782   XML_SetCommentHandler(g_parser, accumulate_comment);
6783   XML_SetUserData(g_parser, &storage);
6784   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
6785       == XML_STATUS_ERROR)
6786     xml_failure(g_parser);
6787   CharData_CheckXMLChars(&storage, expected);
6788 }
6789 END_TEST
6790 
6791 typedef struct {
6792   XML_Parser parser;
6793   CharData *storage;
6794 } ParserPlusStorage;
6795 
6796 static void XMLCALL
6797 accumulate_and_suspend_comment_handler(void *userData, const XML_Char *data) {
6798   ParserPlusStorage *const parserPlusStorage = (ParserPlusStorage *)userData;
6799   accumulate_comment(parserPlusStorage->storage, data);
6800   XML_StopParser(parserPlusStorage->parser, XML_TRUE);
6801 }
6802 
6803 START_TEST(test_nested_entity_suspend) {
6804   const char *const text = "<!DOCTYPE a [\n"
6805                            "  <!ENTITY e1 '<!--e1-->'>\n"
6806                            "  <!ENTITY e2 '<!--e2 head-->&e1;<!--e2 tail-->'>\n"
6807                            "  <!ENTITY e3 '<!--e3 head-->&e2;<!--e3 tail-->'>\n"
6808                            "]>\n"
6809                            "<a><!--start-->&e3;<!--end--></a>";
6810   const XML_Char *const expected = XCS("start") XCS("e3 head") XCS("e2 head")
6811       XCS("e1") XCS("e2 tail") XCS("e3 tail") XCS("end");
6812   CharData storage;
6813   XML_Parser parser = XML_ParserCreate(NULL);
6814   ParserPlusStorage parserPlusStorage = {parser, &storage};
6815 
6816   CharData_Init(&storage);
6817   XML_SetParamEntityParsing(parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
6818   XML_SetCommentHandler(parser, accumulate_and_suspend_comment_handler);
6819   XML_SetUserData(parser, &parserPlusStorage);
6820 
6821   enum XML_Status status = XML_Parse(parser, text, (int)strlen(text), XML_TRUE);
6822   while (status == XML_STATUS_SUSPENDED) {
6823     status = XML_ResumeParser(parser);
6824   }
6825   if (status != XML_STATUS_OK)
6826     xml_failure(parser);
6827 
6828   CharData_CheckXMLChars(&storage, expected);
6829   XML_ParserFree(parser);
6830 }
6831 END_TEST
6832 
6833 /*
6834  * Namespaces tests.
6835  */
6836 
6837 static void
6838 namespace_setup(void) {
6839   g_parser = XML_ParserCreateNS(NULL, XCS(' '));
6840   if (g_parser == NULL)
6841     fail("Parser not created.");
6842 }
6843 
6844 static void
6845 namespace_teardown(void) {
6846   basic_teardown();
6847 }
6848 
6849 /* Check that an element name and attribute name match the expected values.
6850    The expected values are passed as an array reference of string pointers
6851    provided as the userData argument; the first is the expected
6852    element name, and the second is the expected attribute name.
6853 */
6854 static int triplet_start_flag = XML_FALSE;
6855 static int triplet_end_flag = XML_FALSE;
6856 
6857 static void XMLCALL
6858 triplet_start_checker(void *userData, const XML_Char *name,
6859                       const XML_Char **atts) {
6860   XML_Char **elemstr = (XML_Char **)userData;
6861   char buffer[1024];
6862   if (xcstrcmp(elemstr[0], name) != 0) {
6863     sprintf(buffer, "unexpected start string: '%" XML_FMT_STR "'", name);
6864     fail(buffer);
6865   }
6866   if (xcstrcmp(elemstr[1], atts[0]) != 0) {
6867     sprintf(buffer, "unexpected attribute string: '%" XML_FMT_STR "'", atts[0]);
6868     fail(buffer);
6869   }
6870   triplet_start_flag = XML_TRUE;
6871 }
6872 
6873 /* Check that the element name passed to the end-element handler matches
6874    the expected value.  The expected value is passed as the first element
6875    in an array of strings passed as the userData argument.
6876 */
6877 static void XMLCALL
6878 triplet_end_checker(void *userData, const XML_Char *name) {
6879   XML_Char **elemstr = (XML_Char **)userData;
6880   if (xcstrcmp(elemstr[0], name) != 0) {
6881     char buffer[1024];
6882     sprintf(buffer, "unexpected end string: '%" XML_FMT_STR "'", name);
6883     fail(buffer);
6884   }
6885   triplet_end_flag = XML_TRUE;
6886 }
6887 
6888 START_TEST(test_return_ns_triplet) {
6889   const char *text = "<foo:e xmlns:foo='http://example.org/' bar:a='12'\n"
6890                      "       xmlns:bar='http://example.org/'>";
6891   const char *epilog = "</foo:e>";
6892   const XML_Char *elemstr[]
6893       = {XCS("http://example.org/ e foo"), XCS("http://example.org/ a bar")};
6894   XML_SetReturnNSTriplet(g_parser, XML_TRUE);
6895   XML_SetUserData(g_parser, (void *)elemstr);
6896   XML_SetElementHandler(g_parser, triplet_start_checker, triplet_end_checker);
6897   XML_SetNamespaceDeclHandler(g_parser, dummy_start_namespace_decl_handler,
6898                               dummy_end_namespace_decl_handler);
6899   triplet_start_flag = XML_FALSE;
6900   triplet_end_flag = XML_FALSE;
6901   dummy_handler_flags = 0;
6902   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_FALSE)
6903       == XML_STATUS_ERROR)
6904     xml_failure(g_parser);
6905   if (! triplet_start_flag)
6906     fail("triplet_start_checker not invoked");
6907   /* Check that unsetting "return triplets" fails while still parsing */
6908   XML_SetReturnNSTriplet(g_parser, XML_FALSE);
6909   if (_XML_Parse_SINGLE_BYTES(g_parser, epilog, (int)strlen(epilog), XML_TRUE)
6910       == XML_STATUS_ERROR)
6911     xml_failure(g_parser);
6912   if (! triplet_end_flag)
6913     fail("triplet_end_checker not invoked");
6914   if (dummy_handler_flags
6915       != (DUMMY_START_NS_DECL_HANDLER_FLAG | DUMMY_END_NS_DECL_HANDLER_FLAG))
6916     fail("Namespace handlers not called");
6917 }
6918 END_TEST
6919 
6920 static void XMLCALL
6921 overwrite_start_checker(void *userData, const XML_Char *name,
6922                         const XML_Char **atts) {
6923   CharData *storage = (CharData *)userData;
6924   CharData_AppendXMLChars(storage, XCS("start "), 6);
6925   CharData_AppendXMLChars(storage, name, -1);
6926   while (*atts != NULL) {
6927     CharData_AppendXMLChars(storage, XCS("\nattribute "), 11);
6928     CharData_AppendXMLChars(storage, *atts, -1);
6929     atts += 2;
6930   }
6931   CharData_AppendXMLChars(storage, XCS("\n"), 1);
6932 }
6933 
6934 static void XMLCALL
6935 overwrite_end_checker(void *userData, const XML_Char *name) {
6936   CharData *storage = (CharData *)userData;
6937   CharData_AppendXMLChars(storage, XCS("end "), 4);
6938   CharData_AppendXMLChars(storage, name, -1);
6939   CharData_AppendXMLChars(storage, XCS("\n"), 1);
6940 }
6941 
6942 static void
6943 run_ns_tagname_overwrite_test(const char *text, const XML_Char *result) {
6944   CharData storage;
6945   CharData_Init(&storage);
6946   XML_SetUserData(g_parser, &storage);
6947   XML_SetElementHandler(g_parser, overwrite_start_checker,
6948                         overwrite_end_checker);
6949   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
6950       == XML_STATUS_ERROR)
6951     xml_failure(g_parser);
6952   CharData_CheckXMLChars(&storage, result);
6953 }
6954 
6955 /* Regression test for SF bug #566334. */
6956 START_TEST(test_ns_tagname_overwrite) {
6957   const char *text = "<n:e xmlns:n='http://example.org/'>\n"
6958                      "  <n:f n:attr='foo'/>\n"
6959                      "  <n:g n:attr2='bar'/>\n"
6960                      "</n:e>";
6961   const XML_Char *result = XCS("start http://example.org/ e\n")
6962       XCS("start http://example.org/ f\n")
6963           XCS("attribute http://example.org/ attr\n")
6964               XCS("end http://example.org/ f\n")
6965                   XCS("start http://example.org/ g\n")
6966                       XCS("attribute http://example.org/ attr2\n")
6967                           XCS("end http://example.org/ g\n")
6968                               XCS("end http://example.org/ e\n");
6969   run_ns_tagname_overwrite_test(text, result);
6970 }
6971 END_TEST
6972 
6973 /* Regression test for SF bug #566334. */
6974 START_TEST(test_ns_tagname_overwrite_triplet) {
6975   const char *text = "<n:e xmlns:n='http://example.org/'>\n"
6976                      "  <n:f n:attr='foo'/>\n"
6977                      "  <n:g n:attr2='bar'/>\n"
6978                      "</n:e>";
6979   const XML_Char *result = XCS("start http://example.org/ e n\n")
6980       XCS("start http://example.org/ f n\n")
6981           XCS("attribute http://example.org/ attr n\n")
6982               XCS("end http://example.org/ f n\n")
6983                   XCS("start http://example.org/ g n\n")
6984                       XCS("attribute http://example.org/ attr2 n\n")
6985                           XCS("end http://example.org/ g n\n")
6986                               XCS("end http://example.org/ e n\n");
6987   XML_SetReturnNSTriplet(g_parser, XML_TRUE);
6988   run_ns_tagname_overwrite_test(text, result);
6989 }
6990 END_TEST
6991 
6992 /* Regression test for SF bug #620343. */
6993 static void XMLCALL
6994 start_element_fail(void *userData, const XML_Char *name,
6995                    const XML_Char **atts) {
6996   UNUSED_P(userData);
6997   UNUSED_P(name);
6998   UNUSED_P(atts);
6999 
7000   /* We should never get here. */
7001   fail("should never reach start_element_fail()");
7002 }
7003 
7004 static void XMLCALL
7005 start_ns_clearing_start_element(void *userData, const XML_Char *prefix,
7006                                 const XML_Char *uri) {
7007   UNUSED_P(prefix);
7008   UNUSED_P(uri);
7009   XML_SetStartElementHandler((XML_Parser)userData, NULL);
7010 }
7011 
7012 START_TEST(test_start_ns_clears_start_element) {
7013   /* This needs to use separate start/end tags; using the empty tag
7014      syntax doesn't cause the problematic path through Expat to be
7015      taken.
7016   */
7017   const char *text = "<e xmlns='http://example.org/'></e>";
7018 
7019   XML_SetStartElementHandler(g_parser, start_element_fail);
7020   XML_SetStartNamespaceDeclHandler(g_parser, start_ns_clearing_start_element);
7021   XML_SetEndNamespaceDeclHandler(g_parser, dummy_end_namespace_decl_handler);
7022   XML_UseParserAsHandlerArg(g_parser);
7023   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
7024       == XML_STATUS_ERROR)
7025     xml_failure(g_parser);
7026 }
7027 END_TEST
7028 
7029 /* Regression test for SF bug #616863. */
7030 static int XMLCALL
7031 external_entity_handler(XML_Parser parser, const XML_Char *context,
7032                         const XML_Char *base, const XML_Char *systemId,
7033                         const XML_Char *publicId) {
7034   intptr_t callno = 1 + (intptr_t)XML_GetUserData(parser);
7035   const char *text;
7036   XML_Parser p2;
7037 
7038   UNUSED_P(base);
7039   UNUSED_P(systemId);
7040   UNUSED_P(publicId);
7041   if (callno == 1)
7042     text = ("<!ELEMENT doc (e+)>\n"
7043             "<!ATTLIST doc xmlns CDATA #IMPLIED>\n"
7044             "<!ELEMENT e EMPTY>\n");
7045   else
7046     text = ("<?xml version='1.0' encoding='us-ascii'?>"
7047             "<e/>");
7048 
7049   XML_SetUserData(parser, (void *)callno);
7050   p2 = XML_ExternalEntityParserCreate(parser, context, NULL);
7051   if (_XML_Parse_SINGLE_BYTES(p2, text, (int)strlen(text), XML_TRUE)
7052       == XML_STATUS_ERROR) {
7053     xml_failure(p2);
7054     return XML_STATUS_ERROR;
7055   }
7056   XML_ParserFree(p2);
7057   return XML_STATUS_OK;
7058 }
7059 
7060 START_TEST(test_default_ns_from_ext_subset_and_ext_ge) {
7061   const char *text = "<?xml version='1.0'?>\n"
7062                      "<!DOCTYPE doc SYSTEM 'http://example.org/doc.dtd' [\n"
7063                      "  <!ENTITY en SYSTEM 'http://example.org/entity.ent'>\n"
7064                      "]>\n"
7065                      "<doc xmlns='http://example.org/ns1'>\n"
7066                      "&en;\n"
7067                      "</doc>";
7068 
7069   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
7070   XML_SetExternalEntityRefHandler(g_parser, external_entity_handler);
7071   /* We actually need to set this handler to tickle this bug. */
7072   XML_SetStartElementHandler(g_parser, dummy_start_element);
7073   XML_SetUserData(g_parser, NULL);
7074   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
7075       == XML_STATUS_ERROR)
7076     xml_failure(g_parser);
7077 }
7078 END_TEST
7079 
7080 /* Regression test #1 for SF bug #673791. */
7081 START_TEST(test_ns_prefix_with_empty_uri_1) {
7082   const char *text = "<doc xmlns:prefix='http://example.org/'>\n"
7083                      "  <e xmlns:prefix=''/>\n"
7084                      "</doc>";
7085 
7086   expect_failure(text, XML_ERROR_UNDECLARING_PREFIX,
7087                  "Did not report re-setting namespace"
7088                  " URI with prefix to ''.");
7089 }
7090 END_TEST
7091 
7092 /* Regression test #2 for SF bug #673791. */
7093 START_TEST(test_ns_prefix_with_empty_uri_2) {
7094   const char *text = "<?xml version='1.0'?>\n"
7095                      "<docelem xmlns:pre=''/>";
7096 
7097   expect_failure(text, XML_ERROR_UNDECLARING_PREFIX,
7098                  "Did not report setting namespace URI with prefix to ''.");
7099 }
7100 END_TEST
7101 
7102 /* Regression test #3 for SF bug #673791. */
7103 START_TEST(test_ns_prefix_with_empty_uri_3) {
7104   const char *text = "<!DOCTYPE doc [\n"
7105                      "  <!ELEMENT doc EMPTY>\n"
7106                      "  <!ATTLIST doc\n"
7107                      "    xmlns:prefix CDATA ''>\n"
7108                      "]>\n"
7109                      "<doc/>";
7110 
7111   expect_failure(text, XML_ERROR_UNDECLARING_PREFIX,
7112                  "Didn't report attr default setting NS w/ prefix to ''.");
7113 }
7114 END_TEST
7115 
7116 /* Regression test #4 for SF bug #673791. */
7117 START_TEST(test_ns_prefix_with_empty_uri_4) {
7118   const char *text = "<!DOCTYPE doc [\n"
7119                      "  <!ELEMENT prefix:doc EMPTY>\n"
7120                      "  <!ATTLIST prefix:doc\n"
7121                      "    xmlns:prefix CDATA 'http://example.org/'>\n"
7122                      "]>\n"
7123                      "<prefix:doc/>";
7124   /* Packaged info expected by the end element handler;
7125      the weird structuring lets us re-use the triplet_end_checker()
7126      function also used for another test. */
7127   const XML_Char *elemstr[] = {XCS("http://example.org/ doc prefix")};
7128   XML_SetReturnNSTriplet(g_parser, XML_TRUE);
7129   XML_SetUserData(g_parser, (void *)elemstr);
7130   XML_SetEndElementHandler(g_parser, triplet_end_checker);
7131   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
7132       == XML_STATUS_ERROR)
7133     xml_failure(g_parser);
7134 }
7135 END_TEST
7136 
7137 /* Test with non-xmlns prefix */
7138 START_TEST(test_ns_unbound_prefix) {
7139   const char *text = "<!DOCTYPE doc [\n"
7140                      "  <!ELEMENT prefix:doc EMPTY>\n"
7141                      "  <!ATTLIST prefix:doc\n"
7142                      "    notxmlns:prefix CDATA 'http://example.org/'>\n"
7143                      "]>\n"
7144                      "<prefix:doc/>";
7145 
7146   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
7147       != XML_STATUS_ERROR)
7148     fail("Unbound prefix incorrectly passed");
7149   if (XML_GetErrorCode(g_parser) != XML_ERROR_UNBOUND_PREFIX)
7150     xml_failure(g_parser);
7151 }
7152 END_TEST
7153 
7154 START_TEST(test_ns_default_with_empty_uri) {
7155   const char *text = "<doc xmlns='http://example.org/'>\n"
7156                      "  <e xmlns=''/>\n"
7157                      "</doc>";
7158   /* Add some handlers to exercise extra code paths */
7159   XML_SetStartNamespaceDeclHandler(g_parser,
7160                                    dummy_start_namespace_decl_handler);
7161   XML_SetEndNamespaceDeclHandler(g_parser, dummy_end_namespace_decl_handler);
7162   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
7163       == XML_STATUS_ERROR)
7164     xml_failure(g_parser);
7165 }
7166 END_TEST
7167 
7168 /* Regression test for SF bug #692964: two prefixes for one namespace. */
7169 START_TEST(test_ns_duplicate_attrs_diff_prefixes) {
7170   const char *text = "<doc xmlns:a='http://example.org/a'\n"
7171                      "     xmlns:b='http://example.org/a'\n"
7172                      "     a:a='v' b:a='v' />";
7173   expect_failure(text, XML_ERROR_DUPLICATE_ATTRIBUTE,
7174                  "did not report multiple attributes with same URI+name");
7175 }
7176 END_TEST
7177 
7178 START_TEST(test_ns_duplicate_hashes) {
7179   /* The hash of an attribute is calculated as the hash of its URI
7180    * concatenated with a space followed by its name (after the
7181    * colon).  We wish to generate attributes with the same hash
7182    * value modulo the attribute table size so that we can check that
7183    * the attribute hash table works correctly.  The attribute hash
7184    * table size will be the smallest power of two greater than the
7185    * number of attributes, but at least eight.  There is
7186    * unfortunately no programmatic way of getting the hash or the
7187    * table size at user level, but the test code coverage percentage
7188    * will drop if the hashes cease to point to the same row.
7189    *
7190    * The cunning plan is to have few enough attributes to have a
7191    * reliable table size of 8, and have the single letter attribute
7192    * names be 8 characters apart, producing a hash which will be the
7193    * same modulo 8.
7194    */
7195   const char *text = "<doc xmlns:a='http://example.org/a'\n"
7196                      "     a:a='v' a:i='w' />";
7197   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
7198       == XML_STATUS_ERROR)
7199     xml_failure(g_parser);
7200 }
7201 END_TEST
7202 
7203 /* Regression test for SF bug #695401: unbound prefix. */
7204 START_TEST(test_ns_unbound_prefix_on_attribute) {
7205   const char *text = "<doc a:attr=''/>";
7206   expect_failure(text, XML_ERROR_UNBOUND_PREFIX,
7207                  "did not report unbound prefix on attribute");
7208 }
7209 END_TEST
7210 
7211 /* Regression test for SF bug #695401: unbound prefix. */
7212 START_TEST(test_ns_unbound_prefix_on_element) {
7213   const char *text = "<a:doc/>";
7214   expect_failure(text, XML_ERROR_UNBOUND_PREFIX,
7215                  "did not report unbound prefix on element");
7216 }
7217 END_TEST
7218 
7219 /* Test that the parsing status is correctly reset by XML_ParserReset().
7220  * We usE test_return_ns_triplet() for our example parse to improve
7221  * coverage of tidying up code executed.
7222  */
7223 START_TEST(test_ns_parser_reset) {
7224   XML_ParsingStatus status;
7225 
7226   XML_GetParsingStatus(g_parser, &status);
7227   if (status.parsing != XML_INITIALIZED)
7228     fail("parsing status doesn't start INITIALIZED");
7229   test_return_ns_triplet();
7230   XML_GetParsingStatus(g_parser, &status);
7231   if (status.parsing != XML_FINISHED)
7232     fail("parsing status doesn't end FINISHED");
7233   XML_ParserReset(g_parser, NULL);
7234   XML_GetParsingStatus(g_parser, &status);
7235   if (status.parsing != XML_INITIALIZED)
7236     fail("parsing status doesn't reset to INITIALIZED");
7237 }
7238 END_TEST
7239 
7240 /* Test that long element names with namespaces are handled correctly */
7241 START_TEST(test_ns_long_element) {
7242   const char *text
7243       = "<foo:thisisalongenoughelementnametotriggerareallocation\n"
7244         " xmlns:foo='http://example.org/' bar:a='12'\n"
7245         " xmlns:bar='http://example.org/'>"
7246         "</foo:thisisalongenoughelementnametotriggerareallocation>";
7247   const XML_Char *elemstr[]
7248       = {XCS("http://example.org/")
7249              XCS(" thisisalongenoughelementnametotriggerareallocation foo"),
7250          XCS("http://example.org/ a bar")};
7251 
7252   XML_SetReturnNSTriplet(g_parser, XML_TRUE);
7253   XML_SetUserData(g_parser, (void *)elemstr);
7254   XML_SetElementHandler(g_parser, triplet_start_checker, triplet_end_checker);
7255   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
7256       == XML_STATUS_ERROR)
7257     xml_failure(g_parser);
7258 }
7259 END_TEST
7260 
7261 /* Test mixed population of prefixed and unprefixed attributes */
7262 START_TEST(test_ns_mixed_prefix_atts) {
7263   const char *text = "<e a='12' bar:b='13'\n"
7264                      " xmlns:bar='http://example.org/'>"
7265                      "</e>";
7266 
7267   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
7268       == XML_STATUS_ERROR)
7269     xml_failure(g_parser);
7270 }
7271 END_TEST
7272 
7273 /* Test having a long namespaced element name inside a short one.
7274  * This exercises some internal buffer reallocation that is shared
7275  * across elements with the same namespace URI.
7276  */
7277 START_TEST(test_ns_extend_uri_buffer) {
7278   const char *text = "<foo:e xmlns:foo='http://example.org/'>"
7279                      " <foo:thisisalongenoughnametotriggerallocationaction"
7280                      "   foo:a='12' />"
7281                      "</foo:e>";
7282   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
7283       == XML_STATUS_ERROR)
7284     xml_failure(g_parser);
7285 }
7286 END_TEST
7287 
7288 /* Test that xmlns is correctly rejected as an attribute in the xmlns
7289  * namespace, but not in other namespaces
7290  */
7291 START_TEST(test_ns_reserved_attributes) {
7292   const char *text1
7293       = "<foo:e xmlns:foo='http://example.org/' xmlns:xmlns='12' />";
7294   const char *text2
7295       = "<foo:e xmlns:foo='http://example.org/' foo:xmlns='12' />";
7296   expect_failure(text1, XML_ERROR_RESERVED_PREFIX_XMLNS,
7297                  "xmlns not rejected as an attribute");
7298   XML_ParserReset(g_parser, NULL);
7299   if (_XML_Parse_SINGLE_BYTES(g_parser, text2, (int)strlen(text2), XML_TRUE)
7300       == XML_STATUS_ERROR)
7301     xml_failure(g_parser);
7302 }
7303 END_TEST
7304 
7305 /* Test more reserved attributes */
7306 START_TEST(test_ns_reserved_attributes_2) {
7307   const char *text1 = "<foo:e xmlns:foo='http://example.org/'"
7308                       "  xmlns:xml='http://example.org/' />";
7309   const char *text2
7310       = "<foo:e xmlns:foo='http://www.w3.org/XML/1998/namespace' />";
7311   const char *text3 = "<foo:e xmlns:foo='http://www.w3.org/2000/xmlns/' />";
7312 
7313   expect_failure(text1, XML_ERROR_RESERVED_PREFIX_XML,
7314                  "xml not rejected as an attribute");
7315   XML_ParserReset(g_parser, NULL);
7316   expect_failure(text2, XML_ERROR_RESERVED_NAMESPACE_URI,
7317                  "Use of w3.org URL not faulted");
7318   XML_ParserReset(g_parser, NULL);
7319   expect_failure(text3, XML_ERROR_RESERVED_NAMESPACE_URI,
7320                  "Use of w3.org xmlns URL not faulted");
7321 }
7322 END_TEST
7323 
7324 /* Test string pool handling of namespace names of 2048 characters */
7325 /* Exercises a particular string pool growth path */
7326 START_TEST(test_ns_extremely_long_prefix) {
7327   /* C99 compilers are only required to support 4095-character
7328    * strings, so the following needs to be split in two to be safe
7329    * for all compilers.
7330    */
7331   const char *text1
7332       = "<doc "
7333         /* 64 character on each line */
7334         /* ...gives a total length of 2048 */
7335         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7336         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7337         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7338         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7339         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7340         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7341         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7342         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7343         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7344         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7345         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7346         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7347         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7348         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7349         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7350         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7351         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7352         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7353         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7354         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7355         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7356         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7357         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7358         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7359         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7360         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7361         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7362         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7363         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7364         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7365         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7366         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7367         ":a='12'";
7368   const char *text2
7369       = " xmlns:"
7370         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7371         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7372         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7373         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7374         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7375         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7376         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7377         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7378         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7379         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7380         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7381         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7382         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7383         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7384         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7385         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7386         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7387         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7388         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7389         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7390         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7391         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7392         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7393         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7394         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7395         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7396         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7397         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7398         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7399         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7400         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7401         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7402         "='foo'\n>"
7403         "</doc>";
7404 
7405   if (_XML_Parse_SINGLE_BYTES(g_parser, text1, (int)strlen(text1), XML_FALSE)
7406       == XML_STATUS_ERROR)
7407     xml_failure(g_parser);
7408   if (_XML_Parse_SINGLE_BYTES(g_parser, text2, (int)strlen(text2), XML_TRUE)
7409       == XML_STATUS_ERROR)
7410     xml_failure(g_parser);
7411 }
7412 END_TEST
7413 
7414 /* Test unknown encoding handlers in namespace setup */
7415 START_TEST(test_ns_unknown_encoding_success) {
7416   const char *text = "<?xml version='1.0' encoding='prefix-conv'?>\n"
7417                      "<foo:e xmlns:foo='http://example.org/'>Hi</foo:e>";
7418 
7419   XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL);
7420   run_character_check(text, XCS("Hi"));
7421 }
7422 END_TEST
7423 
7424 /* Test that too many colons are rejected */
7425 START_TEST(test_ns_double_colon) {
7426   const char *text = "<foo:e xmlns:foo='http://example.org/' foo:a:b='bar' />";
7427   const enum XML_Status status
7428       = _XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE);
7429 #ifdef XML_NS
7430   if ((status == XML_STATUS_OK)
7431       || (XML_GetErrorCode(g_parser) != XML_ERROR_INVALID_TOKEN)) {
7432     fail("Double colon in attribute name not faulted"
7433          " (despite active namespace support)");
7434   }
7435 #else
7436   if (status != XML_STATUS_OK) {
7437     fail("Double colon in attribute name faulted"
7438          " (despite inactive namespace support");
7439   }
7440 #endif
7441 }
7442 END_TEST
7443 
7444 START_TEST(test_ns_double_colon_element) {
7445   const char *text = "<foo:bar:e xmlns:foo='http://example.org/' />";
7446   const enum XML_Status status
7447       = _XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE);
7448 #ifdef XML_NS
7449   if ((status == XML_STATUS_OK)
7450       || (XML_GetErrorCode(g_parser) != XML_ERROR_INVALID_TOKEN)) {
7451     fail("Double colon in element name not faulted"
7452          " (despite active namespace support)");
7453   }
7454 #else
7455   if (status != XML_STATUS_OK) {
7456     fail("Double colon in element name faulted"
7457          " (despite inactive namespace support");
7458   }
7459 #endif
7460 }
7461 END_TEST
7462 
7463 /* Test that non-name characters after a colon are rejected */
7464 START_TEST(test_ns_bad_attr_leafname) {
7465   const char *text = "<foo:e xmlns:foo='http://example.org/' foo:?ar='baz' />";
7466 
7467   expect_failure(text, XML_ERROR_INVALID_TOKEN,
7468                  "Invalid character in leafname not faulted");
7469 }
7470 END_TEST
7471 
7472 START_TEST(test_ns_bad_element_leafname) {
7473   const char *text = "<foo:?oc xmlns:foo='http://example.org/' />";
7474 
7475   expect_failure(text, XML_ERROR_INVALID_TOKEN,
7476                  "Invalid character in element leafname not faulted");
7477 }
7478 END_TEST
7479 
7480 /* Test high-byte-set UTF-16 characters are valid in a leafname */
7481 START_TEST(test_ns_utf16_leafname) {
7482   const char text[] =
7483       /* <n:e xmlns:n='URI' n:{KHO KHWAI}='a' />
7484        * where {KHO KHWAI} = U+0E04 = 0xe0 0xb8 0x84 in UTF-8
7485        */
7486       "<\0n\0:\0e\0 \0x\0m\0l\0n\0s\0:\0n\0=\0'\0U\0R\0I\0'\0 \0"
7487       "n\0:\0\x04\x0e=\0'\0a\0'\0 \0/\0>\0";
7488   const XML_Char *expected = XCS("a");
7489   CharData storage;
7490 
7491   CharData_Init(&storage);
7492   XML_SetStartElementHandler(g_parser, accumulate_attribute);
7493   XML_SetUserData(g_parser, &storage);
7494   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE)
7495       == XML_STATUS_ERROR)
7496     xml_failure(g_parser);
7497   CharData_CheckXMLChars(&storage, expected);
7498 }
7499 END_TEST
7500 
7501 START_TEST(test_ns_utf16_element_leafname) {
7502   const char text[] =
7503       /* <n:{KHO KHWAI} xmlns:n='URI'/>
7504        * where {KHO KHWAI} = U+0E04 = 0xe0 0xb8 0x84 in UTF-8
7505        */
7506       "\0<\0n\0:\x0e\x04\0 \0x\0m\0l\0n\0s\0:\0n\0=\0'\0U\0R\0I\0'\0/\0>";
7507 #ifdef XML_UNICODE
7508   const XML_Char *expected = XCS("URI \x0e04");
7509 #else
7510   const XML_Char *expected = XCS("URI \xe0\xb8\x84");
7511 #endif
7512   CharData storage;
7513 
7514   CharData_Init(&storage);
7515   XML_SetStartElementHandler(g_parser, start_element_event_handler);
7516   XML_SetUserData(g_parser, &storage);
7517   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE)
7518       == XML_STATUS_ERROR)
7519     xml_failure(g_parser);
7520   CharData_CheckXMLChars(&storage, expected);
7521 }
7522 END_TEST
7523 
7524 START_TEST(test_ns_utf16_doctype) {
7525   const char text[] =
7526       /* <!DOCTYPE foo:{KHO KHWAI} [ <!ENTITY bar 'baz'> ]>\n
7527        * where {KHO KHWAI} = U+0E04 = 0xe0 0xb8 0x84 in UTF-8
7528        */
7529       "\0<\0!\0D\0O\0C\0T\0Y\0P\0E\0 \0f\0o\0o\0:\x0e\x04\0 "
7530       "\0[\0 \0<\0!\0E\0N\0T\0I\0T\0Y\0 \0b\0a\0r\0 \0'\0b\0a\0z\0'\0>\0 "
7531       "\0]\0>\0\n"
7532       /* <foo:{KHO KHWAI} xmlns:foo='URI'>&bar;</foo:{KHO KHWAI}> */
7533       "\0<\0f\0o\0o\0:\x0e\x04\0 "
7534       "\0x\0m\0l\0n\0s\0:\0f\0o\0o\0=\0'\0U\0R\0I\0'\0>"
7535       "\0&\0b\0a\0r\0;"
7536       "\0<\0/\0f\0o\0o\0:\x0e\x04\0>";
7537 #ifdef XML_UNICODE
7538   const XML_Char *expected = XCS("URI \x0e04");
7539 #else
7540   const XML_Char *expected = XCS("URI \xe0\xb8\x84");
7541 #endif
7542   CharData storage;
7543 
7544   CharData_Init(&storage);
7545   XML_SetUserData(g_parser, &storage);
7546   XML_SetStartElementHandler(g_parser, start_element_event_handler);
7547   XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL);
7548   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE)
7549       == XML_STATUS_ERROR)
7550     xml_failure(g_parser);
7551   CharData_CheckXMLChars(&storage, expected);
7552 }
7553 END_TEST
7554 
7555 START_TEST(test_ns_invalid_doctype) {
7556   const char *text = "<!DOCTYPE foo:!bad [ <!ENTITY bar 'baz' ]>\n"
7557                      "<foo:!bad>&bar;</foo:!bad>";
7558 
7559   expect_failure(text, XML_ERROR_INVALID_TOKEN,
7560                  "Invalid character in document local name not faulted");
7561 }
7562 END_TEST
7563 
7564 START_TEST(test_ns_double_colon_doctype) {
7565   const char *text = "<!DOCTYPE foo:a:doc [ <!ENTITY bar 'baz' ]>\n"
7566                      "<foo:a:doc>&bar;</foo:a:doc>";
7567 
7568   expect_failure(text, XML_ERROR_SYNTAX,
7569                  "Double colon in document name not faulted");
7570 }
7571 END_TEST
7572 
7573 START_TEST(test_ns_separator_in_uri) {
7574   struct test_case {
7575     enum XML_Status expectedStatus;
7576     const char *doc;
7577     XML_Char namesep;
7578   };
7579   struct test_case cases[] = {
7580       {XML_STATUS_OK, "<doc xmlns='one_two' />", XCS('\n')},
7581       {XML_STATUS_ERROR, "<doc xmlns='one&#x0A;two' />", XCS('\n')},
7582       {XML_STATUS_OK, "<doc xmlns='one:two' />", XCS(':')},
7583   };
7584 
7585   size_t i = 0;
7586   size_t failCount = 0;
7587   for (; i < sizeof(cases) / sizeof(cases[0]); i++) {
7588     XML_Parser parser = XML_ParserCreateNS(NULL, cases[i].namesep);
7589     XML_SetElementHandler(parser, dummy_start_element, dummy_end_element);
7590     if (XML_Parse(parser, cases[i].doc, (int)strlen(cases[i].doc),
7591                   /*isFinal*/ XML_TRUE)
7592         != cases[i].expectedStatus) {
7593       failCount++;
7594     }
7595     XML_ParserFree(parser);
7596   }
7597 
7598   if (failCount) {
7599     fail("Namespace separator handling is broken");
7600   }
7601 }
7602 END_TEST
7603 
7604 /* Control variable; the number of times duff_allocator() will successfully
7605  * allocate */
7606 #define ALLOC_ALWAYS_SUCCEED (-1)
7607 #define REALLOC_ALWAYS_SUCCEED (-1)
7608 
7609 static intptr_t allocation_count = ALLOC_ALWAYS_SUCCEED;
7610 static intptr_t reallocation_count = REALLOC_ALWAYS_SUCCEED;
7611 
7612 /* Crocked allocator for allocation failure tests */
7613 static void *
7614 duff_allocator(size_t size) {
7615   if (allocation_count == 0)
7616     return NULL;
7617   if (allocation_count != ALLOC_ALWAYS_SUCCEED)
7618     allocation_count--;
7619   return malloc(size);
7620 }
7621 
7622 /* Crocked reallocator for allocation failure tests */
7623 static void *
7624 duff_reallocator(void *ptr, size_t size) {
7625   if (reallocation_count == 0)
7626     return NULL;
7627   if (reallocation_count != REALLOC_ALWAYS_SUCCEED)
7628     reallocation_count--;
7629   return realloc(ptr, size);
7630 }
7631 
7632 /* Test that a failure to allocate the parser structure fails gracefully */
7633 START_TEST(test_misc_alloc_create_parser) {
7634   XML_Memory_Handling_Suite memsuite = {duff_allocator, realloc, free};
7635   unsigned int i;
7636   const unsigned int max_alloc_count = 10;
7637 
7638   /* Something this simple shouldn't need more than 10 allocations */
7639   for (i = 0; i < max_alloc_count; i++) {
7640     allocation_count = i;
7641     g_parser = XML_ParserCreate_MM(NULL, &memsuite, NULL);
7642     if (g_parser != NULL)
7643       break;
7644   }
7645   if (i == 0)
7646     fail("Parser unexpectedly ignored failing allocator");
7647   else if (i == max_alloc_count)
7648     fail("Parser not created with max allocation count");
7649 }
7650 END_TEST
7651 
7652 /* Test memory allocation failures for a parser with an encoding */
7653 START_TEST(test_misc_alloc_create_parser_with_encoding) {
7654   XML_Memory_Handling_Suite memsuite = {duff_allocator, realloc, free};
7655   unsigned int i;
7656   const unsigned int max_alloc_count = 10;
7657 
7658   /* Try several levels of allocation */
7659   for (i = 0; i < max_alloc_count; i++) {
7660     allocation_count = i;
7661     g_parser = XML_ParserCreate_MM(XCS("us-ascii"), &memsuite, NULL);
7662     if (g_parser != NULL)
7663       break;
7664   }
7665   if (i == 0)
7666     fail("Parser ignored failing allocator");
7667   else if (i == max_alloc_count)
7668     fail("Parser not created with max allocation count");
7669 }
7670 END_TEST
7671 
7672 /* Test that freeing a NULL parser doesn't cause an explosion.
7673  * (Not actually tested anywhere else)
7674  */
7675 START_TEST(test_misc_null_parser) {
7676   XML_ParserFree(NULL);
7677 }
7678 END_TEST
7679 
7680 /* Test that XML_ErrorString rejects out-of-range codes */
7681 START_TEST(test_misc_error_string) {
7682   if (XML_ErrorString((enum XML_Error) - 1) != NULL)
7683     fail("Negative error code not rejected");
7684   if (XML_ErrorString((enum XML_Error)100) != NULL)
7685     fail("Large error code not rejected");
7686 }
7687 END_TEST
7688 
7689 /* Test the version information is consistent */
7690 
7691 /* Since we are working in XML_LChars (potentially 16-bits), we
7692  * can't use the standard C library functions for character
7693  * manipulation and have to roll our own.
7694  */
7695 static int
7696 parse_version(const XML_LChar *version_text,
7697               XML_Expat_Version *version_struct) {
7698   if (! version_text)
7699     return XML_FALSE;
7700 
7701   while (*version_text != 0x00) {
7702     if (*version_text >= ASCII_0 && *version_text <= ASCII_9)
7703       break;
7704     version_text++;
7705   }
7706   if (*version_text == 0x00)
7707     return XML_FALSE;
7708 
7709   /* version_struct->major = strtoul(version_text, 10, &version_text) */
7710   version_struct->major = 0;
7711   while (*version_text >= ASCII_0 && *version_text <= ASCII_9) {
7712     version_struct->major
7713         = 10 * version_struct->major + (*version_text++ - ASCII_0);
7714   }
7715   if (*version_text++ != ASCII_PERIOD)
7716     return XML_FALSE;
7717 
7718   /* Now for the minor version number */
7719   version_struct->minor = 0;
7720   while (*version_text >= ASCII_0 && *version_text <= ASCII_9) {
7721     version_struct->minor
7722         = 10 * version_struct->minor + (*version_text++ - ASCII_0);
7723   }
7724   if (*version_text++ != ASCII_PERIOD)
7725     return XML_FALSE;
7726 
7727   /* Finally the micro version number */
7728   version_struct->micro = 0;
7729   while (*version_text >= ASCII_0 && *version_text <= ASCII_9) {
7730     version_struct->micro
7731         = 10 * version_struct->micro + (*version_text++ - ASCII_0);
7732   }
7733   if (*version_text != 0x00)
7734     return XML_FALSE;
7735   return XML_TRUE;
7736 }
7737 
7738 static int
7739 versions_equal(const XML_Expat_Version *first,
7740                const XML_Expat_Version *second) {
7741   return (first->major == second->major && first->minor == second->minor
7742           && first->micro == second->micro);
7743 }
7744 
7745 START_TEST(test_misc_version) {
7746   XML_Expat_Version read_version = XML_ExpatVersionInfo();
7747   /* Silence compiler warning with the following assignment */
7748   XML_Expat_Version parsed_version = {0, 0, 0};
7749   const XML_LChar *version_text = XML_ExpatVersion();
7750 
7751   if (version_text == NULL)
7752     fail("Could not obtain version text");
7753   assert(version_text != NULL);
7754   if (! parse_version(version_text, &parsed_version))
7755     fail("Unable to parse version text");
7756   if (! versions_equal(&read_version, &parsed_version))
7757     fail("Version mismatch");
7758 
7759 #if ! defined(XML_UNICODE) || defined(XML_UNICODE_WCHAR_T)
7760   if (xcstrcmp(version_text, XCS("expat_2.5.0"))) /* needs bump on releases */
7761     fail("XML_*_VERSION in expat.h out of sync?\n");
7762 #else
7763   /* If we have XML_UNICODE defined but not XML_UNICODE_WCHAR_T
7764    * then XML_LChar is defined as char, for some reason.
7765    */
7766   if (strcmp(version_text, "expat_2.2.5")) /* needs bump on releases */
7767     fail("XML_*_VERSION in expat.h out of sync?\n");
7768 #endif /* ! defined(XML_UNICODE) || defined(XML_UNICODE_WCHAR_T) */
7769 }
7770 END_TEST
7771 
7772 /* Test feature information */
7773 START_TEST(test_misc_features) {
7774   const XML_Feature *features = XML_GetFeatureList();
7775 
7776   /* Prevent problems with double-freeing parsers */
7777   g_parser = NULL;
7778   if (features == NULL) {
7779     fail("Failed to get feature information");
7780   } else {
7781     /* Loop through the features checking what we can */
7782     while (features->feature != XML_FEATURE_END) {
7783       switch (features->feature) {
7784       case XML_FEATURE_SIZEOF_XML_CHAR:
7785         if (features->value != sizeof(XML_Char))
7786           fail("Incorrect size of XML_Char");
7787         break;
7788       case XML_FEATURE_SIZEOF_XML_LCHAR:
7789         if (features->value != sizeof(XML_LChar))
7790           fail("Incorrect size of XML_LChar");
7791         break;
7792       default:
7793         break;
7794       }
7795       features++;
7796     }
7797   }
7798 }
7799 END_TEST
7800 
7801 /* Regression test for GitHub Issue #17: memory leak parsing attribute
7802  * values with mixed bound and unbound namespaces.
7803  */
7804 START_TEST(test_misc_attribute_leak) {
7805   const char *text = "<D xmlns:L=\"D\" l:a='' L:a=''/>";
7806   XML_Memory_Handling_Suite memsuite
7807       = {tracking_malloc, tracking_realloc, tracking_free};
7808 
7809   g_parser = XML_ParserCreate_MM(XCS("UTF-8"), &memsuite, XCS("\n"));
7810   expect_failure(text, XML_ERROR_UNBOUND_PREFIX, "Unbound prefixes not found");
7811   XML_ParserFree(g_parser);
7812   /* Prevent the teardown trying to double free */
7813   g_parser = NULL;
7814 
7815   if (! tracking_report())
7816     fail("Memory leak found");
7817 }
7818 END_TEST
7819 
7820 /* Test parser created for UTF-16LE is successful */
7821 START_TEST(test_misc_utf16le) {
7822   const char text[] =
7823       /* <?xml version='1.0'?><q>Hi</q> */
7824       "<\0?\0x\0m\0l\0 \0"
7825       "v\0e\0r\0s\0i\0o\0n\0=\0'\0\x31\0.\0\x30\0'\0?\0>\0"
7826       "<\0q\0>\0H\0i\0<\0/\0q\0>\0";
7827   const XML_Char *expected = XCS("Hi");
7828   CharData storage;
7829 
7830   g_parser = XML_ParserCreate(XCS("UTF-16LE"));
7831   if (g_parser == NULL)
7832     fail("Parser not created");
7833 
7834   CharData_Init(&storage);
7835   XML_SetUserData(g_parser, &storage);
7836   XML_SetCharacterDataHandler(g_parser, accumulate_characters);
7837   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE)
7838       == XML_STATUS_ERROR)
7839     xml_failure(g_parser);
7840   CharData_CheckXMLChars(&storage, expected);
7841 }
7842 END_TEST
7843 
7844 typedef struct {
7845   XML_Parser parser;
7846   int deep;
7847 } DataIssue240;
7848 
7849 static void
7850 start_element_issue_240(void *userData, const XML_Char *name,
7851                         const XML_Char **atts) {
7852   DataIssue240 *mydata = (DataIssue240 *)userData;
7853   UNUSED_P(name);
7854   UNUSED_P(atts);
7855   mydata->deep++;
7856 }
7857 
7858 static void
7859 end_element_issue_240(void *userData, const XML_Char *name) {
7860   DataIssue240 *mydata = (DataIssue240 *)userData;
7861 
7862   UNUSED_P(name);
7863   mydata->deep--;
7864   if (mydata->deep == 0) {
7865     XML_StopParser(mydata->parser, 0);
7866   }
7867 }
7868 
7869 START_TEST(test_misc_stop_during_end_handler_issue_240_1) {
7870   XML_Parser parser;
7871   DataIssue240 *mydata;
7872   enum XML_Status result;
7873   const char *const doc1 = "<doc><e1/><e><foo/></e></doc>";
7874 
7875   parser = XML_ParserCreate(NULL);
7876   XML_SetElementHandler(parser, start_element_issue_240, end_element_issue_240);
7877   mydata = (DataIssue240 *)malloc(sizeof(DataIssue240));
7878   mydata->parser = parser;
7879   mydata->deep = 0;
7880   XML_SetUserData(parser, mydata);
7881 
7882   result = XML_Parse(parser, doc1, (int)strlen(doc1), 1);
7883   XML_ParserFree(parser);
7884   free(mydata);
7885   if (result != XML_STATUS_ERROR)
7886     fail("Stopping the parser did not work as expected");
7887 }
7888 END_TEST
7889 
7890 START_TEST(test_misc_stop_during_end_handler_issue_240_2) {
7891   XML_Parser parser;
7892   DataIssue240 *mydata;
7893   enum XML_Status result;
7894   const char *const doc2 = "<doc><elem/></doc>";
7895 
7896   parser = XML_ParserCreate(NULL);
7897   XML_SetElementHandler(parser, start_element_issue_240, end_element_issue_240);
7898   mydata = (DataIssue240 *)malloc(sizeof(DataIssue240));
7899   mydata->parser = parser;
7900   mydata->deep = 0;
7901   XML_SetUserData(parser, mydata);
7902 
7903   result = XML_Parse(parser, doc2, (int)strlen(doc2), 1);
7904   XML_ParserFree(parser);
7905   free(mydata);
7906   if (result != XML_STATUS_ERROR)
7907     fail("Stopping the parser did not work as expected");
7908 }
7909 END_TEST
7910 
7911 START_TEST(test_misc_deny_internal_entity_closing_doctype_issue_317) {
7912   const char *const inputOne = "<!DOCTYPE d [\n"
7913                                "<!ENTITY % e ']><d/>'>\n"
7914                                "\n"
7915                                "%e;";
7916   const char *const inputTwo = "<!DOCTYPE d [\n"
7917                                "<!ENTITY % e1 ']><d/>'><!ENTITY % e2 '&e1;'>\n"
7918                                "\n"
7919                                "%e2;";
7920   const char *const inputThree = "<!DOCTYPE d [\n"
7921                                  "<!ENTITY % e ']><d'>\n"
7922                                  "\n"
7923                                  "%e;";
7924   const char *const inputIssue317 = "<!DOCTYPE doc [\n"
7925                                     "<!ENTITY % foo ']>\n"
7926                                     "<doc>Hell<oc (#PCDATA)*>'>\n"
7927                                     "%foo;\n"
7928                                     "]>\n"
7929                                     "<doc>Hello, world</dVc>";
7930 
7931   const char *const inputs[] = {inputOne, inputTwo, inputThree, inputIssue317};
7932   size_t inputIndex = 0;
7933 
7934   for (; inputIndex < sizeof(inputs) / sizeof(inputs[0]); inputIndex++) {
7935     XML_Parser parser;
7936     enum XML_Status parseResult;
7937     int setParamEntityResult;
7938     XML_Size lineNumber;
7939     XML_Size columnNumber;
7940     const char *const input = inputs[inputIndex];
7941 
7942     parser = XML_ParserCreate(NULL);
7943     setParamEntityResult
7944         = XML_SetParamEntityParsing(parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
7945     if (setParamEntityResult != 1)
7946       fail("Failed to set XML_PARAM_ENTITY_PARSING_ALWAYS.");
7947 
7948     parseResult = XML_Parse(parser, input, (int)strlen(input), 0);
7949     if (parseResult != XML_STATUS_ERROR) {
7950       parseResult = XML_Parse(parser, "", 0, 1);
7951       if (parseResult != XML_STATUS_ERROR) {
7952         fail("Parsing was expected to fail but succeeded.");
7953       }
7954     }
7955 
7956     if (XML_GetErrorCode(parser) != XML_ERROR_INVALID_TOKEN)
7957       fail("Error code does not match XML_ERROR_INVALID_TOKEN");
7958 
7959     lineNumber = XML_GetCurrentLineNumber(parser);
7960     if (lineNumber != 4)
7961       fail("XML_GetCurrentLineNumber does not work as expected.");
7962 
7963     columnNumber = XML_GetCurrentColumnNumber(parser);
7964     if (columnNumber != 0)
7965       fail("XML_GetCurrentColumnNumber does not work as expected.");
7966 
7967     XML_ParserFree(parser);
7968   }
7969 }
7970 END_TEST
7971 
7972 START_TEST(test_misc_tag_mismatch_reset_leak) {
7973 #ifdef XML_NS
7974   const char *const text = "<open xmlns='https://namespace1.test'></close>";
7975   XML_Parser parser = XML_ParserCreateNS(NULL, XCS('\n'));
7976 
7977   if (XML_Parse(parser, text, (int)strlen(text), XML_TRUE) != XML_STATUS_ERROR)
7978     fail("Call to parse was expected to fail");
7979   if (XML_GetErrorCode(parser) != XML_ERROR_TAG_MISMATCH)
7980     fail("Call to parse was expected to fail from a closing tag mismatch");
7981 
7982   XML_ParserReset(parser, NULL);
7983 
7984   if (XML_Parse(parser, text, (int)strlen(text), XML_TRUE) != XML_STATUS_ERROR)
7985     fail("Call to parse was expected to fail");
7986   if (XML_GetErrorCode(parser) != XML_ERROR_TAG_MISMATCH)
7987     fail("Call to parse was expected to fail from a closing tag mismatch");
7988 
7989   XML_ParserFree(parser);
7990 #endif
7991 }
7992 END_TEST
7993 
7994 static void
7995 alloc_setup(void) {
7996   XML_Memory_Handling_Suite memsuite = {duff_allocator, duff_reallocator, free};
7997 
7998   /* Ensure the parser creation will go through */
7999   allocation_count = ALLOC_ALWAYS_SUCCEED;
8000   reallocation_count = REALLOC_ALWAYS_SUCCEED;
8001   g_parser = XML_ParserCreate_MM(NULL, &memsuite, NULL);
8002   if (g_parser == NULL)
8003     fail("Parser not created");
8004 }
8005 
8006 static void
8007 alloc_teardown(void) {
8008   basic_teardown();
8009 }
8010 
8011 /* Test the effects of allocation failures on xml declaration processing */
8012 START_TEST(test_alloc_parse_xdecl) {
8013   const char *text = "<?xml version='1.0' encoding='utf-8'?>\n"
8014                      "<doc>Hello, world</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_SetXmlDeclHandler(g_parser, dummy_xdecl_handler);
8021     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
8022         != XML_STATUS_ERROR)
8023       break;
8024     /* Resetting the parser is insufficient, because some memory
8025      * allocations are cached within the parser.  Instead we use
8026      * the teardown and setup routines to ensure that we have the
8027      * right sort of parser back in our hands.
8028      */
8029     alloc_teardown();
8030     alloc_setup();
8031   }
8032   if (i == 0)
8033     fail("Parse succeeded despite failing allocator");
8034   if (i == max_alloc_count)
8035     fail("Parse failed with max allocations");
8036 }
8037 END_TEST
8038 
8039 /* As above, but with an encoding big enough to cause storing the
8040  * version information to expand the string pool being used.
8041  */
8042 static int XMLCALL
8043 long_encoding_handler(void *userData, const XML_Char *encoding,
8044                       XML_Encoding *info) {
8045   int i;
8046 
8047   UNUSED_P(userData);
8048   UNUSED_P(encoding);
8049   for (i = 0; i < 256; i++)
8050     info->map[i] = i;
8051   info->data = NULL;
8052   info->convert = NULL;
8053   info->release = NULL;
8054   return XML_STATUS_OK;
8055 }
8056 
8057 START_TEST(test_alloc_parse_xdecl_2) {
8058   const char *text
8059       = "<?xml version='1.0' encoding='"
8060         /* Each line is 64 characters */
8061         "ThisIsAStupidlyLongEncodingNameIntendedToTriggerPoolGrowth123456"
8062         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8063         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8064         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8065         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8066         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8067         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8068         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8069         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8070         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8071         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8072         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8073         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8074         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8075         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8076         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMN"
8077         "'?>"
8078         "<doc>Hello, world</doc>";
8079   int i;
8080   const int max_alloc_count = 20;
8081 
8082   for (i = 0; i < max_alloc_count; i++) {
8083     allocation_count = i;
8084     XML_SetXmlDeclHandler(g_parser, dummy_xdecl_handler);
8085     XML_SetUnknownEncodingHandler(g_parser, long_encoding_handler, NULL);
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 /* Test the effects of allocation failures on a straightforward parse */
8101 START_TEST(test_alloc_parse_pi) {
8102   const char *text = "<?xml version='1.0' encoding='utf-8'?>\n"
8103                      "<?pi unknown?>\n"
8104                      "<doc>"
8105                      "Hello, world"
8106                      "</doc>";
8107   int i;
8108   const int max_alloc_count = 15;
8109 
8110   for (i = 0; i < max_alloc_count; i++) {
8111     allocation_count = i;
8112     XML_SetProcessingInstructionHandler(g_parser, dummy_pi_handler);
8113     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
8114         != XML_STATUS_ERROR)
8115       break;
8116     /* See comment in test_alloc_parse_xdecl() */
8117     alloc_teardown();
8118     alloc_setup();
8119   }
8120   if (i == 0)
8121     fail("Parse succeeded despite failing allocator");
8122   if (i == max_alloc_count)
8123     fail("Parse failed with max allocations");
8124 }
8125 END_TEST
8126 
8127 START_TEST(test_alloc_parse_pi_2) {
8128   const char *text = "<?xml version='1.0' encoding='utf-8'?>\n"
8129                      "<doc>"
8130                      "Hello, world"
8131                      "<?pi unknown?>\n"
8132                      "</doc>";
8133   int i;
8134   const int max_alloc_count = 15;
8135 
8136   for (i = 0; i < max_alloc_count; i++) {
8137     allocation_count = i;
8138     XML_SetProcessingInstructionHandler(g_parser, dummy_pi_handler);
8139     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
8140         != XML_STATUS_ERROR)
8141       break;
8142     /* See comment in test_alloc_parse_xdecl() */
8143     alloc_teardown();
8144     alloc_setup();
8145   }
8146   if (i == 0)
8147     fail("Parse succeeded despite failing allocator");
8148   if (i == max_alloc_count)
8149     fail("Parse failed with max allocations");
8150 }
8151 END_TEST
8152 
8153 START_TEST(test_alloc_parse_pi_3) {
8154   const char *text
8155       = "<?"
8156         /* 64 characters per line */
8157         "This processing instruction should be long enough to ensure that"
8158         "it triggers the growth of an internal string pool when the      "
8159         "allocator fails at a cruicial moment FGHIJKLMNOPABCDEFGHIJKLMNOP"
8160         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8161         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8162         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8163         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8164         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8165         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8166         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8167         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8168         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8169         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8170         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8171         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8172         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8173         "Q?><doc/>";
8174   int i;
8175   const int max_alloc_count = 20;
8176 
8177   for (i = 0; i < max_alloc_count; i++) {
8178     allocation_count = i;
8179     XML_SetProcessingInstructionHandler(g_parser, dummy_pi_handler);
8180     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
8181         != XML_STATUS_ERROR)
8182       break;
8183     /* See comment in test_alloc_parse_xdecl() */
8184     alloc_teardown();
8185     alloc_setup();
8186   }
8187   if (i == 0)
8188     fail("Parse succeeded despite failing allocator");
8189   if (i == max_alloc_count)
8190     fail("Parse failed with max allocations");
8191 }
8192 END_TEST
8193 
8194 START_TEST(test_alloc_parse_comment) {
8195   const char *text = "<?xml version='1.0' encoding='utf-8'?>\n"
8196                      "<!-- Test parsing this comment -->"
8197                      "<doc>Hi</doc>";
8198   int i;
8199   const int max_alloc_count = 15;
8200 
8201   for (i = 0; i < max_alloc_count; i++) {
8202     allocation_count = i;
8203     XML_SetCommentHandler(g_parser, dummy_comment_handler);
8204     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
8205         != XML_STATUS_ERROR)
8206       break;
8207     /* See comment in test_alloc_parse_xdecl() */
8208     alloc_teardown();
8209     alloc_setup();
8210   }
8211   if (i == 0)
8212     fail("Parse succeeded despite failing allocator");
8213   if (i == max_alloc_count)
8214     fail("Parse failed with max allocations");
8215 }
8216 END_TEST
8217 
8218 START_TEST(test_alloc_parse_comment_2) {
8219   const char *text = "<?xml version='1.0' encoding='utf-8'?>\n"
8220                      "<doc>"
8221                      "Hello, world"
8222                      "<!-- Parse this comment too -->"
8223                      "</doc>";
8224   int i;
8225   const int max_alloc_count = 15;
8226 
8227   for (i = 0; i < max_alloc_count; i++) {
8228     allocation_count = i;
8229     XML_SetCommentHandler(g_parser, dummy_comment_handler);
8230     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
8231         != XML_STATUS_ERROR)
8232       break;
8233     /* See comment in test_alloc_parse_xdecl() */
8234     alloc_teardown();
8235     alloc_setup();
8236   }
8237   if (i == 0)
8238     fail("Parse succeeded despite failing allocator");
8239   if (i == max_alloc_count)
8240     fail("Parse failed with max allocations");
8241 }
8242 END_TEST
8243 
8244 static int XMLCALL
8245 external_entity_duff_loader(XML_Parser parser, const XML_Char *context,
8246                             const XML_Char *base, const XML_Char *systemId,
8247                             const XML_Char *publicId) {
8248   XML_Parser new_parser;
8249   unsigned int i;
8250   const unsigned int max_alloc_count = 10;
8251 
8252   UNUSED_P(base);
8253   UNUSED_P(systemId);
8254   UNUSED_P(publicId);
8255   /* Try a few different allocation levels */
8256   for (i = 0; i < max_alloc_count; i++) {
8257     allocation_count = i;
8258     new_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
8259     if (new_parser != NULL) {
8260       XML_ParserFree(new_parser);
8261       break;
8262     }
8263   }
8264   if (i == 0)
8265     fail("External parser creation ignored failing allocator");
8266   else if (i == max_alloc_count)
8267     fail("Extern parser not created with max allocation count");
8268 
8269   /* Make sure other random allocation doesn't now fail */
8270   allocation_count = ALLOC_ALWAYS_SUCCEED;
8271 
8272   /* Make sure the failure code path is executed too */
8273   return XML_STATUS_ERROR;
8274 }
8275 
8276 /* Test that external parser creation running out of memory is
8277  * correctly reported.  Based on the external entity test cases.
8278  */
8279 START_TEST(test_alloc_create_external_parser) {
8280   const char *text = "<?xml version='1.0' encoding='us-ascii'?>\n"
8281                      "<!DOCTYPE doc SYSTEM 'foo'>\n"
8282                      "<doc>&entity;</doc>";
8283   char foo_text[] = "<!ELEMENT doc (#PCDATA)*>";
8284 
8285   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
8286   XML_SetUserData(g_parser, foo_text);
8287   XML_SetExternalEntityRefHandler(g_parser, external_entity_duff_loader);
8288   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
8289       != XML_STATUS_ERROR) {
8290     fail("External parser allocator returned success incorrectly");
8291   }
8292 }
8293 END_TEST
8294 
8295 /* More external parser memory allocation testing */
8296 START_TEST(test_alloc_run_external_parser) {
8297   const char *text = "<?xml version='1.0' encoding='us-ascii'?>\n"
8298                      "<!DOCTYPE doc SYSTEM 'foo'>\n"
8299                      "<doc>&entity;</doc>";
8300   char foo_text[] = "<!ELEMENT doc (#PCDATA)*>";
8301   unsigned int i;
8302   const unsigned int max_alloc_count = 15;
8303 
8304   for (i = 0; i < max_alloc_count; i++) {
8305     XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
8306     XML_SetUserData(g_parser, foo_text);
8307     XML_SetExternalEntityRefHandler(g_parser, external_entity_null_loader);
8308     allocation_count = i;
8309     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
8310         != XML_STATUS_ERROR)
8311       break;
8312     /* See comment in test_alloc_parse_xdecl() */
8313     alloc_teardown();
8314     alloc_setup();
8315   }
8316   if (i == 0)
8317     fail("Parsing ignored failing allocator");
8318   else if (i == max_alloc_count)
8319     fail("Parsing failed with allocation count 10");
8320 }
8321 END_TEST
8322 
8323 static int XMLCALL
8324 external_entity_dbl_handler(XML_Parser parser, const XML_Char *context,
8325                             const XML_Char *base, const XML_Char *systemId,
8326                             const XML_Char *publicId) {
8327   intptr_t callno = (intptr_t)XML_GetUserData(parser);
8328   const char *text;
8329   XML_Parser new_parser;
8330   int i;
8331   const int max_alloc_count = 20;
8332 
8333   UNUSED_P(base);
8334   UNUSED_P(systemId);
8335   UNUSED_P(publicId);
8336   if (callno == 0) {
8337     /* First time through, check how many calls to malloc occur */
8338     text = ("<!ELEMENT doc (e+)>\n"
8339             "<!ATTLIST doc xmlns CDATA #IMPLIED>\n"
8340             "<!ELEMENT e EMPTY>\n");
8341     allocation_count = 10000;
8342     new_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
8343     if (new_parser == NULL) {
8344       fail("Unable to allocate first external parser");
8345       return XML_STATUS_ERROR;
8346     }
8347     /* Stash the number of calls in the user data */
8348     XML_SetUserData(parser, (void *)(intptr_t)(10000 - allocation_count));
8349   } else {
8350     text = ("<?xml version='1.0' encoding='us-ascii'?>"
8351             "<e/>");
8352     /* Try at varying levels to exercise more code paths */
8353     for (i = 0; i < max_alloc_count; i++) {
8354       allocation_count = callno + i;
8355       new_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
8356       if (new_parser != NULL)
8357         break;
8358     }
8359     if (i == 0) {
8360       fail("Second external parser unexpectedly created");
8361       XML_ParserFree(new_parser);
8362       return XML_STATUS_ERROR;
8363     } else if (i == max_alloc_count) {
8364       fail("Second external parser not created");
8365       return XML_STATUS_ERROR;
8366     }
8367   }
8368 
8369   allocation_count = ALLOC_ALWAYS_SUCCEED;
8370   if (_XML_Parse_SINGLE_BYTES(new_parser, text, (int)strlen(text), XML_TRUE)
8371       == XML_STATUS_ERROR) {
8372     xml_failure(new_parser);
8373     return XML_STATUS_ERROR;
8374   }
8375   XML_ParserFree(new_parser);
8376   return XML_STATUS_OK;
8377 }
8378 
8379 /* Test that running out of memory in dtdCopy is correctly reported.
8380  * Based on test_default_ns_from_ext_subset_and_ext_ge()
8381  */
8382 START_TEST(test_alloc_dtd_copy_default_atts) {
8383   const char *text = "<?xml version='1.0'?>\n"
8384                      "<!DOCTYPE doc SYSTEM 'http://example.org/doc.dtd' [\n"
8385                      "  <!ENTITY en SYSTEM 'http://example.org/entity.ent'>\n"
8386                      "]>\n"
8387                      "<doc xmlns='http://example.org/ns1'>\n"
8388                      "&en;\n"
8389                      "</doc>";
8390 
8391   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
8392   XML_SetExternalEntityRefHandler(g_parser, external_entity_dbl_handler);
8393   XML_SetUserData(g_parser, NULL);
8394   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
8395       == XML_STATUS_ERROR)
8396     xml_failure(g_parser);
8397 }
8398 END_TEST
8399 
8400 static int XMLCALL
8401 external_entity_dbl_handler_2(XML_Parser parser, const XML_Char *context,
8402                               const XML_Char *base, const XML_Char *systemId,
8403                               const XML_Char *publicId) {
8404   intptr_t callno = (intptr_t)XML_GetUserData(parser);
8405   const char *text;
8406   XML_Parser new_parser;
8407   enum XML_Status rv;
8408 
8409   UNUSED_P(base);
8410   UNUSED_P(systemId);
8411   UNUSED_P(publicId);
8412   if (callno == 0) {
8413     /* Try different allocation levels for whole exercise */
8414     text = ("<!ELEMENT doc (e+)>\n"
8415             "<!ATTLIST doc xmlns CDATA #IMPLIED>\n"
8416             "<!ELEMENT e EMPTY>\n");
8417     XML_SetUserData(parser, (void *)(intptr_t)1);
8418     new_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
8419     if (new_parser == NULL)
8420       return XML_STATUS_ERROR;
8421     rv = _XML_Parse_SINGLE_BYTES(new_parser, text, (int)strlen(text), XML_TRUE);
8422   } else {
8423     /* Just run through once */
8424     text = ("<?xml version='1.0' encoding='us-ascii'?>"
8425             "<e/>");
8426     new_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
8427     if (new_parser == NULL)
8428       return XML_STATUS_ERROR;
8429     rv = _XML_Parse_SINGLE_BYTES(new_parser, text, (int)strlen(text), XML_TRUE);
8430   }
8431   XML_ParserFree(new_parser);
8432   if (rv == XML_STATUS_ERROR)
8433     return XML_STATUS_ERROR;
8434   return XML_STATUS_OK;
8435 }
8436 
8437 /* Test more external entity allocation failure paths */
8438 START_TEST(test_alloc_external_entity) {
8439   const char *text = "<?xml version='1.0'?>\n"
8440                      "<!DOCTYPE doc SYSTEM 'http://example.org/doc.dtd' [\n"
8441                      "  <!ENTITY en SYSTEM 'http://example.org/entity.ent'>\n"
8442                      "]>\n"
8443                      "<doc xmlns='http://example.org/ns1'>\n"
8444                      "&en;\n"
8445                      "</doc>";
8446   int i;
8447   const int alloc_test_max_repeats = 50;
8448 
8449   for (i = 0; i < alloc_test_max_repeats; i++) {
8450     allocation_count = -1;
8451     XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
8452     XML_SetExternalEntityRefHandler(g_parser, external_entity_dbl_handler_2);
8453     XML_SetUserData(g_parser, NULL);
8454     allocation_count = i;
8455     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
8456         == XML_STATUS_OK)
8457       break;
8458     /* See comment in test_alloc_parse_xdecl() */
8459     alloc_teardown();
8460     alloc_setup();
8461   }
8462   allocation_count = -1;
8463   if (i == 0)
8464     fail("External entity parsed despite duff allocator");
8465   if (i == alloc_test_max_repeats)
8466     fail("External entity not parsed at max allocation count");
8467 }
8468 END_TEST
8469 
8470 /* Test more allocation failure paths */
8471 static int XMLCALL
8472 external_entity_alloc_set_encoding(XML_Parser parser, const XML_Char *context,
8473                                    const XML_Char *base,
8474                                    const XML_Char *systemId,
8475                                    const XML_Char *publicId) {
8476   /* As for external_entity_loader() */
8477   const char *text = "<?xml encoding='iso-8859-3'?>"
8478                      "\xC3\xA9";
8479   XML_Parser ext_parser;
8480   enum XML_Status status;
8481 
8482   UNUSED_P(base);
8483   UNUSED_P(systemId);
8484   UNUSED_P(publicId);
8485   ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
8486   if (ext_parser == NULL)
8487     return XML_STATUS_ERROR;
8488   if (! XML_SetEncoding(ext_parser, XCS("utf-8"))) {
8489     XML_ParserFree(ext_parser);
8490     return XML_STATUS_ERROR;
8491   }
8492   status
8493       = _XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE);
8494   XML_ParserFree(ext_parser);
8495   if (status == XML_STATUS_ERROR)
8496     return XML_STATUS_ERROR;
8497   return XML_STATUS_OK;
8498 }
8499 
8500 START_TEST(test_alloc_ext_entity_set_encoding) {
8501   const char *text = "<!DOCTYPE doc [\n"
8502                      "  <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n"
8503                      "]>\n"
8504                      "<doc>&en;</doc>";
8505   int i;
8506   const int max_allocation_count = 30;
8507 
8508   for (i = 0; i < max_allocation_count; i++) {
8509     XML_SetExternalEntityRefHandler(g_parser,
8510                                     external_entity_alloc_set_encoding);
8511     allocation_count = i;
8512     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
8513         == XML_STATUS_OK)
8514       break;
8515     allocation_count = -1;
8516     /* See comment in test_alloc_parse_xdecl() */
8517     alloc_teardown();
8518     alloc_setup();
8519   }
8520   if (i == 0)
8521     fail("Encoding check succeeded despite failing allocator");
8522   if (i == max_allocation_count)
8523     fail("Encoding failed at max allocation count");
8524 }
8525 END_TEST
8526 
8527 static int XMLCALL
8528 unknown_released_encoding_handler(void *data, const XML_Char *encoding,
8529                                   XML_Encoding *info) {
8530   UNUSED_P(data);
8531   if (! xcstrcmp(encoding, XCS("unsupported-encoding"))) {
8532     int i;
8533 
8534     for (i = 0; i < 256; i++)
8535       info->map[i] = i;
8536     info->data = NULL;
8537     info->convert = NULL;
8538     info->release = dummy_release;
8539     return XML_STATUS_OK;
8540   }
8541   return XML_STATUS_ERROR;
8542 }
8543 
8544 /* Test the effects of allocation failure in internal entities.
8545  * Based on test_unknown_encoding_internal_entity
8546  */
8547 START_TEST(test_alloc_internal_entity) {
8548   const char *text = "<?xml version='1.0' encoding='unsupported-encoding'?>\n"
8549                      "<!DOCTYPE test [<!ENTITY foo 'bar'>]>\n"
8550                      "<test a='&foo;'/>";
8551   unsigned int i;
8552   const unsigned int max_alloc_count = 20;
8553 
8554   for (i = 0; i < max_alloc_count; i++) {
8555     allocation_count = i;
8556     XML_SetUnknownEncodingHandler(g_parser, unknown_released_encoding_handler,
8557                                   NULL);
8558     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
8559         != XML_STATUS_ERROR)
8560       break;
8561     /* See comment in test_alloc_parse_xdecl() */
8562     alloc_teardown();
8563     alloc_setup();
8564   }
8565   if (i == 0)
8566     fail("Internal entity worked despite failing allocations");
8567   else if (i == max_alloc_count)
8568     fail("Internal entity failed at max allocation count");
8569 }
8570 END_TEST
8571 
8572 /* Test the robustness against allocation failure of element handling
8573  * Based on test_dtd_default_handling().
8574  */
8575 START_TEST(test_alloc_dtd_default_handling) {
8576   const char *text = "<!DOCTYPE doc [\n"
8577                      "<!ENTITY e SYSTEM 'http://example.org/e'>\n"
8578                      "<!NOTATION n SYSTEM 'http://example.org/n'>\n"
8579                      "<!ENTITY e1 SYSTEM 'http://example.org/e' NDATA n>\n"
8580                      "<!ELEMENT doc (#PCDATA)>\n"
8581                      "<!ATTLIST doc a CDATA #IMPLIED>\n"
8582                      "<?pi in dtd?>\n"
8583                      "<!--comment in dtd-->\n"
8584                      "]>\n"
8585                      "<doc><![CDATA[text in doc]]></doc>";
8586   const XML_Char *expected = XCS("\n\n\n\n\n\n\n\n\n<doc>text in doc</doc>");
8587   CharData storage;
8588   int i;
8589   const int max_alloc_count = 25;
8590 
8591   for (i = 0; i < max_alloc_count; i++) {
8592     allocation_count = i;
8593     dummy_handler_flags = 0;
8594     XML_SetDefaultHandler(g_parser, accumulate_characters);
8595     XML_SetDoctypeDeclHandler(g_parser, dummy_start_doctype_handler,
8596                               dummy_end_doctype_handler);
8597     XML_SetEntityDeclHandler(g_parser, dummy_entity_decl_handler);
8598     XML_SetNotationDeclHandler(g_parser, dummy_notation_decl_handler);
8599     XML_SetElementDeclHandler(g_parser, dummy_element_decl_handler);
8600     XML_SetAttlistDeclHandler(g_parser, dummy_attlist_decl_handler);
8601     XML_SetProcessingInstructionHandler(g_parser, dummy_pi_handler);
8602     XML_SetCommentHandler(g_parser, dummy_comment_handler);
8603     XML_SetCdataSectionHandler(g_parser, dummy_start_cdata_handler,
8604                                dummy_end_cdata_handler);
8605     XML_SetUnparsedEntityDeclHandler(g_parser,
8606                                      dummy_unparsed_entity_decl_handler);
8607     CharData_Init(&storage);
8608     XML_SetUserData(g_parser, &storage);
8609     XML_SetCharacterDataHandler(g_parser, accumulate_characters);
8610     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
8611         != XML_STATUS_ERROR)
8612       break;
8613     /* See comment in test_alloc_parse_xdecl() */
8614     alloc_teardown();
8615     alloc_setup();
8616   }
8617   if (i == 0)
8618     fail("Default DTD parsed despite allocation failures");
8619   if (i == max_alloc_count)
8620     fail("Default DTD not parsed with maximum alloc count");
8621   CharData_CheckXMLChars(&storage, expected);
8622   if (dummy_handler_flags
8623       != (DUMMY_START_DOCTYPE_HANDLER_FLAG | DUMMY_END_DOCTYPE_HANDLER_FLAG
8624           | DUMMY_ENTITY_DECL_HANDLER_FLAG | DUMMY_NOTATION_DECL_HANDLER_FLAG
8625           | DUMMY_ELEMENT_DECL_HANDLER_FLAG | DUMMY_ATTLIST_DECL_HANDLER_FLAG
8626           | DUMMY_COMMENT_HANDLER_FLAG | DUMMY_PI_HANDLER_FLAG
8627           | DUMMY_START_CDATA_HANDLER_FLAG | DUMMY_END_CDATA_HANDLER_FLAG
8628           | DUMMY_UNPARSED_ENTITY_DECL_HANDLER_FLAG))
8629     fail("Not all handlers were called");
8630 }
8631 END_TEST
8632 
8633 /* Test robustness of XML_SetEncoding() with a failing allocator */
8634 START_TEST(test_alloc_explicit_encoding) {
8635   int i;
8636   const int max_alloc_count = 5;
8637 
8638   for (i = 0; i < max_alloc_count; i++) {
8639     allocation_count = i;
8640     if (XML_SetEncoding(g_parser, XCS("us-ascii")) == XML_STATUS_OK)
8641       break;
8642   }
8643   if (i == 0)
8644     fail("Encoding set despite failing allocator");
8645   else if (i == max_alloc_count)
8646     fail("Encoding not set at max allocation count");
8647 }
8648 END_TEST
8649 
8650 /* Test robustness of XML_SetBase against a failing allocator */
8651 START_TEST(test_alloc_set_base) {
8652   const XML_Char *new_base = XCS("/local/file/name.xml");
8653   int i;
8654   const int max_alloc_count = 5;
8655 
8656   for (i = 0; i < max_alloc_count; i++) {
8657     allocation_count = i;
8658     if (XML_SetBase(g_parser, new_base) == XML_STATUS_OK)
8659       break;
8660   }
8661   if (i == 0)
8662     fail("Base set despite failing allocator");
8663   else if (i == max_alloc_count)
8664     fail("Base not set with max allocation count");
8665 }
8666 END_TEST
8667 
8668 /* Test buffer extension in the face of a duff reallocator */
8669 START_TEST(test_alloc_realloc_buffer) {
8670   const char *text = get_buffer_test_text;
8671   void *buffer;
8672   int i;
8673   const int max_realloc_count = 10;
8674 
8675   /* Get a smallish buffer */
8676   for (i = 0; i < max_realloc_count; i++) {
8677     reallocation_count = i;
8678     buffer = XML_GetBuffer(g_parser, 1536);
8679     if (buffer == NULL)
8680       fail("1.5K buffer reallocation failed");
8681     assert(buffer != NULL);
8682     memcpy(buffer, text, strlen(text));
8683     if (XML_ParseBuffer(g_parser, (int)strlen(text), XML_FALSE)
8684         == XML_STATUS_OK)
8685       break;
8686     /* See comment in test_alloc_parse_xdecl() */
8687     alloc_teardown();
8688     alloc_setup();
8689   }
8690   reallocation_count = -1;
8691   if (i == 0)
8692     fail("Parse succeeded with no reallocation");
8693   else if (i == max_realloc_count)
8694     fail("Parse failed with max reallocation count");
8695 }
8696 END_TEST
8697 
8698 /* Same test for external entity parsers */
8699 static int XMLCALL
8700 external_entity_reallocator(XML_Parser parser, const XML_Char *context,
8701                             const XML_Char *base, const XML_Char *systemId,
8702                             const XML_Char *publicId) {
8703   const char *text = get_buffer_test_text;
8704   XML_Parser ext_parser;
8705   void *buffer;
8706   enum XML_Status status;
8707 
8708   UNUSED_P(base);
8709   UNUSED_P(systemId);
8710   UNUSED_P(publicId);
8711   ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
8712   if (ext_parser == NULL)
8713     fail("Could not create external entity parser");
8714 
8715   reallocation_count = (intptr_t)XML_GetUserData(parser);
8716   buffer = XML_GetBuffer(ext_parser, 1536);
8717   if (buffer == NULL)
8718     fail("Buffer allocation failed");
8719   assert(buffer != NULL);
8720   memcpy(buffer, text, strlen(text));
8721   status = XML_ParseBuffer(ext_parser, (int)strlen(text), XML_FALSE);
8722   reallocation_count = -1;
8723   XML_ParserFree(ext_parser);
8724   return (status == XML_STATUS_OK) ? XML_STATUS_OK : XML_STATUS_ERROR;
8725 }
8726 
8727 START_TEST(test_alloc_ext_entity_realloc_buffer) {
8728   const char *text = "<!DOCTYPE doc [\n"
8729                      "  <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n"
8730                      "]>\n"
8731                      "<doc>&en;</doc>";
8732   int i;
8733   const int max_realloc_count = 10;
8734 
8735   for (i = 0; i < max_realloc_count; i++) {
8736     XML_SetExternalEntityRefHandler(g_parser, external_entity_reallocator);
8737     XML_SetUserData(g_parser, (void *)(intptr_t)i);
8738     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
8739         == XML_STATUS_OK)
8740       break;
8741     /* See comment in test_alloc_parse_xdecl() */
8742     alloc_teardown();
8743     alloc_setup();
8744   }
8745   if (i == 0)
8746     fail("Succeeded with no reallocations");
8747   if (i == max_realloc_count)
8748     fail("Failed with max reallocations");
8749 }
8750 END_TEST
8751 
8752 /* Test elements with many attributes are handled correctly */
8753 START_TEST(test_alloc_realloc_many_attributes) {
8754   const char *text = "<!DOCTYPE doc [\n"
8755                      "<!ATTLIST doc za CDATA 'default'>\n"
8756                      "<!ATTLIST doc zb CDATA 'def2'>\n"
8757                      "<!ATTLIST doc zc CDATA 'def3'>\n"
8758                      "]>\n"
8759                      "<doc a='1'"
8760                      "     b='2'"
8761                      "     c='3'"
8762                      "     d='4'"
8763                      "     e='5'"
8764                      "     f='6'"
8765                      "     g='7'"
8766                      "     h='8'"
8767                      "     i='9'"
8768                      "     j='10'"
8769                      "     k='11'"
8770                      "     l='12'"
8771                      "     m='13'"
8772                      "     n='14'"
8773                      "     p='15'"
8774                      "     q='16'"
8775                      "     r='17'"
8776                      "     s='18'>"
8777                      "</doc>";
8778   int i;
8779   const int max_realloc_count = 10;
8780 
8781   for (i = 0; i < max_realloc_count; i++) {
8782     reallocation_count = i;
8783     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
8784         != XML_STATUS_ERROR)
8785       break;
8786     /* See comment in test_alloc_parse_xdecl() */
8787     alloc_teardown();
8788     alloc_setup();
8789   }
8790   if (i == 0)
8791     fail("Parse succeeded despite no reallocations");
8792   if (i == max_realloc_count)
8793     fail("Parse failed at max reallocations");
8794 }
8795 END_TEST
8796 
8797 /* Test handling of a public entity with failing allocator */
8798 START_TEST(test_alloc_public_entity_value) {
8799   const char *text = "<!DOCTYPE doc SYSTEM 'http://example.org/'>\n"
8800                      "<doc></doc>\n";
8801   char dtd_text[]
8802       = "<!ELEMENT doc EMPTY>\n"
8803         "<!ENTITY % e1 PUBLIC 'foo' 'bar.ent'>\n"
8804         "<!ENTITY % "
8805         /* Each line is 64 characters */
8806         "ThisIsAStupidlyLongParameterNameIntendedToTriggerPoolGrowth12345"
8807         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8808         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8809         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8810         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8811         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8812         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8813         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8814         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8815         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8816         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8817         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8818         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8819         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8820         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8821         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8822         " '%e1;'>\n"
8823         "%e1;\n";
8824   int i;
8825   const int max_alloc_count = 50;
8826 
8827   for (i = 0; i < max_alloc_count; i++) {
8828     allocation_count = i;
8829     dummy_handler_flags = 0;
8830     XML_SetUserData(g_parser, dtd_text);
8831     XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
8832     XML_SetExternalEntityRefHandler(g_parser, external_entity_public);
8833     /* Provoke a particular code path */
8834     XML_SetEntityDeclHandler(g_parser, dummy_entity_decl_handler);
8835     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
8836         != XML_STATUS_ERROR)
8837       break;
8838     /* See comment in test_alloc_parse_xdecl() */
8839     alloc_teardown();
8840     alloc_setup();
8841   }
8842   if (i == 0)
8843     fail("Parsing worked despite failing allocation");
8844   if (i == max_alloc_count)
8845     fail("Parsing failed at max allocation count");
8846   if (dummy_handler_flags != DUMMY_ENTITY_DECL_HANDLER_FLAG)
8847     fail("Entity declaration handler not called");
8848 }
8849 END_TEST
8850 
8851 START_TEST(test_alloc_realloc_subst_public_entity_value) {
8852   const char *text = "<!DOCTYPE doc SYSTEM 'http://example.org/'>\n"
8853                      "<doc></doc>\n";
8854   char dtd_text[]
8855       = "<!ELEMENT doc EMPTY>\n"
8856         "<!ENTITY % "
8857         /* Each line is 64 characters */
8858         "ThisIsAStupidlyLongParameterNameIntendedToTriggerPoolGrowth12345"
8859         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8860         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8861         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8862         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8863         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8864         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8865         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8866         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8867         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8868         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8869         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8870         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8871         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8872         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8873         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8874         " PUBLIC 'foo' 'bar.ent'>\n"
8875         "%ThisIsAStupidlyLongParameterNameIntendedToTriggerPoolGrowth12345"
8876         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8877         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8878         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8879         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8880         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8881         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8882         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8883         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8884         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8885         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8886         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8887         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8888         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8889         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8890         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP;";
8891   int i;
8892   const int max_realloc_count = 10;
8893 
8894   for (i = 0; i < max_realloc_count; i++) {
8895     reallocation_count = i;
8896     XML_SetUserData(g_parser, dtd_text);
8897     XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
8898     XML_SetExternalEntityRefHandler(g_parser, external_entity_public);
8899     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
8900         != XML_STATUS_ERROR)
8901       break;
8902     /* See comment in test_alloc_parse_xdecl() */
8903     alloc_teardown();
8904     alloc_setup();
8905   }
8906   if (i == 0)
8907     fail("Parsing worked despite failing reallocation");
8908   if (i == max_realloc_count)
8909     fail("Parsing failed at max reallocation count");
8910 }
8911 END_TEST
8912 
8913 START_TEST(test_alloc_parse_public_doctype) {
8914   const char *text
8915       = "<?xml version='1.0' encoding='utf-8'?>\n"
8916         "<!DOCTYPE doc PUBLIC '"
8917         /* 64 characters per line */
8918         "http://example.com/a/long/enough/name/to/trigger/pool/growth/zz/"
8919         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8920         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8921         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8922         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8923         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8924         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8925         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8926         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8927         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8928         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8929         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8930         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8931         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8932         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8933         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8934         "' 'test'>\n"
8935         "<doc></doc>";
8936   int i;
8937   const int max_alloc_count = 25;
8938 
8939   for (i = 0; i < max_alloc_count; i++) {
8940     allocation_count = i;
8941     dummy_handler_flags = 0;
8942     XML_SetDoctypeDeclHandler(g_parser, dummy_start_doctype_decl_handler,
8943                               dummy_end_doctype_decl_handler);
8944     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
8945         != XML_STATUS_ERROR)
8946       break;
8947     /* See comment in test_alloc_parse_xdecl() */
8948     alloc_teardown();
8949     alloc_setup();
8950   }
8951   if (i == 0)
8952     fail("Parse succeeded despite failing allocator");
8953   if (i == max_alloc_count)
8954     fail("Parse failed at maximum allocation count");
8955   if (dummy_handler_flags
8956       != (DUMMY_START_DOCTYPE_DECL_HANDLER_FLAG
8957           | DUMMY_END_DOCTYPE_DECL_HANDLER_FLAG))
8958     fail("Doctype handler functions not called");
8959 }
8960 END_TEST
8961 
8962 START_TEST(test_alloc_parse_public_doctype_long_name) {
8963   const char *text
8964       = "<?xml version='1.0' encoding='utf-8'?>\n"
8965         "<!DOCTYPE doc PUBLIC 'http://example.com/foo' '"
8966         /* 64 characters per line */
8967         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP"
8968         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP"
8969         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP"
8970         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP"
8971         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP"
8972         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP"
8973         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP"
8974         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP"
8975         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP"
8976         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP"
8977         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP"
8978         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP"
8979         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP"
8980         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP"
8981         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP"
8982         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP"
8983         "'>\n"
8984         "<doc></doc>";
8985   int i;
8986   const int max_alloc_count = 25;
8987 
8988   for (i = 0; i < max_alloc_count; i++) {
8989     allocation_count = i;
8990     XML_SetDoctypeDeclHandler(g_parser, dummy_start_doctype_decl_handler,
8991                               dummy_end_doctype_decl_handler);
8992     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
8993         != XML_STATUS_ERROR)
8994       break;
8995     /* See comment in test_alloc_parse_xdecl() */
8996     alloc_teardown();
8997     alloc_setup();
8998   }
8999   if (i == 0)
9000     fail("Parse succeeded despite failing allocator");
9001   if (i == max_alloc_count)
9002     fail("Parse failed at maximum allocation count");
9003 }
9004 END_TEST
9005 
9006 static int XMLCALL
9007 external_entity_alloc(XML_Parser parser, const XML_Char *context,
9008                       const XML_Char *base, const XML_Char *systemId,
9009                       const XML_Char *publicId) {
9010   const char *text = (const char *)XML_GetUserData(parser);
9011   XML_Parser ext_parser;
9012   int parse_res;
9013 
9014   UNUSED_P(base);
9015   UNUSED_P(systemId);
9016   UNUSED_P(publicId);
9017   ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
9018   if (ext_parser == NULL)
9019     return XML_STATUS_ERROR;
9020   parse_res
9021       = _XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE);
9022   XML_ParserFree(ext_parser);
9023   return parse_res;
9024 }
9025 
9026 /* Test foreign DTD handling */
9027 START_TEST(test_alloc_set_foreign_dtd) {
9028   const char *text1 = "<?xml version='1.0' encoding='us-ascii'?>\n"
9029                       "<doc>&entity;</doc>";
9030   char text2[] = "<!ELEMENT doc (#PCDATA)*>";
9031   int i;
9032   const int max_alloc_count = 25;
9033 
9034   for (i = 0; i < max_alloc_count; i++) {
9035     allocation_count = i;
9036     XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
9037     XML_SetUserData(g_parser, &text2);
9038     XML_SetExternalEntityRefHandler(g_parser, external_entity_alloc);
9039     if (XML_UseForeignDTD(g_parser, XML_TRUE) != XML_ERROR_NONE)
9040       fail("Could not set foreign DTD");
9041     if (_XML_Parse_SINGLE_BYTES(g_parser, text1, (int)strlen(text1), XML_TRUE)
9042         != XML_STATUS_ERROR)
9043       break;
9044     /* See comment in test_alloc_parse_xdecl() */
9045     alloc_teardown();
9046     alloc_setup();
9047   }
9048   if (i == 0)
9049     fail("Parse succeeded despite failing allocator");
9050   if (i == max_alloc_count)
9051     fail("Parse failed at maximum allocation count");
9052 }
9053 END_TEST
9054 
9055 /* Test based on ibm/valid/P32/ibm32v04.xml */
9056 START_TEST(test_alloc_attribute_enum_value) {
9057   const char *text = "<?xml version='1.0' standalone='no'?>\n"
9058                      "<!DOCTYPE animal SYSTEM 'test.dtd'>\n"
9059                      "<animal>This is a \n    <a/>  \n\nyellow tiger</animal>";
9060   char dtd_text[] = "<!ELEMENT animal (#PCDATA|a)*>\n"
9061                     "<!ELEMENT a EMPTY>\n"
9062                     "<!ATTLIST animal xml:space (default|preserve) 'preserve'>";
9063   int i;
9064   const int max_alloc_count = 30;
9065 
9066   for (i = 0; i < max_alloc_count; i++) {
9067     allocation_count = i;
9068     XML_SetExternalEntityRefHandler(g_parser, external_entity_alloc);
9069     XML_SetUserData(g_parser, dtd_text);
9070     XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
9071     /* An attribute list handler provokes a different code path */
9072     XML_SetAttlistDeclHandler(g_parser, dummy_attlist_decl_handler);
9073     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
9074         != XML_STATUS_ERROR)
9075       break;
9076     /* See comment in test_alloc_parse_xdecl() */
9077     alloc_teardown();
9078     alloc_setup();
9079   }
9080   if (i == 0)
9081     fail("Parse succeeded despite failing allocator");
9082   if (i == max_alloc_count)
9083     fail("Parse failed at maximum allocation count");
9084 }
9085 END_TEST
9086 
9087 /* Test attribute enums sufficient to overflow the string pool */
9088 START_TEST(test_alloc_realloc_attribute_enum_value) {
9089   const char *text = "<?xml version='1.0' standalone='no'?>\n"
9090                      "<!DOCTYPE animal SYSTEM 'test.dtd'>\n"
9091                      "<animal>This is a yellow tiger</animal>";
9092   /* We wish to define a collection of attribute enums that will
9093    * cause the string pool storing them to have to expand.  This
9094    * means more than 1024 bytes, including the parentheses and
9095    * separator bars.
9096    */
9097   char dtd_text[]
9098       = "<!ELEMENT animal (#PCDATA)*>\n"
9099         "<!ATTLIST animal thing "
9100         "(default"
9101         /* Each line is 64 characters */
9102         "|ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
9103         "|BBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
9104         "|CBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
9105         "|DBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
9106         "|EBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
9107         "|FBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
9108         "|GBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
9109         "|HBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
9110         "|IBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
9111         "|JBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
9112         "|KBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
9113         "|LBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
9114         "|MBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
9115         "|NBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
9116         "|OBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
9117         "|PBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO)"
9118         " 'default'>";
9119   int i;
9120   const int max_realloc_count = 10;
9121 
9122   for (i = 0; i < max_realloc_count; i++) {
9123     reallocation_count = i;
9124     XML_SetExternalEntityRefHandler(g_parser, external_entity_alloc);
9125     XML_SetUserData(g_parser, dtd_text);
9126     XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
9127     /* An attribute list handler provokes a different code path */
9128     XML_SetAttlistDeclHandler(g_parser, dummy_attlist_decl_handler);
9129     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
9130         != XML_STATUS_ERROR)
9131       break;
9132     /* See comment in test_alloc_parse_xdecl() */
9133     alloc_teardown();
9134     alloc_setup();
9135   }
9136   if (i == 0)
9137     fail("Parse succeeded despite failing reallocator");
9138   if (i == max_realloc_count)
9139     fail("Parse failed at maximum reallocation count");
9140 }
9141 END_TEST
9142 
9143 /* Test attribute enums in a #IMPLIED attribute forcing pool growth */
9144 START_TEST(test_alloc_realloc_implied_attribute) {
9145   /* Forcing this particular code path is a balancing act.  The
9146    * addition of the closing parenthesis and terminal NUL must be
9147    * what pushes the string of enums over the 1024-byte limit,
9148    * otherwise a different code path will pick up the realloc.
9149    */
9150   const char *text
9151       = "<!DOCTYPE doc [\n"
9152         "<!ELEMENT doc EMPTY>\n"
9153         "<!ATTLIST doc a "
9154         /* Each line is 64 characters */
9155         "(ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
9156         "|BBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
9157         "|CBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
9158         "|DBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
9159         "|EBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
9160         "|FBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
9161         "|GBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
9162         "|HBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
9163         "|IBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
9164         "|JBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
9165         "|KBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
9166         "|LBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
9167         "|MBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
9168         "|NBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
9169         "|OBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
9170         "|PBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMN)"
9171         " #IMPLIED>\n"
9172         "]><doc/>";
9173   int i;
9174   const int max_realloc_count = 10;
9175 
9176   for (i = 0; i < max_realloc_count; i++) {
9177     reallocation_count = i;
9178     XML_SetAttlistDeclHandler(g_parser, dummy_attlist_decl_handler);
9179     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
9180         != XML_STATUS_ERROR)
9181       break;
9182     /* See comment in test_alloc_parse_xdecl() */
9183     alloc_teardown();
9184     alloc_setup();
9185   }
9186   if (i == 0)
9187     fail("Parse succeeded despite failing reallocator");
9188   if (i == max_realloc_count)
9189     fail("Parse failed at maximum reallocation count");
9190 }
9191 END_TEST
9192 
9193 /* Test attribute enums in a defaulted attribute forcing pool growth */
9194 START_TEST(test_alloc_realloc_default_attribute) {
9195   /* Forcing this particular code path is a balancing act.  The
9196    * addition of the closing parenthesis and terminal NUL must be
9197    * what pushes the string of enums over the 1024-byte limit,
9198    * otherwise a different code path will pick up the realloc.
9199    */
9200   const char *text
9201       = "<!DOCTYPE doc [\n"
9202         "<!ELEMENT doc EMPTY>\n"
9203         "<!ATTLIST doc a "
9204         /* Each line is 64 characters */
9205         "(ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
9206         "|BBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
9207         "|CBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
9208         "|DBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
9209         "|EBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
9210         "|FBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
9211         "|GBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
9212         "|HBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
9213         "|IBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
9214         "|JBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
9215         "|KBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
9216         "|LBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
9217         "|MBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
9218         "|NBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
9219         "|OBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
9220         "|PBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMN)"
9221         " 'ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO'"
9222         ">\n]><doc/>";
9223   int i;
9224   const int max_realloc_count = 10;
9225 
9226   for (i = 0; i < max_realloc_count; i++) {
9227     reallocation_count = i;
9228     XML_SetAttlistDeclHandler(g_parser, dummy_attlist_decl_handler);
9229     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
9230         != XML_STATUS_ERROR)
9231       break;
9232     /* See comment in test_alloc_parse_xdecl() */
9233     alloc_teardown();
9234     alloc_setup();
9235   }
9236   if (i == 0)
9237     fail("Parse succeeded despite failing reallocator");
9238   if (i == max_realloc_count)
9239     fail("Parse failed at maximum reallocation count");
9240 }
9241 END_TEST
9242 
9243 /* Test long notation name with dodgy allocator */
9244 START_TEST(test_alloc_notation) {
9245   const char *text
9246       = "<!DOCTYPE doc [\n"
9247         "<!NOTATION "
9248         /* Each line is 64 characters */
9249         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9250         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9251         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9252         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9253         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9254         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9255         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9256         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9257         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9258         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9259         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9260         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9261         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9262         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9263         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9264         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9265         " SYSTEM 'http://example.org/n'>\n"
9266         "<!ENTITY e SYSTEM 'http://example.org/e' NDATA "
9267         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9268         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9269         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9270         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9271         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9272         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9273         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9274         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9275         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9276         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9277         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9278         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9279         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9280         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9281         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9282         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9283         ">\n"
9284         "<!ELEMENT doc EMPTY>\n"
9285         "]>\n<doc/>";
9286   int i;
9287   const int max_alloc_count = 20;
9288 
9289   for (i = 0; i < max_alloc_count; i++) {
9290     allocation_count = i;
9291     dummy_handler_flags = 0;
9292     XML_SetNotationDeclHandler(g_parser, dummy_notation_decl_handler);
9293     XML_SetEntityDeclHandler(g_parser, dummy_entity_decl_handler);
9294     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
9295         != XML_STATUS_ERROR)
9296       break;
9297     /* See comment in test_alloc_parse_xdecl() */
9298     alloc_teardown();
9299     alloc_setup();
9300   }
9301   if (i == 0)
9302     fail("Parse succeeded despite allocation failures");
9303   if (i == max_alloc_count)
9304     fail("Parse failed at maximum allocation count");
9305   if (dummy_handler_flags
9306       != (DUMMY_ENTITY_DECL_HANDLER_FLAG | DUMMY_NOTATION_DECL_HANDLER_FLAG))
9307     fail("Entity declaration handler not called");
9308 }
9309 END_TEST
9310 
9311 /* Test public notation with dodgy allocator */
9312 START_TEST(test_alloc_public_notation) {
9313   const char *text
9314       = "<!DOCTYPE doc [\n"
9315         "<!NOTATION note PUBLIC '"
9316         /* 64 characters per line */
9317         "http://example.com/a/long/enough/name/to/trigger/pool/growth/zz/"
9318         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9319         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9320         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9321         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9322         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9323         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9324         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9325         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9326         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9327         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9328         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9329         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9330         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9331         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9332         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9333         "' 'foo'>\n"
9334         "<!ENTITY e SYSTEM 'http://example.com/e' NDATA note>\n"
9335         "<!ELEMENT doc EMPTY>\n"
9336         "]>\n<doc/>";
9337   int i;
9338   const int max_alloc_count = 20;
9339 
9340   for (i = 0; i < max_alloc_count; i++) {
9341     allocation_count = i;
9342     dummy_handler_flags = 0;
9343     XML_SetNotationDeclHandler(g_parser, dummy_notation_decl_handler);
9344     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
9345         != XML_STATUS_ERROR)
9346       break;
9347     /* See comment in test_alloc_parse_xdecl() */
9348     alloc_teardown();
9349     alloc_setup();
9350   }
9351   if (i == 0)
9352     fail("Parse succeeded despite allocation failures");
9353   if (i == max_alloc_count)
9354     fail("Parse failed at maximum allocation count");
9355   if (dummy_handler_flags != DUMMY_NOTATION_DECL_HANDLER_FLAG)
9356     fail("Notation handler not called");
9357 }
9358 END_TEST
9359 
9360 /* Test public notation with dodgy allocator */
9361 START_TEST(test_alloc_system_notation) {
9362   const char *text
9363       = "<!DOCTYPE doc [\n"
9364         "<!NOTATION note SYSTEM '"
9365         /* 64 characters per line */
9366         "http://example.com/a/long/enough/name/to/trigger/pool/growth/zz/"
9367         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9368         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9369         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9370         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9371         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9372         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9373         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9374         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9375         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9376         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9377         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9378         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9379         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9380         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9381         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9382         "'>\n"
9383         "<!ENTITY e SYSTEM 'http://example.com/e' NDATA note>\n"
9384         "<!ELEMENT doc EMPTY>\n"
9385         "]>\n<doc/>";
9386   int i;
9387   const int max_alloc_count = 20;
9388 
9389   for (i = 0; i < max_alloc_count; i++) {
9390     allocation_count = i;
9391     dummy_handler_flags = 0;
9392     XML_SetNotationDeclHandler(g_parser, dummy_notation_decl_handler);
9393     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
9394         != XML_STATUS_ERROR)
9395       break;
9396     /* See comment in test_alloc_parse_xdecl() */
9397     alloc_teardown();
9398     alloc_setup();
9399   }
9400   if (i == 0)
9401     fail("Parse succeeded despite allocation failures");
9402   if (i == max_alloc_count)
9403     fail("Parse failed at maximum allocation count");
9404   if (dummy_handler_flags != DUMMY_NOTATION_DECL_HANDLER_FLAG)
9405     fail("Notation handler not called");
9406 }
9407 END_TEST
9408 
9409 START_TEST(test_alloc_nested_groups) {
9410   const char *text
9411       = "<!DOCTYPE doc [\n"
9412         "<!ELEMENT doc "
9413         /* Sixteen elements per line */
9414         "(e,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,"
9415         "(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?"
9416         "))))))))))))))))))))))))))))))))>\n"
9417         "<!ELEMENT e EMPTY>"
9418         "]>\n"
9419         "<doc><e/></doc>";
9420   CharData storage;
9421   int i;
9422   const int max_alloc_count = 20;
9423 
9424   for (i = 0; i < max_alloc_count; i++) {
9425     allocation_count = i;
9426     CharData_Init(&storage);
9427     XML_SetElementDeclHandler(g_parser, dummy_element_decl_handler);
9428     XML_SetStartElementHandler(g_parser, record_element_start_handler);
9429     XML_SetUserData(g_parser, &storage);
9430     dummy_handler_flags = 0;
9431     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
9432         != XML_STATUS_ERROR)
9433       break;
9434     /* See comment in test_alloc_parse_xdecl() */
9435     alloc_teardown();
9436     alloc_setup();
9437   }
9438 
9439   if (i == 0)
9440     fail("Parse succeeded despite failing reallocator");
9441   if (i == max_alloc_count)
9442     fail("Parse failed at maximum reallocation count");
9443   CharData_CheckXMLChars(&storage, XCS("doce"));
9444   if (dummy_handler_flags != DUMMY_ELEMENT_DECL_HANDLER_FLAG)
9445     fail("Element handler not fired");
9446 }
9447 END_TEST
9448 
9449 START_TEST(test_alloc_realloc_nested_groups) {
9450   const char *text
9451       = "<!DOCTYPE doc [\n"
9452         "<!ELEMENT doc "
9453         /* Sixteen elements per line */
9454         "(e,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,"
9455         "(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?"
9456         "))))))))))))))))))))))))))))))))>\n"
9457         "<!ELEMENT e EMPTY>"
9458         "]>\n"
9459         "<doc><e/></doc>";
9460   CharData storage;
9461   int i;
9462   const int max_realloc_count = 10;
9463 
9464   for (i = 0; i < max_realloc_count; i++) {
9465     reallocation_count = i;
9466     CharData_Init(&storage);
9467     XML_SetElementDeclHandler(g_parser, dummy_element_decl_handler);
9468     XML_SetStartElementHandler(g_parser, record_element_start_handler);
9469     XML_SetUserData(g_parser, &storage);
9470     dummy_handler_flags = 0;
9471     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
9472         != XML_STATUS_ERROR)
9473       break;
9474     /* See comment in test_alloc_parse_xdecl() */
9475     alloc_teardown();
9476     alloc_setup();
9477   }
9478 
9479   if (i == 0)
9480     fail("Parse succeeded despite failing reallocator");
9481   if (i == max_realloc_count)
9482     fail("Parse failed at maximum reallocation count");
9483   CharData_CheckXMLChars(&storage, XCS("doce"));
9484   if (dummy_handler_flags != DUMMY_ELEMENT_DECL_HANDLER_FLAG)
9485     fail("Element handler not fired");
9486 }
9487 END_TEST
9488 
9489 START_TEST(test_alloc_large_group) {
9490   const char *text = "<!DOCTYPE doc [\n"
9491                      "<!ELEMENT doc ("
9492                      "a1|a2|a3|a4|a5|a6|a7|a8|"
9493                      "b1|b2|b3|b4|b5|b6|b7|b8|"
9494                      "c1|c2|c3|c4|c5|c6|c7|c8|"
9495                      "d1|d2|d3|d4|d5|d6|d7|d8|"
9496                      "e1"
9497                      ")+>\n"
9498                      "]>\n"
9499                      "<doc>\n"
9500                      "<a1/>\n"
9501                      "</doc>\n";
9502   int i;
9503   const int max_alloc_count = 50;
9504 
9505   for (i = 0; i < max_alloc_count; i++) {
9506     allocation_count = i;
9507     XML_SetElementDeclHandler(g_parser, dummy_element_decl_handler);
9508     dummy_handler_flags = 0;
9509     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
9510         != XML_STATUS_ERROR)
9511       break;
9512     /* See comment in test_alloc_parse_xdecl() */
9513     alloc_teardown();
9514     alloc_setup();
9515   }
9516   if (i == 0)
9517     fail("Parse succeeded despite failing allocator");
9518   if (i == max_alloc_count)
9519     fail("Parse failed at maximum allocation count");
9520   if (dummy_handler_flags != DUMMY_ELEMENT_DECL_HANDLER_FLAG)
9521     fail("Element handler flag not raised");
9522 }
9523 END_TEST
9524 
9525 START_TEST(test_alloc_realloc_group_choice) {
9526   const char *text = "<!DOCTYPE doc [\n"
9527                      "<!ELEMENT doc ("
9528                      "a1|a2|a3|a4|a5|a6|a7|a8|"
9529                      "b1|b2|b3|b4|b5|b6|b7|b8|"
9530                      "c1|c2|c3|c4|c5|c6|c7|c8|"
9531                      "d1|d2|d3|d4|d5|d6|d7|d8|"
9532                      "e1"
9533                      ")+>\n"
9534                      "]>\n"
9535                      "<doc>\n"
9536                      "<a1/>\n"
9537                      "<b2 attr='foo'>This is a foo</b2>\n"
9538                      "<c3></c3>\n"
9539                      "</doc>\n";
9540   int i;
9541   const int max_realloc_count = 10;
9542 
9543   for (i = 0; i < max_realloc_count; i++) {
9544     reallocation_count = i;
9545     XML_SetElementDeclHandler(g_parser, dummy_element_decl_handler);
9546     dummy_handler_flags = 0;
9547     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
9548         != XML_STATUS_ERROR)
9549       break;
9550     /* See comment in test_alloc_parse_xdecl() */
9551     alloc_teardown();
9552     alloc_setup();
9553   }
9554   if (i == 0)
9555     fail("Parse succeeded despite failing reallocator");
9556   if (i == max_realloc_count)
9557     fail("Parse failed at maximum reallocation count");
9558   if (dummy_handler_flags != DUMMY_ELEMENT_DECL_HANDLER_FLAG)
9559     fail("Element handler flag not raised");
9560 }
9561 END_TEST
9562 
9563 START_TEST(test_alloc_pi_in_epilog) {
9564   const char *text = "<doc></doc>\n"
9565                      "<?pi in epilog?>";
9566   int i;
9567   const int max_alloc_count = 15;
9568 
9569   for (i = 0; i < max_alloc_count; i++) {
9570     allocation_count = i;
9571     XML_SetProcessingInstructionHandler(g_parser, dummy_pi_handler);
9572     dummy_handler_flags = 0;
9573     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
9574         != XML_STATUS_ERROR)
9575       break;
9576     /* See comment in test_alloc_parse_xdecl() */
9577     alloc_teardown();
9578     alloc_setup();
9579   }
9580   if (i == 0)
9581     fail("Parse completed despite failing allocator");
9582   if (i == max_alloc_count)
9583     fail("Parse failed at maximum allocation count");
9584   if (dummy_handler_flags != DUMMY_PI_HANDLER_FLAG)
9585     fail("Processing instruction handler not invoked");
9586 }
9587 END_TEST
9588 
9589 START_TEST(test_alloc_comment_in_epilog) {
9590   const char *text = "<doc></doc>\n"
9591                      "<!-- comment in epilog -->";
9592   int i;
9593   const int max_alloc_count = 15;
9594 
9595   for (i = 0; i < max_alloc_count; i++) {
9596     allocation_count = i;
9597     XML_SetCommentHandler(g_parser, dummy_comment_handler);
9598     dummy_handler_flags = 0;
9599     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
9600         != XML_STATUS_ERROR)
9601       break;
9602     /* See comment in test_alloc_parse_xdecl() */
9603     alloc_teardown();
9604     alloc_setup();
9605   }
9606   if (i == 0)
9607     fail("Parse completed despite failing allocator");
9608   if (i == max_alloc_count)
9609     fail("Parse failed at maximum allocation count");
9610   if (dummy_handler_flags != DUMMY_COMMENT_HANDLER_FLAG)
9611     fail("Processing instruction handler not invoked");
9612 }
9613 END_TEST
9614 
9615 START_TEST(test_alloc_realloc_long_attribute_value) {
9616   const char *text
9617       = "<!DOCTYPE doc [<!ENTITY foo '"
9618         /* Each line is 64 characters */
9619         "This entity will be substituted as an attribute value, and is   "
9620         "calculated to be exactly long enough that the terminating NUL   "
9621         "that the library adds internally will trigger the string pool to"
9622         "grow. GHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9623         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9624         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9625         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9626         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9627         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9628         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9629         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9630         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9631         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9632         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9633         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9634         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9635         "'>]>\n"
9636         "<doc a='&foo;'></doc>";
9637   int i;
9638   const int max_realloc_count = 10;
9639 
9640   for (i = 0; i < max_realloc_count; i++) {
9641     reallocation_count = i;
9642     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
9643         != XML_STATUS_ERROR)
9644       break;
9645     /* See comment in test_alloc_parse_xdecl() */
9646     alloc_teardown();
9647     alloc_setup();
9648   }
9649   if (i == 0)
9650     fail("Parse succeeded despite failing reallocator");
9651   if (i == max_realloc_count)
9652     fail("Parse failed at maximum reallocation count");
9653 }
9654 END_TEST
9655 
9656 START_TEST(test_alloc_attribute_whitespace) {
9657   const char *text = "<doc a=' '></doc>";
9658   int i;
9659   const int max_alloc_count = 15;
9660 
9661   for (i = 0; i < max_alloc_count; i++) {
9662     allocation_count = i;
9663     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
9664         != XML_STATUS_ERROR)
9665       break;
9666     /* See comment in test_alloc_parse_xdecl() */
9667     alloc_teardown();
9668     alloc_setup();
9669   }
9670   if (i == 0)
9671     fail("Parse succeeded despite failing allocator");
9672   if (i == max_alloc_count)
9673     fail("Parse failed at maximum allocation count");
9674 }
9675 END_TEST
9676 
9677 START_TEST(test_alloc_attribute_predefined_entity) {
9678   const char *text = "<doc a='&amp;'></doc>";
9679   int i;
9680   const int max_alloc_count = 15;
9681 
9682   for (i = 0; i < max_alloc_count; i++) {
9683     allocation_count = i;
9684     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
9685         != XML_STATUS_ERROR)
9686       break;
9687     /* See comment in test_alloc_parse_xdecl() */
9688     alloc_teardown();
9689     alloc_setup();
9690   }
9691   if (i == 0)
9692     fail("Parse succeeded despite failing allocator");
9693   if (i == max_alloc_count)
9694     fail("Parse failed at maximum allocation count");
9695 }
9696 END_TEST
9697 
9698 /* Test that a character reference at the end of a suitably long
9699  * default value for an attribute can trigger pool growth, and recovers
9700  * if the allocator fails on it.
9701  */
9702 START_TEST(test_alloc_long_attr_default_with_char_ref) {
9703   const char *text
9704       = "<!DOCTYPE doc [<!ATTLIST doc a CDATA '"
9705         /* 64 characters per line */
9706         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9707         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9708         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9709         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9710         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9711         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9712         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9713         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9714         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9715         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9716         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9717         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9718         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9719         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9720         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9721         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHI"
9722         "&#x31;'>]>\n"
9723         "<doc/>";
9724   int i;
9725   const int max_alloc_count = 20;
9726 
9727   for (i = 0; i < max_alloc_count; i++) {
9728     allocation_count = i;
9729     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
9730         != XML_STATUS_ERROR)
9731       break;
9732     /* See comment in test_alloc_parse_xdecl() */
9733     alloc_teardown();
9734     alloc_setup();
9735   }
9736   if (i == 0)
9737     fail("Parse succeeded despite failing allocator");
9738   if (i == max_alloc_count)
9739     fail("Parse failed at maximum allocation count");
9740 }
9741 END_TEST
9742 
9743 /* Test that a long character reference substitution triggers a pool
9744  * expansion correctly for an attribute value.
9745  */
9746 START_TEST(test_alloc_long_attr_value) {
9747   const char *text
9748       = "<!DOCTYPE test [<!ENTITY foo '\n"
9749         /* 64 characters per line */
9750         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9751         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9752         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9753         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9754         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9755         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9756         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9757         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9758         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9759         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9760         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9761         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9762         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9763         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9764         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9765         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9766         "'>]>\n"
9767         "<test a='&foo;'/>";
9768   int i;
9769   const int max_alloc_count = 25;
9770 
9771   for (i = 0; i < max_alloc_count; i++) {
9772     allocation_count = i;
9773     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
9774         != XML_STATUS_ERROR)
9775       break;
9776     /* See comment in test_alloc_parse_xdecl() */
9777     alloc_teardown();
9778     alloc_setup();
9779   }
9780   if (i == 0)
9781     fail("Parse succeeded despite failing allocator");
9782   if (i == max_alloc_count)
9783     fail("Parse failed at maximum allocation count");
9784 }
9785 END_TEST
9786 
9787 /* Test that an error in a nested parameter entity substitution is
9788  * handled correctly.  It seems unlikely that the code path being
9789  * exercised can be reached purely by carefully crafted XML, but an
9790  * allocation error in the right place will definitely do it.
9791  */
9792 START_TEST(test_alloc_nested_entities) {
9793   const char *text = "<!DOCTYPE doc SYSTEM 'http://example.org/one.ent'>\n"
9794                      "<doc />";
9795   ExtFaults test_data
9796       = {"<!ENTITY % pe1 '"
9797          /* 64 characters per line */
9798          "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9799          "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9800          "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9801          "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9802          "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9803          "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9804          "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9805          "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9806          "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9807          "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9808          "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9809          "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9810          "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9811          "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9812          "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9813          "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9814          "'>\n"
9815          "<!ENTITY % pe2 '%pe1;'>\n"
9816          "%pe2;",
9817          "Memory Fail not faulted", NULL, XML_ERROR_NO_MEMORY};
9818 
9819   /* Causes an allocation error in a nested storeEntityValue() */
9820   allocation_count = 12;
9821   XML_SetUserData(g_parser, &test_data);
9822   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
9823   XML_SetExternalEntityRefHandler(g_parser, external_entity_faulter);
9824   expect_failure(text, XML_ERROR_EXTERNAL_ENTITY_HANDLING,
9825                  "Entity allocation failure not noted");
9826 }
9827 END_TEST
9828 
9829 START_TEST(test_alloc_realloc_param_entity_newline) {
9830   const char *text = "<!DOCTYPE doc SYSTEM 'http://example.org/'>\n"
9831                      "<doc/>";
9832   char dtd_text[]
9833       = "<!ENTITY % pe '<!ATTLIST doc att CDATA \""
9834         /* 64 characters per line */
9835         "This default value is carefully crafted so that the carriage    "
9836         "return right at the end of the entity string causes an internal "
9837         "string pool to have to grow.  This allows us to test the alloc  "
9838         "failure path from that point. OPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9839         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9840         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9841         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9842         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9843         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9844         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9845         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9846         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9847         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9848         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9849         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9850         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDE"
9851         "\">\n'>"
9852         "%pe;\n";
9853   int i;
9854   const int max_realloc_count = 5;
9855 
9856   for (i = 0; i < max_realloc_count; i++) {
9857     reallocation_count = i;
9858     XML_SetUserData(g_parser, dtd_text);
9859     XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
9860     XML_SetExternalEntityRefHandler(g_parser, external_entity_alloc);
9861     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
9862         != XML_STATUS_ERROR)
9863       break;
9864     /* See comment in test_alloc_parse_xdecl() */
9865     alloc_teardown();
9866     alloc_setup();
9867   }
9868   if (i == 0)
9869     fail("Parse succeeded despite failing reallocator");
9870   if (i == max_realloc_count)
9871     fail("Parse failed at maximum reallocation count");
9872 }
9873 END_TEST
9874 
9875 START_TEST(test_alloc_realloc_ce_extends_pe) {
9876   const char *text = "<!DOCTYPE doc SYSTEM 'http://example.org/'>\n"
9877                      "<doc/>";
9878   char dtd_text[]
9879       = "<!ENTITY % pe '<!ATTLIST doc att CDATA \""
9880         /* 64 characters per line */
9881         "This default value is carefully crafted so that the character   "
9882         "entity at the end causes an internal string pool to have to     "
9883         "grow.  This allows us to test the allocation failure path from  "
9884         "that point onwards. EFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9885         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9886         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9887         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9888         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9889         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9890         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9891         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9892         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9893         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9894         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9895         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9896         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFG&#x51;"
9897         "\">\n'>"
9898         "%pe;\n";
9899   int i;
9900   const int max_realloc_count = 5;
9901 
9902   for (i = 0; i < max_realloc_count; i++) {
9903     reallocation_count = i;
9904     XML_SetUserData(g_parser, dtd_text);
9905     XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
9906     XML_SetExternalEntityRefHandler(g_parser, external_entity_alloc);
9907     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
9908         != XML_STATUS_ERROR)
9909       break;
9910     /* See comment in test_alloc_parse_xdecl() */
9911     alloc_teardown();
9912     alloc_setup();
9913   }
9914   if (i == 0)
9915     fail("Parse succeeded despite failing reallocator");
9916   if (i == max_realloc_count)
9917     fail("Parse failed at maximum reallocation count");
9918 }
9919 END_TEST
9920 
9921 START_TEST(test_alloc_realloc_attributes) {
9922   const char *text = "<!DOCTYPE doc [\n"
9923                      "  <!ATTLIST doc\n"
9924                      "    a1  (a|b|c)   'a'\n"
9925                      "    a2  (foo|bar) #IMPLIED\n"
9926                      "    a3  NMTOKEN   #IMPLIED\n"
9927                      "    a4  NMTOKENS  #IMPLIED\n"
9928                      "    a5  ID        #IMPLIED\n"
9929                      "    a6  IDREF     #IMPLIED\n"
9930                      "    a7  IDREFS    #IMPLIED\n"
9931                      "    a8  ENTITY    #IMPLIED\n"
9932                      "    a9  ENTITIES  #IMPLIED\n"
9933                      "    a10 CDATA     #IMPLIED\n"
9934                      "  >]>\n"
9935                      "<doc>wombat</doc>\n";
9936   int i;
9937   const int max_realloc_count = 5;
9938 
9939   for (i = 0; i < max_realloc_count; i++) {
9940     reallocation_count = i;
9941     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
9942         != XML_STATUS_ERROR)
9943       break;
9944     /* See comment in test_alloc_parse_xdecl() */
9945     alloc_teardown();
9946     alloc_setup();
9947   }
9948 
9949   if (i == 0)
9950     fail("Parse succeeded despite failing reallocator");
9951   if (i == max_realloc_count)
9952     fail("Parse failed at maximum reallocation count");
9953 }
9954 END_TEST
9955 
9956 START_TEST(test_alloc_long_doc_name) {
9957   const char *text =
9958       /* 64 characters per line */
9959       "<LongRootElementNameThatWillCauseTheNextAllocationToExpandTheStr"
9960       "ingPoolForTheDTDQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9961       "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9962       "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9963       "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9964       "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9965       "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9966       "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9967       "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9968       "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9969       "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9970       "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9971       "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9972       "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9973       "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9974       "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9975       " a='1'/>";
9976   int i;
9977   const int max_alloc_count = 20;
9978 
9979   for (i = 0; i < max_alloc_count; i++) {
9980     allocation_count = i;
9981     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
9982         != XML_STATUS_ERROR)
9983       break;
9984     /* See comment in test_alloc_parse_xdecl() */
9985     alloc_teardown();
9986     alloc_setup();
9987   }
9988   if (i == 0)
9989     fail("Parsing worked despite failing reallocations");
9990   else if (i == max_alloc_count)
9991     fail("Parsing failed even at max reallocation count");
9992 }
9993 END_TEST
9994 
9995 START_TEST(test_alloc_long_base) {
9996   const char *text = "<!DOCTYPE doc [\n"
9997                      "  <!ENTITY e SYSTEM 'foo'>\n"
9998                      "]>\n"
9999                      "<doc>&e;</doc>";
10000   char entity_text[] = "Hello world";
10001   const XML_Char *base =
10002       /* 64 characters per line */
10003       /* clang-format off */
10004         XCS("LongBaseURI/that/will/overflow/an/internal/buffer/and/cause/it/t")
10005         XCS("o/have/to/grow/PQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/")
10006         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/")
10007         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/")
10008         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/")
10009         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/")
10010         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/")
10011         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/")
10012         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/")
10013         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/")
10014         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/")
10015         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/")
10016         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/")
10017         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/")
10018         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/")
10019         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/");
10020   /* clang-format on */
10021   int i;
10022   const int max_alloc_count = 25;
10023 
10024   for (i = 0; i < max_alloc_count; i++) {
10025     allocation_count = i;
10026     XML_SetUserData(g_parser, entity_text);
10027     XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
10028     XML_SetExternalEntityRefHandler(g_parser, external_entity_alloc);
10029     if (XML_SetBase(g_parser, base) == XML_STATUS_ERROR) {
10030       XML_ParserReset(g_parser, NULL);
10031       continue;
10032     }
10033     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
10034         != XML_STATUS_ERROR)
10035       break;
10036     /* See comment in test_alloc_parse_xdecl() */
10037     alloc_teardown();
10038     alloc_setup();
10039   }
10040   if (i == 0)
10041     fail("Parsing worked despite failing allocations");
10042   else if (i == max_alloc_count)
10043     fail("Parsing failed even at max allocation count");
10044 }
10045 END_TEST
10046 
10047 START_TEST(test_alloc_long_public_id) {
10048   const char *text
10049       = "<!DOCTYPE doc [\n"
10050         "  <!ENTITY e PUBLIC '"
10051         /* 64 characters per line */
10052         "LongPublicIDThatShouldResultInAnInternalStringPoolGrowingAtASpec"
10053         "ificMomentKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
10054         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
10055         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
10056         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
10057         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
10058         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
10059         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
10060         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
10061         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
10062         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
10063         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
10064         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
10065         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
10066         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
10067         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
10068         "' 'bar'>\n"
10069         "]>\n"
10070         "<doc>&e;</doc>";
10071   char entity_text[] = "Hello world";
10072   int i;
10073   const int max_alloc_count = 40;
10074 
10075   for (i = 0; i < max_alloc_count; i++) {
10076     allocation_count = i;
10077     XML_SetUserData(g_parser, entity_text);
10078     XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
10079     XML_SetExternalEntityRefHandler(g_parser, external_entity_alloc);
10080     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
10081         != XML_STATUS_ERROR)
10082       break;
10083     /* See comment in test_alloc_parse_xdecl() */
10084     alloc_teardown();
10085     alloc_setup();
10086   }
10087   if (i == 0)
10088     fail("Parsing worked despite failing allocations");
10089   else if (i == max_alloc_count)
10090     fail("Parsing failed even at max allocation count");
10091 }
10092 END_TEST
10093 
10094 START_TEST(test_alloc_long_entity_value) {
10095   const char *text
10096       = "<!DOCTYPE doc [\n"
10097         "  <!ENTITY e1 '"
10098         /* 64 characters per line */
10099         "Long entity value that should provoke a string pool to grow whil"
10100         "e setting up to parse the external entity below. xyz0123456789AB"
10101         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
10102         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
10103         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
10104         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
10105         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
10106         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
10107         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
10108         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
10109         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
10110         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
10111         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
10112         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
10113         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
10114         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
10115         "'>\n"
10116         "  <!ENTITY e2 SYSTEM 'bar'>\n"
10117         "]>\n"
10118         "<doc>&e2;</doc>";
10119   char entity_text[] = "Hello world";
10120   int i;
10121   const int max_alloc_count = 40;
10122 
10123   for (i = 0; i < max_alloc_count; i++) {
10124     allocation_count = i;
10125     XML_SetUserData(g_parser, entity_text);
10126     XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
10127     XML_SetExternalEntityRefHandler(g_parser, external_entity_alloc);
10128     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
10129         != XML_STATUS_ERROR)
10130       break;
10131     /* See comment in test_alloc_parse_xdecl() */
10132     alloc_teardown();
10133     alloc_setup();
10134   }
10135   if (i == 0)
10136     fail("Parsing worked despite failing allocations");
10137   else if (i == max_alloc_count)
10138     fail("Parsing failed even at max allocation count");
10139 }
10140 END_TEST
10141 
10142 START_TEST(test_alloc_long_notation) {
10143   const char *text
10144       = "<!DOCTYPE doc [\n"
10145         "  <!NOTATION note SYSTEM '"
10146         /* 64 characters per line */
10147         "ALongNotationNameThatShouldProvokeStringPoolGrowthWhileCallingAn"
10148         "ExternalEntityParserUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
10149         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
10150         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
10151         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
10152         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
10153         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
10154         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
10155         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
10156         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
10157         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
10158         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
10159         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
10160         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
10161         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
10162         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
10163         "'>\n"
10164         "  <!ENTITY e1 SYSTEM 'foo' NDATA "
10165         /* 64 characters per line */
10166         "ALongNotationNameThatShouldProvokeStringPoolGrowthWhileCallingAn"
10167         "ExternalEntityParserUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
10168         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
10169         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
10170         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
10171         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
10172         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
10173         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
10174         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
10175         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
10176         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
10177         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
10178         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
10179         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
10180         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
10181         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
10182         ">\n"
10183         "  <!ENTITY e2 SYSTEM 'bar'>\n"
10184         "]>\n"
10185         "<doc>&e2;</doc>";
10186   ExtOption options[]
10187       = {{XCS("foo"), "Entity Foo"}, {XCS("bar"), "Entity Bar"}, {NULL, NULL}};
10188   int i;
10189   const int max_alloc_count = 40;
10190 
10191   for (i = 0; i < max_alloc_count; i++) {
10192     allocation_count = i;
10193     XML_SetUserData(g_parser, options);
10194     XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
10195     XML_SetExternalEntityRefHandler(g_parser, external_entity_optioner);
10196     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
10197         != XML_STATUS_ERROR)
10198       break;
10199 
10200     /* See comment in test_alloc_parse_xdecl() */
10201     alloc_teardown();
10202     alloc_setup();
10203   }
10204   if (i == 0)
10205     fail("Parsing worked despite failing allocations");
10206   else if (i == max_alloc_count)
10207     fail("Parsing failed even at max allocation count");
10208 }
10209 END_TEST
10210 
10211 static int XMLCALL
10212 external_entity_parser_create_alloc_fail_handler(XML_Parser parser,
10213                                                  const XML_Char *context,
10214                                                  const XML_Char *base,
10215                                                  const XML_Char *systemId,
10216                                                  const XML_Char *publicId) {
10217   UNUSED_P(base);
10218   UNUSED_P(systemId);
10219   UNUSED_P(publicId);
10220 
10221   if (context != NULL)
10222     fail("Unexpected non-NULL context");
10223 
10224   // The following number intends to fail the upcoming allocation in line
10225   // "parser->m_protocolEncodingName = copyString(encodingName,
10226   // &(parser->m_mem));" in function parserInit.
10227   allocation_count = 3;
10228 
10229   const XML_Char *const encodingName = XCS("UTF-8"); // needs something non-NULL
10230   const XML_Parser ext_parser
10231       = XML_ExternalEntityParserCreate(parser, context, encodingName);
10232   if (ext_parser != NULL)
10233     fail(
10234         "Call to XML_ExternalEntityParserCreate was expected to fail out-of-memory");
10235 
10236   allocation_count = ALLOC_ALWAYS_SUCCEED;
10237   return XML_STATUS_ERROR;
10238 }
10239 
10240 START_TEST(test_alloc_reset_after_external_entity_parser_create_fail) {
10241   const char *const text = "<!DOCTYPE doc SYSTEM 'foo'><doc/>";
10242 
10243   XML_SetExternalEntityRefHandler(
10244       g_parser, external_entity_parser_create_alloc_fail_handler);
10245   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
10246 
10247   if (XML_Parse(g_parser, text, (int)strlen(text), XML_TRUE)
10248       != XML_STATUS_ERROR)
10249     fail("Call to parse was expected to fail");
10250 
10251   if (XML_GetErrorCode(g_parser) != XML_ERROR_EXTERNAL_ENTITY_HANDLING)
10252     fail("Call to parse was expected to fail from the external entity handler");
10253 
10254   XML_ParserReset(g_parser, NULL);
10255 }
10256 END_TEST
10257 
10258 static void
10259 nsalloc_setup(void) {
10260   XML_Memory_Handling_Suite memsuite = {duff_allocator, duff_reallocator, free};
10261   XML_Char ns_sep[2] = {' ', '\0'};
10262 
10263   /* Ensure the parser creation will go through */
10264   allocation_count = ALLOC_ALWAYS_SUCCEED;
10265   reallocation_count = REALLOC_ALWAYS_SUCCEED;
10266   g_parser = XML_ParserCreate_MM(NULL, &memsuite, ns_sep);
10267   if (g_parser == NULL)
10268     fail("Parser not created");
10269 }
10270 
10271 static void
10272 nsalloc_teardown(void) {
10273   basic_teardown();
10274 }
10275 
10276 /* Test the effects of allocation failure in simple namespace parsing.
10277  * Based on test_ns_default_with_empty_uri()
10278  */
10279 START_TEST(test_nsalloc_xmlns) {
10280   const char *text = "<doc xmlns='http://example.org/'>\n"
10281                      "  <e xmlns=''/>\n"
10282                      "</doc>";
10283   unsigned int i;
10284   const unsigned int max_alloc_count = 30;
10285 
10286   for (i = 0; i < max_alloc_count; i++) {
10287     allocation_count = i;
10288     /* Exercise more code paths with a default handler */
10289     XML_SetDefaultHandler(g_parser, dummy_default_handler);
10290     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
10291         != XML_STATUS_ERROR)
10292       break;
10293     /* Resetting the parser is insufficient, because some memory
10294      * allocations are cached within the parser.  Instead we use
10295      * the teardown and setup routines to ensure that we have the
10296      * right sort of parser back in our hands.
10297      */
10298     nsalloc_teardown();
10299     nsalloc_setup();
10300   }
10301   if (i == 0)
10302     fail("Parsing worked despite failing allocations");
10303   else if (i == max_alloc_count)
10304     fail("Parsing failed even at maximum allocation count");
10305 }
10306 END_TEST
10307 
10308 /* Test XML_ParseBuffer interface with namespace and a dicky allocator */
10309 START_TEST(test_nsalloc_parse_buffer) {
10310   const char *text = "<doc>Hello</doc>";
10311   void *buffer;
10312 
10313   /* Try a parse before the start of the world */
10314   /* (Exercises new code path) */
10315   if (XML_ParseBuffer(g_parser, 0, XML_FALSE) != XML_STATUS_ERROR)
10316     fail("Pre-init XML_ParseBuffer not faulted");
10317   if (XML_GetErrorCode(g_parser) != XML_ERROR_NO_BUFFER)
10318     fail("Pre-init XML_ParseBuffer faulted for wrong reason");
10319 
10320   buffer = XML_GetBuffer(g_parser, 1 /* any small number greater than 0 */);
10321   if (buffer == NULL)
10322     fail("Could not acquire parse buffer");
10323 
10324   allocation_count = 0;
10325   if (XML_ParseBuffer(g_parser, 0, XML_FALSE) != XML_STATUS_ERROR)
10326     fail("Pre-init XML_ParseBuffer not faulted");
10327   if (XML_GetErrorCode(g_parser) != XML_ERROR_NO_MEMORY)
10328     fail("Pre-init XML_ParseBuffer faulted for wrong reason");
10329 
10330   /* Now with actual memory allocation */
10331   allocation_count = ALLOC_ALWAYS_SUCCEED;
10332   if (XML_ParseBuffer(g_parser, 0, XML_FALSE) != XML_STATUS_OK)
10333     xml_failure(g_parser);
10334 
10335   /* Check that resuming an unsuspended parser is faulted */
10336   if (XML_ResumeParser(g_parser) != XML_STATUS_ERROR)
10337     fail("Resuming unsuspended parser not faulted");
10338   if (XML_GetErrorCode(g_parser) != XML_ERROR_NOT_SUSPENDED)
10339     xml_failure(g_parser);
10340 
10341   /* Get the parser into suspended state */
10342   XML_SetCharacterDataHandler(g_parser, clearing_aborting_character_handler);
10343   resumable = XML_TRUE;
10344   buffer = XML_GetBuffer(g_parser, (int)strlen(text));
10345   if (buffer == NULL)
10346     fail("Could not acquire parse buffer");
10347   assert(buffer != NULL);
10348   memcpy(buffer, text, strlen(text));
10349   if (XML_ParseBuffer(g_parser, (int)strlen(text), XML_TRUE)
10350       != XML_STATUS_SUSPENDED)
10351     xml_failure(g_parser);
10352   if (XML_GetErrorCode(g_parser) != XML_ERROR_NONE)
10353     xml_failure(g_parser);
10354   if (XML_ParseBuffer(g_parser, (int)strlen(text), XML_TRUE)
10355       != XML_STATUS_ERROR)
10356     fail("Suspended XML_ParseBuffer not faulted");
10357   if (XML_GetErrorCode(g_parser) != XML_ERROR_SUSPENDED)
10358     xml_failure(g_parser);
10359   if (XML_GetBuffer(g_parser, (int)strlen(text)) != NULL)
10360     fail("Suspended XML_GetBuffer not faulted");
10361 
10362   /* Get it going again and complete the world */
10363   XML_SetCharacterDataHandler(g_parser, NULL);
10364   if (XML_ResumeParser(g_parser) != XML_STATUS_OK)
10365     xml_failure(g_parser);
10366   if (XML_ParseBuffer(g_parser, (int)strlen(text), XML_TRUE)
10367       != XML_STATUS_ERROR)
10368     fail("Post-finishing XML_ParseBuffer not faulted");
10369   if (XML_GetErrorCode(g_parser) != XML_ERROR_FINISHED)
10370     xml_failure(g_parser);
10371   if (XML_GetBuffer(g_parser, (int)strlen(text)) != NULL)
10372     fail("Post-finishing XML_GetBuffer not faulted");
10373 }
10374 END_TEST
10375 
10376 /* Check handling of long prefix names (pool growth) */
10377 START_TEST(test_nsalloc_long_prefix) {
10378   const char *text
10379       = "<"
10380         /* 64 characters per line */
10381         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10382         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10383         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10384         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10385         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10386         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10387         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10388         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10389         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10390         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10391         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10392         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10393         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10394         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10395         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10396         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10397         ":foo xmlns:"
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         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10412         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10413         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10414         "='http://example.org/'>"
10415         "</"
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         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10431         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10432         ":foo>";
10433   int i;
10434   const int max_alloc_count = 40;
10435 
10436   for (i = 0; i < max_alloc_count; i++) {
10437     allocation_count = i;
10438     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
10439         != XML_STATUS_ERROR)
10440       break;
10441     /* See comment in test_nsalloc_xmlns() */
10442     nsalloc_teardown();
10443     nsalloc_setup();
10444   }
10445   if (i == 0)
10446     fail("Parsing worked despite failing allocations");
10447   else if (i == max_alloc_count)
10448     fail("Parsing failed even at max allocation count");
10449 }
10450 END_TEST
10451 
10452 /* Check handling of long uri names (pool growth) */
10453 START_TEST(test_nsalloc_long_uri) {
10454   const char *text
10455       = "<foo:e xmlns:foo='http://example.org/"
10456         /* 64 characters per line */
10457         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10458         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10459         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10460         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10461         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10462         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10463         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10464         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10465         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10466         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10467         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10468         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10469         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10470         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10471         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10472         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10473         "' bar:a='12'\n"
10474         "xmlns:bar='http://example.org/"
10475         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10476         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10477         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10478         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10479         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10480         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10481         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10482         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10483         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10484         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10485         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10486         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10487         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10488         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10489         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10490         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10491         "'>"
10492         "</foo:e>";
10493   int i;
10494   const int max_alloc_count = 40;
10495 
10496   for (i = 0; i < max_alloc_count; i++) {
10497     allocation_count = i;
10498     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
10499         != XML_STATUS_ERROR)
10500       break;
10501     /* See comment in test_nsalloc_xmlns() */
10502     nsalloc_teardown();
10503     nsalloc_setup();
10504   }
10505   if (i == 0)
10506     fail("Parsing worked despite failing allocations");
10507   else if (i == max_alloc_count)
10508     fail("Parsing failed even at max allocation count");
10509 }
10510 END_TEST
10511 
10512 /* Test handling of long attribute names with prefixes */
10513 START_TEST(test_nsalloc_long_attr) {
10514   const char *text
10515       = "<foo:e xmlns:foo='http://example.org/' bar:"
10516         /* 64 characters per line */
10517         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10518         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10519         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10520         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10521         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10522         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10523         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10524         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10525         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10526         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10527         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10528         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10529         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10530         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10531         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10532         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10533         "='12'\n"
10534         "xmlns:bar='http://example.org/'>"
10535         "</foo:e>";
10536   int i;
10537   const int max_alloc_count = 40;
10538 
10539   for (i = 0; i < max_alloc_count; i++) {
10540     allocation_count = i;
10541     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
10542         != XML_STATUS_ERROR)
10543       break;
10544     /* See comment in test_nsalloc_xmlns() */
10545     nsalloc_teardown();
10546     nsalloc_setup();
10547   }
10548   if (i == 0)
10549     fail("Parsing worked despite failing allocations");
10550   else if (i == max_alloc_count)
10551     fail("Parsing failed even at max allocation count");
10552 }
10553 END_TEST
10554 
10555 /* Test handling of an attribute name with a long namespace prefix */
10556 START_TEST(test_nsalloc_long_attr_prefix) {
10557   const char *text
10558       = "<foo:e xmlns:foo='http://example.org/' "
10559         /* 64 characters per line */
10560         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10561         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10562         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10563         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10564         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10565         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10566         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10567         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10568         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10569         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10570         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10571         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10572         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10573         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10574         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10575         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10576         ":a='12'\n"
10577         "xmlns:"
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         "='http://example.org/'>"
10596         "</foo:e>";
10597   const XML_Char *elemstr[] = {
10598       /* clang-format off */
10599         XCS("http://example.org/ e foo"),
10600         XCS("http://example.org/ a ")
10601         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ")
10602         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ")
10603         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ")
10604         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ")
10605         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ")
10606         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ")
10607         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ")
10608         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ")
10609         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ")
10610         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ")
10611         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ")
10612         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ")
10613         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ")
10614         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ")
10615         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ")
10616         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ")
10617       /* clang-format on */
10618   };
10619   int i;
10620   const int max_alloc_count = 40;
10621 
10622   for (i = 0; i < max_alloc_count; i++) {
10623     allocation_count = i;
10624     XML_SetReturnNSTriplet(g_parser, XML_TRUE);
10625     XML_SetUserData(g_parser, (void *)elemstr);
10626     XML_SetElementHandler(g_parser, triplet_start_checker, triplet_end_checker);
10627     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
10628         != XML_STATUS_ERROR)
10629       break;
10630     /* See comment in test_nsalloc_xmlns() */
10631     nsalloc_teardown();
10632     nsalloc_setup();
10633   }
10634   if (i == 0)
10635     fail("Parsing worked despite failing allocations");
10636   else if (i == max_alloc_count)
10637     fail("Parsing failed even at max allocation count");
10638 }
10639 END_TEST
10640 
10641 /* Test attribute handling in the face of a dodgy reallocator */
10642 START_TEST(test_nsalloc_realloc_attributes) {
10643   const char *text = "<foo:e xmlns:foo='http://example.org/' bar:a='12'\n"
10644                      "       xmlns:bar='http://example.org/'>"
10645                      "</foo:e>";
10646   int i;
10647   const int max_realloc_count = 10;
10648 
10649   for (i = 0; i < max_realloc_count; i++) {
10650     reallocation_count = i;
10651     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
10652         != XML_STATUS_ERROR)
10653       break;
10654     /* See comment in test_nsalloc_xmlns() */
10655     nsalloc_teardown();
10656     nsalloc_setup();
10657   }
10658   if (i == 0)
10659     fail("Parsing worked despite failing reallocations");
10660   else if (i == max_realloc_count)
10661     fail("Parsing failed at max reallocation count");
10662 }
10663 END_TEST
10664 
10665 /* Test long element names with namespaces under a failing allocator */
10666 START_TEST(test_nsalloc_long_element) {
10667   const char *text
10668       = "<foo:thisisalongenoughelementnametotriggerareallocation\n"
10669         " xmlns:foo='http://example.org/' bar:a='12'\n"
10670         " xmlns:bar='http://example.org/'>"
10671         "</foo:thisisalongenoughelementnametotriggerareallocation>";
10672   const XML_Char *elemstr[]
10673       = {XCS("http://example.org/")
10674              XCS(" thisisalongenoughelementnametotriggerareallocation foo"),
10675          XCS("http://example.org/ a bar")};
10676   int i;
10677   const int max_alloc_count = 30;
10678 
10679   for (i = 0; i < max_alloc_count; i++) {
10680     allocation_count = i;
10681     XML_SetReturnNSTriplet(g_parser, XML_TRUE);
10682     XML_SetUserData(g_parser, (void *)elemstr);
10683     XML_SetElementHandler(g_parser, triplet_start_checker, triplet_end_checker);
10684     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
10685         != XML_STATUS_ERROR)
10686       break;
10687     /* See comment in test_nsalloc_xmlns() */
10688     nsalloc_teardown();
10689     nsalloc_setup();
10690   }
10691   if (i == 0)
10692     fail("Parsing worked despite failing reallocations");
10693   else if (i == max_alloc_count)
10694     fail("Parsing failed at max reallocation count");
10695 }
10696 END_TEST
10697 
10698 /* Test the effects of reallocation failure when reassigning a
10699  * binding.
10700  *
10701  * XML_ParserReset does not free the BINDING structures used by a
10702  * parser, but instead adds them to an internal free list to be reused
10703  * as necessary.  Likewise the URI buffers allocated for the binding
10704  * aren't freed, but kept attached to their existing binding.  If the
10705  * new binding has a longer URI, it will need reallocation.  This test
10706  * provokes that reallocation, and tests the control path if it fails.
10707  */
10708 START_TEST(test_nsalloc_realloc_binding_uri) {
10709   const char *first = "<doc xmlns='http://example.org/'>\n"
10710                       "  <e xmlns='' />\n"
10711                       "</doc>";
10712   const char *second
10713       = "<doc xmlns='http://example.org/long/enough/URI/to/reallocate/'>\n"
10714         "  <e xmlns='' />\n"
10715         "</doc>";
10716   unsigned i;
10717   const unsigned max_realloc_count = 10;
10718 
10719   /* First, do a full parse that will leave bindings around */
10720   if (_XML_Parse_SINGLE_BYTES(g_parser, first, (int)strlen(first), XML_TRUE)
10721       == XML_STATUS_ERROR)
10722     xml_failure(g_parser);
10723 
10724   /* Now repeat with a longer URI and a duff reallocator */
10725   for (i = 0; i < max_realloc_count; i++) {
10726     XML_ParserReset(g_parser, NULL);
10727     reallocation_count = i;
10728     if (_XML_Parse_SINGLE_BYTES(g_parser, second, (int)strlen(second), XML_TRUE)
10729         != XML_STATUS_ERROR)
10730       break;
10731   }
10732   if (i == 0)
10733     fail("Parsing worked despite failing reallocation");
10734   else if (i == max_realloc_count)
10735     fail("Parsing failed at max reallocation count");
10736 }
10737 END_TEST
10738 
10739 /* Check handling of long prefix names (pool growth) */
10740 START_TEST(test_nsalloc_realloc_long_prefix) {
10741   const char *text
10742       = "<"
10743         /* 64 characters per line */
10744         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10745         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10746         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
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         ":foo xmlns:"
10761         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10762         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10763         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10764         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10765         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10766         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10767         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10768         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10769         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10770         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10771         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10772         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10773         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10774         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10775         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10776         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10777         "='http://example.org/'>"
10778         "</"
10779         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10780         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10781         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10782         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
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         ":foo>";
10796   int i;
10797   const int max_realloc_count = 12;
10798 
10799   for (i = 0; i < max_realloc_count; i++) {
10800     reallocation_count = i;
10801     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
10802         != XML_STATUS_ERROR)
10803       break;
10804     /* See comment in test_nsalloc_xmlns() */
10805     nsalloc_teardown();
10806     nsalloc_setup();
10807   }
10808   if (i == 0)
10809     fail("Parsing worked despite failing reallocations");
10810   else if (i == max_realloc_count)
10811     fail("Parsing failed even at max reallocation count");
10812 }
10813 END_TEST
10814 
10815 /* Check handling of even long prefix names (different code path) */
10816 START_TEST(test_nsalloc_realloc_longer_prefix) {
10817   const char *text
10818       = "<"
10819         /* 64 characters per line */
10820         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10821         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10822         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10823         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10824         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10825         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10826         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10827         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10828         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10829         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10830         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10831         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10832         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10833         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10834         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10835         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10836         "Q:foo xmlns:"
10837         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10838         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10839         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10840         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10841         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10842         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10843         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10844         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10845         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10846         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10847         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10848         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10849         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10850         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10851         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10852         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10853         "Q='http://example.org/'>"
10854         "</"
10855         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10856         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10857         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10858         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10859         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10860         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10861         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10862         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10863         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10864         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10865         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10866         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10867         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10868         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10869         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10870         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10871         "Q:foo>";
10872   int i;
10873   const int max_realloc_count = 12;
10874 
10875   for (i = 0; i < max_realloc_count; i++) {
10876     reallocation_count = i;
10877     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
10878         != XML_STATUS_ERROR)
10879       break;
10880     /* See comment in test_nsalloc_xmlns() */
10881     nsalloc_teardown();
10882     nsalloc_setup();
10883   }
10884   if (i == 0)
10885     fail("Parsing worked despite failing reallocations");
10886   else if (i == max_realloc_count)
10887     fail("Parsing failed even at max reallocation count");
10888 }
10889 END_TEST
10890 
10891 START_TEST(test_nsalloc_long_namespace) {
10892   const char *text1
10893       = "<"
10894         /* 64 characters per line */
10895         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10896         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10897         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10898         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10899         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10900         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10901         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10902         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10903         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10904         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10905         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10906         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10907         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10908         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10909         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10910         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10911         ":e xmlns:"
10912         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10913         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10914         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10915         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10916         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10917         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10918         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10919         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10920         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10921         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10922         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10923         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10924         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10925         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10926         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10927         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10928         "='http://example.org/'>\n";
10929   const char *text2
10930       = "<"
10931         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10932         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10933         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10934         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10935         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10936         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10937         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10938         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10939         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10940         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10941         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10942         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10943         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10944         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10945         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10946         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10947         ":f "
10948         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10949         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10950         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10951         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10952         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10953         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10954         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10955         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10956         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10957         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10958         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10959         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10960         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10961         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10962         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10963         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10964         ":attr='foo'/>\n"
10965         "</"
10966         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10967         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10968         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10969         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10970         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10971         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10972         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10973         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10974         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10975         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10976         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10977         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10978         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10979         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10980         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10981         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10982         ":e>";
10983   int i;
10984   const int max_alloc_count = 40;
10985 
10986   for (i = 0; i < max_alloc_count; i++) {
10987     allocation_count = i;
10988     if (_XML_Parse_SINGLE_BYTES(g_parser, text1, (int)strlen(text1), XML_FALSE)
10989             != XML_STATUS_ERROR
10990         && _XML_Parse_SINGLE_BYTES(g_parser, text2, (int)strlen(text2),
10991                                    XML_TRUE)
10992                != XML_STATUS_ERROR)
10993       break;
10994     /* See comment in test_nsalloc_xmlns() */
10995     nsalloc_teardown();
10996     nsalloc_setup();
10997   }
10998   if (i == 0)
10999     fail("Parsing worked despite failing allocations");
11000   else if (i == max_alloc_count)
11001     fail("Parsing failed even at max allocation count");
11002 }
11003 END_TEST
11004 
11005 /* Using a slightly shorter namespace name provokes allocations in
11006  * slightly different places in the code.
11007  */
11008 START_TEST(test_nsalloc_less_long_namespace) {
11009   const char *text
11010       = "<"
11011         /* 64 characters per line */
11012         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
11013         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
11014         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
11015         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
11016         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
11017         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
11018         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
11019         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz012345678"
11020         ":e xmlns:"
11021         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
11022         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
11023         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
11024         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
11025         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
11026         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
11027         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
11028         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz012345678"
11029         "='http://example.org/'>\n"
11030         "<"
11031         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
11032         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
11033         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
11034         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
11035         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
11036         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
11037         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
11038         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz012345678"
11039         ":f "
11040         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
11041         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
11042         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
11043         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
11044         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
11045         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
11046         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
11047         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz012345678"
11048         ":att='foo'/>\n"
11049         "</"
11050         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
11051         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
11052         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
11053         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
11054         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
11055         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
11056         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
11057         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz012345678"
11058         ":e>";
11059   int i;
11060   const int max_alloc_count = 40;
11061 
11062   for (i = 0; i < max_alloc_count; i++) {
11063     allocation_count = i;
11064     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
11065         != XML_STATUS_ERROR)
11066       break;
11067     /* See comment in test_nsalloc_xmlns() */
11068     nsalloc_teardown();
11069     nsalloc_setup();
11070   }
11071   if (i == 0)
11072     fail("Parsing worked despite failing allocations");
11073   else if (i == max_alloc_count)
11074     fail("Parsing failed even at max allocation count");
11075 }
11076 END_TEST
11077 
11078 START_TEST(test_nsalloc_long_context) {
11079   const char *text
11080       = "<!DOCTYPE doc SYSTEM 'foo' [\n"
11081         "  <!ATTLIST doc baz ID #REQUIRED>\n"
11082         "  <!ENTITY en SYSTEM 'bar'>\n"
11083         "]>\n"
11084         "<doc xmlns='http://example.org/"
11085         /* 64 characters per line */
11086         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11087         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11088         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11089         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11090         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11091         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11092         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
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/ABCDEFGHIJKL"
11102         "' baz='2'>\n"
11103         "&en;"
11104         "</doc>";
11105   ExtOption options[] = {
11106       {XCS("foo"), "<!ELEMENT e EMPTY>"}, {XCS("bar"), "<e/>"}, {NULL, NULL}};
11107   int i;
11108   const int max_alloc_count = 70;
11109 
11110   for (i = 0; i < max_alloc_count; i++) {
11111     allocation_count = i;
11112     XML_SetUserData(g_parser, options);
11113     XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
11114     XML_SetExternalEntityRefHandler(g_parser, external_entity_optioner);
11115     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
11116         != XML_STATUS_ERROR)
11117       break;
11118 
11119     /* See comment in test_nsalloc_xmlns() */
11120     nsalloc_teardown();
11121     nsalloc_setup();
11122   }
11123   if (i == 0)
11124     fail("Parsing worked despite failing allocations");
11125   else if (i == max_alloc_count)
11126     fail("Parsing failed even at max allocation count");
11127 }
11128 END_TEST
11129 
11130 /* This function is void; it will throw a fail() on error, so if it
11131  * returns normally it must have succeeded.
11132  */
11133 static void
11134 context_realloc_test(const char *text) {
11135   ExtOption options[] = {
11136       {XCS("foo"), "<!ELEMENT e EMPTY>"}, {XCS("bar"), "<e/>"}, {NULL, NULL}};
11137   int i;
11138   const int max_realloc_count = 6;
11139 
11140   for (i = 0; i < max_realloc_count; i++) {
11141     reallocation_count = i;
11142     XML_SetUserData(g_parser, options);
11143     XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
11144     XML_SetExternalEntityRefHandler(g_parser, external_entity_optioner);
11145     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
11146         != XML_STATUS_ERROR)
11147       break;
11148     /* See comment in test_nsalloc_xmlns() */
11149     nsalloc_teardown();
11150     nsalloc_setup();
11151   }
11152   if (i == 0)
11153     fail("Parsing worked despite failing reallocations");
11154   else if (i == max_realloc_count)
11155     fail("Parsing failed even at max reallocation count");
11156 }
11157 
11158 START_TEST(test_nsalloc_realloc_long_context) {
11159   const char *text
11160       = "<!DOCTYPE doc SYSTEM 'foo' [\n"
11161         "  <!ENTITY en SYSTEM 'bar'>\n"
11162         "]>\n"
11163         "<doc xmlns='http://example.org/"
11164         /* 64 characters per line */
11165         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11166         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11167         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11168         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11169         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11170         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11171         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11172         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11173         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11174         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11175         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11176         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11177         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11178         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11179         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11180         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKL"
11181         "'>\n"
11182         "&en;"
11183         "</doc>";
11184 
11185   context_realloc_test(text);
11186 }
11187 END_TEST
11188 
11189 START_TEST(test_nsalloc_realloc_long_context_2) {
11190   const char *text
11191       = "<!DOCTYPE doc SYSTEM 'foo' [\n"
11192         "  <!ENTITY en SYSTEM 'bar'>\n"
11193         "]>\n"
11194         "<doc xmlns='http://example.org/"
11195         /* 64 characters per line */
11196         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11197         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11198         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11199         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11200         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11201         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11202         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11203         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11204         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11205         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11206         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11207         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11208         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11209         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11210         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11211         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJK"
11212         "'>\n"
11213         "&en;"
11214         "</doc>";
11215 
11216   context_realloc_test(text);
11217 }
11218 END_TEST
11219 
11220 START_TEST(test_nsalloc_realloc_long_context_3) {
11221   const char *text
11222       = "<!DOCTYPE doc SYSTEM 'foo' [\n"
11223         "  <!ENTITY en SYSTEM 'bar'>\n"
11224         "]>\n"
11225         "<doc xmlns='http://example.org/"
11226         /* 64 characters per line */
11227         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11228         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11229         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11230         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11231         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11232         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11233         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11234         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11235         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11236         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11237         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11238         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11239         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11240         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11241         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11242         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGH"
11243         "'>\n"
11244         "&en;"
11245         "</doc>";
11246 
11247   context_realloc_test(text);
11248 }
11249 END_TEST
11250 
11251 START_TEST(test_nsalloc_realloc_long_context_4) {
11252   const char *text
11253       = "<!DOCTYPE doc SYSTEM 'foo' [\n"
11254         "  <!ENTITY en SYSTEM 'bar'>\n"
11255         "]>\n"
11256         "<doc xmlns='http://example.org/"
11257         /* 64 characters per line */
11258         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11259         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11260         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11261         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11262         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11263         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11264         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11265         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11266         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11267         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11268         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11269         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11270         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11271         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11272         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11273         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO"
11274         "'>\n"
11275         "&en;"
11276         "</doc>";
11277 
11278   context_realloc_test(text);
11279 }
11280 END_TEST
11281 
11282 START_TEST(test_nsalloc_realloc_long_context_5) {
11283   const char *text
11284       = "<!DOCTYPE doc SYSTEM 'foo' [\n"
11285         "  <!ENTITY en SYSTEM 'bar'>\n"
11286         "]>\n"
11287         "<doc xmlns='http://example.org/"
11288         /* 64 characters per line */
11289         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11290         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11291         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11292         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11293         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11294         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11295         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11296         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11297         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11298         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11299         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11300         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11301         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11302         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11303         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11304         "ABC"
11305         "'>\n"
11306         "&en;"
11307         "</doc>";
11308 
11309   context_realloc_test(text);
11310 }
11311 END_TEST
11312 
11313 START_TEST(test_nsalloc_realloc_long_context_6) {
11314   const char *text
11315       = "<!DOCTYPE doc SYSTEM 'foo' [\n"
11316         "  <!ENTITY en SYSTEM 'bar'>\n"
11317         "]>\n"
11318         "<doc xmlns='http://example.org/"
11319         /* 64 characters per line */
11320         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11321         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11322         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11323         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11324         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11325         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11326         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11327         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11328         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11329         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11330         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11331         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11332         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11333         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11334         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP"
11335         "'>\n"
11336         "&en;"
11337         "</doc>";
11338 
11339   context_realloc_test(text);
11340 }
11341 END_TEST
11342 
11343 START_TEST(test_nsalloc_realloc_long_context_7) {
11344   const char *text
11345       = "<!DOCTYPE doc SYSTEM 'foo' [\n"
11346         "  <!ENTITY en SYSTEM 'bar'>\n"
11347         "]>\n"
11348         "<doc xmlns='http://example.org/"
11349         /* 64 characters per line */
11350         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11351         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11352         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11353         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11354         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11355         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11356         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11357         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11358         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11359         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11360         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11361         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11362         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11363         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11364         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11365         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLM"
11366         "'>\n"
11367         "&en;"
11368         "</doc>";
11369 
11370   context_realloc_test(text);
11371 }
11372 END_TEST
11373 
11374 START_TEST(test_nsalloc_realloc_long_ge_name) {
11375   const char *text
11376       = "<!DOCTYPE doc SYSTEM 'foo' [\n"
11377         "  <!ENTITY "
11378         /* 64 characters per line */
11379         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11380         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11381         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11382         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11383         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11384         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11385         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11386         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11387         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11388         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11389         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11390         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11391         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11392         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11393         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11394         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11395         " SYSTEM 'bar'>\n"
11396         "]>\n"
11397         "<doc xmlns='http://example.org/baz'>\n"
11398         "&"
11399         /* 64 characters per line */
11400         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11401         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11402         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11403         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11404         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11405         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11406         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11407         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11408         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11409         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11410         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11411         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11412         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11413         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11414         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11415         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11416         ";"
11417         "</doc>";
11418   ExtOption options[] = {
11419       {XCS("foo"), "<!ELEMENT el EMPTY>"}, {XCS("bar"), "<el/>"}, {NULL, NULL}};
11420   int i;
11421   const int max_realloc_count = 10;
11422 
11423   for (i = 0; i < max_realloc_count; i++) {
11424     reallocation_count = i;
11425     XML_SetUserData(g_parser, options);
11426     XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
11427     XML_SetExternalEntityRefHandler(g_parser, external_entity_optioner);
11428     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
11429         != XML_STATUS_ERROR)
11430       break;
11431     /* See comment in test_nsalloc_xmlns() */
11432     nsalloc_teardown();
11433     nsalloc_setup();
11434   }
11435   if (i == 0)
11436     fail("Parsing worked despite failing reallocations");
11437   else if (i == max_realloc_count)
11438     fail("Parsing failed even at max reallocation count");
11439 }
11440 END_TEST
11441 
11442 /* Test that when a namespace is passed through the context mechanism
11443  * to an external entity parser, the parsers handle reallocation
11444  * failures correctly.  The prefix is exactly the right length to
11445  * provoke particular uncommon code paths.
11446  */
11447 START_TEST(test_nsalloc_realloc_long_context_in_dtd) {
11448   const char *text1
11449       = "<!DOCTYPE "
11450         /* 64 characters per line */
11451         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11452         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11453         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11454         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11455         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11456         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11457         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11458         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11459         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11460         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11461         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11462         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11463         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11464         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11465         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11466         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11467         ":doc [\n"
11468         "  <!ENTITY First SYSTEM 'foo/First'>\n"
11469         "]>\n"
11470         "<"
11471         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11472         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11473         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11474         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11475         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11476         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11477         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11478         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11479         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11480         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11481         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11482         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11483         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11484         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11485         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11486         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11487         ":doc xmlns:"
11488         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11489         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11490         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11491         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11492         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11493         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11494         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11495         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11496         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11497         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11498         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11499         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11500         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11501         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11502         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11503         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11504         "='foo/Second'>&First;";
11505   const char *text2
11506       = "</"
11507         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11508         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11509         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11510         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11511         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11512         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11513         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11514         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11515         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11516         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11517         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11518         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11519         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11520         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11521         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11522         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11523         ":doc>";
11524   ExtOption options[] = {{XCS("foo/First"), "Hello world"}, {NULL, NULL}};
11525   int i;
11526   const int max_realloc_count = 20;
11527 
11528   for (i = 0; i < max_realloc_count; i++) {
11529     reallocation_count = i;
11530     XML_SetUserData(g_parser, options);
11531     XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
11532     XML_SetExternalEntityRefHandler(g_parser, external_entity_optioner);
11533     if (_XML_Parse_SINGLE_BYTES(g_parser, text1, (int)strlen(text1), XML_FALSE)
11534             != XML_STATUS_ERROR
11535         && _XML_Parse_SINGLE_BYTES(g_parser, text2, (int)strlen(text2),
11536                                    XML_TRUE)
11537                != XML_STATUS_ERROR)
11538       break;
11539     /* See comment in test_nsalloc_xmlns() */
11540     nsalloc_teardown();
11541     nsalloc_setup();
11542   }
11543   if (i == 0)
11544     fail("Parsing worked despite failing reallocations");
11545   else if (i == max_realloc_count)
11546     fail("Parsing failed even at max reallocation count");
11547 }
11548 END_TEST
11549 
11550 START_TEST(test_nsalloc_long_default_in_ext) {
11551   const char *text
11552       = "<!DOCTYPE doc [\n"
11553         "  <!ATTLIST e a1 CDATA '"
11554         /* 64 characters per line */
11555         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11556         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11557         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11558         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11559         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11560         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11561         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11562         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11563         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11564         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11565         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11566         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11567         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11568         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11569         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11570         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11571         "'>\n"
11572         "  <!ENTITY x SYSTEM 'foo'>\n"
11573         "]>\n"
11574         "<doc>&x;</doc>";
11575   ExtOption options[] = {{XCS("foo"), "<e/>"}, {NULL, NULL}};
11576   int i;
11577   const int max_alloc_count = 50;
11578 
11579   for (i = 0; i < max_alloc_count; i++) {
11580     allocation_count = i;
11581     XML_SetUserData(g_parser, options);
11582     XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
11583     XML_SetExternalEntityRefHandler(g_parser, external_entity_optioner);
11584     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
11585         != XML_STATUS_ERROR)
11586       break;
11587 
11588     /* See comment in test_nsalloc_xmlns() */
11589     nsalloc_teardown();
11590     nsalloc_setup();
11591   }
11592   if (i == 0)
11593     fail("Parsing worked despite failing allocations");
11594   else if (i == max_alloc_count)
11595     fail("Parsing failed even at max allocation count");
11596 }
11597 END_TEST
11598 
11599 START_TEST(test_nsalloc_long_systemid_in_ext) {
11600   const char *text
11601       = "<!DOCTYPE doc SYSTEM 'foo' [\n"
11602         "  <!ENTITY en SYSTEM '"
11603         /* 64 characters per line */
11604         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11605         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11606         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11607         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11608         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11609         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11610         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11611         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11612         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11613         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11614         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11615         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11616         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11617         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11618         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11619         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11620         "'>\n"
11621         "]>\n"
11622         "<doc>&en;</doc>";
11623   ExtOption options[] = {
11624       {XCS("foo"), "<!ELEMENT e EMPTY>"},
11625       {/* clang-format off */
11626             XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/")
11627             XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/")
11628             XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/")
11629             XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/")
11630             XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/")
11631             XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/")
11632             XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/")
11633             XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/")
11634             XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/")
11635             XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/")
11636             XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/")
11637             XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/")
11638             XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/")
11639             XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/")
11640             XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/")
11641             XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"),
11642        /* clang-format on */
11643        "<e/>"},
11644       {NULL, NULL}};
11645   int i;
11646   const int max_alloc_count = 55;
11647 
11648   for (i = 0; i < max_alloc_count; i++) {
11649     allocation_count = i;
11650     XML_SetUserData(g_parser, options);
11651     XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
11652     XML_SetExternalEntityRefHandler(g_parser, external_entity_optioner);
11653     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
11654         != XML_STATUS_ERROR)
11655       break;
11656 
11657     /* See comment in test_nsalloc_xmlns() */
11658     nsalloc_teardown();
11659     nsalloc_setup();
11660   }
11661   if (i == 0)
11662     fail("Parsing worked despite failing allocations");
11663   else if (i == max_alloc_count)
11664     fail("Parsing failed even at max allocation count");
11665 }
11666 END_TEST
11667 
11668 /* Test the effects of allocation failure on parsing an element in a
11669  * namespace.  Based on test_nsalloc_long_context.
11670  */
11671 START_TEST(test_nsalloc_prefixed_element) {
11672   const char *text = "<!DOCTYPE pfx:element SYSTEM 'foo' [\n"
11673                      "  <!ATTLIST pfx:element baz ID #REQUIRED>\n"
11674                      "  <!ENTITY en SYSTEM 'bar'>\n"
11675                      "]>\n"
11676                      "<pfx:element xmlns:pfx='http://example.org/' baz='2'>\n"
11677                      "&en;"
11678                      "</pfx:element>";
11679   ExtOption options[] = {
11680       {XCS("foo"), "<!ELEMENT e EMPTY>"}, {XCS("bar"), "<e/>"}, {NULL, NULL}};
11681   int i;
11682   const int max_alloc_count = 70;
11683 
11684   for (i = 0; i < max_alloc_count; i++) {
11685     allocation_count = i;
11686     XML_SetUserData(g_parser, options);
11687     XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
11688     XML_SetExternalEntityRefHandler(g_parser, external_entity_optioner);
11689     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
11690         != XML_STATUS_ERROR)
11691       break;
11692 
11693     /* See comment in test_nsalloc_xmlns() */
11694     nsalloc_teardown();
11695     nsalloc_setup();
11696   }
11697   if (i == 0)
11698     fail("Success despite failing allocator");
11699   else if (i == max_alloc_count)
11700     fail("Failed even at full allocation count");
11701 }
11702 END_TEST
11703 
11704 #if defined(XML_DTD)
11705 typedef enum XML_Status (*XmlParseFunction)(XML_Parser, const char *, int, int);
11706 
11707 struct AccountingTestCase {
11708   const char *primaryText;
11709   const char *firstExternalText;  /* often NULL */
11710   const char *secondExternalText; /* often NULL */
11711   const unsigned long long expectedCountBytesIndirectExtra;
11712   XML_Bool singleBytesWanted;
11713 };
11714 
11715 static int
11716 accounting_external_entity_ref_handler(XML_Parser parser,
11717                                        const XML_Char *context,
11718                                        const XML_Char *base,
11719                                        const XML_Char *systemId,
11720                                        const XML_Char *publicId) {
11721   UNUSED_P(context);
11722   UNUSED_P(base);
11723   UNUSED_P(publicId);
11724 
11725   const struct AccountingTestCase *const testCase
11726       = (const struct AccountingTestCase *)XML_GetUserData(parser);
11727 
11728   const char *externalText = NULL;
11729   if (xcstrcmp(systemId, XCS("first.ent")) == 0) {
11730     externalText = testCase->firstExternalText;
11731   } else if (xcstrcmp(systemId, XCS("second.ent")) == 0) {
11732     externalText = testCase->secondExternalText;
11733   } else {
11734     assert(! "systemId is neither \"first.ent\" nor \"second.ent\"");
11735   }
11736   assert(externalText);
11737 
11738   XML_Parser entParser = XML_ExternalEntityParserCreate(parser, context, 0);
11739   assert(entParser);
11740 
11741   const XmlParseFunction xmlParseFunction
11742       = testCase->singleBytesWanted ? _XML_Parse_SINGLE_BYTES : XML_Parse;
11743 
11744   const enum XML_Status status = xmlParseFunction(
11745       entParser, externalText, (int)strlen(externalText), XML_TRUE);
11746 
11747   XML_ParserFree(entParser);
11748   return status;
11749 }
11750 
11751 START_TEST(test_accounting_precision) {
11752   const XML_Bool filled_later = XML_TRUE; /* value is arbitrary */
11753   struct AccountingTestCase cases[] = {
11754       {"<e/>", NULL, NULL, 0, 0},
11755       {"<e></e>", NULL, NULL, 0, 0},
11756 
11757       /* Attributes */
11758       {"<e k1=\"v2\" k2=\"v2\"/>", NULL, NULL, 0, filled_later},
11759       {"<e k1=\"v2\" k2=\"v2\"></e>", NULL, NULL, 0, 0},
11760       {"<p:e xmlns:p=\"https://domain.invalid/\" />", NULL, NULL, 0,
11761        filled_later},
11762       {"<e k=\"&amp;&apos;&gt;&lt;&quot;\" />", NULL, NULL,
11763        sizeof(XML_Char) * 5 /* number of predefined entities */, filled_later},
11764       {"<e1 xmlns='https://example.org/'>\n"
11765        "  <e2 xmlns=''/>\n"
11766        "</e1>",
11767        NULL, NULL, 0, filled_later},
11768 
11769       /* Text */
11770       {"<e>text</e>", NULL, NULL, 0, filled_later},
11771       {"<e1><e2>text1<e3/>text2</e2></e1>", NULL, NULL, 0, filled_later},
11772       {"<e>&amp;&apos;&gt;&lt;&quot;</e>", NULL, NULL,
11773        sizeof(XML_Char) * 5 /* number of predefined entities */, filled_later},
11774       {"<e>&#65;&#41;</e>", NULL, NULL, 0, filled_later},
11775 
11776       /* Prolog */
11777       {"<?xml version=\"1.0\"?><root/>", NULL, NULL, 0, filled_later},
11778 
11779       /* Whitespace */
11780       {"  <e1>  <e2>  </e2>  </e1>  ", NULL, NULL, 0, filled_later},
11781       {"<e1  ><e2  /></e1  >", NULL, NULL, 0, filled_later},
11782       {"<e1><e2 k = \"v\"/><e3 k = 'v'/></e1>", NULL, NULL, 0, filled_later},
11783 
11784       /* Comments */
11785       {"<!-- Comment --><e><!-- Comment --></e>", NULL, NULL, 0, filled_later},
11786 
11787       /* Processing instructions */
11788       {"<?xml-stylesheet type=\"text/xsl\" href=\"https://domain.invalid/\" media=\"all\"?><e/>",
11789        NULL, NULL, 0, filled_later},
11790       {"<?pi0?><?pi1 ?><?pi2  ?><!DOCTYPE r SYSTEM 'first.ent'><r/>",
11791        "<?pi3?><!ENTITY % e1 SYSTEM 'second.ent'><?pi4?>%e1;<?pi5?>", "<?pi6?>",
11792        0, filled_later},
11793 
11794       /* CDATA */
11795       {"<e><![CDATA[one two three]]></e>", NULL, NULL, 0, filled_later},
11796       /* The following is the essence of this OSS-Fuzz finding:
11797          https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=34302
11798          https://oss-fuzz.com/testcase-detail/4860575394955264
11799       */
11800       {"<!DOCTYPE r [\n"
11801        "<!ENTITY e \"111<![CDATA[2 <= 2]]>333\">\n"
11802        "]>\n"
11803        "<r>&e;</r>\n",
11804        NULL, NULL, sizeof(XML_Char) * strlen("111<![CDATA[2 <= 2]]>333"),
11805        filled_later},
11806 
11807       /* Conditional sections */
11808       {"<!DOCTYPE r [\n"
11809        "<!ENTITY % draft 'INCLUDE'>\n"
11810        "<!ENTITY % final 'IGNORE'>\n"
11811        "<!ENTITY % import SYSTEM \"first.ent\">\n"
11812        "%import;\n"
11813        "]>\n"
11814        "<r/>\n",
11815        "<![%draft;[<!--1-->]]>\n"
11816        "<![%final;[<!--22-->]]>",
11817        NULL, sizeof(XML_Char) * (strlen("INCLUDE") + strlen("IGNORE")),
11818        filled_later},
11819 
11820       /* General entities */
11821       {"<!DOCTYPE root [\n"
11822        "<!ENTITY nine \"123456789\">\n"
11823        "]>\n"
11824        "<root>&nine;</root>",
11825        NULL, NULL, sizeof(XML_Char) * strlen("123456789"), filled_later},
11826       {"<!DOCTYPE root [\n"
11827        "<!ENTITY nine \"123456789\">\n"
11828        "]>\n"
11829        "<root k1=\"&nine;\"/>",
11830        NULL, NULL, sizeof(XML_Char) * strlen("123456789"), filled_later},
11831       {"<!DOCTYPE root [\n"
11832        "<!ENTITY nine \"123456789\">\n"
11833        "<!ENTITY nine2 \"&nine;&nine;\">\n"
11834        "]>\n"
11835        "<root>&nine2;&nine2;&nine2;</root>",
11836        NULL, NULL,
11837        sizeof(XML_Char) * 3 /* calls to &nine2; */ * 2 /* calls to &nine; */
11838            * (strlen("&nine;") + strlen("123456789")),
11839        filled_later},
11840       {"<!DOCTYPE r [\n"
11841        "  <!ENTITY five SYSTEM 'first.ent'>\n"
11842        "]>\n"
11843        "<r>&five;</r>",
11844        "12345", NULL, 0, filled_later},
11845 
11846       /* Parameter entities */
11847       {"<!DOCTYPE r [\n"
11848        "<!ENTITY % comment \"<!---->\">\n"
11849        "%comment;\n"
11850        "]>\n"
11851        "<r/>",
11852        NULL, NULL, sizeof(XML_Char) * strlen("<!---->"), filled_later},
11853       {"<!DOCTYPE r [\n"
11854        "<!ENTITY % ninedef \"&#60;!ENTITY nine &#34;123456789&#34;&#62;\">\n"
11855        "%ninedef;\n"
11856        "]>\n"
11857        "<r>&nine;</r>",
11858        NULL, NULL,
11859        sizeof(XML_Char)
11860            * (strlen("<!ENTITY nine \"123456789\">") + strlen("123456789")),
11861        filled_later},
11862       {"<!DOCTYPE r [\n"
11863        "<!ENTITY % comment \"<!--1-->\">\n"
11864        "<!ENTITY % comment2 \"&#37;comment;<!--22-->&#37;comment;\">\n"
11865        "%comment2;\n"
11866        "]>\n"
11867        "<r/>\n",
11868        NULL, NULL,
11869        sizeof(XML_Char)
11870            * (strlen("%comment;<!--22-->%comment;") + 2 * strlen("<!--1-->")),
11871        filled_later},
11872       {"<!DOCTYPE r [\n"
11873        "  <!ENTITY % five \"12345\">\n"
11874        "  <!ENTITY % five2def \"&#60;!ENTITY five2 &#34;[&#37;five;][&#37;five;]]]]&#34;&#62;\">\n"
11875        "  %five2def;\n"
11876        "]>\n"
11877        "<r>&five2;</r>",
11878        NULL, NULL, /* from "%five2def;": */
11879        sizeof(XML_Char)
11880            * (strlen("<!ENTITY five2 \"[%five;][%five;]]]]\">")
11881               + 2 /* calls to "%five;" */ * strlen("12345")
11882               + /* from "&five2;": */ strlen("[12345][12345]]]]")),
11883        filled_later},
11884       {"<!DOCTYPE r SYSTEM \"first.ent\">\n"
11885        "<r/>",
11886        "<!ENTITY % comment '<!--1-->'>\n"
11887        "<!ENTITY % comment2 '<!--22-->%comment;<!--22-->%comment;<!--22-->'>\n"
11888        "%comment2;",
11889        NULL,
11890        sizeof(XML_Char)
11891            * (strlen("<!--22-->%comment;<!--22-->%comment;<!--22-->")
11892               + 2 /* calls to "%comment;" */ * strlen("<!---->")),
11893        filled_later},
11894       {"<!DOCTYPE r SYSTEM 'first.ent'>\n"
11895        "<r/>",
11896        "<!ENTITY % e1 PUBLIC 'foo' 'second.ent'>\n"
11897        "<!ENTITY % e2 '<!--22-->%e1;<!--22-->'>\n"
11898        "%e2;\n",
11899        "<!--1-->", sizeof(XML_Char) * strlen("<!--22--><!--1--><!--22-->"),
11900        filled_later},
11901       {
11902           "<!DOCTYPE r SYSTEM 'first.ent'>\n"
11903           "<r/>",
11904           "<!ENTITY % e1 SYSTEM 'second.ent'>\n"
11905           "<!ENTITY % e2 '%e1;'>",
11906           "<?xml version='1.0' encoding='utf-8'?>\n"
11907           "hello\n"
11908           "xml" /* without trailing newline! */,
11909           0,
11910           filled_later,
11911       },
11912       {
11913           "<!DOCTYPE r SYSTEM 'first.ent'>\n"
11914           "<r/>",
11915           "<!ENTITY % e1 SYSTEM 'second.ent'>\n"
11916           "<!ENTITY % e2 '%e1;'>",
11917           "<?xml version='1.0' encoding='utf-8'?>\n"
11918           "hello\n"
11919           "xml\n" /* with trailing newline! */,
11920           0,
11921           filled_later,
11922       },
11923       {"<!DOCTYPE doc SYSTEM 'first.ent'>\n"
11924        "<doc></doc>\n",
11925        "<!ELEMENT doc EMPTY>\n"
11926        "<!ENTITY % e1 SYSTEM 'second.ent'>\n"
11927        "<!ENTITY % e2 '%e1;'>\n"
11928        "%e1;\n",
11929        "\xEF\xBB\xBF<!ATTLIST doc a1 CDATA 'value'>" /* UTF-8 BOM */,
11930        strlen("\xEF\xBB\xBF<!ATTLIST doc a1 CDATA 'value'>"), filled_later},
11931       {"<!DOCTYPE r [\n"
11932        "  <!ENTITY five SYSTEM 'first.ent'>\n"
11933        "]>\n"
11934        "<r>&five;</r>",
11935        "\xEF\xBB\xBF" /* UTF-8 BOM */, NULL, 0, filled_later},
11936   };
11937 
11938   const size_t countCases = sizeof(cases) / sizeof(cases[0]);
11939   size_t u = 0;
11940   for (; u < countCases; u++) {
11941     size_t v = 0;
11942     for (; v < 2; v++) {
11943       const XML_Bool singleBytesWanted = (v == 0) ? XML_FALSE : XML_TRUE;
11944       const unsigned long long expectedCountBytesDirect
11945           = strlen(cases[u].primaryText);
11946       const unsigned long long expectedCountBytesIndirect
11947           = (cases[u].firstExternalText ? strlen(cases[u].firstExternalText)
11948                                         : 0)
11949             + (cases[u].secondExternalText ? strlen(cases[u].secondExternalText)
11950                                            : 0)
11951             + cases[u].expectedCountBytesIndirectExtra;
11952 
11953       XML_Parser parser = XML_ParserCreate(NULL);
11954       XML_SetParamEntityParsing(parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
11955       if (cases[u].firstExternalText) {
11956         XML_SetExternalEntityRefHandler(parser,
11957                                         accounting_external_entity_ref_handler);
11958         XML_SetUserData(parser, (void *)&cases[u]);
11959         cases[u].singleBytesWanted = singleBytesWanted;
11960       }
11961 
11962       const XmlParseFunction xmlParseFunction
11963           = singleBytesWanted ? _XML_Parse_SINGLE_BYTES : XML_Parse;
11964 
11965       enum XML_Status status
11966           = xmlParseFunction(parser, cases[u].primaryText,
11967                              (int)strlen(cases[u].primaryText), XML_TRUE);
11968       if (status != XML_STATUS_OK) {
11969         _xml_failure(parser, __FILE__, __LINE__);
11970       }
11971 
11972       const unsigned long long actualCountBytesDirect
11973           = testingAccountingGetCountBytesDirect(parser);
11974       const unsigned long long actualCountBytesIndirect
11975           = testingAccountingGetCountBytesIndirect(parser);
11976 
11977       XML_ParserFree(parser);
11978 
11979       if (actualCountBytesDirect != expectedCountBytesDirect) {
11980         fprintf(
11981             stderr,
11982             "Document " EXPAT_FMT_SIZE_T("") " of " EXPAT_FMT_SIZE_T("") ", %s: Expected " EXPAT_FMT_ULL(
11983                 "") " count direct bytes, got " EXPAT_FMT_ULL("") " instead.\n",
11984             u + 1, countCases, singleBytesWanted ? "single bytes" : "chunks",
11985             expectedCountBytesDirect, actualCountBytesDirect);
11986         fail("Count of direct bytes is off");
11987       }
11988 
11989       if (actualCountBytesIndirect != expectedCountBytesIndirect) {
11990         fprintf(
11991             stderr,
11992             "Document " EXPAT_FMT_SIZE_T("") " of " EXPAT_FMT_SIZE_T("") ", %s: Expected " EXPAT_FMT_ULL(
11993                 "") " count indirect bytes, got " EXPAT_FMT_ULL("") " instead.\n",
11994             u + 1, countCases, singleBytesWanted ? "single bytes" : "chunks",
11995             expectedCountBytesIndirect, actualCountBytesIndirect);
11996         fail("Count of indirect bytes is off");
11997       }
11998     }
11999   }
12000 }
12001 END_TEST
12002 
12003 static float
12004 portableNAN(void) {
12005   return strtof("nan", NULL);
12006 }
12007 
12008 static float
12009 portableINFINITY(void) {
12010   return strtof("infinity", NULL);
12011 }
12012 
12013 START_TEST(test_billion_laughs_attack_protection_api) {
12014   XML_Parser parserWithoutParent = XML_ParserCreate(NULL);
12015   XML_Parser parserWithParent
12016       = XML_ExternalEntityParserCreate(parserWithoutParent, NULL, NULL);
12017   if (parserWithoutParent == NULL)
12018     fail("parserWithoutParent is NULL");
12019   if (parserWithParent == NULL)
12020     fail("parserWithParent is NULL");
12021 
12022   // XML_SetBillionLaughsAttackProtectionMaximumAmplification, error cases
12023   if (XML_SetBillionLaughsAttackProtectionMaximumAmplification(NULL, 123.0f)
12024       == XML_TRUE)
12025     fail("Call with NULL parser is NOT supposed to succeed");
12026   if (XML_SetBillionLaughsAttackProtectionMaximumAmplification(parserWithParent,
12027                                                                123.0f)
12028       == XML_TRUE)
12029     fail("Call with non-root parser is NOT supposed to succeed");
12030   if (XML_SetBillionLaughsAttackProtectionMaximumAmplification(
12031           parserWithoutParent, portableNAN())
12032       == XML_TRUE)
12033     fail("Call with NaN limit is NOT supposed to succeed");
12034   if (XML_SetBillionLaughsAttackProtectionMaximumAmplification(
12035           parserWithoutParent, -1.0f)
12036       == XML_TRUE)
12037     fail("Call with negative limit is NOT supposed to succeed");
12038   if (XML_SetBillionLaughsAttackProtectionMaximumAmplification(
12039           parserWithoutParent, 0.9f)
12040       == XML_TRUE)
12041     fail("Call with positive limit <1.0 is NOT supposed to succeed");
12042 
12043   // XML_SetBillionLaughsAttackProtectionMaximumAmplification, success cases
12044   if (XML_SetBillionLaughsAttackProtectionMaximumAmplification(
12045           parserWithoutParent, 1.0f)
12046       == XML_FALSE)
12047     fail("Call with positive limit >=1.0 is supposed to succeed");
12048   if (XML_SetBillionLaughsAttackProtectionMaximumAmplification(
12049           parserWithoutParent, 123456.789f)
12050       == XML_FALSE)
12051     fail("Call with positive limit >=1.0 is supposed to succeed");
12052   if (XML_SetBillionLaughsAttackProtectionMaximumAmplification(
12053           parserWithoutParent, portableINFINITY())
12054       == XML_FALSE)
12055     fail("Call with positive limit >=1.0 is supposed to succeed");
12056 
12057   // XML_SetBillionLaughsAttackProtectionActivationThreshold, error cases
12058   if (XML_SetBillionLaughsAttackProtectionActivationThreshold(NULL, 123)
12059       == XML_TRUE)
12060     fail("Call with NULL parser is NOT supposed to succeed");
12061   if (XML_SetBillionLaughsAttackProtectionActivationThreshold(parserWithParent,
12062                                                               123)
12063       == XML_TRUE)
12064     fail("Call with non-root parser is NOT supposed to succeed");
12065 
12066   // XML_SetBillionLaughsAttackProtectionActivationThreshold, success cases
12067   if (XML_SetBillionLaughsAttackProtectionActivationThreshold(
12068           parserWithoutParent, 123)
12069       == XML_FALSE)
12070     fail("Call with non-NULL parentless parser is supposed to succeed");
12071 
12072   XML_ParserFree(parserWithParent);
12073   XML_ParserFree(parserWithoutParent);
12074 }
12075 END_TEST
12076 
12077 START_TEST(test_helper_unsigned_char_to_printable) {
12078   // Smoke test
12079   unsigned char uc = 0;
12080   for (; uc < (unsigned char)-1; uc++) {
12081     const char *const printable = unsignedCharToPrintable(uc);
12082     if (printable == NULL)
12083       fail("unsignedCharToPrintable returned NULL");
12084     if (strlen(printable) < (size_t)1)
12085       fail("unsignedCharToPrintable returned empty string");
12086   }
12087 
12088   // Two concrete samples
12089   if (strcmp(unsignedCharToPrintable('A'), "A") != 0)
12090     fail("unsignedCharToPrintable result mistaken");
12091   if (strcmp(unsignedCharToPrintable('\\'), "\\\\") != 0)
12092     fail("unsignedCharToPrintable result mistaken");
12093 }
12094 END_TEST
12095 #endif // defined(XML_DTD)
12096 
12097 static Suite *
12098 make_suite(void) {
12099   Suite *s = suite_create("basic");
12100   TCase *tc_basic = tcase_create("basic tests");
12101   TCase *tc_namespace = tcase_create("XML namespaces");
12102   TCase *tc_misc = tcase_create("miscellaneous tests");
12103   TCase *tc_alloc = tcase_create("allocation tests");
12104   TCase *tc_nsalloc = tcase_create("namespace allocation tests");
12105 #if defined(XML_DTD)
12106   TCase *tc_accounting = tcase_create("accounting tests");
12107 #endif
12108 
12109   suite_add_tcase(s, tc_basic);
12110   tcase_add_checked_fixture(tc_basic, basic_setup, basic_teardown);
12111   tcase_add_test(tc_basic, test_nul_byte);
12112   tcase_add_test(tc_basic, test_u0000_char);
12113   tcase_add_test(tc_basic, test_siphash_self);
12114   tcase_add_test(tc_basic, test_siphash_spec);
12115   tcase_add_test(tc_basic, test_bom_utf8);
12116   tcase_add_test(tc_basic, test_bom_utf16_be);
12117   tcase_add_test(tc_basic, test_bom_utf16_le);
12118   tcase_add_test(tc_basic, test_nobom_utf16_le);
12119   tcase_add_test(tc_basic, test_illegal_utf8);
12120   tcase_add_test(tc_basic, test_utf8_auto_align);
12121   tcase_add_test(tc_basic, test_utf16);
12122   tcase_add_test(tc_basic, test_utf16_le_epilog_newline);
12123   tcase_add_test(tc_basic, test_not_utf16);
12124   tcase_add_test(tc_basic, test_bad_encoding);
12125   tcase_add_test(tc_basic, test_latin1_umlauts);
12126   tcase_add_test(tc_basic, test_long_utf8_character);
12127   tcase_add_test(tc_basic, test_long_latin1_attribute);
12128   tcase_add_test(tc_basic, test_long_ascii_attribute);
12129   /* Regression test for SF bug #491986. */
12130   tcase_add_test(tc_basic, test_danish_latin1);
12131   /* Regression test for SF bug #514281. */
12132   tcase_add_test(tc_basic, test_french_charref_hexidecimal);
12133   tcase_add_test(tc_basic, test_french_charref_decimal);
12134   tcase_add_test(tc_basic, test_french_latin1);
12135   tcase_add_test(tc_basic, test_french_utf8);
12136   tcase_add_test(tc_basic, test_utf8_false_rejection);
12137   tcase_add_test(tc_basic, test_line_number_after_parse);
12138   tcase_add_test(tc_basic, test_column_number_after_parse);
12139   tcase_add_test(tc_basic, test_line_and_column_numbers_inside_handlers);
12140   tcase_add_test(tc_basic, test_line_number_after_error);
12141   tcase_add_test(tc_basic, test_column_number_after_error);
12142   tcase_add_test(tc_basic, test_really_long_lines);
12143   tcase_add_test(tc_basic, test_really_long_encoded_lines);
12144   tcase_add_test(tc_basic, test_end_element_events);
12145   tcase_add_test(tc_basic, test_attr_whitespace_normalization);
12146   tcase_add_test(tc_basic, test_xmldecl_misplaced);
12147   tcase_add_test(tc_basic, test_xmldecl_invalid);
12148   tcase_add_test(tc_basic, test_xmldecl_missing_attr);
12149   tcase_add_test(tc_basic, test_xmldecl_missing_value);
12150   tcase_add_test(tc_basic, test_unknown_encoding_internal_entity);
12151   tcase_add_test(tc_basic, test_unrecognised_encoding_internal_entity);
12152   tcase_add_test(tc_basic, test_wfc_undeclared_entity_unread_external_subset);
12153   tcase_add_test(tc_basic, test_wfc_undeclared_entity_no_external_subset);
12154   tcase_add_test(tc_basic, test_wfc_undeclared_entity_standalone);
12155   tcase_add_test(tc_basic, test_wfc_undeclared_entity_with_external_subset);
12156   tcase_add_test(tc_basic, test_not_standalone_handler_reject);
12157   tcase_add_test(tc_basic, test_not_standalone_handler_accept);
12158   tcase_add_test(tc_basic,
12159                  test_wfc_undeclared_entity_with_external_subset_standalone);
12160   tcase_add_test(tc_basic, test_entity_with_external_subset_unless_standalone);
12161   tcase_add_test(tc_basic, test_wfc_no_recursive_entity_refs);
12162   tcase_add_test__ifdef_xml_dtd(tc_basic, test_ext_entity_set_encoding);
12163   tcase_add_test__ifdef_xml_dtd(tc_basic, test_ext_entity_no_handler);
12164   tcase_add_test__ifdef_xml_dtd(tc_basic, test_ext_entity_set_bom);
12165   tcase_add_test__ifdef_xml_dtd(tc_basic, test_ext_entity_bad_encoding);
12166   tcase_add_test__ifdef_xml_dtd(tc_basic, test_ext_entity_bad_encoding_2);
12167   tcase_add_test__ifdef_xml_dtd(tc_basic, test_ext_entity_invalid_parse);
12168   tcase_add_test__ifdef_xml_dtd(tc_basic,
12169                                 test_ext_entity_invalid_suspended_parse);
12170   tcase_add_test(tc_basic, test_dtd_default_handling);
12171   tcase_add_test(tc_basic, test_dtd_attr_handling);
12172   tcase_add_test(tc_basic, test_empty_ns_without_namespaces);
12173   tcase_add_test(tc_basic, test_ns_in_attribute_default_without_namespaces);
12174   tcase_add_test(tc_basic, test_stop_parser_between_char_data_calls);
12175   tcase_add_test(tc_basic, test_suspend_parser_between_char_data_calls);
12176   tcase_add_test(tc_basic, test_repeated_stop_parser_between_char_data_calls);
12177   tcase_add_test(tc_basic, test_good_cdata_ascii);
12178   tcase_add_test(tc_basic, test_good_cdata_utf16);
12179   tcase_add_test(tc_basic, test_good_cdata_utf16_le);
12180   tcase_add_test(tc_basic, test_long_cdata_utf16);
12181   tcase_add_test(tc_basic, test_multichar_cdata_utf16);
12182   tcase_add_test(tc_basic, test_utf16_bad_surrogate_pair);
12183   tcase_add_test(tc_basic, test_bad_cdata);
12184   tcase_add_test(tc_basic, test_bad_cdata_utf16);
12185   tcase_add_test(tc_basic, test_stop_parser_between_cdata_calls);
12186   tcase_add_test(tc_basic, test_suspend_parser_between_cdata_calls);
12187   tcase_add_test(tc_basic, test_memory_allocation);
12188   tcase_add_test(tc_basic, test_default_current);
12189   tcase_add_test(tc_basic, test_dtd_elements);
12190   tcase_add_test(tc_basic, test_dtd_elements_nesting);
12191   tcase_add_test__ifdef_xml_dtd(tc_basic, test_set_foreign_dtd);
12192   tcase_add_test__ifdef_xml_dtd(tc_basic, test_foreign_dtd_not_standalone);
12193   tcase_add_test__ifdef_xml_dtd(tc_basic, test_invalid_foreign_dtd);
12194   tcase_add_test__ifdef_xml_dtd(tc_basic, test_foreign_dtd_with_doctype);
12195   tcase_add_test__ifdef_xml_dtd(tc_basic,
12196                                 test_foreign_dtd_without_external_subset);
12197   tcase_add_test__ifdef_xml_dtd(tc_basic, test_empty_foreign_dtd);
12198   tcase_add_test(tc_basic, test_set_base);
12199   tcase_add_test(tc_basic, test_attributes);
12200   tcase_add_test(tc_basic, test_reset_in_entity);
12201   tcase_add_test(tc_basic, test_resume_invalid_parse);
12202   tcase_add_test(tc_basic, test_resume_resuspended);
12203   tcase_add_test(tc_basic, test_cdata_default);
12204   tcase_add_test(tc_basic, test_subordinate_reset);
12205   tcase_add_test(tc_basic, test_subordinate_suspend);
12206   tcase_add_test(tc_basic, test_subordinate_xdecl_suspend);
12207   tcase_add_test(tc_basic, test_subordinate_xdecl_abort);
12208   tcase_add_test(tc_basic, test_explicit_encoding);
12209   tcase_add_test(tc_basic, test_trailing_cr);
12210   tcase_add_test(tc_basic, test_ext_entity_trailing_cr);
12211   tcase_add_test(tc_basic, test_trailing_rsqb);
12212   tcase_add_test(tc_basic, test_ext_entity_trailing_rsqb);
12213   tcase_add_test(tc_basic, test_ext_entity_good_cdata);
12214   tcase_add_test__ifdef_xml_dtd(tc_basic, test_user_parameters);
12215   tcase_add_test__ifdef_xml_dtd(tc_basic, test_ext_entity_ref_parameter);
12216   tcase_add_test(tc_basic, test_empty_parse);
12217   tcase_add_test(tc_basic, test_get_buffer_1);
12218   tcase_add_test(tc_basic, test_get_buffer_2);
12219 #if defined(XML_CONTEXT_BYTES)
12220   tcase_add_test(tc_basic, test_get_buffer_3_overflow);
12221 #endif
12222   tcase_add_test(tc_basic, test_byte_info_at_end);
12223   tcase_add_test(tc_basic, test_byte_info_at_error);
12224   tcase_add_test(tc_basic, test_byte_info_at_cdata);
12225   tcase_add_test(tc_basic, test_predefined_entities);
12226   tcase_add_test__ifdef_xml_dtd(tc_basic, test_invalid_tag_in_dtd);
12227   tcase_add_test(tc_basic, test_not_predefined_entities);
12228   tcase_add_test__ifdef_xml_dtd(tc_basic, test_ignore_section);
12229   tcase_add_test__ifdef_xml_dtd(tc_basic, test_ignore_section_utf16);
12230   tcase_add_test__ifdef_xml_dtd(tc_basic, test_ignore_section_utf16_be);
12231   tcase_add_test__ifdef_xml_dtd(tc_basic, test_bad_ignore_section);
12232   tcase_add_test__ifdef_xml_dtd(tc_basic, test_external_entity_values);
12233   tcase_add_test__ifdef_xml_dtd(tc_basic, test_ext_entity_not_standalone);
12234   tcase_add_test__ifdef_xml_dtd(tc_basic, test_ext_entity_value_abort);
12235   tcase_add_test(tc_basic, test_bad_public_doctype);
12236   tcase_add_test(tc_basic, test_attribute_enum_value);
12237   tcase_add_test(tc_basic, test_predefined_entity_redefinition);
12238   tcase_add_test__ifdef_xml_dtd(tc_basic, test_dtd_stop_processing);
12239   tcase_add_test(tc_basic, test_public_notation_no_sysid);
12240   tcase_add_test(tc_basic, test_nested_groups);
12241   tcase_add_test(tc_basic, test_group_choice);
12242   tcase_add_test(tc_basic, test_standalone_parameter_entity);
12243   tcase_add_test__ifdef_xml_dtd(tc_basic, test_skipped_parameter_entity);
12244   tcase_add_test__ifdef_xml_dtd(tc_basic,
12245                                 test_recursive_external_parameter_entity);
12246   tcase_add_test(tc_basic, test_undefined_ext_entity_in_external_dtd);
12247   tcase_add_test(tc_basic, test_suspend_xdecl);
12248   tcase_add_test(tc_basic, test_abort_epilog);
12249   tcase_add_test(tc_basic, test_abort_epilog_2);
12250   tcase_add_test(tc_basic, test_suspend_epilog);
12251   tcase_add_test(tc_basic, test_suspend_in_sole_empty_tag);
12252   tcase_add_test(tc_basic, test_unfinished_epilog);
12253   tcase_add_test(tc_basic, test_partial_char_in_epilog);
12254   tcase_add_test(tc_basic, test_hash_collision);
12255   tcase_add_test__ifdef_xml_dtd(tc_basic, test_suspend_resume_internal_entity);
12256   tcase_add_test__ifdef_xml_dtd(tc_basic,
12257                                 test_suspend_resume_internal_entity_issue_629);
12258   tcase_add_test__ifdef_xml_dtd(tc_basic, test_resume_entity_with_syntax_error);
12259   tcase_add_test__ifdef_xml_dtd(tc_basic, test_suspend_resume_parameter_entity);
12260   tcase_add_test(tc_basic, test_restart_on_error);
12261   tcase_add_test(tc_basic, test_reject_lt_in_attribute_value);
12262   tcase_add_test(tc_basic, test_reject_unfinished_param_in_att_value);
12263   tcase_add_test(tc_basic, test_trailing_cr_in_att_value);
12264   tcase_add_test(tc_basic, test_standalone_internal_entity);
12265   tcase_add_test(tc_basic, test_skipped_external_entity);
12266   tcase_add_test(tc_basic, test_skipped_null_loaded_ext_entity);
12267   tcase_add_test(tc_basic, test_skipped_unloaded_ext_entity);
12268   tcase_add_test__ifdef_xml_dtd(tc_basic, test_param_entity_with_trailing_cr);
12269   tcase_add_test(tc_basic, test_invalid_character_entity);
12270   tcase_add_test(tc_basic, test_invalid_character_entity_2);
12271   tcase_add_test(tc_basic, test_invalid_character_entity_3);
12272   tcase_add_test(tc_basic, test_invalid_character_entity_4);
12273   tcase_add_test(tc_basic, test_pi_handled_in_default);
12274   tcase_add_test(tc_basic, test_comment_handled_in_default);
12275   tcase_add_test(tc_basic, test_pi_yml);
12276   tcase_add_test(tc_basic, test_pi_xnl);
12277   tcase_add_test(tc_basic, test_pi_xmm);
12278   tcase_add_test(tc_basic, test_utf16_pi);
12279   tcase_add_test(tc_basic, test_utf16_be_pi);
12280   tcase_add_test(tc_basic, test_utf16_be_comment);
12281   tcase_add_test(tc_basic, test_utf16_le_comment);
12282   tcase_add_test(tc_basic, test_missing_encoding_conversion_fn);
12283   tcase_add_test(tc_basic, test_failing_encoding_conversion_fn);
12284   tcase_add_test(tc_basic, test_unknown_encoding_success);
12285   tcase_add_test(tc_basic, test_unknown_encoding_bad_name);
12286   tcase_add_test(tc_basic, test_unknown_encoding_bad_name_2);
12287   tcase_add_test(tc_basic, test_unknown_encoding_long_name_1);
12288   tcase_add_test(tc_basic, test_unknown_encoding_long_name_2);
12289   tcase_add_test(tc_basic, test_invalid_unknown_encoding);
12290   tcase_add_test(tc_basic, test_unknown_ascii_encoding_ok);
12291   tcase_add_test(tc_basic, test_unknown_ascii_encoding_fail);
12292   tcase_add_test(tc_basic, test_unknown_encoding_invalid_length);
12293   tcase_add_test(tc_basic, test_unknown_encoding_invalid_topbit);
12294   tcase_add_test(tc_basic, test_unknown_encoding_invalid_surrogate);
12295   tcase_add_test(tc_basic, test_unknown_encoding_invalid_high);
12296   tcase_add_test(tc_basic, test_unknown_encoding_invalid_attr_value);
12297   tcase_add_test(tc_basic, test_ext_entity_latin1_utf16le_bom);
12298   tcase_add_test(tc_basic, test_ext_entity_latin1_utf16be_bom);
12299   tcase_add_test(tc_basic, test_ext_entity_latin1_utf16le_bom2);
12300   tcase_add_test(tc_basic, test_ext_entity_latin1_utf16be_bom2);
12301   tcase_add_test(tc_basic, test_ext_entity_utf16_be);
12302   tcase_add_test(tc_basic, test_ext_entity_utf16_le);
12303   tcase_add_test(tc_basic, test_ext_entity_utf16_unknown);
12304   tcase_add_test(tc_basic, test_ext_entity_utf8_non_bom);
12305   tcase_add_test(tc_basic, test_utf8_in_cdata_section);
12306   tcase_add_test(tc_basic, test_utf8_in_cdata_section_2);
12307   tcase_add_test(tc_basic, test_utf8_in_start_tags);
12308   tcase_add_test(tc_basic, test_trailing_spaces_in_elements);
12309   tcase_add_test(tc_basic, test_utf16_attribute);
12310   tcase_add_test(tc_basic, test_utf16_second_attr);
12311   tcase_add_test(tc_basic, test_attr_after_solidus);
12312   tcase_add_test__ifdef_xml_dtd(tc_basic, test_utf16_pe);
12313   tcase_add_test(tc_basic, test_bad_attr_desc_keyword);
12314   tcase_add_test(tc_basic, test_bad_attr_desc_keyword_utf16);
12315   tcase_add_test(tc_basic, test_bad_doctype);
12316   tcase_add_test(tc_basic, test_bad_doctype_utf8);
12317   tcase_add_test(tc_basic, test_bad_doctype_utf16);
12318   tcase_add_test(tc_basic, test_bad_doctype_plus);
12319   tcase_add_test(tc_basic, test_bad_doctype_star);
12320   tcase_add_test(tc_basic, test_bad_doctype_query);
12321   tcase_add_test__ifdef_xml_dtd(tc_basic, test_unknown_encoding_bad_ignore);
12322   tcase_add_test(tc_basic, test_entity_in_utf16_be_attr);
12323   tcase_add_test(tc_basic, test_entity_in_utf16_le_attr);
12324   tcase_add_test__ifdef_xml_dtd(tc_basic, test_entity_public_utf16_be);
12325   tcase_add_test__ifdef_xml_dtd(tc_basic, test_entity_public_utf16_le);
12326   tcase_add_test(tc_basic, test_short_doctype);
12327   tcase_add_test(tc_basic, test_short_doctype_2);
12328   tcase_add_test(tc_basic, test_short_doctype_3);
12329   tcase_add_test(tc_basic, test_long_doctype);
12330   tcase_add_test(tc_basic, test_bad_entity);
12331   tcase_add_test(tc_basic, test_bad_entity_2);
12332   tcase_add_test(tc_basic, test_bad_entity_3);
12333   tcase_add_test(tc_basic, test_bad_entity_4);
12334   tcase_add_test(tc_basic, test_bad_notation);
12335   tcase_add_test(tc_basic, test_default_doctype_handler);
12336   tcase_add_test(tc_basic, test_empty_element_abort);
12337   tcase_add_test__ifdef_xml_dtd(tc_basic,
12338                                 test_pool_integrity_with_unfinished_attr);
12339   tcase_add_test(tc_basic, test_nested_entity_suspend);
12340 
12341   suite_add_tcase(s, tc_namespace);
12342   tcase_add_checked_fixture(tc_namespace, namespace_setup, namespace_teardown);
12343   tcase_add_test(tc_namespace, test_return_ns_triplet);
12344   tcase_add_test(tc_namespace, test_ns_tagname_overwrite);
12345   tcase_add_test(tc_namespace, test_ns_tagname_overwrite_triplet);
12346   tcase_add_test(tc_namespace, test_start_ns_clears_start_element);
12347   tcase_add_test__ifdef_xml_dtd(tc_namespace,
12348                                 test_default_ns_from_ext_subset_and_ext_ge);
12349   tcase_add_test(tc_namespace, test_ns_prefix_with_empty_uri_1);
12350   tcase_add_test(tc_namespace, test_ns_prefix_with_empty_uri_2);
12351   tcase_add_test(tc_namespace, test_ns_prefix_with_empty_uri_3);
12352   tcase_add_test(tc_namespace, test_ns_prefix_with_empty_uri_4);
12353   tcase_add_test(tc_namespace, test_ns_unbound_prefix);
12354   tcase_add_test(tc_namespace, test_ns_default_with_empty_uri);
12355   tcase_add_test(tc_namespace, test_ns_duplicate_attrs_diff_prefixes);
12356   tcase_add_test(tc_namespace, test_ns_duplicate_hashes);
12357   tcase_add_test(tc_namespace, test_ns_unbound_prefix_on_attribute);
12358   tcase_add_test(tc_namespace, test_ns_unbound_prefix_on_element);
12359   tcase_add_test(tc_namespace, test_ns_parser_reset);
12360   tcase_add_test(tc_namespace, test_ns_long_element);
12361   tcase_add_test(tc_namespace, test_ns_mixed_prefix_atts);
12362   tcase_add_test(tc_namespace, test_ns_extend_uri_buffer);
12363   tcase_add_test(tc_namespace, test_ns_reserved_attributes);
12364   tcase_add_test(tc_namespace, test_ns_reserved_attributes_2);
12365   tcase_add_test(tc_namespace, test_ns_extremely_long_prefix);
12366   tcase_add_test(tc_namespace, test_ns_unknown_encoding_success);
12367   tcase_add_test(tc_namespace, test_ns_double_colon);
12368   tcase_add_test(tc_namespace, test_ns_double_colon_element);
12369   tcase_add_test(tc_namespace, test_ns_bad_attr_leafname);
12370   tcase_add_test(tc_namespace, test_ns_bad_element_leafname);
12371   tcase_add_test(tc_namespace, test_ns_utf16_leafname);
12372   tcase_add_test(tc_namespace, test_ns_utf16_element_leafname);
12373   tcase_add_test(tc_namespace, test_ns_utf16_doctype);
12374   tcase_add_test(tc_namespace, test_ns_invalid_doctype);
12375   tcase_add_test(tc_namespace, test_ns_double_colon_doctype);
12376   tcase_add_test(tc_namespace, test_ns_separator_in_uri);
12377 
12378   suite_add_tcase(s, tc_misc);
12379   tcase_add_checked_fixture(tc_misc, NULL, basic_teardown);
12380   tcase_add_test(tc_misc, test_misc_alloc_create_parser);
12381   tcase_add_test(tc_misc, test_misc_alloc_create_parser_with_encoding);
12382   tcase_add_test(tc_misc, test_misc_null_parser);
12383   tcase_add_test(tc_misc, test_misc_error_string);
12384   tcase_add_test(tc_misc, test_misc_version);
12385   tcase_add_test(tc_misc, test_misc_features);
12386   tcase_add_test(tc_misc, test_misc_attribute_leak);
12387   tcase_add_test(tc_misc, test_misc_utf16le);
12388   tcase_add_test(tc_misc, test_misc_stop_during_end_handler_issue_240_1);
12389   tcase_add_test(tc_misc, test_misc_stop_during_end_handler_issue_240_2);
12390   tcase_add_test__ifdef_xml_dtd(
12391       tc_misc, test_misc_deny_internal_entity_closing_doctype_issue_317);
12392   tcase_add_test(tc_misc, test_misc_tag_mismatch_reset_leak);
12393 
12394   suite_add_tcase(s, tc_alloc);
12395   tcase_add_checked_fixture(tc_alloc, alloc_setup, alloc_teardown);
12396   tcase_add_test(tc_alloc, test_alloc_parse_xdecl);
12397   tcase_add_test(tc_alloc, test_alloc_parse_xdecl_2);
12398   tcase_add_test(tc_alloc, test_alloc_parse_pi);
12399   tcase_add_test(tc_alloc, test_alloc_parse_pi_2);
12400   tcase_add_test(tc_alloc, test_alloc_parse_pi_3);
12401   tcase_add_test(tc_alloc, test_alloc_parse_comment);
12402   tcase_add_test(tc_alloc, test_alloc_parse_comment_2);
12403   tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_create_external_parser);
12404   tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_run_external_parser);
12405   tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_dtd_copy_default_atts);
12406   tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_external_entity);
12407   tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_ext_entity_set_encoding);
12408   tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_internal_entity);
12409   tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_dtd_default_handling);
12410   tcase_add_test(tc_alloc, test_alloc_explicit_encoding);
12411   tcase_add_test(tc_alloc, test_alloc_set_base);
12412   tcase_add_test(tc_alloc, test_alloc_realloc_buffer);
12413   tcase_add_test(tc_alloc, test_alloc_ext_entity_realloc_buffer);
12414   tcase_add_test(tc_alloc, test_alloc_realloc_many_attributes);
12415   tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_public_entity_value);
12416   tcase_add_test__ifdef_xml_dtd(tc_alloc,
12417                                 test_alloc_realloc_subst_public_entity_value);
12418   tcase_add_test(tc_alloc, test_alloc_parse_public_doctype);
12419   tcase_add_test(tc_alloc, test_alloc_parse_public_doctype_long_name);
12420   tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_set_foreign_dtd);
12421   tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_attribute_enum_value);
12422   tcase_add_test__ifdef_xml_dtd(tc_alloc,
12423                                 test_alloc_realloc_attribute_enum_value);
12424   tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_realloc_implied_attribute);
12425   tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_realloc_default_attribute);
12426   tcase_add_test(tc_alloc, test_alloc_notation);
12427   tcase_add_test(tc_alloc, test_alloc_public_notation);
12428   tcase_add_test(tc_alloc, test_alloc_system_notation);
12429   tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_nested_groups);
12430   tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_realloc_nested_groups);
12431   tcase_add_test(tc_alloc, test_alloc_large_group);
12432   tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_realloc_group_choice);
12433   tcase_add_test(tc_alloc, test_alloc_pi_in_epilog);
12434   tcase_add_test(tc_alloc, test_alloc_comment_in_epilog);
12435   tcase_add_test__ifdef_xml_dtd(tc_alloc,
12436                                 test_alloc_realloc_long_attribute_value);
12437   tcase_add_test(tc_alloc, test_alloc_attribute_whitespace);
12438   tcase_add_test(tc_alloc, test_alloc_attribute_predefined_entity);
12439   tcase_add_test(tc_alloc, test_alloc_long_attr_default_with_char_ref);
12440   tcase_add_test(tc_alloc, test_alloc_long_attr_value);
12441   tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_nested_entities);
12442   tcase_add_test__ifdef_xml_dtd(tc_alloc,
12443                                 test_alloc_realloc_param_entity_newline);
12444   tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_realloc_ce_extends_pe);
12445   tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_realloc_attributes);
12446   tcase_add_test(tc_alloc, test_alloc_long_doc_name);
12447   tcase_add_test(tc_alloc, test_alloc_long_base);
12448   tcase_add_test(tc_alloc, test_alloc_long_public_id);
12449   tcase_add_test(tc_alloc, test_alloc_long_entity_value);
12450   tcase_add_test(tc_alloc, test_alloc_long_notation);
12451   tcase_add_test__ifdef_xml_dtd(
12452       tc_alloc, test_alloc_reset_after_external_entity_parser_create_fail);
12453 
12454   suite_add_tcase(s, tc_nsalloc);
12455   tcase_add_checked_fixture(tc_nsalloc, nsalloc_setup, nsalloc_teardown);
12456   tcase_add_test(tc_nsalloc, test_nsalloc_xmlns);
12457   tcase_add_test(tc_nsalloc, test_nsalloc_parse_buffer);
12458   tcase_add_test(tc_nsalloc, test_nsalloc_long_prefix);
12459   tcase_add_test(tc_nsalloc, test_nsalloc_long_uri);
12460   tcase_add_test(tc_nsalloc, test_nsalloc_long_attr);
12461   tcase_add_test(tc_nsalloc, test_nsalloc_long_attr_prefix);
12462   tcase_add_test(tc_nsalloc, test_nsalloc_realloc_attributes);
12463   tcase_add_test(tc_nsalloc, test_nsalloc_long_element);
12464   tcase_add_test(tc_nsalloc, test_nsalloc_realloc_binding_uri);
12465   tcase_add_test(tc_nsalloc, test_nsalloc_realloc_long_prefix);
12466   tcase_add_test(tc_nsalloc, test_nsalloc_realloc_longer_prefix);
12467   tcase_add_test(tc_nsalloc, test_nsalloc_long_namespace);
12468   tcase_add_test(tc_nsalloc, test_nsalloc_less_long_namespace);
12469   tcase_add_test(tc_nsalloc, test_nsalloc_long_context);
12470   tcase_add_test(tc_nsalloc, test_nsalloc_realloc_long_context);
12471   tcase_add_test(tc_nsalloc, test_nsalloc_realloc_long_context_2);
12472   tcase_add_test(tc_nsalloc, test_nsalloc_realloc_long_context_3);
12473   tcase_add_test(tc_nsalloc, test_nsalloc_realloc_long_context_4);
12474   tcase_add_test(tc_nsalloc, test_nsalloc_realloc_long_context_5);
12475   tcase_add_test(tc_nsalloc, test_nsalloc_realloc_long_context_6);
12476   tcase_add_test(tc_nsalloc, test_nsalloc_realloc_long_context_7);
12477   tcase_add_test(tc_nsalloc, test_nsalloc_realloc_long_ge_name);
12478   tcase_add_test(tc_nsalloc, test_nsalloc_realloc_long_context_in_dtd);
12479   tcase_add_test(tc_nsalloc, test_nsalloc_long_default_in_ext);
12480   tcase_add_test(tc_nsalloc, test_nsalloc_long_systemid_in_ext);
12481   tcase_add_test(tc_nsalloc, test_nsalloc_prefixed_element);
12482 
12483 #if defined(XML_DTD)
12484   suite_add_tcase(s, tc_accounting);
12485   tcase_add_test(tc_accounting, test_accounting_precision);
12486   tcase_add_test(tc_accounting, test_billion_laughs_attack_protection_api);
12487   tcase_add_test(tc_accounting, test_helper_unsigned_char_to_printable);
12488 #endif
12489 
12490   return s;
12491 }
12492 
12493 int
12494 main(int argc, char *argv[]) {
12495   int i, nf;
12496   int verbosity = CK_NORMAL;
12497   Suite *s = make_suite();
12498   SRunner *sr = srunner_create(s);
12499 
12500   /* run the tests for internal helper functions */
12501   testhelper_is_whitespace_normalized();
12502 
12503   for (i = 1; i < argc; ++i) {
12504     char *opt = argv[i];
12505     if (strcmp(opt, "-v") == 0 || strcmp(opt, "--verbose") == 0)
12506       verbosity = CK_VERBOSE;
12507     else if (strcmp(opt, "-q") == 0 || strcmp(opt, "--quiet") == 0)
12508       verbosity = CK_SILENT;
12509     else {
12510       fprintf(stderr, "runtests: unknown option '%s'\n", opt);
12511       return 2;
12512     }
12513   }
12514   if (verbosity != CK_SILENT)
12515     printf("Expat version: %" XML_FMT_STR "\n", XML_ExpatVersion());
12516   srunner_run_all(sr, verbosity);
12517   nf = srunner_ntests_failed(sr);
12518   srunner_free(sr);
12519 
12520   return (nf == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
12521 }
12522