xref: /freebsd/contrib/expat/tests/runtests.c (revision 81e0e7b9e36d6a25b3af6482811318e085537d2f)
1 /* Run the Expat test suite
2                             __  __            _
3                          ___\ \/ /_ __   __ _| |_
4                         / _ \\  /| '_ \ / _` | __|
5                        |  __//  \| |_) | (_| | |_
6                         \___/_/\_\ .__/ \__,_|\__|
7                                  |_| XML parser
8 
9    Copyright (c) 2001-2006 Fred L. Drake, Jr. <fdrake@users.sourceforge.net>
10    Copyright (c) 2003      Greg Stein <gstein@users.sourceforge.net>
11    Copyright (c) 2005-2007 Steven Solie <steven@solie.ca>
12    Copyright (c) 2005-2012 Karl Waclawek <karl@waclawek.net>
13    Copyright (c) 2016-2022 Sebastian Pipping <sebastian@pipping.org>
14    Copyright (c) 2017-2018 Rhodri James <rhodri@wildebeest.org.uk>
15    Copyright (c) 2017      Joe Orton <jorton@redhat.com>
16    Copyright (c) 2017      José Gutiérrez de la Concha <jose@zeroc.com>
17    Copyright (c) 2018      Marco Maggi <marco.maggi-ipsu@poste.it>
18    Copyright (c) 2019      David Loffredo <loffredo@steptools.com>
19    Copyright (c) 2020      Tim Gates <tim.gates@iress.com>
20    Copyright (c) 2021      Dong-hee Na <donghee.na@python.org>
21    Licensed under the MIT license:
22 
23    Permission is  hereby granted,  free of charge,  to any  person obtaining
24    a  copy  of  this  software   and  associated  documentation  files  (the
25    "Software"),  to  deal in  the  Software  without restriction,  including
26    without  limitation the  rights  to use,  copy,  modify, merge,  publish,
27    distribute, sublicense, and/or sell copies of the Software, and to permit
28    persons  to whom  the Software  is  furnished to  do so,  subject to  the
29    following conditions:
30 
31    The above copyright  notice and this permission notice  shall be included
32    in all copies or substantial portions of the Software.
33 
34    THE  SOFTWARE  IS  PROVIDED  "AS  IS",  WITHOUT  WARRANTY  OF  ANY  KIND,
35    EXPRESS  OR IMPLIED,  INCLUDING  BUT  NOT LIMITED  TO  THE WARRANTIES  OF
36    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
37    NO EVENT SHALL THE AUTHORS OR  COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
38    DAMAGES OR  OTHER LIABILITY, WHETHER  IN AN  ACTION OF CONTRACT,  TORT OR
39    OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
40    USE OR OTHER DEALINGS IN THE SOFTWARE.
41 */
42 
43 #include <expat_config.h>
44 
45 #if defined(NDEBUG)
46 #  undef NDEBUG /* because test suite relies on assert(...) at the moment */
47 #endif
48 
49 #include <assert.h>
50 #include <stdlib.h>
51 #include <stdio.h>
52 #include <string.h>
53 #include <stddef.h> /* ptrdiff_t */
54 #include <ctype.h>
55 #include <limits.h>
56 #include <stdint.h> /* intptr_t uint64_t */
57 #include <math.h>   /* NAN, INFINITY, isnan */
58 
59 #if ! defined(__cplusplus)
60 #  include <stdbool.h>
61 #endif
62 
63 #include "expat.h"
64 #include "chardata.h"
65 #include "structdata.h"
66 #include "internal.h"
67 #include "minicheck.h"
68 #include "memcheck.h"
69 #include "siphash.h"
70 #include "ascii.h" /* for ASCII_xxx */
71 
72 #ifdef XML_LARGE_SIZE
73 #  define XML_FMT_INT_MOD "ll"
74 #else
75 #  define XML_FMT_INT_MOD "l"
76 #endif
77 
78 #ifdef XML_UNICODE_WCHAR_T
79 #  define XML_FMT_CHAR "lc"
80 #  define XML_FMT_STR "ls"
81 #  include <wchar.h>
82 #  define xcstrlen(s) wcslen(s)
83 #  define xcstrcmp(s, t) wcscmp((s), (t))
84 #  define xcstrncmp(s, t, n) wcsncmp((s), (t), (n))
85 #  define XCS(s) _XCS(s)
86 #  define _XCS(s) L##s
87 #else
88 #  ifdef XML_UNICODE
89 #    error "No support for UTF-16 character without wchar_t in tests"
90 #  else
91 #    define XML_FMT_CHAR "c"
92 #    define XML_FMT_STR "s"
93 #    define xcstrlen(s) strlen(s)
94 #    define xcstrcmp(s, t) strcmp((s), (t))
95 #    define xcstrncmp(s, t, n) strncmp((s), (t), (n))
96 #    define XCS(s) s
97 #  endif /* XML_UNICODE */
98 #endif   /* XML_UNICODE_WCHAR_T */
99 
100 static XML_Parser g_parser = NULL;
101 
102 static void
103 tcase_add_test__ifdef_xml_dtd(TCase *tc, tcase_test_function test) {
104 #ifdef XML_DTD
105   tcase_add_test(tc, test);
106 #else
107   UNUSED_P(tc);
108   UNUSED_P(test);
109 #endif
110 }
111 
112 static void
113 basic_setup(void) {
114   g_parser = XML_ParserCreate(NULL);
115   if (g_parser == NULL)
116     fail("Parser not created.");
117 }
118 
119 static void
120 basic_teardown(void) {
121   if (g_parser != NULL) {
122     XML_ParserFree(g_parser);
123     g_parser = NULL;
124   }
125 }
126 
127 /* Generate a failure using the parser state to create an error message;
128    this should be used when the parser reports an error we weren't
129    expecting.
130 */
131 static void
132 _xml_failure(XML_Parser parser, const char *file, int line) {
133   char buffer[1024];
134   enum XML_Error err = XML_GetErrorCode(parser);
135   sprintf(buffer,
136           "    %d: %" XML_FMT_STR " (line %" XML_FMT_INT_MOD
137           "u, offset %" XML_FMT_INT_MOD "u)\n    reported from %s, line %d\n",
138           err, XML_ErrorString(err), XML_GetCurrentLineNumber(parser),
139           XML_GetCurrentColumnNumber(parser), file, line);
140   _fail_unless(0, file, line, buffer);
141 }
142 
143 static enum XML_Status
144 _XML_Parse_SINGLE_BYTES(XML_Parser parser, const char *s, int len,
145                         int isFinal) {
146   enum XML_Status res = XML_STATUS_ERROR;
147   int offset = 0;
148 
149   if (len == 0) {
150     return XML_Parse(parser, s, len, isFinal);
151   }
152 
153   for (; offset < len; offset++) {
154     const int innerIsFinal = (offset == len - 1) && isFinal;
155     const char c = s[offset]; /* to help out-of-bounds detection */
156     res = XML_Parse(parser, &c, sizeof(char), innerIsFinal);
157     if (res != XML_STATUS_OK) {
158       return res;
159     }
160   }
161   return res;
162 }
163 
164 #define xml_failure(parser) _xml_failure((parser), __FILE__, __LINE__)
165 
166 static void
167 _expect_failure(const char *text, enum XML_Error errorCode,
168                 const char *errorMessage, const char *file, int lineno) {
169   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
170       == XML_STATUS_OK)
171     /* Hackish use of _fail_unless() macro, but let's us report
172        the right filename and line number. */
173     _fail_unless(0, file, lineno, errorMessage);
174   if (XML_GetErrorCode(g_parser) != errorCode)
175     _xml_failure(g_parser, file, lineno);
176 }
177 
178 #define expect_failure(text, errorCode, errorMessage)                          \
179   _expect_failure((text), (errorCode), (errorMessage), __FILE__, __LINE__)
180 
181 /* Dummy handlers for when we need to set a handler to tickle a bug,
182    but it doesn't need to do anything.
183 */
184 static unsigned long dummy_handler_flags = 0;
185 
186 #define DUMMY_START_DOCTYPE_HANDLER_FLAG (1UL << 0)
187 #define DUMMY_END_DOCTYPE_HANDLER_FLAG (1UL << 1)
188 #define DUMMY_ENTITY_DECL_HANDLER_FLAG (1UL << 2)
189 #define DUMMY_NOTATION_DECL_HANDLER_FLAG (1UL << 3)
190 #define DUMMY_ELEMENT_DECL_HANDLER_FLAG (1UL << 4)
191 #define DUMMY_ATTLIST_DECL_HANDLER_FLAG (1UL << 5)
192 #define DUMMY_COMMENT_HANDLER_FLAG (1UL << 6)
193 #define DUMMY_PI_HANDLER_FLAG (1UL << 7)
194 #define DUMMY_START_ELEMENT_HANDLER_FLAG (1UL << 8)
195 #define DUMMY_START_CDATA_HANDLER_FLAG (1UL << 9)
196 #define DUMMY_END_CDATA_HANDLER_FLAG (1UL << 10)
197 #define DUMMY_UNPARSED_ENTITY_DECL_HANDLER_FLAG (1UL << 11)
198 #define DUMMY_START_NS_DECL_HANDLER_FLAG (1UL << 12)
199 #define DUMMY_END_NS_DECL_HANDLER_FLAG (1UL << 13)
200 #define DUMMY_START_DOCTYPE_DECL_HANDLER_FLAG (1UL << 14)
201 #define DUMMY_END_DOCTYPE_DECL_HANDLER_FLAG (1UL << 15)
202 #define DUMMY_SKIP_HANDLER_FLAG (1UL << 16)
203 #define DUMMY_DEFAULT_HANDLER_FLAG (1UL << 17)
204 
205 static void XMLCALL
206 dummy_xdecl_handler(void *userData, const XML_Char *version,
207                     const XML_Char *encoding, int standalone) {
208   UNUSED_P(userData);
209   UNUSED_P(version);
210   UNUSED_P(encoding);
211   UNUSED_P(standalone);
212 }
213 
214 static void XMLCALL
215 dummy_start_doctype_handler(void *userData, const XML_Char *doctypeName,
216                             const XML_Char *sysid, const XML_Char *pubid,
217                             int has_internal_subset) {
218   UNUSED_P(userData);
219   UNUSED_P(doctypeName);
220   UNUSED_P(sysid);
221   UNUSED_P(pubid);
222   UNUSED_P(has_internal_subset);
223   dummy_handler_flags |= DUMMY_START_DOCTYPE_HANDLER_FLAG;
224 }
225 
226 static void XMLCALL
227 dummy_end_doctype_handler(void *userData) {
228   UNUSED_P(userData);
229   dummy_handler_flags |= DUMMY_END_DOCTYPE_HANDLER_FLAG;
230 }
231 
232 static void XMLCALL
233 dummy_entity_decl_handler(void *userData, const XML_Char *entityName,
234                           int is_parameter_entity, const XML_Char *value,
235                           int value_length, const XML_Char *base,
236                           const XML_Char *systemId, const XML_Char *publicId,
237                           const XML_Char *notationName) {
238   UNUSED_P(userData);
239   UNUSED_P(entityName);
240   UNUSED_P(is_parameter_entity);
241   UNUSED_P(value);
242   UNUSED_P(value_length);
243   UNUSED_P(base);
244   UNUSED_P(systemId);
245   UNUSED_P(publicId);
246   UNUSED_P(notationName);
247   dummy_handler_flags |= DUMMY_ENTITY_DECL_HANDLER_FLAG;
248 }
249 
250 static void XMLCALL
251 dummy_notation_decl_handler(void *userData, const XML_Char *notationName,
252                             const XML_Char *base, const XML_Char *systemId,
253                             const XML_Char *publicId) {
254   UNUSED_P(userData);
255   UNUSED_P(notationName);
256   UNUSED_P(base);
257   UNUSED_P(systemId);
258   UNUSED_P(publicId);
259   dummy_handler_flags |= DUMMY_NOTATION_DECL_HANDLER_FLAG;
260 }
261 
262 static void XMLCALL
263 dummy_element_decl_handler(void *userData, const XML_Char *name,
264                            XML_Content *model) {
265   UNUSED_P(userData);
266   UNUSED_P(name);
267   /* The content model must be freed by the handler.  Unfortunately
268    * we cannot pass the parser as the userData because this is used
269    * with other handlers that require other userData.
270    */
271   XML_FreeContentModel(g_parser, model);
272   dummy_handler_flags |= DUMMY_ELEMENT_DECL_HANDLER_FLAG;
273 }
274 
275 static void XMLCALL
276 dummy_attlist_decl_handler(void *userData, const XML_Char *elname,
277                            const XML_Char *attname, const XML_Char *att_type,
278                            const XML_Char *dflt, int isrequired) {
279   UNUSED_P(userData);
280   UNUSED_P(elname);
281   UNUSED_P(attname);
282   UNUSED_P(att_type);
283   UNUSED_P(dflt);
284   UNUSED_P(isrequired);
285   dummy_handler_flags |= DUMMY_ATTLIST_DECL_HANDLER_FLAG;
286 }
287 
288 static void XMLCALL
289 dummy_comment_handler(void *userData, const XML_Char *data) {
290   UNUSED_P(userData);
291   UNUSED_P(data);
292   dummy_handler_flags |= DUMMY_COMMENT_HANDLER_FLAG;
293 }
294 
295 static void XMLCALL
296 dummy_pi_handler(void *userData, const XML_Char *target, const XML_Char *data) {
297   UNUSED_P(userData);
298   UNUSED_P(target);
299   UNUSED_P(data);
300   dummy_handler_flags |= DUMMY_PI_HANDLER_FLAG;
301 }
302 
303 static void XMLCALL
304 dummy_start_element(void *userData, const XML_Char *name,
305                     const XML_Char **atts) {
306   UNUSED_P(userData);
307   UNUSED_P(name);
308   UNUSED_P(atts);
309   dummy_handler_flags |= DUMMY_START_ELEMENT_HANDLER_FLAG;
310 }
311 
312 static void XMLCALL
313 dummy_end_element(void *userData, const XML_Char *name) {
314   UNUSED_P(userData);
315   UNUSED_P(name);
316 }
317 
318 static void XMLCALL
319 dummy_start_cdata_handler(void *userData) {
320   UNUSED_P(userData);
321   dummy_handler_flags |= DUMMY_START_CDATA_HANDLER_FLAG;
322 }
323 
324 static void XMLCALL
325 dummy_end_cdata_handler(void *userData) {
326   UNUSED_P(userData);
327   dummy_handler_flags |= DUMMY_END_CDATA_HANDLER_FLAG;
328 }
329 
330 static void XMLCALL
331 dummy_cdata_handler(void *userData, const XML_Char *s, int len) {
332   UNUSED_P(userData);
333   UNUSED_P(s);
334   UNUSED_P(len);
335 }
336 
337 static void XMLCALL
338 dummy_start_namespace_decl_handler(void *userData, const XML_Char *prefix,
339                                    const XML_Char *uri) {
340   UNUSED_P(userData);
341   UNUSED_P(prefix);
342   UNUSED_P(uri);
343   dummy_handler_flags |= DUMMY_START_NS_DECL_HANDLER_FLAG;
344 }
345 
346 static void XMLCALL
347 dummy_end_namespace_decl_handler(void *userData, const XML_Char *prefix) {
348   UNUSED_P(userData);
349   UNUSED_P(prefix);
350   dummy_handler_flags |= DUMMY_END_NS_DECL_HANDLER_FLAG;
351 }
352 
353 /* This handler is obsolete, but while the code exists we should
354  * ensure that dealing with the handler is covered by tests.
355  */
356 static void XMLCALL
357 dummy_unparsed_entity_decl_handler(void *userData, const XML_Char *entityName,
358                                    const XML_Char *base,
359                                    const XML_Char *systemId,
360                                    const XML_Char *publicId,
361                                    const XML_Char *notationName) {
362   UNUSED_P(userData);
363   UNUSED_P(entityName);
364   UNUSED_P(base);
365   UNUSED_P(systemId);
366   UNUSED_P(publicId);
367   UNUSED_P(notationName);
368   dummy_handler_flags |= DUMMY_UNPARSED_ENTITY_DECL_HANDLER_FLAG;
369 }
370 
371 static void XMLCALL
372 dummy_default_handler(void *userData, const XML_Char *s, int len) {
373   UNUSED_P(userData);
374   UNUSED_P(s);
375   UNUSED_P(len);
376 }
377 
378 static void XMLCALL
379 dummy_start_doctype_decl_handler(void *userData, const XML_Char *doctypeName,
380                                  const XML_Char *sysid, const XML_Char *pubid,
381                                  int has_internal_subset) {
382   UNUSED_P(userData);
383   UNUSED_P(doctypeName);
384   UNUSED_P(sysid);
385   UNUSED_P(pubid);
386   UNUSED_P(has_internal_subset);
387   dummy_handler_flags |= DUMMY_START_DOCTYPE_DECL_HANDLER_FLAG;
388 }
389 
390 static void XMLCALL
391 dummy_end_doctype_decl_handler(void *userData) {
392   UNUSED_P(userData);
393   dummy_handler_flags |= DUMMY_END_DOCTYPE_DECL_HANDLER_FLAG;
394 }
395 
396 static void XMLCALL
397 dummy_skip_handler(void *userData, const XML_Char *entityName,
398                    int is_parameter_entity) {
399   UNUSED_P(userData);
400   UNUSED_P(entityName);
401   UNUSED_P(is_parameter_entity);
402   dummy_handler_flags |= DUMMY_SKIP_HANDLER_FLAG;
403 }
404 
405 /* Useful external entity handler */
406 typedef struct ExtOption {
407   const XML_Char *system_id;
408   const char *parse_text;
409 } ExtOption;
410 
411 static int XMLCALL
412 external_entity_optioner(XML_Parser parser, const XML_Char *context,
413                          const XML_Char *base, const XML_Char *systemId,
414                          const XML_Char *publicId) {
415   ExtOption *options = (ExtOption *)XML_GetUserData(parser);
416   XML_Parser ext_parser;
417 
418   UNUSED_P(base);
419   UNUSED_P(publicId);
420   while (options->parse_text != NULL) {
421     if (! xcstrcmp(systemId, options->system_id)) {
422       enum XML_Status rc;
423       ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
424       if (ext_parser == NULL)
425         return XML_STATUS_ERROR;
426       rc = _XML_Parse_SINGLE_BYTES(ext_parser, options->parse_text,
427                                    (int)strlen(options->parse_text), XML_TRUE);
428       XML_ParserFree(ext_parser);
429       return rc;
430     }
431     options++;
432   }
433   fail("No suitable option found");
434   return XML_STATUS_ERROR;
435 }
436 
437 /*
438  * Parameter entity evaluation support.
439  */
440 #define ENTITY_MATCH_FAIL (-1)
441 #define ENTITY_MATCH_NOT_FOUND (0)
442 #define ENTITY_MATCH_SUCCESS (1)
443 static const XML_Char *entity_name_to_match = NULL;
444 static const XML_Char *entity_value_to_match = NULL;
445 static int entity_match_flag = ENTITY_MATCH_NOT_FOUND;
446 
447 static void XMLCALL
448 param_entity_match_handler(void *userData, const XML_Char *entityName,
449                            int is_parameter_entity, const XML_Char *value,
450                            int value_length, const XML_Char *base,
451                            const XML_Char *systemId, const XML_Char *publicId,
452                            const XML_Char *notationName) {
453   UNUSED_P(userData);
454   UNUSED_P(base);
455   UNUSED_P(systemId);
456   UNUSED_P(publicId);
457   UNUSED_P(notationName);
458   if (! is_parameter_entity || entity_name_to_match == NULL
459       || entity_value_to_match == NULL) {
460     return;
461   }
462   if (! xcstrcmp(entityName, entity_name_to_match)) {
463     /* The cast here is safe because we control the horizontal and
464      * the vertical, and we therefore know our strings are never
465      * going to overflow an int.
466      */
467     if (value_length != (int)xcstrlen(entity_value_to_match)
468         || xcstrncmp(value, entity_value_to_match, value_length)) {
469       entity_match_flag = ENTITY_MATCH_FAIL;
470     } else {
471       entity_match_flag = ENTITY_MATCH_SUCCESS;
472     }
473   }
474   /* Else leave the match flag alone */
475 }
476 
477 /*
478  * Character & encoding tests.
479  */
480 
481 START_TEST(test_nul_byte) {
482   char text[] = "<doc>\0</doc>";
483 
484   /* test that a NUL byte (in US-ASCII data) is an error */
485   if (_XML_Parse_SINGLE_BYTES(g_parser, text, sizeof(text) - 1, XML_TRUE)
486       == XML_STATUS_OK)
487     fail("Parser did not report error on NUL-byte.");
488   if (XML_GetErrorCode(g_parser) != XML_ERROR_INVALID_TOKEN)
489     xml_failure(g_parser);
490 }
491 END_TEST
492 
493 START_TEST(test_u0000_char) {
494   /* test that a NUL byte (in US-ASCII data) is an error */
495   expect_failure("<doc>&#0;</doc>", XML_ERROR_BAD_CHAR_REF,
496                  "Parser did not report error on NUL-byte.");
497 }
498 END_TEST
499 
500 START_TEST(test_siphash_self) {
501   if (! sip24_valid())
502     fail("SipHash self-test failed");
503 }
504 END_TEST
505 
506 START_TEST(test_siphash_spec) {
507   /* https://131002.net/siphash/siphash.pdf (page 19, "Test values") */
508   const char message[] = "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09"
509                          "\x0a\x0b\x0c\x0d\x0e";
510   const size_t len = sizeof(message) - 1;
511   const uint64_t expected = _SIP_ULL(0xa129ca61U, 0x49be45e5U);
512   struct siphash state;
513   struct sipkey key;
514 
515   sip_tokey(&key, "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09"
516                   "\x0a\x0b\x0c\x0d\x0e\x0f");
517   sip24_init(&state, &key);
518 
519   /* Cover spread across calls */
520   sip24_update(&state, message, 4);
521   sip24_update(&state, message + 4, len - 4);
522 
523   /* Cover null length */
524   sip24_update(&state, message, 0);
525 
526   if (sip24_final(&state) != expected)
527     fail("sip24_final failed spec test\n");
528 
529   /* Cover wrapper */
530   if (siphash24(message, len, &key) != expected)
531     fail("siphash24 failed spec test\n");
532 }
533 END_TEST
534 
535 START_TEST(test_bom_utf8) {
536   /* This test is really just making sure we don't core on a UTF-8 BOM. */
537   const char *text = "\357\273\277<e/>";
538 
539   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
540       == XML_STATUS_ERROR)
541     xml_failure(g_parser);
542 }
543 END_TEST
544 
545 START_TEST(test_bom_utf16_be) {
546   char text[] = "\376\377\0<\0e\0/\0>";
547 
548   if (_XML_Parse_SINGLE_BYTES(g_parser, text, sizeof(text) - 1, XML_TRUE)
549       == XML_STATUS_ERROR)
550     xml_failure(g_parser);
551 }
552 END_TEST
553 
554 START_TEST(test_bom_utf16_le) {
555   char text[] = "\377\376<\0e\0/\0>\0";
556 
557   if (_XML_Parse_SINGLE_BYTES(g_parser, text, sizeof(text) - 1, XML_TRUE)
558       == XML_STATUS_ERROR)
559     xml_failure(g_parser);
560 }
561 END_TEST
562 
563 /* Parse whole buffer at once to exercise a different code path */
564 START_TEST(test_nobom_utf16_le) {
565   char text[] = " \0<\0e\0/\0>\0";
566 
567   if (XML_Parse(g_parser, text, sizeof(text) - 1, XML_TRUE) == XML_STATUS_ERROR)
568     xml_failure(g_parser);
569 }
570 END_TEST
571 
572 static void XMLCALL
573 accumulate_characters(void *userData, const XML_Char *s, int len) {
574   CharData_AppendXMLChars((CharData *)userData, s, len);
575 }
576 
577 static void XMLCALL
578 accumulate_attribute(void *userData, const XML_Char *name,
579                      const XML_Char **atts) {
580   CharData *storage = (CharData *)userData;
581   UNUSED_P(name);
582   /* Check there are attributes to deal with */
583   if (atts == NULL)
584     return;
585 
586   while (storage->count < 0 && atts[0] != NULL) {
587     /* "accumulate" the value of the first attribute we see */
588     CharData_AppendXMLChars(storage, atts[1], -1);
589     atts += 2;
590   }
591 }
592 
593 static void
594 _run_character_check(const char *text, const XML_Char *expected,
595                      const char *file, int line) {
596   CharData storage;
597 
598   CharData_Init(&storage);
599   XML_SetUserData(g_parser, &storage);
600   XML_SetCharacterDataHandler(g_parser, accumulate_characters);
601   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
602       == XML_STATUS_ERROR)
603     _xml_failure(g_parser, file, line);
604   CharData_CheckXMLChars(&storage, expected);
605 }
606 
607 #define run_character_check(text, expected)                                    \
608   _run_character_check(text, expected, __FILE__, __LINE__)
609 
610 static void
611 _run_attribute_check(const char *text, const XML_Char *expected,
612                      const char *file, int line) {
613   CharData storage;
614 
615   CharData_Init(&storage);
616   XML_SetUserData(g_parser, &storage);
617   XML_SetStartElementHandler(g_parser, accumulate_attribute);
618   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
619       == XML_STATUS_ERROR)
620     _xml_failure(g_parser, file, line);
621   CharData_CheckXMLChars(&storage, expected);
622 }
623 
624 #define run_attribute_check(text, expected)                                    \
625   _run_attribute_check(text, expected, __FILE__, __LINE__)
626 
627 typedef struct ExtTest {
628   const char *parse_text;
629   const XML_Char *encoding;
630   CharData *storage;
631 } ExtTest;
632 
633 static void XMLCALL
634 ext_accumulate_characters(void *userData, const XML_Char *s, int len) {
635   ExtTest *test_data = (ExtTest *)userData;
636   accumulate_characters(test_data->storage, s, len);
637 }
638 
639 static void
640 _run_ext_character_check(const char *text, ExtTest *test_data,
641                          const XML_Char *expected, const char *file, int line) {
642   CharData *const storage = (CharData *)malloc(sizeof(CharData));
643 
644   CharData_Init(storage);
645   test_data->storage = storage;
646   XML_SetUserData(g_parser, test_data);
647   XML_SetCharacterDataHandler(g_parser, ext_accumulate_characters);
648   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
649       == XML_STATUS_ERROR)
650     _xml_failure(g_parser, file, line);
651   CharData_CheckXMLChars(storage, expected);
652 
653   free(storage);
654 }
655 
656 #define run_ext_character_check(text, test_data, expected)                     \
657   _run_ext_character_check(text, test_data, expected, __FILE__, __LINE__)
658 
659 /* Regression test for SF bug #491986. */
660 START_TEST(test_danish_latin1) {
661   const char *text = "<?xml version='1.0' encoding='iso-8859-1'?>\n"
662                      "<e>J\xF8rgen \xE6\xF8\xE5\xC6\xD8\xC5</e>";
663 #ifdef XML_UNICODE
664   const XML_Char *expected
665       = XCS("J\x00f8rgen \x00e6\x00f8\x00e5\x00c6\x00d8\x00c5");
666 #else
667   const XML_Char *expected
668       = XCS("J\xC3\xB8rgen \xC3\xA6\xC3\xB8\xC3\xA5\xC3\x86\xC3\x98\xC3\x85");
669 #endif
670   run_character_check(text, expected);
671 }
672 END_TEST
673 
674 /* Regression test for SF bug #514281. */
675 START_TEST(test_french_charref_hexidecimal) {
676   const char *text = "<?xml version='1.0' encoding='iso-8859-1'?>\n"
677                      "<doc>&#xE9;&#xE8;&#xE0;&#xE7;&#xEA;&#xC8;</doc>";
678 #ifdef XML_UNICODE
679   const XML_Char *expected = XCS("\x00e9\x00e8\x00e0\x00e7\x00ea\x00c8");
680 #else
681   const XML_Char *expected
682       = XCS("\xC3\xA9\xC3\xA8\xC3\xA0\xC3\xA7\xC3\xAA\xC3\x88");
683 #endif
684   run_character_check(text, expected);
685 }
686 END_TEST
687 
688 START_TEST(test_french_charref_decimal) {
689   const char *text = "<?xml version='1.0' encoding='iso-8859-1'?>\n"
690                      "<doc>&#233;&#232;&#224;&#231;&#234;&#200;</doc>";
691 #ifdef XML_UNICODE
692   const XML_Char *expected = XCS("\x00e9\x00e8\x00e0\x00e7\x00ea\x00c8");
693 #else
694   const XML_Char *expected
695       = XCS("\xC3\xA9\xC3\xA8\xC3\xA0\xC3\xA7\xC3\xAA\xC3\x88");
696 #endif
697   run_character_check(text, expected);
698 }
699 END_TEST
700 
701 START_TEST(test_french_latin1) {
702   const char *text = "<?xml version='1.0' encoding='iso-8859-1'?>\n"
703                      "<doc>\xE9\xE8\xE0\xE7\xEa\xC8</doc>";
704 #ifdef XML_UNICODE
705   const XML_Char *expected = XCS("\x00e9\x00e8\x00e0\x00e7\x00ea\x00c8");
706 #else
707   const XML_Char *expected
708       = XCS("\xC3\xA9\xC3\xA8\xC3\xA0\xC3\xA7\xC3\xAA\xC3\x88");
709 #endif
710   run_character_check(text, expected);
711 }
712 END_TEST
713 
714 START_TEST(test_french_utf8) {
715   const char *text = "<?xml version='1.0' encoding='utf-8'?>\n"
716                      "<doc>\xC3\xA9</doc>";
717 #ifdef XML_UNICODE
718   const XML_Char *expected = XCS("\x00e9");
719 #else
720   const XML_Char *expected = XCS("\xC3\xA9");
721 #endif
722   run_character_check(text, expected);
723 }
724 END_TEST
725 
726 /* Regression test for SF bug #600479.
727    XXX There should be a test that exercises all legal XML Unicode
728    characters as PCDATA and attribute value content, and XML Name
729    characters as part of element and attribute names.
730 */
731 START_TEST(test_utf8_false_rejection) {
732   const char *text = "<doc>\xEF\xBA\xBF</doc>";
733 #ifdef XML_UNICODE
734   const XML_Char *expected = XCS("\xfebf");
735 #else
736   const XML_Char *expected = XCS("\xEF\xBA\xBF");
737 #endif
738   run_character_check(text, expected);
739 }
740 END_TEST
741 
742 /* Regression test for SF bug #477667.
743    This test assures that any 8-bit character followed by a 7-bit
744    character will not be mistakenly interpreted as a valid UTF-8
745    sequence.
746 */
747 START_TEST(test_illegal_utf8) {
748   char text[100];
749   int i;
750 
751   for (i = 128; i <= 255; ++i) {
752     sprintf(text, "<e>%ccd</e>", i);
753     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
754         == XML_STATUS_OK) {
755       sprintf(text, "expected token error for '%c' (ordinal %d) in UTF-8 text",
756               i, i);
757       fail(text);
758     } else if (XML_GetErrorCode(g_parser) != XML_ERROR_INVALID_TOKEN)
759       xml_failure(g_parser);
760     /* Reset the parser since we use the same parser repeatedly. */
761     XML_ParserReset(g_parser, NULL);
762   }
763 }
764 END_TEST
765 
766 /* Examples, not masks: */
767 #define UTF8_LEAD_1 "\x7f" /* 0b01111111 */
768 #define UTF8_LEAD_2 "\xdf" /* 0b11011111 */
769 #define UTF8_LEAD_3 "\xef" /* 0b11101111 */
770 #define UTF8_LEAD_4 "\xf7" /* 0b11110111 */
771 #define UTF8_FOLLOW "\xbf" /* 0b10111111 */
772 
773 START_TEST(test_utf8_auto_align) {
774   struct TestCase {
775     ptrdiff_t expectedMovementInChars;
776     const char *input;
777   };
778 
779   struct TestCase cases[] = {
780       {00, ""},
781 
782       {00, UTF8_LEAD_1},
783 
784       {-1, UTF8_LEAD_2},
785       {00, UTF8_LEAD_2 UTF8_FOLLOW},
786 
787       {-1, UTF8_LEAD_3},
788       {-2, UTF8_LEAD_3 UTF8_FOLLOW},
789       {00, UTF8_LEAD_3 UTF8_FOLLOW UTF8_FOLLOW},
790 
791       {-1, UTF8_LEAD_4},
792       {-2, UTF8_LEAD_4 UTF8_FOLLOW},
793       {-3, UTF8_LEAD_4 UTF8_FOLLOW UTF8_FOLLOW},
794       {00, UTF8_LEAD_4 UTF8_FOLLOW UTF8_FOLLOW UTF8_FOLLOW},
795   };
796 
797   size_t i = 0;
798   bool success = true;
799   for (; i < sizeof(cases) / sizeof(*cases); i++) {
800     const char *fromLim = cases[i].input + strlen(cases[i].input);
801     const char *const fromLimInitially = fromLim;
802     ptrdiff_t actualMovementInChars;
803 
804     _INTERNAL_trim_to_complete_utf8_characters(cases[i].input, &fromLim);
805 
806     actualMovementInChars = (fromLim - fromLimInitially);
807     if (actualMovementInChars != cases[i].expectedMovementInChars) {
808       size_t j = 0;
809       success = false;
810       printf("[-] UTF-8 case %2u: Expected movement by %2d chars"
811              ", actually moved by %2d chars: \"",
812              (unsigned)(i + 1), (int)cases[i].expectedMovementInChars,
813              (int)actualMovementInChars);
814       for (; j < strlen(cases[i].input); j++) {
815         printf("\\x%02x", (unsigned char)cases[i].input[j]);
816       }
817       printf("\"\n");
818     }
819   }
820 
821   if (! success) {
822     fail("UTF-8 auto-alignment is not bullet-proof\n");
823   }
824 }
825 END_TEST
826 
827 START_TEST(test_utf16) {
828   /* <?xml version="1.0" encoding="UTF-16"?>
829    *  <doc a='123'>some {A} text</doc>
830    *
831    * where {A} is U+FF21, FULLWIDTH LATIN CAPITAL LETTER A
832    */
833   char text[]
834       = "\000<\000?\000x\000m\000\154\000 \000v\000e\000r\000s\000i\000o"
835         "\000n\000=\000'\0001\000.\000\060\000'\000 \000e\000n\000c\000o"
836         "\000d\000i\000n\000g\000=\000'\000U\000T\000F\000-\0001\000\066"
837         "\000'\000?\000>\000\n"
838         "\000<\000d\000o\000c\000 \000a\000=\000'\0001\0002\0003\000'\000>"
839         "\000s\000o\000m\000e\000 \xff\x21\000 \000t\000e\000x\000t\000"
840         "<\000/\000d\000o\000c\000>";
841 #ifdef XML_UNICODE
842   const XML_Char *expected = XCS("some \xff21 text");
843 #else
844   const XML_Char *expected = XCS("some \357\274\241 text");
845 #endif
846   CharData storage;
847 
848   CharData_Init(&storage);
849   XML_SetUserData(g_parser, &storage);
850   XML_SetCharacterDataHandler(g_parser, accumulate_characters);
851   if (_XML_Parse_SINGLE_BYTES(g_parser, text, sizeof(text) - 1, XML_TRUE)
852       == XML_STATUS_ERROR)
853     xml_failure(g_parser);
854   CharData_CheckXMLChars(&storage, expected);
855 }
856 END_TEST
857 
858 START_TEST(test_utf16_le_epilog_newline) {
859   unsigned int first_chunk_bytes = 17;
860   char text[] = "\xFF\xFE"                  /* BOM */
861                 "<\000e\000/\000>\000"      /* document element */
862                 "\r\000\n\000\r\000\n\000"; /* epilog */
863 
864   if (first_chunk_bytes >= sizeof(text) - 1)
865     fail("bad value of first_chunk_bytes");
866   if (_XML_Parse_SINGLE_BYTES(g_parser, text, first_chunk_bytes, XML_FALSE)
867       == XML_STATUS_ERROR)
868     xml_failure(g_parser);
869   else {
870     enum XML_Status rc;
871     rc = _XML_Parse_SINGLE_BYTES(g_parser, text + first_chunk_bytes,
872                                  sizeof(text) - first_chunk_bytes - 1,
873                                  XML_TRUE);
874     if (rc == XML_STATUS_ERROR)
875       xml_failure(g_parser);
876   }
877 }
878 END_TEST
879 
880 /* Test that an outright lie in the encoding is faulted */
881 START_TEST(test_not_utf16) {
882   const char *text = "<?xml version='1.0' encoding='utf-16'?>"
883                      "<doc>Hi</doc>";
884 
885   /* Use a handler to provoke the appropriate code paths */
886   XML_SetXmlDeclHandler(g_parser, dummy_xdecl_handler);
887   expect_failure(text, XML_ERROR_INCORRECT_ENCODING,
888                  "UTF-16 declared in UTF-8 not faulted");
889 }
890 END_TEST
891 
892 /* Test that an unknown encoding is rejected */
893 START_TEST(test_bad_encoding) {
894   const char *text = "<doc>Hi</doc>";
895 
896   if (! XML_SetEncoding(g_parser, XCS("unknown-encoding")))
897     fail("XML_SetEncoding failed");
898   expect_failure(text, XML_ERROR_UNKNOWN_ENCODING,
899                  "Unknown encoding not faulted");
900 }
901 END_TEST
902 
903 /* Regression test for SF bug #481609, #774028. */
904 START_TEST(test_latin1_umlauts) {
905   const char *text
906       = "<?xml version='1.0' encoding='iso-8859-1'?>\n"
907         "<e a='\xE4 \xF6 \xFC &#228; &#246; &#252; &#x00E4; &#x0F6; &#xFC; >'\n"
908         "  >\xE4 \xF6 \xFC &#228; &#246; &#252; &#x00E4; &#x0F6; &#xFC; ></e>";
909 #ifdef XML_UNICODE
910   /* Expected results in UTF-16 */
911   const XML_Char *expected = XCS("\x00e4 \x00f6 \x00fc ")
912       XCS("\x00e4 \x00f6 \x00fc ") XCS("\x00e4 \x00f6 \x00fc >");
913 #else
914   /* Expected results in UTF-8 */
915   const XML_Char *expected = XCS("\xC3\xA4 \xC3\xB6 \xC3\xBC ")
916       XCS("\xC3\xA4 \xC3\xB6 \xC3\xBC ") XCS("\xC3\xA4 \xC3\xB6 \xC3\xBC >");
917 #endif
918 
919   run_character_check(text, expected);
920   XML_ParserReset(g_parser, NULL);
921   run_attribute_check(text, expected);
922   /* Repeat with a default handler */
923   XML_ParserReset(g_parser, NULL);
924   XML_SetDefaultHandler(g_parser, dummy_default_handler);
925   run_character_check(text, expected);
926   XML_ParserReset(g_parser, NULL);
927   XML_SetDefaultHandler(g_parser, dummy_default_handler);
928   run_attribute_check(text, expected);
929 }
930 END_TEST
931 
932 /* Test that an element name with a 4-byte UTF-8 character is rejected */
933 START_TEST(test_long_utf8_character) {
934   const char *text
935       = "<?xml version='1.0' encoding='utf-8'?>\n"
936         /* 0xf0 0x90 0x80 0x80 = U+10000, the first Linear B character */
937         "<do\xf0\x90\x80\x80/>";
938   expect_failure(text, XML_ERROR_INVALID_TOKEN,
939                  "4-byte UTF-8 character in element name not faulted");
940 }
941 END_TEST
942 
943 /* Test that a long latin-1 attribute (too long to convert in one go)
944  * is correctly converted
945  */
946 START_TEST(test_long_latin1_attribute) {
947   const char *text
948       = "<?xml version='1.0' encoding='iso-8859-1'?>\n"
949         "<doc att='"
950         /* 64 characters per line */
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         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
966         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
967         /* Last character splits across a buffer boundary */
968         "\xe4'>\n</doc>";
969 
970   const XML_Char *expected =
971       /* 64 characters per line */
972       /* clang-format off */
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("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
988         XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO")
989   /* clang-format on */
990 #ifdef XML_UNICODE
991                                                   XCS("\x00e4");
992 #else
993                                                   XCS("\xc3\xa4");
994 #endif
995 
996   run_attribute_check(text, expected);
997 }
998 END_TEST
999 
1000 /* Test that a long ASCII attribute (too long to convert in one go)
1001  * is correctly converted
1002  */
1003 START_TEST(test_long_ascii_attribute) {
1004   const char *text
1005       = "<?xml version='1.0' encoding='us-ascii'?>\n"
1006         "<doc att='"
1007         /* 64 characters per line */
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         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1024         "01234'>\n</doc>";
1025   const XML_Char *expected =
1026       /* 64 characters per line */
1027       /* clang-format off */
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("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
1044         XCS("01234");
1045   /* clang-format on */
1046 
1047   run_attribute_check(text, expected);
1048 }
1049 END_TEST
1050 
1051 /* Regression test #1 for SF bug #653180. */
1052 START_TEST(test_line_number_after_parse) {
1053   const char *text = "<tag>\n"
1054                      "\n"
1055                      "\n</tag>";
1056   XML_Size lineno;
1057 
1058   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_FALSE)
1059       == XML_STATUS_ERROR)
1060     xml_failure(g_parser);
1061   lineno = XML_GetCurrentLineNumber(g_parser);
1062   if (lineno != 4) {
1063     char buffer[100];
1064     sprintf(buffer, "expected 4 lines, saw %" XML_FMT_INT_MOD "u", lineno);
1065     fail(buffer);
1066   }
1067 }
1068 END_TEST
1069 
1070 /* Regression test #2 for SF bug #653180. */
1071 START_TEST(test_column_number_after_parse) {
1072   const char *text = "<tag></tag>";
1073   XML_Size colno;
1074 
1075   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_FALSE)
1076       == XML_STATUS_ERROR)
1077     xml_failure(g_parser);
1078   colno = XML_GetCurrentColumnNumber(g_parser);
1079   if (colno != 11) {
1080     char buffer[100];
1081     sprintf(buffer, "expected 11 columns, saw %" XML_FMT_INT_MOD "u", colno);
1082     fail(buffer);
1083   }
1084 }
1085 END_TEST
1086 
1087 #define STRUCT_START_TAG 0
1088 #define STRUCT_END_TAG 1
1089 static void XMLCALL
1090 start_element_event_handler2(void *userData, const XML_Char *name,
1091                              const XML_Char **attr) {
1092   StructData *storage = (StructData *)userData;
1093   UNUSED_P(attr);
1094   StructData_AddItem(storage, name, XML_GetCurrentColumnNumber(g_parser),
1095                      XML_GetCurrentLineNumber(g_parser), STRUCT_START_TAG);
1096 }
1097 
1098 static void XMLCALL
1099 end_element_event_handler2(void *userData, const XML_Char *name) {
1100   StructData *storage = (StructData *)userData;
1101   StructData_AddItem(storage, name, XML_GetCurrentColumnNumber(g_parser),
1102                      XML_GetCurrentLineNumber(g_parser), STRUCT_END_TAG);
1103 }
1104 
1105 /* Regression test #3 for SF bug #653180. */
1106 START_TEST(test_line_and_column_numbers_inside_handlers) {
1107   const char *text = "<a>\n"      /* Unix end-of-line */
1108                      "  <b>\r\n"  /* Windows end-of-line */
1109                      "    <c/>\r" /* Mac OS end-of-line */
1110                      "  </b>\n"
1111                      "  <d>\n"
1112                      "    <f/>\n"
1113                      "  </d>\n"
1114                      "</a>";
1115   const StructDataEntry expected[]
1116       = {{XCS("a"), 0, 1, STRUCT_START_TAG}, {XCS("b"), 2, 2, STRUCT_START_TAG},
1117          {XCS("c"), 4, 3, STRUCT_START_TAG}, {XCS("c"), 8, 3, STRUCT_END_TAG},
1118          {XCS("b"), 2, 4, STRUCT_END_TAG},   {XCS("d"), 2, 5, STRUCT_START_TAG},
1119          {XCS("f"), 4, 6, STRUCT_START_TAG}, {XCS("f"), 8, 6, STRUCT_END_TAG},
1120          {XCS("d"), 2, 7, STRUCT_END_TAG},   {XCS("a"), 0, 8, STRUCT_END_TAG}};
1121   const int expected_count = sizeof(expected) / sizeof(StructDataEntry);
1122   StructData storage;
1123 
1124   StructData_Init(&storage);
1125   XML_SetUserData(g_parser, &storage);
1126   XML_SetStartElementHandler(g_parser, start_element_event_handler2);
1127   XML_SetEndElementHandler(g_parser, end_element_event_handler2);
1128   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
1129       == XML_STATUS_ERROR)
1130     xml_failure(g_parser);
1131 
1132   StructData_CheckItems(&storage, expected, expected_count);
1133   StructData_Dispose(&storage);
1134 }
1135 END_TEST
1136 
1137 /* Regression test #4 for SF bug #653180. */
1138 START_TEST(test_line_number_after_error) {
1139   const char *text = "<a>\n"
1140                      "  <b>\n"
1141                      "  </a>"; /* missing </b> */
1142   XML_Size lineno;
1143   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_FALSE)
1144       != XML_STATUS_ERROR)
1145     fail("Expected a parse error");
1146 
1147   lineno = XML_GetCurrentLineNumber(g_parser);
1148   if (lineno != 3) {
1149     char buffer[100];
1150     sprintf(buffer, "expected 3 lines, saw %" XML_FMT_INT_MOD "u", lineno);
1151     fail(buffer);
1152   }
1153 }
1154 END_TEST
1155 
1156 /* Regression test #5 for SF bug #653180. */
1157 START_TEST(test_column_number_after_error) {
1158   const char *text = "<a>\n"
1159                      "  <b>\n"
1160                      "  </a>"; /* missing </b> */
1161   XML_Size colno;
1162   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_FALSE)
1163       != XML_STATUS_ERROR)
1164     fail("Expected a parse error");
1165 
1166   colno = XML_GetCurrentColumnNumber(g_parser);
1167   if (colno != 4) {
1168     char buffer[100];
1169     sprintf(buffer, "expected 4 columns, saw %" XML_FMT_INT_MOD "u", colno);
1170     fail(buffer);
1171   }
1172 }
1173 END_TEST
1174 
1175 /* Regression test for SF bug #478332. */
1176 START_TEST(test_really_long_lines) {
1177   /* This parses an input line longer than INIT_DATA_BUF_SIZE
1178      characters long (defined to be 1024 in xmlparse.c).  We take a
1179      really cheesy approach to building the input buffer, because
1180      this avoids writing bugs in buffer-filling code.
1181   */
1182   const char *text
1183       = "<e>"
1184         /* 64 chars */
1185         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1186         /* until we have at least 1024 characters on the line: */
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         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1203         "</e>";
1204   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
1205       == XML_STATUS_ERROR)
1206     xml_failure(g_parser);
1207 }
1208 END_TEST
1209 
1210 /* Test cdata processing across a buffer boundary */
1211 START_TEST(test_really_long_encoded_lines) {
1212   /* As above, except that we want to provoke an output buffer
1213    * overflow with a non-trivial encoding.  For this we need to pass
1214    * the whole cdata in one go, not byte-by-byte.
1215    */
1216   void *buffer;
1217   const char *text
1218       = "<?xml version='1.0' encoding='iso-8859-1'?>"
1219         "<e>"
1220         /* 64 chars */
1221         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1222         /* until we have at least 1024 characters on the line: */
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         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1239         "</e>";
1240   int parse_len = (int)strlen(text);
1241 
1242   /* Need a cdata handler to provoke the code path we want to test */
1243   XML_SetCharacterDataHandler(g_parser, dummy_cdata_handler);
1244   buffer = XML_GetBuffer(g_parser, parse_len);
1245   if (buffer == NULL)
1246     fail("Could not allocate parse buffer");
1247   assert(buffer != NULL);
1248   memcpy(buffer, text, parse_len);
1249   if (XML_ParseBuffer(g_parser, parse_len, XML_TRUE) == XML_STATUS_ERROR)
1250     xml_failure(g_parser);
1251 }
1252 END_TEST
1253 
1254 /*
1255  * Element event tests.
1256  */
1257 
1258 static void XMLCALL
1259 start_element_event_handler(void *userData, const XML_Char *name,
1260                             const XML_Char **atts) {
1261   UNUSED_P(atts);
1262   CharData_AppendXMLChars((CharData *)userData, name, -1);
1263 }
1264 
1265 static void XMLCALL
1266 end_element_event_handler(void *userData, const XML_Char *name) {
1267   CharData *storage = (CharData *)userData;
1268   CharData_AppendXMLChars(storage, XCS("/"), 1);
1269   CharData_AppendXMLChars(storage, name, -1);
1270 }
1271 
1272 START_TEST(test_end_element_events) {
1273   const char *text = "<a><b><c/></b><d><f/></d></a>";
1274   const XML_Char *expected = XCS("/c/b/f/d/a");
1275   CharData storage;
1276 
1277   CharData_Init(&storage);
1278   XML_SetUserData(g_parser, &storage);
1279   XML_SetEndElementHandler(g_parser, end_element_event_handler);
1280   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
1281       == XML_STATUS_ERROR)
1282     xml_failure(g_parser);
1283   CharData_CheckXMLChars(&storage, expected);
1284 }
1285 END_TEST
1286 
1287 /*
1288  * Attribute tests.
1289  */
1290 
1291 /* Helpers used by the following test; this checks any "attr" and "refs"
1292    attributes to make sure whitespace has been normalized.
1293 
1294    Return true if whitespace has been normalized in a string, using
1295    the rules for attribute value normalization.  The 'is_cdata' flag
1296    is needed since CDATA attributes don't need to have multiple
1297    whitespace characters collapsed to a single space, while other
1298    attribute data types do.  (Section 3.3.3 of the recommendation.)
1299 */
1300 static int
1301 is_whitespace_normalized(const XML_Char *s, int is_cdata) {
1302   int blanks = 0;
1303   int at_start = 1;
1304   while (*s) {
1305     if (*s == XCS(' '))
1306       ++blanks;
1307     else if (*s == XCS('\t') || *s == XCS('\n') || *s == XCS('\r'))
1308       return 0;
1309     else {
1310       if (at_start) {
1311         at_start = 0;
1312         if (blanks && ! is_cdata)
1313           /* illegal leading blanks */
1314           return 0;
1315       } else if (blanks > 1 && ! is_cdata)
1316         return 0;
1317       blanks = 0;
1318     }
1319     ++s;
1320   }
1321   if (blanks && ! is_cdata)
1322     return 0;
1323   return 1;
1324 }
1325 
1326 /* Check the attribute whitespace checker: */
1327 static void
1328 testhelper_is_whitespace_normalized(void) {
1329   assert(is_whitespace_normalized(XCS("abc"), 0));
1330   assert(is_whitespace_normalized(XCS("abc"), 1));
1331   assert(is_whitespace_normalized(XCS("abc def ghi"), 0));
1332   assert(is_whitespace_normalized(XCS("abc def ghi"), 1));
1333   assert(! is_whitespace_normalized(XCS(" abc def ghi"), 0));
1334   assert(is_whitespace_normalized(XCS(" abc def ghi"), 1));
1335   assert(! is_whitespace_normalized(XCS("abc  def ghi"), 0));
1336   assert(is_whitespace_normalized(XCS("abc  def ghi"), 1));
1337   assert(! is_whitespace_normalized(XCS("abc def ghi "), 0));
1338   assert(is_whitespace_normalized(XCS("abc def ghi "), 1));
1339   assert(! is_whitespace_normalized(XCS(" "), 0));
1340   assert(is_whitespace_normalized(XCS(" "), 1));
1341   assert(! is_whitespace_normalized(XCS("\t"), 0));
1342   assert(! is_whitespace_normalized(XCS("\t"), 1));
1343   assert(! is_whitespace_normalized(XCS("\n"), 0));
1344   assert(! is_whitespace_normalized(XCS("\n"), 1));
1345   assert(! is_whitespace_normalized(XCS("\r"), 0));
1346   assert(! is_whitespace_normalized(XCS("\r"), 1));
1347   assert(! is_whitespace_normalized(XCS("abc\t def"), 1));
1348 }
1349 
1350 static void XMLCALL
1351 check_attr_contains_normalized_whitespace(void *userData, const XML_Char *name,
1352                                           const XML_Char **atts) {
1353   int i;
1354   UNUSED_P(userData);
1355   UNUSED_P(name);
1356   for (i = 0; atts[i] != NULL; i += 2) {
1357     const XML_Char *attrname = atts[i];
1358     const XML_Char *value = atts[i + 1];
1359     if (xcstrcmp(XCS("attr"), attrname) == 0
1360         || xcstrcmp(XCS("ents"), attrname) == 0
1361         || xcstrcmp(XCS("refs"), attrname) == 0) {
1362       if (! is_whitespace_normalized(value, 0)) {
1363         char buffer[256];
1364         sprintf(buffer,
1365                 "attribute value not normalized: %" XML_FMT_STR
1366                 "='%" XML_FMT_STR "'",
1367                 attrname, value);
1368         fail(buffer);
1369       }
1370     }
1371   }
1372 }
1373 
1374 START_TEST(test_attr_whitespace_normalization) {
1375   const char *text
1376       = "<!DOCTYPE doc [\n"
1377         "  <!ATTLIST doc\n"
1378         "            attr NMTOKENS #REQUIRED\n"
1379         "            ents ENTITIES #REQUIRED\n"
1380         "            refs IDREFS   #REQUIRED>\n"
1381         "]>\n"
1382         "<doc attr='    a  b c\t\td\te\t' refs=' id-1   \t  id-2\t\t'  \n"
1383         "     ents=' ent-1   \t\r\n"
1384         "            ent-2  ' >\n"
1385         "  <e id='id-1'/>\n"
1386         "  <e id='id-2'/>\n"
1387         "</doc>";
1388 
1389   XML_SetStartElementHandler(g_parser,
1390                              check_attr_contains_normalized_whitespace);
1391   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
1392       == XML_STATUS_ERROR)
1393     xml_failure(g_parser);
1394 }
1395 END_TEST
1396 
1397 /*
1398  * XML declaration tests.
1399  */
1400 
1401 START_TEST(test_xmldecl_misplaced) {
1402   expect_failure("\n"
1403                  "<?xml version='1.0'?>\n"
1404                  "<a/>",
1405                  XML_ERROR_MISPLACED_XML_PI,
1406                  "failed to report misplaced XML declaration");
1407 }
1408 END_TEST
1409 
1410 START_TEST(test_xmldecl_invalid) {
1411   expect_failure("<?xml version='1.0' \xc3\xa7?>\n<doc/>", XML_ERROR_XML_DECL,
1412                  "Failed to report invalid XML declaration");
1413 }
1414 END_TEST
1415 
1416 START_TEST(test_xmldecl_missing_attr) {
1417   expect_failure("<?xml ='1.0'?>\n<doc/>\n", XML_ERROR_XML_DECL,
1418                  "Failed to report missing XML declaration attribute");
1419 }
1420 END_TEST
1421 
1422 START_TEST(test_xmldecl_missing_value) {
1423   expect_failure("<?xml version='1.0' encoding='us-ascii' standalone?>\n"
1424                  "<doc/>",
1425                  XML_ERROR_XML_DECL,
1426                  "Failed to report missing attribute value");
1427 }
1428 END_TEST
1429 
1430 /* Regression test for SF bug #584832. */
1431 static int XMLCALL
1432 UnknownEncodingHandler(void *data, const XML_Char *encoding,
1433                        XML_Encoding *info) {
1434   UNUSED_P(data);
1435   if (xcstrcmp(encoding, XCS("unsupported-encoding")) == 0) {
1436     int i;
1437     for (i = 0; i < 256; ++i)
1438       info->map[i] = i;
1439     info->data = NULL;
1440     info->convert = NULL;
1441     info->release = NULL;
1442     return XML_STATUS_OK;
1443   }
1444   return XML_STATUS_ERROR;
1445 }
1446 
1447 START_TEST(test_unknown_encoding_internal_entity) {
1448   const char *text = "<?xml version='1.0' encoding='unsupported-encoding'?>\n"
1449                      "<!DOCTYPE test [<!ENTITY foo 'bar'>]>\n"
1450                      "<test a='&foo;'/>";
1451 
1452   XML_SetUnknownEncodingHandler(g_parser, UnknownEncodingHandler, NULL);
1453   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
1454       == XML_STATUS_ERROR)
1455     xml_failure(g_parser);
1456 }
1457 END_TEST
1458 
1459 /* Test unrecognised encoding handler */
1460 static void
1461 dummy_release(void *data) {
1462   UNUSED_P(data);
1463 }
1464 
1465 static int XMLCALL
1466 UnrecognisedEncodingHandler(void *data, const XML_Char *encoding,
1467                             XML_Encoding *info) {
1468   UNUSED_P(data);
1469   UNUSED_P(encoding);
1470   info->data = NULL;
1471   info->convert = NULL;
1472   info->release = dummy_release;
1473   return XML_STATUS_ERROR;
1474 }
1475 
1476 START_TEST(test_unrecognised_encoding_internal_entity) {
1477   const char *text = "<?xml version='1.0' encoding='unsupported-encoding'?>\n"
1478                      "<!DOCTYPE test [<!ENTITY foo 'bar'>]>\n"
1479                      "<test a='&foo;'/>";
1480 
1481   XML_SetUnknownEncodingHandler(g_parser, UnrecognisedEncodingHandler, NULL);
1482   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
1483       != XML_STATUS_ERROR)
1484     fail("Unrecognised encoding not rejected");
1485 }
1486 END_TEST
1487 
1488 /* Regression test for SF bug #620106. */
1489 static int XMLCALL
1490 external_entity_loader(XML_Parser parser, const XML_Char *context,
1491                        const XML_Char *base, const XML_Char *systemId,
1492                        const XML_Char *publicId) {
1493   ExtTest *test_data = (ExtTest *)XML_GetUserData(parser);
1494   XML_Parser extparser;
1495 
1496   UNUSED_P(base);
1497   UNUSED_P(systemId);
1498   UNUSED_P(publicId);
1499   extparser = XML_ExternalEntityParserCreate(parser, context, NULL);
1500   if (extparser == NULL)
1501     fail("Could not create external entity parser.");
1502   if (test_data->encoding != NULL) {
1503     if (! XML_SetEncoding(extparser, test_data->encoding))
1504       fail("XML_SetEncoding() ignored for external entity");
1505   }
1506   if (_XML_Parse_SINGLE_BYTES(extparser, test_data->parse_text,
1507                               (int)strlen(test_data->parse_text), XML_TRUE)
1508       == XML_STATUS_ERROR) {
1509     xml_failure(extparser);
1510     return XML_STATUS_ERROR;
1511   }
1512   XML_ParserFree(extparser);
1513   return XML_STATUS_OK;
1514 }
1515 
1516 START_TEST(test_ext_entity_set_encoding) {
1517   const char *text = "<!DOCTYPE doc [\n"
1518                      "  <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n"
1519                      "]>\n"
1520                      "<doc>&en;</doc>";
1521   ExtTest test_data
1522       = {/* This text says it's an unsupported encoding, but it's really
1523             UTF-8, which we tell Expat using XML_SetEncoding().
1524          */
1525          "<?xml encoding='iso-8859-3'?>\xC3\xA9", XCS("utf-8"), NULL};
1526 #ifdef XML_UNICODE
1527   const XML_Char *expected = XCS("\x00e9");
1528 #else
1529   const XML_Char *expected = XCS("\xc3\xa9");
1530 #endif
1531 
1532   XML_SetExternalEntityRefHandler(g_parser, external_entity_loader);
1533   run_ext_character_check(text, &test_data, expected);
1534 }
1535 END_TEST
1536 
1537 /* Test external entities with no handler */
1538 START_TEST(test_ext_entity_no_handler) {
1539   const char *text = "<!DOCTYPE doc [\n"
1540                      "  <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n"
1541                      "]>\n"
1542                      "<doc>&en;</doc>";
1543 
1544   XML_SetDefaultHandler(g_parser, dummy_default_handler);
1545   run_character_check(text, XCS(""));
1546 }
1547 END_TEST
1548 
1549 /* Test UTF-8 BOM is accepted */
1550 START_TEST(test_ext_entity_set_bom) {
1551   const char *text = "<!DOCTYPE doc [\n"
1552                      "  <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n"
1553                      "]>\n"
1554                      "<doc>&en;</doc>";
1555   ExtTest test_data = {"\xEF\xBB\xBF" /* BOM */
1556                        "<?xml encoding='iso-8859-3'?>"
1557                        "\xC3\xA9",
1558                        XCS("utf-8"), NULL};
1559 #ifdef XML_UNICODE
1560   const XML_Char *expected = XCS("\x00e9");
1561 #else
1562   const XML_Char *expected = XCS("\xc3\xa9");
1563 #endif
1564 
1565   XML_SetExternalEntityRefHandler(g_parser, external_entity_loader);
1566   run_ext_character_check(text, &test_data, expected);
1567 }
1568 END_TEST
1569 
1570 /* Test that bad encodings are faulted */
1571 typedef struct ext_faults {
1572   const char *parse_text;
1573   const char *fail_text;
1574   const XML_Char *encoding;
1575   enum XML_Error error;
1576 } ExtFaults;
1577 
1578 static int XMLCALL
1579 external_entity_faulter(XML_Parser parser, const XML_Char *context,
1580                         const XML_Char *base, const XML_Char *systemId,
1581                         const XML_Char *publicId) {
1582   XML_Parser ext_parser;
1583   ExtFaults *fault = (ExtFaults *)XML_GetUserData(parser);
1584 
1585   UNUSED_P(base);
1586   UNUSED_P(systemId);
1587   UNUSED_P(publicId);
1588   ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
1589   if (ext_parser == NULL)
1590     fail("Could not create external entity parser");
1591   if (fault->encoding != NULL) {
1592     if (! XML_SetEncoding(ext_parser, fault->encoding))
1593       fail("XML_SetEncoding failed");
1594   }
1595   if (_XML_Parse_SINGLE_BYTES(ext_parser, fault->parse_text,
1596                               (int)strlen(fault->parse_text), XML_TRUE)
1597       != XML_STATUS_ERROR)
1598     fail(fault->fail_text);
1599   if (XML_GetErrorCode(ext_parser) != fault->error)
1600     xml_failure(ext_parser);
1601 
1602   XML_ParserFree(ext_parser);
1603   return XML_STATUS_ERROR;
1604 }
1605 
1606 START_TEST(test_ext_entity_bad_encoding) {
1607   const char *text = "<!DOCTYPE doc [\n"
1608                      "  <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n"
1609                      "]>\n"
1610                      "<doc>&en;</doc>";
1611   ExtFaults fault
1612       = {"<?xml encoding='iso-8859-3'?>u", "Unsupported encoding not faulted",
1613          XCS("unknown"), XML_ERROR_UNKNOWN_ENCODING};
1614 
1615   XML_SetExternalEntityRefHandler(g_parser, external_entity_faulter);
1616   XML_SetUserData(g_parser, &fault);
1617   expect_failure(text, XML_ERROR_EXTERNAL_ENTITY_HANDLING,
1618                  "Bad encoding should not have been accepted");
1619 }
1620 END_TEST
1621 
1622 /* Try handing an invalid encoding to an external entity parser */
1623 START_TEST(test_ext_entity_bad_encoding_2) {
1624   const char *text = "<?xml version='1.0' encoding='us-ascii'?>\n"
1625                      "<!DOCTYPE doc SYSTEM 'foo'>\n"
1626                      "<doc>&entity;</doc>";
1627   ExtFaults fault
1628       = {"<!ELEMENT doc (#PCDATA)*>", "Unknown encoding not faulted",
1629          XCS("unknown-encoding"), XML_ERROR_UNKNOWN_ENCODING};
1630 
1631   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
1632   XML_SetExternalEntityRefHandler(g_parser, external_entity_faulter);
1633   XML_SetUserData(g_parser, &fault);
1634   expect_failure(text, XML_ERROR_EXTERNAL_ENTITY_HANDLING,
1635                  "Bad encoding not faulted in external entity handler");
1636 }
1637 END_TEST
1638 
1639 /* Test that no error is reported for unknown entities if we don't
1640    read an external subset.  This was fixed in Expat 1.95.5.
1641 */
1642 START_TEST(test_wfc_undeclared_entity_unread_external_subset) {
1643   const char *text = "<!DOCTYPE doc SYSTEM 'foo'>\n"
1644                      "<doc>&entity;</doc>";
1645 
1646   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
1647       == XML_STATUS_ERROR)
1648     xml_failure(g_parser);
1649 }
1650 END_TEST
1651 
1652 /* Test that an error is reported for unknown entities if we don't
1653    have an external subset.
1654 */
1655 START_TEST(test_wfc_undeclared_entity_no_external_subset) {
1656   expect_failure("<doc>&entity;</doc>", XML_ERROR_UNDEFINED_ENTITY,
1657                  "Parser did not report undefined entity w/out a DTD.");
1658 }
1659 END_TEST
1660 
1661 /* Test that an error is reported for unknown entities if we don't
1662    read an external subset, but have been declared standalone.
1663 */
1664 START_TEST(test_wfc_undeclared_entity_standalone) {
1665   const char *text
1666       = "<?xml version='1.0' encoding='us-ascii' standalone='yes'?>\n"
1667         "<!DOCTYPE doc SYSTEM 'foo'>\n"
1668         "<doc>&entity;</doc>";
1669 
1670   expect_failure(text, XML_ERROR_UNDEFINED_ENTITY,
1671                  "Parser did not report undefined entity (standalone).");
1672 }
1673 END_TEST
1674 
1675 /* Test that an error is reported for unknown entities if we have read
1676    an external subset, and standalone is true.
1677 */
1678 START_TEST(test_wfc_undeclared_entity_with_external_subset_standalone) {
1679   const char *text
1680       = "<?xml version='1.0' encoding='us-ascii' standalone='yes'?>\n"
1681         "<!DOCTYPE doc SYSTEM 'foo'>\n"
1682         "<doc>&entity;</doc>";
1683   ExtTest test_data = {"<!ELEMENT doc (#PCDATA)*>", NULL, NULL};
1684 
1685   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
1686   XML_SetUserData(g_parser, &test_data);
1687   XML_SetExternalEntityRefHandler(g_parser, external_entity_loader);
1688   expect_failure(text, XML_ERROR_UNDEFINED_ENTITY,
1689                  "Parser did not report undefined entity (external DTD).");
1690 }
1691 END_TEST
1692 
1693 /* Test that external entity handling is not done if the parsing flag
1694  * is set to UNLESS_STANDALONE
1695  */
1696 START_TEST(test_entity_with_external_subset_unless_standalone) {
1697   const char *text
1698       = "<?xml version='1.0' encoding='us-ascii' standalone='yes'?>\n"
1699         "<!DOCTYPE doc SYSTEM 'foo'>\n"
1700         "<doc>&entity;</doc>";
1701   ExtTest test_data = {"<!ENTITY entity 'bar'>", NULL, NULL};
1702 
1703   XML_SetParamEntityParsing(g_parser,
1704                             XML_PARAM_ENTITY_PARSING_UNLESS_STANDALONE);
1705   XML_SetUserData(g_parser, &test_data);
1706   XML_SetExternalEntityRefHandler(g_parser, external_entity_loader);
1707   expect_failure(text, XML_ERROR_UNDEFINED_ENTITY,
1708                  "Parser did not report undefined entity");
1709 }
1710 END_TEST
1711 
1712 /* Test that no error is reported for unknown entities if we have read
1713    an external subset, and standalone is false.
1714 */
1715 START_TEST(test_wfc_undeclared_entity_with_external_subset) {
1716   const char *text = "<?xml version='1.0' encoding='us-ascii'?>\n"
1717                      "<!DOCTYPE doc SYSTEM 'foo'>\n"
1718                      "<doc>&entity;</doc>";
1719   ExtTest test_data = {"<!ELEMENT doc (#PCDATA)*>", NULL, NULL};
1720 
1721   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
1722   XML_SetExternalEntityRefHandler(g_parser, external_entity_loader);
1723   run_ext_character_check(text, &test_data, XCS(""));
1724 }
1725 END_TEST
1726 
1727 /* Test that an error is reported if our NotStandalone handler fails */
1728 static int XMLCALL
1729 reject_not_standalone_handler(void *userData) {
1730   UNUSED_P(userData);
1731   return XML_STATUS_ERROR;
1732 }
1733 
1734 START_TEST(test_not_standalone_handler_reject) {
1735   const char *text = "<?xml version='1.0' encoding='us-ascii'?>\n"
1736                      "<!DOCTYPE doc SYSTEM 'foo'>\n"
1737                      "<doc>&entity;</doc>";
1738   ExtTest test_data = {"<!ELEMENT doc (#PCDATA)*>", NULL, NULL};
1739 
1740   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
1741   XML_SetUserData(g_parser, &test_data);
1742   XML_SetExternalEntityRefHandler(g_parser, external_entity_loader);
1743   XML_SetNotStandaloneHandler(g_parser, reject_not_standalone_handler);
1744   expect_failure(text, XML_ERROR_NOT_STANDALONE,
1745                  "NotStandalone handler failed to reject");
1746 
1747   /* Try again but without external entity handling */
1748   XML_ParserReset(g_parser, NULL);
1749   XML_SetNotStandaloneHandler(g_parser, reject_not_standalone_handler);
1750   expect_failure(text, XML_ERROR_NOT_STANDALONE,
1751                  "NotStandalone handler failed to reject");
1752 }
1753 END_TEST
1754 
1755 /* Test that no error is reported if our NotStandalone handler succeeds */
1756 static int XMLCALL
1757 accept_not_standalone_handler(void *userData) {
1758   UNUSED_P(userData);
1759   return XML_STATUS_OK;
1760 }
1761 
1762 START_TEST(test_not_standalone_handler_accept) {
1763   const char *text = "<?xml version='1.0' encoding='us-ascii'?>\n"
1764                      "<!DOCTYPE doc SYSTEM 'foo'>\n"
1765                      "<doc>&entity;</doc>";
1766   ExtTest test_data = {"<!ELEMENT doc (#PCDATA)*>", NULL, NULL};
1767 
1768   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
1769   XML_SetExternalEntityRefHandler(g_parser, external_entity_loader);
1770   XML_SetNotStandaloneHandler(g_parser, accept_not_standalone_handler);
1771   run_ext_character_check(text, &test_data, XCS(""));
1772 
1773   /* Repeat without the external entity handler */
1774   XML_ParserReset(g_parser, NULL);
1775   XML_SetNotStandaloneHandler(g_parser, accept_not_standalone_handler);
1776   run_character_check(text, XCS(""));
1777 }
1778 END_TEST
1779 
1780 START_TEST(test_wfc_no_recursive_entity_refs) {
1781   const char *text = "<!DOCTYPE doc [\n"
1782                      "  <!ENTITY entity '&#38;entity;'>\n"
1783                      "]>\n"
1784                      "<doc>&entity;</doc>";
1785 
1786   expect_failure(text, XML_ERROR_RECURSIVE_ENTITY_REF,
1787                  "Parser did not report recursive entity reference.");
1788 }
1789 END_TEST
1790 
1791 /* Test incomplete external entities are faulted */
1792 START_TEST(test_ext_entity_invalid_parse) {
1793   const char *text = "<!DOCTYPE doc [\n"
1794                      "  <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n"
1795                      "]>\n"
1796                      "<doc>&en;</doc>";
1797   const ExtFaults faults[]
1798       = {{"<", "Incomplete element declaration not faulted", NULL,
1799           XML_ERROR_UNCLOSED_TOKEN},
1800          {"<\xe2\x82", /* First two bytes of a three-byte char */
1801           "Incomplete character not faulted", NULL, XML_ERROR_PARTIAL_CHAR},
1802          {"<tag>\xe2\x82", "Incomplete character in CDATA not faulted", NULL,
1803           XML_ERROR_PARTIAL_CHAR},
1804          {NULL, NULL, NULL, XML_ERROR_NONE}};
1805   const ExtFaults *fault = faults;
1806 
1807   for (; fault->parse_text != NULL; fault++) {
1808     XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
1809     XML_SetExternalEntityRefHandler(g_parser, external_entity_faulter);
1810     XML_SetUserData(g_parser, (void *)fault);
1811     expect_failure(text, XML_ERROR_EXTERNAL_ENTITY_HANDLING,
1812                    "Parser did not report external entity error");
1813     XML_ParserReset(g_parser, NULL);
1814   }
1815 }
1816 END_TEST
1817 
1818 /* Regression test for SF bug #483514. */
1819 START_TEST(test_dtd_default_handling) {
1820   const char *text = "<!DOCTYPE doc [\n"
1821                      "<!ENTITY e SYSTEM 'http://example.org/e'>\n"
1822                      "<!NOTATION n SYSTEM 'http://example.org/n'>\n"
1823                      "<!ELEMENT doc EMPTY>\n"
1824                      "<!ATTLIST doc a CDATA #IMPLIED>\n"
1825                      "<?pi in dtd?>\n"
1826                      "<!--comment in dtd-->\n"
1827                      "]><doc/>";
1828 
1829   XML_SetDefaultHandler(g_parser, accumulate_characters);
1830   XML_SetStartDoctypeDeclHandler(g_parser, dummy_start_doctype_handler);
1831   XML_SetEndDoctypeDeclHandler(g_parser, dummy_end_doctype_handler);
1832   XML_SetEntityDeclHandler(g_parser, dummy_entity_decl_handler);
1833   XML_SetNotationDeclHandler(g_parser, dummy_notation_decl_handler);
1834   XML_SetElementDeclHandler(g_parser, dummy_element_decl_handler);
1835   XML_SetAttlistDeclHandler(g_parser, dummy_attlist_decl_handler);
1836   XML_SetProcessingInstructionHandler(g_parser, dummy_pi_handler);
1837   XML_SetCommentHandler(g_parser, dummy_comment_handler);
1838   XML_SetStartCdataSectionHandler(g_parser, dummy_start_cdata_handler);
1839   XML_SetEndCdataSectionHandler(g_parser, dummy_end_cdata_handler);
1840   run_character_check(text, XCS("\n\n\n\n\n\n\n<doc/>"));
1841 }
1842 END_TEST
1843 
1844 /* Test handling of attribute declarations */
1845 typedef struct AttTest {
1846   const char *definition;
1847   const XML_Char *element_name;
1848   const XML_Char *attr_name;
1849   const XML_Char *attr_type;
1850   const XML_Char *default_value;
1851   int is_required;
1852 } AttTest;
1853 
1854 static void XMLCALL
1855 verify_attlist_decl_handler(void *userData, const XML_Char *element_name,
1856                             const XML_Char *attr_name,
1857                             const XML_Char *attr_type,
1858                             const XML_Char *default_value, int is_required) {
1859   AttTest *at = (AttTest *)userData;
1860 
1861   if (xcstrcmp(element_name, at->element_name))
1862     fail("Unexpected element name in attribute declaration");
1863   if (xcstrcmp(attr_name, at->attr_name))
1864     fail("Unexpected attribute name in attribute declaration");
1865   if (xcstrcmp(attr_type, at->attr_type))
1866     fail("Unexpected attribute type in attribute declaration");
1867   if ((default_value == NULL && at->default_value != NULL)
1868       || (default_value != NULL && at->default_value == NULL)
1869       || (default_value != NULL && xcstrcmp(default_value, at->default_value)))
1870     fail("Unexpected default value in attribute declaration");
1871   if (is_required != at->is_required)
1872     fail("Requirement mismatch in attribute declaration");
1873 }
1874 
1875 START_TEST(test_dtd_attr_handling) {
1876   const char *prolog = "<!DOCTYPE doc [\n"
1877                        "<!ELEMENT doc EMPTY>\n";
1878   AttTest attr_data[]
1879       = {{"<!ATTLIST doc a ( one | two | three ) #REQUIRED>\n"
1880           "]>"
1881           "<doc a='two'/>",
1882           XCS("doc"), XCS("a"),
1883           XCS("(one|two|three)"), /* Extraneous spaces will be removed */
1884           NULL, XML_TRUE},
1885          {"<!NOTATION foo SYSTEM 'http://example.org/foo'>\n"
1886           "<!ATTLIST doc a NOTATION (foo) #IMPLIED>\n"
1887           "]>"
1888           "<doc/>",
1889           XCS("doc"), XCS("a"), XCS("NOTATION(foo)"), NULL, XML_FALSE},
1890          {"<!ATTLIST doc a NOTATION (foo) 'bar'>\n"
1891           "]>"
1892           "<doc/>",
1893           XCS("doc"), XCS("a"), XCS("NOTATION(foo)"), XCS("bar"), XML_FALSE},
1894          {"<!ATTLIST doc a CDATA '\xdb\xb2'>\n"
1895           "]>"
1896           "<doc/>",
1897           XCS("doc"), XCS("a"), XCS("CDATA"),
1898 #ifdef XML_UNICODE
1899           XCS("\x06f2"),
1900 #else
1901           XCS("\xdb\xb2"),
1902 #endif
1903           XML_FALSE},
1904          {NULL, NULL, NULL, NULL, NULL, XML_FALSE}};
1905   AttTest *test;
1906 
1907   for (test = attr_data; test->definition != NULL; test++) {
1908     XML_SetAttlistDeclHandler(g_parser, verify_attlist_decl_handler);
1909     XML_SetUserData(g_parser, test);
1910     if (_XML_Parse_SINGLE_BYTES(g_parser, prolog, (int)strlen(prolog),
1911                                 XML_FALSE)
1912         == XML_STATUS_ERROR)
1913       xml_failure(g_parser);
1914     if (_XML_Parse_SINGLE_BYTES(g_parser, test->definition,
1915                                 (int)strlen(test->definition), XML_TRUE)
1916         == XML_STATUS_ERROR)
1917       xml_failure(g_parser);
1918     XML_ParserReset(g_parser, NULL);
1919   }
1920 }
1921 END_TEST
1922 
1923 /* See related SF bug #673791.
1924    When namespace processing is enabled, setting the namespace URI for
1925    a prefix is not allowed; this test ensures that it *is* allowed
1926    when namespace processing is not enabled.
1927    (See Namespaces in XML, section 2.)
1928 */
1929 START_TEST(test_empty_ns_without_namespaces) {
1930   const char *text = "<doc xmlns:prefix='http://example.org/'>\n"
1931                      "  <e xmlns:prefix=''/>\n"
1932                      "</doc>";
1933 
1934   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
1935       == XML_STATUS_ERROR)
1936     xml_failure(g_parser);
1937 }
1938 END_TEST
1939 
1940 /* Regression test for SF bug #824420.
1941    Checks that an xmlns:prefix attribute set in an attribute's default
1942    value isn't misinterpreted.
1943 */
1944 START_TEST(test_ns_in_attribute_default_without_namespaces) {
1945   const char *text = "<!DOCTYPE e:element [\n"
1946                      "  <!ATTLIST e:element\n"
1947                      "    xmlns:e CDATA 'http://example.org/'>\n"
1948                      "      ]>\n"
1949                      "<e:element/>";
1950 
1951   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
1952       == XML_STATUS_ERROR)
1953     xml_failure(g_parser);
1954 }
1955 END_TEST
1956 
1957 static const char *long_character_data_text
1958     = "<?xml version='1.0' encoding='iso-8859-1'?><s>"
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       "012345678901234567890123456789012345678901234567890123456789"
1979       "</s>";
1980 
1981 static XML_Bool resumable = XML_FALSE;
1982 
1983 static void
1984 clearing_aborting_character_handler(void *userData, const XML_Char *s,
1985                                     int len) {
1986   UNUSED_P(userData);
1987   UNUSED_P(s);
1988   UNUSED_P(len);
1989   XML_StopParser(g_parser, resumable);
1990   XML_SetCharacterDataHandler(g_parser, NULL);
1991 }
1992 
1993 /* Regression test for SF bug #1515266: missing check of stopped
1994    parser in doContext() 'for' loop. */
1995 START_TEST(test_stop_parser_between_char_data_calls) {
1996   /* The sample data must be big enough that there are two calls to
1997      the character data handler from within the inner "for" loop of
1998      the XML_TOK_DATA_CHARS case in doContent(), and the character
1999      handler must stop the parser and clear the character data
2000      handler.
2001   */
2002   const char *text = long_character_data_text;
2003 
2004   XML_SetCharacterDataHandler(g_parser, clearing_aborting_character_handler);
2005   resumable = XML_FALSE;
2006   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
2007       != XML_STATUS_ERROR)
2008     xml_failure(g_parser);
2009   if (XML_GetErrorCode(g_parser) != XML_ERROR_ABORTED)
2010     xml_failure(g_parser);
2011 }
2012 END_TEST
2013 
2014 /* Regression test for SF bug #1515266: missing check of stopped
2015    parser in doContext() 'for' loop. */
2016 START_TEST(test_suspend_parser_between_char_data_calls) {
2017   /* The sample data must be big enough that there are two calls to
2018      the character data handler from within the inner "for" loop of
2019      the XML_TOK_DATA_CHARS case in doContent(), and the character
2020      handler must stop the parser and clear the character data
2021      handler.
2022   */
2023   const char *text = long_character_data_text;
2024 
2025   XML_SetCharacterDataHandler(g_parser, clearing_aborting_character_handler);
2026   resumable = XML_TRUE;
2027   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
2028       != XML_STATUS_SUSPENDED)
2029     xml_failure(g_parser);
2030   if (XML_GetErrorCode(g_parser) != XML_ERROR_NONE)
2031     xml_failure(g_parser);
2032   /* Try parsing directly */
2033   if (XML_Parse(g_parser, text, (int)strlen(text), XML_TRUE)
2034       != XML_STATUS_ERROR)
2035     fail("Attempt to continue parse while suspended not faulted");
2036   if (XML_GetErrorCode(g_parser) != XML_ERROR_SUSPENDED)
2037     fail("Suspended parse not faulted with correct error");
2038 }
2039 END_TEST
2040 
2041 static XML_Bool abortable = XML_FALSE;
2042 
2043 static void
2044 parser_stop_character_handler(void *userData, const XML_Char *s, int len) {
2045   UNUSED_P(userData);
2046   UNUSED_P(s);
2047   UNUSED_P(len);
2048   XML_StopParser(g_parser, resumable);
2049   XML_SetCharacterDataHandler(g_parser, NULL);
2050   if (! resumable) {
2051     /* Check that aborting an aborted parser is faulted */
2052     if (XML_StopParser(g_parser, XML_FALSE) != XML_STATUS_ERROR)
2053       fail("Aborting aborted parser not faulted");
2054     if (XML_GetErrorCode(g_parser) != XML_ERROR_FINISHED)
2055       xml_failure(g_parser);
2056   } else if (abortable) {
2057     /* Check that aborting a suspended parser works */
2058     if (XML_StopParser(g_parser, XML_FALSE) == XML_STATUS_ERROR)
2059       xml_failure(g_parser);
2060   } else {
2061     /* Check that suspending a suspended parser works */
2062     if (XML_StopParser(g_parser, XML_TRUE) != XML_STATUS_ERROR)
2063       fail("Suspending suspended parser not faulted");
2064     if (XML_GetErrorCode(g_parser) != XML_ERROR_SUSPENDED)
2065       xml_failure(g_parser);
2066   }
2067 }
2068 
2069 /* Test repeated calls to XML_StopParser are handled correctly */
2070 START_TEST(test_repeated_stop_parser_between_char_data_calls) {
2071   const char *text = long_character_data_text;
2072 
2073   XML_SetCharacterDataHandler(g_parser, parser_stop_character_handler);
2074   resumable = XML_FALSE;
2075   abortable = XML_FALSE;
2076   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
2077       != XML_STATUS_ERROR)
2078     fail("Failed to double-stop parser");
2079 
2080   XML_ParserReset(g_parser, NULL);
2081   XML_SetCharacterDataHandler(g_parser, parser_stop_character_handler);
2082   resumable = XML_TRUE;
2083   abortable = XML_FALSE;
2084   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
2085       != XML_STATUS_SUSPENDED)
2086     fail("Failed to double-suspend parser");
2087 
2088   XML_ParserReset(g_parser, NULL);
2089   XML_SetCharacterDataHandler(g_parser, parser_stop_character_handler);
2090   resumable = XML_TRUE;
2091   abortable = XML_TRUE;
2092   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
2093       != XML_STATUS_ERROR)
2094     fail("Failed to suspend-abort parser");
2095 }
2096 END_TEST
2097 
2098 START_TEST(test_good_cdata_ascii) {
2099   const char *text = "<a><![CDATA[<greeting>Hello, world!</greeting>]]></a>";
2100   const XML_Char *expected = XCS("<greeting>Hello, world!</greeting>");
2101 
2102   CharData storage;
2103   CharData_Init(&storage);
2104   XML_SetUserData(g_parser, &storage);
2105   XML_SetCharacterDataHandler(g_parser, accumulate_characters);
2106   /* Add start and end handlers for coverage */
2107   XML_SetStartCdataSectionHandler(g_parser, dummy_start_cdata_handler);
2108   XML_SetEndCdataSectionHandler(g_parser, dummy_end_cdata_handler);
2109 
2110   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
2111       == XML_STATUS_ERROR)
2112     xml_failure(g_parser);
2113   CharData_CheckXMLChars(&storage, expected);
2114 
2115   /* Try again, this time with a default handler */
2116   XML_ParserReset(g_parser, NULL);
2117   CharData_Init(&storage);
2118   XML_SetUserData(g_parser, &storage);
2119   XML_SetCharacterDataHandler(g_parser, accumulate_characters);
2120   XML_SetDefaultHandler(g_parser, dummy_default_handler);
2121 
2122   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
2123       == XML_STATUS_ERROR)
2124     xml_failure(g_parser);
2125   CharData_CheckXMLChars(&storage, expected);
2126 }
2127 END_TEST
2128 
2129 START_TEST(test_good_cdata_utf16) {
2130   /* Test data is:
2131    *   <?xml version='1.0' encoding='utf-16'?>
2132    *   <a><![CDATA[hello]]></a>
2133    */
2134   const char text[]
2135       = "\0<\0?\0x\0m\0l\0"
2136         " \0v\0e\0r\0s\0i\0o\0n\0=\0'\0\x31\0.\0\x30\0'\0"
2137         " \0e\0n\0c\0o\0d\0i\0n\0g\0=\0'\0u\0t\0f\0-\0"
2138         "1\0"
2139         "6\0'"
2140         "\0?\0>\0\n"
2141         "\0<\0a\0>\0<\0!\0[\0C\0D\0A\0T\0A\0[\0h\0e\0l\0l\0o\0]\0]\0>\0<\0/\0a\0>";
2142   const XML_Char *expected = XCS("hello");
2143 
2144   CharData storage;
2145   CharData_Init(&storage);
2146   XML_SetUserData(g_parser, &storage);
2147   XML_SetCharacterDataHandler(g_parser, accumulate_characters);
2148 
2149   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE)
2150       == XML_STATUS_ERROR)
2151     xml_failure(g_parser);
2152   CharData_CheckXMLChars(&storage, expected);
2153 }
2154 END_TEST
2155 
2156 START_TEST(test_good_cdata_utf16_le) {
2157   /* Test data is:
2158    *   <?xml version='1.0' encoding='utf-16'?>
2159    *   <a><![CDATA[hello]]></a>
2160    */
2161   const char text[]
2162       = "<\0?\0x\0m\0l\0"
2163         " \0v\0e\0r\0s\0i\0o\0n\0=\0'\0\x31\0.\0\x30\0'\0"
2164         " \0e\0n\0c\0o\0d\0i\0n\0g\0=\0'\0u\0t\0f\0-\0"
2165         "1\0"
2166         "6\0'"
2167         "\0?\0>\0\n"
2168         "\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";
2169   const XML_Char *expected = XCS("hello");
2170 
2171   CharData storage;
2172   CharData_Init(&storage);
2173   XML_SetUserData(g_parser, &storage);
2174   XML_SetCharacterDataHandler(g_parser, accumulate_characters);
2175 
2176   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE)
2177       == XML_STATUS_ERROR)
2178     xml_failure(g_parser);
2179   CharData_CheckXMLChars(&storage, expected);
2180 }
2181 END_TEST
2182 
2183 /* Test UTF16 conversion of a long cdata string */
2184 
2185 /* 16 characters: handy macro to reduce visual clutter */
2186 #define A_TO_P_IN_UTF16 "\0A\0B\0C\0D\0E\0F\0G\0H\0I\0J\0K\0L\0M\0N\0O\0P"
2187 
2188 START_TEST(test_long_cdata_utf16) {
2189   /* Test data is:
2190    * <?xlm version='1.0' encoding='utf-16'?>
2191    * <a><![CDATA[
2192    * ABCDEFGHIJKLMNOP
2193    * ]]></a>
2194    */
2195   const char text[]
2196       = "\0<\0?\0x\0m\0l\0 "
2197         "\0v\0e\0r\0s\0i\0o\0n\0=\0'\0\x31\0.\0\x30\0'\0 "
2198         "\0e\0n\0c\0o\0d\0i\0n\0g\0=\0'\0u\0t\0f\0-\0\x31\0\x36\0'\0?\0>"
2199         "\0<\0a\0>\0<\0!\0[\0C\0D\0A\0T\0A\0["
2200       /* 64 characters per line */
2201       /* clang-format off */
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  A_TO_P_IN_UTF16  A_TO_P_IN_UTF16  A_TO_P_IN_UTF16
2218         A_TO_P_IN_UTF16
2219         /* clang-format on */
2220         "\0]\0]\0>\0<\0/\0a\0>";
2221   const XML_Char *expected =
2222       /* clang-format off */
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("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
2239         XCS("ABCDEFGHIJKLMNOP");
2240   /* clang-format on */
2241   CharData storage;
2242   void *buffer;
2243 
2244   CharData_Init(&storage);
2245   XML_SetUserData(g_parser, &storage);
2246   XML_SetCharacterDataHandler(g_parser, accumulate_characters);
2247   buffer = XML_GetBuffer(g_parser, sizeof(text) - 1);
2248   if (buffer == NULL)
2249     fail("Could not allocate parse buffer");
2250   assert(buffer != NULL);
2251   memcpy(buffer, text, sizeof(text) - 1);
2252   if (XML_ParseBuffer(g_parser, sizeof(text) - 1, XML_TRUE) == XML_STATUS_ERROR)
2253     xml_failure(g_parser);
2254   CharData_CheckXMLChars(&storage, expected);
2255 }
2256 END_TEST
2257 
2258 /* Test handling of multiple unit UTF-16 characters */
2259 START_TEST(test_multichar_cdata_utf16) {
2260   /* Test data is:
2261    *   <?xml version='1.0' encoding='utf-16'?>
2262    *   <a><![CDATA[{MINIM}{CROTCHET}]]></a>
2263    *
2264    * where {MINIM} is U+1d15e (a minim or half-note)
2265    *   UTF-16: 0xd834 0xdd5e
2266    *   UTF-8:  0xf0 0x9d 0x85 0x9e
2267    * and {CROTCHET} is U+1d15f (a crotchet or quarter-note)
2268    *   UTF-16: 0xd834 0xdd5f
2269    *   UTF-8:  0xf0 0x9d 0x85 0x9f
2270    */
2271   const char text[] = "\0<\0?\0x\0m\0l\0"
2272                       " \0v\0e\0r\0s\0i\0o\0n\0=\0'\0\x31\0.\0\x30\0'\0"
2273                       " \0e\0n\0c\0o\0d\0i\0n\0g\0=\0'\0u\0t\0f\0-\0"
2274                       "1\0"
2275                       "6\0'"
2276                       "\0?\0>\0\n"
2277                       "\0<\0a\0>\0<\0!\0[\0C\0D\0A\0T\0A\0["
2278                       "\xd8\x34\xdd\x5e\xd8\x34\xdd\x5f"
2279                       "\0]\0]\0>\0<\0/\0a\0>";
2280 #ifdef XML_UNICODE
2281   const XML_Char *expected = XCS("\xd834\xdd5e\xd834\xdd5f");
2282 #else
2283   const XML_Char *expected = XCS("\xf0\x9d\x85\x9e\xf0\x9d\x85\x9f");
2284 #endif
2285   CharData storage;
2286 
2287   CharData_Init(&storage);
2288   XML_SetUserData(g_parser, &storage);
2289   XML_SetCharacterDataHandler(g_parser, accumulate_characters);
2290 
2291   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE)
2292       == XML_STATUS_ERROR)
2293     xml_failure(g_parser);
2294   CharData_CheckXMLChars(&storage, expected);
2295 }
2296 END_TEST
2297 
2298 /* Test that an element name with a UTF-16 surrogate pair is rejected */
2299 START_TEST(test_utf16_bad_surrogate_pair) {
2300   /* Test data is:
2301    *   <?xml version='1.0' encoding='utf-16'?>
2302    *   <a><![CDATA[{BADLINB}]]></a>
2303    *
2304    * where {BADLINB} is U+10000 (the first Linear B character)
2305    * with the UTF-16 surrogate pair in the wrong order, i.e.
2306    *   0xdc00 0xd800
2307    */
2308   const char text[] = "\0<\0?\0x\0m\0l\0"
2309                       " \0v\0e\0r\0s\0i\0o\0n\0=\0'\0\x31\0.\0\x30\0'\0"
2310                       " \0e\0n\0c\0o\0d\0i\0n\0g\0=\0'\0u\0t\0f\0-\0"
2311                       "1\0"
2312                       "6\0'"
2313                       "\0?\0>\0\n"
2314                       "\0<\0a\0>\0<\0!\0[\0C\0D\0A\0T\0A\0["
2315                       "\xdc\x00\xd8\x00"
2316                       "\0]\0]\0>\0<\0/\0a\0>";
2317 
2318   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE)
2319       != XML_STATUS_ERROR)
2320     fail("Reversed UTF-16 surrogate pair not faulted");
2321   if (XML_GetErrorCode(g_parser) != XML_ERROR_INVALID_TOKEN)
2322     xml_failure(g_parser);
2323 }
2324 END_TEST
2325 
2326 START_TEST(test_bad_cdata) {
2327   struct CaseData {
2328     const char *text;
2329     enum XML_Error expectedError;
2330   };
2331 
2332   struct CaseData cases[]
2333       = {{"<a><", XML_ERROR_UNCLOSED_TOKEN},
2334          {"<a><!", XML_ERROR_UNCLOSED_TOKEN},
2335          {"<a><![", XML_ERROR_UNCLOSED_TOKEN},
2336          {"<a><![C", XML_ERROR_UNCLOSED_TOKEN},
2337          {"<a><![CD", XML_ERROR_UNCLOSED_TOKEN},
2338          {"<a><![CDA", XML_ERROR_UNCLOSED_TOKEN},
2339          {"<a><![CDAT", XML_ERROR_UNCLOSED_TOKEN},
2340          {"<a><![CDATA", XML_ERROR_UNCLOSED_TOKEN},
2341 
2342          {"<a><![CDATA[", XML_ERROR_UNCLOSED_CDATA_SECTION},
2343          {"<a><![CDATA[]", XML_ERROR_UNCLOSED_CDATA_SECTION},
2344          {"<a><![CDATA[]]", XML_ERROR_UNCLOSED_CDATA_SECTION},
2345 
2346          {"<a><!<a/>", XML_ERROR_INVALID_TOKEN},
2347          {"<a><![<a/>", XML_ERROR_UNCLOSED_TOKEN},  /* ?! */
2348          {"<a><![C<a/>", XML_ERROR_UNCLOSED_TOKEN}, /* ?! */
2349          {"<a><![CD<a/>", XML_ERROR_INVALID_TOKEN},
2350          {"<a><![CDA<a/>", XML_ERROR_INVALID_TOKEN},
2351          {"<a><![CDAT<a/>", XML_ERROR_INVALID_TOKEN},
2352          {"<a><![CDATA<a/>", XML_ERROR_INVALID_TOKEN},
2353 
2354          {"<a><![CDATA[<a/>", XML_ERROR_UNCLOSED_CDATA_SECTION},
2355          {"<a><![CDATA[]<a/>", XML_ERROR_UNCLOSED_CDATA_SECTION},
2356          {"<a><![CDATA[]]<a/>", XML_ERROR_UNCLOSED_CDATA_SECTION}};
2357 
2358   size_t i = 0;
2359   for (; i < sizeof(cases) / sizeof(struct CaseData); i++) {
2360     const enum XML_Status actualStatus = _XML_Parse_SINGLE_BYTES(
2361         g_parser, cases[i].text, (int)strlen(cases[i].text), XML_TRUE);
2362     const enum XML_Error actualError = XML_GetErrorCode(g_parser);
2363 
2364     assert(actualStatus == XML_STATUS_ERROR);
2365 
2366     if (actualError != cases[i].expectedError) {
2367       char message[100];
2368       sprintf(message,
2369               "Expected error %d but got error %d for case %u: \"%s\"\n",
2370               cases[i].expectedError, actualError, (unsigned int)i + 1,
2371               cases[i].text);
2372       fail(message);
2373     }
2374 
2375     XML_ParserReset(g_parser, NULL);
2376   }
2377 }
2378 END_TEST
2379 
2380 /* Test failures in UTF-16 CDATA */
2381 START_TEST(test_bad_cdata_utf16) {
2382   struct CaseData {
2383     size_t text_bytes;
2384     const char *text;
2385     enum XML_Error expected_error;
2386   };
2387 
2388   const char prolog[] = "\0<\0?\0x\0m\0l\0"
2389                         " \0v\0e\0r\0s\0i\0o\0n\0=\0'\0\x31\0.\0\x30\0'\0"
2390                         " \0e\0n\0c\0o\0d\0i\0n\0g\0=\0'\0u\0t\0f\0-\0"
2391                         "1\0"
2392                         "6\0'"
2393                         "\0?\0>\0\n"
2394                         "\0<\0a\0>";
2395   struct CaseData cases[] = {
2396       {1, "\0", XML_ERROR_UNCLOSED_TOKEN},
2397       {2, "\0<", XML_ERROR_UNCLOSED_TOKEN},
2398       {3, "\0<\0", XML_ERROR_UNCLOSED_TOKEN},
2399       {4, "\0<\0!", XML_ERROR_UNCLOSED_TOKEN},
2400       {5, "\0<\0!\0", XML_ERROR_UNCLOSED_TOKEN},
2401       {6, "\0<\0!\0[", XML_ERROR_UNCLOSED_TOKEN},
2402       {7, "\0<\0!\0[\0", XML_ERROR_UNCLOSED_TOKEN},
2403       {8, "\0<\0!\0[\0C", XML_ERROR_UNCLOSED_TOKEN},
2404       {9, "\0<\0!\0[\0C\0", XML_ERROR_UNCLOSED_TOKEN},
2405       {10, "\0<\0!\0[\0C\0D", XML_ERROR_UNCLOSED_TOKEN},
2406       {11, "\0<\0!\0[\0C\0D\0", XML_ERROR_UNCLOSED_TOKEN},
2407       {12, "\0<\0!\0[\0C\0D\0A", XML_ERROR_UNCLOSED_TOKEN},
2408       {13, "\0<\0!\0[\0C\0D\0A\0", XML_ERROR_UNCLOSED_TOKEN},
2409       {14, "\0<\0!\0[\0C\0D\0A\0T", XML_ERROR_UNCLOSED_TOKEN},
2410       {15, "\0<\0!\0[\0C\0D\0A\0T\0", XML_ERROR_UNCLOSED_TOKEN},
2411       {16, "\0<\0!\0[\0C\0D\0A\0T\0A", XML_ERROR_UNCLOSED_TOKEN},
2412       {17, "\0<\0!\0[\0C\0D\0A\0T\0A\0", XML_ERROR_UNCLOSED_TOKEN},
2413       {18, "\0<\0!\0[\0C\0D\0A\0T\0A\0[", XML_ERROR_UNCLOSED_CDATA_SECTION},
2414       {19, "\0<\0!\0[\0C\0D\0A\0T\0A\0[\0", XML_ERROR_UNCLOSED_CDATA_SECTION},
2415       {20, "\0<\0!\0[\0C\0D\0A\0T\0A\0[\0Z", XML_ERROR_UNCLOSED_CDATA_SECTION},
2416       /* Now add a four-byte UTF-16 character */
2417       {21, "\0<\0!\0[\0C\0D\0A\0T\0A\0[\0Z\xd8",
2418        XML_ERROR_UNCLOSED_CDATA_SECTION},
2419       {22, "\0<\0!\0[\0C\0D\0A\0T\0A\0[\0Z\xd8\x34", XML_ERROR_PARTIAL_CHAR},
2420       {23, "\0<\0!\0[\0C\0D\0A\0T\0A\0[\0Z\xd8\x34\xdd",
2421        XML_ERROR_PARTIAL_CHAR},
2422       {24, "\0<\0!\0[\0C\0D\0A\0T\0A\0[\0Z\xd8\x34\xdd\x5e",
2423        XML_ERROR_UNCLOSED_CDATA_SECTION}};
2424   size_t i;
2425 
2426   for (i = 0; i < sizeof(cases) / sizeof(struct CaseData); i++) {
2427     enum XML_Status actual_status;
2428     enum XML_Error actual_error;
2429 
2430     if (_XML_Parse_SINGLE_BYTES(g_parser, prolog, (int)sizeof(prolog) - 1,
2431                                 XML_FALSE)
2432         == XML_STATUS_ERROR)
2433       xml_failure(g_parser);
2434     actual_status = _XML_Parse_SINGLE_BYTES(g_parser, cases[i].text,
2435                                             (int)cases[i].text_bytes, XML_TRUE);
2436     assert(actual_status == XML_STATUS_ERROR);
2437     actual_error = XML_GetErrorCode(g_parser);
2438     if (actual_error != cases[i].expected_error) {
2439       char message[1024];
2440 
2441       sprintf(message,
2442               "Expected error %d (%" XML_FMT_STR "), got %d (%" XML_FMT_STR
2443               ") for case %lu\n",
2444               cases[i].expected_error, XML_ErrorString(cases[i].expected_error),
2445               actual_error, XML_ErrorString(actual_error),
2446               (long unsigned)(i + 1));
2447       fail(message);
2448     }
2449     XML_ParserReset(g_parser, NULL);
2450   }
2451 }
2452 END_TEST
2453 
2454 static const char *long_cdata_text
2455     = "<s><![CDATA["
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       "012345678901234567890123456789012345678901234567890123456789"
2476       "]]></s>";
2477 
2478 /* Test stopping the parser in cdata handler */
2479 START_TEST(test_stop_parser_between_cdata_calls) {
2480   const char *text = long_cdata_text;
2481 
2482   XML_SetCharacterDataHandler(g_parser, clearing_aborting_character_handler);
2483   resumable = XML_FALSE;
2484   expect_failure(text, XML_ERROR_ABORTED, "Parse not aborted in CDATA handler");
2485 }
2486 END_TEST
2487 
2488 /* Test suspending the parser in cdata handler */
2489 START_TEST(test_suspend_parser_between_cdata_calls) {
2490   const char *text = long_cdata_text;
2491   enum XML_Status result;
2492 
2493   XML_SetCharacterDataHandler(g_parser, clearing_aborting_character_handler);
2494   resumable = XML_TRUE;
2495   result = _XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE);
2496   if (result != XML_STATUS_SUSPENDED) {
2497     if (result == XML_STATUS_ERROR)
2498       xml_failure(g_parser);
2499     fail("Parse not suspended in CDATA handler");
2500   }
2501   if (XML_GetErrorCode(g_parser) != XML_ERROR_NONE)
2502     xml_failure(g_parser);
2503 }
2504 END_TEST
2505 
2506 /* Test memory allocation functions */
2507 START_TEST(test_memory_allocation) {
2508   char *buffer = (char *)XML_MemMalloc(g_parser, 256);
2509   char *p;
2510 
2511   if (buffer == NULL) {
2512     fail("Allocation failed");
2513   } else {
2514     /* Try writing to memory; some OSes try to cheat! */
2515     buffer[0] = 'T';
2516     buffer[1] = 'E';
2517     buffer[2] = 'S';
2518     buffer[3] = 'T';
2519     buffer[4] = '\0';
2520     if (strcmp(buffer, "TEST") != 0) {
2521       fail("Memory not writable");
2522     } else {
2523       p = (char *)XML_MemRealloc(g_parser, buffer, 512);
2524       if (p == NULL) {
2525         fail("Reallocation failed");
2526       } else {
2527         /* Write again, just to be sure */
2528         buffer = p;
2529         buffer[0] = 'V';
2530         if (strcmp(buffer, "VEST") != 0) {
2531           fail("Reallocated memory not writable");
2532         }
2533       }
2534     }
2535     XML_MemFree(g_parser, buffer);
2536   }
2537 }
2538 END_TEST
2539 
2540 static void XMLCALL
2541 record_default_handler(void *userData, const XML_Char *s, int len) {
2542   UNUSED_P(s);
2543   UNUSED_P(len);
2544   CharData_AppendXMLChars((CharData *)userData, XCS("D"), 1);
2545 }
2546 
2547 static void XMLCALL
2548 record_cdata_handler(void *userData, const XML_Char *s, int len) {
2549   UNUSED_P(s);
2550   UNUSED_P(len);
2551   CharData_AppendXMLChars((CharData *)userData, XCS("C"), 1);
2552   XML_DefaultCurrent(g_parser);
2553 }
2554 
2555 static void XMLCALL
2556 record_cdata_nodefault_handler(void *userData, const XML_Char *s, int len) {
2557   UNUSED_P(s);
2558   UNUSED_P(len);
2559   CharData_AppendXMLChars((CharData *)userData, XCS("c"), 1);
2560 }
2561 
2562 static void XMLCALL
2563 record_skip_handler(void *userData, const XML_Char *entityName,
2564                     int is_parameter_entity) {
2565   UNUSED_P(entityName);
2566   CharData_AppendXMLChars((CharData *)userData,
2567                           is_parameter_entity ? XCS("E") : XCS("e"), 1);
2568 }
2569 
2570 /* Test XML_DefaultCurrent() passes handling on correctly */
2571 START_TEST(test_default_current) {
2572   const char *text = "<doc>hell]</doc>";
2573   const char *entity_text = "<!DOCTYPE doc [\n"
2574                             "<!ENTITY entity '&#37;'>\n"
2575                             "]>\n"
2576                             "<doc>&entity;</doc>";
2577   CharData storage;
2578 
2579   XML_SetDefaultHandler(g_parser, record_default_handler);
2580   XML_SetCharacterDataHandler(g_parser, record_cdata_handler);
2581   CharData_Init(&storage);
2582   XML_SetUserData(g_parser, &storage);
2583   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
2584       == XML_STATUS_ERROR)
2585     xml_failure(g_parser);
2586   CharData_CheckXMLChars(&storage, XCS("DCDCDCDCDCDD"));
2587 
2588   /* Again, without the defaulting */
2589   XML_ParserReset(g_parser, NULL);
2590   XML_SetDefaultHandler(g_parser, record_default_handler);
2591   XML_SetCharacterDataHandler(g_parser, record_cdata_nodefault_handler);
2592   CharData_Init(&storage);
2593   XML_SetUserData(g_parser, &storage);
2594   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
2595       == XML_STATUS_ERROR)
2596     xml_failure(g_parser);
2597   CharData_CheckXMLChars(&storage, XCS("DcccccD"));
2598 
2599   /* Now with an internal entity to complicate matters */
2600   XML_ParserReset(g_parser, NULL);
2601   XML_SetDefaultHandler(g_parser, record_default_handler);
2602   XML_SetCharacterDataHandler(g_parser, record_cdata_handler);
2603   CharData_Init(&storage);
2604   XML_SetUserData(g_parser, &storage);
2605   if (_XML_Parse_SINGLE_BYTES(g_parser, entity_text, (int)strlen(entity_text),
2606                               XML_TRUE)
2607       == XML_STATUS_ERROR)
2608     xml_failure(g_parser);
2609   /* The default handler suppresses the entity */
2610   CharData_CheckXMLChars(&storage, XCS("DDDDDDDDDDDDDDDDDDD"));
2611 
2612   /* Again, with a skip handler */
2613   XML_ParserReset(g_parser, NULL);
2614   XML_SetDefaultHandler(g_parser, record_default_handler);
2615   XML_SetCharacterDataHandler(g_parser, record_cdata_handler);
2616   XML_SetSkippedEntityHandler(g_parser, record_skip_handler);
2617   CharData_Init(&storage);
2618   XML_SetUserData(g_parser, &storage);
2619   if (_XML_Parse_SINGLE_BYTES(g_parser, entity_text, (int)strlen(entity_text),
2620                               XML_TRUE)
2621       == XML_STATUS_ERROR)
2622     xml_failure(g_parser);
2623   /* The default handler suppresses the entity */
2624   CharData_CheckXMLChars(&storage, XCS("DDDDDDDDDDDDDDDDDeD"));
2625 
2626   /* This time, allow the entity through */
2627   XML_ParserReset(g_parser, NULL);
2628   XML_SetDefaultHandlerExpand(g_parser, record_default_handler);
2629   XML_SetCharacterDataHandler(g_parser, record_cdata_handler);
2630   CharData_Init(&storage);
2631   XML_SetUserData(g_parser, &storage);
2632   if (_XML_Parse_SINGLE_BYTES(g_parser, entity_text, (int)strlen(entity_text),
2633                               XML_TRUE)
2634       == XML_STATUS_ERROR)
2635     xml_failure(g_parser);
2636   CharData_CheckXMLChars(&storage, XCS("DDDDDDDDDDDDDDDDDCDD"));
2637 
2638   /* Finally, without passing the cdata to the default handler */
2639   XML_ParserReset(g_parser, NULL);
2640   XML_SetDefaultHandlerExpand(g_parser, record_default_handler);
2641   XML_SetCharacterDataHandler(g_parser, record_cdata_nodefault_handler);
2642   CharData_Init(&storage);
2643   XML_SetUserData(g_parser, &storage);
2644   if (_XML_Parse_SINGLE_BYTES(g_parser, entity_text, (int)strlen(entity_text),
2645                               XML_TRUE)
2646       == XML_STATUS_ERROR)
2647     xml_failure(g_parser);
2648   CharData_CheckXMLChars(&storage, XCS("DDDDDDDDDDDDDDDDDcD"));
2649 }
2650 END_TEST
2651 
2652 /* Test DTD element parsing code paths */
2653 START_TEST(test_dtd_elements) {
2654   const char *text = "<!DOCTYPE doc [\n"
2655                      "<!ELEMENT doc (chapter)>\n"
2656                      "<!ELEMENT chapter (#PCDATA)>\n"
2657                      "]>\n"
2658                      "<doc><chapter>Wombats are go</chapter></doc>";
2659 
2660   XML_SetElementDeclHandler(g_parser, dummy_element_decl_handler);
2661   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
2662       == XML_STATUS_ERROR)
2663     xml_failure(g_parser);
2664 }
2665 END_TEST
2666 
2667 static void XMLCALL
2668 element_decl_check_model(void *userData, const XML_Char *name,
2669                          XML_Content *model) {
2670   UNUSED_P(userData);
2671   uint32_t errorFlags = 0;
2672 
2673   /* Expected model array structure is this:
2674    * [0] (type 6, quant 0)
2675    *   [1] (type 5, quant 0)
2676    *     [3] (type 4, quant 0, name "bar")
2677    *     [4] (type 4, quant 0, name "foo")
2678    *     [5] (type 4, quant 3, name "xyz")
2679    *   [2] (type 4, quant 2, name "zebra")
2680    */
2681   errorFlags |= ((xcstrcmp(name, XCS("junk")) == 0) ? 0 : (1u << 0));
2682   errorFlags |= ((model != NULL) ? 0 : (1u << 1));
2683 
2684   errorFlags |= ((model[0].type == XML_CTYPE_SEQ) ? 0 : (1u << 2));
2685   errorFlags |= ((model[0].quant == XML_CQUANT_NONE) ? 0 : (1u << 3));
2686   errorFlags |= ((model[0].numchildren == 2) ? 0 : (1u << 4));
2687   errorFlags |= ((model[0].children == &model[1]) ? 0 : (1u << 5));
2688   errorFlags |= ((model[0].name == NULL) ? 0 : (1u << 6));
2689 
2690   errorFlags |= ((model[1].type == XML_CTYPE_CHOICE) ? 0 : (1u << 7));
2691   errorFlags |= ((model[1].quant == XML_CQUANT_NONE) ? 0 : (1u << 8));
2692   errorFlags |= ((model[1].numchildren == 3) ? 0 : (1u << 9));
2693   errorFlags |= ((model[1].children == &model[3]) ? 0 : (1u << 10));
2694   errorFlags |= ((model[1].name == NULL) ? 0 : (1u << 11));
2695 
2696   errorFlags |= ((model[2].type == XML_CTYPE_NAME) ? 0 : (1u << 12));
2697   errorFlags |= ((model[2].quant == XML_CQUANT_REP) ? 0 : (1u << 13));
2698   errorFlags |= ((model[2].numchildren == 0) ? 0 : (1u << 14));
2699   errorFlags |= ((model[2].children == NULL) ? 0 : (1u << 15));
2700   errorFlags |= ((xcstrcmp(model[2].name, XCS("zebra")) == 0) ? 0 : (1u << 16));
2701 
2702   errorFlags |= ((model[3].type == XML_CTYPE_NAME) ? 0 : (1u << 17));
2703   errorFlags |= ((model[3].quant == XML_CQUANT_NONE) ? 0 : (1u << 18));
2704   errorFlags |= ((model[3].numchildren == 0) ? 0 : (1u << 19));
2705   errorFlags |= ((model[3].children == NULL) ? 0 : (1u << 20));
2706   errorFlags |= ((xcstrcmp(model[3].name, XCS("bar")) == 0) ? 0 : (1u << 21));
2707 
2708   errorFlags |= ((model[4].type == XML_CTYPE_NAME) ? 0 : (1u << 22));
2709   errorFlags |= ((model[4].quant == XML_CQUANT_NONE) ? 0 : (1u << 23));
2710   errorFlags |= ((model[4].numchildren == 0) ? 0 : (1u << 24));
2711   errorFlags |= ((model[4].children == NULL) ? 0 : (1u << 25));
2712   errorFlags |= ((xcstrcmp(model[4].name, XCS("foo")) == 0) ? 0 : (1u << 26));
2713 
2714   errorFlags |= ((model[5].type == XML_CTYPE_NAME) ? 0 : (1u << 27));
2715   errorFlags |= ((model[5].quant == XML_CQUANT_PLUS) ? 0 : (1u << 28));
2716   errorFlags |= ((model[5].numchildren == 0) ? 0 : (1u << 29));
2717   errorFlags |= ((model[5].children == NULL) ? 0 : (1u << 30));
2718   errorFlags |= ((xcstrcmp(model[5].name, XCS("xyz")) == 0) ? 0 : (1u << 31));
2719 
2720   XML_SetUserData(g_parser, (void *)(uintptr_t)errorFlags);
2721   XML_FreeContentModel(g_parser, model);
2722 }
2723 
2724 START_TEST(test_dtd_elements_nesting) {
2725   // Payload inspired by a test in Perl's XML::Parser
2726   const char *text = "<!DOCTYPE foo [\n"
2727                      "<!ELEMENT junk ((bar|foo|xyz+), zebra*)>\n"
2728                      "]>\n"
2729                      "<foo/>";
2730 
2731   XML_SetUserData(g_parser, (void *)(uintptr_t)-1);
2732 
2733   XML_SetElementDeclHandler(g_parser, element_decl_check_model);
2734   if (XML_Parse(g_parser, text, (int)strlen(text), XML_TRUE)
2735       == XML_STATUS_ERROR)
2736     xml_failure(g_parser);
2737 
2738   if ((uint32_t)(uintptr_t)XML_GetUserData(g_parser) != 0)
2739     fail("Element declaration model regression detected");
2740 }
2741 END_TEST
2742 
2743 /* Test foreign DTD handling */
2744 START_TEST(test_set_foreign_dtd) {
2745   const char *text1 = "<?xml version='1.0' encoding='us-ascii'?>\n";
2746   const char *text2 = "<doc>&entity;</doc>";
2747   ExtTest test_data = {"<!ELEMENT doc (#PCDATA)*>", NULL, NULL};
2748 
2749   /* Check hash salt is passed through too */
2750   XML_SetHashSalt(g_parser, 0x12345678);
2751   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
2752   XML_SetUserData(g_parser, &test_data);
2753   XML_SetExternalEntityRefHandler(g_parser, external_entity_loader);
2754   /* Add a default handler to exercise more code paths */
2755   XML_SetDefaultHandler(g_parser, dummy_default_handler);
2756   if (XML_UseForeignDTD(g_parser, XML_TRUE) != XML_ERROR_NONE)
2757     fail("Could not set foreign DTD");
2758   if (_XML_Parse_SINGLE_BYTES(g_parser, text1, (int)strlen(text1), XML_FALSE)
2759       == XML_STATUS_ERROR)
2760     xml_failure(g_parser);
2761 
2762   /* Ensure that trying to set the DTD after parsing has started
2763    * is faulted, even if it's the same setting.
2764    */
2765   if (XML_UseForeignDTD(g_parser, XML_TRUE)
2766       != XML_ERROR_CANT_CHANGE_FEATURE_ONCE_PARSING)
2767     fail("Failed to reject late foreign DTD setting");
2768   /* Ditto for the hash salt */
2769   if (XML_SetHashSalt(g_parser, 0x23456789))
2770     fail("Failed to reject late hash salt change");
2771 
2772   /* Now finish the parse */
2773   if (_XML_Parse_SINGLE_BYTES(g_parser, text2, (int)strlen(text2), XML_TRUE)
2774       == XML_STATUS_ERROR)
2775     xml_failure(g_parser);
2776 }
2777 END_TEST
2778 
2779 /* Test foreign DTD handling with a failing NotStandalone handler */
2780 START_TEST(test_foreign_dtd_not_standalone) {
2781   const char *text = "<?xml version='1.0' encoding='us-ascii'?>\n"
2782                      "<doc>&entity;</doc>";
2783   ExtTest test_data = {"<!ELEMENT doc (#PCDATA)*>", NULL, NULL};
2784 
2785   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
2786   XML_SetUserData(g_parser, &test_data);
2787   XML_SetExternalEntityRefHandler(g_parser, external_entity_loader);
2788   XML_SetNotStandaloneHandler(g_parser, reject_not_standalone_handler);
2789   if (XML_UseForeignDTD(g_parser, XML_TRUE) != XML_ERROR_NONE)
2790     fail("Could not set foreign DTD");
2791   expect_failure(text, XML_ERROR_NOT_STANDALONE,
2792                  "NotStandalonehandler failed to reject");
2793 }
2794 END_TEST
2795 
2796 /* Test invalid character in a foreign DTD is faulted */
2797 START_TEST(test_invalid_foreign_dtd) {
2798   const char *text = "<?xml version='1.0' encoding='us-ascii'?>\n"
2799                      "<doc>&entity;</doc>";
2800   ExtFaults test_data
2801       = {"$", "Dollar not faulted", NULL, XML_ERROR_INVALID_TOKEN};
2802 
2803   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
2804   XML_SetUserData(g_parser, &test_data);
2805   XML_SetExternalEntityRefHandler(g_parser, external_entity_faulter);
2806   XML_UseForeignDTD(g_parser, XML_TRUE);
2807   expect_failure(text, XML_ERROR_EXTERNAL_ENTITY_HANDLING,
2808                  "Bad DTD should not have been accepted");
2809 }
2810 END_TEST
2811 
2812 /* Test foreign DTD use with a doctype */
2813 START_TEST(test_foreign_dtd_with_doctype) {
2814   const char *text1 = "<?xml version='1.0' encoding='us-ascii'?>\n"
2815                       "<!DOCTYPE doc [<!ENTITY entity 'hello world'>]>\n";
2816   const char *text2 = "<doc>&entity;</doc>";
2817   ExtTest test_data = {"<!ELEMENT doc (#PCDATA)*>", NULL, NULL};
2818 
2819   /* Check hash salt is passed through too */
2820   XML_SetHashSalt(g_parser, 0x12345678);
2821   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
2822   XML_SetUserData(g_parser, &test_data);
2823   XML_SetExternalEntityRefHandler(g_parser, external_entity_loader);
2824   /* Add a default handler to exercise more code paths */
2825   XML_SetDefaultHandler(g_parser, dummy_default_handler);
2826   if (XML_UseForeignDTD(g_parser, XML_TRUE) != XML_ERROR_NONE)
2827     fail("Could not set foreign DTD");
2828   if (_XML_Parse_SINGLE_BYTES(g_parser, text1, (int)strlen(text1), XML_FALSE)
2829       == XML_STATUS_ERROR)
2830     xml_failure(g_parser);
2831 
2832   /* Ensure that trying to set the DTD after parsing has started
2833    * is faulted, even if it's the same setting.
2834    */
2835   if (XML_UseForeignDTD(g_parser, XML_TRUE)
2836       != XML_ERROR_CANT_CHANGE_FEATURE_ONCE_PARSING)
2837     fail("Failed to reject late foreign DTD setting");
2838   /* Ditto for the hash salt */
2839   if (XML_SetHashSalt(g_parser, 0x23456789))
2840     fail("Failed to reject late hash salt change");
2841 
2842   /* Now finish the parse */
2843   if (_XML_Parse_SINGLE_BYTES(g_parser, text2, (int)strlen(text2), XML_TRUE)
2844       == XML_STATUS_ERROR)
2845     xml_failure(g_parser);
2846 }
2847 END_TEST
2848 
2849 /* Test XML_UseForeignDTD with no external subset present */
2850 static int XMLCALL
2851 external_entity_null_loader(XML_Parser parser, const XML_Char *context,
2852                             const XML_Char *base, const XML_Char *systemId,
2853                             const XML_Char *publicId) {
2854   UNUSED_P(parser);
2855   UNUSED_P(context);
2856   UNUSED_P(base);
2857   UNUSED_P(systemId);
2858   UNUSED_P(publicId);
2859   return XML_STATUS_OK;
2860 }
2861 
2862 START_TEST(test_foreign_dtd_without_external_subset) {
2863   const char *text = "<!DOCTYPE doc [<!ENTITY foo 'bar'>]>\n"
2864                      "<doc>&foo;</doc>";
2865 
2866   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
2867   XML_SetUserData(g_parser, NULL);
2868   XML_SetExternalEntityRefHandler(g_parser, external_entity_null_loader);
2869   XML_UseForeignDTD(g_parser, XML_TRUE);
2870   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
2871       == XML_STATUS_ERROR)
2872     xml_failure(g_parser);
2873 }
2874 END_TEST
2875 
2876 START_TEST(test_empty_foreign_dtd) {
2877   const char *text = "<?xml version='1.0' encoding='us-ascii'?>\n"
2878                      "<doc>&entity;</doc>";
2879 
2880   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
2881   XML_SetExternalEntityRefHandler(g_parser, external_entity_null_loader);
2882   XML_UseForeignDTD(g_parser, XML_TRUE);
2883   expect_failure(text, XML_ERROR_UNDEFINED_ENTITY,
2884                  "Undefined entity not faulted");
2885 }
2886 END_TEST
2887 
2888 /* Test XML Base is set and unset appropriately */
2889 START_TEST(test_set_base) {
2890   const XML_Char *old_base;
2891   const XML_Char *new_base = XCS("/local/file/name.xml");
2892 
2893   old_base = XML_GetBase(g_parser);
2894   if (XML_SetBase(g_parser, new_base) != XML_STATUS_OK)
2895     fail("Unable to set base");
2896   if (xcstrcmp(XML_GetBase(g_parser), new_base) != 0)
2897     fail("Base setting not correct");
2898   if (XML_SetBase(g_parser, NULL) != XML_STATUS_OK)
2899     fail("Unable to NULL base");
2900   if (XML_GetBase(g_parser) != NULL)
2901     fail("Base setting not nulled");
2902   XML_SetBase(g_parser, old_base);
2903 }
2904 END_TEST
2905 
2906 /* Test attribute counts, indexing, etc */
2907 typedef struct attrInfo {
2908   const XML_Char *name;
2909   const XML_Char *value;
2910 } AttrInfo;
2911 
2912 typedef struct elementInfo {
2913   const XML_Char *name;
2914   int attr_count;
2915   const XML_Char *id_name;
2916   AttrInfo *attributes;
2917 } ElementInfo;
2918 
2919 static void XMLCALL
2920 counting_start_element_handler(void *userData, const XML_Char *name,
2921                                const XML_Char **atts) {
2922   ElementInfo *info = (ElementInfo *)userData;
2923   AttrInfo *attr;
2924   int count, id, i;
2925 
2926   while (info->name != NULL) {
2927     if (! xcstrcmp(name, info->name))
2928       break;
2929     info++;
2930   }
2931   if (info->name == NULL)
2932     fail("Element not recognised");
2933   /* The attribute count is twice what you might expect.  It is a
2934    * count of items in atts, an array which contains alternating
2935    * attribute names and attribute values.  For the naive user this
2936    * is possibly a little unexpected, but it is what the
2937    * documentation in expat.h tells us to expect.
2938    */
2939   count = XML_GetSpecifiedAttributeCount(g_parser);
2940   if (info->attr_count * 2 != count) {
2941     fail("Not got expected attribute count");
2942     return;
2943   }
2944   id = XML_GetIdAttributeIndex(g_parser);
2945   if (id == -1 && info->id_name != NULL) {
2946     fail("ID not present");
2947     return;
2948   }
2949   if (id != -1 && xcstrcmp(atts[id], info->id_name)) {
2950     fail("ID does not have the correct name");
2951     return;
2952   }
2953   for (i = 0; i < info->attr_count; i++) {
2954     attr = info->attributes;
2955     while (attr->name != NULL) {
2956       if (! xcstrcmp(atts[0], attr->name))
2957         break;
2958       attr++;
2959     }
2960     if (attr->name == NULL) {
2961       fail("Attribute not recognised");
2962       return;
2963     }
2964     if (xcstrcmp(atts[1], attr->value)) {
2965       fail("Attribute has wrong value");
2966       return;
2967     }
2968     /* Remember, two entries in atts per attribute (see above) */
2969     atts += 2;
2970   }
2971 }
2972 
2973 START_TEST(test_attributes) {
2974   const char *text = "<!DOCTYPE doc [\n"
2975                      "<!ELEMENT doc (tag)>\n"
2976                      "<!ATTLIST doc id ID #REQUIRED>\n"
2977                      "]>"
2978                      "<doc a='1' id='one' b='2'>"
2979                      "<tag c='3'/>"
2980                      "</doc>";
2981   AttrInfo doc_info[] = {{XCS("a"), XCS("1")},
2982                          {XCS("b"), XCS("2")},
2983                          {XCS("id"), XCS("one")},
2984                          {NULL, NULL}};
2985   AttrInfo tag_info[] = {{XCS("c"), XCS("3")}, {NULL, NULL}};
2986   ElementInfo info[] = {{XCS("doc"), 3, XCS("id"), NULL},
2987                         {XCS("tag"), 1, NULL, NULL},
2988                         {NULL, 0, NULL, NULL}};
2989   info[0].attributes = doc_info;
2990   info[1].attributes = tag_info;
2991 
2992   XML_SetStartElementHandler(g_parser, counting_start_element_handler);
2993   XML_SetUserData(g_parser, info);
2994   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
2995       == XML_STATUS_ERROR)
2996     xml_failure(g_parser);
2997 }
2998 END_TEST
2999 
3000 /* Test reset works correctly in the middle of processing an internal
3001  * entity.  Exercises some obscure code in XML_ParserReset().
3002  */
3003 START_TEST(test_reset_in_entity) {
3004   const char *text = "<!DOCTYPE doc [\n"
3005                      "<!ENTITY wombat 'wom'>\n"
3006                      "<!ENTITY entity 'hi &wom; there'>\n"
3007                      "]>\n"
3008                      "<doc>&entity;</doc>";
3009   XML_ParsingStatus status;
3010 
3011   resumable = XML_TRUE;
3012   XML_SetCharacterDataHandler(g_parser, clearing_aborting_character_handler);
3013   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_FALSE)
3014       == XML_STATUS_ERROR)
3015     xml_failure(g_parser);
3016   XML_GetParsingStatus(g_parser, &status);
3017   if (status.parsing != XML_SUSPENDED)
3018     fail("Parsing status not SUSPENDED");
3019   XML_ParserReset(g_parser, NULL);
3020   XML_GetParsingStatus(g_parser, &status);
3021   if (status.parsing != XML_INITIALIZED)
3022     fail("Parsing status doesn't reset to INITIALIZED");
3023 }
3024 END_TEST
3025 
3026 /* Test that resume correctly passes through parse errors */
3027 START_TEST(test_resume_invalid_parse) {
3028   const char *text = "<doc>Hello</doc"; /* Missing closing wedge */
3029 
3030   resumable = XML_TRUE;
3031   XML_SetCharacterDataHandler(g_parser, clearing_aborting_character_handler);
3032   if (XML_Parse(g_parser, text, (int)strlen(text), XML_TRUE)
3033       == XML_STATUS_ERROR)
3034     xml_failure(g_parser);
3035   if (XML_ResumeParser(g_parser) == XML_STATUS_OK)
3036     fail("Resumed invalid parse not faulted");
3037   if (XML_GetErrorCode(g_parser) != XML_ERROR_UNCLOSED_TOKEN)
3038     fail("Invalid parse not correctly faulted");
3039 }
3040 END_TEST
3041 
3042 /* Test that re-suspended parses are correctly passed through */
3043 START_TEST(test_resume_resuspended) {
3044   const char *text = "<doc>Hello<meep/>world</doc>";
3045 
3046   resumable = XML_TRUE;
3047   XML_SetCharacterDataHandler(g_parser, clearing_aborting_character_handler);
3048   if (XML_Parse(g_parser, text, (int)strlen(text), XML_TRUE)
3049       == XML_STATUS_ERROR)
3050     xml_failure(g_parser);
3051   resumable = XML_TRUE;
3052   XML_SetCharacterDataHandler(g_parser, clearing_aborting_character_handler);
3053   if (XML_ResumeParser(g_parser) != XML_STATUS_SUSPENDED)
3054     fail("Resumption not suspended");
3055   /* This one should succeed and finish up */
3056   if (XML_ResumeParser(g_parser) != XML_STATUS_OK)
3057     xml_failure(g_parser);
3058 }
3059 END_TEST
3060 
3061 /* Test that CDATA shows up correctly through a default handler */
3062 START_TEST(test_cdata_default) {
3063   const char *text = "<doc><![CDATA[Hello\nworld]]></doc>";
3064   const XML_Char *expected = XCS("<doc><![CDATA[Hello\nworld]]></doc>");
3065   CharData storage;
3066 
3067   CharData_Init(&storage);
3068   XML_SetUserData(g_parser, &storage);
3069   XML_SetDefaultHandler(g_parser, accumulate_characters);
3070 
3071   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
3072       == XML_STATUS_ERROR)
3073     xml_failure(g_parser);
3074   CharData_CheckXMLChars(&storage, expected);
3075 }
3076 END_TEST
3077 
3078 /* Test resetting a subordinate parser does exactly nothing */
3079 static int XMLCALL
3080 external_entity_resetter(XML_Parser parser, const XML_Char *context,
3081                          const XML_Char *base, const XML_Char *systemId,
3082                          const XML_Char *publicId) {
3083   const char *text = "<!ELEMENT doc (#PCDATA)*>";
3084   XML_Parser ext_parser;
3085   XML_ParsingStatus status;
3086 
3087   UNUSED_P(base);
3088   UNUSED_P(systemId);
3089   UNUSED_P(publicId);
3090   ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
3091   if (ext_parser == NULL)
3092     fail("Could not create external entity parser");
3093   XML_GetParsingStatus(ext_parser, &status);
3094   if (status.parsing != XML_INITIALIZED) {
3095     fail("Parsing status is not INITIALIZED");
3096     return XML_STATUS_ERROR;
3097   }
3098   if (_XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE)
3099       == XML_STATUS_ERROR) {
3100     xml_failure(parser);
3101     return XML_STATUS_ERROR;
3102   }
3103   XML_GetParsingStatus(ext_parser, &status);
3104   if (status.parsing != XML_FINISHED) {
3105     fail("Parsing status is not FINISHED");
3106     return XML_STATUS_ERROR;
3107   }
3108   /* Check we can't parse here */
3109   if (XML_Parse(ext_parser, text, (int)strlen(text), XML_TRUE)
3110       != XML_STATUS_ERROR)
3111     fail("Parsing when finished not faulted");
3112   if (XML_GetErrorCode(ext_parser) != XML_ERROR_FINISHED)
3113     fail("Parsing when finished faulted with wrong code");
3114   XML_ParserReset(ext_parser, NULL);
3115   XML_GetParsingStatus(ext_parser, &status);
3116   if (status.parsing != XML_FINISHED) {
3117     fail("Parsing status not still FINISHED");
3118     return XML_STATUS_ERROR;
3119   }
3120   XML_ParserFree(ext_parser);
3121   return XML_STATUS_OK;
3122 }
3123 
3124 START_TEST(test_subordinate_reset) {
3125   const char *text = "<?xml version='1.0' encoding='us-ascii'?>\n"
3126                      "<!DOCTYPE doc SYSTEM 'foo'>\n"
3127                      "<doc>&entity;</doc>";
3128 
3129   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
3130   XML_SetExternalEntityRefHandler(g_parser, external_entity_resetter);
3131   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
3132       == XML_STATUS_ERROR)
3133     xml_failure(g_parser);
3134 }
3135 END_TEST
3136 
3137 /* Test suspending a subordinate parser */
3138 
3139 static void XMLCALL
3140 entity_suspending_decl_handler(void *userData, const XML_Char *name,
3141                                XML_Content *model) {
3142   XML_Parser ext_parser = (XML_Parser)userData;
3143 
3144   UNUSED_P(name);
3145   if (XML_StopParser(ext_parser, XML_TRUE) != XML_STATUS_ERROR)
3146     fail("Attempting to suspend a subordinate parser not faulted");
3147   if (XML_GetErrorCode(ext_parser) != XML_ERROR_SUSPEND_PE)
3148     fail("Suspending subordinate parser get wrong code");
3149   XML_SetElementDeclHandler(ext_parser, NULL);
3150   XML_FreeContentModel(g_parser, model);
3151 }
3152 
3153 static int XMLCALL
3154 external_entity_suspender(XML_Parser parser, const XML_Char *context,
3155                           const XML_Char *base, const XML_Char *systemId,
3156                           const XML_Char *publicId) {
3157   const char *text = "<!ELEMENT doc (#PCDATA)*>";
3158   XML_Parser ext_parser;
3159 
3160   UNUSED_P(base);
3161   UNUSED_P(systemId);
3162   UNUSED_P(publicId);
3163   ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
3164   if (ext_parser == NULL)
3165     fail("Could not create external entity parser");
3166   XML_SetElementDeclHandler(ext_parser, entity_suspending_decl_handler);
3167   XML_SetUserData(ext_parser, ext_parser);
3168   if (_XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE)
3169       == XML_STATUS_ERROR) {
3170     xml_failure(ext_parser);
3171     return XML_STATUS_ERROR;
3172   }
3173   XML_ParserFree(ext_parser);
3174   return XML_STATUS_OK;
3175 }
3176 
3177 START_TEST(test_subordinate_suspend) {
3178   const char *text = "<?xml version='1.0' encoding='us-ascii'?>\n"
3179                      "<!DOCTYPE doc SYSTEM 'foo'>\n"
3180                      "<doc>&entity;</doc>";
3181 
3182   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
3183   XML_SetExternalEntityRefHandler(g_parser, external_entity_suspender);
3184   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
3185       == XML_STATUS_ERROR)
3186     xml_failure(g_parser);
3187 }
3188 END_TEST
3189 
3190 /* Test suspending a subordinate parser from an XML declaration */
3191 /* Increases code coverage of the tests */
3192 static void XMLCALL
3193 entity_suspending_xdecl_handler(void *userData, const XML_Char *version,
3194                                 const XML_Char *encoding, int standalone) {
3195   XML_Parser ext_parser = (XML_Parser)userData;
3196 
3197   UNUSED_P(version);
3198   UNUSED_P(encoding);
3199   UNUSED_P(standalone);
3200   XML_StopParser(ext_parser, resumable);
3201   XML_SetXmlDeclHandler(ext_parser, NULL);
3202 }
3203 
3204 static int XMLCALL
3205 external_entity_suspend_xmldecl(XML_Parser parser, const XML_Char *context,
3206                                 const XML_Char *base, const XML_Char *systemId,
3207                                 const XML_Char *publicId) {
3208   const char *text = "<?xml version='1.0' encoding='us-ascii'?>";
3209   XML_Parser ext_parser;
3210   XML_ParsingStatus status;
3211   enum XML_Status rc;
3212 
3213   UNUSED_P(base);
3214   UNUSED_P(systemId);
3215   UNUSED_P(publicId);
3216   ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
3217   if (ext_parser == NULL)
3218     fail("Could not create external entity parser");
3219   XML_SetXmlDeclHandler(ext_parser, entity_suspending_xdecl_handler);
3220   XML_SetUserData(ext_parser, ext_parser);
3221   rc = _XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE);
3222   XML_GetParsingStatus(ext_parser, &status);
3223   if (resumable) {
3224     if (rc == XML_STATUS_ERROR)
3225       xml_failure(ext_parser);
3226     if (status.parsing != XML_SUSPENDED)
3227       fail("Ext Parsing status not SUSPENDED");
3228   } else {
3229     if (rc != XML_STATUS_ERROR)
3230       fail("Ext parsing not aborted");
3231     if (XML_GetErrorCode(ext_parser) != XML_ERROR_ABORTED)
3232       xml_failure(ext_parser);
3233     if (status.parsing != XML_FINISHED)
3234       fail("Ext Parsing status not FINISHED");
3235   }
3236 
3237   XML_ParserFree(ext_parser);
3238   return XML_STATUS_OK;
3239 }
3240 
3241 START_TEST(test_subordinate_xdecl_suspend) {
3242   const char *text
3243       = "<!DOCTYPE doc [\n"
3244         "  <!ENTITY entity SYSTEM 'http://example.org/dummy.ent'>\n"
3245         "]>\n"
3246         "<doc>&entity;</doc>";
3247 
3248   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
3249   XML_SetExternalEntityRefHandler(g_parser, external_entity_suspend_xmldecl);
3250   resumable = XML_TRUE;
3251   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
3252       == XML_STATUS_ERROR)
3253     xml_failure(g_parser);
3254 }
3255 END_TEST
3256 
3257 START_TEST(test_subordinate_xdecl_abort) {
3258   const char *text
3259       = "<!DOCTYPE doc [\n"
3260         "  <!ENTITY entity SYSTEM 'http://example.org/dummy.ent'>\n"
3261         "]>\n"
3262         "<doc>&entity;</doc>";
3263 
3264   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
3265   XML_SetExternalEntityRefHandler(g_parser, external_entity_suspend_xmldecl);
3266   resumable = XML_FALSE;
3267   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
3268       == XML_STATUS_ERROR)
3269     xml_failure(g_parser);
3270 }
3271 END_TEST
3272 
3273 /* Test external entity fault handling with suspension */
3274 static int XMLCALL
3275 external_entity_suspending_faulter(XML_Parser parser, const XML_Char *context,
3276                                    const XML_Char *base,
3277                                    const XML_Char *systemId,
3278                                    const XML_Char *publicId) {
3279   XML_Parser ext_parser;
3280   ExtFaults *fault = (ExtFaults *)XML_GetUserData(parser);
3281   void *buffer;
3282   int parse_len = (int)strlen(fault->parse_text);
3283 
3284   UNUSED_P(base);
3285   UNUSED_P(systemId);
3286   UNUSED_P(publicId);
3287   ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
3288   if (ext_parser == NULL)
3289     fail("Could not create external entity parser");
3290   XML_SetXmlDeclHandler(ext_parser, entity_suspending_xdecl_handler);
3291   XML_SetUserData(ext_parser, ext_parser);
3292   resumable = XML_TRUE;
3293   buffer = XML_GetBuffer(ext_parser, parse_len);
3294   if (buffer == NULL)
3295     fail("Could not allocate parse buffer");
3296   assert(buffer != NULL);
3297   memcpy(buffer, fault->parse_text, parse_len);
3298   if (XML_ParseBuffer(ext_parser, parse_len, XML_FALSE) != XML_STATUS_SUSPENDED)
3299     fail("XML declaration did not suspend");
3300   if (XML_ResumeParser(ext_parser) != XML_STATUS_OK)
3301     xml_failure(ext_parser);
3302   if (XML_ParseBuffer(ext_parser, 0, XML_TRUE) != XML_STATUS_ERROR)
3303     fail(fault->fail_text);
3304   if (XML_GetErrorCode(ext_parser) != fault->error)
3305     xml_failure(ext_parser);
3306 
3307   XML_ParserFree(ext_parser);
3308   return XML_STATUS_ERROR;
3309 }
3310 
3311 START_TEST(test_ext_entity_invalid_suspended_parse) {
3312   const char *text = "<!DOCTYPE doc [\n"
3313                      "  <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n"
3314                      "]>\n"
3315                      "<doc>&en;</doc>";
3316   ExtFaults faults[]
3317       = {{"<?xml version='1.0' encoding='us-ascii'?><",
3318           "Incomplete element declaration not faulted", NULL,
3319           XML_ERROR_UNCLOSED_TOKEN},
3320          {/* First two bytes of a three-byte char */
3321           "<?xml version='1.0' encoding='utf-8'?>\xe2\x82",
3322           "Incomplete character not faulted", NULL, XML_ERROR_PARTIAL_CHAR},
3323          {NULL, NULL, NULL, XML_ERROR_NONE}};
3324   ExtFaults *fault;
3325 
3326   for (fault = &faults[0]; fault->parse_text != NULL; fault++) {
3327     XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
3328     XML_SetExternalEntityRefHandler(g_parser,
3329                                     external_entity_suspending_faulter);
3330     XML_SetUserData(g_parser, fault);
3331     expect_failure(text, XML_ERROR_EXTERNAL_ENTITY_HANDLING,
3332                    "Parser did not report external entity error");
3333     XML_ParserReset(g_parser, NULL);
3334   }
3335 }
3336 END_TEST
3337 
3338 /* Test setting an explicit encoding */
3339 START_TEST(test_explicit_encoding) {
3340   const char *text1 = "<doc>Hello ";
3341   const char *text2 = " World</doc>";
3342 
3343   /* Just check that we can set the encoding to NULL before starting */
3344   if (XML_SetEncoding(g_parser, NULL) != XML_STATUS_OK)
3345     fail("Failed to initialise encoding to NULL");
3346   /* Say we are UTF-8 */
3347   if (XML_SetEncoding(g_parser, XCS("utf-8")) != XML_STATUS_OK)
3348     fail("Failed to set explicit encoding");
3349   if (_XML_Parse_SINGLE_BYTES(g_parser, text1, (int)strlen(text1), XML_FALSE)
3350       == XML_STATUS_ERROR)
3351     xml_failure(g_parser);
3352   /* Try to switch encodings mid-parse */
3353   if (XML_SetEncoding(g_parser, XCS("us-ascii")) != XML_STATUS_ERROR)
3354     fail("Allowed encoding change");
3355   if (_XML_Parse_SINGLE_BYTES(g_parser, text2, (int)strlen(text2), XML_TRUE)
3356       == XML_STATUS_ERROR)
3357     xml_failure(g_parser);
3358   /* Try now the parse is over */
3359   if (XML_SetEncoding(g_parser, NULL) != XML_STATUS_OK)
3360     fail("Failed to unset encoding");
3361 }
3362 END_TEST
3363 
3364 /* Test handling of trailing CR (rather than newline) */
3365 static void XMLCALL
3366 cr_cdata_handler(void *userData, const XML_Char *s, int len) {
3367   int *pfound = (int *)userData;
3368 
3369   /* Internal processing turns the CR into a newline for the
3370    * character data handler, but not for the default handler
3371    */
3372   if (len == 1 && (*s == XCS('\n') || *s == XCS('\r')))
3373     *pfound = 1;
3374 }
3375 
3376 START_TEST(test_trailing_cr) {
3377   const char *text = "<doc>\r";
3378   int found_cr;
3379 
3380   /* Try with a character handler, for code coverage */
3381   XML_SetCharacterDataHandler(g_parser, cr_cdata_handler);
3382   XML_SetUserData(g_parser, &found_cr);
3383   found_cr = 0;
3384   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
3385       == XML_STATUS_OK)
3386     fail("Failed to fault unclosed doc");
3387   if (found_cr == 0)
3388     fail("Did not catch the carriage return");
3389   XML_ParserReset(g_parser, NULL);
3390 
3391   /* Now with a default handler instead */
3392   XML_SetDefaultHandler(g_parser, cr_cdata_handler);
3393   XML_SetUserData(g_parser, &found_cr);
3394   found_cr = 0;
3395   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
3396       == XML_STATUS_OK)
3397     fail("Failed to fault unclosed doc");
3398   if (found_cr == 0)
3399     fail("Did not catch default carriage return");
3400 }
3401 END_TEST
3402 
3403 /* Test trailing CR in an external entity parse */
3404 static int XMLCALL
3405 external_entity_cr_catcher(XML_Parser parser, const XML_Char *context,
3406                            const XML_Char *base, const XML_Char *systemId,
3407                            const XML_Char *publicId) {
3408   const char *text = "\r";
3409   XML_Parser ext_parser;
3410 
3411   UNUSED_P(base);
3412   UNUSED_P(systemId);
3413   UNUSED_P(publicId);
3414   ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
3415   if (ext_parser == NULL)
3416     fail("Could not create external entity parser");
3417   XML_SetCharacterDataHandler(ext_parser, cr_cdata_handler);
3418   if (_XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE)
3419       == XML_STATUS_ERROR)
3420     xml_failure(ext_parser);
3421   XML_ParserFree(ext_parser);
3422   return XML_STATUS_OK;
3423 }
3424 
3425 static int XMLCALL
3426 external_entity_bad_cr_catcher(XML_Parser parser, const XML_Char *context,
3427                                const XML_Char *base, const XML_Char *systemId,
3428                                const XML_Char *publicId) {
3429   const char *text = "<tag>\r";
3430   XML_Parser ext_parser;
3431 
3432   UNUSED_P(base);
3433   UNUSED_P(systemId);
3434   UNUSED_P(publicId);
3435   ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
3436   if (ext_parser == NULL)
3437     fail("Could not create external entity parser");
3438   XML_SetCharacterDataHandler(ext_parser, cr_cdata_handler);
3439   if (_XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE)
3440       == XML_STATUS_OK)
3441     fail("Async entity error not caught");
3442   if (XML_GetErrorCode(ext_parser) != XML_ERROR_ASYNC_ENTITY)
3443     xml_failure(ext_parser);
3444   XML_ParserFree(ext_parser);
3445   return XML_STATUS_OK;
3446 }
3447 
3448 START_TEST(test_ext_entity_trailing_cr) {
3449   const char *text = "<!DOCTYPE doc [\n"
3450                      "  <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n"
3451                      "]>\n"
3452                      "<doc>&en;</doc>";
3453   int found_cr;
3454 
3455   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
3456   XML_SetExternalEntityRefHandler(g_parser, external_entity_cr_catcher);
3457   XML_SetUserData(g_parser, &found_cr);
3458   found_cr = 0;
3459   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
3460       != XML_STATUS_OK)
3461     xml_failure(g_parser);
3462   if (found_cr == 0)
3463     fail("No carriage return found");
3464   XML_ParserReset(g_parser, NULL);
3465 
3466   /* Try again with a different trailing CR */
3467   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
3468   XML_SetExternalEntityRefHandler(g_parser, external_entity_bad_cr_catcher);
3469   XML_SetUserData(g_parser, &found_cr);
3470   found_cr = 0;
3471   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
3472       != XML_STATUS_OK)
3473     xml_failure(g_parser);
3474   if (found_cr == 0)
3475     fail("No carriage return found");
3476 }
3477 END_TEST
3478 
3479 /* Test handling of trailing square bracket */
3480 static void XMLCALL
3481 rsqb_handler(void *userData, const XML_Char *s, int len) {
3482   int *pfound = (int *)userData;
3483 
3484   if (len == 1 && *s == XCS(']'))
3485     *pfound = 1;
3486 }
3487 
3488 START_TEST(test_trailing_rsqb) {
3489   const char *text8 = "<doc>]";
3490   const char text16[] = "\xFF\xFE<\000d\000o\000c\000>\000]\000";
3491   int found_rsqb;
3492   int text8_len = (int)strlen(text8);
3493 
3494   XML_SetCharacterDataHandler(g_parser, rsqb_handler);
3495   XML_SetUserData(g_parser, &found_rsqb);
3496   found_rsqb = 0;
3497   if (_XML_Parse_SINGLE_BYTES(g_parser, text8, text8_len, XML_TRUE)
3498       == XML_STATUS_OK)
3499     fail("Failed to fault unclosed doc");
3500   if (found_rsqb == 0)
3501     fail("Did not catch the right square bracket");
3502 
3503   /* Try again with a different encoding */
3504   XML_ParserReset(g_parser, NULL);
3505   XML_SetCharacterDataHandler(g_parser, rsqb_handler);
3506   XML_SetUserData(g_parser, &found_rsqb);
3507   found_rsqb = 0;
3508   if (_XML_Parse_SINGLE_BYTES(g_parser, text16, (int)sizeof(text16) - 1,
3509                               XML_TRUE)
3510       == XML_STATUS_OK)
3511     fail("Failed to fault unclosed doc");
3512   if (found_rsqb == 0)
3513     fail("Did not catch the right square bracket");
3514 
3515   /* And finally with a default handler */
3516   XML_ParserReset(g_parser, NULL);
3517   XML_SetDefaultHandler(g_parser, rsqb_handler);
3518   XML_SetUserData(g_parser, &found_rsqb);
3519   found_rsqb = 0;
3520   if (_XML_Parse_SINGLE_BYTES(g_parser, text16, (int)sizeof(text16) - 1,
3521                               XML_TRUE)
3522       == XML_STATUS_OK)
3523     fail("Failed to fault unclosed doc");
3524   if (found_rsqb == 0)
3525     fail("Did not catch the right square bracket");
3526 }
3527 END_TEST
3528 
3529 /* Test trailing right square bracket in an external entity parse */
3530 static int XMLCALL
3531 external_entity_rsqb_catcher(XML_Parser parser, const XML_Char *context,
3532                              const XML_Char *base, const XML_Char *systemId,
3533                              const XML_Char *publicId) {
3534   const char *text = "<tag>]";
3535   XML_Parser ext_parser;
3536 
3537   UNUSED_P(base);
3538   UNUSED_P(systemId);
3539   UNUSED_P(publicId);
3540   ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
3541   if (ext_parser == NULL)
3542     fail("Could not create external entity parser");
3543   XML_SetCharacterDataHandler(ext_parser, rsqb_handler);
3544   if (_XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE)
3545       != XML_STATUS_ERROR)
3546     fail("Async entity error not caught");
3547   if (XML_GetErrorCode(ext_parser) != XML_ERROR_ASYNC_ENTITY)
3548     xml_failure(ext_parser);
3549   XML_ParserFree(ext_parser);
3550   return XML_STATUS_OK;
3551 }
3552 
3553 START_TEST(test_ext_entity_trailing_rsqb) {
3554   const char *text = "<!DOCTYPE doc [\n"
3555                      "  <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n"
3556                      "]>\n"
3557                      "<doc>&en;</doc>";
3558   int found_rsqb;
3559 
3560   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
3561   XML_SetExternalEntityRefHandler(g_parser, external_entity_rsqb_catcher);
3562   XML_SetUserData(g_parser, &found_rsqb);
3563   found_rsqb = 0;
3564   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
3565       != XML_STATUS_OK)
3566     xml_failure(g_parser);
3567   if (found_rsqb == 0)
3568     fail("No right square bracket found");
3569 }
3570 END_TEST
3571 
3572 /* Test CDATA handling in an external entity */
3573 static int XMLCALL
3574 external_entity_good_cdata_ascii(XML_Parser parser, const XML_Char *context,
3575                                  const XML_Char *base, const XML_Char *systemId,
3576                                  const XML_Char *publicId) {
3577   const char *text = "<a><![CDATA[<greeting>Hello, world!</greeting>]]></a>";
3578   const XML_Char *expected = XCS("<greeting>Hello, world!</greeting>");
3579   CharData storage;
3580   XML_Parser ext_parser;
3581 
3582   UNUSED_P(base);
3583   UNUSED_P(systemId);
3584   UNUSED_P(publicId);
3585   CharData_Init(&storage);
3586   ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
3587   if (ext_parser == NULL)
3588     fail("Could not create external entity parser");
3589   XML_SetUserData(ext_parser, &storage);
3590   XML_SetCharacterDataHandler(ext_parser, accumulate_characters);
3591 
3592   if (_XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE)
3593       == XML_STATUS_ERROR)
3594     xml_failure(ext_parser);
3595   CharData_CheckXMLChars(&storage, expected);
3596 
3597   XML_ParserFree(ext_parser);
3598   return XML_STATUS_OK;
3599 }
3600 
3601 START_TEST(test_ext_entity_good_cdata) {
3602   const char *text = "<!DOCTYPE doc [\n"
3603                      "  <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n"
3604                      "]>\n"
3605                      "<doc>&en;</doc>";
3606 
3607   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
3608   XML_SetExternalEntityRefHandler(g_parser, external_entity_good_cdata_ascii);
3609   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
3610       != XML_STATUS_OK)
3611     xml_failure(g_parser);
3612 }
3613 END_TEST
3614 
3615 /* Test user parameter settings */
3616 /* Variable holding the expected handler userData */
3617 static void *handler_data = NULL;
3618 /* Count of the number of times the comment handler has been invoked */
3619 static int comment_count = 0;
3620 /* Count of the number of skipped entities */
3621 static int skip_count = 0;
3622 /* Count of the number of times the XML declaration handler is invoked */
3623 static int xdecl_count = 0;
3624 
3625 static void XMLCALL
3626 xml_decl_handler(void *userData, const XML_Char *version,
3627                  const XML_Char *encoding, int standalone) {
3628   UNUSED_P(version);
3629   UNUSED_P(encoding);
3630   if (userData != handler_data)
3631     fail("User data (xml decl) not correctly set");
3632   if (standalone != -1)
3633     fail("Standalone not flagged as not present in XML decl");
3634   xdecl_count++;
3635 }
3636 
3637 static void XMLCALL
3638 param_check_skip_handler(void *userData, const XML_Char *entityName,
3639                          int is_parameter_entity) {
3640   UNUSED_P(entityName);
3641   UNUSED_P(is_parameter_entity);
3642   if (userData != handler_data)
3643     fail("User data (skip) not correctly set");
3644   skip_count++;
3645 }
3646 
3647 static void XMLCALL
3648 data_check_comment_handler(void *userData, const XML_Char *data) {
3649   UNUSED_P(data);
3650   /* Check that the userData passed through is what we expect */
3651   if (userData != handler_data)
3652     fail("User data (parser) not correctly set");
3653   /* Check that the user data in the parser is appropriate */
3654   if (XML_GetUserData(userData) != (void *)1)
3655     fail("User data in parser not correctly set");
3656   comment_count++;
3657 }
3658 
3659 static int XMLCALL
3660 external_entity_param_checker(XML_Parser parser, const XML_Char *context,
3661                               const XML_Char *base, const XML_Char *systemId,
3662                               const XML_Char *publicId) {
3663   const char *text = "<!-- Subordinate parser -->\n"
3664                      "<!ELEMENT doc (#PCDATA)*>";
3665   XML_Parser ext_parser;
3666 
3667   UNUSED_P(base);
3668   UNUSED_P(systemId);
3669   UNUSED_P(publicId);
3670   ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
3671   if (ext_parser == NULL)
3672     fail("Could not create external entity parser");
3673   handler_data = ext_parser;
3674   if (_XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE)
3675       == XML_STATUS_ERROR) {
3676     xml_failure(parser);
3677     return XML_STATUS_ERROR;
3678   }
3679   handler_data = parser;
3680   XML_ParserFree(ext_parser);
3681   return XML_STATUS_OK;
3682 }
3683 
3684 START_TEST(test_user_parameters) {
3685   const char *text = "<?xml version='1.0' encoding='us-ascii'?>\n"
3686                      "<!-- Primary parse -->\n"
3687                      "<!DOCTYPE doc SYSTEM 'foo'>\n"
3688                      "<doc>&entity;";
3689   const char *epilog = "<!-- Back to primary parser -->\n"
3690                        "</doc>";
3691 
3692   comment_count = 0;
3693   skip_count = 0;
3694   xdecl_count = 0;
3695   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
3696   XML_SetXmlDeclHandler(g_parser, xml_decl_handler);
3697   XML_SetExternalEntityRefHandler(g_parser, external_entity_param_checker);
3698   XML_SetCommentHandler(g_parser, data_check_comment_handler);
3699   XML_SetSkippedEntityHandler(g_parser, param_check_skip_handler);
3700   XML_UseParserAsHandlerArg(g_parser);
3701   XML_SetUserData(g_parser, (void *)1);
3702   handler_data = g_parser;
3703   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_FALSE)
3704       == XML_STATUS_ERROR)
3705     xml_failure(g_parser);
3706   if (comment_count != 2)
3707     fail("Comment handler not invoked enough times");
3708   /* Ensure we can't change policy mid-parse */
3709   if (XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_NEVER))
3710     fail("Changed param entity parsing policy while parsing");
3711   if (_XML_Parse_SINGLE_BYTES(g_parser, epilog, (int)strlen(epilog), XML_TRUE)
3712       == XML_STATUS_ERROR)
3713     xml_failure(g_parser);
3714   if (comment_count != 3)
3715     fail("Comment handler not invoked enough times");
3716   if (skip_count != 1)
3717     fail("Skip handler not invoked enough times");
3718   if (xdecl_count != 1)
3719     fail("XML declaration handler not invoked");
3720 }
3721 END_TEST
3722 
3723 /* Test that an explicit external entity handler argument replaces
3724  * the parser as the first argument.
3725  *
3726  * We do not call the first parameter to the external entity handler
3727  * 'parser' for once, since the first time the handler is called it
3728  * will actually be a text string.  We need to be able to access the
3729  * global 'parser' variable to create our external entity parser from,
3730  * since there are code paths we need to ensure get executed.
3731  */
3732 static int XMLCALL
3733 external_entity_ref_param_checker(XML_Parser parameter, const XML_Char *context,
3734                                   const XML_Char *base,
3735                                   const XML_Char *systemId,
3736                                   const XML_Char *publicId) {
3737   const char *text = "<!ELEMENT doc (#PCDATA)*>";
3738   XML_Parser ext_parser;
3739 
3740   UNUSED_P(base);
3741   UNUSED_P(systemId);
3742   UNUSED_P(publicId);
3743   if ((void *)parameter != handler_data)
3744     fail("External entity ref handler parameter not correct");
3745 
3746   /* Here we use the global 'parser' variable */
3747   ext_parser = XML_ExternalEntityParserCreate(g_parser, context, NULL);
3748   if (ext_parser == NULL)
3749     fail("Could not create external entity parser");
3750   if (_XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE)
3751       == XML_STATUS_ERROR)
3752     xml_failure(ext_parser);
3753 
3754   XML_ParserFree(ext_parser);
3755   return XML_STATUS_OK;
3756 }
3757 
3758 START_TEST(test_ext_entity_ref_parameter) {
3759   const char *text = "<?xml version='1.0' encoding='us-ascii'?>\n"
3760                      "<!DOCTYPE doc SYSTEM 'foo'>\n"
3761                      "<doc>&entity;</doc>";
3762 
3763   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
3764   XML_SetExternalEntityRefHandler(g_parser, external_entity_ref_param_checker);
3765   /* Set a handler arg that is not NULL and not parser (which is
3766    * what NULL would cause to be passed.
3767    */
3768   XML_SetExternalEntityRefHandlerArg(g_parser, (void *)text);
3769   handler_data = (void *)text;
3770   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
3771       == XML_STATUS_ERROR)
3772     xml_failure(g_parser);
3773 
3774   /* Now try again with unset args */
3775   XML_ParserReset(g_parser, NULL);
3776   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
3777   XML_SetExternalEntityRefHandler(g_parser, external_entity_ref_param_checker);
3778   XML_SetExternalEntityRefHandlerArg(g_parser, NULL);
3779   handler_data = (void *)g_parser;
3780   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
3781       == XML_STATUS_ERROR)
3782     xml_failure(g_parser);
3783 }
3784 END_TEST
3785 
3786 /* Test the parsing of an empty string */
3787 START_TEST(test_empty_parse) {
3788   const char *text = "<doc></doc>";
3789   const char *partial = "<doc>";
3790 
3791   if (XML_Parse(g_parser, NULL, 0, XML_FALSE) == XML_STATUS_ERROR)
3792     fail("Parsing empty string faulted");
3793   if (XML_Parse(g_parser, NULL, 0, XML_TRUE) != XML_STATUS_ERROR)
3794     fail("Parsing final empty string not faulted");
3795   if (XML_GetErrorCode(g_parser) != XML_ERROR_NO_ELEMENTS)
3796     fail("Parsing final empty string faulted for wrong reason");
3797 
3798   /* Now try with valid text before the empty end */
3799   XML_ParserReset(g_parser, NULL);
3800   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_FALSE)
3801       == XML_STATUS_ERROR)
3802     xml_failure(g_parser);
3803   if (XML_Parse(g_parser, NULL, 0, XML_TRUE) == XML_STATUS_ERROR)
3804     fail("Parsing final empty string faulted");
3805 
3806   /* Now try with invalid text before the empty end */
3807   XML_ParserReset(g_parser, NULL);
3808   if (_XML_Parse_SINGLE_BYTES(g_parser, partial, (int)strlen(partial),
3809                               XML_FALSE)
3810       == XML_STATUS_ERROR)
3811     xml_failure(g_parser);
3812   if (XML_Parse(g_parser, NULL, 0, XML_TRUE) != XML_STATUS_ERROR)
3813     fail("Parsing final incomplete empty string not faulted");
3814 }
3815 END_TEST
3816 
3817 /* Test odd corners of the XML_GetBuffer interface */
3818 static enum XML_Status
3819 get_feature(enum XML_FeatureEnum feature_id, long *presult) {
3820   const XML_Feature *feature = XML_GetFeatureList();
3821 
3822   if (feature == NULL)
3823     return XML_STATUS_ERROR;
3824   for (; feature->feature != XML_FEATURE_END; feature++) {
3825     if (feature->feature == feature_id) {
3826       *presult = feature->value;
3827       return XML_STATUS_OK;
3828     }
3829   }
3830   return XML_STATUS_ERROR;
3831 }
3832 
3833 /* Having an element name longer than 1024 characters exercises some
3834  * of the pool allocation code in the parser that otherwise does not
3835  * get executed.  The count at the end of the line is the number of
3836  * characters (bytes) in the element name by that point.x
3837  */
3838 static const char *get_buffer_test_text
3839     = "<documentwitharidiculouslylongelementnametotease"  /* 0x030 */
3840       "aparticularcorneroftheallocationinXML_GetBuffers"  /* 0x060 */
3841       "othatwecanimprovethecoverageyetagain012345678901"  /* 0x090 */
3842       "123456789abcdef0123456789abcdef0123456789abcdef0"  /* 0x0c0 */
3843       "123456789abcdef0123456789abcdef0123456789abcdef0"  /* 0x0f0 */
3844       "123456789abcdef0123456789abcdef0123456789abcdef0"  /* 0x120 */
3845       "123456789abcdef0123456789abcdef0123456789abcdef0"  /* 0x150 */
3846       "123456789abcdef0123456789abcdef0123456789abcdef0"  /* 0x180 */
3847       "123456789abcdef0123456789abcdef0123456789abcdef0"  /* 0x1b0 */
3848       "123456789abcdef0123456789abcdef0123456789abcdef0"  /* 0x1e0 */
3849       "123456789abcdef0123456789abcdef0123456789abcdef0"  /* 0x210 */
3850       "123456789abcdef0123456789abcdef0123456789abcdef0"  /* 0x240 */
3851       "123456789abcdef0123456789abcdef0123456789abcdef0"  /* 0x270 */
3852       "123456789abcdef0123456789abcdef0123456789abcdef0"  /* 0x2a0 */
3853       "123456789abcdef0123456789abcdef0123456789abcdef0"  /* 0x2d0 */
3854       "123456789abcdef0123456789abcdef0123456789abcdef0"  /* 0x300 */
3855       "123456789abcdef0123456789abcdef0123456789abcdef0"  /* 0x330 */
3856       "123456789abcdef0123456789abcdef0123456789abcdef0"  /* 0x360 */
3857       "123456789abcdef0123456789abcdef0123456789abcdef0"  /* 0x390 */
3858       "123456789abcdef0123456789abcdef0123456789abcdef0"  /* 0x3c0 */
3859       "123456789abcdef0123456789abcdef0123456789abcdef0"  /* 0x3f0 */
3860       "123456789abcdef0123456789abcdef0123456789>\n<ef0"; /* 0x420 */
3861 
3862 /* Test odd corners of the XML_GetBuffer interface */
3863 START_TEST(test_get_buffer_1) {
3864   const char *text = get_buffer_test_text;
3865   void *buffer;
3866   long context_bytes;
3867 
3868   /* Attempt to allocate a negative length buffer */
3869   if (XML_GetBuffer(g_parser, -12) != NULL)
3870     fail("Negative length buffer not failed");
3871 
3872   /* Now get a small buffer and extend it past valid length */
3873   buffer = XML_GetBuffer(g_parser, 1536);
3874   if (buffer == NULL)
3875     fail("1.5K buffer failed");
3876   assert(buffer != NULL);
3877   memcpy(buffer, text, strlen(text));
3878   if (XML_ParseBuffer(g_parser, (int)strlen(text), XML_FALSE)
3879       == XML_STATUS_ERROR)
3880     xml_failure(g_parser);
3881   if (XML_GetBuffer(g_parser, INT_MAX) != NULL)
3882     fail("INT_MAX buffer not failed");
3883 
3884   /* Now try extending it a more reasonable but still too large
3885    * amount.  The allocator in XML_GetBuffer() doubles the buffer
3886    * size until it exceeds the requested amount or INT_MAX.  If it
3887    * exceeds INT_MAX, it rejects the request, so we want a request
3888    * between INT_MAX and INT_MAX/2.  A gap of 1K seems comfortable,
3889    * with an extra byte just to ensure that the request is off any
3890    * boundary.  The request will be inflated internally by
3891    * XML_CONTEXT_BYTES (if defined), so we subtract that from our
3892    * request.
3893    */
3894   if (get_feature(XML_FEATURE_CONTEXT_BYTES, &context_bytes) != XML_STATUS_OK)
3895     context_bytes = 0;
3896   if (XML_GetBuffer(g_parser, INT_MAX - (context_bytes + 1025)) != NULL)
3897     fail("INT_MAX- buffer not failed");
3898 
3899   /* Now try extending it a carefully crafted amount */
3900   if (XML_GetBuffer(g_parser, 1000) == NULL)
3901     fail("1000 buffer failed");
3902 }
3903 END_TEST
3904 
3905 /* Test more corners of the XML_GetBuffer interface */
3906 START_TEST(test_get_buffer_2) {
3907   const char *text = get_buffer_test_text;
3908   void *buffer;
3909 
3910   /* Now get a decent buffer */
3911   buffer = XML_GetBuffer(g_parser, 1536);
3912   if (buffer == NULL)
3913     fail("1.5K buffer failed");
3914   assert(buffer != NULL);
3915   memcpy(buffer, text, strlen(text));
3916   if (XML_ParseBuffer(g_parser, (int)strlen(text), XML_FALSE)
3917       == XML_STATUS_ERROR)
3918     xml_failure(g_parser);
3919 
3920   /* Extend it, to catch a different code path */
3921   if (XML_GetBuffer(g_parser, 1024) == NULL)
3922     fail("1024 buffer failed");
3923 }
3924 END_TEST
3925 
3926 /* Test for signed integer overflow CVE-2022-23852 */
3927 #if defined(XML_CONTEXT_BYTES)
3928 START_TEST(test_get_buffer_3_overflow) {
3929   XML_Parser parser = XML_ParserCreate(NULL);
3930   assert(parser != NULL);
3931 
3932   const char *const text = "\n";
3933   const int expectedKeepValue = (int)strlen(text);
3934 
3935   // After this call, variable "keep" in XML_GetBuffer will
3936   // have value expectedKeepValue
3937   if (XML_Parse(parser, text, (int)strlen(text), XML_FALSE /* isFinal */)
3938       == XML_STATUS_ERROR)
3939     xml_failure(parser);
3940 
3941   assert(expectedKeepValue > 0);
3942   if (XML_GetBuffer(parser, INT_MAX - expectedKeepValue + 1) != NULL)
3943     fail("enlarging buffer not failed");
3944 
3945   XML_ParserFree(parser);
3946 }
3947 END_TEST
3948 #endif // defined(XML_CONTEXT_BYTES)
3949 
3950 /* Test position information macros */
3951 START_TEST(test_byte_info_at_end) {
3952   const char *text = "<doc></doc>";
3953 
3954   if (XML_GetCurrentByteIndex(g_parser) != -1
3955       || XML_GetCurrentByteCount(g_parser) != 0)
3956     fail("Byte index/count incorrect at start of parse");
3957   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
3958       == XML_STATUS_ERROR)
3959     xml_failure(g_parser);
3960   /* At end, the count will be zero and the index the end of string */
3961   if (XML_GetCurrentByteCount(g_parser) != 0)
3962     fail("Terminal byte count incorrect");
3963   if (XML_GetCurrentByteIndex(g_parser) != (XML_Index)strlen(text))
3964     fail("Terminal byte index incorrect");
3965 }
3966 END_TEST
3967 
3968 /* Test position information from errors */
3969 #define PRE_ERROR_STR "<doc></"
3970 #define POST_ERROR_STR "wombat></doc>"
3971 START_TEST(test_byte_info_at_error) {
3972   const char *text = PRE_ERROR_STR POST_ERROR_STR;
3973 
3974   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
3975       == XML_STATUS_OK)
3976     fail("Syntax error not faulted");
3977   if (XML_GetCurrentByteCount(g_parser) != 0)
3978     fail("Error byte count incorrect");
3979   if (XML_GetCurrentByteIndex(g_parser) != strlen(PRE_ERROR_STR))
3980     fail("Error byte index incorrect");
3981 }
3982 END_TEST
3983 #undef PRE_ERROR_STR
3984 #undef POST_ERROR_STR
3985 
3986 /* Test position information in handler */
3987 typedef struct ByteTestData {
3988   int start_element_len;
3989   int cdata_len;
3990   int total_string_len;
3991 } ByteTestData;
3992 
3993 static void
3994 byte_character_handler(void *userData, const XML_Char *s, int len) {
3995 #ifdef XML_CONTEXT_BYTES
3996   int offset, size;
3997   const char *buffer;
3998   ByteTestData *data = (ByteTestData *)userData;
3999 
4000   UNUSED_P(s);
4001   buffer = XML_GetInputContext(g_parser, &offset, &size);
4002   if (buffer == NULL)
4003     fail("Failed to get context buffer");
4004   if (offset != data->start_element_len)
4005     fail("Context offset in unexpected position");
4006   if (len != data->cdata_len)
4007     fail("CDATA length reported incorrectly");
4008   if (size != data->total_string_len)
4009     fail("Context size is not full buffer");
4010   if (XML_GetCurrentByteIndex(g_parser) != offset)
4011     fail("Character byte index incorrect");
4012   if (XML_GetCurrentByteCount(g_parser) != len)
4013     fail("Character byte count incorrect");
4014 #else
4015   UNUSED_P(s);
4016   UNUSED_P(userData);
4017   UNUSED_P(len);
4018 #endif
4019 }
4020 
4021 #define START_ELEMENT "<e>"
4022 #define CDATA_TEXT "Hello"
4023 #define END_ELEMENT "</e>"
4024 START_TEST(test_byte_info_at_cdata) {
4025   const char *text = START_ELEMENT CDATA_TEXT END_ELEMENT;
4026   int offset, size;
4027   ByteTestData data;
4028 
4029   /* Check initial context is empty */
4030   if (XML_GetInputContext(g_parser, &offset, &size) != NULL)
4031     fail("Unexpected context at start of parse");
4032 
4033   data.start_element_len = (int)strlen(START_ELEMENT);
4034   data.cdata_len = (int)strlen(CDATA_TEXT);
4035   data.total_string_len = (int)strlen(text);
4036   XML_SetCharacterDataHandler(g_parser, byte_character_handler);
4037   XML_SetUserData(g_parser, &data);
4038   if (XML_Parse(g_parser, text, (int)strlen(text), XML_TRUE) != XML_STATUS_OK)
4039     xml_failure(g_parser);
4040 }
4041 END_TEST
4042 #undef START_ELEMENT
4043 #undef CDATA_TEXT
4044 #undef END_ELEMENT
4045 
4046 /* Test predefined entities are correctly recognised */
4047 START_TEST(test_predefined_entities) {
4048   const char *text = "<doc>&lt;&gt;&amp;&quot;&apos;</doc>";
4049   const XML_Char *expected = XCS("<doc>&lt;&gt;&amp;&quot;&apos;</doc>");
4050   const XML_Char *result = XCS("<>&\"'");
4051   CharData storage;
4052 
4053   XML_SetDefaultHandler(g_parser, accumulate_characters);
4054   /* run_character_check uses XML_SetCharacterDataHandler(), which
4055    * unfortunately heads off a code path that we need to exercise.
4056    */
4057   CharData_Init(&storage);
4058   XML_SetUserData(g_parser, &storage);
4059   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
4060       == XML_STATUS_ERROR)
4061     xml_failure(g_parser);
4062   /* The default handler doesn't translate the entities */
4063   CharData_CheckXMLChars(&storage, expected);
4064 
4065   /* Now try again and check the translation */
4066   XML_ParserReset(g_parser, NULL);
4067   run_character_check(text, result);
4068 }
4069 END_TEST
4070 
4071 /* Regression test that an invalid tag in an external parameter
4072  * reference in an external DTD is correctly faulted.
4073  *
4074  * Only a few specific tags are legal in DTDs ignoring comments and
4075  * processing instructions, all of which begin with an exclamation
4076  * mark.  "<el/>" is not one of them, so the parser should raise an
4077  * error on encountering it.
4078  */
4079 static int XMLCALL
4080 external_entity_param(XML_Parser parser, const XML_Char *context,
4081                       const XML_Char *base, const XML_Char *systemId,
4082                       const XML_Char *publicId) {
4083   const char *text1 = "<!ELEMENT doc EMPTY>\n"
4084                       "<!ENTITY % e1 SYSTEM '004-2.ent'>\n"
4085                       "<!ENTITY % e2 '%e1;'>\n"
4086                       "%e1;\n";
4087   const char *text2 = "<!ELEMENT el EMPTY>\n"
4088                       "<el/>\n";
4089   XML_Parser ext_parser;
4090 
4091   UNUSED_P(base);
4092   UNUSED_P(publicId);
4093   if (systemId == NULL)
4094     return XML_STATUS_OK;
4095 
4096   ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
4097   if (ext_parser == NULL)
4098     fail("Could not create external entity parser");
4099 
4100   if (! xcstrcmp(systemId, XCS("004-1.ent"))) {
4101     if (_XML_Parse_SINGLE_BYTES(ext_parser, text1, (int)strlen(text1), XML_TRUE)
4102         != XML_STATUS_ERROR)
4103       fail("Inner DTD with invalid tag not rejected");
4104     if (XML_GetErrorCode(ext_parser) != XML_ERROR_EXTERNAL_ENTITY_HANDLING)
4105       xml_failure(ext_parser);
4106   } else if (! xcstrcmp(systemId, XCS("004-2.ent"))) {
4107     if (_XML_Parse_SINGLE_BYTES(ext_parser, text2, (int)strlen(text2), XML_TRUE)
4108         != XML_STATUS_ERROR)
4109       fail("Invalid tag in external param not rejected");
4110     if (XML_GetErrorCode(ext_parser) != XML_ERROR_SYNTAX)
4111       xml_failure(ext_parser);
4112   } else {
4113     fail("Unknown system ID");
4114   }
4115 
4116   XML_ParserFree(ext_parser);
4117   return XML_STATUS_ERROR;
4118 }
4119 
4120 START_TEST(test_invalid_tag_in_dtd) {
4121   const char *text = "<!DOCTYPE doc SYSTEM '004-1.ent'>\n"
4122                      "<doc></doc>\n";
4123 
4124   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
4125   XML_SetExternalEntityRefHandler(g_parser, external_entity_param);
4126   expect_failure(text, XML_ERROR_EXTERNAL_ENTITY_HANDLING,
4127                  "Invalid tag IN DTD external param not rejected");
4128 }
4129 END_TEST
4130 
4131 /* Test entities not quite the predefined ones are not mis-recognised */
4132 START_TEST(test_not_predefined_entities) {
4133   const char *text[] = {"<doc>&pt;</doc>", "<doc>&amo;</doc>",
4134                         "<doc>&quid;</doc>", "<doc>&apod;</doc>", NULL};
4135   int i = 0;
4136 
4137   while (text[i] != NULL) {
4138     expect_failure(text[i], XML_ERROR_UNDEFINED_ENTITY,
4139                    "Undefined entity not rejected");
4140     XML_ParserReset(g_parser, NULL);
4141     i++;
4142   }
4143 }
4144 END_TEST
4145 
4146 /* Test conditional inclusion (IGNORE) */
4147 static int XMLCALL
4148 external_entity_load_ignore(XML_Parser parser, const XML_Char *context,
4149                             const XML_Char *base, const XML_Char *systemId,
4150                             const XML_Char *publicId) {
4151   const char *text = "<![IGNORE[<!ELEMENT e (#PCDATA)*>]]>";
4152   XML_Parser ext_parser;
4153 
4154   UNUSED_P(base);
4155   UNUSED_P(systemId);
4156   UNUSED_P(publicId);
4157   ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
4158   if (ext_parser == NULL)
4159     fail("Could not create external entity parser");
4160   if (_XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE)
4161       == XML_STATUS_ERROR)
4162     xml_failure(parser);
4163 
4164   XML_ParserFree(ext_parser);
4165   return XML_STATUS_OK;
4166 }
4167 
4168 START_TEST(test_ignore_section) {
4169   const char *text = "<!DOCTYPE doc SYSTEM 'foo'>\n"
4170                      "<doc><e>&entity;</e></doc>";
4171   const XML_Char *expected
4172       = XCS("<![IGNORE[<!ELEMENT e (#PCDATA)*>]]>\n&entity;");
4173   CharData storage;
4174 
4175   CharData_Init(&storage);
4176   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
4177   XML_SetUserData(g_parser, &storage);
4178   XML_SetExternalEntityRefHandler(g_parser, external_entity_load_ignore);
4179   XML_SetDefaultHandler(g_parser, accumulate_characters);
4180   XML_SetStartDoctypeDeclHandler(g_parser, dummy_start_doctype_handler);
4181   XML_SetEndDoctypeDeclHandler(g_parser, dummy_end_doctype_handler);
4182   XML_SetElementDeclHandler(g_parser, dummy_element_decl_handler);
4183   XML_SetStartElementHandler(g_parser, dummy_start_element);
4184   XML_SetEndElementHandler(g_parser, dummy_end_element);
4185   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
4186       == XML_STATUS_ERROR)
4187     xml_failure(g_parser);
4188   CharData_CheckXMLChars(&storage, expected);
4189 }
4190 END_TEST
4191 
4192 static int XMLCALL
4193 external_entity_load_ignore_utf16(XML_Parser parser, const XML_Char *context,
4194                                   const XML_Char *base,
4195                                   const XML_Char *systemId,
4196                                   const XML_Char *publicId) {
4197   const char text[] =
4198       /* <![IGNORE[<!ELEMENT e (#PCDATA)*>]]> */
4199       "<\0!\0[\0I\0G\0N\0O\0R\0E\0[\0"
4200       "<\0!\0E\0L\0E\0M\0E\0N\0T\0 \0e\0 \0"
4201       "(\0#\0P\0C\0D\0A\0T\0A\0)\0*\0>\0]\0]\0>\0";
4202   XML_Parser ext_parser;
4203 
4204   UNUSED_P(base);
4205   UNUSED_P(systemId);
4206   UNUSED_P(publicId);
4207   ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
4208   if (ext_parser == NULL)
4209     fail("Could not create external entity parser");
4210   if (_XML_Parse_SINGLE_BYTES(ext_parser, text, (int)sizeof(text) - 1, XML_TRUE)
4211       == XML_STATUS_ERROR)
4212     xml_failure(parser);
4213 
4214   XML_ParserFree(ext_parser);
4215   return XML_STATUS_OK;
4216 }
4217 
4218 START_TEST(test_ignore_section_utf16) {
4219   const char text[] =
4220       /* <!DOCTYPE d SYSTEM 's'> */
4221       "<\0!\0D\0O\0C\0T\0Y\0P\0E\0 \0d\0 "
4222       "\0S\0Y\0S\0T\0E\0M\0 \0'\0s\0'\0>\0\n\0"
4223       /* <d><e>&en;</e></d> */
4224       "<\0d\0>\0<\0e\0>\0&\0e\0n\0;\0<\0/\0e\0>\0<\0/\0d\0>\0";
4225   const XML_Char *expected = XCS("<![IGNORE[<!ELEMENT e (#PCDATA)*>]]>\n&en;");
4226   CharData storage;
4227 
4228   CharData_Init(&storage);
4229   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
4230   XML_SetUserData(g_parser, &storage);
4231   XML_SetExternalEntityRefHandler(g_parser, external_entity_load_ignore_utf16);
4232   XML_SetDefaultHandler(g_parser, accumulate_characters);
4233   XML_SetStartDoctypeDeclHandler(g_parser, dummy_start_doctype_handler);
4234   XML_SetEndDoctypeDeclHandler(g_parser, dummy_end_doctype_handler);
4235   XML_SetElementDeclHandler(g_parser, dummy_element_decl_handler);
4236   XML_SetStartElementHandler(g_parser, dummy_start_element);
4237   XML_SetEndElementHandler(g_parser, dummy_end_element);
4238   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE)
4239       == XML_STATUS_ERROR)
4240     xml_failure(g_parser);
4241   CharData_CheckXMLChars(&storage, expected);
4242 }
4243 END_TEST
4244 
4245 static int XMLCALL
4246 external_entity_load_ignore_utf16_be(XML_Parser parser, const XML_Char *context,
4247                                      const XML_Char *base,
4248                                      const XML_Char *systemId,
4249                                      const XML_Char *publicId) {
4250   const char text[] =
4251       /* <![IGNORE[<!ELEMENT e (#PCDATA)*>]]> */
4252       "\0<\0!\0[\0I\0G\0N\0O\0R\0E\0["
4253       "\0<\0!\0E\0L\0E\0M\0E\0N\0T\0 \0e\0 "
4254       "\0(\0#\0P\0C\0D\0A\0T\0A\0)\0*\0>\0]\0]\0>";
4255   XML_Parser ext_parser;
4256 
4257   UNUSED_P(base);
4258   UNUSED_P(systemId);
4259   UNUSED_P(publicId);
4260   ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
4261   if (ext_parser == NULL)
4262     fail("Could not create external entity parser");
4263   if (_XML_Parse_SINGLE_BYTES(ext_parser, text, (int)sizeof(text) - 1, XML_TRUE)
4264       == XML_STATUS_ERROR)
4265     xml_failure(parser);
4266 
4267   XML_ParserFree(ext_parser);
4268   return XML_STATUS_OK;
4269 }
4270 
4271 START_TEST(test_ignore_section_utf16_be) {
4272   const char text[] =
4273       /* <!DOCTYPE d SYSTEM 's'> */
4274       "\0<\0!\0D\0O\0C\0T\0Y\0P\0E\0 \0d\0 "
4275       "\0S\0Y\0S\0T\0E\0M\0 \0'\0s\0'\0>\0\n"
4276       /* <d><e>&en;</e></d> */
4277       "\0<\0d\0>\0<\0e\0>\0&\0e\0n\0;\0<\0/\0e\0>\0<\0/\0d\0>";
4278   const XML_Char *expected = XCS("<![IGNORE[<!ELEMENT e (#PCDATA)*>]]>\n&en;");
4279   CharData storage;
4280 
4281   CharData_Init(&storage);
4282   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
4283   XML_SetUserData(g_parser, &storage);
4284   XML_SetExternalEntityRefHandler(g_parser,
4285                                   external_entity_load_ignore_utf16_be);
4286   XML_SetDefaultHandler(g_parser, accumulate_characters);
4287   XML_SetStartDoctypeDeclHandler(g_parser, dummy_start_doctype_handler);
4288   XML_SetEndDoctypeDeclHandler(g_parser, dummy_end_doctype_handler);
4289   XML_SetElementDeclHandler(g_parser, dummy_element_decl_handler);
4290   XML_SetStartElementHandler(g_parser, dummy_start_element);
4291   XML_SetEndElementHandler(g_parser, dummy_end_element);
4292   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE)
4293       == XML_STATUS_ERROR)
4294     xml_failure(g_parser);
4295   CharData_CheckXMLChars(&storage, expected);
4296 }
4297 END_TEST
4298 
4299 /* Test mis-formatted conditional exclusion */
4300 START_TEST(test_bad_ignore_section) {
4301   const char *text = "<!DOCTYPE doc SYSTEM 'foo'>\n"
4302                      "<doc><e>&entity;</e></doc>";
4303   ExtFaults faults[]
4304       = {{"<![IGNORE[<!ELEM", "Broken-off declaration not faulted", NULL,
4305           XML_ERROR_SYNTAX},
4306          {"<![IGNORE[\x01]]>", "Invalid XML character not faulted", NULL,
4307           XML_ERROR_INVALID_TOKEN},
4308          {/* FIrst two bytes of a three-byte char */
4309           "<![IGNORE[\xe2\x82", "Partial XML character not faulted", NULL,
4310           XML_ERROR_PARTIAL_CHAR},
4311          {NULL, NULL, NULL, XML_ERROR_NONE}};
4312   ExtFaults *fault;
4313 
4314   for (fault = &faults[0]; fault->parse_text != NULL; fault++) {
4315     XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
4316     XML_SetExternalEntityRefHandler(g_parser, external_entity_faulter);
4317     XML_SetUserData(g_parser, fault);
4318     expect_failure(text, XML_ERROR_EXTERNAL_ENTITY_HANDLING,
4319                    "Incomplete IGNORE section not failed");
4320     XML_ParserReset(g_parser, NULL);
4321   }
4322 }
4323 END_TEST
4324 
4325 /* Test recursive parsing */
4326 static int XMLCALL
4327 external_entity_valuer(XML_Parser parser, const XML_Char *context,
4328                        const XML_Char *base, const XML_Char *systemId,
4329                        const XML_Char *publicId) {
4330   const char *text1 = "<!ELEMENT doc EMPTY>\n"
4331                       "<!ENTITY % e1 SYSTEM '004-2.ent'>\n"
4332                       "<!ENTITY % e2 '%e1;'>\n"
4333                       "%e1;\n";
4334   XML_Parser ext_parser;
4335 
4336   UNUSED_P(base);
4337   UNUSED_P(publicId);
4338   if (systemId == NULL)
4339     return XML_STATUS_OK;
4340   ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
4341   if (ext_parser == NULL)
4342     fail("Could not create external entity parser");
4343   if (! xcstrcmp(systemId, XCS("004-1.ent"))) {
4344     if (_XML_Parse_SINGLE_BYTES(ext_parser, text1, (int)strlen(text1), XML_TRUE)
4345         == XML_STATUS_ERROR)
4346       xml_failure(ext_parser);
4347   } else if (! xcstrcmp(systemId, XCS("004-2.ent"))) {
4348     ExtFaults *fault = (ExtFaults *)XML_GetUserData(parser);
4349     enum XML_Status status;
4350     enum XML_Error error;
4351 
4352     status = _XML_Parse_SINGLE_BYTES(ext_parser, fault->parse_text,
4353                                      (int)strlen(fault->parse_text), XML_TRUE);
4354     if (fault->error == XML_ERROR_NONE) {
4355       if (status == XML_STATUS_ERROR)
4356         xml_failure(ext_parser);
4357     } else {
4358       if (status != XML_STATUS_ERROR)
4359         fail(fault->fail_text);
4360       error = XML_GetErrorCode(ext_parser);
4361       if (error != fault->error
4362           && (fault->error != XML_ERROR_XML_DECL
4363               || error != XML_ERROR_TEXT_DECL))
4364         xml_failure(ext_parser);
4365     }
4366   }
4367 
4368   XML_ParserFree(ext_parser);
4369   return XML_STATUS_OK;
4370 }
4371 
4372 START_TEST(test_external_entity_values) {
4373   const char *text = "<!DOCTYPE doc SYSTEM '004-1.ent'>\n"
4374                      "<doc></doc>\n";
4375   ExtFaults data_004_2[] = {
4376       {"<!ATTLIST doc a1 CDATA 'value'>", NULL, NULL, XML_ERROR_NONE},
4377       {"<!ATTLIST $doc a1 CDATA 'value'>", "Invalid token not faulted", NULL,
4378        XML_ERROR_INVALID_TOKEN},
4379       {"'wombat", "Unterminated string not faulted", NULL,
4380        XML_ERROR_UNCLOSED_TOKEN},
4381       {"\xe2\x82", "Partial UTF-8 character not faulted", NULL,
4382        XML_ERROR_PARTIAL_CHAR},
4383       {"<?xml version='1.0' encoding='utf-8'?>\n", NULL, NULL, XML_ERROR_NONE},
4384       {"<?xml?>", "Malformed XML declaration not faulted", NULL,
4385        XML_ERROR_XML_DECL},
4386       {/* UTF-8 BOM */
4387        "\xEF\xBB\xBF<!ATTLIST doc a1 CDATA 'value'>", NULL, NULL,
4388        XML_ERROR_NONE},
4389       {"<?xml version='1.0' encoding='utf-8'?>\n$",
4390        "Invalid token after text declaration not faulted", NULL,
4391        XML_ERROR_INVALID_TOKEN},
4392       {"<?xml version='1.0' encoding='utf-8'?>\n'wombat",
4393        "Unterminated string after text decl not faulted", NULL,
4394        XML_ERROR_UNCLOSED_TOKEN},
4395       {"<?xml version='1.0' encoding='utf-8'?>\n\xe2\x82",
4396        "Partial UTF-8 character after text decl not faulted", NULL,
4397        XML_ERROR_PARTIAL_CHAR},
4398       {"%e1;", "Recursive parameter entity not faulted", NULL,
4399        XML_ERROR_RECURSIVE_ENTITY_REF},
4400       {NULL, NULL, NULL, XML_ERROR_NONE}};
4401   int i;
4402 
4403   for (i = 0; data_004_2[i].parse_text != NULL; i++) {
4404     XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
4405     XML_SetExternalEntityRefHandler(g_parser, external_entity_valuer);
4406     XML_SetUserData(g_parser, &data_004_2[i]);
4407     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
4408         == XML_STATUS_ERROR)
4409       xml_failure(g_parser);
4410     XML_ParserReset(g_parser, NULL);
4411   }
4412 }
4413 END_TEST
4414 
4415 /* Test the recursive parse interacts with a not standalone handler */
4416 static int XMLCALL
4417 external_entity_not_standalone(XML_Parser parser, const XML_Char *context,
4418                                const XML_Char *base, const XML_Char *systemId,
4419                                const XML_Char *publicId) {
4420   const char *text1 = "<!ELEMENT doc EMPTY>\n"
4421                       "<!ENTITY % e1 SYSTEM 'bar'>\n"
4422                       "%e1;\n";
4423   const char *text2 = "<!ATTLIST doc a1 CDATA 'value'>";
4424   XML_Parser ext_parser;
4425 
4426   UNUSED_P(base);
4427   UNUSED_P(publicId);
4428   if (systemId == NULL)
4429     return XML_STATUS_OK;
4430   ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
4431   if (ext_parser == NULL)
4432     fail("Could not create external entity parser");
4433   if (! xcstrcmp(systemId, XCS("foo"))) {
4434     XML_SetNotStandaloneHandler(ext_parser, reject_not_standalone_handler);
4435     if (_XML_Parse_SINGLE_BYTES(ext_parser, text1, (int)strlen(text1), XML_TRUE)
4436         != XML_STATUS_ERROR)
4437       fail("Expected not standalone rejection");
4438     if (XML_GetErrorCode(ext_parser) != XML_ERROR_NOT_STANDALONE)
4439       xml_failure(ext_parser);
4440     XML_SetNotStandaloneHandler(ext_parser, NULL);
4441     XML_ParserFree(ext_parser);
4442     return XML_STATUS_ERROR;
4443   } else if (! xcstrcmp(systemId, XCS("bar"))) {
4444     if (_XML_Parse_SINGLE_BYTES(ext_parser, text2, (int)strlen(text2), XML_TRUE)
4445         == XML_STATUS_ERROR)
4446       xml_failure(ext_parser);
4447   }
4448 
4449   XML_ParserFree(ext_parser);
4450   return XML_STATUS_OK;
4451 }
4452 
4453 START_TEST(test_ext_entity_not_standalone) {
4454   const char *text = "<!DOCTYPE doc SYSTEM 'foo'>\n"
4455                      "<doc></doc>";
4456 
4457   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
4458   XML_SetExternalEntityRefHandler(g_parser, external_entity_not_standalone);
4459   expect_failure(text, XML_ERROR_EXTERNAL_ENTITY_HANDLING,
4460                  "Standalone rejection not caught");
4461 }
4462 END_TEST
4463 
4464 static int XMLCALL
4465 external_entity_value_aborter(XML_Parser parser, const XML_Char *context,
4466                               const XML_Char *base, const XML_Char *systemId,
4467                               const XML_Char *publicId) {
4468   const char *text1 = "<!ELEMENT doc EMPTY>\n"
4469                       "<!ENTITY % e1 SYSTEM '004-2.ent'>\n"
4470                       "<!ENTITY % e2 '%e1;'>\n"
4471                       "%e1;\n";
4472   const char *text2 = "<?xml version='1.0' encoding='utf-8'?>";
4473   XML_Parser ext_parser;
4474 
4475   UNUSED_P(base);
4476   UNUSED_P(publicId);
4477   if (systemId == NULL)
4478     return XML_STATUS_OK;
4479   ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
4480   if (ext_parser == NULL)
4481     fail("Could not create external entity parser");
4482   if (! xcstrcmp(systemId, XCS("004-1.ent"))) {
4483     if (_XML_Parse_SINGLE_BYTES(ext_parser, text1, (int)strlen(text1), XML_TRUE)
4484         == XML_STATUS_ERROR)
4485       xml_failure(ext_parser);
4486   }
4487   if (! xcstrcmp(systemId, XCS("004-2.ent"))) {
4488     XML_SetXmlDeclHandler(ext_parser, entity_suspending_xdecl_handler);
4489     XML_SetUserData(ext_parser, ext_parser);
4490     if (_XML_Parse_SINGLE_BYTES(ext_parser, text2, (int)strlen(text2), XML_TRUE)
4491         != XML_STATUS_ERROR)
4492       fail("Aborted parse not faulted");
4493     if (XML_GetErrorCode(ext_parser) != XML_ERROR_ABORTED)
4494       xml_failure(ext_parser);
4495   }
4496 
4497   XML_ParserFree(ext_parser);
4498   return XML_STATUS_OK;
4499 }
4500 
4501 START_TEST(test_ext_entity_value_abort) {
4502   const char *text = "<!DOCTYPE doc SYSTEM '004-1.ent'>\n"
4503                      "<doc></doc>\n";
4504 
4505   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
4506   XML_SetExternalEntityRefHandler(g_parser, external_entity_value_aborter);
4507   resumable = XML_FALSE;
4508   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
4509       == XML_STATUS_ERROR)
4510     xml_failure(g_parser);
4511 }
4512 END_TEST
4513 
4514 START_TEST(test_bad_public_doctype) {
4515   const char *text = "<?xml version='1.0' encoding='utf-8'?>\n"
4516                      "<!DOCTYPE doc PUBLIC '{BadName}' 'test'>\n"
4517                      "<doc></doc>";
4518 
4519   /* Setting a handler provokes a particular code path */
4520   XML_SetDoctypeDeclHandler(g_parser, dummy_start_doctype_handler,
4521                             dummy_end_doctype_handler);
4522   expect_failure(text, XML_ERROR_PUBLICID, "Bad Public ID not failed");
4523 }
4524 END_TEST
4525 
4526 /* Test based on ibm/valid/P32/ibm32v04.xml */
4527 START_TEST(test_attribute_enum_value) {
4528   const char *text = "<?xml version='1.0' standalone='no'?>\n"
4529                      "<!DOCTYPE animal SYSTEM 'test.dtd'>\n"
4530                      "<animal>This is a \n    <a/>  \n\nyellow tiger</animal>";
4531   ExtTest dtd_data
4532       = {"<!ELEMENT animal (#PCDATA|a)*>\n"
4533          "<!ELEMENT a EMPTY>\n"
4534          "<!ATTLIST animal xml:space (default|preserve) 'preserve'>",
4535          NULL, NULL};
4536   const XML_Char *expected = XCS("This is a \n      \n\nyellow tiger");
4537 
4538   XML_SetExternalEntityRefHandler(g_parser, external_entity_loader);
4539   XML_SetUserData(g_parser, &dtd_data);
4540   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
4541   /* An attribute list handler provokes a different code path */
4542   XML_SetAttlistDeclHandler(g_parser, dummy_attlist_decl_handler);
4543   run_ext_character_check(text, &dtd_data, expected);
4544 }
4545 END_TEST
4546 
4547 /* Slightly bizarrely, the library seems to silently ignore entity
4548  * definitions for predefined entities, even when they are wrong.  The
4549  * language of the XML 1.0 spec is somewhat unhelpful as to what ought
4550  * to happen, so this is currently treated as acceptable.
4551  */
4552 START_TEST(test_predefined_entity_redefinition) {
4553   const char *text = "<!DOCTYPE doc [\n"
4554                      "<!ENTITY apos 'foo'>\n"
4555                      "]>\n"
4556                      "<doc>&apos;</doc>";
4557   run_character_check(text, XCS("'"));
4558 }
4559 END_TEST
4560 
4561 /* Test that the parser stops processing the DTD after an unresolved
4562  * parameter entity is encountered.
4563  */
4564 START_TEST(test_dtd_stop_processing) {
4565   const char *text = "<!DOCTYPE doc [\n"
4566                      "%foo;\n"
4567                      "<!ENTITY bar 'bas'>\n"
4568                      "]><doc/>";
4569 
4570   XML_SetEntityDeclHandler(g_parser, dummy_entity_decl_handler);
4571   dummy_handler_flags = 0;
4572   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
4573       == XML_STATUS_ERROR)
4574     xml_failure(g_parser);
4575   if (dummy_handler_flags != 0)
4576     fail("DTD processing still going after undefined PE");
4577 }
4578 END_TEST
4579 
4580 /* Test public notations with no system ID */
4581 START_TEST(test_public_notation_no_sysid) {
4582   const char *text = "<!DOCTYPE doc [\n"
4583                      "<!NOTATION note PUBLIC 'foo'>\n"
4584                      "<!ELEMENT doc EMPTY>\n"
4585                      "]>\n<doc/>";
4586 
4587   dummy_handler_flags = 0;
4588   XML_SetNotationDeclHandler(g_parser, dummy_notation_decl_handler);
4589   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
4590       == XML_STATUS_ERROR)
4591     xml_failure(g_parser);
4592   if (dummy_handler_flags != DUMMY_NOTATION_DECL_HANDLER_FLAG)
4593     fail("Notation declaration handler not called");
4594 }
4595 END_TEST
4596 
4597 static void XMLCALL
4598 record_element_start_handler(void *userData, const XML_Char *name,
4599                              const XML_Char **atts) {
4600   UNUSED_P(atts);
4601   CharData_AppendXMLChars((CharData *)userData, name, (int)xcstrlen(name));
4602 }
4603 
4604 START_TEST(test_nested_groups) {
4605   const char *text
4606       = "<!DOCTYPE doc [\n"
4607         "<!ELEMENT doc "
4608         /* Sixteen elements per line */
4609         "(e,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,"
4610         "(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?"
4611         "))))))))))))))))))))))))))))))))>\n"
4612         "<!ELEMENT e EMPTY>"
4613         "]>\n"
4614         "<doc><e/></doc>";
4615   CharData storage;
4616 
4617   CharData_Init(&storage);
4618   XML_SetElementDeclHandler(g_parser, dummy_element_decl_handler);
4619   XML_SetStartElementHandler(g_parser, record_element_start_handler);
4620   XML_SetUserData(g_parser, &storage);
4621   dummy_handler_flags = 0;
4622   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
4623       == XML_STATUS_ERROR)
4624     xml_failure(g_parser);
4625   CharData_CheckXMLChars(&storage, XCS("doce"));
4626   if (dummy_handler_flags != DUMMY_ELEMENT_DECL_HANDLER_FLAG)
4627     fail("Element handler not fired");
4628 }
4629 END_TEST
4630 
4631 START_TEST(test_group_choice) {
4632   const char *text = "<!DOCTYPE doc [\n"
4633                      "<!ELEMENT doc (a|b|c)+>\n"
4634                      "<!ELEMENT a EMPTY>\n"
4635                      "<!ELEMENT b (#PCDATA)>\n"
4636                      "<!ELEMENT c ANY>\n"
4637                      "]>\n"
4638                      "<doc>\n"
4639                      "<a/>\n"
4640                      "<b attr='foo'>This is a foo</b>\n"
4641                      "<c></c>\n"
4642                      "</doc>\n";
4643 
4644   XML_SetElementDeclHandler(g_parser, dummy_element_decl_handler);
4645   dummy_handler_flags = 0;
4646   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
4647       == XML_STATUS_ERROR)
4648     xml_failure(g_parser);
4649   if (dummy_handler_flags != DUMMY_ELEMENT_DECL_HANDLER_FLAG)
4650     fail("Element handler flag not raised");
4651 }
4652 END_TEST
4653 
4654 static int XMLCALL
4655 external_entity_public(XML_Parser parser, const XML_Char *context,
4656                        const XML_Char *base, const XML_Char *systemId,
4657                        const XML_Char *publicId) {
4658   const char *text1 = (const char *)XML_GetUserData(parser);
4659   const char *text2 = "<!ATTLIST doc a CDATA 'value'>";
4660   const char *text = NULL;
4661   XML_Parser ext_parser;
4662   int parse_res;
4663 
4664   UNUSED_P(base);
4665   ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
4666   if (ext_parser == NULL)
4667     return XML_STATUS_ERROR;
4668   if (systemId != NULL && ! xcstrcmp(systemId, XCS("http://example.org/"))) {
4669     text = text1;
4670   } else if (publicId != NULL && ! xcstrcmp(publicId, XCS("foo"))) {
4671     text = text2;
4672   } else
4673     fail("Unexpected parameters to external entity parser");
4674   assert(text != NULL);
4675   parse_res
4676       = _XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE);
4677   XML_ParserFree(ext_parser);
4678   return parse_res;
4679 }
4680 
4681 START_TEST(test_standalone_parameter_entity) {
4682   const char *text = "<?xml version='1.0' standalone='yes'?>\n"
4683                      "<!DOCTYPE doc SYSTEM 'http://example.org/' [\n"
4684                      "<!ENTITY % entity '<!ELEMENT doc (#PCDATA)>'>\n"
4685                      "%entity;\n"
4686                      "]>\n"
4687                      "<doc></doc>";
4688   char dtd_data[] = "<!ENTITY % e1 'foo'>\n";
4689 
4690   XML_SetUserData(g_parser, dtd_data);
4691   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
4692   XML_SetExternalEntityRefHandler(g_parser, external_entity_public);
4693   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
4694       == XML_STATUS_ERROR)
4695     xml_failure(g_parser);
4696 }
4697 END_TEST
4698 
4699 /* Test skipping of parameter entity in an external DTD */
4700 /* Derived from ibm/invalid/P69/ibm69i01.xml */
4701 START_TEST(test_skipped_parameter_entity) {
4702   const char *text = "<?xml version='1.0'?>\n"
4703                      "<!DOCTYPE root SYSTEM 'http://example.org/dtd.ent' [\n"
4704                      "<!ELEMENT root (#PCDATA|a)* >\n"
4705                      "]>\n"
4706                      "<root></root>";
4707   ExtTest dtd_data = {"%pe2;", NULL, NULL};
4708 
4709   XML_SetExternalEntityRefHandler(g_parser, external_entity_loader);
4710   XML_SetUserData(g_parser, &dtd_data);
4711   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
4712   XML_SetSkippedEntityHandler(g_parser, dummy_skip_handler);
4713   dummy_handler_flags = 0;
4714   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
4715       == XML_STATUS_ERROR)
4716     xml_failure(g_parser);
4717   if (dummy_handler_flags != DUMMY_SKIP_HANDLER_FLAG)
4718     fail("Skip handler not executed");
4719 }
4720 END_TEST
4721 
4722 /* Test recursive parameter entity definition rejected in external DTD */
4723 START_TEST(test_recursive_external_parameter_entity) {
4724   const char *text = "<?xml version='1.0'?>\n"
4725                      "<!DOCTYPE root SYSTEM 'http://example.org/dtd.ent' [\n"
4726                      "<!ELEMENT root (#PCDATA|a)* >\n"
4727                      "]>\n"
4728                      "<root></root>";
4729   ExtFaults dtd_data = {"<!ENTITY % pe2 '&#37;pe2;'>\n%pe2;",
4730                         "Recursive external parameter entity not faulted", NULL,
4731                         XML_ERROR_RECURSIVE_ENTITY_REF};
4732 
4733   XML_SetExternalEntityRefHandler(g_parser, external_entity_faulter);
4734   XML_SetUserData(g_parser, &dtd_data);
4735   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
4736   expect_failure(text, XML_ERROR_EXTERNAL_ENTITY_HANDLING,
4737                  "Recursive external parameter not spotted");
4738 }
4739 END_TEST
4740 
4741 /* Test undefined parameter entity in external entity handler */
4742 static int XMLCALL
4743 external_entity_devaluer(XML_Parser parser, const XML_Char *context,
4744                          const XML_Char *base, const XML_Char *systemId,
4745                          const XML_Char *publicId) {
4746   const char *text = "<!ELEMENT doc EMPTY>\n"
4747                      "<!ENTITY % e1 SYSTEM 'bar'>\n"
4748                      "%e1;\n";
4749   XML_Parser ext_parser;
4750   intptr_t clear_handler = (intptr_t)XML_GetUserData(parser);
4751 
4752   UNUSED_P(base);
4753   UNUSED_P(publicId);
4754   if (systemId == NULL || ! xcstrcmp(systemId, XCS("bar")))
4755     return XML_STATUS_OK;
4756   if (xcstrcmp(systemId, XCS("foo")))
4757     fail("Unexpected system ID");
4758   ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
4759   if (ext_parser == NULL)
4760     fail("Could note create external entity parser");
4761   if (clear_handler)
4762     XML_SetExternalEntityRefHandler(ext_parser, NULL);
4763   if (_XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE)
4764       == XML_STATUS_ERROR)
4765     xml_failure(ext_parser);
4766 
4767   XML_ParserFree(ext_parser);
4768   return XML_STATUS_OK;
4769 }
4770 
4771 START_TEST(test_undefined_ext_entity_in_external_dtd) {
4772   const char *text = "<!DOCTYPE doc SYSTEM 'foo'>\n"
4773                      "<doc></doc>\n";
4774 
4775   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
4776   XML_SetExternalEntityRefHandler(g_parser, external_entity_devaluer);
4777   XML_SetUserData(g_parser, (void *)(intptr_t)XML_FALSE);
4778   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
4779       == XML_STATUS_ERROR)
4780     xml_failure(g_parser);
4781 
4782   /* Now repeat without the external entity ref handler invoking
4783    * another copy of itself.
4784    */
4785   XML_ParserReset(g_parser, NULL);
4786   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
4787   XML_SetExternalEntityRefHandler(g_parser, external_entity_devaluer);
4788   XML_SetUserData(g_parser, (void *)(intptr_t)XML_TRUE);
4789   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
4790       == XML_STATUS_ERROR)
4791     xml_failure(g_parser);
4792 }
4793 END_TEST
4794 
4795 static void XMLCALL
4796 aborting_xdecl_handler(void *userData, const XML_Char *version,
4797                        const XML_Char *encoding, int standalone) {
4798   UNUSED_P(userData);
4799   UNUSED_P(version);
4800   UNUSED_P(encoding);
4801   UNUSED_P(standalone);
4802   XML_StopParser(g_parser, resumable);
4803   XML_SetXmlDeclHandler(g_parser, NULL);
4804 }
4805 
4806 /* Test suspending the parse on receiving an XML declaration works */
4807 START_TEST(test_suspend_xdecl) {
4808   const char *text = long_character_data_text;
4809 
4810   XML_SetXmlDeclHandler(g_parser, aborting_xdecl_handler);
4811   resumable = XML_TRUE;
4812   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
4813       != XML_STATUS_SUSPENDED)
4814     xml_failure(g_parser);
4815   if (XML_GetErrorCode(g_parser) != XML_ERROR_NONE)
4816     xml_failure(g_parser);
4817   /* Attempt to start a new parse while suspended */
4818   if (XML_Parse(g_parser, text, (int)strlen(text), XML_TRUE)
4819       != XML_STATUS_ERROR)
4820     fail("Attempt to parse while suspended not faulted");
4821   if (XML_GetErrorCode(g_parser) != XML_ERROR_SUSPENDED)
4822     fail("Suspended parse not faulted with correct error");
4823 }
4824 END_TEST
4825 
4826 /* Test aborting the parse in an epilog works */
4827 static void XMLCALL
4828 selective_aborting_default_handler(void *userData, const XML_Char *s, int len) {
4829   const XML_Char *match = (const XML_Char *)userData;
4830 
4831   if (match == NULL
4832       || (xcstrlen(match) == (unsigned)len && ! xcstrncmp(match, s, len))) {
4833     XML_StopParser(g_parser, resumable);
4834     XML_SetDefaultHandler(g_parser, NULL);
4835   }
4836 }
4837 
4838 START_TEST(test_abort_epilog) {
4839   const char *text = "<doc></doc>\n\r\n";
4840   XML_Char match[] = XCS("\r");
4841 
4842   XML_SetDefaultHandler(g_parser, selective_aborting_default_handler);
4843   XML_SetUserData(g_parser, match);
4844   resumable = XML_FALSE;
4845   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
4846       != XML_STATUS_ERROR)
4847     fail("Abort not triggered");
4848   if (XML_GetErrorCode(g_parser) != XML_ERROR_ABORTED)
4849     xml_failure(g_parser);
4850 }
4851 END_TEST
4852 
4853 /* Test a different code path for abort in the epilog */
4854 START_TEST(test_abort_epilog_2) {
4855   const char *text = "<doc></doc>\n";
4856   XML_Char match[] = XCS("\n");
4857 
4858   XML_SetDefaultHandler(g_parser, selective_aborting_default_handler);
4859   XML_SetUserData(g_parser, match);
4860   resumable = XML_FALSE;
4861   expect_failure(text, XML_ERROR_ABORTED, "Abort not triggered");
4862 }
4863 END_TEST
4864 
4865 /* Test suspension from the epilog */
4866 START_TEST(test_suspend_epilog) {
4867   const char *text = "<doc></doc>\n";
4868   XML_Char match[] = XCS("\n");
4869 
4870   XML_SetDefaultHandler(g_parser, selective_aborting_default_handler);
4871   XML_SetUserData(g_parser, match);
4872   resumable = XML_TRUE;
4873   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
4874       != XML_STATUS_SUSPENDED)
4875     xml_failure(g_parser);
4876 }
4877 END_TEST
4878 
4879 static void XMLCALL
4880 suspending_end_handler(void *userData, const XML_Char *s) {
4881   UNUSED_P(s);
4882   XML_StopParser((XML_Parser)userData, 1);
4883 }
4884 
4885 START_TEST(test_suspend_in_sole_empty_tag) {
4886   const char *text = "<doc/>";
4887   enum XML_Status rc;
4888 
4889   XML_SetEndElementHandler(g_parser, suspending_end_handler);
4890   XML_SetUserData(g_parser, g_parser);
4891   rc = _XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE);
4892   if (rc == XML_STATUS_ERROR)
4893     xml_failure(g_parser);
4894   else if (rc != XML_STATUS_SUSPENDED)
4895     fail("Suspend not triggered");
4896   rc = XML_ResumeParser(g_parser);
4897   if (rc == XML_STATUS_ERROR)
4898     xml_failure(g_parser);
4899   else if (rc != XML_STATUS_OK)
4900     fail("Resume failed");
4901 }
4902 END_TEST
4903 
4904 START_TEST(test_unfinished_epilog) {
4905   const char *text = "<doc></doc><";
4906 
4907   expect_failure(text, XML_ERROR_UNCLOSED_TOKEN,
4908                  "Incomplete epilog entry not faulted");
4909 }
4910 END_TEST
4911 
4912 START_TEST(test_partial_char_in_epilog) {
4913   const char *text = "<doc></doc>\xe2\x82";
4914 
4915   /* First check that no fault is raised if the parse is not finished */
4916   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_FALSE)
4917       == XML_STATUS_ERROR)
4918     xml_failure(g_parser);
4919   /* Now check that it is faulted once we finish */
4920   if (XML_ParseBuffer(g_parser, 0, XML_TRUE) != XML_STATUS_ERROR)
4921     fail("Partial character in epilog not faulted");
4922   if (XML_GetErrorCode(g_parser) != XML_ERROR_PARTIAL_CHAR)
4923     xml_failure(g_parser);
4924 }
4925 END_TEST
4926 
4927 START_TEST(test_hash_collision) {
4928   /* For full coverage of the lookup routine, we need to ensure a
4929    * hash collision even though we can only tell that we have one
4930    * through breakpoint debugging or coverage statistics.  The
4931    * following will cause a hash collision on machines with a 64-bit
4932    * long type; others will have to experiment.  The full coverage
4933    * tests invoked from qa.sh usually provide a hash collision, but
4934    * not always.  This is an attempt to provide insurance.
4935    */
4936 #define COLLIDING_HASH_SALT (unsigned long)_SIP_ULL(0xffffffffU, 0xff99fc90U)
4937   const char *text
4938       = "<doc>\n"
4939         "<a1/><a2/><a3/><a4/><a5/><a6/><a7/><a8/>\n"
4940         "<b1></b1><b2 attr='foo'>This is a foo</b2><b3></b3><b4></b4>\n"
4941         "<b5></b5><b6></b6><b7></b7><b8></b8>\n"
4942         "<c1/><c2/><c3/><c4/><c5/><c6/><c7/><c8/>\n"
4943         "<d1/><d2/><d3/><d4/><d5/><d6/><d7/>\n"
4944         "<d8>This triggers the table growth and collides with b2</d8>\n"
4945         "</doc>\n";
4946 
4947   XML_SetHashSalt(g_parser, COLLIDING_HASH_SALT);
4948   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
4949       == XML_STATUS_ERROR)
4950     xml_failure(g_parser);
4951 }
4952 END_TEST
4953 #undef COLLIDING_HASH_SALT
4954 
4955 /* Test resuming a parse suspended in entity substitution */
4956 static void XMLCALL
4957 start_element_suspender(void *userData, const XML_Char *name,
4958                         const XML_Char **atts) {
4959   UNUSED_P(userData);
4960   UNUSED_P(atts);
4961   if (! xcstrcmp(name, XCS("suspend")))
4962     XML_StopParser(g_parser, XML_TRUE);
4963   if (! xcstrcmp(name, XCS("abort")))
4964     XML_StopParser(g_parser, XML_FALSE);
4965 }
4966 
4967 START_TEST(test_suspend_resume_internal_entity) {
4968   const char *text
4969       = "<!DOCTYPE doc [\n"
4970         "<!ENTITY foo '<suspend>Hi<suspend>Ho</suspend></suspend>'>\n"
4971         "]>\n"
4972         "<doc>&foo;</doc>\n";
4973   const XML_Char *expected1 = XCS("Hi");
4974   const XML_Char *expected2 = XCS("HiHo");
4975   CharData storage;
4976 
4977   CharData_Init(&storage);
4978   XML_SetStartElementHandler(g_parser, start_element_suspender);
4979   XML_SetCharacterDataHandler(g_parser, accumulate_characters);
4980   XML_SetUserData(g_parser, &storage);
4981   if (XML_Parse(g_parser, text, (int)strlen(text), XML_TRUE)
4982       != XML_STATUS_SUSPENDED)
4983     xml_failure(g_parser);
4984   CharData_CheckXMLChars(&storage, XCS(""));
4985   if (XML_ResumeParser(g_parser) != XML_STATUS_SUSPENDED)
4986     xml_failure(g_parser);
4987   CharData_CheckXMLChars(&storage, expected1);
4988   if (XML_ResumeParser(g_parser) != XML_STATUS_OK)
4989     xml_failure(g_parser);
4990   CharData_CheckXMLChars(&storage, expected2);
4991 }
4992 END_TEST
4993 
4994 /* Test syntax error is caught at parse resumption */
4995 START_TEST(test_resume_entity_with_syntax_error) {
4996   const char *text = "<!DOCTYPE doc [\n"
4997                      "<!ENTITY foo '<suspend>Hi</wombat>'>\n"
4998                      "]>\n"
4999                      "<doc>&foo;</doc>\n";
5000 
5001   XML_SetStartElementHandler(g_parser, start_element_suspender);
5002   if (XML_Parse(g_parser, text, (int)strlen(text), XML_TRUE)
5003       != XML_STATUS_SUSPENDED)
5004     xml_failure(g_parser);
5005   if (XML_ResumeParser(g_parser) != XML_STATUS_ERROR)
5006     fail("Syntax error in entity not faulted");
5007   if (XML_GetErrorCode(g_parser) != XML_ERROR_TAG_MISMATCH)
5008     xml_failure(g_parser);
5009 }
5010 END_TEST
5011 
5012 /* Test suspending and resuming in a parameter entity substitution */
5013 static void XMLCALL
5014 element_decl_suspender(void *userData, const XML_Char *name,
5015                        XML_Content *model) {
5016   UNUSED_P(userData);
5017   UNUSED_P(name);
5018   XML_StopParser(g_parser, XML_TRUE);
5019   XML_FreeContentModel(g_parser, model);
5020 }
5021 
5022 START_TEST(test_suspend_resume_parameter_entity) {
5023   const char *text = "<!DOCTYPE doc [\n"
5024                      "<!ENTITY % foo '<!ELEMENT doc (#PCDATA)*>'>\n"
5025                      "%foo;\n"
5026                      "]>\n"
5027                      "<doc>Hello, world</doc>";
5028   const XML_Char *expected = XCS("Hello, world");
5029   CharData storage;
5030 
5031   CharData_Init(&storage);
5032   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
5033   XML_SetElementDeclHandler(g_parser, element_decl_suspender);
5034   XML_SetCharacterDataHandler(g_parser, accumulate_characters);
5035   XML_SetUserData(g_parser, &storage);
5036   if (XML_Parse(g_parser, text, (int)strlen(text), XML_TRUE)
5037       != XML_STATUS_SUSPENDED)
5038     xml_failure(g_parser);
5039   CharData_CheckXMLChars(&storage, XCS(""));
5040   if (XML_ResumeParser(g_parser) != XML_STATUS_OK)
5041     xml_failure(g_parser);
5042   CharData_CheckXMLChars(&storage, expected);
5043 }
5044 END_TEST
5045 
5046 /* Test attempting to use parser after an error is faulted */
5047 START_TEST(test_restart_on_error) {
5048   const char *text = "<$doc><doc></doc>";
5049 
5050   if (XML_Parse(g_parser, text, (int)strlen(text), XML_TRUE)
5051       != XML_STATUS_ERROR)
5052     fail("Invalid tag name not faulted");
5053   if (XML_GetErrorCode(g_parser) != XML_ERROR_INVALID_TOKEN)
5054     xml_failure(g_parser);
5055   if (XML_Parse(g_parser, NULL, 0, XML_TRUE) != XML_STATUS_ERROR)
5056     fail("Restarting invalid parse not faulted");
5057   if (XML_GetErrorCode(g_parser) != XML_ERROR_INVALID_TOKEN)
5058     xml_failure(g_parser);
5059 }
5060 END_TEST
5061 
5062 /* Test that angle brackets in an attribute default value are faulted */
5063 START_TEST(test_reject_lt_in_attribute_value) {
5064   const char *text = "<!DOCTYPE doc [<!ATTLIST doc a CDATA '<bar>'>]>\n"
5065                      "<doc></doc>";
5066 
5067   expect_failure(text, XML_ERROR_INVALID_TOKEN,
5068                  "Bad attribute default not faulted");
5069 }
5070 END_TEST
5071 
5072 START_TEST(test_reject_unfinished_param_in_att_value) {
5073   const char *text = "<!DOCTYPE doc [<!ATTLIST doc a CDATA '&foo'>]>\n"
5074                      "<doc></doc>";
5075 
5076   expect_failure(text, XML_ERROR_INVALID_TOKEN,
5077                  "Bad attribute default not faulted");
5078 }
5079 END_TEST
5080 
5081 START_TEST(test_trailing_cr_in_att_value) {
5082   const char *text = "<doc a='value\r'/>";
5083 
5084   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
5085       == XML_STATUS_ERROR)
5086     xml_failure(g_parser);
5087 }
5088 END_TEST
5089 
5090 /* Try parsing a general entity within a parameter entity in a
5091  * standalone internal DTD.  Covers a corner case in the parser.
5092  */
5093 START_TEST(test_standalone_internal_entity) {
5094   const char *text = "<?xml version='1.0' standalone='yes' ?>\n"
5095                      "<!DOCTYPE doc [\n"
5096                      "  <!ELEMENT doc (#PCDATA)>\n"
5097                      "  <!ENTITY % pe '<!ATTLIST doc att2 CDATA \"&ge;\">'>\n"
5098                      "  <!ENTITY ge 'AttDefaultValue'>\n"
5099                      "  %pe;\n"
5100                      "]>\n"
5101                      "<doc att2='any'/>";
5102 
5103   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
5104   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
5105       == XML_STATUS_ERROR)
5106     xml_failure(g_parser);
5107 }
5108 END_TEST
5109 
5110 /* Test that a reference to an unknown external entity is skipped */
5111 START_TEST(test_skipped_external_entity) {
5112   const char *text = "<!DOCTYPE doc SYSTEM 'http://example.org/'>\n"
5113                      "<doc></doc>\n";
5114   ExtTest test_data = {"<!ELEMENT doc EMPTY>\n"
5115                        "<!ENTITY % e2 '%e1;'>\n",
5116                        NULL, NULL};
5117 
5118   XML_SetUserData(g_parser, &test_data);
5119   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
5120   XML_SetExternalEntityRefHandler(g_parser, external_entity_loader);
5121   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
5122       == XML_STATUS_ERROR)
5123     xml_failure(g_parser);
5124 }
5125 END_TEST
5126 
5127 /* Test a different form of unknown external entity */
5128 typedef struct ext_hdlr_data {
5129   const char *parse_text;
5130   XML_ExternalEntityRefHandler handler;
5131 } ExtHdlrData;
5132 
5133 static int XMLCALL
5134 external_entity_oneshot_loader(XML_Parser parser, const XML_Char *context,
5135                                const XML_Char *base, const XML_Char *systemId,
5136                                const XML_Char *publicId) {
5137   ExtHdlrData *test_data = (ExtHdlrData *)XML_GetUserData(parser);
5138   XML_Parser ext_parser;
5139 
5140   UNUSED_P(base);
5141   UNUSED_P(systemId);
5142   UNUSED_P(publicId);
5143   ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
5144   if (ext_parser == NULL)
5145     fail("Could not create external entity parser.");
5146   /* Use the requested entity parser for further externals */
5147   XML_SetExternalEntityRefHandler(ext_parser, test_data->handler);
5148   if (_XML_Parse_SINGLE_BYTES(ext_parser, test_data->parse_text,
5149                               (int)strlen(test_data->parse_text), XML_TRUE)
5150       == XML_STATUS_ERROR) {
5151     xml_failure(ext_parser);
5152   }
5153 
5154   XML_ParserFree(ext_parser);
5155   return XML_STATUS_OK;
5156 }
5157 
5158 START_TEST(test_skipped_null_loaded_ext_entity) {
5159   const char *text = "<!DOCTYPE doc SYSTEM 'http://example.org/one.ent'>\n"
5160                      "<doc />";
5161   ExtHdlrData test_data
5162       = {"<!ENTITY % pe1 SYSTEM 'http://example.org/two.ent'>\n"
5163          "<!ENTITY % pe2 '%pe1;'>\n"
5164          "%pe2;\n",
5165          external_entity_null_loader};
5166 
5167   XML_SetUserData(g_parser, &test_data);
5168   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
5169   XML_SetExternalEntityRefHandler(g_parser, external_entity_oneshot_loader);
5170   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
5171       == XML_STATUS_ERROR)
5172     xml_failure(g_parser);
5173 }
5174 END_TEST
5175 
5176 START_TEST(test_skipped_unloaded_ext_entity) {
5177   const char *text = "<!DOCTYPE doc SYSTEM 'http://example.org/one.ent'>\n"
5178                      "<doc />";
5179   ExtHdlrData test_data
5180       = {"<!ENTITY % pe1 SYSTEM 'http://example.org/two.ent'>\n"
5181          "<!ENTITY % pe2 '%pe1;'>\n"
5182          "%pe2;\n",
5183          NULL};
5184 
5185   XML_SetUserData(g_parser, &test_data);
5186   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
5187   XML_SetExternalEntityRefHandler(g_parser, external_entity_oneshot_loader);
5188   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
5189       == XML_STATUS_ERROR)
5190     xml_failure(g_parser);
5191 }
5192 END_TEST
5193 
5194 /* Test that a parameter entity value ending with a carriage return
5195  * has it translated internally into a newline.
5196  */
5197 START_TEST(test_param_entity_with_trailing_cr) {
5198 #define PARAM_ENTITY_NAME "pe"
5199 #define PARAM_ENTITY_CORE_VALUE "<!ATTLIST doc att CDATA \"default\">"
5200   const char *text = "<!DOCTYPE doc SYSTEM 'http://example.org/'>\n"
5201                      "<doc/>";
5202   ExtTest test_data
5203       = {"<!ENTITY % " PARAM_ENTITY_NAME " '" PARAM_ENTITY_CORE_VALUE "\r'>\n"
5204          "%" PARAM_ENTITY_NAME ";\n",
5205          NULL, NULL};
5206 
5207   XML_SetUserData(g_parser, &test_data);
5208   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
5209   XML_SetExternalEntityRefHandler(g_parser, external_entity_loader);
5210   XML_SetEntityDeclHandler(g_parser, param_entity_match_handler);
5211   entity_name_to_match = XCS(PARAM_ENTITY_NAME);
5212   entity_value_to_match = XCS(PARAM_ENTITY_CORE_VALUE) XCS("\n");
5213   entity_match_flag = ENTITY_MATCH_NOT_FOUND;
5214   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
5215       == XML_STATUS_ERROR)
5216     xml_failure(g_parser);
5217   if (entity_match_flag == ENTITY_MATCH_FAIL)
5218     fail("Parameter entity CR->NEWLINE conversion failed");
5219   else if (entity_match_flag == ENTITY_MATCH_NOT_FOUND)
5220     fail("Parameter entity not parsed");
5221 }
5222 #undef PARAM_ENTITY_NAME
5223 #undef PARAM_ENTITY_CORE_VALUE
5224 END_TEST
5225 
5226 START_TEST(test_invalid_character_entity) {
5227   const char *text = "<!DOCTYPE doc [\n"
5228                      "  <!ENTITY entity '&#x110000;'>\n"
5229                      "]>\n"
5230                      "<doc>&entity;</doc>";
5231 
5232   expect_failure(text, XML_ERROR_BAD_CHAR_REF,
5233                  "Out of range character reference not faulted");
5234 }
5235 END_TEST
5236 
5237 START_TEST(test_invalid_character_entity_2) {
5238   const char *text = "<!DOCTYPE doc [\n"
5239                      "  <!ENTITY entity '&#xg0;'>\n"
5240                      "]>\n"
5241                      "<doc>&entity;</doc>";
5242 
5243   expect_failure(text, XML_ERROR_INVALID_TOKEN,
5244                  "Out of range character reference not faulted");
5245 }
5246 END_TEST
5247 
5248 START_TEST(test_invalid_character_entity_3) {
5249   const char text[] =
5250       /* <!DOCTYPE doc [\n */
5251       "\0<\0!\0D\0O\0C\0T\0Y\0P\0E\0 \0d\0o\0c\0 \0[\0\n"
5252       /* U+0E04 = KHO KHWAI
5253        * U+0E08 = CHO CHAN */
5254       /* <!ENTITY entity '&\u0e04\u0e08;'>\n */
5255       "\0<\0!\0E\0N\0T\0I\0T\0Y\0 \0e\0n\0t\0i\0t\0y\0 "
5256       "\0'\0&\x0e\x04\x0e\x08\0;\0'\0>\0\n"
5257       /* ]>\n */
5258       "\0]\0>\0\n"
5259       /* <doc>&entity;</doc> */
5260       "\0<\0d\0o\0c\0>\0&\0e\0n\0t\0i\0t\0y\0;\0<\0/\0d\0o\0c\0>";
5261 
5262   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE)
5263       != XML_STATUS_ERROR)
5264     fail("Invalid start of entity name not faulted");
5265   if (XML_GetErrorCode(g_parser) != XML_ERROR_UNDEFINED_ENTITY)
5266     xml_failure(g_parser);
5267 }
5268 END_TEST
5269 
5270 START_TEST(test_invalid_character_entity_4) {
5271   const char *text = "<!DOCTYPE doc [\n"
5272                      "  <!ENTITY entity '&#1114112;'>\n" /* = &#x110000 */
5273                      "]>\n"
5274                      "<doc>&entity;</doc>";
5275 
5276   expect_failure(text, XML_ERROR_BAD_CHAR_REF,
5277                  "Out of range character reference not faulted");
5278 }
5279 END_TEST
5280 
5281 /* Test that processing instructions are picked up by a default handler */
5282 START_TEST(test_pi_handled_in_default) {
5283   const char *text = "<?test processing instruction?>\n<doc/>";
5284   const XML_Char *expected = XCS("<?test processing instruction?>\n<doc/>");
5285   CharData storage;
5286 
5287   CharData_Init(&storage);
5288   XML_SetDefaultHandler(g_parser, accumulate_characters);
5289   XML_SetUserData(g_parser, &storage);
5290   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
5291       == XML_STATUS_ERROR)
5292     xml_failure(g_parser);
5293   CharData_CheckXMLChars(&storage, expected);
5294 }
5295 END_TEST
5296 
5297 /* Test that comments are picked up by a default handler */
5298 START_TEST(test_comment_handled_in_default) {
5299   const char *text = "<!-- This is a comment -->\n<doc/>";
5300   const XML_Char *expected = XCS("<!-- This is a comment -->\n<doc/>");
5301   CharData storage;
5302 
5303   CharData_Init(&storage);
5304   XML_SetDefaultHandler(g_parser, accumulate_characters);
5305   XML_SetUserData(g_parser, &storage);
5306   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
5307       == XML_STATUS_ERROR)
5308     xml_failure(g_parser);
5309   CharData_CheckXMLChars(&storage, expected);
5310 }
5311 END_TEST
5312 
5313 /* Test PIs that look almost but not quite like XML declarations */
5314 static void XMLCALL
5315 accumulate_pi_characters(void *userData, const XML_Char *target,
5316                          const XML_Char *data) {
5317   CharData *storage = (CharData *)userData;
5318 
5319   CharData_AppendXMLChars(storage, target, -1);
5320   CharData_AppendXMLChars(storage, XCS(": "), 2);
5321   CharData_AppendXMLChars(storage, data, -1);
5322   CharData_AppendXMLChars(storage, XCS("\n"), 1);
5323 }
5324 
5325 START_TEST(test_pi_yml) {
5326   const char *text = "<?yml something like data?><doc/>";
5327   const XML_Char *expected = XCS("yml: something like data\n");
5328   CharData storage;
5329 
5330   CharData_Init(&storage);
5331   XML_SetProcessingInstructionHandler(g_parser, accumulate_pi_characters);
5332   XML_SetUserData(g_parser, &storage);
5333   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
5334       == XML_STATUS_ERROR)
5335     xml_failure(g_parser);
5336   CharData_CheckXMLChars(&storage, expected);
5337 }
5338 END_TEST
5339 
5340 START_TEST(test_pi_xnl) {
5341   const char *text = "<?xnl nothing like data?><doc/>";
5342   const XML_Char *expected = XCS("xnl: nothing like data\n");
5343   CharData storage;
5344 
5345   CharData_Init(&storage);
5346   XML_SetProcessingInstructionHandler(g_parser, accumulate_pi_characters);
5347   XML_SetUserData(g_parser, &storage);
5348   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
5349       == XML_STATUS_ERROR)
5350     xml_failure(g_parser);
5351   CharData_CheckXMLChars(&storage, expected);
5352 }
5353 END_TEST
5354 
5355 START_TEST(test_pi_xmm) {
5356   const char *text = "<?xmm everything like data?><doc/>";
5357   const XML_Char *expected = XCS("xmm: everything like data\n");
5358   CharData storage;
5359 
5360   CharData_Init(&storage);
5361   XML_SetProcessingInstructionHandler(g_parser, accumulate_pi_characters);
5362   XML_SetUserData(g_parser, &storage);
5363   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
5364       == XML_STATUS_ERROR)
5365     xml_failure(g_parser);
5366   CharData_CheckXMLChars(&storage, expected);
5367 }
5368 END_TEST
5369 
5370 START_TEST(test_utf16_pi) {
5371   const char text[] =
5372       /* <?{KHO KHWAI}{CHO CHAN}?>
5373        * where {KHO KHWAI} = U+0E04
5374        * and   {CHO CHAN}  = U+0E08
5375        */
5376       "<\0?\0\x04\x0e\x08\x0e?\0>\0"
5377       /* <q/> */
5378       "<\0q\0/\0>\0";
5379 #ifdef XML_UNICODE
5380   const XML_Char *expected = XCS("\x0e04\x0e08: \n");
5381 #else
5382   const XML_Char *expected = XCS("\xe0\xb8\x84\xe0\xb8\x88: \n");
5383 #endif
5384   CharData storage;
5385 
5386   CharData_Init(&storage);
5387   XML_SetProcessingInstructionHandler(g_parser, accumulate_pi_characters);
5388   XML_SetUserData(g_parser, &storage);
5389   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE)
5390       == XML_STATUS_ERROR)
5391     xml_failure(g_parser);
5392   CharData_CheckXMLChars(&storage, expected);
5393 }
5394 END_TEST
5395 
5396 START_TEST(test_utf16_be_pi) {
5397   const char text[] =
5398       /* <?{KHO KHWAI}{CHO CHAN}?>
5399        * where {KHO KHWAI} = U+0E04
5400        * and   {CHO CHAN}  = U+0E08
5401        */
5402       "\0<\0?\x0e\x04\x0e\x08\0?\0>"
5403       /* <q/> */
5404       "\0<\0q\0/\0>";
5405 #ifdef XML_UNICODE
5406   const XML_Char *expected = XCS("\x0e04\x0e08: \n");
5407 #else
5408   const XML_Char *expected = XCS("\xe0\xb8\x84\xe0\xb8\x88: \n");
5409 #endif
5410   CharData storage;
5411 
5412   CharData_Init(&storage);
5413   XML_SetProcessingInstructionHandler(g_parser, accumulate_pi_characters);
5414   XML_SetUserData(g_parser, &storage);
5415   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE)
5416       == XML_STATUS_ERROR)
5417     xml_failure(g_parser);
5418   CharData_CheckXMLChars(&storage, expected);
5419 }
5420 END_TEST
5421 
5422 /* Test that comments can be picked up and translated */
5423 static void XMLCALL
5424 accumulate_comment(void *userData, const XML_Char *data) {
5425   CharData *storage = (CharData *)userData;
5426 
5427   CharData_AppendXMLChars(storage, data, -1);
5428 }
5429 
5430 START_TEST(test_utf16_be_comment) {
5431   const char text[] =
5432       /* <!-- Comment A --> */
5433       "\0<\0!\0-\0-\0 \0C\0o\0m\0m\0e\0n\0t\0 \0A\0 \0-\0-\0>\0\n"
5434       /* <doc/> */
5435       "\0<\0d\0o\0c\0/\0>";
5436   const XML_Char *expected = XCS(" Comment A ");
5437   CharData storage;
5438 
5439   CharData_Init(&storage);
5440   XML_SetCommentHandler(g_parser, accumulate_comment);
5441   XML_SetUserData(g_parser, &storage);
5442   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE)
5443       == XML_STATUS_ERROR)
5444     xml_failure(g_parser);
5445   CharData_CheckXMLChars(&storage, expected);
5446 }
5447 END_TEST
5448 
5449 START_TEST(test_utf16_le_comment) {
5450   const char text[] =
5451       /* <!-- Comment B --> */
5452       "<\0!\0-\0-\0 \0C\0o\0m\0m\0e\0n\0t\0 \0B\0 \0-\0-\0>\0\n\0"
5453       /* <doc/> */
5454       "<\0d\0o\0c\0/\0>\0";
5455   const XML_Char *expected = XCS(" Comment B ");
5456   CharData storage;
5457 
5458   CharData_Init(&storage);
5459   XML_SetCommentHandler(g_parser, accumulate_comment);
5460   XML_SetUserData(g_parser, &storage);
5461   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE)
5462       == XML_STATUS_ERROR)
5463     xml_failure(g_parser);
5464   CharData_CheckXMLChars(&storage, expected);
5465 }
5466 END_TEST
5467 
5468 /* Test that the unknown encoding handler with map entries that expect
5469  * conversion but no conversion function is faulted
5470  */
5471 static int XMLCALL
5472 failing_converter(void *data, const char *s) {
5473   UNUSED_P(data);
5474   UNUSED_P(s);
5475   /* Always claim to have failed */
5476   return -1;
5477 }
5478 
5479 static int XMLCALL
5480 prefix_converter(void *data, const char *s) {
5481   UNUSED_P(data);
5482   /* If the first byte is 0xff, raise an error */
5483   if (s[0] == (char)-1)
5484     return -1;
5485   /* Just add the low bits of the first byte to the second */
5486   return (s[1] + (s[0] & 0x7f)) & 0x01ff;
5487 }
5488 
5489 static int XMLCALL
5490 MiscEncodingHandler(void *data, const XML_Char *encoding, XML_Encoding *info) {
5491   int i;
5492   int high_map = -2; /* Assume a 2-byte sequence */
5493 
5494   if (! xcstrcmp(encoding, XCS("invalid-9"))
5495       || ! xcstrcmp(encoding, XCS("ascii-like"))
5496       || ! xcstrcmp(encoding, XCS("invalid-len"))
5497       || ! xcstrcmp(encoding, XCS("invalid-a"))
5498       || ! xcstrcmp(encoding, XCS("invalid-surrogate"))
5499       || ! xcstrcmp(encoding, XCS("invalid-high")))
5500     high_map = -1;
5501 
5502   for (i = 0; i < 128; ++i)
5503     info->map[i] = i;
5504   for (; i < 256; ++i)
5505     info->map[i] = high_map;
5506 
5507   /* If required, put an invalid value in the ASCII entries */
5508   if (! xcstrcmp(encoding, XCS("invalid-9")))
5509     info->map[9] = 5;
5510   /* If required, have a top-bit set character starts a 5-byte sequence */
5511   if (! xcstrcmp(encoding, XCS("invalid-len")))
5512     info->map[0x81] = -5;
5513   /* If required, make a top-bit set character a valid ASCII character */
5514   if (! xcstrcmp(encoding, XCS("invalid-a")))
5515     info->map[0x82] = 'a';
5516   /* If required, give a top-bit set character a forbidden value,
5517    * what would otherwise be the first of a surrogate pair.
5518    */
5519   if (! xcstrcmp(encoding, XCS("invalid-surrogate")))
5520     info->map[0x83] = 0xd801;
5521   /* If required, give a top-bit set character too high a value */
5522   if (! xcstrcmp(encoding, XCS("invalid-high")))
5523     info->map[0x84] = 0x010101;
5524 
5525   info->data = data;
5526   info->release = NULL;
5527   if (! xcstrcmp(encoding, XCS("failing-conv")))
5528     info->convert = failing_converter;
5529   else if (! xcstrcmp(encoding, XCS("prefix-conv")))
5530     info->convert = prefix_converter;
5531   else
5532     info->convert = NULL;
5533   return XML_STATUS_OK;
5534 }
5535 
5536 START_TEST(test_missing_encoding_conversion_fn) {
5537   const char *text = "<?xml version='1.0' encoding='no-conv'?>\n"
5538                      "<doc>\x81</doc>";
5539 
5540   XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL);
5541   /* MiscEncodingHandler sets up an encoding with every top-bit-set
5542    * character introducing a two-byte sequence.  For this, it
5543    * requires a convert function.  The above function call doesn't
5544    * pass one through, so when BadEncodingHandler actually gets
5545    * called it should supply an invalid encoding.
5546    */
5547   expect_failure(text, XML_ERROR_UNKNOWN_ENCODING,
5548                  "Encoding with missing convert() not faulted");
5549 }
5550 END_TEST
5551 
5552 START_TEST(test_failing_encoding_conversion_fn) {
5553   const char *text = "<?xml version='1.0' encoding='failing-conv'?>\n"
5554                      "<doc>\x81</doc>";
5555 
5556   XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL);
5557   /* BadEncodingHandler sets up an encoding with every top-bit-set
5558    * character introducing a two-byte sequence.  For this, it
5559    * requires a convert function.  The above function call passes
5560    * one that insists all possible sequences are invalid anyway.
5561    */
5562   expect_failure(text, XML_ERROR_INVALID_TOKEN,
5563                  "Encoding with failing convert() not faulted");
5564 }
5565 END_TEST
5566 
5567 /* Test unknown encoding conversions */
5568 START_TEST(test_unknown_encoding_success) {
5569   const char *text = "<?xml version='1.0' encoding='prefix-conv'?>\n"
5570                      /* Equivalent to <eoc>Hello, world</eoc> */
5571                      "<\x81\x64\x80oc>Hello, world</\x81\x64\x80oc>";
5572 
5573   XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL);
5574   run_character_check(text, XCS("Hello, world"));
5575 }
5576 END_TEST
5577 
5578 /* Test bad name character in unknown encoding */
5579 START_TEST(test_unknown_encoding_bad_name) {
5580   const char *text = "<?xml version='1.0' encoding='prefix-conv'?>\n"
5581                      "<\xff\x64oc>Hello, world</\xff\x64oc>";
5582 
5583   XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL);
5584   expect_failure(text, XML_ERROR_INVALID_TOKEN,
5585                  "Bad name start in unknown encoding not faulted");
5586 }
5587 END_TEST
5588 
5589 /* Test bad mid-name character in unknown encoding */
5590 START_TEST(test_unknown_encoding_bad_name_2) {
5591   const char *text = "<?xml version='1.0' encoding='prefix-conv'?>\n"
5592                      "<d\xffoc>Hello, world</d\xffoc>";
5593 
5594   XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL);
5595   expect_failure(text, XML_ERROR_INVALID_TOKEN,
5596                  "Bad name in unknown encoding not faulted");
5597 }
5598 END_TEST
5599 
5600 /* Test element name that is long enough to fill the conversion buffer
5601  * in an unknown encoding, finishing with an encoded character.
5602  */
5603 START_TEST(test_unknown_encoding_long_name_1) {
5604   const char *text = "<?xml version='1.0' encoding='prefix-conv'?>\n"
5605                      "<abcdefghabcdefghabcdefghijkl\x80m\x80n\x80o\x80p>"
5606                      "Hi"
5607                      "</abcdefghabcdefghabcdefghijkl\x80m\x80n\x80o\x80p>";
5608   const XML_Char *expected = XCS("abcdefghabcdefghabcdefghijklmnop");
5609   CharData storage;
5610 
5611   CharData_Init(&storage);
5612   XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL);
5613   XML_SetStartElementHandler(g_parser, record_element_start_handler);
5614   XML_SetUserData(g_parser, &storage);
5615   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
5616       == XML_STATUS_ERROR)
5617     xml_failure(g_parser);
5618   CharData_CheckXMLChars(&storage, expected);
5619 }
5620 END_TEST
5621 
5622 /* Test element name that is long enough to fill the conversion buffer
5623  * in an unknown encoding, finishing with an simple character.
5624  */
5625 START_TEST(test_unknown_encoding_long_name_2) {
5626   const char *text = "<?xml version='1.0' encoding='prefix-conv'?>\n"
5627                      "<abcdefghabcdefghabcdefghijklmnop>"
5628                      "Hi"
5629                      "</abcdefghabcdefghabcdefghijklmnop>";
5630   const XML_Char *expected = XCS("abcdefghabcdefghabcdefghijklmnop");
5631   CharData storage;
5632 
5633   CharData_Init(&storage);
5634   XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL);
5635   XML_SetStartElementHandler(g_parser, record_element_start_handler);
5636   XML_SetUserData(g_parser, &storage);
5637   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
5638       == XML_STATUS_ERROR)
5639     xml_failure(g_parser);
5640   CharData_CheckXMLChars(&storage, expected);
5641 }
5642 END_TEST
5643 
5644 START_TEST(test_invalid_unknown_encoding) {
5645   const char *text = "<?xml version='1.0' encoding='invalid-9'?>\n"
5646                      "<doc>Hello world</doc>";
5647 
5648   XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL);
5649   expect_failure(text, XML_ERROR_UNKNOWN_ENCODING,
5650                  "Invalid unknown encoding not faulted");
5651 }
5652 END_TEST
5653 
5654 START_TEST(test_unknown_ascii_encoding_ok) {
5655   const char *text = "<?xml version='1.0' encoding='ascii-like'?>\n"
5656                      "<doc>Hello, world</doc>";
5657 
5658   XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL);
5659   run_character_check(text, XCS("Hello, world"));
5660 }
5661 END_TEST
5662 
5663 START_TEST(test_unknown_ascii_encoding_fail) {
5664   const char *text = "<?xml version='1.0' encoding='ascii-like'?>\n"
5665                      "<doc>Hello, \x80 world</doc>";
5666 
5667   XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL);
5668   expect_failure(text, XML_ERROR_INVALID_TOKEN,
5669                  "Invalid character not faulted");
5670 }
5671 END_TEST
5672 
5673 START_TEST(test_unknown_encoding_invalid_length) {
5674   const char *text = "<?xml version='1.0' encoding='invalid-len'?>\n"
5675                      "<doc>Hello, world</doc>";
5676 
5677   XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL);
5678   expect_failure(text, XML_ERROR_UNKNOWN_ENCODING,
5679                  "Invalid unknown encoding not faulted");
5680 }
5681 END_TEST
5682 
5683 START_TEST(test_unknown_encoding_invalid_topbit) {
5684   const char *text = "<?xml version='1.0' encoding='invalid-a'?>\n"
5685                      "<doc>Hello, world</doc>";
5686 
5687   XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL);
5688   expect_failure(text, XML_ERROR_UNKNOWN_ENCODING,
5689                  "Invalid unknown encoding not faulted");
5690 }
5691 END_TEST
5692 
5693 START_TEST(test_unknown_encoding_invalid_surrogate) {
5694   const char *text = "<?xml version='1.0' encoding='invalid-surrogate'?>\n"
5695                      "<doc>Hello, \x82 world</doc>";
5696 
5697   XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL);
5698   expect_failure(text, XML_ERROR_INVALID_TOKEN,
5699                  "Invalid unknown encoding not faulted");
5700 }
5701 END_TEST
5702 
5703 START_TEST(test_unknown_encoding_invalid_high) {
5704   const char *text = "<?xml version='1.0' encoding='invalid-high'?>\n"
5705                      "<doc>Hello, world</doc>";
5706 
5707   XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL);
5708   expect_failure(text, XML_ERROR_UNKNOWN_ENCODING,
5709                  "Invalid unknown encoding not faulted");
5710 }
5711 END_TEST
5712 
5713 START_TEST(test_unknown_encoding_invalid_attr_value) {
5714   const char *text = "<?xml version='1.0' encoding='prefix-conv'?>\n"
5715                      "<doc attr='\xff\x30'/>";
5716 
5717   XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL);
5718   expect_failure(text, XML_ERROR_INVALID_TOKEN,
5719                  "Invalid attribute valid not faulted");
5720 }
5721 END_TEST
5722 
5723 /* Test an external entity parser set to use latin-1 detects UTF-16
5724  * BOMs correctly.
5725  */
5726 enum ee_parse_flags { EE_PARSE_NONE = 0x00, EE_PARSE_FULL_BUFFER = 0x01 };
5727 
5728 typedef struct ExtTest2 {
5729   const char *parse_text;
5730   int parse_len;
5731   const XML_Char *encoding;
5732   CharData *storage;
5733   enum ee_parse_flags flags;
5734 } ExtTest2;
5735 
5736 static int XMLCALL
5737 external_entity_loader2(XML_Parser parser, const XML_Char *context,
5738                         const XML_Char *base, const XML_Char *systemId,
5739                         const XML_Char *publicId) {
5740   ExtTest2 *test_data = (ExtTest2 *)XML_GetUserData(parser);
5741   XML_Parser extparser;
5742 
5743   UNUSED_P(base);
5744   UNUSED_P(systemId);
5745   UNUSED_P(publicId);
5746   extparser = XML_ExternalEntityParserCreate(parser, context, NULL);
5747   if (extparser == NULL)
5748     fail("Coulr not create external entity parser");
5749   if (test_data->encoding != NULL) {
5750     if (! XML_SetEncoding(extparser, test_data->encoding))
5751       fail("XML_SetEncoding() ignored for external entity");
5752   }
5753   if (test_data->flags & EE_PARSE_FULL_BUFFER) {
5754     if (XML_Parse(extparser, test_data->parse_text, test_data->parse_len,
5755                   XML_TRUE)
5756         == XML_STATUS_ERROR) {
5757       xml_failure(extparser);
5758     }
5759   } else if (_XML_Parse_SINGLE_BYTES(extparser, test_data->parse_text,
5760                                      test_data->parse_len, XML_TRUE)
5761              == XML_STATUS_ERROR) {
5762     xml_failure(extparser);
5763   }
5764 
5765   XML_ParserFree(extparser);
5766   return XML_STATUS_OK;
5767 }
5768 
5769 /* Test that UTF-16 BOM does not select UTF-16 given explicit encoding */
5770 static void XMLCALL
5771 ext2_accumulate_characters(void *userData, const XML_Char *s, int len) {
5772   ExtTest2 *test_data = (ExtTest2 *)userData;
5773   accumulate_characters(test_data->storage, s, len);
5774 }
5775 
5776 START_TEST(test_ext_entity_latin1_utf16le_bom) {
5777   const char *text = "<!DOCTYPE doc [\n"
5778                      "  <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n"
5779                      "]>\n"
5780                      "<doc>&en;</doc>";
5781   ExtTest2 test_data
5782       = {/* If UTF-16, 0xfeff is the BOM and 0x204c is black left bullet */
5783          /* If Latin-1, 0xff = Y-diaeresis, 0xfe = lowercase thorn,
5784           *   0x4c = L and 0x20 is a space
5785           */
5786          "\xff\xfe\x4c\x20", 4, XCS("iso-8859-1"), NULL, EE_PARSE_NONE};
5787 #ifdef XML_UNICODE
5788   const XML_Char *expected = XCS("\x00ff\x00feL ");
5789 #else
5790   /* In UTF-8, y-diaeresis is 0xc3 0xbf, lowercase thorn is 0xc3 0xbe */
5791   const XML_Char *expected = XCS("\xc3\xbf\xc3\xbeL ");
5792 #endif
5793   CharData storage;
5794 
5795   CharData_Init(&storage);
5796   test_data.storage = &storage;
5797   XML_SetExternalEntityRefHandler(g_parser, external_entity_loader2);
5798   XML_SetUserData(g_parser, &test_data);
5799   XML_SetCharacterDataHandler(g_parser, ext2_accumulate_characters);
5800   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
5801       == XML_STATUS_ERROR)
5802     xml_failure(g_parser);
5803   CharData_CheckXMLChars(&storage, expected);
5804 }
5805 END_TEST
5806 
5807 START_TEST(test_ext_entity_latin1_utf16be_bom) {
5808   const char *text = "<!DOCTYPE doc [\n"
5809                      "  <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n"
5810                      "]>\n"
5811                      "<doc>&en;</doc>";
5812   ExtTest2 test_data
5813       = {/* If UTF-16, 0xfeff is the BOM and 0x204c is black left bullet */
5814          /* If Latin-1, 0xff = Y-diaeresis, 0xfe = lowercase thorn,
5815           *   0x4c = L and 0x20 is a space
5816           */
5817          "\xfe\xff\x20\x4c", 4, XCS("iso-8859-1"), NULL, EE_PARSE_NONE};
5818 #ifdef XML_UNICODE
5819   const XML_Char *expected = XCS("\x00fe\x00ff L");
5820 #else
5821   /* In UTF-8, y-diaeresis is 0xc3 0xbf, lowercase thorn is 0xc3 0xbe */
5822   const XML_Char *expected = XCS("\xc3\xbe\xc3\xbf L");
5823 #endif
5824   CharData storage;
5825 
5826   CharData_Init(&storage);
5827   test_data.storage = &storage;
5828   XML_SetExternalEntityRefHandler(g_parser, external_entity_loader2);
5829   XML_SetUserData(g_parser, &test_data);
5830   XML_SetCharacterDataHandler(g_parser, ext2_accumulate_characters);
5831   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
5832       == XML_STATUS_ERROR)
5833     xml_failure(g_parser);
5834   CharData_CheckXMLChars(&storage, expected);
5835 }
5836 END_TEST
5837 
5838 /* Parsing the full buffer rather than a byte at a time makes a
5839  * difference to the encoding scanning code, so repeat the above tests
5840  * without breaking them down by byte.
5841  */
5842 START_TEST(test_ext_entity_latin1_utf16le_bom2) {
5843   const char *text = "<!DOCTYPE doc [\n"
5844                      "  <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n"
5845                      "]>\n"
5846                      "<doc>&en;</doc>";
5847   ExtTest2 test_data
5848       = {/* If UTF-16, 0xfeff is the BOM and 0x204c is black left bullet */
5849          /* If Latin-1, 0xff = Y-diaeresis, 0xfe = lowercase thorn,
5850           *   0x4c = L and 0x20 is a space
5851           */
5852          "\xff\xfe\x4c\x20", 4, XCS("iso-8859-1"), NULL, EE_PARSE_FULL_BUFFER};
5853 #ifdef XML_UNICODE
5854   const XML_Char *expected = XCS("\x00ff\x00feL ");
5855 #else
5856   /* In UTF-8, y-diaeresis is 0xc3 0xbf, lowercase thorn is 0xc3 0xbe */
5857   const XML_Char *expected = XCS("\xc3\xbf\xc3\xbeL ");
5858 #endif
5859   CharData storage;
5860 
5861   CharData_Init(&storage);
5862   test_data.storage = &storage;
5863   XML_SetExternalEntityRefHandler(g_parser, external_entity_loader2);
5864   XML_SetUserData(g_parser, &test_data);
5865   XML_SetCharacterDataHandler(g_parser, ext2_accumulate_characters);
5866   if (XML_Parse(g_parser, text, (int)strlen(text), XML_TRUE)
5867       == XML_STATUS_ERROR)
5868     xml_failure(g_parser);
5869   CharData_CheckXMLChars(&storage, expected);
5870 }
5871 END_TEST
5872 
5873 START_TEST(test_ext_entity_latin1_utf16be_bom2) {
5874   const char *text = "<!DOCTYPE doc [\n"
5875                      "  <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n"
5876                      "]>\n"
5877                      "<doc>&en;</doc>";
5878   ExtTest2 test_data
5879       = {/* If UTF-16, 0xfeff is the BOM and 0x204c is black left bullet */
5880          /* If Latin-1, 0xff = Y-diaeresis, 0xfe = lowercase thorn,
5881           *   0x4c = L and 0x20 is a space
5882           */
5883          "\xfe\xff\x20\x4c", 4, XCS("iso-8859-1"), NULL, EE_PARSE_FULL_BUFFER};
5884 #ifdef XML_UNICODE
5885   const XML_Char *expected = XCS("\x00fe\x00ff L");
5886 #else
5887   /* In UTF-8, y-diaeresis is 0xc3 0xbf, lowercase thorn is 0xc3 0xbe */
5888   const XML_Char *expected = "\xc3\xbe\xc3\xbf L";
5889 #endif
5890   CharData storage;
5891 
5892   CharData_Init(&storage);
5893   test_data.storage = &storage;
5894   XML_SetExternalEntityRefHandler(g_parser, external_entity_loader2);
5895   XML_SetUserData(g_parser, &test_data);
5896   XML_SetCharacterDataHandler(g_parser, ext2_accumulate_characters);
5897   if (XML_Parse(g_parser, text, (int)strlen(text), XML_TRUE)
5898       == XML_STATUS_ERROR)
5899     xml_failure(g_parser);
5900   CharData_CheckXMLChars(&storage, expected);
5901 }
5902 END_TEST
5903 
5904 /* Test little-endian UTF-16 given an explicit big-endian encoding */
5905 START_TEST(test_ext_entity_utf16_be) {
5906   const char *text = "<!DOCTYPE doc [\n"
5907                      "  <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n"
5908                      "]>\n"
5909                      "<doc>&en;</doc>";
5910   ExtTest2 test_data
5911       = {"<\0e\0/\0>\0", 8, XCS("utf-16be"), NULL, EE_PARSE_NONE};
5912 #ifdef XML_UNICODE
5913   const XML_Char *expected = XCS("\x3c00\x6500\x2f00\x3e00");
5914 #else
5915   const XML_Char *expected = XCS("\xe3\xb0\x80"   /* U+3C00 */
5916                                  "\xe6\x94\x80"   /* U+6500 */
5917                                  "\xe2\xbc\x80"   /* U+2F00 */
5918                                  "\xe3\xb8\x80"); /* U+3E00 */
5919 #endif
5920   CharData storage;
5921 
5922   CharData_Init(&storage);
5923   test_data.storage = &storage;
5924   XML_SetExternalEntityRefHandler(g_parser, external_entity_loader2);
5925   XML_SetUserData(g_parser, &test_data);
5926   XML_SetCharacterDataHandler(g_parser, ext2_accumulate_characters);
5927   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
5928       == XML_STATUS_ERROR)
5929     xml_failure(g_parser);
5930   CharData_CheckXMLChars(&storage, expected);
5931 }
5932 END_TEST
5933 
5934 /* Test big-endian UTF-16 given an explicit little-endian encoding */
5935 START_TEST(test_ext_entity_utf16_le) {
5936   const char *text = "<!DOCTYPE doc [\n"
5937                      "  <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n"
5938                      "]>\n"
5939                      "<doc>&en;</doc>";
5940   ExtTest2 test_data
5941       = {"\0<\0e\0/\0>", 8, XCS("utf-16le"), NULL, EE_PARSE_NONE};
5942 #ifdef XML_UNICODE
5943   const XML_Char *expected = XCS("\x3c00\x6500\x2f00\x3e00");
5944 #else
5945   const XML_Char *expected = XCS("\xe3\xb0\x80"   /* U+3C00 */
5946                                  "\xe6\x94\x80"   /* U+6500 */
5947                                  "\xe2\xbc\x80"   /* U+2F00 */
5948                                  "\xe3\xb8\x80"); /* U+3E00 */
5949 #endif
5950   CharData storage;
5951 
5952   CharData_Init(&storage);
5953   test_data.storage = &storage;
5954   XML_SetExternalEntityRefHandler(g_parser, external_entity_loader2);
5955   XML_SetUserData(g_parser, &test_data);
5956   XML_SetCharacterDataHandler(g_parser, ext2_accumulate_characters);
5957   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
5958       == XML_STATUS_ERROR)
5959     xml_failure(g_parser);
5960   CharData_CheckXMLChars(&storage, expected);
5961 }
5962 END_TEST
5963 
5964 /* Test little-endian UTF-16 given no explicit encoding.
5965  * The existing default encoding (UTF-8) is assumed to hold without a
5966  * BOM to contradict it, so the entity value will in fact provoke an
5967  * error because 0x00 is not a valid XML character.  We parse the
5968  * whole buffer in one go rather than feeding it in byte by byte to
5969  * exercise different code paths in the initial scanning routines.
5970  */
5971 typedef struct ExtFaults2 {
5972   const char *parse_text;
5973   int parse_len;
5974   const char *fail_text;
5975   const XML_Char *encoding;
5976   enum XML_Error error;
5977 } ExtFaults2;
5978 
5979 static int XMLCALL
5980 external_entity_faulter2(XML_Parser parser, const XML_Char *context,
5981                          const XML_Char *base, const XML_Char *systemId,
5982                          const XML_Char *publicId) {
5983   ExtFaults2 *test_data = (ExtFaults2 *)XML_GetUserData(parser);
5984   XML_Parser extparser;
5985 
5986   UNUSED_P(base);
5987   UNUSED_P(systemId);
5988   UNUSED_P(publicId);
5989   extparser = XML_ExternalEntityParserCreate(parser, context, NULL);
5990   if (extparser == NULL)
5991     fail("Could not create external entity parser");
5992   if (test_data->encoding != NULL) {
5993     if (! XML_SetEncoding(extparser, test_data->encoding))
5994       fail("XML_SetEncoding() ignored for external entity");
5995   }
5996   if (XML_Parse(extparser, test_data->parse_text, test_data->parse_len,
5997                 XML_TRUE)
5998       != XML_STATUS_ERROR)
5999     fail(test_data->fail_text);
6000   if (XML_GetErrorCode(extparser) != test_data->error)
6001     xml_failure(extparser);
6002 
6003   XML_ParserFree(extparser);
6004   return XML_STATUS_ERROR;
6005 }
6006 
6007 START_TEST(test_ext_entity_utf16_unknown) {
6008   const char *text = "<!DOCTYPE doc [\n"
6009                      "  <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n"
6010                      "]>\n"
6011                      "<doc>&en;</doc>";
6012   ExtFaults2 test_data
6013       = {"a\0b\0c\0", 6, "Invalid character in entity not faulted", NULL,
6014          XML_ERROR_INVALID_TOKEN};
6015 
6016   XML_SetExternalEntityRefHandler(g_parser, external_entity_faulter2);
6017   XML_SetUserData(g_parser, &test_data);
6018   expect_failure(text, XML_ERROR_EXTERNAL_ENTITY_HANDLING,
6019                  "Invalid character should not have been accepted");
6020 }
6021 END_TEST
6022 
6023 /* Test not-quite-UTF-8 BOM (0xEF 0xBB 0xBF) */
6024 START_TEST(test_ext_entity_utf8_non_bom) {
6025   const char *text = "<!DOCTYPE doc [\n"
6026                      "  <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n"
6027                      "]>\n"
6028                      "<doc>&en;</doc>";
6029   ExtTest2 test_data
6030       = {"\xef\xbb\x80", /* Arabic letter DAD medial form, U+FEC0 */
6031          3, NULL, NULL, EE_PARSE_NONE};
6032 #ifdef XML_UNICODE
6033   const XML_Char *expected = XCS("\xfec0");
6034 #else
6035   const XML_Char *expected = XCS("\xef\xbb\x80");
6036 #endif
6037   CharData storage;
6038 
6039   CharData_Init(&storage);
6040   test_data.storage = &storage;
6041   XML_SetExternalEntityRefHandler(g_parser, external_entity_loader2);
6042   XML_SetUserData(g_parser, &test_data);
6043   XML_SetCharacterDataHandler(g_parser, ext2_accumulate_characters);
6044   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
6045       == XML_STATUS_ERROR)
6046     xml_failure(g_parser);
6047   CharData_CheckXMLChars(&storage, expected);
6048 }
6049 END_TEST
6050 
6051 /* Test that UTF-8 in a CDATA section is correctly passed through */
6052 START_TEST(test_utf8_in_cdata_section) {
6053   const char *text = "<doc><![CDATA[one \xc3\xa9 two]]></doc>";
6054 #ifdef XML_UNICODE
6055   const XML_Char *expected = XCS("one \x00e9 two");
6056 #else
6057   const XML_Char *expected = XCS("one \xc3\xa9 two");
6058 #endif
6059 
6060   run_character_check(text, expected);
6061 }
6062 END_TEST
6063 
6064 /* Test that little-endian UTF-16 in a CDATA section is handled */
6065 START_TEST(test_utf8_in_cdata_section_2) {
6066   const char *text = "<doc><![CDATA[\xc3\xa9]\xc3\xa9two]]></doc>";
6067 #ifdef XML_UNICODE
6068   const XML_Char *expected = XCS("\x00e9]\x00e9two");
6069 #else
6070   const XML_Char *expected = XCS("\xc3\xa9]\xc3\xa9two");
6071 #endif
6072 
6073   run_character_check(text, expected);
6074 }
6075 END_TEST
6076 
6077 START_TEST(test_utf8_in_start_tags) {
6078   struct test_case {
6079     bool goodName;
6080     bool goodNameStart;
6081     const char *tagName;
6082   };
6083 
6084   // The idea with the tests below is this:
6085   // We want to cover 1-, 2- and 3-byte sequences, 4-byte sequences
6086   // go to isNever and are hence not a concern.
6087   //
6088   // We start with a character that is a valid name character
6089   // (or even name-start character, see XML 1.0r4 spec) and then we flip
6090   // single bits at places where (1) the result leaves the UTF-8 encoding space
6091   // and (2) we stay in the same n-byte sequence family.
6092   //
6093   // The flipped bits are highlighted in angle brackets in comments,
6094   // e.g. "[<1>011 1001]" means we had [0011 1001] but we now flipped
6095   // the most significant bit to 1 to leave UTF-8 encoding space.
6096   struct test_case cases[] = {
6097       // 1-byte UTF-8: [0xxx xxxx]
6098       {true, true, "\x3A"},   // [0011 1010] = ASCII colon ':'
6099       {false, false, "\xBA"}, // [<1>011 1010]
6100       {true, false, "\x39"},  // [0011 1001] = ASCII nine '9'
6101       {false, false, "\xB9"}, // [<1>011 1001]
6102 
6103       // 2-byte UTF-8: [110x xxxx] [10xx xxxx]
6104       {true, true, "\xDB\xA5"},   // [1101 1011] [1010 0101] =
6105                                   // Arabic small waw U+06E5
6106       {false, false, "\x9B\xA5"}, // [1<0>01 1011] [1010 0101]
6107       {false, false, "\xDB\x25"}, // [1101 1011] [<0>010 0101]
6108       {false, false, "\xDB\xE5"}, // [1101 1011] [1<1>10 0101]
6109       {true, false, "\xCC\x81"},  // [1100 1100] [1000 0001] =
6110                                   // combining char U+0301
6111       {false, false, "\x8C\x81"}, // [1<0>00 1100] [1000 0001]
6112       {false, false, "\xCC\x01"}, // [1100 1100] [<0>000 0001]
6113       {false, false, "\xCC\xC1"}, // [1100 1100] [1<1>00 0001]
6114 
6115       // 3-byte UTF-8: [1110 xxxx] [10xx xxxx] [10xxxxxx]
6116       {true, true, "\xE0\xA4\x85"},   // [1110 0000] [1010 0100] [1000 0101] =
6117                                       // Devanagari Letter A U+0905
6118       {false, false, "\xA0\xA4\x85"}, // [1<0>10 0000] [1010 0100] [1000 0101]
6119       {false, false, "\xE0\x24\x85"}, // [1110 0000] [<0>010 0100] [1000 0101]
6120       {false, false, "\xE0\xE4\x85"}, // [1110 0000] [1<1>10 0100] [1000 0101]
6121       {false, false, "\xE0\xA4\x05"}, // [1110 0000] [1010 0100] [<0>000 0101]
6122       {false, false, "\xE0\xA4\xC5"}, // [1110 0000] [1010 0100] [1<1>00 0101]
6123       {true, false, "\xE0\xA4\x81"},  // [1110 0000] [1010 0100] [1000 0001] =
6124                                       // combining char U+0901
6125       {false, false, "\xA0\xA4\x81"}, // [1<0>10 0000] [1010 0100] [1000 0001]
6126       {false, false, "\xE0\x24\x81"}, // [1110 0000] [<0>010 0100] [1000 0001]
6127       {false, false, "\xE0\xE4\x81"}, // [1110 0000] [1<1>10 0100] [1000 0001]
6128       {false, false, "\xE0\xA4\x01"}, // [1110 0000] [1010 0100] [<0>000 0001]
6129       {false, false, "\xE0\xA4\xC1"}, // [1110 0000] [1010 0100] [1<1>00 0001]
6130   };
6131   const bool atNameStart[] = {true, false};
6132 
6133   size_t i = 0;
6134   char doc[1024];
6135   size_t failCount = 0;
6136 
6137   for (; i < sizeof(cases) / sizeof(cases[0]); i++) {
6138     size_t j = 0;
6139     for (; j < sizeof(atNameStart) / sizeof(atNameStart[0]); j++) {
6140       const bool expectedSuccess
6141           = atNameStart[j] ? cases[i].goodNameStart : cases[i].goodName;
6142       sprintf(doc, "<%s%s><!--", atNameStart[j] ? "" : "a", cases[i].tagName);
6143       XML_Parser parser = XML_ParserCreate(NULL);
6144 
6145       const enum XML_Status status
6146           = XML_Parse(parser, doc, (int)strlen(doc), /*isFinal=*/XML_FALSE);
6147 
6148       bool success = true;
6149       if ((status == XML_STATUS_OK) != expectedSuccess) {
6150         success = false;
6151       }
6152       if ((status == XML_STATUS_ERROR)
6153           && (XML_GetErrorCode(parser) != XML_ERROR_INVALID_TOKEN)) {
6154         success = false;
6155       }
6156 
6157       if (! success) {
6158         fprintf(
6159             stderr,
6160             "FAIL case %2u (%sat name start, %u-byte sequence, error code %d)\n",
6161             (unsigned)i + 1u, atNameStart[j] ? "    " : "not ",
6162             (unsigned)strlen(cases[i].tagName), XML_GetErrorCode(parser));
6163         failCount++;
6164       }
6165 
6166       XML_ParserFree(parser);
6167     }
6168   }
6169 
6170   if (failCount > 0) {
6171     fail("UTF-8 regression detected");
6172   }
6173 }
6174 END_TEST
6175 
6176 /* Test trailing spaces in elements are accepted */
6177 static void XMLCALL
6178 record_element_end_handler(void *userData, const XML_Char *name) {
6179   CharData *storage = (CharData *)userData;
6180 
6181   CharData_AppendXMLChars(storage, XCS("/"), 1);
6182   CharData_AppendXMLChars(storage, name, -1);
6183 }
6184 
6185 START_TEST(test_trailing_spaces_in_elements) {
6186   const char *text = "<doc   >Hi</doc >";
6187   const XML_Char *expected = XCS("doc/doc");
6188   CharData storage;
6189 
6190   CharData_Init(&storage);
6191   XML_SetElementHandler(g_parser, record_element_start_handler,
6192                         record_element_end_handler);
6193   XML_SetUserData(g_parser, &storage);
6194   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
6195       == XML_STATUS_ERROR)
6196     xml_failure(g_parser);
6197   CharData_CheckXMLChars(&storage, expected);
6198 }
6199 END_TEST
6200 
6201 START_TEST(test_utf16_attribute) {
6202   const char text[] =
6203       /* <d {KHO KHWAI}{CHO CHAN}='a'/>
6204        * where {KHO KHWAI} = U+0E04 = 0xe0 0xb8 0x84 in UTF-8
6205        * and   {CHO CHAN}  = U+0E08 = 0xe0 0xb8 0x88 in UTF-8
6206        */
6207       "<\0d\0 \0\x04\x0e\x08\x0e=\0'\0a\0'\0/\0>\0";
6208   const XML_Char *expected = XCS("a");
6209   CharData storage;
6210 
6211   CharData_Init(&storage);
6212   XML_SetStartElementHandler(g_parser, accumulate_attribute);
6213   XML_SetUserData(g_parser, &storage);
6214   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE)
6215       == XML_STATUS_ERROR)
6216     xml_failure(g_parser);
6217   CharData_CheckXMLChars(&storage, expected);
6218 }
6219 END_TEST
6220 
6221 START_TEST(test_utf16_second_attr) {
6222   /* <d a='1' {KHO KHWAI}{CHO CHAN}='2'/>
6223    * where {KHO KHWAI} = U+0E04 = 0xe0 0xb8 0x84 in UTF-8
6224    * and   {CHO CHAN}  = U+0E08 = 0xe0 0xb8 0x88 in UTF-8
6225    */
6226   const char text[] = "<\0d\0 \0a\0=\0'\0\x31\0'\0 \0"
6227                       "\x04\x0e\x08\x0e=\0'\0\x32\0'\0/\0>\0";
6228   const XML_Char *expected = XCS("1");
6229   CharData storage;
6230 
6231   CharData_Init(&storage);
6232   XML_SetStartElementHandler(g_parser, accumulate_attribute);
6233   XML_SetUserData(g_parser, &storage);
6234   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE)
6235       == XML_STATUS_ERROR)
6236     xml_failure(g_parser);
6237   CharData_CheckXMLChars(&storage, expected);
6238 }
6239 END_TEST
6240 
6241 START_TEST(test_attr_after_solidus) {
6242   const char *text = "<doc attr1='a' / attr2='b'>";
6243 
6244   expect_failure(text, XML_ERROR_INVALID_TOKEN, "Misplaced / not faulted");
6245 }
6246 END_TEST
6247 
6248 static void XMLCALL
6249 accumulate_entity_decl(void *userData, const XML_Char *entityName,
6250                        int is_parameter_entity, const XML_Char *value,
6251                        int value_length, const XML_Char *base,
6252                        const XML_Char *systemId, const XML_Char *publicId,
6253                        const XML_Char *notationName) {
6254   CharData *storage = (CharData *)userData;
6255 
6256   UNUSED_P(is_parameter_entity);
6257   UNUSED_P(base);
6258   UNUSED_P(systemId);
6259   UNUSED_P(publicId);
6260   UNUSED_P(notationName);
6261   CharData_AppendXMLChars(storage, entityName, -1);
6262   CharData_AppendXMLChars(storage, XCS("="), 1);
6263   CharData_AppendXMLChars(storage, value, value_length);
6264   CharData_AppendXMLChars(storage, XCS("\n"), 1);
6265 }
6266 
6267 START_TEST(test_utf16_pe) {
6268   /* <!DOCTYPE doc [
6269    * <!ENTITY % {KHO KHWAI}{CHO CHAN} '<!ELEMENT doc (#PCDATA)>'>
6270    * %{KHO KHWAI}{CHO CHAN};
6271    * ]>
6272    * <doc></doc>
6273    *
6274    * where {KHO KHWAI} = U+0E04 = 0xe0 0xb8 0x84 in UTF-8
6275    * and   {CHO CHAN}  = U+0E08 = 0xe0 0xb8 0x88 in UTF-8
6276    */
6277   const char text[] = "\0<\0!\0D\0O\0C\0T\0Y\0P\0E\0 \0d\0o\0c\0 \0[\0\n"
6278                       "\0<\0!\0E\0N\0T\0I\0T\0Y\0 \0%\0 \x0e\x04\x0e\x08\0 "
6279                       "\0'\0<\0!\0E\0L\0E\0M\0E\0N\0T\0 "
6280                       "\0d\0o\0c\0 \0(\0#\0P\0C\0D\0A\0T\0A\0)\0>\0'\0>\0\n"
6281                       "\0%\x0e\x04\x0e\x08\0;\0\n"
6282                       "\0]\0>\0\n"
6283                       "\0<\0d\0o\0c\0>\0<\0/\0d\0o\0c\0>";
6284 #ifdef XML_UNICODE
6285   const XML_Char *expected = XCS("\x0e04\x0e08=<!ELEMENT doc (#PCDATA)>\n");
6286 #else
6287   const XML_Char *expected
6288       = XCS("\xe0\xb8\x84\xe0\xb8\x88=<!ELEMENT doc (#PCDATA)>\n");
6289 #endif
6290   CharData storage;
6291 
6292   CharData_Init(&storage);
6293   XML_SetUserData(g_parser, &storage);
6294   XML_SetEntityDeclHandler(g_parser, accumulate_entity_decl);
6295   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE)
6296       == XML_STATUS_ERROR)
6297     xml_failure(g_parser);
6298   CharData_CheckXMLChars(&storage, expected);
6299 }
6300 END_TEST
6301 
6302 /* Test that duff attribute description keywords are rejected */
6303 START_TEST(test_bad_attr_desc_keyword) {
6304   const char *text = "<!DOCTYPE doc [\n"
6305                      "  <!ATTLIST doc attr CDATA #!IMPLIED>\n"
6306                      "]>\n"
6307                      "<doc />";
6308 
6309   expect_failure(text, XML_ERROR_INVALID_TOKEN,
6310                  "Bad keyword !IMPLIED not faulted");
6311 }
6312 END_TEST
6313 
6314 /* Test that an invalid attribute description keyword consisting of
6315  * UTF-16 characters with their top bytes non-zero are correctly
6316  * faulted
6317  */
6318 START_TEST(test_bad_attr_desc_keyword_utf16) {
6319   /* <!DOCTYPE d [
6320    * <!ATTLIST d a CDATA #{KHO KHWAI}{CHO CHAN}>
6321    * ]><d/>
6322    *
6323    * where {KHO KHWAI} = U+0E04 = 0xe0 0xb8 0x84 in UTF-8
6324    * and   {CHO CHAN}  = U+0E08 = 0xe0 0xb8 0x88 in UTF-8
6325    */
6326   const char text[]
6327       = "\0<\0!\0D\0O\0C\0T\0Y\0P\0E\0 \0d\0 \0[\0\n"
6328         "\0<\0!\0A\0T\0T\0L\0I\0S\0T\0 \0d\0 \0a\0 \0C\0D\0A\0T\0A\0 "
6329         "\0#\x0e\x04\x0e\x08\0>\0\n"
6330         "\0]\0>\0<\0d\0/\0>";
6331 
6332   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE)
6333       != XML_STATUS_ERROR)
6334     fail("Invalid UTF16 attribute keyword not faulted");
6335   if (XML_GetErrorCode(g_parser) != XML_ERROR_SYNTAX)
6336     xml_failure(g_parser);
6337 }
6338 END_TEST
6339 
6340 /* Test that invalid syntax in a <!DOCTYPE> is rejected.  Do this
6341  * using prefix-encoding (see above) to trigger specific code paths
6342  */
6343 START_TEST(test_bad_doctype) {
6344   const char *text = "<?xml version='1.0' encoding='prefix-conv'?>\n"
6345                      "<!DOCTYPE doc [ \x80\x44 ]><doc/>";
6346 
6347   XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL);
6348   expect_failure(text, XML_ERROR_SYNTAX,
6349                  "Invalid bytes in DOCTYPE not faulted");
6350 }
6351 END_TEST
6352 
6353 START_TEST(test_bad_doctype_utf8) {
6354   const char *text = "<!DOCTYPE \xDB\x25"
6355                      "doc><doc/>"; // [1101 1011] [<0>010 0101]
6356   expect_failure(text, XML_ERROR_INVALID_TOKEN,
6357                  "Invalid UTF-8 in DOCTYPE not faulted");
6358 }
6359 END_TEST
6360 
6361 START_TEST(test_bad_doctype_utf16) {
6362   const char text[] =
6363       /* <!DOCTYPE doc [ \x06f2 ]><doc/>
6364        *
6365        * U+06F2 = EXTENDED ARABIC-INDIC DIGIT TWO, a valid number
6366        * (name character) but not a valid letter (name start character)
6367        */
6368       "\0<\0!\0D\0O\0C\0T\0Y\0P\0E\0 \0d\0o\0c\0 \0[\0 "
6369       "\x06\xf2"
6370       "\0 \0]\0>\0<\0d\0o\0c\0/\0>";
6371 
6372   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE)
6373       != XML_STATUS_ERROR)
6374     fail("Invalid bytes in DOCTYPE not faulted");
6375   if (XML_GetErrorCode(g_parser) != XML_ERROR_SYNTAX)
6376     xml_failure(g_parser);
6377 }
6378 END_TEST
6379 
6380 START_TEST(test_bad_doctype_plus) {
6381   const char *text = "<!DOCTYPE 1+ [ <!ENTITY foo 'bar'> ]>\n"
6382                      "<1+>&foo;</1+>";
6383 
6384   expect_failure(text, XML_ERROR_INVALID_TOKEN,
6385                  "'+' in document name not faulted");
6386 }
6387 END_TEST
6388 
6389 START_TEST(test_bad_doctype_star) {
6390   const char *text = "<!DOCTYPE 1* [ <!ENTITY foo 'bar'> ]>\n"
6391                      "<1*>&foo;</1*>";
6392 
6393   expect_failure(text, XML_ERROR_INVALID_TOKEN,
6394                  "'*' in document name not faulted");
6395 }
6396 END_TEST
6397 
6398 START_TEST(test_bad_doctype_query) {
6399   const char *text = "<!DOCTYPE 1? [ <!ENTITY foo 'bar'> ]>\n"
6400                      "<1?>&foo;</1?>";
6401 
6402   expect_failure(text, XML_ERROR_INVALID_TOKEN,
6403                  "'?' in document name not faulted");
6404 }
6405 END_TEST
6406 
6407 START_TEST(test_unknown_encoding_bad_ignore) {
6408   const char *text = "<?xml version='1.0' encoding='prefix-conv'?>"
6409                      "<!DOCTYPE doc SYSTEM 'foo'>"
6410                      "<doc><e>&entity;</e></doc>";
6411   ExtFaults fault = {"<![IGNORE[<!ELEMENT \xffG (#PCDATA)*>]]>",
6412                      "Invalid character not faulted", XCS("prefix-conv"),
6413                      XML_ERROR_INVALID_TOKEN};
6414 
6415   XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL);
6416   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
6417   XML_SetExternalEntityRefHandler(g_parser, external_entity_faulter);
6418   XML_SetUserData(g_parser, &fault);
6419   expect_failure(text, XML_ERROR_EXTERNAL_ENTITY_HANDLING,
6420                  "Bad IGNORE section with unknown encoding not failed");
6421 }
6422 END_TEST
6423 
6424 START_TEST(test_entity_in_utf16_be_attr) {
6425   const char text[] =
6426       /* <e a='&#228; &#x00E4;'></e> */
6427       "\0<\0e\0 \0a\0=\0'\0&\0#\0\x32\0\x32\0\x38\0;\0 "
6428       "\0&\0#\0x\0\x30\0\x30\0E\0\x34\0;\0'\0>\0<\0/\0e\0>";
6429 #ifdef XML_UNICODE
6430   const XML_Char *expected = XCS("\x00e4 \x00e4");
6431 #else
6432   const XML_Char *expected = XCS("\xc3\xa4 \xc3\xa4");
6433 #endif
6434   CharData storage;
6435 
6436   CharData_Init(&storage);
6437   XML_SetUserData(g_parser, &storage);
6438   XML_SetStartElementHandler(g_parser, accumulate_attribute);
6439   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE)
6440       == XML_STATUS_ERROR)
6441     xml_failure(g_parser);
6442   CharData_CheckXMLChars(&storage, expected);
6443 }
6444 END_TEST
6445 
6446 START_TEST(test_entity_in_utf16_le_attr) {
6447   const char text[] =
6448       /* <e a='&#228; &#x00E4;'></e> */
6449       "<\0e\0 \0a\0=\0'\0&\0#\0\x32\0\x32\0\x38\0;\0 \0"
6450       "&\0#\0x\0\x30\0\x30\0E\0\x34\0;\0'\0>\0<\0/\0e\0>\0";
6451 #ifdef XML_UNICODE
6452   const XML_Char *expected = XCS("\x00e4 \x00e4");
6453 #else
6454   const XML_Char *expected = XCS("\xc3\xa4 \xc3\xa4");
6455 #endif
6456   CharData storage;
6457 
6458   CharData_Init(&storage);
6459   XML_SetUserData(g_parser, &storage);
6460   XML_SetStartElementHandler(g_parser, accumulate_attribute);
6461   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE)
6462       == XML_STATUS_ERROR)
6463     xml_failure(g_parser);
6464   CharData_CheckXMLChars(&storage, expected);
6465 }
6466 END_TEST
6467 
6468 START_TEST(test_entity_public_utf16_be) {
6469   const char text[] =
6470       /* <!DOCTYPE d [ */
6471       "\0<\0!\0D\0O\0C\0T\0Y\0P\0E\0 \0d\0 \0[\0\n"
6472       /* <!ENTITY % e PUBLIC 'foo' 'bar.ent'> */
6473       "\0<\0!\0E\0N\0T\0I\0T\0Y\0 \0%\0 \0e\0 \0P\0U\0B\0L\0I\0C\0 "
6474       "\0'\0f\0o\0o\0'\0 \0'\0b\0a\0r\0.\0e\0n\0t\0'\0>\0\n"
6475       /* %e; */
6476       "\0%\0e\0;\0\n"
6477       /* ]> */
6478       "\0]\0>\0\n"
6479       /* <d>&j;</d> */
6480       "\0<\0d\0>\0&\0j\0;\0<\0/\0d\0>";
6481   ExtTest2 test_data = {/* <!ENTITY j 'baz'> */
6482                         "\0<\0!\0E\0N\0T\0I\0T\0Y\0 \0j\0 \0'\0b\0a\0z\0'\0>",
6483                         34, NULL, NULL, EE_PARSE_NONE};
6484   const XML_Char *expected = XCS("baz");
6485   CharData storage;
6486 
6487   CharData_Init(&storage);
6488   test_data.storage = &storage;
6489   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
6490   XML_SetExternalEntityRefHandler(g_parser, external_entity_loader2);
6491   XML_SetUserData(g_parser, &test_data);
6492   XML_SetCharacterDataHandler(g_parser, ext2_accumulate_characters);
6493   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE)
6494       == XML_STATUS_ERROR)
6495     xml_failure(g_parser);
6496   CharData_CheckXMLChars(&storage, expected);
6497 }
6498 END_TEST
6499 
6500 START_TEST(test_entity_public_utf16_le) {
6501   const char text[] =
6502       /* <!DOCTYPE d [ */
6503       "<\0!\0D\0O\0C\0T\0Y\0P\0E\0 \0d\0 \0[\0\n\0"
6504       /* <!ENTITY % e PUBLIC 'foo' 'bar.ent'> */
6505       "<\0!\0E\0N\0T\0I\0T\0Y\0 \0%\0 \0e\0 \0P\0U\0B\0L\0I\0C\0 \0"
6506       "'\0f\0o\0o\0'\0 \0'\0b\0a\0r\0.\0e\0n\0t\0'\0>\0\n\0"
6507       /* %e; */
6508       "%\0e\0;\0\n\0"
6509       /* ]> */
6510       "]\0>\0\n\0"
6511       /* <d>&j;</d> */
6512       "<\0d\0>\0&\0j\0;\0<\0/\0d\0>\0";
6513   ExtTest2 test_data = {/* <!ENTITY j 'baz'> */
6514                         "<\0!\0E\0N\0T\0I\0T\0Y\0 \0j\0 \0'\0b\0a\0z\0'\0>\0",
6515                         34, NULL, NULL, EE_PARSE_NONE};
6516   const XML_Char *expected = XCS("baz");
6517   CharData storage;
6518 
6519   CharData_Init(&storage);
6520   test_data.storage = &storage;
6521   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
6522   XML_SetExternalEntityRefHandler(g_parser, external_entity_loader2);
6523   XML_SetUserData(g_parser, &test_data);
6524   XML_SetCharacterDataHandler(g_parser, ext2_accumulate_characters);
6525   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE)
6526       == XML_STATUS_ERROR)
6527     xml_failure(g_parser);
6528   CharData_CheckXMLChars(&storage, expected);
6529 }
6530 END_TEST
6531 
6532 /* Test that a doctype with neither an internal nor external subset is
6533  * faulted
6534  */
6535 START_TEST(test_short_doctype) {
6536   const char *text = "<!DOCTYPE doc></doc>";
6537   expect_failure(text, XML_ERROR_INVALID_TOKEN,
6538                  "DOCTYPE without subset not rejected");
6539 }
6540 END_TEST
6541 
6542 START_TEST(test_short_doctype_2) {
6543   const char *text = "<!DOCTYPE doc PUBLIC></doc>";
6544   expect_failure(text, XML_ERROR_SYNTAX,
6545                  "DOCTYPE without Public ID not rejected");
6546 }
6547 END_TEST
6548 
6549 START_TEST(test_short_doctype_3) {
6550   const char *text = "<!DOCTYPE doc SYSTEM></doc>";
6551   expect_failure(text, XML_ERROR_SYNTAX,
6552                  "DOCTYPE without System ID not rejected");
6553 }
6554 END_TEST
6555 
6556 START_TEST(test_long_doctype) {
6557   const char *text = "<!DOCTYPE doc PUBLIC 'foo' 'bar' 'baz'></doc>";
6558   expect_failure(text, XML_ERROR_SYNTAX, "DOCTYPE with extra ID not rejected");
6559 }
6560 END_TEST
6561 
6562 START_TEST(test_bad_entity) {
6563   const char *text = "<!DOCTYPE doc [\n"
6564                      "  <!ENTITY foo PUBLIC>\n"
6565                      "]>\n"
6566                      "<doc/>";
6567   expect_failure(text, XML_ERROR_SYNTAX,
6568                  "ENTITY without Public ID is not rejected");
6569 }
6570 END_TEST
6571 
6572 /* Test unquoted value is faulted */
6573 START_TEST(test_bad_entity_2) {
6574   const char *text = "<!DOCTYPE doc [\n"
6575                      "  <!ENTITY % foo bar>\n"
6576                      "]>\n"
6577                      "<doc/>";
6578   expect_failure(text, XML_ERROR_SYNTAX,
6579                  "ENTITY without Public ID is not rejected");
6580 }
6581 END_TEST
6582 
6583 START_TEST(test_bad_entity_3) {
6584   const char *text = "<!DOCTYPE doc [\n"
6585                      "  <!ENTITY % foo PUBLIC>\n"
6586                      "]>\n"
6587                      "<doc/>";
6588   expect_failure(text, XML_ERROR_SYNTAX,
6589                  "Parameter ENTITY without Public ID is not rejected");
6590 }
6591 END_TEST
6592 
6593 START_TEST(test_bad_entity_4) {
6594   const char *text = "<!DOCTYPE doc [\n"
6595                      "  <!ENTITY % foo SYSTEM>\n"
6596                      "]>\n"
6597                      "<doc/>";
6598   expect_failure(text, XML_ERROR_SYNTAX,
6599                  "Parameter ENTITY without Public ID is not rejected");
6600 }
6601 END_TEST
6602 
6603 START_TEST(test_bad_notation) {
6604   const char *text = "<!DOCTYPE doc [\n"
6605                      "  <!NOTATION n SYSTEM>\n"
6606                      "]>\n"
6607                      "<doc/>";
6608   expect_failure(text, XML_ERROR_SYNTAX,
6609                  "Notation without System ID is not rejected");
6610 }
6611 END_TEST
6612 
6613 /* Test for issue #11, wrongly suppressed default handler */
6614 typedef struct default_check {
6615   const XML_Char *expected;
6616   const int expectedLen;
6617   XML_Bool seen;
6618 } DefaultCheck;
6619 
6620 static void XMLCALL
6621 checking_default_handler(void *userData, const XML_Char *s, int len) {
6622   DefaultCheck *data = (DefaultCheck *)userData;
6623   int i;
6624 
6625   for (i = 0; data[i].expected != NULL; i++) {
6626     if (data[i].expectedLen == len
6627         && ! memcmp(data[i].expected, s, len * sizeof(XML_Char))) {
6628       data[i].seen = XML_TRUE;
6629       break;
6630     }
6631   }
6632 }
6633 
6634 START_TEST(test_default_doctype_handler) {
6635   const char *text = "<!DOCTYPE doc PUBLIC 'pubname' 'test.dtd' [\n"
6636                      "  <!ENTITY foo 'bar'>\n"
6637                      "]>\n"
6638                      "<doc>&foo;</doc>";
6639   DefaultCheck test_data[] = {{XCS("'pubname'"), 9, XML_FALSE},
6640                               {XCS("'test.dtd'"), 10, XML_FALSE},
6641                               {NULL, 0, XML_FALSE}};
6642   int i;
6643 
6644   XML_SetUserData(g_parser, &test_data);
6645   XML_SetDefaultHandler(g_parser, checking_default_handler);
6646   XML_SetEntityDeclHandler(g_parser, dummy_entity_decl_handler);
6647   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
6648       == XML_STATUS_ERROR)
6649     xml_failure(g_parser);
6650   for (i = 0; test_data[i].expected != NULL; i++)
6651     if (! test_data[i].seen)
6652       fail("Default handler not run for public !DOCTYPE");
6653 }
6654 END_TEST
6655 
6656 START_TEST(test_empty_element_abort) {
6657   const char *text = "<abort/>";
6658 
6659   XML_SetStartElementHandler(g_parser, start_element_suspender);
6660   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
6661       != XML_STATUS_ERROR)
6662     fail("Expected to error on abort");
6663 }
6664 END_TEST
6665 
6666 /*
6667  * Namespaces tests.
6668  */
6669 
6670 static void
6671 namespace_setup(void) {
6672   g_parser = XML_ParserCreateNS(NULL, XCS(' '));
6673   if (g_parser == NULL)
6674     fail("Parser not created.");
6675 }
6676 
6677 static void
6678 namespace_teardown(void) {
6679   basic_teardown();
6680 }
6681 
6682 /* Check that an element name and attribute name match the expected values.
6683    The expected values are passed as an array reference of string pointers
6684    provided as the userData argument; the first is the expected
6685    element name, and the second is the expected attribute name.
6686 */
6687 static int triplet_start_flag = XML_FALSE;
6688 static int triplet_end_flag = XML_FALSE;
6689 
6690 static void XMLCALL
6691 triplet_start_checker(void *userData, const XML_Char *name,
6692                       const XML_Char **atts) {
6693   XML_Char **elemstr = (XML_Char **)userData;
6694   char buffer[1024];
6695   if (xcstrcmp(elemstr[0], name) != 0) {
6696     sprintf(buffer, "unexpected start string: '%" XML_FMT_STR "'", name);
6697     fail(buffer);
6698   }
6699   if (xcstrcmp(elemstr[1], atts[0]) != 0) {
6700     sprintf(buffer, "unexpected attribute string: '%" XML_FMT_STR "'", atts[0]);
6701     fail(buffer);
6702   }
6703   triplet_start_flag = XML_TRUE;
6704 }
6705 
6706 /* Check that the element name passed to the end-element handler matches
6707    the expected value.  The expected value is passed as the first element
6708    in an array of strings passed as the userData argument.
6709 */
6710 static void XMLCALL
6711 triplet_end_checker(void *userData, const XML_Char *name) {
6712   XML_Char **elemstr = (XML_Char **)userData;
6713   if (xcstrcmp(elemstr[0], name) != 0) {
6714     char buffer[1024];
6715     sprintf(buffer, "unexpected end string: '%" XML_FMT_STR "'", name);
6716     fail(buffer);
6717   }
6718   triplet_end_flag = XML_TRUE;
6719 }
6720 
6721 START_TEST(test_return_ns_triplet) {
6722   const char *text = "<foo:e xmlns:foo='http://example.org/' bar:a='12'\n"
6723                      "       xmlns:bar='http://example.org/'>";
6724   const char *epilog = "</foo:e>";
6725   const XML_Char *elemstr[]
6726       = {XCS("http://example.org/ e foo"), XCS("http://example.org/ a bar")};
6727   XML_SetReturnNSTriplet(g_parser, XML_TRUE);
6728   XML_SetUserData(g_parser, (void *)elemstr);
6729   XML_SetElementHandler(g_parser, triplet_start_checker, triplet_end_checker);
6730   XML_SetNamespaceDeclHandler(g_parser, dummy_start_namespace_decl_handler,
6731                               dummy_end_namespace_decl_handler);
6732   triplet_start_flag = XML_FALSE;
6733   triplet_end_flag = XML_FALSE;
6734   dummy_handler_flags = 0;
6735   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_FALSE)
6736       == XML_STATUS_ERROR)
6737     xml_failure(g_parser);
6738   if (! triplet_start_flag)
6739     fail("triplet_start_checker not invoked");
6740   /* Check that unsetting "return triplets" fails while still parsing */
6741   XML_SetReturnNSTriplet(g_parser, XML_FALSE);
6742   if (_XML_Parse_SINGLE_BYTES(g_parser, epilog, (int)strlen(epilog), XML_TRUE)
6743       == XML_STATUS_ERROR)
6744     xml_failure(g_parser);
6745   if (! triplet_end_flag)
6746     fail("triplet_end_checker not invoked");
6747   if (dummy_handler_flags
6748       != (DUMMY_START_NS_DECL_HANDLER_FLAG | DUMMY_END_NS_DECL_HANDLER_FLAG))
6749     fail("Namespace handlers not called");
6750 }
6751 END_TEST
6752 
6753 static void XMLCALL
6754 overwrite_start_checker(void *userData, const XML_Char *name,
6755                         const XML_Char **atts) {
6756   CharData *storage = (CharData *)userData;
6757   CharData_AppendXMLChars(storage, XCS("start "), 6);
6758   CharData_AppendXMLChars(storage, name, -1);
6759   while (*atts != NULL) {
6760     CharData_AppendXMLChars(storage, XCS("\nattribute "), 11);
6761     CharData_AppendXMLChars(storage, *atts, -1);
6762     atts += 2;
6763   }
6764   CharData_AppendXMLChars(storage, XCS("\n"), 1);
6765 }
6766 
6767 static void XMLCALL
6768 overwrite_end_checker(void *userData, const XML_Char *name) {
6769   CharData *storage = (CharData *)userData;
6770   CharData_AppendXMLChars(storage, XCS("end "), 4);
6771   CharData_AppendXMLChars(storage, name, -1);
6772   CharData_AppendXMLChars(storage, XCS("\n"), 1);
6773 }
6774 
6775 static void
6776 run_ns_tagname_overwrite_test(const char *text, const XML_Char *result) {
6777   CharData storage;
6778   CharData_Init(&storage);
6779   XML_SetUserData(g_parser, &storage);
6780   XML_SetElementHandler(g_parser, overwrite_start_checker,
6781                         overwrite_end_checker);
6782   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
6783       == XML_STATUS_ERROR)
6784     xml_failure(g_parser);
6785   CharData_CheckXMLChars(&storage, result);
6786 }
6787 
6788 /* Regression test for SF bug #566334. */
6789 START_TEST(test_ns_tagname_overwrite) {
6790   const char *text = "<n:e xmlns:n='http://example.org/'>\n"
6791                      "  <n:f n:attr='foo'/>\n"
6792                      "  <n:g n:attr2='bar'/>\n"
6793                      "</n:e>";
6794   const XML_Char *result = XCS("start http://example.org/ e\n")
6795       XCS("start http://example.org/ f\n")
6796           XCS("attribute http://example.org/ attr\n")
6797               XCS("end http://example.org/ f\n")
6798                   XCS("start http://example.org/ g\n")
6799                       XCS("attribute http://example.org/ attr2\n")
6800                           XCS("end http://example.org/ g\n")
6801                               XCS("end http://example.org/ e\n");
6802   run_ns_tagname_overwrite_test(text, result);
6803 }
6804 END_TEST
6805 
6806 /* Regression test for SF bug #566334. */
6807 START_TEST(test_ns_tagname_overwrite_triplet) {
6808   const char *text = "<n:e xmlns:n='http://example.org/'>\n"
6809                      "  <n:f n:attr='foo'/>\n"
6810                      "  <n:g n:attr2='bar'/>\n"
6811                      "</n:e>";
6812   const XML_Char *result = XCS("start http://example.org/ e n\n")
6813       XCS("start http://example.org/ f n\n")
6814           XCS("attribute http://example.org/ attr n\n")
6815               XCS("end http://example.org/ f n\n")
6816                   XCS("start http://example.org/ g n\n")
6817                       XCS("attribute http://example.org/ attr2 n\n")
6818                           XCS("end http://example.org/ g n\n")
6819                               XCS("end http://example.org/ e n\n");
6820   XML_SetReturnNSTriplet(g_parser, XML_TRUE);
6821   run_ns_tagname_overwrite_test(text, result);
6822 }
6823 END_TEST
6824 
6825 /* Regression test for SF bug #620343. */
6826 static void XMLCALL
6827 start_element_fail(void *userData, const XML_Char *name,
6828                    const XML_Char **atts) {
6829   UNUSED_P(userData);
6830   UNUSED_P(name);
6831   UNUSED_P(atts);
6832 
6833   /* We should never get here. */
6834   fail("should never reach start_element_fail()");
6835 }
6836 
6837 static void XMLCALL
6838 start_ns_clearing_start_element(void *userData, const XML_Char *prefix,
6839                                 const XML_Char *uri) {
6840   UNUSED_P(prefix);
6841   UNUSED_P(uri);
6842   XML_SetStartElementHandler((XML_Parser)userData, NULL);
6843 }
6844 
6845 START_TEST(test_start_ns_clears_start_element) {
6846   /* This needs to use separate start/end tags; using the empty tag
6847      syntax doesn't cause the problematic path through Expat to be
6848      taken.
6849   */
6850   const char *text = "<e xmlns='http://example.org/'></e>";
6851 
6852   XML_SetStartElementHandler(g_parser, start_element_fail);
6853   XML_SetStartNamespaceDeclHandler(g_parser, start_ns_clearing_start_element);
6854   XML_SetEndNamespaceDeclHandler(g_parser, dummy_end_namespace_decl_handler);
6855   XML_UseParserAsHandlerArg(g_parser);
6856   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
6857       == XML_STATUS_ERROR)
6858     xml_failure(g_parser);
6859 }
6860 END_TEST
6861 
6862 /* Regression test for SF bug #616863. */
6863 static int XMLCALL
6864 external_entity_handler(XML_Parser parser, const XML_Char *context,
6865                         const XML_Char *base, const XML_Char *systemId,
6866                         const XML_Char *publicId) {
6867   intptr_t callno = 1 + (intptr_t)XML_GetUserData(parser);
6868   const char *text;
6869   XML_Parser p2;
6870 
6871   UNUSED_P(base);
6872   UNUSED_P(systemId);
6873   UNUSED_P(publicId);
6874   if (callno == 1)
6875     text = ("<!ELEMENT doc (e+)>\n"
6876             "<!ATTLIST doc xmlns CDATA #IMPLIED>\n"
6877             "<!ELEMENT e EMPTY>\n");
6878   else
6879     text = ("<?xml version='1.0' encoding='us-ascii'?>"
6880             "<e/>");
6881 
6882   XML_SetUserData(parser, (void *)callno);
6883   p2 = XML_ExternalEntityParserCreate(parser, context, NULL);
6884   if (_XML_Parse_SINGLE_BYTES(p2, text, (int)strlen(text), XML_TRUE)
6885       == XML_STATUS_ERROR) {
6886     xml_failure(p2);
6887     return XML_STATUS_ERROR;
6888   }
6889   XML_ParserFree(p2);
6890   return XML_STATUS_OK;
6891 }
6892 
6893 START_TEST(test_default_ns_from_ext_subset_and_ext_ge) {
6894   const char *text = "<?xml version='1.0'?>\n"
6895                      "<!DOCTYPE doc SYSTEM 'http://example.org/doc.dtd' [\n"
6896                      "  <!ENTITY en SYSTEM 'http://example.org/entity.ent'>\n"
6897                      "]>\n"
6898                      "<doc xmlns='http://example.org/ns1'>\n"
6899                      "&en;\n"
6900                      "</doc>";
6901 
6902   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
6903   XML_SetExternalEntityRefHandler(g_parser, external_entity_handler);
6904   /* We actually need to set this handler to tickle this bug. */
6905   XML_SetStartElementHandler(g_parser, dummy_start_element);
6906   XML_SetUserData(g_parser, NULL);
6907   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
6908       == XML_STATUS_ERROR)
6909     xml_failure(g_parser);
6910 }
6911 END_TEST
6912 
6913 /* Regression test #1 for SF bug #673791. */
6914 START_TEST(test_ns_prefix_with_empty_uri_1) {
6915   const char *text = "<doc xmlns:prefix='http://example.org/'>\n"
6916                      "  <e xmlns:prefix=''/>\n"
6917                      "</doc>";
6918 
6919   expect_failure(text, XML_ERROR_UNDECLARING_PREFIX,
6920                  "Did not report re-setting namespace"
6921                  " URI with prefix to ''.");
6922 }
6923 END_TEST
6924 
6925 /* Regression test #2 for SF bug #673791. */
6926 START_TEST(test_ns_prefix_with_empty_uri_2) {
6927   const char *text = "<?xml version='1.0'?>\n"
6928                      "<docelem xmlns:pre=''/>";
6929 
6930   expect_failure(text, XML_ERROR_UNDECLARING_PREFIX,
6931                  "Did not report setting namespace URI with prefix to ''.");
6932 }
6933 END_TEST
6934 
6935 /* Regression test #3 for SF bug #673791. */
6936 START_TEST(test_ns_prefix_with_empty_uri_3) {
6937   const char *text = "<!DOCTYPE doc [\n"
6938                      "  <!ELEMENT doc EMPTY>\n"
6939                      "  <!ATTLIST doc\n"
6940                      "    xmlns:prefix CDATA ''>\n"
6941                      "]>\n"
6942                      "<doc/>";
6943 
6944   expect_failure(text, XML_ERROR_UNDECLARING_PREFIX,
6945                  "Didn't report attr default setting NS w/ prefix to ''.");
6946 }
6947 END_TEST
6948 
6949 /* Regression test #4 for SF bug #673791. */
6950 START_TEST(test_ns_prefix_with_empty_uri_4) {
6951   const char *text = "<!DOCTYPE doc [\n"
6952                      "  <!ELEMENT prefix:doc EMPTY>\n"
6953                      "  <!ATTLIST prefix:doc\n"
6954                      "    xmlns:prefix CDATA 'http://example.org/'>\n"
6955                      "]>\n"
6956                      "<prefix:doc/>";
6957   /* Packaged info expected by the end element handler;
6958      the weird structuring lets us re-use the triplet_end_checker()
6959      function also used for another test. */
6960   const XML_Char *elemstr[] = {XCS("http://example.org/ doc prefix")};
6961   XML_SetReturnNSTriplet(g_parser, XML_TRUE);
6962   XML_SetUserData(g_parser, (void *)elemstr);
6963   XML_SetEndElementHandler(g_parser, triplet_end_checker);
6964   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
6965       == XML_STATUS_ERROR)
6966     xml_failure(g_parser);
6967 }
6968 END_TEST
6969 
6970 /* Test with non-xmlns prefix */
6971 START_TEST(test_ns_unbound_prefix) {
6972   const char *text = "<!DOCTYPE doc [\n"
6973                      "  <!ELEMENT prefix:doc EMPTY>\n"
6974                      "  <!ATTLIST prefix:doc\n"
6975                      "    notxmlns:prefix CDATA 'http://example.org/'>\n"
6976                      "]>\n"
6977                      "<prefix:doc/>";
6978 
6979   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
6980       != XML_STATUS_ERROR)
6981     fail("Unbound prefix incorrectly passed");
6982   if (XML_GetErrorCode(g_parser) != XML_ERROR_UNBOUND_PREFIX)
6983     xml_failure(g_parser);
6984 }
6985 END_TEST
6986 
6987 START_TEST(test_ns_default_with_empty_uri) {
6988   const char *text = "<doc xmlns='http://example.org/'>\n"
6989                      "  <e xmlns=''/>\n"
6990                      "</doc>";
6991   /* Add some handlers to exercise extra code paths */
6992   XML_SetStartNamespaceDeclHandler(g_parser,
6993                                    dummy_start_namespace_decl_handler);
6994   XML_SetEndNamespaceDeclHandler(g_parser, dummy_end_namespace_decl_handler);
6995   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
6996       == XML_STATUS_ERROR)
6997     xml_failure(g_parser);
6998 }
6999 END_TEST
7000 
7001 /* Regression test for SF bug #692964: two prefixes for one namespace. */
7002 START_TEST(test_ns_duplicate_attrs_diff_prefixes) {
7003   const char *text = "<doc xmlns:a='http://example.org/a'\n"
7004                      "     xmlns:b='http://example.org/a'\n"
7005                      "     a:a='v' b:a='v' />";
7006   expect_failure(text, XML_ERROR_DUPLICATE_ATTRIBUTE,
7007                  "did not report multiple attributes with same URI+name");
7008 }
7009 END_TEST
7010 
7011 START_TEST(test_ns_duplicate_hashes) {
7012   /* The hash of an attribute is calculated as the hash of its URI
7013    * concatenated with a space followed by its name (after the
7014    * colon).  We wish to generate attributes with the same hash
7015    * value modulo the attribute table size so that we can check that
7016    * the attribute hash table works correctly.  The attribute hash
7017    * table size will be the smallest power of two greater than the
7018    * number of attributes, but at least eight.  There is
7019    * unfortunately no programmatic way of getting the hash or the
7020    * table size at user level, but the test code coverage percentage
7021    * will drop if the hashes cease to point to the same row.
7022    *
7023    * The cunning plan is to have few enough attributes to have a
7024    * reliable table size of 8, and have the single letter attribute
7025    * names be 8 characters apart, producing a hash which will be the
7026    * same modulo 8.
7027    */
7028   const char *text = "<doc xmlns:a='http://example.org/a'\n"
7029                      "     a:a='v' a:i='w' />";
7030   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
7031       == XML_STATUS_ERROR)
7032     xml_failure(g_parser);
7033 }
7034 END_TEST
7035 
7036 /* Regression test for SF bug #695401: unbound prefix. */
7037 START_TEST(test_ns_unbound_prefix_on_attribute) {
7038   const char *text = "<doc a:attr=''/>";
7039   expect_failure(text, XML_ERROR_UNBOUND_PREFIX,
7040                  "did not report unbound prefix on attribute");
7041 }
7042 END_TEST
7043 
7044 /* Regression test for SF bug #695401: unbound prefix. */
7045 START_TEST(test_ns_unbound_prefix_on_element) {
7046   const char *text = "<a:doc/>";
7047   expect_failure(text, XML_ERROR_UNBOUND_PREFIX,
7048                  "did not report unbound prefix on element");
7049 }
7050 END_TEST
7051 
7052 /* Test that the parsing status is correctly reset by XML_ParserReset().
7053  * We usE test_return_ns_triplet() for our example parse to improve
7054  * coverage of tidying up code executed.
7055  */
7056 START_TEST(test_ns_parser_reset) {
7057   XML_ParsingStatus status;
7058 
7059   XML_GetParsingStatus(g_parser, &status);
7060   if (status.parsing != XML_INITIALIZED)
7061     fail("parsing status doesn't start INITIALIZED");
7062   test_return_ns_triplet();
7063   XML_GetParsingStatus(g_parser, &status);
7064   if (status.parsing != XML_FINISHED)
7065     fail("parsing status doesn't end FINISHED");
7066   XML_ParserReset(g_parser, NULL);
7067   XML_GetParsingStatus(g_parser, &status);
7068   if (status.parsing != XML_INITIALIZED)
7069     fail("parsing status doesn't reset to INITIALIZED");
7070 }
7071 END_TEST
7072 
7073 /* Test that long element names with namespaces are handled correctly */
7074 START_TEST(test_ns_long_element) {
7075   const char *text
7076       = "<foo:thisisalongenoughelementnametotriggerareallocation\n"
7077         " xmlns:foo='http://example.org/' bar:a='12'\n"
7078         " xmlns:bar='http://example.org/'>"
7079         "</foo:thisisalongenoughelementnametotriggerareallocation>";
7080   const XML_Char *elemstr[]
7081       = {XCS("http://example.org/")
7082              XCS(" thisisalongenoughelementnametotriggerareallocation foo"),
7083          XCS("http://example.org/ a bar")};
7084 
7085   XML_SetReturnNSTriplet(g_parser, XML_TRUE);
7086   XML_SetUserData(g_parser, (void *)elemstr);
7087   XML_SetElementHandler(g_parser, triplet_start_checker, triplet_end_checker);
7088   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
7089       == XML_STATUS_ERROR)
7090     xml_failure(g_parser);
7091 }
7092 END_TEST
7093 
7094 /* Test mixed population of prefixed and unprefixed attributes */
7095 START_TEST(test_ns_mixed_prefix_atts) {
7096   const char *text = "<e a='12' bar:b='13'\n"
7097                      " xmlns:bar='http://example.org/'>"
7098                      "</e>";
7099 
7100   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
7101       == XML_STATUS_ERROR)
7102     xml_failure(g_parser);
7103 }
7104 END_TEST
7105 
7106 /* Test having a long namespaced element name inside a short one.
7107  * This exercises some internal buffer reallocation that is shared
7108  * across elements with the same namespace URI.
7109  */
7110 START_TEST(test_ns_extend_uri_buffer) {
7111   const char *text = "<foo:e xmlns:foo='http://example.org/'>"
7112                      " <foo:thisisalongenoughnametotriggerallocationaction"
7113                      "   foo:a='12' />"
7114                      "</foo:e>";
7115   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
7116       == XML_STATUS_ERROR)
7117     xml_failure(g_parser);
7118 }
7119 END_TEST
7120 
7121 /* Test that xmlns is correctly rejected as an attribute in the xmlns
7122  * namespace, but not in other namespaces
7123  */
7124 START_TEST(test_ns_reserved_attributes) {
7125   const char *text1
7126       = "<foo:e xmlns:foo='http://example.org/' xmlns:xmlns='12' />";
7127   const char *text2
7128       = "<foo:e xmlns:foo='http://example.org/' foo:xmlns='12' />";
7129   expect_failure(text1, XML_ERROR_RESERVED_PREFIX_XMLNS,
7130                  "xmlns not rejected as an attribute");
7131   XML_ParserReset(g_parser, NULL);
7132   if (_XML_Parse_SINGLE_BYTES(g_parser, text2, (int)strlen(text2), XML_TRUE)
7133       == XML_STATUS_ERROR)
7134     xml_failure(g_parser);
7135 }
7136 END_TEST
7137 
7138 /* Test more reserved attributes */
7139 START_TEST(test_ns_reserved_attributes_2) {
7140   const char *text1 = "<foo:e xmlns:foo='http://example.org/'"
7141                       "  xmlns:xml='http://example.org/' />";
7142   const char *text2
7143       = "<foo:e xmlns:foo='http://www.w3.org/XML/1998/namespace' />";
7144   const char *text3 = "<foo:e xmlns:foo='http://www.w3.org/2000/xmlns/' />";
7145 
7146   expect_failure(text1, XML_ERROR_RESERVED_PREFIX_XML,
7147                  "xml not rejected as an attribute");
7148   XML_ParserReset(g_parser, NULL);
7149   expect_failure(text2, XML_ERROR_RESERVED_NAMESPACE_URI,
7150                  "Use of w3.org URL not faulted");
7151   XML_ParserReset(g_parser, NULL);
7152   expect_failure(text3, XML_ERROR_RESERVED_NAMESPACE_URI,
7153                  "Use of w3.org xmlns URL not faulted");
7154 }
7155 END_TEST
7156 
7157 /* Test string pool handling of namespace names of 2048 characters */
7158 /* Exercises a particular string pool growth path */
7159 START_TEST(test_ns_extremely_long_prefix) {
7160   /* C99 compilers are only required to support 4095-character
7161    * strings, so the following needs to be split in two to be safe
7162    * for all compilers.
7163    */
7164   const char *text1
7165       = "<doc "
7166         /* 64 character on each line */
7167         /* ...gives a total length of 2048 */
7168         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7169         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7170         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7171         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7172         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7173         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7174         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7175         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7176         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7177         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7178         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7179         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7180         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7181         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7182         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7183         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7184         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7185         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7186         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7187         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7188         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7189         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7190         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7191         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7192         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7193         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7194         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7195         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7196         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7197         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7198         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7199         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7200         ":a='12'";
7201   const char *text2
7202       = " xmlns:"
7203         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7204         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7205         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7206         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7207         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7208         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7209         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7210         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7211         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7212         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7213         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7214         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7215         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7216         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7217         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7218         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7219         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7220         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7221         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7222         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7223         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7224         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7225         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7226         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7227         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7228         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7229         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7230         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7231         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7232         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7233         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7234         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7235         "='foo'\n>"
7236         "</doc>";
7237 
7238   if (_XML_Parse_SINGLE_BYTES(g_parser, text1, (int)strlen(text1), XML_FALSE)
7239       == XML_STATUS_ERROR)
7240     xml_failure(g_parser);
7241   if (_XML_Parse_SINGLE_BYTES(g_parser, text2, (int)strlen(text2), XML_TRUE)
7242       == XML_STATUS_ERROR)
7243     xml_failure(g_parser);
7244 }
7245 END_TEST
7246 
7247 /* Test unknown encoding handlers in namespace setup */
7248 START_TEST(test_ns_unknown_encoding_success) {
7249   const char *text = "<?xml version='1.0' encoding='prefix-conv'?>\n"
7250                      "<foo:e xmlns:foo='http://example.org/'>Hi</foo:e>";
7251 
7252   XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL);
7253   run_character_check(text, XCS("Hi"));
7254 }
7255 END_TEST
7256 
7257 /* Test that too many colons are rejected */
7258 START_TEST(test_ns_double_colon) {
7259   const char *text = "<foo:e xmlns:foo='http://example.org/' foo:a:b='bar' />";
7260   const enum XML_Status status
7261       = _XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE);
7262 #ifdef XML_NS
7263   if ((status == XML_STATUS_OK)
7264       || (XML_GetErrorCode(g_parser) != XML_ERROR_INVALID_TOKEN)) {
7265     fail("Double colon in attribute name not faulted"
7266          " (despite active namespace support)");
7267   }
7268 #else
7269   if (status != XML_STATUS_OK) {
7270     fail("Double colon in attribute name faulted"
7271          " (despite inactive namespace support");
7272   }
7273 #endif
7274 }
7275 END_TEST
7276 
7277 START_TEST(test_ns_double_colon_element) {
7278   const char *text = "<foo:bar:e xmlns:foo='http://example.org/' />";
7279   const enum XML_Status status
7280       = _XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE);
7281 #ifdef XML_NS
7282   if ((status == XML_STATUS_OK)
7283       || (XML_GetErrorCode(g_parser) != XML_ERROR_INVALID_TOKEN)) {
7284     fail("Double colon in element name not faulted"
7285          " (despite active namespace support)");
7286   }
7287 #else
7288   if (status != XML_STATUS_OK) {
7289     fail("Double colon in element name faulted"
7290          " (despite inactive namespace support");
7291   }
7292 #endif
7293 }
7294 END_TEST
7295 
7296 /* Test that non-name characters after a colon are rejected */
7297 START_TEST(test_ns_bad_attr_leafname) {
7298   const char *text = "<foo:e xmlns:foo='http://example.org/' foo:?ar='baz' />";
7299 
7300   expect_failure(text, XML_ERROR_INVALID_TOKEN,
7301                  "Invalid character in leafname not faulted");
7302 }
7303 END_TEST
7304 
7305 START_TEST(test_ns_bad_element_leafname) {
7306   const char *text = "<foo:?oc xmlns:foo='http://example.org/' />";
7307 
7308   expect_failure(text, XML_ERROR_INVALID_TOKEN,
7309                  "Invalid character in element leafname not faulted");
7310 }
7311 END_TEST
7312 
7313 /* Test high-byte-set UTF-16 characters are valid in a leafname */
7314 START_TEST(test_ns_utf16_leafname) {
7315   const char text[] =
7316       /* <n:e xmlns:n='URI' n:{KHO KHWAI}='a' />
7317        * where {KHO KHWAI} = U+0E04 = 0xe0 0xb8 0x84 in UTF-8
7318        */
7319       "<\0n\0:\0e\0 \0x\0m\0l\0n\0s\0:\0n\0=\0'\0U\0R\0I\0'\0 \0"
7320       "n\0:\0\x04\x0e=\0'\0a\0'\0 \0/\0>\0";
7321   const XML_Char *expected = XCS("a");
7322   CharData storage;
7323 
7324   CharData_Init(&storage);
7325   XML_SetStartElementHandler(g_parser, accumulate_attribute);
7326   XML_SetUserData(g_parser, &storage);
7327   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE)
7328       == XML_STATUS_ERROR)
7329     xml_failure(g_parser);
7330   CharData_CheckXMLChars(&storage, expected);
7331 }
7332 END_TEST
7333 
7334 START_TEST(test_ns_utf16_element_leafname) {
7335   const char text[] =
7336       /* <n:{KHO KHWAI} xmlns:n='URI'/>
7337        * where {KHO KHWAI} = U+0E04 = 0xe0 0xb8 0x84 in UTF-8
7338        */
7339       "\0<\0n\0:\x0e\x04\0 \0x\0m\0l\0n\0s\0:\0n\0=\0'\0U\0R\0I\0'\0/\0>";
7340 #ifdef XML_UNICODE
7341   const XML_Char *expected = XCS("URI \x0e04");
7342 #else
7343   const XML_Char *expected = XCS("URI \xe0\xb8\x84");
7344 #endif
7345   CharData storage;
7346 
7347   CharData_Init(&storage);
7348   XML_SetStartElementHandler(g_parser, start_element_event_handler);
7349   XML_SetUserData(g_parser, &storage);
7350   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE)
7351       == XML_STATUS_ERROR)
7352     xml_failure(g_parser);
7353   CharData_CheckXMLChars(&storage, expected);
7354 }
7355 END_TEST
7356 
7357 START_TEST(test_ns_utf16_doctype) {
7358   const char text[] =
7359       /* <!DOCTYPE foo:{KHO KHWAI} [ <!ENTITY bar 'baz'> ]>\n
7360        * where {KHO KHWAI} = U+0E04 = 0xe0 0xb8 0x84 in UTF-8
7361        */
7362       "\0<\0!\0D\0O\0C\0T\0Y\0P\0E\0 \0f\0o\0o\0:\x0e\x04\0 "
7363       "\0[\0 \0<\0!\0E\0N\0T\0I\0T\0Y\0 \0b\0a\0r\0 \0'\0b\0a\0z\0'\0>\0 "
7364       "\0]\0>\0\n"
7365       /* <foo:{KHO KHWAI} xmlns:foo='URI'>&bar;</foo:{KHO KHWAI}> */
7366       "\0<\0f\0o\0o\0:\x0e\x04\0 "
7367       "\0x\0m\0l\0n\0s\0:\0f\0o\0o\0=\0'\0U\0R\0I\0'\0>"
7368       "\0&\0b\0a\0r\0;"
7369       "\0<\0/\0f\0o\0o\0:\x0e\x04\0>";
7370 #ifdef XML_UNICODE
7371   const XML_Char *expected = XCS("URI \x0e04");
7372 #else
7373   const XML_Char *expected = XCS("URI \xe0\xb8\x84");
7374 #endif
7375   CharData storage;
7376 
7377   CharData_Init(&storage);
7378   XML_SetUserData(g_parser, &storage);
7379   XML_SetStartElementHandler(g_parser, start_element_event_handler);
7380   XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL);
7381   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE)
7382       == XML_STATUS_ERROR)
7383     xml_failure(g_parser);
7384   CharData_CheckXMLChars(&storage, expected);
7385 }
7386 END_TEST
7387 
7388 START_TEST(test_ns_invalid_doctype) {
7389   const char *text = "<!DOCTYPE foo:!bad [ <!ENTITY bar 'baz' ]>\n"
7390                      "<foo:!bad>&bar;</foo:!bad>";
7391 
7392   expect_failure(text, XML_ERROR_INVALID_TOKEN,
7393                  "Invalid character in document local name not faulted");
7394 }
7395 END_TEST
7396 
7397 START_TEST(test_ns_double_colon_doctype) {
7398   const char *text = "<!DOCTYPE foo:a:doc [ <!ENTITY bar 'baz' ]>\n"
7399                      "<foo:a:doc>&bar;</foo:a:doc>";
7400 
7401   expect_failure(text, XML_ERROR_SYNTAX,
7402                  "Double colon in document name not faulted");
7403 }
7404 END_TEST
7405 
7406 START_TEST(test_ns_separator_in_uri) {
7407   struct test_case {
7408     enum XML_Status expectedStatus;
7409     const char *doc;
7410   };
7411   struct test_case cases[] = {
7412       {XML_STATUS_OK, "<doc xmlns='one_two' />"},
7413       {XML_STATUS_ERROR, "<doc xmlns='one&#x0A;two' />"},
7414   };
7415 
7416   size_t i = 0;
7417   size_t failCount = 0;
7418   for (; i < sizeof(cases) / sizeof(cases[0]); i++) {
7419     XML_Parser parser = XML_ParserCreateNS(NULL, '\n');
7420     XML_SetElementHandler(parser, dummy_start_element, dummy_end_element);
7421     if (XML_Parse(parser, cases[i].doc, (int)strlen(cases[i].doc),
7422                   /*isFinal*/ XML_TRUE)
7423         != cases[i].expectedStatus) {
7424       failCount++;
7425     }
7426     XML_ParserFree(parser);
7427   }
7428 
7429   if (failCount) {
7430     fail("Namespace separator handling is broken");
7431   }
7432 }
7433 END_TEST
7434 
7435 /* Control variable; the number of times duff_allocator() will successfully
7436  * allocate */
7437 #define ALLOC_ALWAYS_SUCCEED (-1)
7438 #define REALLOC_ALWAYS_SUCCEED (-1)
7439 
7440 static intptr_t allocation_count = ALLOC_ALWAYS_SUCCEED;
7441 static intptr_t reallocation_count = REALLOC_ALWAYS_SUCCEED;
7442 
7443 /* Crocked allocator for allocation failure tests */
7444 static void *
7445 duff_allocator(size_t size) {
7446   if (allocation_count == 0)
7447     return NULL;
7448   if (allocation_count != ALLOC_ALWAYS_SUCCEED)
7449     allocation_count--;
7450   return malloc(size);
7451 }
7452 
7453 /* Crocked reallocator for allocation failure tests */
7454 static void *
7455 duff_reallocator(void *ptr, size_t size) {
7456   if (reallocation_count == 0)
7457     return NULL;
7458   if (reallocation_count != REALLOC_ALWAYS_SUCCEED)
7459     reallocation_count--;
7460   return realloc(ptr, size);
7461 }
7462 
7463 /* Test that a failure to allocate the parser structure fails gracefully */
7464 START_TEST(test_misc_alloc_create_parser) {
7465   XML_Memory_Handling_Suite memsuite = {duff_allocator, realloc, free};
7466   unsigned int i;
7467   const unsigned int max_alloc_count = 10;
7468 
7469   /* Something this simple shouldn't need more than 10 allocations */
7470   for (i = 0; i < max_alloc_count; i++) {
7471     allocation_count = i;
7472     g_parser = XML_ParserCreate_MM(NULL, &memsuite, NULL);
7473     if (g_parser != NULL)
7474       break;
7475   }
7476   if (i == 0)
7477     fail("Parser unexpectedly ignored failing allocator");
7478   else if (i == max_alloc_count)
7479     fail("Parser not created with max allocation count");
7480 }
7481 END_TEST
7482 
7483 /* Test memory allocation failures for a parser with an encoding */
7484 START_TEST(test_misc_alloc_create_parser_with_encoding) {
7485   XML_Memory_Handling_Suite memsuite = {duff_allocator, realloc, free};
7486   unsigned int i;
7487   const unsigned int max_alloc_count = 10;
7488 
7489   /* Try several levels of allocation */
7490   for (i = 0; i < max_alloc_count; i++) {
7491     allocation_count = i;
7492     g_parser = XML_ParserCreate_MM(XCS("us-ascii"), &memsuite, NULL);
7493     if (g_parser != NULL)
7494       break;
7495   }
7496   if (i == 0)
7497     fail("Parser ignored failing allocator");
7498   else if (i == max_alloc_count)
7499     fail("Parser not created with max allocation count");
7500 }
7501 END_TEST
7502 
7503 /* Test that freeing a NULL parser doesn't cause an explosion.
7504  * (Not actually tested anywhere else)
7505  */
7506 START_TEST(test_misc_null_parser) {
7507   XML_ParserFree(NULL);
7508 }
7509 END_TEST
7510 
7511 /* Test that XML_ErrorString rejects out-of-range codes */
7512 START_TEST(test_misc_error_string) {
7513   if (XML_ErrorString((enum XML_Error) - 1) != NULL)
7514     fail("Negative error code not rejected");
7515   if (XML_ErrorString((enum XML_Error)100) != NULL)
7516     fail("Large error code not rejected");
7517 }
7518 END_TEST
7519 
7520 /* Test the version information is consistent */
7521 
7522 /* Since we are working in XML_LChars (potentially 16-bits), we
7523  * can't use the standard C library functions for character
7524  * manipulation and have to roll our own.
7525  */
7526 static int
7527 parse_version(const XML_LChar *version_text,
7528               XML_Expat_Version *version_struct) {
7529   if (! version_text)
7530     return XML_FALSE;
7531 
7532   while (*version_text != 0x00) {
7533     if (*version_text >= ASCII_0 && *version_text <= ASCII_9)
7534       break;
7535     version_text++;
7536   }
7537   if (*version_text == 0x00)
7538     return XML_FALSE;
7539 
7540   /* version_struct->major = strtoul(version_text, 10, &version_text) */
7541   version_struct->major = 0;
7542   while (*version_text >= ASCII_0 && *version_text <= ASCII_9) {
7543     version_struct->major
7544         = 10 * version_struct->major + (*version_text++ - ASCII_0);
7545   }
7546   if (*version_text++ != ASCII_PERIOD)
7547     return XML_FALSE;
7548 
7549   /* Now for the minor version number */
7550   version_struct->minor = 0;
7551   while (*version_text >= ASCII_0 && *version_text <= ASCII_9) {
7552     version_struct->minor
7553         = 10 * version_struct->minor + (*version_text++ - ASCII_0);
7554   }
7555   if (*version_text++ != ASCII_PERIOD)
7556     return XML_FALSE;
7557 
7558   /* Finally the micro version number */
7559   version_struct->micro = 0;
7560   while (*version_text >= ASCII_0 && *version_text <= ASCII_9) {
7561     version_struct->micro
7562         = 10 * version_struct->micro + (*version_text++ - ASCII_0);
7563   }
7564   if (*version_text != 0x00)
7565     return XML_FALSE;
7566   return XML_TRUE;
7567 }
7568 
7569 static int
7570 versions_equal(const XML_Expat_Version *first,
7571                const XML_Expat_Version *second) {
7572   return (first->major == second->major && first->minor == second->minor
7573           && first->micro == second->micro);
7574 }
7575 
7576 START_TEST(test_misc_version) {
7577   XML_Expat_Version read_version = XML_ExpatVersionInfo();
7578   /* Silence compiler warning with the following assignment */
7579   XML_Expat_Version parsed_version = {0, 0, 0};
7580   const XML_LChar *version_text = XML_ExpatVersion();
7581 
7582   if (version_text == NULL)
7583     fail("Could not obtain version text");
7584   assert(version_text != NULL);
7585   if (! parse_version(version_text, &parsed_version))
7586     fail("Unable to parse version text");
7587   if (! versions_equal(&read_version, &parsed_version))
7588     fail("Version mismatch");
7589 
7590 #if ! defined(XML_UNICODE) || defined(XML_UNICODE_WCHAR_T)
7591   if (xcstrcmp(version_text, XCS("expat_2.4.6"))) /* needs bump on releases */
7592     fail("XML_*_VERSION in expat.h out of sync?\n");
7593 #else
7594   /* If we have XML_UNICODE defined but not XML_UNICODE_WCHAR_T
7595    * then XML_LChar is defined as char, for some reason.
7596    */
7597   if (strcmp(version_text, "expat_2.2.5")) /* needs bump on releases */
7598     fail("XML_*_VERSION in expat.h out of sync?\n");
7599 #endif /* ! defined(XML_UNICODE) || defined(XML_UNICODE_WCHAR_T) */
7600 }
7601 END_TEST
7602 
7603 /* Test feature information */
7604 START_TEST(test_misc_features) {
7605   const XML_Feature *features = XML_GetFeatureList();
7606 
7607   /* Prevent problems with double-freeing parsers */
7608   g_parser = NULL;
7609   if (features == NULL) {
7610     fail("Failed to get feature information");
7611   } else {
7612     /* Loop through the features checking what we can */
7613     while (features->feature != XML_FEATURE_END) {
7614       switch (features->feature) {
7615       case XML_FEATURE_SIZEOF_XML_CHAR:
7616         if (features->value != sizeof(XML_Char))
7617           fail("Incorrect size of XML_Char");
7618         break;
7619       case XML_FEATURE_SIZEOF_XML_LCHAR:
7620         if (features->value != sizeof(XML_LChar))
7621           fail("Incorrect size of XML_LChar");
7622         break;
7623       default:
7624         break;
7625       }
7626       features++;
7627     }
7628   }
7629 }
7630 END_TEST
7631 
7632 /* Regression test for GitHub Issue #17: memory leak parsing attribute
7633  * values with mixed bound and unbound namespaces.
7634  */
7635 START_TEST(test_misc_attribute_leak) {
7636   const char *text = "<D xmlns:L=\"D\" l:a='' L:a=''/>";
7637   XML_Memory_Handling_Suite memsuite
7638       = {tracking_malloc, tracking_realloc, tracking_free};
7639 
7640   g_parser = XML_ParserCreate_MM(XCS("UTF-8"), &memsuite, XCS("\n"));
7641   expect_failure(text, XML_ERROR_UNBOUND_PREFIX, "Unbound prefixes not found");
7642   XML_ParserFree(g_parser);
7643   /* Prevent the teardown trying to double free */
7644   g_parser = NULL;
7645 
7646   if (! tracking_report())
7647     fail("Memory leak found");
7648 }
7649 END_TEST
7650 
7651 /* Test parser created for UTF-16LE is successful */
7652 START_TEST(test_misc_utf16le) {
7653   const char text[] =
7654       /* <?xml version='1.0'?><q>Hi</q> */
7655       "<\0?\0x\0m\0l\0 \0"
7656       "v\0e\0r\0s\0i\0o\0n\0=\0'\0\x31\0.\0\x30\0'\0?\0>\0"
7657       "<\0q\0>\0H\0i\0<\0/\0q\0>\0";
7658   const XML_Char *expected = XCS("Hi");
7659   CharData storage;
7660 
7661   g_parser = XML_ParserCreate(XCS("UTF-16LE"));
7662   if (g_parser == NULL)
7663     fail("Parser not created");
7664 
7665   CharData_Init(&storage);
7666   XML_SetUserData(g_parser, &storage);
7667   XML_SetCharacterDataHandler(g_parser, accumulate_characters);
7668   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE)
7669       == XML_STATUS_ERROR)
7670     xml_failure(g_parser);
7671   CharData_CheckXMLChars(&storage, expected);
7672 }
7673 END_TEST
7674 
7675 typedef struct {
7676   XML_Parser parser;
7677   int deep;
7678 } DataIssue240;
7679 
7680 static void
7681 start_element_issue_240(void *userData, const XML_Char *name,
7682                         const XML_Char **atts) {
7683   DataIssue240 *mydata = (DataIssue240 *)userData;
7684   UNUSED_P(name);
7685   UNUSED_P(atts);
7686   mydata->deep++;
7687 }
7688 
7689 static void
7690 end_element_issue_240(void *userData, const XML_Char *name) {
7691   DataIssue240 *mydata = (DataIssue240 *)userData;
7692 
7693   UNUSED_P(name);
7694   mydata->deep--;
7695   if (mydata->deep == 0) {
7696     XML_StopParser(mydata->parser, 0);
7697   }
7698 }
7699 
7700 START_TEST(test_misc_stop_during_end_handler_issue_240_1) {
7701   XML_Parser parser;
7702   DataIssue240 *mydata;
7703   enum XML_Status result;
7704   const char *const doc1 = "<doc><e1/><e><foo/></e></doc>";
7705 
7706   parser = XML_ParserCreate(NULL);
7707   XML_SetElementHandler(parser, start_element_issue_240, end_element_issue_240);
7708   mydata = (DataIssue240 *)malloc(sizeof(DataIssue240));
7709   mydata->parser = parser;
7710   mydata->deep = 0;
7711   XML_SetUserData(parser, mydata);
7712 
7713   result = XML_Parse(parser, doc1, (int)strlen(doc1), 1);
7714   XML_ParserFree(parser);
7715   free(mydata);
7716   if (result != XML_STATUS_ERROR)
7717     fail("Stopping the parser did not work as expected");
7718 }
7719 END_TEST
7720 
7721 START_TEST(test_misc_stop_during_end_handler_issue_240_2) {
7722   XML_Parser parser;
7723   DataIssue240 *mydata;
7724   enum XML_Status result;
7725   const char *const doc2 = "<doc><elem/></doc>";
7726 
7727   parser = XML_ParserCreate(NULL);
7728   XML_SetElementHandler(parser, start_element_issue_240, end_element_issue_240);
7729   mydata = (DataIssue240 *)malloc(sizeof(DataIssue240));
7730   mydata->parser = parser;
7731   mydata->deep = 0;
7732   XML_SetUserData(parser, mydata);
7733 
7734   result = XML_Parse(parser, doc2, (int)strlen(doc2), 1);
7735   XML_ParserFree(parser);
7736   free(mydata);
7737   if (result != XML_STATUS_ERROR)
7738     fail("Stopping the parser did not work as expected");
7739 }
7740 END_TEST
7741 
7742 START_TEST(test_misc_deny_internal_entity_closing_doctype_issue_317) {
7743   const char *const inputOne = "<!DOCTYPE d [\n"
7744                                "<!ENTITY % e ']><d/>'>\n"
7745                                "\n"
7746                                "%e;";
7747   const char *const inputTwo = "<!DOCTYPE d [\n"
7748                                "<!ENTITY % e1 ']><d/>'><!ENTITY % e2 '&e1;'>\n"
7749                                "\n"
7750                                "%e2;";
7751   const char *const inputThree = "<!DOCTYPE d [\n"
7752                                  "<!ENTITY % e ']><d'>\n"
7753                                  "\n"
7754                                  "%e;";
7755   const char *const inputIssue317 = "<!DOCTYPE doc [\n"
7756                                     "<!ENTITY % foo ']>\n"
7757                                     "<doc>Hell<oc (#PCDATA)*>'>\n"
7758                                     "%foo;\n"
7759                                     "]>\n"
7760                                     "<doc>Hello, world</dVc>";
7761 
7762   const char *const inputs[] = {inputOne, inputTwo, inputThree, inputIssue317};
7763   size_t inputIndex = 0;
7764 
7765   for (; inputIndex < sizeof(inputs) / sizeof(inputs[0]); inputIndex++) {
7766     XML_Parser parser;
7767     enum XML_Status parseResult;
7768     int setParamEntityResult;
7769     XML_Size lineNumber;
7770     XML_Size columnNumber;
7771     const char *const input = inputs[inputIndex];
7772 
7773     parser = XML_ParserCreate(NULL);
7774     setParamEntityResult
7775         = XML_SetParamEntityParsing(parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
7776     if (setParamEntityResult != 1)
7777       fail("Failed to set XML_PARAM_ENTITY_PARSING_ALWAYS.");
7778 
7779     parseResult = XML_Parse(parser, input, (int)strlen(input), 0);
7780     if (parseResult != XML_STATUS_ERROR) {
7781       parseResult = XML_Parse(parser, "", 0, 1);
7782       if (parseResult != XML_STATUS_ERROR) {
7783         fail("Parsing was expected to fail but succeeded.");
7784       }
7785     }
7786 
7787     if (XML_GetErrorCode(parser) != XML_ERROR_INVALID_TOKEN)
7788       fail("Error code does not match XML_ERROR_INVALID_TOKEN");
7789 
7790     lineNumber = XML_GetCurrentLineNumber(parser);
7791     if (lineNumber != 4)
7792       fail("XML_GetCurrentLineNumber does not work as expected.");
7793 
7794     columnNumber = XML_GetCurrentColumnNumber(parser);
7795     if (columnNumber != 0)
7796       fail("XML_GetCurrentColumnNumber does not work as expected.");
7797 
7798     XML_ParserFree(parser);
7799   }
7800 }
7801 END_TEST
7802 
7803 static void
7804 alloc_setup(void) {
7805   XML_Memory_Handling_Suite memsuite = {duff_allocator, duff_reallocator, free};
7806 
7807   /* Ensure the parser creation will go through */
7808   allocation_count = ALLOC_ALWAYS_SUCCEED;
7809   reallocation_count = REALLOC_ALWAYS_SUCCEED;
7810   g_parser = XML_ParserCreate_MM(NULL, &memsuite, NULL);
7811   if (g_parser == NULL)
7812     fail("Parser not created");
7813 }
7814 
7815 static void
7816 alloc_teardown(void) {
7817   basic_teardown();
7818 }
7819 
7820 /* Test the effects of allocation failures on xml declaration processing */
7821 START_TEST(test_alloc_parse_xdecl) {
7822   const char *text = "<?xml version='1.0' encoding='utf-8'?>\n"
7823                      "<doc>Hello, world</doc>";
7824   int i;
7825   const int max_alloc_count = 15;
7826 
7827   for (i = 0; i < max_alloc_count; i++) {
7828     allocation_count = i;
7829     XML_SetXmlDeclHandler(g_parser, dummy_xdecl_handler);
7830     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
7831         != XML_STATUS_ERROR)
7832       break;
7833     /* Resetting the parser is insufficient, because some memory
7834      * allocations are cached within the parser.  Instead we use
7835      * the teardown and setup routines to ensure that we have the
7836      * right sort of parser back in our hands.
7837      */
7838     alloc_teardown();
7839     alloc_setup();
7840   }
7841   if (i == 0)
7842     fail("Parse succeeded despite failing allocator");
7843   if (i == max_alloc_count)
7844     fail("Parse failed with max allocations");
7845 }
7846 END_TEST
7847 
7848 /* As above, but with an encoding big enough to cause storing the
7849  * version information to expand the string pool being used.
7850  */
7851 static int XMLCALL
7852 long_encoding_handler(void *userData, const XML_Char *encoding,
7853                       XML_Encoding *info) {
7854   int i;
7855 
7856   UNUSED_P(userData);
7857   UNUSED_P(encoding);
7858   for (i = 0; i < 256; i++)
7859     info->map[i] = i;
7860   info->data = NULL;
7861   info->convert = NULL;
7862   info->release = NULL;
7863   return XML_STATUS_OK;
7864 }
7865 
7866 START_TEST(test_alloc_parse_xdecl_2) {
7867   const char *text
7868       = "<?xml version='1.0' encoding='"
7869         /* Each line is 64 characters */
7870         "ThisIsAStupidlyLongEncodingNameIntendedToTriggerPoolGrowth123456"
7871         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7872         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7873         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7874         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7875         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7876         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7877         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7878         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7879         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7880         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7881         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7882         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7883         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7884         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7885         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMN"
7886         "'?>"
7887         "<doc>Hello, world</doc>";
7888   int i;
7889   const int max_alloc_count = 20;
7890 
7891   for (i = 0; i < max_alloc_count; i++) {
7892     allocation_count = i;
7893     XML_SetXmlDeclHandler(g_parser, dummy_xdecl_handler);
7894     XML_SetUnknownEncodingHandler(g_parser, long_encoding_handler, NULL);
7895     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
7896         != XML_STATUS_ERROR)
7897       break;
7898     /* See comment in test_alloc_parse_xdecl() */
7899     alloc_teardown();
7900     alloc_setup();
7901   }
7902   if (i == 0)
7903     fail("Parse succeeded despite failing allocator");
7904   if (i == max_alloc_count)
7905     fail("Parse failed with max allocations");
7906 }
7907 END_TEST
7908 
7909 /* Test the effects of allocation failures on a straightforward parse */
7910 START_TEST(test_alloc_parse_pi) {
7911   const char *text = "<?xml version='1.0' encoding='utf-8'?>\n"
7912                      "<?pi unknown?>\n"
7913                      "<doc>"
7914                      "Hello, world"
7915                      "</doc>";
7916   int i;
7917   const int max_alloc_count = 15;
7918 
7919   for (i = 0; i < max_alloc_count; i++) {
7920     allocation_count = i;
7921     XML_SetProcessingInstructionHandler(g_parser, dummy_pi_handler);
7922     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
7923         != XML_STATUS_ERROR)
7924       break;
7925     /* See comment in test_alloc_parse_xdecl() */
7926     alloc_teardown();
7927     alloc_setup();
7928   }
7929   if (i == 0)
7930     fail("Parse succeeded despite failing allocator");
7931   if (i == max_alloc_count)
7932     fail("Parse failed with max allocations");
7933 }
7934 END_TEST
7935 
7936 START_TEST(test_alloc_parse_pi_2) {
7937   const char *text = "<?xml version='1.0' encoding='utf-8'?>\n"
7938                      "<doc>"
7939                      "Hello, world"
7940                      "<?pi unknown?>\n"
7941                      "</doc>";
7942   int i;
7943   const int max_alloc_count = 15;
7944 
7945   for (i = 0; i < max_alloc_count; i++) {
7946     allocation_count = i;
7947     XML_SetProcessingInstructionHandler(g_parser, dummy_pi_handler);
7948     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
7949         != XML_STATUS_ERROR)
7950       break;
7951     /* See comment in test_alloc_parse_xdecl() */
7952     alloc_teardown();
7953     alloc_setup();
7954   }
7955   if (i == 0)
7956     fail("Parse succeeded despite failing allocator");
7957   if (i == max_alloc_count)
7958     fail("Parse failed with max allocations");
7959 }
7960 END_TEST
7961 
7962 START_TEST(test_alloc_parse_pi_3) {
7963   const char *text
7964       = "<?"
7965         /* 64 characters per line */
7966         "This processing instruction should be long enough to ensure that"
7967         "it triggers the growth of an internal string pool when the      "
7968         "allocator fails at a cruicial moment FGHIJKLMNOPABCDEFGHIJKLMNOP"
7969         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7970         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7971         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7972         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7973         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7974         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7975         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7976         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7977         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7978         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7979         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7980         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7981         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7982         "Q?><doc/>";
7983   int i;
7984   const int max_alloc_count = 20;
7985 
7986   for (i = 0; i < max_alloc_count; i++) {
7987     allocation_count = i;
7988     XML_SetProcessingInstructionHandler(g_parser, dummy_pi_handler);
7989     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
7990         != XML_STATUS_ERROR)
7991       break;
7992     /* See comment in test_alloc_parse_xdecl() */
7993     alloc_teardown();
7994     alloc_setup();
7995   }
7996   if (i == 0)
7997     fail("Parse succeeded despite failing allocator");
7998   if (i == max_alloc_count)
7999     fail("Parse failed with max allocations");
8000 }
8001 END_TEST
8002 
8003 START_TEST(test_alloc_parse_comment) {
8004   const char *text = "<?xml version='1.0' encoding='utf-8'?>\n"
8005                      "<!-- Test parsing this comment -->"
8006                      "<doc>Hi</doc>";
8007   int i;
8008   const int max_alloc_count = 15;
8009 
8010   for (i = 0; i < max_alloc_count; i++) {
8011     allocation_count = i;
8012     XML_SetCommentHandler(g_parser, dummy_comment_handler);
8013     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
8014         != XML_STATUS_ERROR)
8015       break;
8016     /* See comment in test_alloc_parse_xdecl() */
8017     alloc_teardown();
8018     alloc_setup();
8019   }
8020   if (i == 0)
8021     fail("Parse succeeded despite failing allocator");
8022   if (i == max_alloc_count)
8023     fail("Parse failed with max allocations");
8024 }
8025 END_TEST
8026 
8027 START_TEST(test_alloc_parse_comment_2) {
8028   const char *text = "<?xml version='1.0' encoding='utf-8'?>\n"
8029                      "<doc>"
8030                      "Hello, world"
8031                      "<!-- Parse this comment too -->"
8032                      "</doc>";
8033   int i;
8034   const int max_alloc_count = 15;
8035 
8036   for (i = 0; i < max_alloc_count; i++) {
8037     allocation_count = i;
8038     XML_SetCommentHandler(g_parser, dummy_comment_handler);
8039     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
8040         != XML_STATUS_ERROR)
8041       break;
8042     /* See comment in test_alloc_parse_xdecl() */
8043     alloc_teardown();
8044     alloc_setup();
8045   }
8046   if (i == 0)
8047     fail("Parse succeeded despite failing allocator");
8048   if (i == max_alloc_count)
8049     fail("Parse failed with max allocations");
8050 }
8051 END_TEST
8052 
8053 static int XMLCALL
8054 external_entity_duff_loader(XML_Parser parser, const XML_Char *context,
8055                             const XML_Char *base, const XML_Char *systemId,
8056                             const XML_Char *publicId) {
8057   XML_Parser new_parser;
8058   unsigned int i;
8059   const unsigned int max_alloc_count = 10;
8060 
8061   UNUSED_P(base);
8062   UNUSED_P(systemId);
8063   UNUSED_P(publicId);
8064   /* Try a few different allocation levels */
8065   for (i = 0; i < max_alloc_count; i++) {
8066     allocation_count = i;
8067     new_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
8068     if (new_parser != NULL) {
8069       XML_ParserFree(new_parser);
8070       break;
8071     }
8072   }
8073   if (i == 0)
8074     fail("External parser creation ignored failing allocator");
8075   else if (i == max_alloc_count)
8076     fail("Extern parser not created with max allocation count");
8077 
8078   /* Make sure other random allocation doesn't now fail */
8079   allocation_count = ALLOC_ALWAYS_SUCCEED;
8080 
8081   /* Make sure the failure code path is executed too */
8082   return XML_STATUS_ERROR;
8083 }
8084 
8085 /* Test that external parser creation running out of memory is
8086  * correctly reported.  Based on the external entity test cases.
8087  */
8088 START_TEST(test_alloc_create_external_parser) {
8089   const char *text = "<?xml version='1.0' encoding='us-ascii'?>\n"
8090                      "<!DOCTYPE doc SYSTEM 'foo'>\n"
8091                      "<doc>&entity;</doc>";
8092   char foo_text[] = "<!ELEMENT doc (#PCDATA)*>";
8093 
8094   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
8095   XML_SetUserData(g_parser, foo_text);
8096   XML_SetExternalEntityRefHandler(g_parser, external_entity_duff_loader);
8097   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
8098       != XML_STATUS_ERROR) {
8099     fail("External parser allocator returned success incorrectly");
8100   }
8101 }
8102 END_TEST
8103 
8104 /* More external parser memory allocation testing */
8105 START_TEST(test_alloc_run_external_parser) {
8106   const char *text = "<?xml version='1.0' encoding='us-ascii'?>\n"
8107                      "<!DOCTYPE doc SYSTEM 'foo'>\n"
8108                      "<doc>&entity;</doc>";
8109   char foo_text[] = "<!ELEMENT doc (#PCDATA)*>";
8110   unsigned int i;
8111   const unsigned int max_alloc_count = 15;
8112 
8113   for (i = 0; i < max_alloc_count; i++) {
8114     XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
8115     XML_SetUserData(g_parser, foo_text);
8116     XML_SetExternalEntityRefHandler(g_parser, external_entity_null_loader);
8117     allocation_count = i;
8118     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
8119         != XML_STATUS_ERROR)
8120       break;
8121     /* See comment in test_alloc_parse_xdecl() */
8122     alloc_teardown();
8123     alloc_setup();
8124   }
8125   if (i == 0)
8126     fail("Parsing ignored failing allocator");
8127   else if (i == max_alloc_count)
8128     fail("Parsing failed with allocation count 10");
8129 }
8130 END_TEST
8131 
8132 static int XMLCALL
8133 external_entity_dbl_handler(XML_Parser parser, const XML_Char *context,
8134                             const XML_Char *base, const XML_Char *systemId,
8135                             const XML_Char *publicId) {
8136   intptr_t callno = (intptr_t)XML_GetUserData(parser);
8137   const char *text;
8138   XML_Parser new_parser;
8139   int i;
8140   const int max_alloc_count = 20;
8141 
8142   UNUSED_P(base);
8143   UNUSED_P(systemId);
8144   UNUSED_P(publicId);
8145   if (callno == 0) {
8146     /* First time through, check how many calls to malloc occur */
8147     text = ("<!ELEMENT doc (e+)>\n"
8148             "<!ATTLIST doc xmlns CDATA #IMPLIED>\n"
8149             "<!ELEMENT e EMPTY>\n");
8150     allocation_count = 10000;
8151     new_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
8152     if (new_parser == NULL) {
8153       fail("Unable to allocate first external parser");
8154       return XML_STATUS_ERROR;
8155     }
8156     /* Stash the number of calls in the user data */
8157     XML_SetUserData(parser, (void *)(intptr_t)(10000 - allocation_count));
8158   } else {
8159     text = ("<?xml version='1.0' encoding='us-ascii'?>"
8160             "<e/>");
8161     /* Try at varying levels to exercise more code paths */
8162     for (i = 0; i < max_alloc_count; i++) {
8163       allocation_count = callno + i;
8164       new_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
8165       if (new_parser != NULL)
8166         break;
8167     }
8168     if (i == 0) {
8169       fail("Second external parser unexpectedly created");
8170       XML_ParserFree(new_parser);
8171       return XML_STATUS_ERROR;
8172     } else if (i == max_alloc_count) {
8173       fail("Second external parser not created");
8174       return XML_STATUS_ERROR;
8175     }
8176   }
8177 
8178   allocation_count = ALLOC_ALWAYS_SUCCEED;
8179   if (_XML_Parse_SINGLE_BYTES(new_parser, text, (int)strlen(text), XML_TRUE)
8180       == XML_STATUS_ERROR) {
8181     xml_failure(new_parser);
8182     return XML_STATUS_ERROR;
8183   }
8184   XML_ParserFree(new_parser);
8185   return XML_STATUS_OK;
8186 }
8187 
8188 /* Test that running out of memory in dtdCopy is correctly reported.
8189  * Based on test_default_ns_from_ext_subset_and_ext_ge()
8190  */
8191 START_TEST(test_alloc_dtd_copy_default_atts) {
8192   const char *text = "<?xml version='1.0'?>\n"
8193                      "<!DOCTYPE doc SYSTEM 'http://example.org/doc.dtd' [\n"
8194                      "  <!ENTITY en SYSTEM 'http://example.org/entity.ent'>\n"
8195                      "]>\n"
8196                      "<doc xmlns='http://example.org/ns1'>\n"
8197                      "&en;\n"
8198                      "</doc>";
8199 
8200   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
8201   XML_SetExternalEntityRefHandler(g_parser, external_entity_dbl_handler);
8202   XML_SetUserData(g_parser, NULL);
8203   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
8204       == XML_STATUS_ERROR)
8205     xml_failure(g_parser);
8206 }
8207 END_TEST
8208 
8209 static int XMLCALL
8210 external_entity_dbl_handler_2(XML_Parser parser, const XML_Char *context,
8211                               const XML_Char *base, const XML_Char *systemId,
8212                               const XML_Char *publicId) {
8213   intptr_t callno = (intptr_t)XML_GetUserData(parser);
8214   const char *text;
8215   XML_Parser new_parser;
8216   enum XML_Status rv;
8217 
8218   UNUSED_P(base);
8219   UNUSED_P(systemId);
8220   UNUSED_P(publicId);
8221   if (callno == 0) {
8222     /* Try different allocation levels for whole exercise */
8223     text = ("<!ELEMENT doc (e+)>\n"
8224             "<!ATTLIST doc xmlns CDATA #IMPLIED>\n"
8225             "<!ELEMENT e EMPTY>\n");
8226     XML_SetUserData(parser, (void *)(intptr_t)1);
8227     new_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
8228     if (new_parser == NULL)
8229       return XML_STATUS_ERROR;
8230     rv = _XML_Parse_SINGLE_BYTES(new_parser, text, (int)strlen(text), XML_TRUE);
8231   } else {
8232     /* Just run through once */
8233     text = ("<?xml version='1.0' encoding='us-ascii'?>"
8234             "<e/>");
8235     new_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
8236     if (new_parser == NULL)
8237       return XML_STATUS_ERROR;
8238     rv = _XML_Parse_SINGLE_BYTES(new_parser, text, (int)strlen(text), XML_TRUE);
8239   }
8240   XML_ParserFree(new_parser);
8241   if (rv == XML_STATUS_ERROR)
8242     return XML_STATUS_ERROR;
8243   return XML_STATUS_OK;
8244 }
8245 
8246 /* Test more external entity allocation failure paths */
8247 START_TEST(test_alloc_external_entity) {
8248   const char *text = "<?xml version='1.0'?>\n"
8249                      "<!DOCTYPE doc SYSTEM 'http://example.org/doc.dtd' [\n"
8250                      "  <!ENTITY en SYSTEM 'http://example.org/entity.ent'>\n"
8251                      "]>\n"
8252                      "<doc xmlns='http://example.org/ns1'>\n"
8253                      "&en;\n"
8254                      "</doc>";
8255   int i;
8256   const int alloc_test_max_repeats = 50;
8257 
8258   for (i = 0; i < alloc_test_max_repeats; i++) {
8259     allocation_count = -1;
8260     XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
8261     XML_SetExternalEntityRefHandler(g_parser, external_entity_dbl_handler_2);
8262     XML_SetUserData(g_parser, NULL);
8263     allocation_count = i;
8264     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
8265         == XML_STATUS_OK)
8266       break;
8267     /* See comment in test_alloc_parse_xdecl() */
8268     alloc_teardown();
8269     alloc_setup();
8270   }
8271   allocation_count = -1;
8272   if (i == 0)
8273     fail("External entity parsed despite duff allocator");
8274   if (i == alloc_test_max_repeats)
8275     fail("External entity not parsed at max allocation count");
8276 }
8277 END_TEST
8278 
8279 /* Test more allocation failure paths */
8280 static int XMLCALL
8281 external_entity_alloc_set_encoding(XML_Parser parser, const XML_Char *context,
8282                                    const XML_Char *base,
8283                                    const XML_Char *systemId,
8284                                    const XML_Char *publicId) {
8285   /* As for external_entity_loader() */
8286   const char *text = "<?xml encoding='iso-8859-3'?>"
8287                      "\xC3\xA9";
8288   XML_Parser ext_parser;
8289   enum XML_Status status;
8290 
8291   UNUSED_P(base);
8292   UNUSED_P(systemId);
8293   UNUSED_P(publicId);
8294   ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
8295   if (ext_parser == NULL)
8296     return XML_STATUS_ERROR;
8297   if (! XML_SetEncoding(ext_parser, XCS("utf-8"))) {
8298     XML_ParserFree(ext_parser);
8299     return XML_STATUS_ERROR;
8300   }
8301   status
8302       = _XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE);
8303   XML_ParserFree(ext_parser);
8304   if (status == XML_STATUS_ERROR)
8305     return XML_STATUS_ERROR;
8306   return XML_STATUS_OK;
8307 }
8308 
8309 START_TEST(test_alloc_ext_entity_set_encoding) {
8310   const char *text = "<!DOCTYPE doc [\n"
8311                      "  <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n"
8312                      "]>\n"
8313                      "<doc>&en;</doc>";
8314   int i;
8315   const int max_allocation_count = 30;
8316 
8317   for (i = 0; i < max_allocation_count; i++) {
8318     XML_SetExternalEntityRefHandler(g_parser,
8319                                     external_entity_alloc_set_encoding);
8320     allocation_count = i;
8321     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
8322         == XML_STATUS_OK)
8323       break;
8324     allocation_count = -1;
8325     /* See comment in test_alloc_parse_xdecl() */
8326     alloc_teardown();
8327     alloc_setup();
8328   }
8329   if (i == 0)
8330     fail("Encoding check succeeded despite failing allocator");
8331   if (i == max_allocation_count)
8332     fail("Encoding failed at max allocation count");
8333 }
8334 END_TEST
8335 
8336 static int XMLCALL
8337 unknown_released_encoding_handler(void *data, const XML_Char *encoding,
8338                                   XML_Encoding *info) {
8339   UNUSED_P(data);
8340   if (! xcstrcmp(encoding, XCS("unsupported-encoding"))) {
8341     int i;
8342 
8343     for (i = 0; i < 256; i++)
8344       info->map[i] = i;
8345     info->data = NULL;
8346     info->convert = NULL;
8347     info->release = dummy_release;
8348     return XML_STATUS_OK;
8349   }
8350   return XML_STATUS_ERROR;
8351 }
8352 
8353 /* Test the effects of allocation failure in internal entities.
8354  * Based on test_unknown_encoding_internal_entity
8355  */
8356 START_TEST(test_alloc_internal_entity) {
8357   const char *text = "<?xml version='1.0' encoding='unsupported-encoding'?>\n"
8358                      "<!DOCTYPE test [<!ENTITY foo 'bar'>]>\n"
8359                      "<test a='&foo;'/>";
8360   unsigned int i;
8361   const unsigned int max_alloc_count = 20;
8362 
8363   for (i = 0; i < max_alloc_count; i++) {
8364     allocation_count = i;
8365     XML_SetUnknownEncodingHandler(g_parser, unknown_released_encoding_handler,
8366                                   NULL);
8367     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
8368         != XML_STATUS_ERROR)
8369       break;
8370     /* See comment in test_alloc_parse_xdecl() */
8371     alloc_teardown();
8372     alloc_setup();
8373   }
8374   if (i == 0)
8375     fail("Internal entity worked despite failing allocations");
8376   else if (i == max_alloc_count)
8377     fail("Internal entity failed at max allocation count");
8378 }
8379 END_TEST
8380 
8381 /* Test the robustness against allocation failure of element handling
8382  * Based on test_dtd_default_handling().
8383  */
8384 START_TEST(test_alloc_dtd_default_handling) {
8385   const char *text = "<!DOCTYPE doc [\n"
8386                      "<!ENTITY e SYSTEM 'http://example.org/e'>\n"
8387                      "<!NOTATION n SYSTEM 'http://example.org/n'>\n"
8388                      "<!ENTITY e1 SYSTEM 'http://example.org/e' NDATA n>\n"
8389                      "<!ELEMENT doc (#PCDATA)>\n"
8390                      "<!ATTLIST doc a CDATA #IMPLIED>\n"
8391                      "<?pi in dtd?>\n"
8392                      "<!--comment in dtd-->\n"
8393                      "]>\n"
8394                      "<doc><![CDATA[text in doc]]></doc>";
8395   const XML_Char *expected = XCS("\n\n\n\n\n\n\n\n\n<doc>text in doc</doc>");
8396   CharData storage;
8397   int i;
8398   const int max_alloc_count = 25;
8399 
8400   for (i = 0; i < max_alloc_count; i++) {
8401     allocation_count = i;
8402     dummy_handler_flags = 0;
8403     XML_SetDefaultHandler(g_parser, accumulate_characters);
8404     XML_SetDoctypeDeclHandler(g_parser, dummy_start_doctype_handler,
8405                               dummy_end_doctype_handler);
8406     XML_SetEntityDeclHandler(g_parser, dummy_entity_decl_handler);
8407     XML_SetNotationDeclHandler(g_parser, dummy_notation_decl_handler);
8408     XML_SetElementDeclHandler(g_parser, dummy_element_decl_handler);
8409     XML_SetAttlistDeclHandler(g_parser, dummy_attlist_decl_handler);
8410     XML_SetProcessingInstructionHandler(g_parser, dummy_pi_handler);
8411     XML_SetCommentHandler(g_parser, dummy_comment_handler);
8412     XML_SetCdataSectionHandler(g_parser, dummy_start_cdata_handler,
8413                                dummy_end_cdata_handler);
8414     XML_SetUnparsedEntityDeclHandler(g_parser,
8415                                      dummy_unparsed_entity_decl_handler);
8416     CharData_Init(&storage);
8417     XML_SetUserData(g_parser, &storage);
8418     XML_SetCharacterDataHandler(g_parser, accumulate_characters);
8419     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
8420         != XML_STATUS_ERROR)
8421       break;
8422     /* See comment in test_alloc_parse_xdecl() */
8423     alloc_teardown();
8424     alloc_setup();
8425   }
8426   if (i == 0)
8427     fail("Default DTD parsed despite allocation failures");
8428   if (i == max_alloc_count)
8429     fail("Default DTD not parsed with maximum alloc count");
8430   CharData_CheckXMLChars(&storage, expected);
8431   if (dummy_handler_flags
8432       != (DUMMY_START_DOCTYPE_HANDLER_FLAG | DUMMY_END_DOCTYPE_HANDLER_FLAG
8433           | DUMMY_ENTITY_DECL_HANDLER_FLAG | DUMMY_NOTATION_DECL_HANDLER_FLAG
8434           | DUMMY_ELEMENT_DECL_HANDLER_FLAG | DUMMY_ATTLIST_DECL_HANDLER_FLAG
8435           | DUMMY_COMMENT_HANDLER_FLAG | DUMMY_PI_HANDLER_FLAG
8436           | DUMMY_START_CDATA_HANDLER_FLAG | DUMMY_END_CDATA_HANDLER_FLAG
8437           | DUMMY_UNPARSED_ENTITY_DECL_HANDLER_FLAG))
8438     fail("Not all handlers were called");
8439 }
8440 END_TEST
8441 
8442 /* Test robustness of XML_SetEncoding() with a failing allocator */
8443 START_TEST(test_alloc_explicit_encoding) {
8444   int i;
8445   const int max_alloc_count = 5;
8446 
8447   for (i = 0; i < max_alloc_count; i++) {
8448     allocation_count = i;
8449     if (XML_SetEncoding(g_parser, XCS("us-ascii")) == XML_STATUS_OK)
8450       break;
8451   }
8452   if (i == 0)
8453     fail("Encoding set despite failing allocator");
8454   else if (i == max_alloc_count)
8455     fail("Encoding not set at max allocation count");
8456 }
8457 END_TEST
8458 
8459 /* Test robustness of XML_SetBase against a failing allocator */
8460 START_TEST(test_alloc_set_base) {
8461   const XML_Char *new_base = XCS("/local/file/name.xml");
8462   int i;
8463   const int max_alloc_count = 5;
8464 
8465   for (i = 0; i < max_alloc_count; i++) {
8466     allocation_count = i;
8467     if (XML_SetBase(g_parser, new_base) == XML_STATUS_OK)
8468       break;
8469   }
8470   if (i == 0)
8471     fail("Base set despite failing allocator");
8472   else if (i == max_alloc_count)
8473     fail("Base not set with max allocation count");
8474 }
8475 END_TEST
8476 
8477 /* Test buffer extension in the face of a duff reallocator */
8478 START_TEST(test_alloc_realloc_buffer) {
8479   const char *text = get_buffer_test_text;
8480   void *buffer;
8481   int i;
8482   const int max_realloc_count = 10;
8483 
8484   /* Get a smallish buffer */
8485   for (i = 0; i < max_realloc_count; i++) {
8486     reallocation_count = i;
8487     buffer = XML_GetBuffer(g_parser, 1536);
8488     if (buffer == NULL)
8489       fail("1.5K buffer reallocation failed");
8490     assert(buffer != NULL);
8491     memcpy(buffer, text, strlen(text));
8492     if (XML_ParseBuffer(g_parser, (int)strlen(text), XML_FALSE)
8493         == XML_STATUS_OK)
8494       break;
8495     /* See comment in test_alloc_parse_xdecl() */
8496     alloc_teardown();
8497     alloc_setup();
8498   }
8499   reallocation_count = -1;
8500   if (i == 0)
8501     fail("Parse succeeded with no reallocation");
8502   else if (i == max_realloc_count)
8503     fail("Parse failed with max reallocation count");
8504 }
8505 END_TEST
8506 
8507 /* Same test for external entity parsers */
8508 static int XMLCALL
8509 external_entity_reallocator(XML_Parser parser, const XML_Char *context,
8510                             const XML_Char *base, const XML_Char *systemId,
8511                             const XML_Char *publicId) {
8512   const char *text = get_buffer_test_text;
8513   XML_Parser ext_parser;
8514   void *buffer;
8515   enum XML_Status status;
8516 
8517   UNUSED_P(base);
8518   UNUSED_P(systemId);
8519   UNUSED_P(publicId);
8520   ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
8521   if (ext_parser == NULL)
8522     fail("Could not create external entity parser");
8523 
8524   reallocation_count = (intptr_t)XML_GetUserData(parser);
8525   buffer = XML_GetBuffer(ext_parser, 1536);
8526   if (buffer == NULL)
8527     fail("Buffer allocation failed");
8528   assert(buffer != NULL);
8529   memcpy(buffer, text, strlen(text));
8530   status = XML_ParseBuffer(ext_parser, (int)strlen(text), XML_FALSE);
8531   reallocation_count = -1;
8532   XML_ParserFree(ext_parser);
8533   return (status == XML_STATUS_OK) ? XML_STATUS_OK : XML_STATUS_ERROR;
8534 }
8535 
8536 START_TEST(test_alloc_ext_entity_realloc_buffer) {
8537   const char *text = "<!DOCTYPE doc [\n"
8538                      "  <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n"
8539                      "]>\n"
8540                      "<doc>&en;</doc>";
8541   int i;
8542   const int max_realloc_count = 10;
8543 
8544   for (i = 0; i < max_realloc_count; i++) {
8545     XML_SetExternalEntityRefHandler(g_parser, external_entity_reallocator);
8546     XML_SetUserData(g_parser, (void *)(intptr_t)i);
8547     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
8548         == XML_STATUS_OK)
8549       break;
8550     /* See comment in test_alloc_parse_xdecl() */
8551     alloc_teardown();
8552     alloc_setup();
8553   }
8554   if (i == 0)
8555     fail("Succeeded with no reallocations");
8556   if (i == max_realloc_count)
8557     fail("Failed with max reallocations");
8558 }
8559 END_TEST
8560 
8561 /* Test elements with many attributes are handled correctly */
8562 START_TEST(test_alloc_realloc_many_attributes) {
8563   const char *text = "<!DOCTYPE doc [\n"
8564                      "<!ATTLIST doc za CDATA 'default'>\n"
8565                      "<!ATTLIST doc zb CDATA 'def2'>\n"
8566                      "<!ATTLIST doc zc CDATA 'def3'>\n"
8567                      "]>\n"
8568                      "<doc a='1'"
8569                      "     b='2'"
8570                      "     c='3'"
8571                      "     d='4'"
8572                      "     e='5'"
8573                      "     f='6'"
8574                      "     g='7'"
8575                      "     h='8'"
8576                      "     i='9'"
8577                      "     j='10'"
8578                      "     k='11'"
8579                      "     l='12'"
8580                      "     m='13'"
8581                      "     n='14'"
8582                      "     p='15'"
8583                      "     q='16'"
8584                      "     r='17'"
8585                      "     s='18'>"
8586                      "</doc>";
8587   int i;
8588   const int max_realloc_count = 10;
8589 
8590   for (i = 0; i < max_realloc_count; i++) {
8591     reallocation_count = i;
8592     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
8593         != XML_STATUS_ERROR)
8594       break;
8595     /* See comment in test_alloc_parse_xdecl() */
8596     alloc_teardown();
8597     alloc_setup();
8598   }
8599   if (i == 0)
8600     fail("Parse succeeded despite no reallocations");
8601   if (i == max_realloc_count)
8602     fail("Parse failed at max reallocations");
8603 }
8604 END_TEST
8605 
8606 /* Test handling of a public entity with failing allocator */
8607 START_TEST(test_alloc_public_entity_value) {
8608   const char *text = "<!DOCTYPE doc SYSTEM 'http://example.org/'>\n"
8609                      "<doc></doc>\n";
8610   char dtd_text[]
8611       = "<!ELEMENT doc EMPTY>\n"
8612         "<!ENTITY % e1 PUBLIC 'foo' 'bar.ent'>\n"
8613         "<!ENTITY % "
8614         /* Each line is 64 characters */
8615         "ThisIsAStupidlyLongParameterNameIntendedToTriggerPoolGrowth12345"
8616         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8617         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8618         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8619         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8620         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8621         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8622         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8623         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8624         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8625         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8626         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8627         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8628         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8629         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8630         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8631         " '%e1;'>\n"
8632         "%e1;\n";
8633   int i;
8634   const int max_alloc_count = 50;
8635 
8636   for (i = 0; i < max_alloc_count; i++) {
8637     allocation_count = i;
8638     dummy_handler_flags = 0;
8639     XML_SetUserData(g_parser, dtd_text);
8640     XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
8641     XML_SetExternalEntityRefHandler(g_parser, external_entity_public);
8642     /* Provoke a particular code path */
8643     XML_SetEntityDeclHandler(g_parser, dummy_entity_decl_handler);
8644     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
8645         != XML_STATUS_ERROR)
8646       break;
8647     /* See comment in test_alloc_parse_xdecl() */
8648     alloc_teardown();
8649     alloc_setup();
8650   }
8651   if (i == 0)
8652     fail("Parsing worked despite failing allocation");
8653   if (i == max_alloc_count)
8654     fail("Parsing failed at max allocation count");
8655   if (dummy_handler_flags != DUMMY_ENTITY_DECL_HANDLER_FLAG)
8656     fail("Entity declaration handler not called");
8657 }
8658 END_TEST
8659 
8660 START_TEST(test_alloc_realloc_subst_public_entity_value) {
8661   const char *text = "<!DOCTYPE doc SYSTEM 'http://example.org/'>\n"
8662                      "<doc></doc>\n";
8663   char dtd_text[]
8664       = "<!ELEMENT doc EMPTY>\n"
8665         "<!ENTITY % "
8666         /* Each line is 64 characters */
8667         "ThisIsAStupidlyLongParameterNameIntendedToTriggerPoolGrowth12345"
8668         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8669         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8670         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8671         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8672         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8673         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8674         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8675         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8676         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8677         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8678         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8679         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8680         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8681         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8682         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8683         " PUBLIC 'foo' 'bar.ent'>\n"
8684         "%ThisIsAStupidlyLongParameterNameIntendedToTriggerPoolGrowth12345"
8685         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8686         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8687         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8688         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8689         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8690         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8691         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8692         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8693         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8694         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8695         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8696         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8697         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8698         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8699         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP;";
8700   int i;
8701   const int max_realloc_count = 10;
8702 
8703   for (i = 0; i < max_realloc_count; i++) {
8704     reallocation_count = i;
8705     XML_SetUserData(g_parser, dtd_text);
8706     XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
8707     XML_SetExternalEntityRefHandler(g_parser, external_entity_public);
8708     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
8709         != XML_STATUS_ERROR)
8710       break;
8711     /* See comment in test_alloc_parse_xdecl() */
8712     alloc_teardown();
8713     alloc_setup();
8714   }
8715   if (i == 0)
8716     fail("Parsing worked despite failing reallocation");
8717   if (i == max_realloc_count)
8718     fail("Parsing failed at max reallocation count");
8719 }
8720 END_TEST
8721 
8722 START_TEST(test_alloc_parse_public_doctype) {
8723   const char *text
8724       = "<?xml version='1.0' encoding='utf-8'?>\n"
8725         "<!DOCTYPE doc PUBLIC '"
8726         /* 64 characters per line */
8727         "http://example.com/a/long/enough/name/to/trigger/pool/growth/zz/"
8728         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8729         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8730         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8731         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8732         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8733         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8734         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8735         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8736         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8737         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8738         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8739         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8740         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8741         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8742         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8743         "' 'test'>\n"
8744         "<doc></doc>";
8745   int i;
8746   const int max_alloc_count = 25;
8747 
8748   for (i = 0; i < max_alloc_count; i++) {
8749     allocation_count = i;
8750     dummy_handler_flags = 0;
8751     XML_SetDoctypeDeclHandler(g_parser, dummy_start_doctype_decl_handler,
8752                               dummy_end_doctype_decl_handler);
8753     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
8754         != XML_STATUS_ERROR)
8755       break;
8756     /* See comment in test_alloc_parse_xdecl() */
8757     alloc_teardown();
8758     alloc_setup();
8759   }
8760   if (i == 0)
8761     fail("Parse succeeded despite failing allocator");
8762   if (i == max_alloc_count)
8763     fail("Parse failed at maximum allocation count");
8764   if (dummy_handler_flags
8765       != (DUMMY_START_DOCTYPE_DECL_HANDLER_FLAG
8766           | DUMMY_END_DOCTYPE_DECL_HANDLER_FLAG))
8767     fail("Doctype handler functions not called");
8768 }
8769 END_TEST
8770 
8771 START_TEST(test_alloc_parse_public_doctype_long_name) {
8772   const char *text
8773       = "<?xml version='1.0' encoding='utf-8'?>\n"
8774         "<!DOCTYPE doc PUBLIC 'http://example.com/foo' '"
8775         /* 64 characters per line */
8776         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP"
8777         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP"
8778         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP"
8779         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP"
8780         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP"
8781         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP"
8782         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP"
8783         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP"
8784         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP"
8785         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP"
8786         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP"
8787         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP"
8788         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP"
8789         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP"
8790         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP"
8791         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP"
8792         "'>\n"
8793         "<doc></doc>";
8794   int i;
8795   const int max_alloc_count = 25;
8796 
8797   for (i = 0; i < max_alloc_count; i++) {
8798     allocation_count = i;
8799     XML_SetDoctypeDeclHandler(g_parser, dummy_start_doctype_decl_handler,
8800                               dummy_end_doctype_decl_handler);
8801     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
8802         != XML_STATUS_ERROR)
8803       break;
8804     /* See comment in test_alloc_parse_xdecl() */
8805     alloc_teardown();
8806     alloc_setup();
8807   }
8808   if (i == 0)
8809     fail("Parse succeeded despite failing allocator");
8810   if (i == max_alloc_count)
8811     fail("Parse failed at maximum allocation count");
8812 }
8813 END_TEST
8814 
8815 static int XMLCALL
8816 external_entity_alloc(XML_Parser parser, const XML_Char *context,
8817                       const XML_Char *base, const XML_Char *systemId,
8818                       const XML_Char *publicId) {
8819   const char *text = (const char *)XML_GetUserData(parser);
8820   XML_Parser ext_parser;
8821   int parse_res;
8822 
8823   UNUSED_P(base);
8824   UNUSED_P(systemId);
8825   UNUSED_P(publicId);
8826   ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
8827   if (ext_parser == NULL)
8828     return XML_STATUS_ERROR;
8829   parse_res
8830       = _XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE);
8831   XML_ParserFree(ext_parser);
8832   return parse_res;
8833 }
8834 
8835 /* Test foreign DTD handling */
8836 START_TEST(test_alloc_set_foreign_dtd) {
8837   const char *text1 = "<?xml version='1.0' encoding='us-ascii'?>\n"
8838                       "<doc>&entity;</doc>";
8839   char text2[] = "<!ELEMENT doc (#PCDATA)*>";
8840   int i;
8841   const int max_alloc_count = 25;
8842 
8843   for (i = 0; i < max_alloc_count; i++) {
8844     allocation_count = i;
8845     XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
8846     XML_SetUserData(g_parser, &text2);
8847     XML_SetExternalEntityRefHandler(g_parser, external_entity_alloc);
8848     if (XML_UseForeignDTD(g_parser, XML_TRUE) != XML_ERROR_NONE)
8849       fail("Could not set foreign DTD");
8850     if (_XML_Parse_SINGLE_BYTES(g_parser, text1, (int)strlen(text1), XML_TRUE)
8851         != XML_STATUS_ERROR)
8852       break;
8853     /* See comment in test_alloc_parse_xdecl() */
8854     alloc_teardown();
8855     alloc_setup();
8856   }
8857   if (i == 0)
8858     fail("Parse succeeded despite failing allocator");
8859   if (i == max_alloc_count)
8860     fail("Parse failed at maximum allocation count");
8861 }
8862 END_TEST
8863 
8864 /* Test based on ibm/valid/P32/ibm32v04.xml */
8865 START_TEST(test_alloc_attribute_enum_value) {
8866   const char *text = "<?xml version='1.0' standalone='no'?>\n"
8867                      "<!DOCTYPE animal SYSTEM 'test.dtd'>\n"
8868                      "<animal>This is a \n    <a/>  \n\nyellow tiger</animal>";
8869   char dtd_text[] = "<!ELEMENT animal (#PCDATA|a)*>\n"
8870                     "<!ELEMENT a EMPTY>\n"
8871                     "<!ATTLIST animal xml:space (default|preserve) 'preserve'>";
8872   int i;
8873   const int max_alloc_count = 30;
8874 
8875   for (i = 0; i < max_alloc_count; i++) {
8876     allocation_count = i;
8877     XML_SetExternalEntityRefHandler(g_parser, external_entity_alloc);
8878     XML_SetUserData(g_parser, dtd_text);
8879     XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
8880     /* An attribute list handler provokes a different code path */
8881     XML_SetAttlistDeclHandler(g_parser, dummy_attlist_decl_handler);
8882     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
8883         != XML_STATUS_ERROR)
8884       break;
8885     /* See comment in test_alloc_parse_xdecl() */
8886     alloc_teardown();
8887     alloc_setup();
8888   }
8889   if (i == 0)
8890     fail("Parse succeeded despite failing allocator");
8891   if (i == max_alloc_count)
8892     fail("Parse failed at maximum allocation count");
8893 }
8894 END_TEST
8895 
8896 /* Test attribute enums sufficient to overflow the string pool */
8897 START_TEST(test_alloc_realloc_attribute_enum_value) {
8898   const char *text = "<?xml version='1.0' standalone='no'?>\n"
8899                      "<!DOCTYPE animal SYSTEM 'test.dtd'>\n"
8900                      "<animal>This is a yellow tiger</animal>";
8901   /* We wish to define a collection of attribute enums that will
8902    * cause the string pool storing them to have to expand.  This
8903    * means more than 1024 bytes, including the parentheses and
8904    * separator bars.
8905    */
8906   char dtd_text[]
8907       = "<!ELEMENT animal (#PCDATA)*>\n"
8908         "<!ATTLIST animal thing "
8909         "(default"
8910         /* Each line is 64 characters */
8911         "|ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8912         "|BBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8913         "|CBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8914         "|DBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8915         "|EBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8916         "|FBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8917         "|GBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8918         "|HBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8919         "|IBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8920         "|JBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8921         "|KBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8922         "|LBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8923         "|MBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8924         "|NBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8925         "|OBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8926         "|PBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO)"
8927         " 'default'>";
8928   int i;
8929   const int max_realloc_count = 10;
8930 
8931   for (i = 0; i < max_realloc_count; i++) {
8932     reallocation_count = i;
8933     XML_SetExternalEntityRefHandler(g_parser, external_entity_alloc);
8934     XML_SetUserData(g_parser, dtd_text);
8935     XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
8936     /* An attribute list handler provokes a different code path */
8937     XML_SetAttlistDeclHandler(g_parser, dummy_attlist_decl_handler);
8938     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
8939         != XML_STATUS_ERROR)
8940       break;
8941     /* See comment in test_alloc_parse_xdecl() */
8942     alloc_teardown();
8943     alloc_setup();
8944   }
8945   if (i == 0)
8946     fail("Parse succeeded despite failing reallocator");
8947   if (i == max_realloc_count)
8948     fail("Parse failed at maximum reallocation count");
8949 }
8950 END_TEST
8951 
8952 /* Test attribute enums in a #IMPLIED attribute forcing pool growth */
8953 START_TEST(test_alloc_realloc_implied_attribute) {
8954   /* Forcing this particular code path is a balancing act.  The
8955    * addition of the closing parenthesis and terminal NUL must be
8956    * what pushes the string of enums over the 1024-byte limit,
8957    * otherwise a different code path will pick up the realloc.
8958    */
8959   const char *text
8960       = "<!DOCTYPE doc [\n"
8961         "<!ELEMENT doc EMPTY>\n"
8962         "<!ATTLIST doc a "
8963         /* Each line is 64 characters */
8964         "(ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8965         "|BBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8966         "|CBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8967         "|DBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8968         "|EBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8969         "|FBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8970         "|GBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8971         "|HBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8972         "|IBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8973         "|JBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8974         "|KBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8975         "|LBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8976         "|MBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8977         "|NBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8978         "|OBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8979         "|PBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMN)"
8980         " #IMPLIED>\n"
8981         "]><doc/>";
8982   int i;
8983   const int max_realloc_count = 10;
8984 
8985   for (i = 0; i < max_realloc_count; i++) {
8986     reallocation_count = i;
8987     XML_SetAttlistDeclHandler(g_parser, dummy_attlist_decl_handler);
8988     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
8989         != XML_STATUS_ERROR)
8990       break;
8991     /* See comment in test_alloc_parse_xdecl() */
8992     alloc_teardown();
8993     alloc_setup();
8994   }
8995   if (i == 0)
8996     fail("Parse succeeded despite failing reallocator");
8997   if (i == max_realloc_count)
8998     fail("Parse failed at maximum reallocation count");
8999 }
9000 END_TEST
9001 
9002 /* Test attribute enums in a defaulted attribute forcing pool growth */
9003 START_TEST(test_alloc_realloc_default_attribute) {
9004   /* Forcing this particular code path is a balancing act.  The
9005    * addition of the closing parenthesis and terminal NUL must be
9006    * what pushes the string of enums over the 1024-byte limit,
9007    * otherwise a different code path will pick up the realloc.
9008    */
9009   const char *text
9010       = "<!DOCTYPE doc [\n"
9011         "<!ELEMENT doc EMPTY>\n"
9012         "<!ATTLIST doc a "
9013         /* Each line is 64 characters */
9014         "(ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
9015         "|BBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
9016         "|CBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
9017         "|DBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
9018         "|EBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
9019         "|FBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
9020         "|GBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
9021         "|HBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
9022         "|IBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
9023         "|JBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
9024         "|KBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
9025         "|LBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
9026         "|MBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
9027         "|NBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
9028         "|OBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
9029         "|PBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMN)"
9030         " 'ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO'"
9031         ">\n]><doc/>";
9032   int i;
9033   const int max_realloc_count = 10;
9034 
9035   for (i = 0; i < max_realloc_count; i++) {
9036     reallocation_count = i;
9037     XML_SetAttlistDeclHandler(g_parser, dummy_attlist_decl_handler);
9038     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
9039         != XML_STATUS_ERROR)
9040       break;
9041     /* See comment in test_alloc_parse_xdecl() */
9042     alloc_teardown();
9043     alloc_setup();
9044   }
9045   if (i == 0)
9046     fail("Parse succeeded despite failing reallocator");
9047   if (i == max_realloc_count)
9048     fail("Parse failed at maximum reallocation count");
9049 }
9050 END_TEST
9051 
9052 /* Test long notation name with dodgy allocator */
9053 START_TEST(test_alloc_notation) {
9054   const char *text
9055       = "<!DOCTYPE doc [\n"
9056         "<!NOTATION "
9057         /* Each line is 64 characters */
9058         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9059         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9060         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9061         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9062         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9063         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9064         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9065         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9066         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9067         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9068         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9069         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9070         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9071         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9072         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9073         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9074         " SYSTEM 'http://example.org/n'>\n"
9075         "<!ENTITY e SYSTEM 'http://example.org/e' NDATA "
9076         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9077         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9078         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9079         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9080         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9081         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9082         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9083         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9084         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9085         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9086         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9087         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9088         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9089         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9090         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9091         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9092         ">\n"
9093         "<!ELEMENT doc EMPTY>\n"
9094         "]>\n<doc/>";
9095   int i;
9096   const int max_alloc_count = 20;
9097 
9098   for (i = 0; i < max_alloc_count; i++) {
9099     allocation_count = i;
9100     dummy_handler_flags = 0;
9101     XML_SetNotationDeclHandler(g_parser, dummy_notation_decl_handler);
9102     XML_SetEntityDeclHandler(g_parser, dummy_entity_decl_handler);
9103     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
9104         != XML_STATUS_ERROR)
9105       break;
9106     /* See comment in test_alloc_parse_xdecl() */
9107     alloc_teardown();
9108     alloc_setup();
9109   }
9110   if (i == 0)
9111     fail("Parse succeeded despite allocation failures");
9112   if (i == max_alloc_count)
9113     fail("Parse failed at maximum allocation count");
9114   if (dummy_handler_flags
9115       != (DUMMY_ENTITY_DECL_HANDLER_FLAG | DUMMY_NOTATION_DECL_HANDLER_FLAG))
9116     fail("Entity declaration handler not called");
9117 }
9118 END_TEST
9119 
9120 /* Test public notation with dodgy allocator */
9121 START_TEST(test_alloc_public_notation) {
9122   const char *text
9123       = "<!DOCTYPE doc [\n"
9124         "<!NOTATION note PUBLIC '"
9125         /* 64 characters per line */
9126         "http://example.com/a/long/enough/name/to/trigger/pool/growth/zz/"
9127         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9128         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9129         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9130         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9131         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9132         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9133         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9134         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9135         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9136         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9137         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9138         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9139         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9140         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9141         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9142         "' 'foo'>\n"
9143         "<!ENTITY e SYSTEM 'http://example.com/e' NDATA note>\n"
9144         "<!ELEMENT doc EMPTY>\n"
9145         "]>\n<doc/>";
9146   int i;
9147   const int max_alloc_count = 20;
9148 
9149   for (i = 0; i < max_alloc_count; i++) {
9150     allocation_count = i;
9151     dummy_handler_flags = 0;
9152     XML_SetNotationDeclHandler(g_parser, dummy_notation_decl_handler);
9153     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
9154         != XML_STATUS_ERROR)
9155       break;
9156     /* See comment in test_alloc_parse_xdecl() */
9157     alloc_teardown();
9158     alloc_setup();
9159   }
9160   if (i == 0)
9161     fail("Parse succeeded despite allocation failures");
9162   if (i == max_alloc_count)
9163     fail("Parse failed at maximum allocation count");
9164   if (dummy_handler_flags != DUMMY_NOTATION_DECL_HANDLER_FLAG)
9165     fail("Notation handler not called");
9166 }
9167 END_TEST
9168 
9169 /* Test public notation with dodgy allocator */
9170 START_TEST(test_alloc_system_notation) {
9171   const char *text
9172       = "<!DOCTYPE doc [\n"
9173         "<!NOTATION note SYSTEM '"
9174         /* 64 characters per line */
9175         "http://example.com/a/long/enough/name/to/trigger/pool/growth/zz/"
9176         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9177         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9178         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9179         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9180         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9181         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9182         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9183         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9184         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9185         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9186         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9187         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9188         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9189         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9190         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
9191         "'>\n"
9192         "<!ENTITY e SYSTEM 'http://example.com/e' NDATA note>\n"
9193         "<!ELEMENT doc EMPTY>\n"
9194         "]>\n<doc/>";
9195   int i;
9196   const int max_alloc_count = 20;
9197 
9198   for (i = 0; i < max_alloc_count; i++) {
9199     allocation_count = i;
9200     dummy_handler_flags = 0;
9201     XML_SetNotationDeclHandler(g_parser, dummy_notation_decl_handler);
9202     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
9203         != XML_STATUS_ERROR)
9204       break;
9205     /* See comment in test_alloc_parse_xdecl() */
9206     alloc_teardown();
9207     alloc_setup();
9208   }
9209   if (i == 0)
9210     fail("Parse succeeded despite allocation failures");
9211   if (i == max_alloc_count)
9212     fail("Parse failed at maximum allocation count");
9213   if (dummy_handler_flags != DUMMY_NOTATION_DECL_HANDLER_FLAG)
9214     fail("Notation handler not called");
9215 }
9216 END_TEST
9217 
9218 START_TEST(test_alloc_nested_groups) {
9219   const char *text
9220       = "<!DOCTYPE doc [\n"
9221         "<!ELEMENT doc "
9222         /* Sixteen elements per line */
9223         "(e,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,"
9224         "(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?"
9225         "))))))))))))))))))))))))))))))))>\n"
9226         "<!ELEMENT e EMPTY>"
9227         "]>\n"
9228         "<doc><e/></doc>";
9229   CharData storage;
9230   int i;
9231   const int max_alloc_count = 20;
9232 
9233   for (i = 0; i < max_alloc_count; i++) {
9234     allocation_count = i;
9235     CharData_Init(&storage);
9236     XML_SetElementDeclHandler(g_parser, dummy_element_decl_handler);
9237     XML_SetStartElementHandler(g_parser, record_element_start_handler);
9238     XML_SetUserData(g_parser, &storage);
9239     dummy_handler_flags = 0;
9240     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
9241         != XML_STATUS_ERROR)
9242       break;
9243     /* See comment in test_alloc_parse_xdecl() */
9244     alloc_teardown();
9245     alloc_setup();
9246   }
9247 
9248   if (i == 0)
9249     fail("Parse succeeded despite failing reallocator");
9250   if (i == max_alloc_count)
9251     fail("Parse failed at maximum reallocation count");
9252   CharData_CheckXMLChars(&storage, XCS("doce"));
9253   if (dummy_handler_flags != DUMMY_ELEMENT_DECL_HANDLER_FLAG)
9254     fail("Element handler not fired");
9255 }
9256 END_TEST
9257 
9258 START_TEST(test_alloc_realloc_nested_groups) {
9259   const char *text
9260       = "<!DOCTYPE doc [\n"
9261         "<!ELEMENT doc "
9262         /* Sixteen elements per line */
9263         "(e,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,"
9264         "(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?"
9265         "))))))))))))))))))))))))))))))))>\n"
9266         "<!ELEMENT e EMPTY>"
9267         "]>\n"
9268         "<doc><e/></doc>";
9269   CharData storage;
9270   int i;
9271   const int max_realloc_count = 10;
9272 
9273   for (i = 0; i < max_realloc_count; i++) {
9274     reallocation_count = i;
9275     CharData_Init(&storage);
9276     XML_SetElementDeclHandler(g_parser, dummy_element_decl_handler);
9277     XML_SetStartElementHandler(g_parser, record_element_start_handler);
9278     XML_SetUserData(g_parser, &storage);
9279     dummy_handler_flags = 0;
9280     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
9281         != XML_STATUS_ERROR)
9282       break;
9283     /* See comment in test_alloc_parse_xdecl() */
9284     alloc_teardown();
9285     alloc_setup();
9286   }
9287 
9288   if (i == 0)
9289     fail("Parse succeeded despite failing reallocator");
9290   if (i == max_realloc_count)
9291     fail("Parse failed at maximum reallocation count");
9292   CharData_CheckXMLChars(&storage, XCS("doce"));
9293   if (dummy_handler_flags != DUMMY_ELEMENT_DECL_HANDLER_FLAG)
9294     fail("Element handler not fired");
9295 }
9296 END_TEST
9297 
9298 START_TEST(test_alloc_large_group) {
9299   const char *text = "<!DOCTYPE doc [\n"
9300                      "<!ELEMENT doc ("
9301                      "a1|a2|a3|a4|a5|a6|a7|a8|"
9302                      "b1|b2|b3|b4|b5|b6|b7|b8|"
9303                      "c1|c2|c3|c4|c5|c6|c7|c8|"
9304                      "d1|d2|d3|d4|d5|d6|d7|d8|"
9305                      "e1"
9306                      ")+>\n"
9307                      "]>\n"
9308                      "<doc>\n"
9309                      "<a1/>\n"
9310                      "</doc>\n";
9311   int i;
9312   const int max_alloc_count = 50;
9313 
9314   for (i = 0; i < max_alloc_count; i++) {
9315     allocation_count = i;
9316     XML_SetElementDeclHandler(g_parser, dummy_element_decl_handler);
9317     dummy_handler_flags = 0;
9318     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
9319         != XML_STATUS_ERROR)
9320       break;
9321     /* See comment in test_alloc_parse_xdecl() */
9322     alloc_teardown();
9323     alloc_setup();
9324   }
9325   if (i == 0)
9326     fail("Parse succeeded despite failing allocator");
9327   if (i == max_alloc_count)
9328     fail("Parse failed at maximum allocation count");
9329   if (dummy_handler_flags != DUMMY_ELEMENT_DECL_HANDLER_FLAG)
9330     fail("Element handler flag not raised");
9331 }
9332 END_TEST
9333 
9334 START_TEST(test_alloc_realloc_group_choice) {
9335   const char *text = "<!DOCTYPE doc [\n"
9336                      "<!ELEMENT doc ("
9337                      "a1|a2|a3|a4|a5|a6|a7|a8|"
9338                      "b1|b2|b3|b4|b5|b6|b7|b8|"
9339                      "c1|c2|c3|c4|c5|c6|c7|c8|"
9340                      "d1|d2|d3|d4|d5|d6|d7|d8|"
9341                      "e1"
9342                      ")+>\n"
9343                      "]>\n"
9344                      "<doc>\n"
9345                      "<a1/>\n"
9346                      "<b2 attr='foo'>This is a foo</b2>\n"
9347                      "<c3></c3>\n"
9348                      "</doc>\n";
9349   int i;
9350   const int max_realloc_count = 10;
9351 
9352   for (i = 0; i < max_realloc_count; i++) {
9353     reallocation_count = i;
9354     XML_SetElementDeclHandler(g_parser, dummy_element_decl_handler);
9355     dummy_handler_flags = 0;
9356     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
9357         != XML_STATUS_ERROR)
9358       break;
9359     /* See comment in test_alloc_parse_xdecl() */
9360     alloc_teardown();
9361     alloc_setup();
9362   }
9363   if (i == 0)
9364     fail("Parse succeeded despite failing reallocator");
9365   if (i == max_realloc_count)
9366     fail("Parse failed at maximum reallocation count");
9367   if (dummy_handler_flags != DUMMY_ELEMENT_DECL_HANDLER_FLAG)
9368     fail("Element handler flag not raised");
9369 }
9370 END_TEST
9371 
9372 START_TEST(test_alloc_pi_in_epilog) {
9373   const char *text = "<doc></doc>\n"
9374                      "<?pi in epilog?>";
9375   int i;
9376   const int max_alloc_count = 15;
9377 
9378   for (i = 0; i < max_alloc_count; i++) {
9379     allocation_count = i;
9380     XML_SetProcessingInstructionHandler(g_parser, dummy_pi_handler);
9381     dummy_handler_flags = 0;
9382     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
9383         != XML_STATUS_ERROR)
9384       break;
9385     /* See comment in test_alloc_parse_xdecl() */
9386     alloc_teardown();
9387     alloc_setup();
9388   }
9389   if (i == 0)
9390     fail("Parse completed despite failing allocator");
9391   if (i == max_alloc_count)
9392     fail("Parse failed at maximum allocation count");
9393   if (dummy_handler_flags != DUMMY_PI_HANDLER_FLAG)
9394     fail("Processing instruction handler not invoked");
9395 }
9396 END_TEST
9397 
9398 START_TEST(test_alloc_comment_in_epilog) {
9399   const char *text = "<doc></doc>\n"
9400                      "<!-- comment in epilog -->";
9401   int i;
9402   const int max_alloc_count = 15;
9403 
9404   for (i = 0; i < max_alloc_count; i++) {
9405     allocation_count = i;
9406     XML_SetCommentHandler(g_parser, dummy_comment_handler);
9407     dummy_handler_flags = 0;
9408     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
9409         != XML_STATUS_ERROR)
9410       break;
9411     /* See comment in test_alloc_parse_xdecl() */
9412     alloc_teardown();
9413     alloc_setup();
9414   }
9415   if (i == 0)
9416     fail("Parse completed despite failing allocator");
9417   if (i == max_alloc_count)
9418     fail("Parse failed at maximum allocation count");
9419   if (dummy_handler_flags != DUMMY_COMMENT_HANDLER_FLAG)
9420     fail("Processing instruction handler not invoked");
9421 }
9422 END_TEST
9423 
9424 START_TEST(test_alloc_realloc_long_attribute_value) {
9425   const char *text
9426       = "<!DOCTYPE doc [<!ENTITY foo '"
9427         /* Each line is 64 characters */
9428         "This entity will be substituted as an attribute value, and is   "
9429         "calculated to be exactly long enough that the terminating NUL   "
9430         "that the library adds internally will trigger the string pool to"
9431         "grow. GHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9432         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9433         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9434         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9435         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9436         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9437         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9438         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9439         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9440         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9441         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9442         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9443         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9444         "'>]>\n"
9445         "<doc a='&foo;'></doc>";
9446   int i;
9447   const int max_realloc_count = 10;
9448 
9449   for (i = 0; i < max_realloc_count; i++) {
9450     reallocation_count = i;
9451     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
9452         != XML_STATUS_ERROR)
9453       break;
9454     /* See comment in test_alloc_parse_xdecl() */
9455     alloc_teardown();
9456     alloc_setup();
9457   }
9458   if (i == 0)
9459     fail("Parse succeeded despite failing reallocator");
9460   if (i == max_realloc_count)
9461     fail("Parse failed at maximum reallocation count");
9462 }
9463 END_TEST
9464 
9465 START_TEST(test_alloc_attribute_whitespace) {
9466   const char *text = "<doc a=' '></doc>";
9467   int i;
9468   const int max_alloc_count = 15;
9469 
9470   for (i = 0; i < max_alloc_count; i++) {
9471     allocation_count = i;
9472     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
9473         != XML_STATUS_ERROR)
9474       break;
9475     /* See comment in test_alloc_parse_xdecl() */
9476     alloc_teardown();
9477     alloc_setup();
9478   }
9479   if (i == 0)
9480     fail("Parse succeeded despite failing allocator");
9481   if (i == max_alloc_count)
9482     fail("Parse failed at maximum allocation count");
9483 }
9484 END_TEST
9485 
9486 START_TEST(test_alloc_attribute_predefined_entity) {
9487   const char *text = "<doc a='&amp;'></doc>";
9488   int i;
9489   const int max_alloc_count = 15;
9490 
9491   for (i = 0; i < max_alloc_count; i++) {
9492     allocation_count = i;
9493     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
9494         != XML_STATUS_ERROR)
9495       break;
9496     /* See comment in test_alloc_parse_xdecl() */
9497     alloc_teardown();
9498     alloc_setup();
9499   }
9500   if (i == 0)
9501     fail("Parse succeeded despite failing allocator");
9502   if (i == max_alloc_count)
9503     fail("Parse failed at maximum allocation count");
9504 }
9505 END_TEST
9506 
9507 /* Test that a character reference at the end of a suitably long
9508  * default value for an attribute can trigger pool growth, and recovers
9509  * if the allocator fails on it.
9510  */
9511 START_TEST(test_alloc_long_attr_default_with_char_ref) {
9512   const char *text
9513       = "<!DOCTYPE doc [<!ATTLIST doc a CDATA '"
9514         /* 64 characters per line */
9515         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9516         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9517         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9518         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9519         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9520         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9521         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9522         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9523         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9524         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9525         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9526         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9527         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9528         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9529         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9530         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHI"
9531         "&#x31;'>]>\n"
9532         "<doc/>";
9533   int i;
9534   const int max_alloc_count = 20;
9535 
9536   for (i = 0; i < max_alloc_count; i++) {
9537     allocation_count = i;
9538     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
9539         != XML_STATUS_ERROR)
9540       break;
9541     /* See comment in test_alloc_parse_xdecl() */
9542     alloc_teardown();
9543     alloc_setup();
9544   }
9545   if (i == 0)
9546     fail("Parse succeeded despite failing allocator");
9547   if (i == max_alloc_count)
9548     fail("Parse failed at maximum allocation count");
9549 }
9550 END_TEST
9551 
9552 /* Test that a long character reference substitution triggers a pool
9553  * expansion correctly for an attribute value.
9554  */
9555 START_TEST(test_alloc_long_attr_value) {
9556   const char *text
9557       = "<!DOCTYPE test [<!ENTITY foo '\n"
9558         /* 64 characters per line */
9559         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9560         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9561         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9562         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9563         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9564         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9565         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9566         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9567         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9568         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9569         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9570         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9571         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9572         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9573         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9574         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9575         "'>]>\n"
9576         "<test a='&foo;'/>";
9577   int i;
9578   const int max_alloc_count = 25;
9579 
9580   for (i = 0; i < max_alloc_count; i++) {
9581     allocation_count = i;
9582     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
9583         != XML_STATUS_ERROR)
9584       break;
9585     /* See comment in test_alloc_parse_xdecl() */
9586     alloc_teardown();
9587     alloc_setup();
9588   }
9589   if (i == 0)
9590     fail("Parse succeeded despite failing allocator");
9591   if (i == max_alloc_count)
9592     fail("Parse failed at maximum allocation count");
9593 }
9594 END_TEST
9595 
9596 /* Test that an error in a nested parameter entity substitution is
9597  * handled correctly.  It seems unlikely that the code path being
9598  * exercised can be reached purely by carefully crafted XML, but an
9599  * allocation error in the right place will definitely do it.
9600  */
9601 START_TEST(test_alloc_nested_entities) {
9602   const char *text = "<!DOCTYPE doc SYSTEM 'http://example.org/one.ent'>\n"
9603                      "<doc />";
9604   ExtFaults test_data
9605       = {"<!ENTITY % pe1 '"
9606          /* 64 characters per line */
9607          "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9608          "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9609          "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9610          "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9611          "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9612          "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9613          "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9614          "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9615          "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9616          "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9617          "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9618          "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9619          "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9620          "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9621          "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9622          "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9623          "'>\n"
9624          "<!ENTITY % pe2 '%pe1;'>\n"
9625          "%pe2;",
9626          "Memory Fail not faulted", NULL, XML_ERROR_NO_MEMORY};
9627 
9628   /* Causes an allocation error in a nested storeEntityValue() */
9629   allocation_count = 12;
9630   XML_SetUserData(g_parser, &test_data);
9631   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
9632   XML_SetExternalEntityRefHandler(g_parser, external_entity_faulter);
9633   expect_failure(text, XML_ERROR_EXTERNAL_ENTITY_HANDLING,
9634                  "Entity allocation failure not noted");
9635 }
9636 END_TEST
9637 
9638 START_TEST(test_alloc_realloc_param_entity_newline) {
9639   const char *text = "<!DOCTYPE doc SYSTEM 'http://example.org/'>\n"
9640                      "<doc/>";
9641   char dtd_text[]
9642       = "<!ENTITY % pe '<!ATTLIST doc att CDATA \""
9643         /* 64 characters per line */
9644         "This default value is carefully crafted so that the carriage    "
9645         "return right at the end of the entity string causes an internal "
9646         "string pool to have to grow.  This allows us to test the alloc  "
9647         "failure path from that point. OPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9648         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9649         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9650         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9651         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9652         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9653         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9654         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9655         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9656         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9657         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9658         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9659         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDE"
9660         "\">\n'>"
9661         "%pe;\n";
9662   int i;
9663   const int max_realloc_count = 5;
9664 
9665   for (i = 0; i < max_realloc_count; i++) {
9666     reallocation_count = i;
9667     XML_SetUserData(g_parser, dtd_text);
9668     XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
9669     XML_SetExternalEntityRefHandler(g_parser, external_entity_alloc);
9670     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
9671         != XML_STATUS_ERROR)
9672       break;
9673     /* See comment in test_alloc_parse_xdecl() */
9674     alloc_teardown();
9675     alloc_setup();
9676   }
9677   if (i == 0)
9678     fail("Parse succeeded despite failing reallocator");
9679   if (i == max_realloc_count)
9680     fail("Parse failed at maximum reallocation count");
9681 }
9682 END_TEST
9683 
9684 START_TEST(test_alloc_realloc_ce_extends_pe) {
9685   const char *text = "<!DOCTYPE doc SYSTEM 'http://example.org/'>\n"
9686                      "<doc/>";
9687   char dtd_text[]
9688       = "<!ENTITY % pe '<!ATTLIST doc att CDATA \""
9689         /* 64 characters per line */
9690         "This default value is carefully crafted so that the character   "
9691         "entity at the end causes an internal string pool to have to     "
9692         "grow.  This allows us to test the allocation failure path from  "
9693         "that point onwards. EFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9694         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9695         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9696         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9697         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9698         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9699         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9700         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9701         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9702         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9703         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9704         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9705         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFG&#x51;"
9706         "\">\n'>"
9707         "%pe;\n";
9708   int i;
9709   const int max_realloc_count = 5;
9710 
9711   for (i = 0; i < max_realloc_count; i++) {
9712     reallocation_count = i;
9713     XML_SetUserData(g_parser, dtd_text);
9714     XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
9715     XML_SetExternalEntityRefHandler(g_parser, external_entity_alloc);
9716     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
9717         != XML_STATUS_ERROR)
9718       break;
9719     /* See comment in test_alloc_parse_xdecl() */
9720     alloc_teardown();
9721     alloc_setup();
9722   }
9723   if (i == 0)
9724     fail("Parse succeeded despite failing reallocator");
9725   if (i == max_realloc_count)
9726     fail("Parse failed at maximum reallocation count");
9727 }
9728 END_TEST
9729 
9730 START_TEST(test_alloc_realloc_attributes) {
9731   const char *text = "<!DOCTYPE doc [\n"
9732                      "  <!ATTLIST doc\n"
9733                      "    a1  (a|b|c)   'a'\n"
9734                      "    a2  (foo|bar) #IMPLIED\n"
9735                      "    a3  NMTOKEN   #IMPLIED\n"
9736                      "    a4  NMTOKENS  #IMPLIED\n"
9737                      "    a5  ID        #IMPLIED\n"
9738                      "    a6  IDREF     #IMPLIED\n"
9739                      "    a7  IDREFS    #IMPLIED\n"
9740                      "    a8  ENTITY    #IMPLIED\n"
9741                      "    a9  ENTITIES  #IMPLIED\n"
9742                      "    a10 CDATA     #IMPLIED\n"
9743                      "  >]>\n"
9744                      "<doc>wombat</doc>\n";
9745   int i;
9746   const int max_realloc_count = 5;
9747 
9748   for (i = 0; i < max_realloc_count; i++) {
9749     reallocation_count = i;
9750     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
9751         != XML_STATUS_ERROR)
9752       break;
9753     /* See comment in test_alloc_parse_xdecl() */
9754     alloc_teardown();
9755     alloc_setup();
9756   }
9757 
9758   if (i == 0)
9759     fail("Parse succeeded despite failing reallocator");
9760   if (i == max_realloc_count)
9761     fail("Parse failed at maximum reallocation count");
9762 }
9763 END_TEST
9764 
9765 START_TEST(test_alloc_long_doc_name) {
9766   const char *text =
9767       /* 64 characters per line */
9768       "<LongRootElementNameThatWillCauseTheNextAllocationToExpandTheStr"
9769       "ingPoolForTheDTDQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9770       "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9771       "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9772       "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9773       "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9774       "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9775       "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9776       "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9777       "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9778       "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9779       "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9780       "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9781       "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9782       "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9783       "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9784       " a='1'/>";
9785   int i;
9786   const int max_alloc_count = 20;
9787 
9788   for (i = 0; i < max_alloc_count; i++) {
9789     allocation_count = i;
9790     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
9791         != XML_STATUS_ERROR)
9792       break;
9793     /* See comment in test_alloc_parse_xdecl() */
9794     alloc_teardown();
9795     alloc_setup();
9796   }
9797   if (i == 0)
9798     fail("Parsing worked despite failing reallocations");
9799   else if (i == max_alloc_count)
9800     fail("Parsing failed even at max reallocation count");
9801 }
9802 END_TEST
9803 
9804 START_TEST(test_alloc_long_base) {
9805   const char *text = "<!DOCTYPE doc [\n"
9806                      "  <!ENTITY e SYSTEM 'foo'>\n"
9807                      "]>\n"
9808                      "<doc>&e;</doc>";
9809   char entity_text[] = "Hello world";
9810   const XML_Char *base =
9811       /* 64 characters per line */
9812       /* clang-format off */
9813         XCS("LongBaseURI/that/will/overflow/an/internal/buffer/and/cause/it/t")
9814         XCS("o/have/to/grow/PQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/")
9815         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/")
9816         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/")
9817         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/")
9818         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/")
9819         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/")
9820         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/")
9821         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/")
9822         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/")
9823         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/")
9824         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/")
9825         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/")
9826         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/")
9827         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/")
9828         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/");
9829   /* clang-format on */
9830   int i;
9831   const int max_alloc_count = 25;
9832 
9833   for (i = 0; i < max_alloc_count; i++) {
9834     allocation_count = i;
9835     XML_SetUserData(g_parser, entity_text);
9836     XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
9837     XML_SetExternalEntityRefHandler(g_parser, external_entity_alloc);
9838     if (XML_SetBase(g_parser, base) == XML_STATUS_ERROR) {
9839       XML_ParserReset(g_parser, NULL);
9840       continue;
9841     }
9842     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
9843         != XML_STATUS_ERROR)
9844       break;
9845     /* See comment in test_alloc_parse_xdecl() */
9846     alloc_teardown();
9847     alloc_setup();
9848   }
9849   if (i == 0)
9850     fail("Parsing worked despite failing allocations");
9851   else if (i == max_alloc_count)
9852     fail("Parsing failed even at max allocation count");
9853 }
9854 END_TEST
9855 
9856 START_TEST(test_alloc_long_public_id) {
9857   const char *text
9858       = "<!DOCTYPE doc [\n"
9859         "  <!ENTITY e PUBLIC '"
9860         /* 64 characters per line */
9861         "LongPublicIDThatShouldResultInAnInternalStringPoolGrowingAtASpec"
9862         "ificMomentKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9863         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9864         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9865         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9866         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9867         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9868         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9869         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9870         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9871         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9872         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9873         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9874         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9875         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9876         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9877         "' 'bar'>\n"
9878         "]>\n"
9879         "<doc>&e;</doc>";
9880   char entity_text[] = "Hello world";
9881   int i;
9882   const int max_alloc_count = 40;
9883 
9884   for (i = 0; i < max_alloc_count; i++) {
9885     allocation_count = i;
9886     XML_SetUserData(g_parser, entity_text);
9887     XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
9888     XML_SetExternalEntityRefHandler(g_parser, external_entity_alloc);
9889     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
9890         != XML_STATUS_ERROR)
9891       break;
9892     /* See comment in test_alloc_parse_xdecl() */
9893     alloc_teardown();
9894     alloc_setup();
9895   }
9896   if (i == 0)
9897     fail("Parsing worked despite failing allocations");
9898   else if (i == max_alloc_count)
9899     fail("Parsing failed even at max allocation count");
9900 }
9901 END_TEST
9902 
9903 START_TEST(test_alloc_long_entity_value) {
9904   const char *text
9905       = "<!DOCTYPE doc [\n"
9906         "  <!ENTITY e1 '"
9907         /* 64 characters per line */
9908         "Long entity value that should provoke a string pool to grow whil"
9909         "e setting up to parse the external entity below. xyz0123456789AB"
9910         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9911         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9912         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9913         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9914         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9915         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9916         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9917         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9918         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9919         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9920         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9921         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9922         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9923         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9924         "'>\n"
9925         "  <!ENTITY e2 SYSTEM 'bar'>\n"
9926         "]>\n"
9927         "<doc>&e2;</doc>";
9928   char entity_text[] = "Hello world";
9929   int i;
9930   const int max_alloc_count = 40;
9931 
9932   for (i = 0; i < max_alloc_count; i++) {
9933     allocation_count = i;
9934     XML_SetUserData(g_parser, entity_text);
9935     XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
9936     XML_SetExternalEntityRefHandler(g_parser, external_entity_alloc);
9937     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
9938         != XML_STATUS_ERROR)
9939       break;
9940     /* See comment in test_alloc_parse_xdecl() */
9941     alloc_teardown();
9942     alloc_setup();
9943   }
9944   if (i == 0)
9945     fail("Parsing worked despite failing allocations");
9946   else if (i == max_alloc_count)
9947     fail("Parsing failed even at max allocation count");
9948 }
9949 END_TEST
9950 
9951 START_TEST(test_alloc_long_notation) {
9952   const char *text
9953       = "<!DOCTYPE doc [\n"
9954         "  <!NOTATION note SYSTEM '"
9955         /* 64 characters per line */
9956         "ALongNotationNameThatShouldProvokeStringPoolGrowthWhileCallingAn"
9957         "ExternalEntityParserUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9958         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9959         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9960         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9961         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9962         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9963         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9964         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9965         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9966         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9967         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9968         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9969         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9970         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9971         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9972         "'>\n"
9973         "  <!ENTITY e1 SYSTEM 'foo' NDATA "
9974         /* 64 characters per line */
9975         "ALongNotationNameThatShouldProvokeStringPoolGrowthWhileCallingAn"
9976         "ExternalEntityParserUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9977         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9978         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9979         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9980         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9981         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9982         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9983         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9984         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9985         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9986         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9987         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9988         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9989         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9990         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9991         ">\n"
9992         "  <!ENTITY e2 SYSTEM 'bar'>\n"
9993         "]>\n"
9994         "<doc>&e2;</doc>";
9995   ExtOption options[]
9996       = {{XCS("foo"), "Entity Foo"}, {XCS("bar"), "Entity Bar"}, {NULL, NULL}};
9997   int i;
9998   const int max_alloc_count = 40;
9999 
10000   for (i = 0; i < max_alloc_count; i++) {
10001     allocation_count = i;
10002     XML_SetUserData(g_parser, options);
10003     XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
10004     XML_SetExternalEntityRefHandler(g_parser, external_entity_optioner);
10005     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
10006         != XML_STATUS_ERROR)
10007       break;
10008 
10009     /* See comment in test_alloc_parse_xdecl() */
10010     alloc_teardown();
10011     alloc_setup();
10012   }
10013   if (i == 0)
10014     fail("Parsing worked despite failing allocations");
10015   else if (i == max_alloc_count)
10016     fail("Parsing failed even at max allocation count");
10017 }
10018 END_TEST
10019 
10020 static void
10021 nsalloc_setup(void) {
10022   XML_Memory_Handling_Suite memsuite = {duff_allocator, duff_reallocator, free};
10023   XML_Char ns_sep[2] = {' ', '\0'};
10024 
10025   /* Ensure the parser creation will go through */
10026   allocation_count = ALLOC_ALWAYS_SUCCEED;
10027   reallocation_count = REALLOC_ALWAYS_SUCCEED;
10028   g_parser = XML_ParserCreate_MM(NULL, &memsuite, ns_sep);
10029   if (g_parser == NULL)
10030     fail("Parser not created");
10031 }
10032 
10033 static void
10034 nsalloc_teardown(void) {
10035   basic_teardown();
10036 }
10037 
10038 /* Test the effects of allocation failure in simple namespace parsing.
10039  * Based on test_ns_default_with_empty_uri()
10040  */
10041 START_TEST(test_nsalloc_xmlns) {
10042   const char *text = "<doc xmlns='http://example.org/'>\n"
10043                      "  <e xmlns=''/>\n"
10044                      "</doc>";
10045   unsigned int i;
10046   const unsigned int max_alloc_count = 30;
10047 
10048   for (i = 0; i < max_alloc_count; i++) {
10049     allocation_count = i;
10050     /* Exercise more code paths with a default handler */
10051     XML_SetDefaultHandler(g_parser, dummy_default_handler);
10052     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
10053         != XML_STATUS_ERROR)
10054       break;
10055     /* Resetting the parser is insufficient, because some memory
10056      * allocations are cached within the parser.  Instead we use
10057      * the teardown and setup routines to ensure that we have the
10058      * right sort of parser back in our hands.
10059      */
10060     nsalloc_teardown();
10061     nsalloc_setup();
10062   }
10063   if (i == 0)
10064     fail("Parsing worked despite failing allocations");
10065   else if (i == max_alloc_count)
10066     fail("Parsing failed even at maximum allocation count");
10067 }
10068 END_TEST
10069 
10070 /* Test XML_ParseBuffer interface with namespace and a dicky allocator */
10071 START_TEST(test_nsalloc_parse_buffer) {
10072   const char *text = "<doc>Hello</doc>";
10073   void *buffer;
10074 
10075   /* Try a parse before the start of the world */
10076   /* (Exercises new code path) */
10077   if (XML_ParseBuffer(g_parser, 0, XML_FALSE) != XML_STATUS_ERROR)
10078     fail("Pre-init XML_ParseBuffer not faulted");
10079   if (XML_GetErrorCode(g_parser) != XML_ERROR_NO_BUFFER)
10080     fail("Pre-init XML_ParseBuffer faulted for wrong reason");
10081 
10082   buffer = XML_GetBuffer(g_parser, 1 /* any small number greater than 0 */);
10083   if (buffer == NULL)
10084     fail("Could not acquire parse buffer");
10085 
10086   allocation_count = 0;
10087   if (XML_ParseBuffer(g_parser, 0, XML_FALSE) != XML_STATUS_ERROR)
10088     fail("Pre-init XML_ParseBuffer not faulted");
10089   if (XML_GetErrorCode(g_parser) != XML_ERROR_NO_MEMORY)
10090     fail("Pre-init XML_ParseBuffer faulted for wrong reason");
10091 
10092   /* Now with actual memory allocation */
10093   allocation_count = ALLOC_ALWAYS_SUCCEED;
10094   if (XML_ParseBuffer(g_parser, 0, XML_FALSE) != XML_STATUS_OK)
10095     xml_failure(g_parser);
10096 
10097   /* Check that resuming an unsuspended parser is faulted */
10098   if (XML_ResumeParser(g_parser) != XML_STATUS_ERROR)
10099     fail("Resuming unsuspended parser not faulted");
10100   if (XML_GetErrorCode(g_parser) != XML_ERROR_NOT_SUSPENDED)
10101     xml_failure(g_parser);
10102 
10103   /* Get the parser into suspended state */
10104   XML_SetCharacterDataHandler(g_parser, clearing_aborting_character_handler);
10105   resumable = XML_TRUE;
10106   buffer = XML_GetBuffer(g_parser, (int)strlen(text));
10107   if (buffer == NULL)
10108     fail("Could not acquire parse buffer");
10109   assert(buffer != NULL);
10110   memcpy(buffer, text, strlen(text));
10111   if (XML_ParseBuffer(g_parser, (int)strlen(text), XML_TRUE)
10112       != XML_STATUS_SUSPENDED)
10113     xml_failure(g_parser);
10114   if (XML_GetErrorCode(g_parser) != XML_ERROR_NONE)
10115     xml_failure(g_parser);
10116   if (XML_ParseBuffer(g_parser, (int)strlen(text), XML_TRUE)
10117       != XML_STATUS_ERROR)
10118     fail("Suspended XML_ParseBuffer not faulted");
10119   if (XML_GetErrorCode(g_parser) != XML_ERROR_SUSPENDED)
10120     xml_failure(g_parser);
10121   if (XML_GetBuffer(g_parser, (int)strlen(text)) != NULL)
10122     fail("Suspended XML_GetBuffer not faulted");
10123 
10124   /* Get it going again and complete the world */
10125   XML_SetCharacterDataHandler(g_parser, NULL);
10126   if (XML_ResumeParser(g_parser) != XML_STATUS_OK)
10127     xml_failure(g_parser);
10128   if (XML_ParseBuffer(g_parser, (int)strlen(text), XML_TRUE)
10129       != XML_STATUS_ERROR)
10130     fail("Post-finishing XML_ParseBuffer not faulted");
10131   if (XML_GetErrorCode(g_parser) != XML_ERROR_FINISHED)
10132     xml_failure(g_parser);
10133   if (XML_GetBuffer(g_parser, (int)strlen(text)) != NULL)
10134     fail("Post-finishing XML_GetBuffer not faulted");
10135 }
10136 END_TEST
10137 
10138 /* Check handling of long prefix names (pool growth) */
10139 START_TEST(test_nsalloc_long_prefix) {
10140   const char *text
10141       = "<"
10142         /* 64 characters per line */
10143         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10144         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10145         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10146         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10147         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10148         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10149         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10150         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10151         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10152         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10153         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10154         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10155         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10156         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10157         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10158         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10159         ":foo xmlns:"
10160         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10161         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10162         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10163         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10164         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10165         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10166         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10167         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10168         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10169         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10170         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10171         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10172         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10173         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10174         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10175         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10176         "='http://example.org/'>"
10177         "</"
10178         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10179         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10180         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10181         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10182         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10183         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10184         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10185         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10186         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10187         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10188         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10189         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10190         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10191         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10192         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10193         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10194         ":foo>";
10195   int i;
10196   const int max_alloc_count = 40;
10197 
10198   for (i = 0; i < max_alloc_count; i++) {
10199     allocation_count = i;
10200     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
10201         != XML_STATUS_ERROR)
10202       break;
10203     /* See comment in test_nsalloc_xmlns() */
10204     nsalloc_teardown();
10205     nsalloc_setup();
10206   }
10207   if (i == 0)
10208     fail("Parsing worked despite failing allocations");
10209   else if (i == max_alloc_count)
10210     fail("Parsing failed even at max allocation count");
10211 }
10212 END_TEST
10213 
10214 /* Check handling of long uri names (pool growth) */
10215 START_TEST(test_nsalloc_long_uri) {
10216   const char *text
10217       = "<foo:e xmlns:foo='http://example.org/"
10218         /* 64 characters per line */
10219         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10220         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10221         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10222         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10223         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10224         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10225         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10226         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10227         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10228         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10229         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10230         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10231         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10232         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10233         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10234         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10235         "' bar:a='12'\n"
10236         "xmlns:bar='http://example.org/"
10237         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10238         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10239         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10240         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10241         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10242         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10243         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10244         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10245         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10246         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10247         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10248         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10249         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10250         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10251         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10252         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10253         "'>"
10254         "</foo:e>";
10255   int i;
10256   const int max_alloc_count = 40;
10257 
10258   for (i = 0; i < max_alloc_count; i++) {
10259     allocation_count = i;
10260     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
10261         != XML_STATUS_ERROR)
10262       break;
10263     /* See comment in test_nsalloc_xmlns() */
10264     nsalloc_teardown();
10265     nsalloc_setup();
10266   }
10267   if (i == 0)
10268     fail("Parsing worked despite failing allocations");
10269   else if (i == max_alloc_count)
10270     fail("Parsing failed even at max allocation count");
10271 }
10272 END_TEST
10273 
10274 /* Test handling of long attribute names with prefixes */
10275 START_TEST(test_nsalloc_long_attr) {
10276   const char *text
10277       = "<foo:e xmlns:foo='http://example.org/' bar:"
10278         /* 64 characters per line */
10279         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10280         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10281         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10282         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10283         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10284         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10285         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10286         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10287         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10288         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10289         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10290         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10291         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10292         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10293         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10294         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10295         "='12'\n"
10296         "xmlns:bar='http://example.org/'>"
10297         "</foo:e>";
10298   int i;
10299   const int max_alloc_count = 40;
10300 
10301   for (i = 0; i < max_alloc_count; i++) {
10302     allocation_count = i;
10303     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
10304         != XML_STATUS_ERROR)
10305       break;
10306     /* See comment in test_nsalloc_xmlns() */
10307     nsalloc_teardown();
10308     nsalloc_setup();
10309   }
10310   if (i == 0)
10311     fail("Parsing worked despite failing allocations");
10312   else if (i == max_alloc_count)
10313     fail("Parsing failed even at max allocation count");
10314 }
10315 END_TEST
10316 
10317 /* Test handling of an attribute name with a long namespace prefix */
10318 START_TEST(test_nsalloc_long_attr_prefix) {
10319   const char *text
10320       = "<foo:e xmlns:foo='http://example.org/' "
10321         /* 64 characters per line */
10322         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10323         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10324         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10325         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10326         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10327         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10328         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10329         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10330         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10331         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10332         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10333         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10334         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10335         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10336         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10337         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10338         ":a='12'\n"
10339         "xmlns:"
10340         /* 64 characters per line */
10341         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10342         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10343         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10344         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10345         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10346         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10347         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10348         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10349         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10350         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10351         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10352         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10353         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10354         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10355         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10356         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10357         "='http://example.org/'>"
10358         "</foo:e>";
10359   const XML_Char *elemstr[] = {
10360       /* clang-format off */
10361         XCS("http://example.org/ e foo"),
10362         XCS("http://example.org/ a ")
10363         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ")
10364         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ")
10365         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ")
10366         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ")
10367         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ")
10368         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ")
10369         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ")
10370         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ")
10371         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ")
10372         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ")
10373         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ")
10374         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ")
10375         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ")
10376         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ")
10377         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ")
10378         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ")
10379       /* clang-format on */
10380   };
10381   int i;
10382   const int max_alloc_count = 40;
10383 
10384   for (i = 0; i < max_alloc_count; i++) {
10385     allocation_count = i;
10386     XML_SetReturnNSTriplet(g_parser, XML_TRUE);
10387     XML_SetUserData(g_parser, (void *)elemstr);
10388     XML_SetElementHandler(g_parser, triplet_start_checker, triplet_end_checker);
10389     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
10390         != XML_STATUS_ERROR)
10391       break;
10392     /* See comment in test_nsalloc_xmlns() */
10393     nsalloc_teardown();
10394     nsalloc_setup();
10395   }
10396   if (i == 0)
10397     fail("Parsing worked despite failing allocations");
10398   else if (i == max_alloc_count)
10399     fail("Parsing failed even at max allocation count");
10400 }
10401 END_TEST
10402 
10403 /* Test attribute handling in the face of a dodgy reallocator */
10404 START_TEST(test_nsalloc_realloc_attributes) {
10405   const char *text = "<foo:e xmlns:foo='http://example.org/' bar:a='12'\n"
10406                      "       xmlns:bar='http://example.org/'>"
10407                      "</foo:e>";
10408   int i;
10409   const int max_realloc_count = 10;
10410 
10411   for (i = 0; i < max_realloc_count; i++) {
10412     reallocation_count = i;
10413     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
10414         != XML_STATUS_ERROR)
10415       break;
10416     /* See comment in test_nsalloc_xmlns() */
10417     nsalloc_teardown();
10418     nsalloc_setup();
10419   }
10420   if (i == 0)
10421     fail("Parsing worked despite failing reallocations");
10422   else if (i == max_realloc_count)
10423     fail("Parsing failed at max reallocation count");
10424 }
10425 END_TEST
10426 
10427 /* Test long element names with namespaces under a failing allocator */
10428 START_TEST(test_nsalloc_long_element) {
10429   const char *text
10430       = "<foo:thisisalongenoughelementnametotriggerareallocation\n"
10431         " xmlns:foo='http://example.org/' bar:a='12'\n"
10432         " xmlns:bar='http://example.org/'>"
10433         "</foo:thisisalongenoughelementnametotriggerareallocation>";
10434   const XML_Char *elemstr[]
10435       = {XCS("http://example.org/")
10436              XCS(" thisisalongenoughelementnametotriggerareallocation foo"),
10437          XCS("http://example.org/ a bar")};
10438   int i;
10439   const int max_alloc_count = 30;
10440 
10441   for (i = 0; i < max_alloc_count; i++) {
10442     allocation_count = i;
10443     XML_SetReturnNSTriplet(g_parser, XML_TRUE);
10444     XML_SetUserData(g_parser, (void *)elemstr);
10445     XML_SetElementHandler(g_parser, triplet_start_checker, triplet_end_checker);
10446     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
10447         != XML_STATUS_ERROR)
10448       break;
10449     /* See comment in test_nsalloc_xmlns() */
10450     nsalloc_teardown();
10451     nsalloc_setup();
10452   }
10453   if (i == 0)
10454     fail("Parsing worked despite failing reallocations");
10455   else if (i == max_alloc_count)
10456     fail("Parsing failed at max reallocation count");
10457 }
10458 END_TEST
10459 
10460 /* Test the effects of reallocation failure when reassigning a
10461  * binding.
10462  *
10463  * XML_ParserReset does not free the BINDING structures used by a
10464  * parser, but instead adds them to an internal free list to be reused
10465  * as necessary.  Likewise the URI buffers allocated for the binding
10466  * aren't freed, but kept attached to their existing binding.  If the
10467  * new binding has a longer URI, it will need reallocation.  This test
10468  * provokes that reallocation, and tests the control path if it fails.
10469  */
10470 START_TEST(test_nsalloc_realloc_binding_uri) {
10471   const char *first = "<doc xmlns='http://example.org/'>\n"
10472                       "  <e xmlns='' />\n"
10473                       "</doc>";
10474   const char *second
10475       = "<doc xmlns='http://example.org/long/enough/URI/to/reallocate/'>\n"
10476         "  <e xmlns='' />\n"
10477         "</doc>";
10478   unsigned i;
10479   const unsigned max_realloc_count = 10;
10480 
10481   /* First, do a full parse that will leave bindings around */
10482   if (_XML_Parse_SINGLE_BYTES(g_parser, first, (int)strlen(first), XML_TRUE)
10483       == XML_STATUS_ERROR)
10484     xml_failure(g_parser);
10485 
10486   /* Now repeat with a longer URI and a duff reallocator */
10487   for (i = 0; i < max_realloc_count; i++) {
10488     XML_ParserReset(g_parser, NULL);
10489     reallocation_count = i;
10490     if (_XML_Parse_SINGLE_BYTES(g_parser, second, (int)strlen(second), XML_TRUE)
10491         != XML_STATUS_ERROR)
10492       break;
10493   }
10494   if (i == 0)
10495     fail("Parsing worked despite failing reallocation");
10496   else if (i == max_realloc_count)
10497     fail("Parsing failed at max reallocation count");
10498 }
10499 END_TEST
10500 
10501 /* Check handling of long prefix names (pool growth) */
10502 START_TEST(test_nsalloc_realloc_long_prefix) {
10503   const char *text
10504       = "<"
10505         /* 64 characters per line */
10506         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10507         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10508         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10509         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10510         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10511         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10512         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10513         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10514         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10515         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10516         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10517         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10518         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10519         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10520         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10521         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10522         ":foo xmlns:"
10523         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10524         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10525         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10526         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10527         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10528         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10529         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10530         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10531         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10532         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10533         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10534         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10535         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10536         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10537         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10538         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10539         "='http://example.org/'>"
10540         "</"
10541         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10542         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10543         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10544         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10545         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10546         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10547         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10548         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10549         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10550         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10551         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10552         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10553         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10554         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10555         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10556         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10557         ":foo>";
10558   int i;
10559   const int max_realloc_count = 12;
10560 
10561   for (i = 0; i < max_realloc_count; i++) {
10562     reallocation_count = i;
10563     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
10564         != XML_STATUS_ERROR)
10565       break;
10566     /* See comment in test_nsalloc_xmlns() */
10567     nsalloc_teardown();
10568     nsalloc_setup();
10569   }
10570   if (i == 0)
10571     fail("Parsing worked despite failing reallocations");
10572   else if (i == max_realloc_count)
10573     fail("Parsing failed even at max reallocation count");
10574 }
10575 END_TEST
10576 
10577 /* Check handling of even long prefix names (different code path) */
10578 START_TEST(test_nsalloc_realloc_longer_prefix) {
10579   const char *text
10580       = "<"
10581         /* 64 characters per line */
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         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10596         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10597         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10598         "Q:foo xmlns:"
10599         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10600         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10601         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10602         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10603         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10604         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10605         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10606         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10607         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10608         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10609         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10610         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10611         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10612         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10613         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10614         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10615         "Q='http://example.org/'>"
10616         "</"
10617         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10618         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10619         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10620         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10621         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10622         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10623         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10624         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10625         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10626         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10627         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10628         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10629         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10630         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10631         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10632         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10633         "Q:foo>";
10634   int i;
10635   const int max_realloc_count = 12;
10636 
10637   for (i = 0; i < max_realloc_count; i++) {
10638     reallocation_count = i;
10639     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
10640         != XML_STATUS_ERROR)
10641       break;
10642     /* See comment in test_nsalloc_xmlns() */
10643     nsalloc_teardown();
10644     nsalloc_setup();
10645   }
10646   if (i == 0)
10647     fail("Parsing worked despite failing reallocations");
10648   else if (i == max_realloc_count)
10649     fail("Parsing failed even at max reallocation count");
10650 }
10651 END_TEST
10652 
10653 START_TEST(test_nsalloc_long_namespace) {
10654   const char *text1
10655       = "<"
10656         /* 64 characters per line */
10657         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10658         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10659         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10660         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10661         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10662         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10663         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10664         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10665         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10666         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10667         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10668         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10669         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10670         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10671         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10672         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10673         ":e xmlns:"
10674         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10675         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10676         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10677         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10678         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10679         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10680         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10681         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10682         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10683         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10684         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10685         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10686         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10687         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10688         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10689         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10690         "='http://example.org/'>\n";
10691   const char *text2
10692       = "<"
10693         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10694         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10695         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10696         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10697         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10698         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10699         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10700         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10701         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10702         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10703         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10704         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10705         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10706         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10707         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10708         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10709         ":f "
10710         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10711         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10712         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10713         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10714         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10715         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10716         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10717         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10718         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10719         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10720         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10721         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10722         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10723         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10724         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10725         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10726         ":attr='foo'/>\n"
10727         "</"
10728         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10729         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10730         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10731         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10732         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10733         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10734         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10735         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10736         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10737         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10738         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10739         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10740         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10741         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10742         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10743         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10744         ":e>";
10745   int i;
10746   const int max_alloc_count = 40;
10747 
10748   for (i = 0; i < max_alloc_count; i++) {
10749     allocation_count = i;
10750     if (_XML_Parse_SINGLE_BYTES(g_parser, text1, (int)strlen(text1), XML_FALSE)
10751             != XML_STATUS_ERROR
10752         && _XML_Parse_SINGLE_BYTES(g_parser, text2, (int)strlen(text2),
10753                                    XML_TRUE)
10754                != XML_STATUS_ERROR)
10755       break;
10756     /* See comment in test_nsalloc_xmlns() */
10757     nsalloc_teardown();
10758     nsalloc_setup();
10759   }
10760   if (i == 0)
10761     fail("Parsing worked despite failing allocations");
10762   else if (i == max_alloc_count)
10763     fail("Parsing failed even at max allocation count");
10764 }
10765 END_TEST
10766 
10767 /* Using a slightly shorter namespace name provokes allocations in
10768  * slightly different places in the code.
10769  */
10770 START_TEST(test_nsalloc_less_long_namespace) {
10771   const char *text
10772       = "<"
10773         /* 64 characters per line */
10774         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10775         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10776         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10777         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10778         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10779         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10780         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10781         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz012345678"
10782         ":e xmlns:"
10783         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10784         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10785         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10786         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10787         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10788         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10789         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10790         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz012345678"
10791         "='http://example.org/'>\n"
10792         "<"
10793         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10794         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10795         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10796         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10797         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10798         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10799         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10800         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz012345678"
10801         ":f "
10802         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10803         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10804         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10805         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10806         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10807         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10808         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10809         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz012345678"
10810         ":att='foo'/>\n"
10811         "</"
10812         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10813         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10814         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10815         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10816         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10817         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10818         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10819         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz012345678"
10820         ":e>";
10821   int i;
10822   const int max_alloc_count = 40;
10823 
10824   for (i = 0; i < max_alloc_count; i++) {
10825     allocation_count = i;
10826     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
10827         != XML_STATUS_ERROR)
10828       break;
10829     /* See comment in test_nsalloc_xmlns() */
10830     nsalloc_teardown();
10831     nsalloc_setup();
10832   }
10833   if (i == 0)
10834     fail("Parsing worked despite failing allocations");
10835   else if (i == max_alloc_count)
10836     fail("Parsing failed even at max allocation count");
10837 }
10838 END_TEST
10839 
10840 START_TEST(test_nsalloc_long_context) {
10841   const char *text
10842       = "<!DOCTYPE doc SYSTEM 'foo' [\n"
10843         "  <!ATTLIST doc baz ID #REQUIRED>\n"
10844         "  <!ENTITY en SYSTEM 'bar'>\n"
10845         "]>\n"
10846         "<doc xmlns='http://example.org/"
10847         /* 64 characters per line */
10848         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10849         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10850         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10851         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10852         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10853         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10854         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10855         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10856         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10857         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10858         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10859         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10860         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10861         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10862         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10863         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKL"
10864         "' baz='2'>\n"
10865         "&en;"
10866         "</doc>";
10867   ExtOption options[] = {
10868       {XCS("foo"), "<!ELEMENT e EMPTY>"}, {XCS("bar"), "<e/>"}, {NULL, NULL}};
10869   int i;
10870   const int max_alloc_count = 70;
10871 
10872   for (i = 0; i < max_alloc_count; i++) {
10873     allocation_count = i;
10874     XML_SetUserData(g_parser, options);
10875     XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
10876     XML_SetExternalEntityRefHandler(g_parser, external_entity_optioner);
10877     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
10878         != XML_STATUS_ERROR)
10879       break;
10880 
10881     /* See comment in test_nsalloc_xmlns() */
10882     nsalloc_teardown();
10883     nsalloc_setup();
10884   }
10885   if (i == 0)
10886     fail("Parsing worked despite failing allocations");
10887   else if (i == max_alloc_count)
10888     fail("Parsing failed even at max allocation count");
10889 }
10890 END_TEST
10891 
10892 /* This function is void; it will throw a fail() on error, so if it
10893  * returns normally it must have succeeded.
10894  */
10895 static void
10896 context_realloc_test(const char *text) {
10897   ExtOption options[] = {
10898       {XCS("foo"), "<!ELEMENT e EMPTY>"}, {XCS("bar"), "<e/>"}, {NULL, NULL}};
10899   int i;
10900   const int max_realloc_count = 6;
10901 
10902   for (i = 0; i < max_realloc_count; i++) {
10903     reallocation_count = i;
10904     XML_SetUserData(g_parser, options);
10905     XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
10906     XML_SetExternalEntityRefHandler(g_parser, external_entity_optioner);
10907     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
10908         != XML_STATUS_ERROR)
10909       break;
10910     /* See comment in test_nsalloc_xmlns() */
10911     nsalloc_teardown();
10912     nsalloc_setup();
10913   }
10914   if (i == 0)
10915     fail("Parsing worked despite failing reallocations");
10916   else if (i == max_realloc_count)
10917     fail("Parsing failed even at max reallocation count");
10918 }
10919 
10920 START_TEST(test_nsalloc_realloc_long_context) {
10921   const char *text
10922       = "<!DOCTYPE doc SYSTEM 'foo' [\n"
10923         "  <!ENTITY en SYSTEM 'bar'>\n"
10924         "]>\n"
10925         "<doc xmlns='http://example.org/"
10926         /* 64 characters per line */
10927         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10928         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10929         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10930         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10931         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10932         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10933         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10934         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10935         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10936         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10937         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10938         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10939         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10940         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10941         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10942         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKL"
10943         "'>\n"
10944         "&en;"
10945         "</doc>";
10946 
10947   context_realloc_test(text);
10948 }
10949 END_TEST
10950 
10951 START_TEST(test_nsalloc_realloc_long_context_2) {
10952   const char *text
10953       = "<!DOCTYPE doc SYSTEM 'foo' [\n"
10954         "  <!ENTITY en SYSTEM 'bar'>\n"
10955         "]>\n"
10956         "<doc xmlns='http://example.org/"
10957         /* 64 characters per line */
10958         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10959         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10960         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10961         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10962         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10963         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10964         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10965         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10966         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10967         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10968         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10969         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10970         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10971         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10972         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10973         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJK"
10974         "'>\n"
10975         "&en;"
10976         "</doc>";
10977 
10978   context_realloc_test(text);
10979 }
10980 END_TEST
10981 
10982 START_TEST(test_nsalloc_realloc_long_context_3) {
10983   const char *text
10984       = "<!DOCTYPE doc SYSTEM 'foo' [\n"
10985         "  <!ENTITY en SYSTEM 'bar'>\n"
10986         "]>\n"
10987         "<doc xmlns='http://example.org/"
10988         /* 64 characters per line */
10989         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10990         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10991         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10992         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10993         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10994         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10995         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10996         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10997         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10998         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10999         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11000         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11001         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11002         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11003         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11004         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGH"
11005         "'>\n"
11006         "&en;"
11007         "</doc>";
11008 
11009   context_realloc_test(text);
11010 }
11011 END_TEST
11012 
11013 START_TEST(test_nsalloc_realloc_long_context_4) {
11014   const char *text
11015       = "<!DOCTYPE doc SYSTEM 'foo' [\n"
11016         "  <!ENTITY en SYSTEM 'bar'>\n"
11017         "]>\n"
11018         "<doc xmlns='http://example.org/"
11019         /* 64 characters per line */
11020         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11021         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11022         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11023         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11024         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11025         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11026         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11027         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11028         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11029         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11030         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11031         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11032         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11033         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11034         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11035         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO"
11036         "'>\n"
11037         "&en;"
11038         "</doc>";
11039 
11040   context_realloc_test(text);
11041 }
11042 END_TEST
11043 
11044 START_TEST(test_nsalloc_realloc_long_context_5) {
11045   const char *text
11046       = "<!DOCTYPE doc SYSTEM 'foo' [\n"
11047         "  <!ENTITY en SYSTEM 'bar'>\n"
11048         "]>\n"
11049         "<doc xmlns='http://example.org/"
11050         /* 64 characters per line */
11051         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11052         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11053         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11054         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11055         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11056         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11057         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11058         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11059         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11060         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11061         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11062         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11063         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11064         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11065         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11066         "ABC"
11067         "'>\n"
11068         "&en;"
11069         "</doc>";
11070 
11071   context_realloc_test(text);
11072 }
11073 END_TEST
11074 
11075 START_TEST(test_nsalloc_realloc_long_context_6) {
11076   const char *text
11077       = "<!DOCTYPE doc SYSTEM 'foo' [\n"
11078         "  <!ENTITY en SYSTEM 'bar'>\n"
11079         "]>\n"
11080         "<doc xmlns='http://example.org/"
11081         /* 64 characters per line */
11082         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11083         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11084         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11085         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
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/ABCDEFGHIJKLMNOP"
11097         "'>\n"
11098         "&en;"
11099         "</doc>";
11100 
11101   context_realloc_test(text);
11102 }
11103 END_TEST
11104 
11105 START_TEST(test_nsalloc_realloc_long_context_7) {
11106   const char *text
11107       = "<!DOCTYPE doc SYSTEM 'foo' [\n"
11108         "  <!ENTITY en SYSTEM 'bar'>\n"
11109         "]>\n"
11110         "<doc xmlns='http://example.org/"
11111         /* 64 characters per line */
11112         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11113         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11114         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11115         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11116         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11117         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11118         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11119         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11120         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11121         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11122         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11123         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11124         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11125         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11126         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11127         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLM"
11128         "'>\n"
11129         "&en;"
11130         "</doc>";
11131 
11132   context_realloc_test(text);
11133 }
11134 END_TEST
11135 
11136 START_TEST(test_nsalloc_realloc_long_ge_name) {
11137   const char *text
11138       = "<!DOCTYPE doc SYSTEM 'foo' [\n"
11139         "  <!ENTITY "
11140         /* 64 characters per line */
11141         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11142         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11143         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11144         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11145         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11146         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11147         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11148         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11149         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11150         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11151         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11152         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11153         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11154         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11155         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11156         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11157         " SYSTEM 'bar'>\n"
11158         "]>\n"
11159         "<doc xmlns='http://example.org/baz'>\n"
11160         "&"
11161         /* 64 characters per line */
11162         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11163         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11164         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11165         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11166         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11167         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11168         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11169         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11170         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11171         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11172         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11173         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11174         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11175         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11176         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11177         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11178         ";"
11179         "</doc>";
11180   ExtOption options[] = {
11181       {XCS("foo"), "<!ELEMENT el EMPTY>"}, {XCS("bar"), "<el/>"}, {NULL, NULL}};
11182   int i;
11183   const int max_realloc_count = 10;
11184 
11185   for (i = 0; i < max_realloc_count; i++) {
11186     reallocation_count = i;
11187     XML_SetUserData(g_parser, options);
11188     XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
11189     XML_SetExternalEntityRefHandler(g_parser, external_entity_optioner);
11190     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
11191         != XML_STATUS_ERROR)
11192       break;
11193     /* See comment in test_nsalloc_xmlns() */
11194     nsalloc_teardown();
11195     nsalloc_setup();
11196   }
11197   if (i == 0)
11198     fail("Parsing worked despite failing reallocations");
11199   else if (i == max_realloc_count)
11200     fail("Parsing failed even at max reallocation count");
11201 }
11202 END_TEST
11203 
11204 /* Test that when a namespace is passed through the context mechanism
11205  * to an external entity parser, the parsers handle reallocation
11206  * failures correctly.  The prefix is exactly the right length to
11207  * provoke particular uncommon code paths.
11208  */
11209 START_TEST(test_nsalloc_realloc_long_context_in_dtd) {
11210   const char *text1
11211       = "<!DOCTYPE "
11212         /* 64 characters per line */
11213         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11214         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11215         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11216         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11217         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11218         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11219         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11220         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11221         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11222         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11223         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11224         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11225         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11226         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11227         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11228         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11229         ":doc [\n"
11230         "  <!ENTITY First SYSTEM 'foo/First'>\n"
11231         "]>\n"
11232         "<"
11233         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11234         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11235         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11236         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11237         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11238         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11239         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11240         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11241         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11242         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11243         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11244         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11245         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11246         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11247         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11248         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11249         ":doc xmlns:"
11250         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11251         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11252         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11253         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11254         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11255         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11256         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11257         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11258         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11259         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11260         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11261         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11262         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11263         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11264         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11265         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11266         "='foo/Second'>&First;";
11267   const char *text2
11268       = "</"
11269         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11270         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11271         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11272         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11273         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11274         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11275         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11276         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11277         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11278         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11279         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11280         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11281         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11282         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11283         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11284         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11285         ":doc>";
11286   ExtOption options[] = {{XCS("foo/First"), "Hello world"}, {NULL, NULL}};
11287   int i;
11288   const int max_realloc_count = 20;
11289 
11290   for (i = 0; i < max_realloc_count; i++) {
11291     reallocation_count = i;
11292     XML_SetUserData(g_parser, options);
11293     XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
11294     XML_SetExternalEntityRefHandler(g_parser, external_entity_optioner);
11295     if (_XML_Parse_SINGLE_BYTES(g_parser, text1, (int)strlen(text1), XML_FALSE)
11296             != XML_STATUS_ERROR
11297         && _XML_Parse_SINGLE_BYTES(g_parser, text2, (int)strlen(text2),
11298                                    XML_TRUE)
11299                != XML_STATUS_ERROR)
11300       break;
11301     /* See comment in test_nsalloc_xmlns() */
11302     nsalloc_teardown();
11303     nsalloc_setup();
11304   }
11305   if (i == 0)
11306     fail("Parsing worked despite failing reallocations");
11307   else if (i == max_realloc_count)
11308     fail("Parsing failed even at max reallocation count");
11309 }
11310 END_TEST
11311 
11312 START_TEST(test_nsalloc_long_default_in_ext) {
11313   const char *text
11314       = "<!DOCTYPE doc [\n"
11315         "  <!ATTLIST e a1 CDATA '"
11316         /* 64 characters per line */
11317         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11318         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11319         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11320         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11321         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11322         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11323         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11324         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11325         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11326         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11327         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11328         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11329         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11330         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11331         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11332         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11333         "'>\n"
11334         "  <!ENTITY x SYSTEM 'foo'>\n"
11335         "]>\n"
11336         "<doc>&x;</doc>";
11337   ExtOption options[] = {{XCS("foo"), "<e/>"}, {NULL, NULL}};
11338   int i;
11339   const int max_alloc_count = 50;
11340 
11341   for (i = 0; i < max_alloc_count; i++) {
11342     allocation_count = i;
11343     XML_SetUserData(g_parser, options);
11344     XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
11345     XML_SetExternalEntityRefHandler(g_parser, external_entity_optioner);
11346     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
11347         != XML_STATUS_ERROR)
11348       break;
11349 
11350     /* See comment in test_nsalloc_xmlns() */
11351     nsalloc_teardown();
11352     nsalloc_setup();
11353   }
11354   if (i == 0)
11355     fail("Parsing worked despite failing allocations");
11356   else if (i == max_alloc_count)
11357     fail("Parsing failed even at max allocation count");
11358 }
11359 END_TEST
11360 
11361 START_TEST(test_nsalloc_long_systemid_in_ext) {
11362   const char *text
11363       = "<!DOCTYPE doc SYSTEM 'foo' [\n"
11364         "  <!ENTITY en SYSTEM '"
11365         /* 64 characters per line */
11366         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11367         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11368         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11369         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11370         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11371         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11372         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11373         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11374         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11375         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11376         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11377         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11378         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11379         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11380         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11381         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11382         "'>\n"
11383         "]>\n"
11384         "<doc>&en;</doc>";
11385   ExtOption options[] = {
11386       {XCS("foo"), "<!ELEMENT e EMPTY>"},
11387       {/* clang-format off */
11388             XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/")
11389             XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/")
11390             XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/")
11391             XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/")
11392             XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/")
11393             XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/")
11394             XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/")
11395             XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/")
11396             XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/")
11397             XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/")
11398             XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/")
11399             XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/")
11400             XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/")
11401             XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/")
11402             XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/")
11403             XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"),
11404        /* clang-format on */
11405        "<e/>"},
11406       {NULL, NULL}};
11407   int i;
11408   const int max_alloc_count = 55;
11409 
11410   for (i = 0; i < max_alloc_count; i++) {
11411     allocation_count = i;
11412     XML_SetUserData(g_parser, options);
11413     XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
11414     XML_SetExternalEntityRefHandler(g_parser, external_entity_optioner);
11415     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
11416         != XML_STATUS_ERROR)
11417       break;
11418 
11419     /* See comment in test_nsalloc_xmlns() */
11420     nsalloc_teardown();
11421     nsalloc_setup();
11422   }
11423   if (i == 0)
11424     fail("Parsing worked despite failing allocations");
11425   else if (i == max_alloc_count)
11426     fail("Parsing failed even at max allocation count");
11427 }
11428 END_TEST
11429 
11430 /* Test the effects of allocation failure on parsing an element in a
11431  * namespace.  Based on test_nsalloc_long_context.
11432  */
11433 START_TEST(test_nsalloc_prefixed_element) {
11434   const char *text = "<!DOCTYPE pfx:element SYSTEM 'foo' [\n"
11435                      "  <!ATTLIST pfx:element baz ID #REQUIRED>\n"
11436                      "  <!ENTITY en SYSTEM 'bar'>\n"
11437                      "]>\n"
11438                      "<pfx:element xmlns:pfx='http://example.org/' baz='2'>\n"
11439                      "&en;"
11440                      "</pfx:element>";
11441   ExtOption options[] = {
11442       {XCS("foo"), "<!ELEMENT e EMPTY>"}, {XCS("bar"), "<e/>"}, {NULL, NULL}};
11443   int i;
11444   const int max_alloc_count = 70;
11445 
11446   for (i = 0; i < max_alloc_count; i++) {
11447     allocation_count = i;
11448     XML_SetUserData(g_parser, options);
11449     XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
11450     XML_SetExternalEntityRefHandler(g_parser, external_entity_optioner);
11451     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
11452         != XML_STATUS_ERROR)
11453       break;
11454 
11455     /* See comment in test_nsalloc_xmlns() */
11456     nsalloc_teardown();
11457     nsalloc_setup();
11458   }
11459   if (i == 0)
11460     fail("Success despite failing allocator");
11461   else if (i == max_alloc_count)
11462     fail("Failed even at full allocation count");
11463 }
11464 END_TEST
11465 
11466 #if defined(XML_DTD)
11467 typedef enum XML_Status (*XmlParseFunction)(XML_Parser, const char *, int, int);
11468 
11469 struct AccountingTestCase {
11470   const char *primaryText;
11471   const char *firstExternalText;  /* often NULL */
11472   const char *secondExternalText; /* often NULL */
11473   const unsigned long long expectedCountBytesIndirectExtra;
11474   XML_Bool singleBytesWanted;
11475 };
11476 
11477 static int
11478 accounting_external_entity_ref_handler(XML_Parser parser,
11479                                        const XML_Char *context,
11480                                        const XML_Char *base,
11481                                        const XML_Char *systemId,
11482                                        const XML_Char *publicId) {
11483   UNUSED_P(context);
11484   UNUSED_P(base);
11485   UNUSED_P(publicId);
11486 
11487   const struct AccountingTestCase *const testCase
11488       = (const struct AccountingTestCase *)XML_GetUserData(parser);
11489 
11490   const char *externalText = NULL;
11491   if (xcstrcmp(systemId, XCS("first.ent")) == 0) {
11492     externalText = testCase->firstExternalText;
11493   } else if (xcstrcmp(systemId, XCS("second.ent")) == 0) {
11494     externalText = testCase->secondExternalText;
11495   } else {
11496     assert(! "systemId is neither \"first.ent\" nor \"second.ent\"");
11497   }
11498   assert(externalText);
11499 
11500   XML_Parser entParser = XML_ExternalEntityParserCreate(parser, context, 0);
11501   assert(entParser);
11502 
11503   const XmlParseFunction xmlParseFunction
11504       = testCase->singleBytesWanted ? _XML_Parse_SINGLE_BYTES : XML_Parse;
11505 
11506   const enum XML_Status status = xmlParseFunction(
11507       entParser, externalText, (int)strlen(externalText), XML_TRUE);
11508 
11509   XML_ParserFree(entParser);
11510   return status;
11511 }
11512 
11513 START_TEST(test_accounting_precision) {
11514   const XML_Bool filled_later = XML_TRUE; /* value is arbitrary */
11515   struct AccountingTestCase cases[] = {
11516       {"<e/>", NULL, NULL, 0, 0},
11517       {"<e></e>", NULL, NULL, 0, 0},
11518 
11519       /* Attributes */
11520       {"<e k1=\"v2\" k2=\"v2\"/>", NULL, NULL, 0, filled_later},
11521       {"<e k1=\"v2\" k2=\"v2\"></e>", NULL, NULL, 0, 0},
11522       {"<p:e xmlns:p=\"https://domain.invalid/\" />", NULL, NULL, 0,
11523        filled_later},
11524       {"<e k=\"&amp;&apos;&gt;&lt;&quot;\" />", NULL, NULL,
11525        sizeof(XML_Char) * 5 /* number of predefined entities */, filled_later},
11526       {"<e1 xmlns='https://example.org/'>\n"
11527        "  <e2 xmlns=''/>\n"
11528        "</e1>",
11529        NULL, NULL, 0, filled_later},
11530 
11531       /* Text */
11532       {"<e>text</e>", NULL, NULL, 0, filled_later},
11533       {"<e1><e2>text1<e3/>text2</e2></e1>", NULL, NULL, 0, filled_later},
11534       {"<e>&amp;&apos;&gt;&lt;&quot;</e>", NULL, NULL,
11535        sizeof(XML_Char) * 5 /* number of predefined entities */, filled_later},
11536       {"<e>&#65;&#41;</e>", NULL, NULL, 0, filled_later},
11537 
11538       /* Prolog */
11539       {"<?xml version=\"1.0\"?><root/>", NULL, NULL, 0, filled_later},
11540 
11541       /* Whitespace */
11542       {"  <e1>  <e2>  </e2>  </e1>  ", NULL, NULL, 0, filled_later},
11543       {"<e1  ><e2  /></e1  >", NULL, NULL, 0, filled_later},
11544       {"<e1><e2 k = \"v\"/><e3 k = 'v'/></e1>", NULL, NULL, 0, filled_later},
11545 
11546       /* Comments */
11547       {"<!-- Comment --><e><!-- Comment --></e>", NULL, NULL, 0, filled_later},
11548 
11549       /* Processing instructions */
11550       {"<?xml-stylesheet type=\"text/xsl\" href=\"https://domain.invalid/\" media=\"all\"?><e/>",
11551        NULL, NULL, 0, filled_later},
11552       {"<?pi0?><?pi1 ?><?pi2  ?><!DOCTYPE r SYSTEM 'first.ent'><r/>",
11553        "<?pi3?><!ENTITY % e1 SYSTEM 'second.ent'><?pi4?>%e1;<?pi5?>", "<?pi6?>",
11554        0, filled_later},
11555 
11556       /* CDATA */
11557       {"<e><![CDATA[one two three]]></e>", NULL, NULL, 0, filled_later},
11558       /* The following is the essence of this OSS-Fuzz finding:
11559          https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=34302
11560          https://oss-fuzz.com/testcase-detail/4860575394955264
11561       */
11562       {"<!DOCTYPE r [\n"
11563        "<!ENTITY e \"111<![CDATA[2 <= 2]]>333\">\n"
11564        "]>\n"
11565        "<r>&e;</r>\n",
11566        NULL, NULL, sizeof(XML_Char) * strlen("111<![CDATA[2 <= 2]]>333"),
11567        filled_later},
11568 
11569       /* Conditional sections */
11570       {"<!DOCTYPE r [\n"
11571        "<!ENTITY % draft 'INCLUDE'>\n"
11572        "<!ENTITY % final 'IGNORE'>\n"
11573        "<!ENTITY % import SYSTEM \"first.ent\">\n"
11574        "%import;\n"
11575        "]>\n"
11576        "<r/>\n",
11577        "<![%draft;[<!--1-->]]>\n"
11578        "<![%final;[<!--22-->]]>",
11579        NULL, sizeof(XML_Char) * (strlen("INCLUDE") + strlen("IGNORE")),
11580        filled_later},
11581 
11582       /* General entities */
11583       {"<!DOCTYPE root [\n"
11584        "<!ENTITY nine \"123456789\">\n"
11585        "]>\n"
11586        "<root>&nine;</root>",
11587        NULL, NULL, sizeof(XML_Char) * strlen("123456789"), filled_later},
11588       {"<!DOCTYPE root [\n"
11589        "<!ENTITY nine \"123456789\">\n"
11590        "]>\n"
11591        "<root k1=\"&nine;\"/>",
11592        NULL, NULL, sizeof(XML_Char) * strlen("123456789"), filled_later},
11593       {"<!DOCTYPE root [\n"
11594        "<!ENTITY nine \"123456789\">\n"
11595        "<!ENTITY nine2 \"&nine;&nine;\">\n"
11596        "]>\n"
11597        "<root>&nine2;&nine2;&nine2;</root>",
11598        NULL, NULL,
11599        sizeof(XML_Char) * 3 /* calls to &nine2; */ * 2 /* calls to &nine; */
11600            * (strlen("&nine;") + strlen("123456789")),
11601        filled_later},
11602       {"<!DOCTYPE r [\n"
11603        "  <!ENTITY five SYSTEM 'first.ent'>\n"
11604        "]>\n"
11605        "<r>&five;</r>",
11606        "12345", NULL, 0, filled_later},
11607 
11608       /* Parameter entities */
11609       {"<!DOCTYPE r [\n"
11610        "<!ENTITY % comment \"<!---->\">\n"
11611        "%comment;\n"
11612        "]>\n"
11613        "<r/>",
11614        NULL, NULL, sizeof(XML_Char) * strlen("<!---->"), filled_later},
11615       {"<!DOCTYPE r [\n"
11616        "<!ENTITY % ninedef \"&#60;!ENTITY nine &#34;123456789&#34;&#62;\">\n"
11617        "%ninedef;\n"
11618        "]>\n"
11619        "<r>&nine;</r>",
11620        NULL, NULL,
11621        sizeof(XML_Char)
11622            * (strlen("<!ENTITY nine \"123456789\">") + strlen("123456789")),
11623        filled_later},
11624       {"<!DOCTYPE r [\n"
11625        "<!ENTITY % comment \"<!--1-->\">\n"
11626        "<!ENTITY % comment2 \"&#37;comment;<!--22-->&#37;comment;\">\n"
11627        "%comment2;\n"
11628        "]>\n"
11629        "<r/>\n",
11630        NULL, NULL,
11631        sizeof(XML_Char)
11632            * (strlen("%comment;<!--22-->%comment;") + 2 * strlen("<!--1-->")),
11633        filled_later},
11634       {"<!DOCTYPE r [\n"
11635        "  <!ENTITY % five \"12345\">\n"
11636        "  <!ENTITY % five2def \"&#60;!ENTITY five2 &#34;[&#37;five;][&#37;five;]]]]&#34;&#62;\">\n"
11637        "  %five2def;\n"
11638        "]>\n"
11639        "<r>&five2;</r>",
11640        NULL, NULL, /* from "%five2def;": */
11641        sizeof(XML_Char)
11642            * (strlen("<!ENTITY five2 \"[%five;][%five;]]]]\">")
11643               + 2 /* calls to "%five;" */ * strlen("12345")
11644               + /* from "&five2;": */ strlen("[12345][12345]]]]")),
11645        filled_later},
11646       {"<!DOCTYPE r SYSTEM \"first.ent\">\n"
11647        "<r/>",
11648        "<!ENTITY % comment '<!--1-->'>\n"
11649        "<!ENTITY % comment2 '<!--22-->%comment;<!--22-->%comment;<!--22-->'>\n"
11650        "%comment2;",
11651        NULL,
11652        sizeof(XML_Char)
11653            * (strlen("<!--22-->%comment;<!--22-->%comment;<!--22-->")
11654               + 2 /* calls to "%comment;" */ * strlen("<!---->")),
11655        filled_later},
11656       {"<!DOCTYPE r SYSTEM 'first.ent'>\n"
11657        "<r/>",
11658        "<!ENTITY % e1 PUBLIC 'foo' 'second.ent'>\n"
11659        "<!ENTITY % e2 '<!--22-->%e1;<!--22-->'>\n"
11660        "%e2;\n",
11661        "<!--1-->", sizeof(XML_Char) * strlen("<!--22--><!--1--><!--22-->"),
11662        filled_later},
11663       {
11664           "<!DOCTYPE r SYSTEM 'first.ent'>\n"
11665           "<r/>",
11666           "<!ENTITY % e1 SYSTEM 'second.ent'>\n"
11667           "<!ENTITY % e2 '%e1;'>",
11668           "<?xml version='1.0' encoding='utf-8'?>\n"
11669           "hello\n"
11670           "xml" /* without trailing newline! */,
11671           0,
11672           filled_later,
11673       },
11674       {
11675           "<!DOCTYPE r SYSTEM 'first.ent'>\n"
11676           "<r/>",
11677           "<!ENTITY % e1 SYSTEM 'second.ent'>\n"
11678           "<!ENTITY % e2 '%e1;'>",
11679           "<?xml version='1.0' encoding='utf-8'?>\n"
11680           "hello\n"
11681           "xml\n" /* with trailing newline! */,
11682           0,
11683           filled_later,
11684       },
11685       {"<!DOCTYPE doc SYSTEM 'first.ent'>\n"
11686        "<doc></doc>\n",
11687        "<!ELEMENT doc EMPTY>\n"
11688        "<!ENTITY % e1 SYSTEM 'second.ent'>\n"
11689        "<!ENTITY % e2 '%e1;'>\n"
11690        "%e1;\n",
11691        "\xEF\xBB\xBF<!ATTLIST doc a1 CDATA 'value'>" /* UTF-8 BOM */,
11692        strlen("\xEF\xBB\xBF<!ATTLIST doc a1 CDATA 'value'>"), filled_later},
11693       {"<!DOCTYPE r [\n"
11694        "  <!ENTITY five SYSTEM 'first.ent'>\n"
11695        "]>\n"
11696        "<r>&five;</r>",
11697        "\xEF\xBB\xBF" /* UTF-8 BOM */, NULL, 0, filled_later},
11698   };
11699 
11700   const size_t countCases = sizeof(cases) / sizeof(cases[0]);
11701   size_t u = 0;
11702   for (; u < countCases; u++) {
11703     size_t v = 0;
11704     for (; v < 2; v++) {
11705       const XML_Bool singleBytesWanted = (v == 0) ? XML_FALSE : XML_TRUE;
11706       const unsigned long long expectedCountBytesDirect
11707           = strlen(cases[u].primaryText);
11708       const unsigned long long expectedCountBytesIndirect
11709           = (cases[u].firstExternalText ? strlen(cases[u].firstExternalText)
11710                                         : 0)
11711             + (cases[u].secondExternalText ? strlen(cases[u].secondExternalText)
11712                                            : 0)
11713             + cases[u].expectedCountBytesIndirectExtra;
11714 
11715       XML_Parser parser = XML_ParserCreate(NULL);
11716       XML_SetParamEntityParsing(parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
11717       if (cases[u].firstExternalText) {
11718         XML_SetExternalEntityRefHandler(parser,
11719                                         accounting_external_entity_ref_handler);
11720         XML_SetUserData(parser, (void *)&cases[u]);
11721         cases[u].singleBytesWanted = singleBytesWanted;
11722       }
11723 
11724       const XmlParseFunction xmlParseFunction
11725           = singleBytesWanted ? _XML_Parse_SINGLE_BYTES : XML_Parse;
11726 
11727       enum XML_Status status
11728           = xmlParseFunction(parser, cases[u].primaryText,
11729                              (int)strlen(cases[u].primaryText), XML_TRUE);
11730       if (status != XML_STATUS_OK) {
11731         _xml_failure(parser, __FILE__, __LINE__);
11732       }
11733 
11734       const unsigned long long actualCountBytesDirect
11735           = testingAccountingGetCountBytesDirect(parser);
11736       const unsigned long long actualCountBytesIndirect
11737           = testingAccountingGetCountBytesIndirect(parser);
11738 
11739       XML_ParserFree(parser);
11740 
11741       if (actualCountBytesDirect != expectedCountBytesDirect) {
11742         fprintf(
11743             stderr,
11744             "Document " EXPAT_FMT_SIZE_T("") " of " EXPAT_FMT_SIZE_T("") ", %s: Expected " EXPAT_FMT_ULL(
11745                 "") " count direct bytes, got " EXPAT_FMT_ULL("") " instead.\n",
11746             u + 1, countCases, singleBytesWanted ? "single bytes" : "chunks",
11747             expectedCountBytesDirect, actualCountBytesDirect);
11748         fail("Count of direct bytes is off");
11749       }
11750 
11751       if (actualCountBytesIndirect != expectedCountBytesIndirect) {
11752         fprintf(
11753             stderr,
11754             "Document " EXPAT_FMT_SIZE_T("") " of " EXPAT_FMT_SIZE_T("") ", %s: Expected " EXPAT_FMT_ULL(
11755                 "") " count indirect bytes, got " EXPAT_FMT_ULL("") " instead.\n",
11756             u + 1, countCases, singleBytesWanted ? "single bytes" : "chunks",
11757             expectedCountBytesIndirect, actualCountBytesIndirect);
11758         fail("Count of indirect bytes is off");
11759       }
11760     }
11761   }
11762 }
11763 END_TEST
11764 
11765 START_TEST(test_billion_laughs_attack_protection_api) {
11766   XML_Parser parserWithoutParent = XML_ParserCreate(NULL);
11767   XML_Parser parserWithParent
11768       = XML_ExternalEntityParserCreate(parserWithoutParent, NULL, NULL);
11769   if (parserWithoutParent == NULL)
11770     fail("parserWithoutParent is NULL");
11771   if (parserWithParent == NULL)
11772     fail("parserWithParent is NULL");
11773 
11774   // XML_SetBillionLaughsAttackProtectionMaximumAmplification, error cases
11775   if (XML_SetBillionLaughsAttackProtectionMaximumAmplification(NULL, 123.0f)
11776       == XML_TRUE)
11777     fail("Call with NULL parser is NOT supposed to succeed");
11778   if (XML_SetBillionLaughsAttackProtectionMaximumAmplification(parserWithParent,
11779                                                                123.0f)
11780       == XML_TRUE)
11781     fail("Call with non-root parser is NOT supposed to succeed");
11782   if (XML_SetBillionLaughsAttackProtectionMaximumAmplification(
11783           parserWithoutParent, NAN)
11784       == XML_TRUE)
11785     fail("Call with NaN limit is NOT supposed to succeed");
11786   if (XML_SetBillionLaughsAttackProtectionMaximumAmplification(
11787           parserWithoutParent, -1.0f)
11788       == XML_TRUE)
11789     fail("Call with negative limit is NOT supposed to succeed");
11790   if (XML_SetBillionLaughsAttackProtectionMaximumAmplification(
11791           parserWithoutParent, 0.9f)
11792       == XML_TRUE)
11793     fail("Call with positive limit <1.0 is NOT supposed to succeed");
11794 
11795   // XML_SetBillionLaughsAttackProtectionMaximumAmplification, success cases
11796   if (XML_SetBillionLaughsAttackProtectionMaximumAmplification(
11797           parserWithoutParent, 1.0f)
11798       == XML_FALSE)
11799     fail("Call with positive limit >=1.0 is supposed to succeed");
11800   if (XML_SetBillionLaughsAttackProtectionMaximumAmplification(
11801           parserWithoutParent, 123456.789f)
11802       == XML_FALSE)
11803     fail("Call with positive limit >=1.0 is supposed to succeed");
11804   if (XML_SetBillionLaughsAttackProtectionMaximumAmplification(
11805           parserWithoutParent, INFINITY)
11806       == XML_FALSE)
11807     fail("Call with positive limit >=1.0 is supposed to succeed");
11808 
11809   // XML_SetBillionLaughsAttackProtectionActivationThreshold, error cases
11810   if (XML_SetBillionLaughsAttackProtectionActivationThreshold(NULL, 123)
11811       == XML_TRUE)
11812     fail("Call with NULL parser is NOT supposed to succeed");
11813   if (XML_SetBillionLaughsAttackProtectionActivationThreshold(parserWithParent,
11814                                                               123)
11815       == XML_TRUE)
11816     fail("Call with non-root parser is NOT supposed to succeed");
11817 
11818   // XML_SetBillionLaughsAttackProtectionActivationThreshold, success cases
11819   if (XML_SetBillionLaughsAttackProtectionActivationThreshold(
11820           parserWithoutParent, 123)
11821       == XML_FALSE)
11822     fail("Call with non-NULL parentless parser is supposed to succeed");
11823 
11824   XML_ParserFree(parserWithParent);
11825   XML_ParserFree(parserWithoutParent);
11826 }
11827 END_TEST
11828 
11829 START_TEST(test_helper_unsigned_char_to_printable) {
11830   // Smoke test
11831   unsigned char uc = 0;
11832   for (; uc < (unsigned char)-1; uc++) {
11833     const char *const printable = unsignedCharToPrintable(uc);
11834     if (printable == NULL)
11835       fail("unsignedCharToPrintable returned NULL");
11836     if (strlen(printable) < (size_t)1)
11837       fail("unsignedCharToPrintable returned empty string");
11838   }
11839 
11840   // Two concrete samples
11841   if (strcmp(unsignedCharToPrintable('A'), "A") != 0)
11842     fail("unsignedCharToPrintable result mistaken");
11843   if (strcmp(unsignedCharToPrintable('\\'), "\\\\") != 0)
11844     fail("unsignedCharToPrintable result mistaken");
11845 }
11846 END_TEST
11847 #endif // defined(XML_DTD)
11848 
11849 static Suite *
11850 make_suite(void) {
11851   Suite *s = suite_create("basic");
11852   TCase *tc_basic = tcase_create("basic tests");
11853   TCase *tc_namespace = tcase_create("XML namespaces");
11854   TCase *tc_misc = tcase_create("miscellaneous tests");
11855   TCase *tc_alloc = tcase_create("allocation tests");
11856   TCase *tc_nsalloc = tcase_create("namespace allocation tests");
11857 #if defined(XML_DTD)
11858   TCase *tc_accounting = tcase_create("accounting tests");
11859 #endif
11860 
11861   suite_add_tcase(s, tc_basic);
11862   tcase_add_checked_fixture(tc_basic, basic_setup, basic_teardown);
11863   tcase_add_test(tc_basic, test_nul_byte);
11864   tcase_add_test(tc_basic, test_u0000_char);
11865   tcase_add_test(tc_basic, test_siphash_self);
11866   tcase_add_test(tc_basic, test_siphash_spec);
11867   tcase_add_test(tc_basic, test_bom_utf8);
11868   tcase_add_test(tc_basic, test_bom_utf16_be);
11869   tcase_add_test(tc_basic, test_bom_utf16_le);
11870   tcase_add_test(tc_basic, test_nobom_utf16_le);
11871   tcase_add_test(tc_basic, test_illegal_utf8);
11872   tcase_add_test(tc_basic, test_utf8_auto_align);
11873   tcase_add_test(tc_basic, test_utf16);
11874   tcase_add_test(tc_basic, test_utf16_le_epilog_newline);
11875   tcase_add_test(tc_basic, test_not_utf16);
11876   tcase_add_test(tc_basic, test_bad_encoding);
11877   tcase_add_test(tc_basic, test_latin1_umlauts);
11878   tcase_add_test(tc_basic, test_long_utf8_character);
11879   tcase_add_test(tc_basic, test_long_latin1_attribute);
11880   tcase_add_test(tc_basic, test_long_ascii_attribute);
11881   /* Regression test for SF bug #491986. */
11882   tcase_add_test(tc_basic, test_danish_latin1);
11883   /* Regression test for SF bug #514281. */
11884   tcase_add_test(tc_basic, test_french_charref_hexidecimal);
11885   tcase_add_test(tc_basic, test_french_charref_decimal);
11886   tcase_add_test(tc_basic, test_french_latin1);
11887   tcase_add_test(tc_basic, test_french_utf8);
11888   tcase_add_test(tc_basic, test_utf8_false_rejection);
11889   tcase_add_test(tc_basic, test_line_number_after_parse);
11890   tcase_add_test(tc_basic, test_column_number_after_parse);
11891   tcase_add_test(tc_basic, test_line_and_column_numbers_inside_handlers);
11892   tcase_add_test(tc_basic, test_line_number_after_error);
11893   tcase_add_test(tc_basic, test_column_number_after_error);
11894   tcase_add_test(tc_basic, test_really_long_lines);
11895   tcase_add_test(tc_basic, test_really_long_encoded_lines);
11896   tcase_add_test(tc_basic, test_end_element_events);
11897   tcase_add_test(tc_basic, test_attr_whitespace_normalization);
11898   tcase_add_test(tc_basic, test_xmldecl_misplaced);
11899   tcase_add_test(tc_basic, test_xmldecl_invalid);
11900   tcase_add_test(tc_basic, test_xmldecl_missing_attr);
11901   tcase_add_test(tc_basic, test_xmldecl_missing_value);
11902   tcase_add_test(tc_basic, test_unknown_encoding_internal_entity);
11903   tcase_add_test(tc_basic, test_unrecognised_encoding_internal_entity);
11904   tcase_add_test(tc_basic, test_wfc_undeclared_entity_unread_external_subset);
11905   tcase_add_test(tc_basic, test_wfc_undeclared_entity_no_external_subset);
11906   tcase_add_test(tc_basic, test_wfc_undeclared_entity_standalone);
11907   tcase_add_test(tc_basic, test_wfc_undeclared_entity_with_external_subset);
11908   tcase_add_test(tc_basic, test_not_standalone_handler_reject);
11909   tcase_add_test(tc_basic, test_not_standalone_handler_accept);
11910   tcase_add_test(tc_basic,
11911                  test_wfc_undeclared_entity_with_external_subset_standalone);
11912   tcase_add_test(tc_basic, test_entity_with_external_subset_unless_standalone);
11913   tcase_add_test(tc_basic, test_wfc_no_recursive_entity_refs);
11914   tcase_add_test__ifdef_xml_dtd(tc_basic, test_ext_entity_set_encoding);
11915   tcase_add_test__ifdef_xml_dtd(tc_basic, test_ext_entity_no_handler);
11916   tcase_add_test__ifdef_xml_dtd(tc_basic, test_ext_entity_set_bom);
11917   tcase_add_test__ifdef_xml_dtd(tc_basic, test_ext_entity_bad_encoding);
11918   tcase_add_test__ifdef_xml_dtd(tc_basic, test_ext_entity_bad_encoding_2);
11919   tcase_add_test__ifdef_xml_dtd(tc_basic, test_ext_entity_invalid_parse);
11920   tcase_add_test__ifdef_xml_dtd(tc_basic,
11921                                 test_ext_entity_invalid_suspended_parse);
11922   tcase_add_test(tc_basic, test_dtd_default_handling);
11923   tcase_add_test(tc_basic, test_dtd_attr_handling);
11924   tcase_add_test(tc_basic, test_empty_ns_without_namespaces);
11925   tcase_add_test(tc_basic, test_ns_in_attribute_default_without_namespaces);
11926   tcase_add_test(tc_basic, test_stop_parser_between_char_data_calls);
11927   tcase_add_test(tc_basic, test_suspend_parser_between_char_data_calls);
11928   tcase_add_test(tc_basic, test_repeated_stop_parser_between_char_data_calls);
11929   tcase_add_test(tc_basic, test_good_cdata_ascii);
11930   tcase_add_test(tc_basic, test_good_cdata_utf16);
11931   tcase_add_test(tc_basic, test_good_cdata_utf16_le);
11932   tcase_add_test(tc_basic, test_long_cdata_utf16);
11933   tcase_add_test(tc_basic, test_multichar_cdata_utf16);
11934   tcase_add_test(tc_basic, test_utf16_bad_surrogate_pair);
11935   tcase_add_test(tc_basic, test_bad_cdata);
11936   tcase_add_test(tc_basic, test_bad_cdata_utf16);
11937   tcase_add_test(tc_basic, test_stop_parser_between_cdata_calls);
11938   tcase_add_test(tc_basic, test_suspend_parser_between_cdata_calls);
11939   tcase_add_test(tc_basic, test_memory_allocation);
11940   tcase_add_test(tc_basic, test_default_current);
11941   tcase_add_test(tc_basic, test_dtd_elements);
11942   tcase_add_test(tc_basic, test_dtd_elements_nesting);
11943   tcase_add_test__ifdef_xml_dtd(tc_basic, test_set_foreign_dtd);
11944   tcase_add_test__ifdef_xml_dtd(tc_basic, test_foreign_dtd_not_standalone);
11945   tcase_add_test__ifdef_xml_dtd(tc_basic, test_invalid_foreign_dtd);
11946   tcase_add_test__ifdef_xml_dtd(tc_basic, test_foreign_dtd_with_doctype);
11947   tcase_add_test__ifdef_xml_dtd(tc_basic,
11948                                 test_foreign_dtd_without_external_subset);
11949   tcase_add_test__ifdef_xml_dtd(tc_basic, test_empty_foreign_dtd);
11950   tcase_add_test(tc_basic, test_set_base);
11951   tcase_add_test(tc_basic, test_attributes);
11952   tcase_add_test(tc_basic, test_reset_in_entity);
11953   tcase_add_test(tc_basic, test_resume_invalid_parse);
11954   tcase_add_test(tc_basic, test_resume_resuspended);
11955   tcase_add_test(tc_basic, test_cdata_default);
11956   tcase_add_test(tc_basic, test_subordinate_reset);
11957   tcase_add_test(tc_basic, test_subordinate_suspend);
11958   tcase_add_test(tc_basic, test_subordinate_xdecl_suspend);
11959   tcase_add_test(tc_basic, test_subordinate_xdecl_abort);
11960   tcase_add_test(tc_basic, test_explicit_encoding);
11961   tcase_add_test(tc_basic, test_trailing_cr);
11962   tcase_add_test(tc_basic, test_ext_entity_trailing_cr);
11963   tcase_add_test(tc_basic, test_trailing_rsqb);
11964   tcase_add_test(tc_basic, test_ext_entity_trailing_rsqb);
11965   tcase_add_test(tc_basic, test_ext_entity_good_cdata);
11966   tcase_add_test__ifdef_xml_dtd(tc_basic, test_user_parameters);
11967   tcase_add_test__ifdef_xml_dtd(tc_basic, test_ext_entity_ref_parameter);
11968   tcase_add_test(tc_basic, test_empty_parse);
11969   tcase_add_test(tc_basic, test_get_buffer_1);
11970   tcase_add_test(tc_basic, test_get_buffer_2);
11971 #if defined(XML_CONTEXT_BYTES)
11972   tcase_add_test(tc_basic, test_get_buffer_3_overflow);
11973 #endif
11974   tcase_add_test(tc_basic, test_byte_info_at_end);
11975   tcase_add_test(tc_basic, test_byte_info_at_error);
11976   tcase_add_test(tc_basic, test_byte_info_at_cdata);
11977   tcase_add_test(tc_basic, test_predefined_entities);
11978   tcase_add_test__ifdef_xml_dtd(tc_basic, test_invalid_tag_in_dtd);
11979   tcase_add_test(tc_basic, test_not_predefined_entities);
11980   tcase_add_test__ifdef_xml_dtd(tc_basic, test_ignore_section);
11981   tcase_add_test__ifdef_xml_dtd(tc_basic, test_ignore_section_utf16);
11982   tcase_add_test__ifdef_xml_dtd(tc_basic, test_ignore_section_utf16_be);
11983   tcase_add_test__ifdef_xml_dtd(tc_basic, test_bad_ignore_section);
11984   tcase_add_test__ifdef_xml_dtd(tc_basic, test_external_entity_values);
11985   tcase_add_test__ifdef_xml_dtd(tc_basic, test_ext_entity_not_standalone);
11986   tcase_add_test__ifdef_xml_dtd(tc_basic, test_ext_entity_value_abort);
11987   tcase_add_test(tc_basic, test_bad_public_doctype);
11988   tcase_add_test(tc_basic, test_attribute_enum_value);
11989   tcase_add_test(tc_basic, test_predefined_entity_redefinition);
11990   tcase_add_test__ifdef_xml_dtd(tc_basic, test_dtd_stop_processing);
11991   tcase_add_test(tc_basic, test_public_notation_no_sysid);
11992   tcase_add_test(tc_basic, test_nested_groups);
11993   tcase_add_test(tc_basic, test_group_choice);
11994   tcase_add_test(tc_basic, test_standalone_parameter_entity);
11995   tcase_add_test__ifdef_xml_dtd(tc_basic, test_skipped_parameter_entity);
11996   tcase_add_test__ifdef_xml_dtd(tc_basic,
11997                                 test_recursive_external_parameter_entity);
11998   tcase_add_test(tc_basic, test_undefined_ext_entity_in_external_dtd);
11999   tcase_add_test(tc_basic, test_suspend_xdecl);
12000   tcase_add_test(tc_basic, test_abort_epilog);
12001   tcase_add_test(tc_basic, test_abort_epilog_2);
12002   tcase_add_test(tc_basic, test_suspend_epilog);
12003   tcase_add_test(tc_basic, test_suspend_in_sole_empty_tag);
12004   tcase_add_test(tc_basic, test_unfinished_epilog);
12005   tcase_add_test(tc_basic, test_partial_char_in_epilog);
12006   tcase_add_test(tc_basic, test_hash_collision);
12007   tcase_add_test__ifdef_xml_dtd(tc_basic, test_suspend_resume_internal_entity);
12008   tcase_add_test__ifdef_xml_dtd(tc_basic, test_resume_entity_with_syntax_error);
12009   tcase_add_test__ifdef_xml_dtd(tc_basic, test_suspend_resume_parameter_entity);
12010   tcase_add_test(tc_basic, test_restart_on_error);
12011   tcase_add_test(tc_basic, test_reject_lt_in_attribute_value);
12012   tcase_add_test(tc_basic, test_reject_unfinished_param_in_att_value);
12013   tcase_add_test(tc_basic, test_trailing_cr_in_att_value);
12014   tcase_add_test(tc_basic, test_standalone_internal_entity);
12015   tcase_add_test(tc_basic, test_skipped_external_entity);
12016   tcase_add_test(tc_basic, test_skipped_null_loaded_ext_entity);
12017   tcase_add_test(tc_basic, test_skipped_unloaded_ext_entity);
12018   tcase_add_test__ifdef_xml_dtd(tc_basic, test_param_entity_with_trailing_cr);
12019   tcase_add_test(tc_basic, test_invalid_character_entity);
12020   tcase_add_test(tc_basic, test_invalid_character_entity_2);
12021   tcase_add_test(tc_basic, test_invalid_character_entity_3);
12022   tcase_add_test(tc_basic, test_invalid_character_entity_4);
12023   tcase_add_test(tc_basic, test_pi_handled_in_default);
12024   tcase_add_test(tc_basic, test_comment_handled_in_default);
12025   tcase_add_test(tc_basic, test_pi_yml);
12026   tcase_add_test(tc_basic, test_pi_xnl);
12027   tcase_add_test(tc_basic, test_pi_xmm);
12028   tcase_add_test(tc_basic, test_utf16_pi);
12029   tcase_add_test(tc_basic, test_utf16_be_pi);
12030   tcase_add_test(tc_basic, test_utf16_be_comment);
12031   tcase_add_test(tc_basic, test_utf16_le_comment);
12032   tcase_add_test(tc_basic, test_missing_encoding_conversion_fn);
12033   tcase_add_test(tc_basic, test_failing_encoding_conversion_fn);
12034   tcase_add_test(tc_basic, test_unknown_encoding_success);
12035   tcase_add_test(tc_basic, test_unknown_encoding_bad_name);
12036   tcase_add_test(tc_basic, test_unknown_encoding_bad_name_2);
12037   tcase_add_test(tc_basic, test_unknown_encoding_long_name_1);
12038   tcase_add_test(tc_basic, test_unknown_encoding_long_name_2);
12039   tcase_add_test(tc_basic, test_invalid_unknown_encoding);
12040   tcase_add_test(tc_basic, test_unknown_ascii_encoding_ok);
12041   tcase_add_test(tc_basic, test_unknown_ascii_encoding_fail);
12042   tcase_add_test(tc_basic, test_unknown_encoding_invalid_length);
12043   tcase_add_test(tc_basic, test_unknown_encoding_invalid_topbit);
12044   tcase_add_test(tc_basic, test_unknown_encoding_invalid_surrogate);
12045   tcase_add_test(tc_basic, test_unknown_encoding_invalid_high);
12046   tcase_add_test(tc_basic, test_unknown_encoding_invalid_attr_value);
12047   tcase_add_test(tc_basic, test_ext_entity_latin1_utf16le_bom);
12048   tcase_add_test(tc_basic, test_ext_entity_latin1_utf16be_bom);
12049   tcase_add_test(tc_basic, test_ext_entity_latin1_utf16le_bom2);
12050   tcase_add_test(tc_basic, test_ext_entity_latin1_utf16be_bom2);
12051   tcase_add_test(tc_basic, test_ext_entity_utf16_be);
12052   tcase_add_test(tc_basic, test_ext_entity_utf16_le);
12053   tcase_add_test(tc_basic, test_ext_entity_utf16_unknown);
12054   tcase_add_test(tc_basic, test_ext_entity_utf8_non_bom);
12055   tcase_add_test(tc_basic, test_utf8_in_cdata_section);
12056   tcase_add_test(tc_basic, test_utf8_in_cdata_section_2);
12057   tcase_add_test(tc_basic, test_utf8_in_start_tags);
12058   tcase_add_test(tc_basic, test_trailing_spaces_in_elements);
12059   tcase_add_test(tc_basic, test_utf16_attribute);
12060   tcase_add_test(tc_basic, test_utf16_second_attr);
12061   tcase_add_test(tc_basic, test_attr_after_solidus);
12062   tcase_add_test__ifdef_xml_dtd(tc_basic, test_utf16_pe);
12063   tcase_add_test(tc_basic, test_bad_attr_desc_keyword);
12064   tcase_add_test(tc_basic, test_bad_attr_desc_keyword_utf16);
12065   tcase_add_test(tc_basic, test_bad_doctype);
12066   tcase_add_test(tc_basic, test_bad_doctype_utf8);
12067   tcase_add_test(tc_basic, test_bad_doctype_utf16);
12068   tcase_add_test(tc_basic, test_bad_doctype_plus);
12069   tcase_add_test(tc_basic, test_bad_doctype_star);
12070   tcase_add_test(tc_basic, test_bad_doctype_query);
12071   tcase_add_test__ifdef_xml_dtd(tc_basic, test_unknown_encoding_bad_ignore);
12072   tcase_add_test(tc_basic, test_entity_in_utf16_be_attr);
12073   tcase_add_test(tc_basic, test_entity_in_utf16_le_attr);
12074   tcase_add_test__ifdef_xml_dtd(tc_basic, test_entity_public_utf16_be);
12075   tcase_add_test__ifdef_xml_dtd(tc_basic, test_entity_public_utf16_le);
12076   tcase_add_test(tc_basic, test_short_doctype);
12077   tcase_add_test(tc_basic, test_short_doctype_2);
12078   tcase_add_test(tc_basic, test_short_doctype_3);
12079   tcase_add_test(tc_basic, test_long_doctype);
12080   tcase_add_test(tc_basic, test_bad_entity);
12081   tcase_add_test(tc_basic, test_bad_entity_2);
12082   tcase_add_test(tc_basic, test_bad_entity_3);
12083   tcase_add_test(tc_basic, test_bad_entity_4);
12084   tcase_add_test(tc_basic, test_bad_notation);
12085   tcase_add_test(tc_basic, test_default_doctype_handler);
12086   tcase_add_test(tc_basic, test_empty_element_abort);
12087 
12088   suite_add_tcase(s, tc_namespace);
12089   tcase_add_checked_fixture(tc_namespace, namespace_setup, namespace_teardown);
12090   tcase_add_test(tc_namespace, test_return_ns_triplet);
12091   tcase_add_test(tc_namespace, test_ns_tagname_overwrite);
12092   tcase_add_test(tc_namespace, test_ns_tagname_overwrite_triplet);
12093   tcase_add_test(tc_namespace, test_start_ns_clears_start_element);
12094   tcase_add_test__ifdef_xml_dtd(tc_namespace,
12095                                 test_default_ns_from_ext_subset_and_ext_ge);
12096   tcase_add_test(tc_namespace, test_ns_prefix_with_empty_uri_1);
12097   tcase_add_test(tc_namespace, test_ns_prefix_with_empty_uri_2);
12098   tcase_add_test(tc_namespace, test_ns_prefix_with_empty_uri_3);
12099   tcase_add_test(tc_namespace, test_ns_prefix_with_empty_uri_4);
12100   tcase_add_test(tc_namespace, test_ns_unbound_prefix);
12101   tcase_add_test(tc_namespace, test_ns_default_with_empty_uri);
12102   tcase_add_test(tc_namespace, test_ns_duplicate_attrs_diff_prefixes);
12103   tcase_add_test(tc_namespace, test_ns_duplicate_hashes);
12104   tcase_add_test(tc_namespace, test_ns_unbound_prefix_on_attribute);
12105   tcase_add_test(tc_namespace, test_ns_unbound_prefix_on_element);
12106   tcase_add_test(tc_namespace, test_ns_parser_reset);
12107   tcase_add_test(tc_namespace, test_ns_long_element);
12108   tcase_add_test(tc_namespace, test_ns_mixed_prefix_atts);
12109   tcase_add_test(tc_namespace, test_ns_extend_uri_buffer);
12110   tcase_add_test(tc_namespace, test_ns_reserved_attributes);
12111   tcase_add_test(tc_namespace, test_ns_reserved_attributes_2);
12112   tcase_add_test(tc_namespace, test_ns_extremely_long_prefix);
12113   tcase_add_test(tc_namespace, test_ns_unknown_encoding_success);
12114   tcase_add_test(tc_namespace, test_ns_double_colon);
12115   tcase_add_test(tc_namespace, test_ns_double_colon_element);
12116   tcase_add_test(tc_namespace, test_ns_bad_attr_leafname);
12117   tcase_add_test(tc_namespace, test_ns_bad_element_leafname);
12118   tcase_add_test(tc_namespace, test_ns_utf16_leafname);
12119   tcase_add_test(tc_namespace, test_ns_utf16_element_leafname);
12120   tcase_add_test(tc_namespace, test_ns_utf16_doctype);
12121   tcase_add_test(tc_namespace, test_ns_invalid_doctype);
12122   tcase_add_test(tc_namespace, test_ns_double_colon_doctype);
12123   tcase_add_test(tc_namespace, test_ns_separator_in_uri);
12124 
12125   suite_add_tcase(s, tc_misc);
12126   tcase_add_checked_fixture(tc_misc, NULL, basic_teardown);
12127   tcase_add_test(tc_misc, test_misc_alloc_create_parser);
12128   tcase_add_test(tc_misc, test_misc_alloc_create_parser_with_encoding);
12129   tcase_add_test(tc_misc, test_misc_null_parser);
12130   tcase_add_test(tc_misc, test_misc_error_string);
12131   tcase_add_test(tc_misc, test_misc_version);
12132   tcase_add_test(tc_misc, test_misc_features);
12133   tcase_add_test(tc_misc, test_misc_attribute_leak);
12134   tcase_add_test(tc_misc, test_misc_utf16le);
12135   tcase_add_test(tc_misc, test_misc_stop_during_end_handler_issue_240_1);
12136   tcase_add_test(tc_misc, test_misc_stop_during_end_handler_issue_240_2);
12137   tcase_add_test__ifdef_xml_dtd(
12138       tc_misc, test_misc_deny_internal_entity_closing_doctype_issue_317);
12139 
12140   suite_add_tcase(s, tc_alloc);
12141   tcase_add_checked_fixture(tc_alloc, alloc_setup, alloc_teardown);
12142   tcase_add_test(tc_alloc, test_alloc_parse_xdecl);
12143   tcase_add_test(tc_alloc, test_alloc_parse_xdecl_2);
12144   tcase_add_test(tc_alloc, test_alloc_parse_pi);
12145   tcase_add_test(tc_alloc, test_alloc_parse_pi_2);
12146   tcase_add_test(tc_alloc, test_alloc_parse_pi_3);
12147   tcase_add_test(tc_alloc, test_alloc_parse_comment);
12148   tcase_add_test(tc_alloc, test_alloc_parse_comment_2);
12149   tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_create_external_parser);
12150   tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_run_external_parser);
12151   tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_dtd_copy_default_atts);
12152   tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_external_entity);
12153   tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_ext_entity_set_encoding);
12154   tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_internal_entity);
12155   tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_dtd_default_handling);
12156   tcase_add_test(tc_alloc, test_alloc_explicit_encoding);
12157   tcase_add_test(tc_alloc, test_alloc_set_base);
12158   tcase_add_test(tc_alloc, test_alloc_realloc_buffer);
12159   tcase_add_test(tc_alloc, test_alloc_ext_entity_realloc_buffer);
12160   tcase_add_test(tc_alloc, test_alloc_realloc_many_attributes);
12161   tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_public_entity_value);
12162   tcase_add_test__ifdef_xml_dtd(tc_alloc,
12163                                 test_alloc_realloc_subst_public_entity_value);
12164   tcase_add_test(tc_alloc, test_alloc_parse_public_doctype);
12165   tcase_add_test(tc_alloc, test_alloc_parse_public_doctype_long_name);
12166   tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_set_foreign_dtd);
12167   tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_attribute_enum_value);
12168   tcase_add_test__ifdef_xml_dtd(tc_alloc,
12169                                 test_alloc_realloc_attribute_enum_value);
12170   tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_realloc_implied_attribute);
12171   tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_realloc_default_attribute);
12172   tcase_add_test(tc_alloc, test_alloc_notation);
12173   tcase_add_test(tc_alloc, test_alloc_public_notation);
12174   tcase_add_test(tc_alloc, test_alloc_system_notation);
12175   tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_nested_groups);
12176   tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_realloc_nested_groups);
12177   tcase_add_test(tc_alloc, test_alloc_large_group);
12178   tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_realloc_group_choice);
12179   tcase_add_test(tc_alloc, test_alloc_pi_in_epilog);
12180   tcase_add_test(tc_alloc, test_alloc_comment_in_epilog);
12181   tcase_add_test__ifdef_xml_dtd(tc_alloc,
12182                                 test_alloc_realloc_long_attribute_value);
12183   tcase_add_test(tc_alloc, test_alloc_attribute_whitespace);
12184   tcase_add_test(tc_alloc, test_alloc_attribute_predefined_entity);
12185   tcase_add_test(tc_alloc, test_alloc_long_attr_default_with_char_ref);
12186   tcase_add_test(tc_alloc, test_alloc_long_attr_value);
12187   tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_nested_entities);
12188   tcase_add_test__ifdef_xml_dtd(tc_alloc,
12189                                 test_alloc_realloc_param_entity_newline);
12190   tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_realloc_ce_extends_pe);
12191   tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_realloc_attributes);
12192   tcase_add_test(tc_alloc, test_alloc_long_doc_name);
12193   tcase_add_test(tc_alloc, test_alloc_long_base);
12194   tcase_add_test(tc_alloc, test_alloc_long_public_id);
12195   tcase_add_test(tc_alloc, test_alloc_long_entity_value);
12196   tcase_add_test(tc_alloc, test_alloc_long_notation);
12197 
12198   suite_add_tcase(s, tc_nsalloc);
12199   tcase_add_checked_fixture(tc_nsalloc, nsalloc_setup, nsalloc_teardown);
12200   tcase_add_test(tc_nsalloc, test_nsalloc_xmlns);
12201   tcase_add_test(tc_nsalloc, test_nsalloc_parse_buffer);
12202   tcase_add_test(tc_nsalloc, test_nsalloc_long_prefix);
12203   tcase_add_test(tc_nsalloc, test_nsalloc_long_uri);
12204   tcase_add_test(tc_nsalloc, test_nsalloc_long_attr);
12205   tcase_add_test(tc_nsalloc, test_nsalloc_long_attr_prefix);
12206   tcase_add_test(tc_nsalloc, test_nsalloc_realloc_attributes);
12207   tcase_add_test(tc_nsalloc, test_nsalloc_long_element);
12208   tcase_add_test(tc_nsalloc, test_nsalloc_realloc_binding_uri);
12209   tcase_add_test(tc_nsalloc, test_nsalloc_realloc_long_prefix);
12210   tcase_add_test(tc_nsalloc, test_nsalloc_realloc_longer_prefix);
12211   tcase_add_test(tc_nsalloc, test_nsalloc_long_namespace);
12212   tcase_add_test(tc_nsalloc, test_nsalloc_less_long_namespace);
12213   tcase_add_test(tc_nsalloc, test_nsalloc_long_context);
12214   tcase_add_test(tc_nsalloc, test_nsalloc_realloc_long_context);
12215   tcase_add_test(tc_nsalloc, test_nsalloc_realloc_long_context_2);
12216   tcase_add_test(tc_nsalloc, test_nsalloc_realloc_long_context_3);
12217   tcase_add_test(tc_nsalloc, test_nsalloc_realloc_long_context_4);
12218   tcase_add_test(tc_nsalloc, test_nsalloc_realloc_long_context_5);
12219   tcase_add_test(tc_nsalloc, test_nsalloc_realloc_long_context_6);
12220   tcase_add_test(tc_nsalloc, test_nsalloc_realloc_long_context_7);
12221   tcase_add_test(tc_nsalloc, test_nsalloc_realloc_long_ge_name);
12222   tcase_add_test(tc_nsalloc, test_nsalloc_realloc_long_context_in_dtd);
12223   tcase_add_test(tc_nsalloc, test_nsalloc_long_default_in_ext);
12224   tcase_add_test(tc_nsalloc, test_nsalloc_long_systemid_in_ext);
12225   tcase_add_test(tc_nsalloc, test_nsalloc_prefixed_element);
12226 
12227 #if defined(XML_DTD)
12228   suite_add_tcase(s, tc_accounting);
12229   tcase_add_test(tc_accounting, test_accounting_precision);
12230   tcase_add_test(tc_accounting, test_billion_laughs_attack_protection_api);
12231   tcase_add_test(tc_accounting, test_helper_unsigned_char_to_printable);
12232 #endif
12233 
12234   return s;
12235 }
12236 
12237 int
12238 main(int argc, char *argv[]) {
12239   int i, nf;
12240   int verbosity = CK_NORMAL;
12241   Suite *s = make_suite();
12242   SRunner *sr = srunner_create(s);
12243 
12244   /* run the tests for internal helper functions */
12245   testhelper_is_whitespace_normalized();
12246 
12247   for (i = 1; i < argc; ++i) {
12248     char *opt = argv[i];
12249     if (strcmp(opt, "-v") == 0 || strcmp(opt, "--verbose") == 0)
12250       verbosity = CK_VERBOSE;
12251     else if (strcmp(opt, "-q") == 0 || strcmp(opt, "--quiet") == 0)
12252       verbosity = CK_SILENT;
12253     else {
12254       fprintf(stderr, "runtests: unknown option '%s'\n", opt);
12255       return 2;
12256     }
12257   }
12258   if (verbosity != CK_SILENT)
12259     printf("Expat version: %" XML_FMT_STR "\n", XML_ExpatVersion());
12260   srunner_run_all(sr, verbosity);
12261   nf = srunner_ntests_failed(sr);
12262   srunner_free(sr);
12263 
12264   return (nf == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
12265 }
12266