xref: /openbsd-src/lib/libexpat/tests/runtests.c (revision 46035553bfdd96e63c94e32da0210227ec2e3cf1)
1 /* Run the Expat test suite
2                             __  __            _
3                          ___\ \/ /_ __   __ _| |_
4                         / _ \\  /| '_ \ / _` | __|
5                        |  __//  \| |_) | (_| | |_
6                         \___/_/\_\ .__/ \__,_|\__|
7                                  |_| XML parser
8 
9    Copyright (c) 1997-2000 Thai Open Source Software Center Ltd
10    Copyright (c) 2000-2017 Expat development team
11    Licensed under the MIT license:
12 
13    Permission is  hereby granted,  free of charge,  to any  person obtaining
14    a  copy  of  this  software   and  associated  documentation  files  (the
15    "Software"),  to  deal in  the  Software  without restriction,  including
16    without  limitation the  rights  to use,  copy,  modify, merge,  publish,
17    distribute, sublicense, and/or sell copies of the Software, and to permit
18    persons  to whom  the Software  is  furnished to  do so,  subject to  the
19    following conditions:
20 
21    The above copyright  notice and this permission notice  shall be included
22    in all copies or substantial portions of the Software.
23 
24    THE  SOFTWARE  IS  PROVIDED  "AS  IS",  WITHOUT  WARRANTY  OF  ANY  KIND,
25    EXPRESS  OR IMPLIED,  INCLUDING  BUT  NOT LIMITED  TO  THE WARRANTIES  OF
26    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
27    NO EVENT SHALL THE AUTHORS OR  COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
28    DAMAGES OR  OTHER LIABILITY, WHETHER  IN AN  ACTION OF CONTRACT,  TORT OR
29    OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
30    USE OR OTHER DEALINGS IN THE SOFTWARE.
31 */
32 
33 #if defined(NDEBUG)
34 #  undef NDEBUG /* because test suite relies on assert(...) at the moment */
35 #endif
36 
37 #ifdef HAVE_EXPAT_CONFIG_H
38 #  include <expat_config.h>
39 #endif
40 
41 #include <assert.h>
42 #include <stdlib.h>
43 #include <stdio.h>
44 #include <string.h>
45 #include <stddef.h> /* ptrdiff_t */
46 #include <ctype.h>
47 #include <limits.h>
48 
49 #if defined(_WIN32) && defined(_MSC_VER) && (_MSC_VER < 1600)
50 /* For vs2003/7.1 up to vs2008/9.0; _MSC_VER 1600 is vs2010/10.0 */
51 #  if defined(_WIN64)
52 typedef __int64 intptr_t;
53 #  else
54 typedef __int32 intptr_t;
55 #  endif
56 typedef unsigned __int64 uint64_t;
57 #else
58 #  include <stdint.h> /* intptr_t uint64_t */
59 #endif
60 
61 #if ! defined(__cplusplus)
62 #  if defined(_MSC_VER) && (_MSC_VER <= 1700)
63 /* for vs2012/11.0/1700 and earlier Visual Studio compilers */
64 #    define bool int
65 #    define false 0
66 #    define true 1
67 #  else
68 #    include <stdbool.h>
69 #  endif
70 #endif
71 
72 #include "expat.h"
73 #include "chardata.h"
74 #include "structdata.h"
75 #include "internal.h" /* for UNUSED_P only */
76 #include "minicheck.h"
77 #include "memcheck.h"
78 #include "siphash.h"
79 #include "ascii.h" /* for ASCII_xxx */
80 
81 #ifdef XML_LARGE_SIZE
82 #  define XML_FMT_INT_MOD "ll"
83 #else
84 #  define XML_FMT_INT_MOD "l"
85 #endif
86 
87 #ifdef XML_UNICODE_WCHAR_T
88 #  define XML_FMT_CHAR "lc"
89 #  define XML_FMT_STR "ls"
90 #  include <wchar.h>
91 #  define xcstrlen(s) wcslen(s)
92 #  define xcstrcmp(s, t) wcscmp((s), (t))
93 #  define xcstrncmp(s, t, n) wcsncmp((s), (t), (n))
94 #  define XCS(s) _XCS(s)
95 #  define _XCS(s) L##s
96 #else
97 #  ifdef XML_UNICODE
98 #    error "No support for UTF-16 character without wchar_t in tests"
99 #  else
100 #    define XML_FMT_CHAR "c"
101 #    define XML_FMT_STR "s"
102 #    define xcstrlen(s) strlen(s)
103 #    define xcstrcmp(s, t) strcmp((s), (t))
104 #    define xcstrncmp(s, t, n) strncmp((s), (t), (n))
105 #    define XCS(s) s
106 #  endif /* XML_UNICODE */
107 #endif   /* XML_UNICODE_WCHAR_T */
108 
109 static XML_Parser g_parser = NULL;
110 
111 static void
112 tcase_add_test__ifdef_xml_dtd(TCase *tc, tcase_test_function test) {
113 #ifdef XML_DTD
114   tcase_add_test(tc, test);
115 #else
116   UNUSED_P(tc);
117   UNUSED_P(test);
118 #endif
119 }
120 
121 static void
122 basic_setup(void) {
123   g_parser = XML_ParserCreate(NULL);
124   if (g_parser == NULL)
125     fail("Parser not created.");
126 }
127 
128 static void
129 basic_teardown(void) {
130   if (g_parser != NULL) {
131     XML_ParserFree(g_parser);
132     g_parser = NULL;
133   }
134 }
135 
136 /* Generate a failure using the parser state to create an error message;
137    this should be used when the parser reports an error we weren't
138    expecting.
139 */
140 static void
141 _xml_failure(XML_Parser parser, const char *file, int line) {
142   char buffer[1024];
143   enum XML_Error err = XML_GetErrorCode(parser);
144   sprintf(buffer,
145           "    %d: %" XML_FMT_STR " (line %" XML_FMT_INT_MOD
146           "u, offset %" XML_FMT_INT_MOD "u)\n    reported from %s, line %d\n",
147           err, XML_ErrorString(err), XML_GetCurrentLineNumber(parser),
148           XML_GetCurrentColumnNumber(parser), file, line);
149   _fail_unless(0, file, line, buffer);
150 }
151 
152 static enum XML_Status
153 _XML_Parse_SINGLE_BYTES(XML_Parser parser, const char *s, int len,
154                         int isFinal) {
155   enum XML_Status res = XML_STATUS_ERROR;
156   int offset = 0;
157 
158   if (len == 0) {
159     return XML_Parse(parser, s, len, isFinal);
160   }
161 
162   for (; offset < len; offset++) {
163     const int innerIsFinal = (offset == len - 1) && isFinal;
164     const char c = s[offset]; /* to help out-of-bounds detection */
165     res = XML_Parse(parser, &c, sizeof(char), innerIsFinal);
166     if (res != XML_STATUS_OK) {
167       return res;
168     }
169   }
170   return res;
171 }
172 
173 #define xml_failure(parser) _xml_failure((parser), __FILE__, __LINE__)
174 
175 static void
176 _expect_failure(const char *text, enum XML_Error errorCode,
177                 const char *errorMessage, const char *file, int lineno) {
178   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
179       == XML_STATUS_OK)
180     /* Hackish use of _fail_unless() macro, but let's us report
181        the right filename and line number. */
182     _fail_unless(0, file, lineno, errorMessage);
183   if (XML_GetErrorCode(g_parser) != errorCode)
184     _xml_failure(g_parser, file, lineno);
185 }
186 
187 #define expect_failure(text, errorCode, errorMessage)                          \
188   _expect_failure((text), (errorCode), (errorMessage), __FILE__, __LINE__)
189 
190 /* Dummy handlers for when we need to set a handler to tickle a bug,
191    but it doesn't need to do anything.
192 */
193 static unsigned long dummy_handler_flags = 0;
194 
195 #define DUMMY_START_DOCTYPE_HANDLER_FLAG (1UL << 0)
196 #define DUMMY_END_DOCTYPE_HANDLER_FLAG (1UL << 1)
197 #define DUMMY_ENTITY_DECL_HANDLER_FLAG (1UL << 2)
198 #define DUMMY_NOTATION_DECL_HANDLER_FLAG (1UL << 3)
199 #define DUMMY_ELEMENT_DECL_HANDLER_FLAG (1UL << 4)
200 #define DUMMY_ATTLIST_DECL_HANDLER_FLAG (1UL << 5)
201 #define DUMMY_COMMENT_HANDLER_FLAG (1UL << 6)
202 #define DUMMY_PI_HANDLER_FLAG (1UL << 7)
203 #define DUMMY_START_ELEMENT_HANDLER_FLAG (1UL << 8)
204 #define DUMMY_START_CDATA_HANDLER_FLAG (1UL << 9)
205 #define DUMMY_END_CDATA_HANDLER_FLAG (1UL << 10)
206 #define DUMMY_UNPARSED_ENTITY_DECL_HANDLER_FLAG (1UL << 11)
207 #define DUMMY_START_NS_DECL_HANDLER_FLAG (1UL << 12)
208 #define DUMMY_END_NS_DECL_HANDLER_FLAG (1UL << 13)
209 #define DUMMY_START_DOCTYPE_DECL_HANDLER_FLAG (1UL << 14)
210 #define DUMMY_END_DOCTYPE_DECL_HANDLER_FLAG (1UL << 15)
211 #define DUMMY_SKIP_HANDLER_FLAG (1UL << 16)
212 #define DUMMY_DEFAULT_HANDLER_FLAG (1UL << 17)
213 
214 static void XMLCALL
215 dummy_xdecl_handler(void *userData, const XML_Char *version,
216                     const XML_Char *encoding, int standalone) {
217   UNUSED_P(userData);
218   UNUSED_P(version);
219   UNUSED_P(encoding);
220   UNUSED_P(standalone);
221 }
222 
223 static void XMLCALL
224 dummy_start_doctype_handler(void *userData, const XML_Char *doctypeName,
225                             const XML_Char *sysid, const XML_Char *pubid,
226                             int has_internal_subset) {
227   UNUSED_P(userData);
228   UNUSED_P(doctypeName);
229   UNUSED_P(sysid);
230   UNUSED_P(pubid);
231   UNUSED_P(has_internal_subset);
232   dummy_handler_flags |= DUMMY_START_DOCTYPE_HANDLER_FLAG;
233 }
234 
235 static void XMLCALL
236 dummy_end_doctype_handler(void *userData) {
237   UNUSED_P(userData);
238   dummy_handler_flags |= DUMMY_END_DOCTYPE_HANDLER_FLAG;
239 }
240 
241 static void XMLCALL
242 dummy_entity_decl_handler(void *userData, const XML_Char *entityName,
243                           int is_parameter_entity, const XML_Char *value,
244                           int value_length, const XML_Char *base,
245                           const XML_Char *systemId, const XML_Char *publicId,
246                           const XML_Char *notationName) {
247   UNUSED_P(userData);
248   UNUSED_P(entityName);
249   UNUSED_P(is_parameter_entity);
250   UNUSED_P(value);
251   UNUSED_P(value_length);
252   UNUSED_P(base);
253   UNUSED_P(systemId);
254   UNUSED_P(publicId);
255   UNUSED_P(notationName);
256   dummy_handler_flags |= DUMMY_ENTITY_DECL_HANDLER_FLAG;
257 }
258 
259 static void XMLCALL
260 dummy_notation_decl_handler(void *userData, const XML_Char *notationName,
261                             const XML_Char *base, const XML_Char *systemId,
262                             const XML_Char *publicId) {
263   UNUSED_P(userData);
264   UNUSED_P(notationName);
265   UNUSED_P(base);
266   UNUSED_P(systemId);
267   UNUSED_P(publicId);
268   dummy_handler_flags |= DUMMY_NOTATION_DECL_HANDLER_FLAG;
269 }
270 
271 static void XMLCALL
272 dummy_element_decl_handler(void *userData, const XML_Char *name,
273                            XML_Content *model) {
274   UNUSED_P(userData);
275   UNUSED_P(name);
276   /* The content model must be freed by the handler.  Unfortunately
277    * we cannot pass the parser as the userData because this is used
278    * with other handlers that require other userData.
279    */
280   XML_FreeContentModel(g_parser, model);
281   dummy_handler_flags |= DUMMY_ELEMENT_DECL_HANDLER_FLAG;
282 }
283 
284 static void XMLCALL
285 dummy_attlist_decl_handler(void *userData, const XML_Char *elname,
286                            const XML_Char *attname, const XML_Char *att_type,
287                            const XML_Char *dflt, int isrequired) {
288   UNUSED_P(userData);
289   UNUSED_P(elname);
290   UNUSED_P(attname);
291   UNUSED_P(att_type);
292   UNUSED_P(dflt);
293   UNUSED_P(isrequired);
294   dummy_handler_flags |= DUMMY_ATTLIST_DECL_HANDLER_FLAG;
295 }
296 
297 static void XMLCALL
298 dummy_comment_handler(void *userData, const XML_Char *data) {
299   UNUSED_P(userData);
300   UNUSED_P(data);
301   dummy_handler_flags |= DUMMY_COMMENT_HANDLER_FLAG;
302 }
303 
304 static void XMLCALL
305 dummy_pi_handler(void *userData, const XML_Char *target, const XML_Char *data) {
306   UNUSED_P(userData);
307   UNUSED_P(target);
308   UNUSED_P(data);
309   dummy_handler_flags |= DUMMY_PI_HANDLER_FLAG;
310 }
311 
312 static void XMLCALL
313 dummy_start_element(void *userData, const XML_Char *name,
314                     const XML_Char **atts) {
315   UNUSED_P(userData);
316   UNUSED_P(name);
317   UNUSED_P(atts);
318   dummy_handler_flags |= DUMMY_START_ELEMENT_HANDLER_FLAG;
319 }
320 
321 static void XMLCALL
322 dummy_end_element(void *userData, const XML_Char *name) {
323   UNUSED_P(userData);
324   UNUSED_P(name);
325 }
326 
327 static void XMLCALL
328 dummy_start_cdata_handler(void *userData) {
329   UNUSED_P(userData);
330   dummy_handler_flags |= DUMMY_START_CDATA_HANDLER_FLAG;
331 }
332 
333 static void XMLCALL
334 dummy_end_cdata_handler(void *userData) {
335   UNUSED_P(userData);
336   dummy_handler_flags |= DUMMY_END_CDATA_HANDLER_FLAG;
337 }
338 
339 static void XMLCALL
340 dummy_cdata_handler(void *userData, const XML_Char *s, int len) {
341   UNUSED_P(userData);
342   UNUSED_P(s);
343   UNUSED_P(len);
344 }
345 
346 static void XMLCALL
347 dummy_start_namespace_decl_handler(void *userData, const XML_Char *prefix,
348                                    const XML_Char *uri) {
349   UNUSED_P(userData);
350   UNUSED_P(prefix);
351   UNUSED_P(uri);
352   dummy_handler_flags |= DUMMY_START_NS_DECL_HANDLER_FLAG;
353 }
354 
355 static void XMLCALL
356 dummy_end_namespace_decl_handler(void *userData, const XML_Char *prefix) {
357   UNUSED_P(userData);
358   UNUSED_P(prefix);
359   dummy_handler_flags |= DUMMY_END_NS_DECL_HANDLER_FLAG;
360 }
361 
362 /* This handler is obsolete, but while the code exists we should
363  * ensure that dealing with the handler is covered by tests.
364  */
365 static void XMLCALL
366 dummy_unparsed_entity_decl_handler(void *userData, const XML_Char *entityName,
367                                    const XML_Char *base,
368                                    const XML_Char *systemId,
369                                    const XML_Char *publicId,
370                                    const XML_Char *notationName) {
371   UNUSED_P(userData);
372   UNUSED_P(entityName);
373   UNUSED_P(base);
374   UNUSED_P(systemId);
375   UNUSED_P(publicId);
376   UNUSED_P(notationName);
377   dummy_handler_flags |= DUMMY_UNPARSED_ENTITY_DECL_HANDLER_FLAG;
378 }
379 
380 static void XMLCALL
381 dummy_default_handler(void *userData, const XML_Char *s, int len) {
382   UNUSED_P(userData);
383   UNUSED_P(s);
384   UNUSED_P(len);
385 }
386 
387 static void XMLCALL
388 dummy_start_doctype_decl_handler(void *userData, const XML_Char *doctypeName,
389                                  const XML_Char *sysid, const XML_Char *pubid,
390                                  int has_internal_subset) {
391   UNUSED_P(userData);
392   UNUSED_P(doctypeName);
393   UNUSED_P(sysid);
394   UNUSED_P(pubid);
395   UNUSED_P(has_internal_subset);
396   dummy_handler_flags |= DUMMY_START_DOCTYPE_DECL_HANDLER_FLAG;
397 }
398 
399 static void XMLCALL
400 dummy_end_doctype_decl_handler(void *userData) {
401   UNUSED_P(userData);
402   dummy_handler_flags |= DUMMY_END_DOCTYPE_DECL_HANDLER_FLAG;
403 }
404 
405 static void XMLCALL
406 dummy_skip_handler(void *userData, const XML_Char *entityName,
407                    int is_parameter_entity) {
408   UNUSED_P(userData);
409   UNUSED_P(entityName);
410   UNUSED_P(is_parameter_entity);
411   dummy_handler_flags |= DUMMY_SKIP_HANDLER_FLAG;
412 }
413 
414 /* Useful external entity handler */
415 typedef struct ExtOption {
416   const XML_Char *system_id;
417   const char *parse_text;
418 } ExtOption;
419 
420 static int XMLCALL
421 external_entity_optioner(XML_Parser parser, const XML_Char *context,
422                          const XML_Char *base, const XML_Char *systemId,
423                          const XML_Char *publicId) {
424   ExtOption *options = (ExtOption *)XML_GetUserData(parser);
425   XML_Parser ext_parser;
426 
427   UNUSED_P(base);
428   UNUSED_P(publicId);
429   while (options->parse_text != NULL) {
430     if (! xcstrcmp(systemId, options->system_id)) {
431       enum XML_Status rc;
432       ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
433       if (ext_parser == NULL)
434         return XML_STATUS_ERROR;
435       rc = _XML_Parse_SINGLE_BYTES(ext_parser, options->parse_text,
436                                    (int)strlen(options->parse_text), XML_TRUE);
437       XML_ParserFree(ext_parser);
438       return rc;
439     }
440     options++;
441   }
442   fail("No suitable option found");
443   return XML_STATUS_ERROR;
444 }
445 
446 /*
447  * Parameter entity evaluation support.
448  */
449 #define ENTITY_MATCH_FAIL (-1)
450 #define ENTITY_MATCH_NOT_FOUND (0)
451 #define ENTITY_MATCH_SUCCESS (1)
452 static const XML_Char *entity_name_to_match = NULL;
453 static const XML_Char *entity_value_to_match = NULL;
454 static int entity_match_flag = ENTITY_MATCH_NOT_FOUND;
455 
456 static void XMLCALL
457 param_entity_match_handler(void *userData, const XML_Char *entityName,
458                            int is_parameter_entity, const XML_Char *value,
459                            int value_length, const XML_Char *base,
460                            const XML_Char *systemId, const XML_Char *publicId,
461                            const XML_Char *notationName) {
462   UNUSED_P(userData);
463   UNUSED_P(base);
464   UNUSED_P(systemId);
465   UNUSED_P(publicId);
466   UNUSED_P(notationName);
467   if (! is_parameter_entity || entity_name_to_match == NULL
468       || entity_value_to_match == NULL) {
469     return;
470   }
471   if (! xcstrcmp(entityName, entity_name_to_match)) {
472     /* The cast here is safe because we control the horizontal and
473      * the vertical, and we therefore know our strings are never
474      * going to overflow an int.
475      */
476     if (value_length != (int)xcstrlen(entity_value_to_match)
477         || xcstrncmp(value, entity_value_to_match, value_length)) {
478       entity_match_flag = ENTITY_MATCH_FAIL;
479     } else {
480       entity_match_flag = ENTITY_MATCH_SUCCESS;
481     }
482   }
483   /* Else leave the match flag alone */
484 }
485 
486 /*
487  * Character & encoding tests.
488  */
489 
490 START_TEST(test_nul_byte) {
491   char text[] = "<doc>\0</doc>";
492 
493   /* test that a NUL byte (in US-ASCII data) is an error */
494   if (_XML_Parse_SINGLE_BYTES(g_parser, text, sizeof(text) - 1, XML_TRUE)
495       == XML_STATUS_OK)
496     fail("Parser did not report error on NUL-byte.");
497   if (XML_GetErrorCode(g_parser) != XML_ERROR_INVALID_TOKEN)
498     xml_failure(g_parser);
499 }
500 END_TEST
501 
502 START_TEST(test_u0000_char) {
503   /* test that a NUL byte (in US-ASCII data) is an error */
504   expect_failure("<doc>&#0;</doc>", XML_ERROR_BAD_CHAR_REF,
505                  "Parser did not report error on NUL-byte.");
506 }
507 END_TEST
508 
509 START_TEST(test_siphash_self) {
510   if (! sip24_valid())
511     fail("SipHash self-test failed");
512 }
513 END_TEST
514 
515 START_TEST(test_siphash_spec) {
516   /* https://131002.net/siphash/siphash.pdf (page 19, "Test values") */
517   const char message[] = "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09"
518                          "\x0a\x0b\x0c\x0d\x0e";
519   const size_t len = sizeof(message) - 1;
520   const uint64_t expected = _SIP_ULL(0xa129ca61U, 0x49be45e5U);
521   struct siphash state;
522   struct sipkey key;
523 
524   sip_tokey(&key, "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09"
525                   "\x0a\x0b\x0c\x0d\x0e\x0f");
526   sip24_init(&state, &key);
527 
528   /* Cover spread across calls */
529   sip24_update(&state, message, 4);
530   sip24_update(&state, message + 4, len - 4);
531 
532   /* Cover null length */
533   sip24_update(&state, message, 0);
534 
535   if (sip24_final(&state) != expected)
536     fail("sip24_final failed spec test\n");
537 
538   /* Cover wrapper */
539   if (siphash24(message, len, &key) != expected)
540     fail("siphash24 failed spec test\n");
541 }
542 END_TEST
543 
544 START_TEST(test_bom_utf8) {
545   /* This test is really just making sure we don't core on a UTF-8 BOM. */
546   const char *text = "\357\273\277<e/>";
547 
548   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
549       == XML_STATUS_ERROR)
550     xml_failure(g_parser);
551 }
552 END_TEST
553 
554 START_TEST(test_bom_utf16_be) {
555   char text[] = "\376\377\0<\0e\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 START_TEST(test_bom_utf16_le) {
564   char text[] = "\377\376<\0e\0/\0>\0";
565 
566   if (_XML_Parse_SINGLE_BYTES(g_parser, text, sizeof(text) - 1, XML_TRUE)
567       == XML_STATUS_ERROR)
568     xml_failure(g_parser);
569 }
570 END_TEST
571 
572 /* Parse whole buffer at once to exercise a different code path */
573 START_TEST(test_nobom_utf16_le) {
574   char text[] = " \0<\0e\0/\0>\0";
575 
576   if (XML_Parse(g_parser, text, sizeof(text) - 1, XML_TRUE) == XML_STATUS_ERROR)
577     xml_failure(g_parser);
578 }
579 END_TEST
580 
581 static void XMLCALL
582 accumulate_characters(void *userData, const XML_Char *s, int len) {
583   CharData_AppendXMLChars((CharData *)userData, s, len);
584 }
585 
586 static void XMLCALL
587 accumulate_attribute(void *userData, const XML_Char *name,
588                      const XML_Char **atts) {
589   CharData *storage = (CharData *)userData;
590   UNUSED_P(name);
591   /* Check there are attributes to deal with */
592   if (atts == NULL)
593     return;
594 
595   while (storage->count < 0 && atts[0] != NULL) {
596     /* "accumulate" the value of the first attribute we see */
597     CharData_AppendXMLChars(storage, atts[1], -1);
598     atts += 2;
599   }
600 }
601 
602 static void
603 _run_character_check(const char *text, const XML_Char *expected,
604                      const char *file, int line) {
605   CharData storage;
606 
607   CharData_Init(&storage);
608   XML_SetUserData(g_parser, &storage);
609   XML_SetCharacterDataHandler(g_parser, accumulate_characters);
610   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
611       == XML_STATUS_ERROR)
612     _xml_failure(g_parser, file, line);
613   CharData_CheckXMLChars(&storage, expected);
614 }
615 
616 #define run_character_check(text, expected)                                    \
617   _run_character_check(text, expected, __FILE__, __LINE__)
618 
619 static void
620 _run_attribute_check(const char *text, const XML_Char *expected,
621                      const char *file, int line) {
622   CharData storage;
623 
624   CharData_Init(&storage);
625   XML_SetUserData(g_parser, &storage);
626   XML_SetStartElementHandler(g_parser, accumulate_attribute);
627   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
628       == XML_STATUS_ERROR)
629     _xml_failure(g_parser, file, line);
630   CharData_CheckXMLChars(&storage, expected);
631 }
632 
633 #define run_attribute_check(text, expected)                                    \
634   _run_attribute_check(text, expected, __FILE__, __LINE__)
635 
636 typedef struct ExtTest {
637   const char *parse_text;
638   const XML_Char *encoding;
639   CharData *storage;
640 } ExtTest;
641 
642 static void XMLCALL
643 ext_accumulate_characters(void *userData, const XML_Char *s, int len) {
644   ExtTest *test_data = (ExtTest *)userData;
645   accumulate_characters(test_data->storage, s, len);
646 }
647 
648 static void
649 _run_ext_character_check(const char *text, ExtTest *test_data,
650                          const XML_Char *expected, const char *file, int line) {
651   CharData *const storage = (CharData *)malloc(sizeof(CharData));
652 
653   CharData_Init(storage);
654   test_data->storage = storage;
655   XML_SetUserData(g_parser, test_data);
656   XML_SetCharacterDataHandler(g_parser, ext_accumulate_characters);
657   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
658       == XML_STATUS_ERROR)
659     _xml_failure(g_parser, file, line);
660   CharData_CheckXMLChars(storage, expected);
661 
662   free(storage);
663 }
664 
665 #define run_ext_character_check(text, test_data, expected)                     \
666   _run_ext_character_check(text, test_data, expected, __FILE__, __LINE__)
667 
668 /* Regression test for SF bug #491986. */
669 START_TEST(test_danish_latin1) {
670   const char *text = "<?xml version='1.0' encoding='iso-8859-1'?>\n"
671                      "<e>J\xF8rgen \xE6\xF8\xE5\xC6\xD8\xC5</e>";
672 #ifdef XML_UNICODE
673   const XML_Char *expected
674       = XCS("J\x00f8rgen \x00e6\x00f8\x00e5\x00c6\x00d8\x00c5");
675 #else
676   const XML_Char *expected
677       = XCS("J\xC3\xB8rgen \xC3\xA6\xC3\xB8\xC3\xA5\xC3\x86\xC3\x98\xC3\x85");
678 #endif
679   run_character_check(text, expected);
680 }
681 END_TEST
682 
683 /* Regression test for SF bug #514281. */
684 START_TEST(test_french_charref_hexidecimal) {
685   const char *text = "<?xml version='1.0' encoding='iso-8859-1'?>\n"
686                      "<doc>&#xE9;&#xE8;&#xE0;&#xE7;&#xEA;&#xC8;</doc>";
687 #ifdef XML_UNICODE
688   const XML_Char *expected = XCS("\x00e9\x00e8\x00e0\x00e7\x00ea\x00c8");
689 #else
690   const XML_Char *expected
691       = XCS("\xC3\xA9\xC3\xA8\xC3\xA0\xC3\xA7\xC3\xAA\xC3\x88");
692 #endif
693   run_character_check(text, expected);
694 }
695 END_TEST
696 
697 START_TEST(test_french_charref_decimal) {
698   const char *text = "<?xml version='1.0' encoding='iso-8859-1'?>\n"
699                      "<doc>&#233;&#232;&#224;&#231;&#234;&#200;</doc>";
700 #ifdef XML_UNICODE
701   const XML_Char *expected = XCS("\x00e9\x00e8\x00e0\x00e7\x00ea\x00c8");
702 #else
703   const XML_Char *expected
704       = XCS("\xC3\xA9\xC3\xA8\xC3\xA0\xC3\xA7\xC3\xAA\xC3\x88");
705 #endif
706   run_character_check(text, expected);
707 }
708 END_TEST
709 
710 START_TEST(test_french_latin1) {
711   const char *text = "<?xml version='1.0' encoding='iso-8859-1'?>\n"
712                      "<doc>\xE9\xE8\xE0\xE7\xEa\xC8</doc>";
713 #ifdef XML_UNICODE
714   const XML_Char *expected = XCS("\x00e9\x00e8\x00e0\x00e7\x00ea\x00c8");
715 #else
716   const XML_Char *expected
717       = XCS("\xC3\xA9\xC3\xA8\xC3\xA0\xC3\xA7\xC3\xAA\xC3\x88");
718 #endif
719   run_character_check(text, expected);
720 }
721 END_TEST
722 
723 START_TEST(test_french_utf8) {
724   const char *text = "<?xml version='1.0' encoding='utf-8'?>\n"
725                      "<doc>\xC3\xA9</doc>";
726 #ifdef XML_UNICODE
727   const XML_Char *expected = XCS("\x00e9");
728 #else
729   const XML_Char *expected = XCS("\xC3\xA9");
730 #endif
731   run_character_check(text, expected);
732 }
733 END_TEST
734 
735 /* Regression test for SF bug #600479.
736    XXX There should be a test that exercises all legal XML Unicode
737    characters as PCDATA and attribute value content, and XML Name
738    characters as part of element and attribute names.
739 */
740 START_TEST(test_utf8_false_rejection) {
741   const char *text = "<doc>\xEF\xBA\xBF</doc>";
742 #ifdef XML_UNICODE
743   const XML_Char *expected = XCS("\xfebf");
744 #else
745   const XML_Char *expected = XCS("\xEF\xBA\xBF");
746 #endif
747   run_character_check(text, expected);
748 }
749 END_TEST
750 
751 /* Regression test for SF bug #477667.
752    This test assures that any 8-bit character followed by a 7-bit
753    character will not be mistakenly interpreted as a valid UTF-8
754    sequence.
755 */
756 START_TEST(test_illegal_utf8) {
757   char text[100];
758   int i;
759 
760   for (i = 128; i <= 255; ++i) {
761     sprintf(text, "<e>%ccd</e>", i);
762     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
763         == XML_STATUS_OK) {
764       sprintf(text, "expected token error for '%c' (ordinal %d) in UTF-8 text",
765               i, i);
766       fail(text);
767     } else if (XML_GetErrorCode(g_parser) != XML_ERROR_INVALID_TOKEN)
768       xml_failure(g_parser);
769     /* Reset the parser since we use the same parser repeatedly. */
770     XML_ParserReset(g_parser, NULL);
771   }
772 }
773 END_TEST
774 
775 /* Examples, not masks: */
776 #define UTF8_LEAD_1 "\x7f" /* 0b01111111 */
777 #define UTF8_LEAD_2 "\xdf" /* 0b11011111 */
778 #define UTF8_LEAD_3 "\xef" /* 0b11101111 */
779 #define UTF8_LEAD_4 "\xf7" /* 0b11110111 */
780 #define UTF8_FOLLOW "\xbf" /* 0b10111111 */
781 
782 START_TEST(test_utf8_auto_align) {
783   struct TestCase {
784     ptrdiff_t expectedMovementInChars;
785     const char *input;
786   };
787 
788   struct TestCase cases[] = {
789       {00, ""},
790 
791       {00, UTF8_LEAD_1},
792 
793       {-1, UTF8_LEAD_2},
794       {00, UTF8_LEAD_2 UTF8_FOLLOW},
795 
796       {-1, UTF8_LEAD_3},
797       {-2, UTF8_LEAD_3 UTF8_FOLLOW},
798       {00, UTF8_LEAD_3 UTF8_FOLLOW UTF8_FOLLOW},
799 
800       {-1, UTF8_LEAD_4},
801       {-2, UTF8_LEAD_4 UTF8_FOLLOW},
802       {-3, UTF8_LEAD_4 UTF8_FOLLOW UTF8_FOLLOW},
803       {00, UTF8_LEAD_4 UTF8_FOLLOW UTF8_FOLLOW UTF8_FOLLOW},
804   };
805 
806   size_t i = 0;
807   bool success = true;
808   for (; i < sizeof(cases) / sizeof(*cases); i++) {
809     const char *fromLim = cases[i].input + strlen(cases[i].input);
810     const char *const fromLimInitially = fromLim;
811     ptrdiff_t actualMovementInChars;
812 
813     _INTERNAL_trim_to_complete_utf8_characters(cases[i].input, &fromLim);
814 
815     actualMovementInChars = (fromLim - fromLimInitially);
816     if (actualMovementInChars != cases[i].expectedMovementInChars) {
817       size_t j = 0;
818       success = false;
819       printf("[-] UTF-8 case %2u: Expected movement by %2d chars"
820              ", actually moved by %2d chars: \"",
821              (unsigned)(i + 1), (int)cases[i].expectedMovementInChars,
822              (int)actualMovementInChars);
823       for (; j < strlen(cases[i].input); j++) {
824         printf("\\x%02x", (unsigned char)cases[i].input[j]);
825       }
826       printf("\"\n");
827     }
828   }
829 
830   if (! success) {
831     fail("UTF-8 auto-alignment is not bullet-proof\n");
832   }
833 }
834 END_TEST
835 
836 START_TEST(test_utf16) {
837   /* <?xml version="1.0" encoding="UTF-16"?>
838    *  <doc a='123'>some {A} text</doc>
839    *
840    * where {A} is U+FF21, FULLWIDTH LATIN CAPITAL LETTER A
841    */
842   char text[]
843       = "\000<\000?\000x\000m\000\154\000 \000v\000e\000r\000s\000i\000o"
844         "\000n\000=\000'\0001\000.\000\060\000'\000 \000e\000n\000c\000o"
845         "\000d\000i\000n\000g\000=\000'\000U\000T\000F\000-\0001\000\066"
846         "\000'\000?\000>\000\n"
847         "\000<\000d\000o\000c\000 \000a\000=\000'\0001\0002\0003\000'\000>"
848         "\000s\000o\000m\000e\000 \xff\x21\000 \000t\000e\000x\000t\000"
849         "<\000/\000d\000o\000c\000>";
850 #ifdef XML_UNICODE
851   const XML_Char *expected = XCS("some \xff21 text");
852 #else
853   const XML_Char *expected = XCS("some \357\274\241 text");
854 #endif
855   CharData storage;
856 
857   CharData_Init(&storage);
858   XML_SetUserData(g_parser, &storage);
859   XML_SetCharacterDataHandler(g_parser, accumulate_characters);
860   if (_XML_Parse_SINGLE_BYTES(g_parser, text, sizeof(text) - 1, XML_TRUE)
861       == XML_STATUS_ERROR)
862     xml_failure(g_parser);
863   CharData_CheckXMLChars(&storage, expected);
864 }
865 END_TEST
866 
867 START_TEST(test_utf16_le_epilog_newline) {
868   unsigned int first_chunk_bytes = 17;
869   char text[] = "\xFF\xFE"                  /* BOM */
870                 "<\000e\000/\000>\000"      /* document element */
871                 "\r\000\n\000\r\000\n\000"; /* epilog */
872 
873   if (first_chunk_bytes >= sizeof(text) - 1)
874     fail("bad value of first_chunk_bytes");
875   if (_XML_Parse_SINGLE_BYTES(g_parser, text, first_chunk_bytes, XML_FALSE)
876       == XML_STATUS_ERROR)
877     xml_failure(g_parser);
878   else {
879     enum XML_Status rc;
880     rc = _XML_Parse_SINGLE_BYTES(g_parser, text + first_chunk_bytes,
881                                  sizeof(text) - first_chunk_bytes - 1,
882                                  XML_TRUE);
883     if (rc == XML_STATUS_ERROR)
884       xml_failure(g_parser);
885   }
886 }
887 END_TEST
888 
889 /* Test that an outright lie in the encoding is faulted */
890 START_TEST(test_not_utf16) {
891   const char *text = "<?xml version='1.0' encoding='utf-16'?>"
892                      "<doc>Hi</doc>";
893 
894   /* Use a handler to provoke the appropriate code paths */
895   XML_SetXmlDeclHandler(g_parser, dummy_xdecl_handler);
896   expect_failure(text, XML_ERROR_INCORRECT_ENCODING,
897                  "UTF-16 declared in UTF-8 not faulted");
898 }
899 END_TEST
900 
901 /* Test that an unknown encoding is rejected */
902 START_TEST(test_bad_encoding) {
903   const char *text = "<doc>Hi</doc>";
904 
905   if (! XML_SetEncoding(g_parser, XCS("unknown-encoding")))
906     fail("XML_SetEncoding failed");
907   expect_failure(text, XML_ERROR_UNKNOWN_ENCODING,
908                  "Unknown encoding not faulted");
909 }
910 END_TEST
911 
912 /* Regression test for SF bug #481609, #774028. */
913 START_TEST(test_latin1_umlauts) {
914   const char *text
915       = "<?xml version='1.0' encoding='iso-8859-1'?>\n"
916         "<e a='\xE4 \xF6 \xFC &#228; &#246; &#252; &#x00E4; &#x0F6; &#xFC; >'\n"
917         "  >\xE4 \xF6 \xFC &#228; &#246; &#252; &#x00E4; &#x0F6; &#xFC; ></e>";
918 #ifdef XML_UNICODE
919   /* Expected results in UTF-16 */
920   const XML_Char *expected = XCS("\x00e4 \x00f6 \x00fc ")
921       XCS("\x00e4 \x00f6 \x00fc ") XCS("\x00e4 \x00f6 \x00fc >");
922 #else
923   /* Expected results in UTF-8 */
924   const XML_Char *expected = XCS("\xC3\xA4 \xC3\xB6 \xC3\xBC ")
925       XCS("\xC3\xA4 \xC3\xB6 \xC3\xBC ") XCS("\xC3\xA4 \xC3\xB6 \xC3\xBC >");
926 #endif
927 
928   run_character_check(text, expected);
929   XML_ParserReset(g_parser, NULL);
930   run_attribute_check(text, expected);
931   /* Repeat with a default handler */
932   XML_ParserReset(g_parser, NULL);
933   XML_SetDefaultHandler(g_parser, dummy_default_handler);
934   run_character_check(text, expected);
935   XML_ParserReset(g_parser, NULL);
936   XML_SetDefaultHandler(g_parser, dummy_default_handler);
937   run_attribute_check(text, expected);
938 }
939 END_TEST
940 
941 /* Test that an element name with a 4-byte UTF-8 character is rejected */
942 START_TEST(test_long_utf8_character) {
943   const char *text
944       = "<?xml version='1.0' encoding='utf-8'?>\n"
945         /* 0xf0 0x90 0x80 0x80 = U+10000, the first Linear B character */
946         "<do\xf0\x90\x80\x80/>";
947   expect_failure(text, XML_ERROR_INVALID_TOKEN,
948                  "4-byte UTF-8 character in element name not faulted");
949 }
950 END_TEST
951 
952 /* Test that a long latin-1 attribute (too long to convert in one go)
953  * is correctly converted
954  */
955 START_TEST(test_long_latin1_attribute) {
956   const char *text
957       = "<?xml version='1.0' encoding='iso-8859-1'?>\n"
958         "<doc att='"
959         /* 64 characters per line */
960         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
961         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
962         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
963         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
964         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
965         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
966         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
967         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
968         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
969         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
970         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
971         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
972         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
973         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
974         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
975         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
976         /* Last character splits across a buffer boundary */
977         "\xe4'>\n</doc>";
978 
979   const XML_Char *expected =
980       /* 64 characters per line */
981       /* clang-format off */
982         XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
983         XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
984         XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
985         XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
986         XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
987         XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
988         XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
989         XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
990         XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
991         XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
992         XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
993         XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
994         XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
995         XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
996         XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
997         XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO")
998   /* clang-format on */
999 #ifdef XML_UNICODE
1000                                                   XCS("\x00e4");
1001 #else
1002                                                   XCS("\xc3\xa4");
1003 #endif
1004 
1005   run_attribute_check(text, expected);
1006 }
1007 END_TEST
1008 
1009 /* Test that a long ASCII attribute (too long to convert in one go)
1010  * is correctly converted
1011  */
1012 START_TEST(test_long_ascii_attribute) {
1013   const char *text
1014       = "<?xml version='1.0' encoding='us-ascii'?>\n"
1015         "<doc att='"
1016         /* 64 characters per line */
1017         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1018         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1019         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1020         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1021         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1022         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1023         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1024         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1025         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1026         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1027         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1028         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1029         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1030         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1031         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1032         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
1033         "01234'>\n</doc>";
1034   const XML_Char *expected =
1035       /* 64 characters per line */
1036       /* clang-format off */
1037         XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
1038         XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
1039         XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
1040         XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
1041         XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
1042         XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
1043         XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
1044         XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
1045         XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
1046         XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
1047         XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
1048         XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
1049         XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
1050         XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
1051         XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
1052         XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
1053         XCS("01234");
1054   /* clang-format on */
1055 
1056   run_attribute_check(text, expected);
1057 }
1058 END_TEST
1059 
1060 /* Regression test #1 for SF bug #653180. */
1061 START_TEST(test_line_number_after_parse) {
1062   const char *text = "<tag>\n"
1063                      "\n"
1064                      "\n</tag>";
1065   XML_Size lineno;
1066 
1067   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_FALSE)
1068       == XML_STATUS_ERROR)
1069     xml_failure(g_parser);
1070   lineno = XML_GetCurrentLineNumber(g_parser);
1071   if (lineno != 4) {
1072     char buffer[100];
1073     sprintf(buffer, "expected 4 lines, saw %" XML_FMT_INT_MOD "u", lineno);
1074     fail(buffer);
1075   }
1076 }
1077 END_TEST
1078 
1079 /* Regression test #2 for SF bug #653180. */
1080 START_TEST(test_column_number_after_parse) {
1081   const char *text = "<tag></tag>";
1082   XML_Size colno;
1083 
1084   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_FALSE)
1085       == XML_STATUS_ERROR)
1086     xml_failure(g_parser);
1087   colno = XML_GetCurrentColumnNumber(g_parser);
1088   if (colno != 11) {
1089     char buffer[100];
1090     sprintf(buffer, "expected 11 columns, saw %" XML_FMT_INT_MOD "u", colno);
1091     fail(buffer);
1092   }
1093 }
1094 END_TEST
1095 
1096 #define STRUCT_START_TAG 0
1097 #define STRUCT_END_TAG 1
1098 static void XMLCALL
1099 start_element_event_handler2(void *userData, const XML_Char *name,
1100                              const XML_Char **attr) {
1101   StructData *storage = (StructData *)userData;
1102   UNUSED_P(attr);
1103   StructData_AddItem(storage, name, XML_GetCurrentColumnNumber(g_parser),
1104                      XML_GetCurrentLineNumber(g_parser), STRUCT_START_TAG);
1105 }
1106 
1107 static void XMLCALL
1108 end_element_event_handler2(void *userData, const XML_Char *name) {
1109   StructData *storage = (StructData *)userData;
1110   StructData_AddItem(storage, name, XML_GetCurrentColumnNumber(g_parser),
1111                      XML_GetCurrentLineNumber(g_parser), STRUCT_END_TAG);
1112 }
1113 
1114 /* Regression test #3 for SF bug #653180. */
1115 START_TEST(test_line_and_column_numbers_inside_handlers) {
1116   const char *text = "<a>\n"      /* Unix end-of-line */
1117                      "  <b>\r\n"  /* Windows end-of-line */
1118                      "    <c/>\r" /* Mac OS end-of-line */
1119                      "  </b>\n"
1120                      "  <d>\n"
1121                      "    <f/>\n"
1122                      "  </d>\n"
1123                      "</a>";
1124   const StructDataEntry expected[]
1125       = {{XCS("a"), 0, 1, STRUCT_START_TAG}, {XCS("b"), 2, 2, STRUCT_START_TAG},
1126          {XCS("c"), 4, 3, STRUCT_START_TAG}, {XCS("c"), 8, 3, STRUCT_END_TAG},
1127          {XCS("b"), 2, 4, STRUCT_END_TAG},   {XCS("d"), 2, 5, STRUCT_START_TAG},
1128          {XCS("f"), 4, 6, STRUCT_START_TAG}, {XCS("f"), 8, 6, STRUCT_END_TAG},
1129          {XCS("d"), 2, 7, STRUCT_END_TAG},   {XCS("a"), 0, 8, STRUCT_END_TAG}};
1130   const int expected_count = sizeof(expected) / sizeof(StructDataEntry);
1131   StructData storage;
1132 
1133   StructData_Init(&storage);
1134   XML_SetUserData(g_parser, &storage);
1135   XML_SetStartElementHandler(g_parser, start_element_event_handler2);
1136   XML_SetEndElementHandler(g_parser, end_element_event_handler2);
1137   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
1138       == XML_STATUS_ERROR)
1139     xml_failure(g_parser);
1140 
1141   StructData_CheckItems(&storage, expected, expected_count);
1142   StructData_Dispose(&storage);
1143 }
1144 END_TEST
1145 
1146 /* Regression test #4 for SF bug #653180. */
1147 START_TEST(test_line_number_after_error) {
1148   const char *text = "<a>\n"
1149                      "  <b>\n"
1150                      "  </a>"; /* missing </b> */
1151   XML_Size lineno;
1152   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_FALSE)
1153       != XML_STATUS_ERROR)
1154     fail("Expected a parse error");
1155 
1156   lineno = XML_GetCurrentLineNumber(g_parser);
1157   if (lineno != 3) {
1158     char buffer[100];
1159     sprintf(buffer, "expected 3 lines, saw %" XML_FMT_INT_MOD "u", lineno);
1160     fail(buffer);
1161   }
1162 }
1163 END_TEST
1164 
1165 /* Regression test #5 for SF bug #653180. */
1166 START_TEST(test_column_number_after_error) {
1167   const char *text = "<a>\n"
1168                      "  <b>\n"
1169                      "  </a>"; /* missing </b> */
1170   XML_Size colno;
1171   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_FALSE)
1172       != XML_STATUS_ERROR)
1173     fail("Expected a parse error");
1174 
1175   colno = XML_GetCurrentColumnNumber(g_parser);
1176   if (colno != 4) {
1177     char buffer[100];
1178     sprintf(buffer, "expected 4 columns, saw %" XML_FMT_INT_MOD "u", colno);
1179     fail(buffer);
1180   }
1181 }
1182 END_TEST
1183 
1184 /* Regression test for SF bug #478332. */
1185 START_TEST(test_really_long_lines) {
1186   /* This parses an input line longer than INIT_DATA_BUF_SIZE
1187      characters long (defined to be 1024 in xmlparse.c).  We take a
1188      really cheesy approach to building the input buffer, because
1189      this avoids writing bugs in buffer-filling code.
1190   */
1191   const char *text
1192       = "<e>"
1193         /* 64 chars */
1194         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1195         /* until we have at least 1024 characters on the line: */
1196         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1197         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1198         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1199         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1200         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1201         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1202         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1203         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1204         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1205         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1206         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1207         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1208         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1209         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1210         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1211         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1212         "</e>";
1213   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
1214       == XML_STATUS_ERROR)
1215     xml_failure(g_parser);
1216 }
1217 END_TEST
1218 
1219 /* Test cdata processing across a buffer boundary */
1220 START_TEST(test_really_long_encoded_lines) {
1221   /* As above, except that we want to provoke an output buffer
1222    * overflow with a non-trivial encoding.  For this we need to pass
1223    * the whole cdata in one go, not byte-by-byte.
1224    */
1225   void *buffer;
1226   const char *text
1227       = "<?xml version='1.0' encoding='iso-8859-1'?>"
1228         "<e>"
1229         /* 64 chars */
1230         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1231         /* until we have at least 1024 characters on the line: */
1232         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1233         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1234         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1235         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1236         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1237         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1238         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1239         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1240         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1241         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1242         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1243         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1244         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1245         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1246         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1247         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
1248         "</e>";
1249   int parse_len = (int)strlen(text);
1250 
1251   /* Need a cdata handler to provoke the code path we want to test */
1252   XML_SetCharacterDataHandler(g_parser, dummy_cdata_handler);
1253   buffer = XML_GetBuffer(g_parser, parse_len);
1254   if (buffer == NULL)
1255     fail("Could not allocate parse buffer");
1256   assert(buffer != NULL);
1257   memcpy(buffer, text, parse_len);
1258   if (XML_ParseBuffer(g_parser, parse_len, XML_TRUE) == XML_STATUS_ERROR)
1259     xml_failure(g_parser);
1260 }
1261 END_TEST
1262 
1263 /*
1264  * Element event tests.
1265  */
1266 
1267 static void XMLCALL
1268 start_element_event_handler(void *userData, const XML_Char *name,
1269                             const XML_Char **atts) {
1270   UNUSED_P(atts);
1271   CharData_AppendXMLChars((CharData *)userData, name, -1);
1272 }
1273 
1274 static void XMLCALL
1275 end_element_event_handler(void *userData, const XML_Char *name) {
1276   CharData *storage = (CharData *)userData;
1277   CharData_AppendXMLChars(storage, XCS("/"), 1);
1278   CharData_AppendXMLChars(storage, name, -1);
1279 }
1280 
1281 START_TEST(test_end_element_events) {
1282   const char *text = "<a><b><c/></b><d><f/></d></a>";
1283   const XML_Char *expected = XCS("/c/b/f/d/a");
1284   CharData storage;
1285 
1286   CharData_Init(&storage);
1287   XML_SetUserData(g_parser, &storage);
1288   XML_SetEndElementHandler(g_parser, end_element_event_handler);
1289   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
1290       == XML_STATUS_ERROR)
1291     xml_failure(g_parser);
1292   CharData_CheckXMLChars(&storage, expected);
1293 }
1294 END_TEST
1295 
1296 /*
1297  * Attribute tests.
1298  */
1299 
1300 /* Helpers used by the following test; this checks any "attr" and "refs"
1301    attributes to make sure whitespace has been normalized.
1302 
1303    Return true if whitespace has been normalized in a string, using
1304    the rules for attribute value normalization.  The 'is_cdata' flag
1305    is needed since CDATA attributes don't need to have multiple
1306    whitespace characters collapsed to a single space, while other
1307    attribute data types do.  (Section 3.3.3 of the recommendation.)
1308 */
1309 static int
1310 is_whitespace_normalized(const XML_Char *s, int is_cdata) {
1311   int blanks = 0;
1312   int at_start = 1;
1313   while (*s) {
1314     if (*s == XCS(' '))
1315       ++blanks;
1316     else if (*s == XCS('\t') || *s == XCS('\n') || *s == XCS('\r'))
1317       return 0;
1318     else {
1319       if (at_start) {
1320         at_start = 0;
1321         if (blanks && ! is_cdata)
1322           /* illegal leading blanks */
1323           return 0;
1324       } else if (blanks > 1 && ! is_cdata)
1325         return 0;
1326       blanks = 0;
1327     }
1328     ++s;
1329   }
1330   if (blanks && ! is_cdata)
1331     return 0;
1332   return 1;
1333 }
1334 
1335 /* Check the attribute whitespace checker: */
1336 static void
1337 testhelper_is_whitespace_normalized(void) {
1338   assert(is_whitespace_normalized(XCS("abc"), 0));
1339   assert(is_whitespace_normalized(XCS("abc"), 1));
1340   assert(is_whitespace_normalized(XCS("abc def ghi"), 0));
1341   assert(is_whitespace_normalized(XCS("abc def ghi"), 1));
1342   assert(! is_whitespace_normalized(XCS(" abc def ghi"), 0));
1343   assert(is_whitespace_normalized(XCS(" abc def ghi"), 1));
1344   assert(! is_whitespace_normalized(XCS("abc  def ghi"), 0));
1345   assert(is_whitespace_normalized(XCS("abc  def ghi"), 1));
1346   assert(! is_whitespace_normalized(XCS("abc def ghi "), 0));
1347   assert(is_whitespace_normalized(XCS("abc def ghi "), 1));
1348   assert(! is_whitespace_normalized(XCS(" "), 0));
1349   assert(is_whitespace_normalized(XCS(" "), 1));
1350   assert(! is_whitespace_normalized(XCS("\t"), 0));
1351   assert(! is_whitespace_normalized(XCS("\t"), 1));
1352   assert(! is_whitespace_normalized(XCS("\n"), 0));
1353   assert(! is_whitespace_normalized(XCS("\n"), 1));
1354   assert(! is_whitespace_normalized(XCS("\r"), 0));
1355   assert(! is_whitespace_normalized(XCS("\r"), 1));
1356   assert(! is_whitespace_normalized(XCS("abc\t def"), 1));
1357 }
1358 
1359 static void XMLCALL
1360 check_attr_contains_normalized_whitespace(void *userData, const XML_Char *name,
1361                                           const XML_Char **atts) {
1362   int i;
1363   UNUSED_P(userData);
1364   UNUSED_P(name);
1365   for (i = 0; atts[i] != NULL; i += 2) {
1366     const XML_Char *attrname = atts[i];
1367     const XML_Char *value = atts[i + 1];
1368     if (xcstrcmp(XCS("attr"), attrname) == 0
1369         || xcstrcmp(XCS("ents"), attrname) == 0
1370         || xcstrcmp(XCS("refs"), attrname) == 0) {
1371       if (! is_whitespace_normalized(value, 0)) {
1372         char buffer[256];
1373         sprintf(buffer,
1374                 "attribute value not normalized: %" XML_FMT_STR
1375                 "='%" XML_FMT_STR "'",
1376                 attrname, value);
1377         fail(buffer);
1378       }
1379     }
1380   }
1381 }
1382 
1383 START_TEST(test_attr_whitespace_normalization) {
1384   const char *text
1385       = "<!DOCTYPE doc [\n"
1386         "  <!ATTLIST doc\n"
1387         "            attr NMTOKENS #REQUIRED\n"
1388         "            ents ENTITIES #REQUIRED\n"
1389         "            refs IDREFS   #REQUIRED>\n"
1390         "]>\n"
1391         "<doc attr='    a  b c\t\td\te\t' refs=' id-1   \t  id-2\t\t'  \n"
1392         "     ents=' ent-1   \t\r\n"
1393         "            ent-2  ' >\n"
1394         "  <e id='id-1'/>\n"
1395         "  <e id='id-2'/>\n"
1396         "</doc>";
1397 
1398   XML_SetStartElementHandler(g_parser,
1399                              check_attr_contains_normalized_whitespace);
1400   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
1401       == XML_STATUS_ERROR)
1402     xml_failure(g_parser);
1403 }
1404 END_TEST
1405 
1406 /*
1407  * XML declaration tests.
1408  */
1409 
1410 START_TEST(test_xmldecl_misplaced) {
1411   expect_failure("\n"
1412                  "<?xml version='1.0'?>\n"
1413                  "<a/>",
1414                  XML_ERROR_MISPLACED_XML_PI,
1415                  "failed to report misplaced XML declaration");
1416 }
1417 END_TEST
1418 
1419 START_TEST(test_xmldecl_invalid) {
1420   expect_failure("<?xml version='1.0' \xc3\xa7?>\n<doc/>", XML_ERROR_XML_DECL,
1421                  "Failed to report invalid XML declaration");
1422 }
1423 END_TEST
1424 
1425 START_TEST(test_xmldecl_missing_attr) {
1426   expect_failure("<?xml ='1.0'?>\n<doc/>\n", XML_ERROR_XML_DECL,
1427                  "Failed to report missing XML declaration attribute");
1428 }
1429 END_TEST
1430 
1431 START_TEST(test_xmldecl_missing_value) {
1432   expect_failure("<?xml version='1.0' encoding='us-ascii' standalone?>\n"
1433                  "<doc/>",
1434                  XML_ERROR_XML_DECL,
1435                  "Failed to report missing attribute value");
1436 }
1437 END_TEST
1438 
1439 /* Regression test for SF bug #584832. */
1440 static int XMLCALL
1441 UnknownEncodingHandler(void *data, const XML_Char *encoding,
1442                        XML_Encoding *info) {
1443   UNUSED_P(data);
1444   if (xcstrcmp(encoding, XCS("unsupported-encoding")) == 0) {
1445     int i;
1446     for (i = 0; i < 256; ++i)
1447       info->map[i] = i;
1448     info->data = NULL;
1449     info->convert = NULL;
1450     info->release = NULL;
1451     return XML_STATUS_OK;
1452   }
1453   return XML_STATUS_ERROR;
1454 }
1455 
1456 START_TEST(test_unknown_encoding_internal_entity) {
1457   const char *text = "<?xml version='1.0' encoding='unsupported-encoding'?>\n"
1458                      "<!DOCTYPE test [<!ENTITY foo 'bar'>]>\n"
1459                      "<test a='&foo;'/>";
1460 
1461   XML_SetUnknownEncodingHandler(g_parser, UnknownEncodingHandler, NULL);
1462   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
1463       == XML_STATUS_ERROR)
1464     xml_failure(g_parser);
1465 }
1466 END_TEST
1467 
1468 /* Test unrecognised encoding handler */
1469 static void
1470 dummy_release(void *data) {
1471   UNUSED_P(data);
1472 }
1473 
1474 static int XMLCALL
1475 UnrecognisedEncodingHandler(void *data, const XML_Char *encoding,
1476                             XML_Encoding *info) {
1477   UNUSED_P(data);
1478   UNUSED_P(encoding);
1479   info->data = NULL;
1480   info->convert = NULL;
1481   info->release = dummy_release;
1482   return XML_STATUS_ERROR;
1483 }
1484 
1485 START_TEST(test_unrecognised_encoding_internal_entity) {
1486   const char *text = "<?xml version='1.0' encoding='unsupported-encoding'?>\n"
1487                      "<!DOCTYPE test [<!ENTITY foo 'bar'>]>\n"
1488                      "<test a='&foo;'/>";
1489 
1490   XML_SetUnknownEncodingHandler(g_parser, UnrecognisedEncodingHandler, NULL);
1491   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
1492       != XML_STATUS_ERROR)
1493     fail("Unrecognised encoding not rejected");
1494 }
1495 END_TEST
1496 
1497 /* Regression test for SF bug #620106. */
1498 static int XMLCALL
1499 external_entity_loader(XML_Parser parser, const XML_Char *context,
1500                        const XML_Char *base, const XML_Char *systemId,
1501                        const XML_Char *publicId) {
1502   ExtTest *test_data = (ExtTest *)XML_GetUserData(parser);
1503   XML_Parser extparser;
1504 
1505   UNUSED_P(base);
1506   UNUSED_P(systemId);
1507   UNUSED_P(publicId);
1508   extparser = XML_ExternalEntityParserCreate(parser, context, NULL);
1509   if (extparser == NULL)
1510     fail("Could not create external entity parser.");
1511   if (test_data->encoding != NULL) {
1512     if (! XML_SetEncoding(extparser, test_data->encoding))
1513       fail("XML_SetEncoding() ignored for external entity");
1514   }
1515   if (_XML_Parse_SINGLE_BYTES(extparser, test_data->parse_text,
1516                               (int)strlen(test_data->parse_text), XML_TRUE)
1517       == XML_STATUS_ERROR) {
1518     xml_failure(extparser);
1519     return XML_STATUS_ERROR;
1520   }
1521   XML_ParserFree(extparser);
1522   return XML_STATUS_OK;
1523 }
1524 
1525 START_TEST(test_ext_entity_set_encoding) {
1526   const char *text = "<!DOCTYPE doc [\n"
1527                      "  <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n"
1528                      "]>\n"
1529                      "<doc>&en;</doc>";
1530   ExtTest test_data
1531       = {/* This text says it's an unsupported encoding, but it's really
1532             UTF-8, which we tell Expat using XML_SetEncoding().
1533          */
1534          "<?xml encoding='iso-8859-3'?>\xC3\xA9", XCS("utf-8"), NULL};
1535 #ifdef XML_UNICODE
1536   const XML_Char *expected = XCS("\x00e9");
1537 #else
1538   const XML_Char *expected = XCS("\xc3\xa9");
1539 #endif
1540 
1541   XML_SetExternalEntityRefHandler(g_parser, external_entity_loader);
1542   run_ext_character_check(text, &test_data, expected);
1543 }
1544 END_TEST
1545 
1546 /* Test external entities with no handler */
1547 START_TEST(test_ext_entity_no_handler) {
1548   const char *text = "<!DOCTYPE doc [\n"
1549                      "  <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n"
1550                      "]>\n"
1551                      "<doc>&en;</doc>";
1552 
1553   XML_SetDefaultHandler(g_parser, dummy_default_handler);
1554   run_character_check(text, XCS(""));
1555 }
1556 END_TEST
1557 
1558 /* Test UTF-8 BOM is accepted */
1559 START_TEST(test_ext_entity_set_bom) {
1560   const char *text = "<!DOCTYPE doc [\n"
1561                      "  <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n"
1562                      "]>\n"
1563                      "<doc>&en;</doc>";
1564   ExtTest test_data = {"\xEF\xBB\xBF" /* BOM */
1565                        "<?xml encoding='iso-8859-3'?>"
1566                        "\xC3\xA9",
1567                        XCS("utf-8"), NULL};
1568 #ifdef XML_UNICODE
1569   const XML_Char *expected = XCS("\x00e9");
1570 #else
1571   const XML_Char *expected = XCS("\xc3\xa9");
1572 #endif
1573 
1574   XML_SetExternalEntityRefHandler(g_parser, external_entity_loader);
1575   run_ext_character_check(text, &test_data, expected);
1576 }
1577 END_TEST
1578 
1579 /* Test that bad encodings are faulted */
1580 typedef struct ext_faults {
1581   const char *parse_text;
1582   const char *fail_text;
1583   const XML_Char *encoding;
1584   enum XML_Error error;
1585 } ExtFaults;
1586 
1587 static int XMLCALL
1588 external_entity_faulter(XML_Parser parser, const XML_Char *context,
1589                         const XML_Char *base, const XML_Char *systemId,
1590                         const XML_Char *publicId) {
1591   XML_Parser ext_parser;
1592   ExtFaults *fault = (ExtFaults *)XML_GetUserData(parser);
1593 
1594   UNUSED_P(base);
1595   UNUSED_P(systemId);
1596   UNUSED_P(publicId);
1597   ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
1598   if (ext_parser == NULL)
1599     fail("Could not create external entity parser");
1600   if (fault->encoding != NULL) {
1601     if (! XML_SetEncoding(ext_parser, fault->encoding))
1602       fail("XML_SetEncoding failed");
1603   }
1604   if (_XML_Parse_SINGLE_BYTES(ext_parser, fault->parse_text,
1605                               (int)strlen(fault->parse_text), XML_TRUE)
1606       != XML_STATUS_ERROR)
1607     fail(fault->fail_text);
1608   if (XML_GetErrorCode(ext_parser) != fault->error)
1609     xml_failure(ext_parser);
1610 
1611   XML_ParserFree(ext_parser);
1612   return XML_STATUS_ERROR;
1613 }
1614 
1615 START_TEST(test_ext_entity_bad_encoding) {
1616   const char *text = "<!DOCTYPE doc [\n"
1617                      "  <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n"
1618                      "]>\n"
1619                      "<doc>&en;</doc>";
1620   ExtFaults fault
1621       = {"<?xml encoding='iso-8859-3'?>u", "Unsupported encoding not faulted",
1622          XCS("unknown"), XML_ERROR_UNKNOWN_ENCODING};
1623 
1624   XML_SetExternalEntityRefHandler(g_parser, external_entity_faulter);
1625   XML_SetUserData(g_parser, &fault);
1626   expect_failure(text, XML_ERROR_EXTERNAL_ENTITY_HANDLING,
1627                  "Bad encoding should not have been accepted");
1628 }
1629 END_TEST
1630 
1631 /* Try handing an invalid encoding to an external entity parser */
1632 START_TEST(test_ext_entity_bad_encoding_2) {
1633   const char *text = "<?xml version='1.0' encoding='us-ascii'?>\n"
1634                      "<!DOCTYPE doc SYSTEM 'foo'>\n"
1635                      "<doc>&entity;</doc>";
1636   ExtFaults fault
1637       = {"<!ELEMENT doc (#PCDATA)*>", "Unknown encoding not faulted",
1638          XCS("unknown-encoding"), XML_ERROR_UNKNOWN_ENCODING};
1639 
1640   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
1641   XML_SetExternalEntityRefHandler(g_parser, external_entity_faulter);
1642   XML_SetUserData(g_parser, &fault);
1643   expect_failure(text, XML_ERROR_EXTERNAL_ENTITY_HANDLING,
1644                  "Bad encoding not faulted in external entity handler");
1645 }
1646 END_TEST
1647 
1648 /* Test that no error is reported for unknown entities if we don't
1649    read an external subset.  This was fixed in Expat 1.95.5.
1650 */
1651 START_TEST(test_wfc_undeclared_entity_unread_external_subset) {
1652   const char *text = "<!DOCTYPE doc SYSTEM 'foo'>\n"
1653                      "<doc>&entity;</doc>";
1654 
1655   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
1656       == XML_STATUS_ERROR)
1657     xml_failure(g_parser);
1658 }
1659 END_TEST
1660 
1661 /* Test that an error is reported for unknown entities if we don't
1662    have an external subset.
1663 */
1664 START_TEST(test_wfc_undeclared_entity_no_external_subset) {
1665   expect_failure("<doc>&entity;</doc>", XML_ERROR_UNDEFINED_ENTITY,
1666                  "Parser did not report undefined entity w/out a DTD.");
1667 }
1668 END_TEST
1669 
1670 /* Test that an error is reported for unknown entities if we don't
1671    read an external subset, but have been declared standalone.
1672 */
1673 START_TEST(test_wfc_undeclared_entity_standalone) {
1674   const char *text
1675       = "<?xml version='1.0' encoding='us-ascii' standalone='yes'?>\n"
1676         "<!DOCTYPE doc SYSTEM 'foo'>\n"
1677         "<doc>&entity;</doc>";
1678 
1679   expect_failure(text, XML_ERROR_UNDEFINED_ENTITY,
1680                  "Parser did not report undefined entity (standalone).");
1681 }
1682 END_TEST
1683 
1684 /* Test that an error is reported for unknown entities if we have read
1685    an external subset, and standalone is true.
1686 */
1687 START_TEST(test_wfc_undeclared_entity_with_external_subset_standalone) {
1688   const char *text
1689       = "<?xml version='1.0' encoding='us-ascii' standalone='yes'?>\n"
1690         "<!DOCTYPE doc SYSTEM 'foo'>\n"
1691         "<doc>&entity;</doc>";
1692   ExtTest test_data = {"<!ELEMENT doc (#PCDATA)*>", NULL, NULL};
1693 
1694   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
1695   XML_SetUserData(g_parser, &test_data);
1696   XML_SetExternalEntityRefHandler(g_parser, external_entity_loader);
1697   expect_failure(text, XML_ERROR_UNDEFINED_ENTITY,
1698                  "Parser did not report undefined entity (external DTD).");
1699 }
1700 END_TEST
1701 
1702 /* Test that external entity handling is not done if the parsing flag
1703  * is set to UNLESS_STANDALONE
1704  */
1705 START_TEST(test_entity_with_external_subset_unless_standalone) {
1706   const char *text
1707       = "<?xml version='1.0' encoding='us-ascii' standalone='yes'?>\n"
1708         "<!DOCTYPE doc SYSTEM 'foo'>\n"
1709         "<doc>&entity;</doc>";
1710   ExtTest test_data = {"<!ENTITY entity 'bar'>", NULL, NULL};
1711 
1712   XML_SetParamEntityParsing(g_parser,
1713                             XML_PARAM_ENTITY_PARSING_UNLESS_STANDALONE);
1714   XML_SetUserData(g_parser, &test_data);
1715   XML_SetExternalEntityRefHandler(g_parser, external_entity_loader);
1716   expect_failure(text, XML_ERROR_UNDEFINED_ENTITY,
1717                  "Parser did not report undefined entity");
1718 }
1719 END_TEST
1720 
1721 /* Test that no error is reported for unknown entities if we have read
1722    an external subset, and standalone is false.
1723 */
1724 START_TEST(test_wfc_undeclared_entity_with_external_subset) {
1725   const char *text = "<?xml version='1.0' encoding='us-ascii'?>\n"
1726                      "<!DOCTYPE doc SYSTEM 'foo'>\n"
1727                      "<doc>&entity;</doc>";
1728   ExtTest test_data = {"<!ELEMENT doc (#PCDATA)*>", NULL, NULL};
1729 
1730   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
1731   XML_SetExternalEntityRefHandler(g_parser, external_entity_loader);
1732   run_ext_character_check(text, &test_data, XCS(""));
1733 }
1734 END_TEST
1735 
1736 /* Test that an error is reported if our NotStandalone handler fails */
1737 static int XMLCALL
1738 reject_not_standalone_handler(void *userData) {
1739   UNUSED_P(userData);
1740   return XML_STATUS_ERROR;
1741 }
1742 
1743 START_TEST(test_not_standalone_handler_reject) {
1744   const char *text = "<?xml version='1.0' encoding='us-ascii'?>\n"
1745                      "<!DOCTYPE doc SYSTEM 'foo'>\n"
1746                      "<doc>&entity;</doc>";
1747   ExtTest test_data = {"<!ELEMENT doc (#PCDATA)*>", NULL, NULL};
1748 
1749   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
1750   XML_SetUserData(g_parser, &test_data);
1751   XML_SetExternalEntityRefHandler(g_parser, external_entity_loader);
1752   XML_SetNotStandaloneHandler(g_parser, reject_not_standalone_handler);
1753   expect_failure(text, XML_ERROR_NOT_STANDALONE,
1754                  "NotStandalone handler failed to reject");
1755 
1756   /* Try again but without external entity handling */
1757   XML_ParserReset(g_parser, NULL);
1758   XML_SetNotStandaloneHandler(g_parser, reject_not_standalone_handler);
1759   expect_failure(text, XML_ERROR_NOT_STANDALONE,
1760                  "NotStandalone handler failed to reject");
1761 }
1762 END_TEST
1763 
1764 /* Test that no error is reported if our NotStandalone handler succeeds */
1765 static int XMLCALL
1766 accept_not_standalone_handler(void *userData) {
1767   UNUSED_P(userData);
1768   return XML_STATUS_OK;
1769 }
1770 
1771 START_TEST(test_not_standalone_handler_accept) {
1772   const char *text = "<?xml version='1.0' encoding='us-ascii'?>\n"
1773                      "<!DOCTYPE doc SYSTEM 'foo'>\n"
1774                      "<doc>&entity;</doc>";
1775   ExtTest test_data = {"<!ELEMENT doc (#PCDATA)*>", NULL, NULL};
1776 
1777   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
1778   XML_SetExternalEntityRefHandler(g_parser, external_entity_loader);
1779   XML_SetNotStandaloneHandler(g_parser, accept_not_standalone_handler);
1780   run_ext_character_check(text, &test_data, XCS(""));
1781 
1782   /* Repeat wtihout the external entity handler */
1783   XML_ParserReset(g_parser, NULL);
1784   XML_SetNotStandaloneHandler(g_parser, accept_not_standalone_handler);
1785   run_character_check(text, XCS(""));
1786 }
1787 END_TEST
1788 
1789 START_TEST(test_wfc_no_recursive_entity_refs) {
1790   const char *text = "<!DOCTYPE doc [\n"
1791                      "  <!ENTITY entity '&#38;entity;'>\n"
1792                      "]>\n"
1793                      "<doc>&entity;</doc>";
1794 
1795   expect_failure(text, XML_ERROR_RECURSIVE_ENTITY_REF,
1796                  "Parser did not report recursive entity reference.");
1797 }
1798 END_TEST
1799 
1800 /* Test incomplete external entities are faulted */
1801 START_TEST(test_ext_entity_invalid_parse) {
1802   const char *text = "<!DOCTYPE doc [\n"
1803                      "  <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n"
1804                      "]>\n"
1805                      "<doc>&en;</doc>";
1806   const ExtFaults faults[]
1807       = {{"<", "Incomplete element declaration not faulted", NULL,
1808           XML_ERROR_UNCLOSED_TOKEN},
1809          {"<\xe2\x82", /* First two bytes of a three-byte char */
1810           "Incomplete character not faulted", NULL, XML_ERROR_PARTIAL_CHAR},
1811          {"<tag>\xe2\x82", "Incomplete character in CDATA not faulted", NULL,
1812           XML_ERROR_PARTIAL_CHAR},
1813          {NULL, NULL, NULL, XML_ERROR_NONE}};
1814   const ExtFaults *fault = faults;
1815 
1816   for (; fault->parse_text != NULL; fault++) {
1817     XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
1818     XML_SetExternalEntityRefHandler(g_parser, external_entity_faulter);
1819     XML_SetUserData(g_parser, (void *)fault);
1820     expect_failure(text, XML_ERROR_EXTERNAL_ENTITY_HANDLING,
1821                    "Parser did not report external entity error");
1822     XML_ParserReset(g_parser, NULL);
1823   }
1824 }
1825 END_TEST
1826 
1827 /* Regression test for SF bug #483514. */
1828 START_TEST(test_dtd_default_handling) {
1829   const char *text = "<!DOCTYPE doc [\n"
1830                      "<!ENTITY e SYSTEM 'http://example.org/e'>\n"
1831                      "<!NOTATION n SYSTEM 'http://example.org/n'>\n"
1832                      "<!ELEMENT doc EMPTY>\n"
1833                      "<!ATTLIST doc a CDATA #IMPLIED>\n"
1834                      "<?pi in dtd?>\n"
1835                      "<!--comment in dtd-->\n"
1836                      "]><doc/>";
1837 
1838   XML_SetDefaultHandler(g_parser, accumulate_characters);
1839   XML_SetStartDoctypeDeclHandler(g_parser, dummy_start_doctype_handler);
1840   XML_SetEndDoctypeDeclHandler(g_parser, dummy_end_doctype_handler);
1841   XML_SetEntityDeclHandler(g_parser, dummy_entity_decl_handler);
1842   XML_SetNotationDeclHandler(g_parser, dummy_notation_decl_handler);
1843   XML_SetElementDeclHandler(g_parser, dummy_element_decl_handler);
1844   XML_SetAttlistDeclHandler(g_parser, dummy_attlist_decl_handler);
1845   XML_SetProcessingInstructionHandler(g_parser, dummy_pi_handler);
1846   XML_SetCommentHandler(g_parser, dummy_comment_handler);
1847   XML_SetStartCdataSectionHandler(g_parser, dummy_start_cdata_handler);
1848   XML_SetEndCdataSectionHandler(g_parser, dummy_end_cdata_handler);
1849   run_character_check(text, XCS("\n\n\n\n\n\n\n<doc/>"));
1850 }
1851 END_TEST
1852 
1853 /* Test handling of attribute declarations */
1854 typedef struct AttTest {
1855   const char *definition;
1856   const XML_Char *element_name;
1857   const XML_Char *attr_name;
1858   const XML_Char *attr_type;
1859   const XML_Char *default_value;
1860   int is_required;
1861 } AttTest;
1862 
1863 static void XMLCALL
1864 verify_attlist_decl_handler(void *userData, const XML_Char *element_name,
1865                             const XML_Char *attr_name,
1866                             const XML_Char *attr_type,
1867                             const XML_Char *default_value, int is_required) {
1868   AttTest *at = (AttTest *)userData;
1869 
1870   if (xcstrcmp(element_name, at->element_name))
1871     fail("Unexpected element name in attribute declaration");
1872   if (xcstrcmp(attr_name, at->attr_name))
1873     fail("Unexpected attribute name in attribute declaration");
1874   if (xcstrcmp(attr_type, at->attr_type))
1875     fail("Unexpected attribute type in attribute declaration");
1876   if ((default_value == NULL && at->default_value != NULL)
1877       || (default_value != NULL && at->default_value == NULL)
1878       || (default_value != NULL && xcstrcmp(default_value, at->default_value)))
1879     fail("Unexpected default value in attribute declaration");
1880   if (is_required != at->is_required)
1881     fail("Requirement mismatch in attribute declaration");
1882 }
1883 
1884 START_TEST(test_dtd_attr_handling) {
1885   const char *prolog = "<!DOCTYPE doc [\n"
1886                        "<!ELEMENT doc EMPTY>\n";
1887   AttTest attr_data[]
1888       = {{"<!ATTLIST doc a ( one | two | three ) #REQUIRED>\n"
1889           "]>"
1890           "<doc a='two'/>",
1891           XCS("doc"), XCS("a"),
1892           XCS("(one|two|three)"), /* Extraneous spaces will be removed */
1893           NULL, XML_TRUE},
1894          {"<!NOTATION foo SYSTEM 'http://example.org/foo'>\n"
1895           "<!ATTLIST doc a NOTATION (foo) #IMPLIED>\n"
1896           "]>"
1897           "<doc/>",
1898           XCS("doc"), XCS("a"), XCS("NOTATION(foo)"), NULL, XML_FALSE},
1899          {"<!ATTLIST doc a NOTATION (foo) 'bar'>\n"
1900           "]>"
1901           "<doc/>",
1902           XCS("doc"), XCS("a"), XCS("NOTATION(foo)"), XCS("bar"), XML_FALSE},
1903          {"<!ATTLIST doc a CDATA '\xdb\xb2'>\n"
1904           "]>"
1905           "<doc/>",
1906           XCS("doc"), XCS("a"), XCS("CDATA"),
1907 #ifdef XML_UNICODE
1908           XCS("\x06f2"),
1909 #else
1910           XCS("\xdb\xb2"),
1911 #endif
1912           XML_FALSE},
1913          {NULL, NULL, NULL, NULL, NULL, XML_FALSE}};
1914   AttTest *test;
1915 
1916   for (test = attr_data; test->definition != NULL; test++) {
1917     XML_SetAttlistDeclHandler(g_parser, verify_attlist_decl_handler);
1918     XML_SetUserData(g_parser, test);
1919     if (_XML_Parse_SINGLE_BYTES(g_parser, prolog, (int)strlen(prolog),
1920                                 XML_FALSE)
1921         == XML_STATUS_ERROR)
1922       xml_failure(g_parser);
1923     if (_XML_Parse_SINGLE_BYTES(g_parser, test->definition,
1924                                 (int)strlen(test->definition), XML_TRUE)
1925         == XML_STATUS_ERROR)
1926       xml_failure(g_parser);
1927     XML_ParserReset(g_parser, NULL);
1928   }
1929 }
1930 END_TEST
1931 
1932 /* See related SF bug #673791.
1933    When namespace processing is enabled, setting the namespace URI for
1934    a prefix is not allowed; this test ensures that it *is* allowed
1935    when namespace processing is not enabled.
1936    (See Namespaces in XML, section 2.)
1937 */
1938 START_TEST(test_empty_ns_without_namespaces) {
1939   const char *text = "<doc xmlns:prefix='http://example.org/'>\n"
1940                      "  <e xmlns:prefix=''/>\n"
1941                      "</doc>";
1942 
1943   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
1944       == XML_STATUS_ERROR)
1945     xml_failure(g_parser);
1946 }
1947 END_TEST
1948 
1949 /* Regression test for SF bug #824420.
1950    Checks that an xmlns:prefix attribute set in an attribute's default
1951    value isn't misinterpreted.
1952 */
1953 START_TEST(test_ns_in_attribute_default_without_namespaces) {
1954   const char *text = "<!DOCTYPE e:element [\n"
1955                      "  <!ATTLIST e:element\n"
1956                      "    xmlns:e CDATA 'http://example.org/'>\n"
1957                      "      ]>\n"
1958                      "<e:element/>";
1959 
1960   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
1961       == XML_STATUS_ERROR)
1962     xml_failure(g_parser);
1963 }
1964 END_TEST
1965 
1966 static const char *long_character_data_text
1967     = "<?xml version='1.0' encoding='iso-8859-1'?><s>"
1968       "012345678901234567890123456789012345678901234567890123456789"
1969       "012345678901234567890123456789012345678901234567890123456789"
1970       "012345678901234567890123456789012345678901234567890123456789"
1971       "012345678901234567890123456789012345678901234567890123456789"
1972       "012345678901234567890123456789012345678901234567890123456789"
1973       "012345678901234567890123456789012345678901234567890123456789"
1974       "012345678901234567890123456789012345678901234567890123456789"
1975       "012345678901234567890123456789012345678901234567890123456789"
1976       "012345678901234567890123456789012345678901234567890123456789"
1977       "012345678901234567890123456789012345678901234567890123456789"
1978       "012345678901234567890123456789012345678901234567890123456789"
1979       "012345678901234567890123456789012345678901234567890123456789"
1980       "012345678901234567890123456789012345678901234567890123456789"
1981       "012345678901234567890123456789012345678901234567890123456789"
1982       "012345678901234567890123456789012345678901234567890123456789"
1983       "012345678901234567890123456789012345678901234567890123456789"
1984       "012345678901234567890123456789012345678901234567890123456789"
1985       "012345678901234567890123456789012345678901234567890123456789"
1986       "012345678901234567890123456789012345678901234567890123456789"
1987       "012345678901234567890123456789012345678901234567890123456789"
1988       "</s>";
1989 
1990 static XML_Bool resumable = XML_FALSE;
1991 
1992 static void
1993 clearing_aborting_character_handler(void *userData, const XML_Char *s,
1994                                     int len) {
1995   UNUSED_P(userData);
1996   UNUSED_P(s);
1997   UNUSED_P(len);
1998   XML_StopParser(g_parser, resumable);
1999   XML_SetCharacterDataHandler(g_parser, NULL);
2000 }
2001 
2002 /* Regression test for SF bug #1515266: missing check of stopped
2003    parser in doContext() 'for' loop. */
2004 START_TEST(test_stop_parser_between_char_data_calls) {
2005   /* The sample data must be big enough that there are two calls to
2006      the character data handler from within the inner "for" loop of
2007      the XML_TOK_DATA_CHARS case in doContent(), and the character
2008      handler must stop the parser and clear the character data
2009      handler.
2010   */
2011   const char *text = long_character_data_text;
2012 
2013   XML_SetCharacterDataHandler(g_parser, clearing_aborting_character_handler);
2014   resumable = XML_FALSE;
2015   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
2016       != XML_STATUS_ERROR)
2017     xml_failure(g_parser);
2018   if (XML_GetErrorCode(g_parser) != XML_ERROR_ABORTED)
2019     xml_failure(g_parser);
2020 }
2021 END_TEST
2022 
2023 /* Regression test for SF bug #1515266: missing check of stopped
2024    parser in doContext() 'for' loop. */
2025 START_TEST(test_suspend_parser_between_char_data_calls) {
2026   /* The sample data must be big enough that there are two calls to
2027      the character data handler from within the inner "for" loop of
2028      the XML_TOK_DATA_CHARS case in doContent(), and the character
2029      handler must stop the parser and clear the character data
2030      handler.
2031   */
2032   const char *text = long_character_data_text;
2033 
2034   XML_SetCharacterDataHandler(g_parser, clearing_aborting_character_handler);
2035   resumable = XML_TRUE;
2036   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
2037       != XML_STATUS_SUSPENDED)
2038     xml_failure(g_parser);
2039   if (XML_GetErrorCode(g_parser) != XML_ERROR_NONE)
2040     xml_failure(g_parser);
2041   /* Try parsing directly */
2042   if (XML_Parse(g_parser, text, (int)strlen(text), XML_TRUE)
2043       != XML_STATUS_ERROR)
2044     fail("Attempt to continue parse while suspended not faulted");
2045   if (XML_GetErrorCode(g_parser) != XML_ERROR_SUSPENDED)
2046     fail("Suspended parse not faulted with correct error");
2047 }
2048 END_TEST
2049 
2050 static XML_Bool abortable = XML_FALSE;
2051 
2052 static void
2053 parser_stop_character_handler(void *userData, const XML_Char *s, int len) {
2054   UNUSED_P(userData);
2055   UNUSED_P(s);
2056   UNUSED_P(len);
2057   XML_StopParser(g_parser, resumable);
2058   XML_SetCharacterDataHandler(g_parser, NULL);
2059   if (! resumable) {
2060     /* Check that aborting an aborted parser is faulted */
2061     if (XML_StopParser(g_parser, XML_FALSE) != XML_STATUS_ERROR)
2062       fail("Aborting aborted parser not faulted");
2063     if (XML_GetErrorCode(g_parser) != XML_ERROR_FINISHED)
2064       xml_failure(g_parser);
2065   } else if (abortable) {
2066     /* Check that aborting a suspended parser works */
2067     if (XML_StopParser(g_parser, XML_FALSE) == XML_STATUS_ERROR)
2068       xml_failure(g_parser);
2069   } else {
2070     /* Check that suspending a suspended parser works */
2071     if (XML_StopParser(g_parser, XML_TRUE) != XML_STATUS_ERROR)
2072       fail("Suspending suspended parser not faulted");
2073     if (XML_GetErrorCode(g_parser) != XML_ERROR_SUSPENDED)
2074       xml_failure(g_parser);
2075   }
2076 }
2077 
2078 /* Test repeated calls to XML_StopParser are handled correctly */
2079 START_TEST(test_repeated_stop_parser_between_char_data_calls) {
2080   const char *text = long_character_data_text;
2081 
2082   XML_SetCharacterDataHandler(g_parser, parser_stop_character_handler);
2083   resumable = XML_FALSE;
2084   abortable = XML_FALSE;
2085   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
2086       != XML_STATUS_ERROR)
2087     fail("Failed to double-stop parser");
2088 
2089   XML_ParserReset(g_parser, NULL);
2090   XML_SetCharacterDataHandler(g_parser, parser_stop_character_handler);
2091   resumable = XML_TRUE;
2092   abortable = XML_FALSE;
2093   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
2094       != XML_STATUS_SUSPENDED)
2095     fail("Failed to double-suspend parser");
2096 
2097   XML_ParserReset(g_parser, NULL);
2098   XML_SetCharacterDataHandler(g_parser, parser_stop_character_handler);
2099   resumable = XML_TRUE;
2100   abortable = XML_TRUE;
2101   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
2102       != XML_STATUS_ERROR)
2103     fail("Failed to suspend-abort parser");
2104 }
2105 END_TEST
2106 
2107 START_TEST(test_good_cdata_ascii) {
2108   const char *text = "<a><![CDATA[<greeting>Hello, world!</greeting>]]></a>";
2109   const XML_Char *expected = XCS("<greeting>Hello, world!</greeting>");
2110 
2111   CharData storage;
2112   CharData_Init(&storage);
2113   XML_SetUserData(g_parser, &storage);
2114   XML_SetCharacterDataHandler(g_parser, accumulate_characters);
2115   /* Add start and end handlers for coverage */
2116   XML_SetStartCdataSectionHandler(g_parser, dummy_start_cdata_handler);
2117   XML_SetEndCdataSectionHandler(g_parser, dummy_end_cdata_handler);
2118 
2119   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
2120       == XML_STATUS_ERROR)
2121     xml_failure(g_parser);
2122   CharData_CheckXMLChars(&storage, expected);
2123 
2124   /* Try again, this time with a default handler */
2125   XML_ParserReset(g_parser, NULL);
2126   CharData_Init(&storage);
2127   XML_SetUserData(g_parser, &storage);
2128   XML_SetCharacterDataHandler(g_parser, accumulate_characters);
2129   XML_SetDefaultHandler(g_parser, dummy_default_handler);
2130 
2131   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
2132       == XML_STATUS_ERROR)
2133     xml_failure(g_parser);
2134   CharData_CheckXMLChars(&storage, expected);
2135 }
2136 END_TEST
2137 
2138 START_TEST(test_good_cdata_utf16) {
2139   /* Test data is:
2140    *   <?xml version='1.0' encoding='utf-16'?>
2141    *   <a><![CDATA[hello]]></a>
2142    */
2143   const char text[]
2144       = "\0<\0?\0x\0m\0l\0"
2145         " \0v\0e\0r\0s\0i\0o\0n\0=\0'\0\x31\0.\0\x30\0'\0"
2146         " \0e\0n\0c\0o\0d\0i\0n\0g\0=\0'\0u\0t\0f\0-\0"
2147         "1\0"
2148         "6\0'"
2149         "\0?\0>\0\n"
2150         "\0<\0a\0>\0<\0!\0[\0C\0D\0A\0T\0A\0[\0h\0e\0l\0l\0o\0]\0]\0>\0<\0/\0a\0>";
2151   const XML_Char *expected = XCS("hello");
2152 
2153   CharData storage;
2154   CharData_Init(&storage);
2155   XML_SetUserData(g_parser, &storage);
2156   XML_SetCharacterDataHandler(g_parser, accumulate_characters);
2157 
2158   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE)
2159       == XML_STATUS_ERROR)
2160     xml_failure(g_parser);
2161   CharData_CheckXMLChars(&storage, expected);
2162 }
2163 END_TEST
2164 
2165 START_TEST(test_good_cdata_utf16_le) {
2166   /* Test data is:
2167    *   <?xml version='1.0' encoding='utf-16'?>
2168    *   <a><![CDATA[hello]]></a>
2169    */
2170   const char text[]
2171       = "<\0?\0x\0m\0l\0"
2172         " \0v\0e\0r\0s\0i\0o\0n\0=\0'\0\x31\0.\0\x30\0'\0"
2173         " \0e\0n\0c\0o\0d\0i\0n\0g\0=\0'\0u\0t\0f\0-\0"
2174         "1\0"
2175         "6\0'"
2176         "\0?\0>\0\n"
2177         "\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";
2178   const XML_Char *expected = XCS("hello");
2179 
2180   CharData storage;
2181   CharData_Init(&storage);
2182   XML_SetUserData(g_parser, &storage);
2183   XML_SetCharacterDataHandler(g_parser, accumulate_characters);
2184 
2185   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE)
2186       == XML_STATUS_ERROR)
2187     xml_failure(g_parser);
2188   CharData_CheckXMLChars(&storage, expected);
2189 }
2190 END_TEST
2191 
2192 /* Test UTF16 conversion of a long cdata string */
2193 
2194 /* 16 characters: handy macro to reduce visual clutter */
2195 #define A_TO_P_IN_UTF16 "\0A\0B\0C\0D\0E\0F\0G\0H\0I\0J\0K\0L\0M\0N\0O\0P"
2196 
2197 START_TEST(test_long_cdata_utf16) {
2198   /* Test data is:
2199    * <?xlm version='1.0' encoding='utf-16'?>
2200    * <a><![CDATA[
2201    * ABCDEFGHIJKLMNOP
2202    * ]]></a>
2203    */
2204   const char text[]
2205       = "\0<\0?\0x\0m\0l\0 "
2206         "\0v\0e\0r\0s\0i\0o\0n\0=\0'\0\x31\0.\0\x30\0'\0 "
2207         "\0e\0n\0c\0o\0d\0i\0n\0g\0=\0'\0u\0t\0f\0-\0\x31\0\x36\0'\0?\0>"
2208         "\0<\0a\0>\0<\0!\0[\0C\0D\0A\0T\0A\0["
2209       /* 64 characters per line */
2210       /* clang-format off */
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  A_TO_P_IN_UTF16  A_TO_P_IN_UTF16  A_TO_P_IN_UTF16
2219         A_TO_P_IN_UTF16  A_TO_P_IN_UTF16  A_TO_P_IN_UTF16  A_TO_P_IN_UTF16
2220         A_TO_P_IN_UTF16  A_TO_P_IN_UTF16  A_TO_P_IN_UTF16  A_TO_P_IN_UTF16
2221         A_TO_P_IN_UTF16  A_TO_P_IN_UTF16  A_TO_P_IN_UTF16  A_TO_P_IN_UTF16
2222         A_TO_P_IN_UTF16  A_TO_P_IN_UTF16  A_TO_P_IN_UTF16  A_TO_P_IN_UTF16
2223         A_TO_P_IN_UTF16  A_TO_P_IN_UTF16  A_TO_P_IN_UTF16  A_TO_P_IN_UTF16
2224         A_TO_P_IN_UTF16  A_TO_P_IN_UTF16  A_TO_P_IN_UTF16  A_TO_P_IN_UTF16
2225         A_TO_P_IN_UTF16  A_TO_P_IN_UTF16  A_TO_P_IN_UTF16  A_TO_P_IN_UTF16
2226         A_TO_P_IN_UTF16  A_TO_P_IN_UTF16  A_TO_P_IN_UTF16  A_TO_P_IN_UTF16
2227         A_TO_P_IN_UTF16
2228         /* clang-format on */
2229         "\0]\0]\0>\0<\0/\0a\0>";
2230   const XML_Char *expected =
2231       /* clang-format off */
2232         XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
2233         XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
2234         XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
2235         XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
2236         XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
2237         XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
2238         XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
2239         XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
2240         XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
2241         XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
2242         XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
2243         XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
2244         XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
2245         XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
2246         XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
2247         XCS("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP")
2248         XCS("ABCDEFGHIJKLMNOP");
2249   /* clang-format on */
2250   CharData storage;
2251   void *buffer;
2252 
2253   CharData_Init(&storage);
2254   XML_SetUserData(g_parser, &storage);
2255   XML_SetCharacterDataHandler(g_parser, accumulate_characters);
2256   buffer = XML_GetBuffer(g_parser, sizeof(text) - 1);
2257   if (buffer == NULL)
2258     fail("Could not allocate parse buffer");
2259   assert(buffer != NULL);
2260   memcpy(buffer, text, sizeof(text) - 1);
2261   if (XML_ParseBuffer(g_parser, sizeof(text) - 1, XML_TRUE) == XML_STATUS_ERROR)
2262     xml_failure(g_parser);
2263   CharData_CheckXMLChars(&storage, expected);
2264 }
2265 END_TEST
2266 
2267 /* Test handling of multiple unit UTF-16 characters */
2268 #ifndef XML_MIN_SIZE /* FIXME workaround -DXML_MIN_SIZE + ASan (issue #332) */
2269 START_TEST(test_multichar_cdata_utf16) {
2270   /* Test data is:
2271    *   <?xml version='1.0' encoding='utf-16'?>
2272    *   <a><![CDATA[{MINIM}{CROTCHET}]]></a>
2273    *
2274    * where {MINIM} is U+1d15e (a minim or half-note)
2275    *   UTF-16: 0xd834 0xdd5e
2276    *   UTF-8:  0xf0 0x9d 0x85 0x9e
2277    * and {CROTCHET} is U+1d15f (a crotchet or quarter-note)
2278    *   UTF-16: 0xd834 0xdd5f
2279    *   UTF-8:  0xf0 0x9d 0x85 0x9f
2280    */
2281   const char text[] = "\0<\0?\0x\0m\0l\0"
2282                       " \0v\0e\0r\0s\0i\0o\0n\0=\0'\0\x31\0.\0\x30\0'\0"
2283                       " \0e\0n\0c\0o\0d\0i\0n\0g\0=\0'\0u\0t\0f\0-\0"
2284                       "1\0"
2285                       "6\0'"
2286                       "\0?\0>\0\n"
2287                       "\0<\0a\0>\0<\0!\0[\0C\0D\0A\0T\0A\0["
2288                       "\xd8\x34\xdd\x5e\xd8\x34\xdd\x5f"
2289                       "\0]\0]\0>\0<\0/\0a\0>";
2290 #  ifdef XML_UNICODE
2291   const XML_Char *expected = XCS("\xd834\xdd5e\xd834\xdd5f");
2292 #  else
2293   const XML_Char *expected = XCS("\xf0\x9d\x85\x9e\xf0\x9d\x85\x9f");
2294 #  endif
2295   CharData storage;
2296 
2297   CharData_Init(&storage);
2298   XML_SetUserData(g_parser, &storage);
2299   XML_SetCharacterDataHandler(g_parser, accumulate_characters);
2300 
2301   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE)
2302       == XML_STATUS_ERROR)
2303     xml_failure(g_parser);
2304   CharData_CheckXMLChars(&storage, expected);
2305 }
2306 END_TEST
2307 #endif /* ifndef XML_MIN_SIZE */
2308 
2309 /* Test that an element name with a UTF-16 surrogate pair is rejected */
2310 START_TEST(test_utf16_bad_surrogate_pair) {
2311   /* Test data is:
2312    *   <?xml version='1.0' encoding='utf-16'?>
2313    *   <a><![CDATA[{BADLINB}]]></a>
2314    *
2315    * where {BADLINB} is U+10000 (the first Linear B character)
2316    * with the UTF-16 surrogate pair in the wrong order, i.e.
2317    *   0xdc00 0xd800
2318    */
2319   const char text[] = "\0<\0?\0x\0m\0l\0"
2320                       " \0v\0e\0r\0s\0i\0o\0n\0=\0'\0\x31\0.\0\x30\0'\0"
2321                       " \0e\0n\0c\0o\0d\0i\0n\0g\0=\0'\0u\0t\0f\0-\0"
2322                       "1\0"
2323                       "6\0'"
2324                       "\0?\0>\0\n"
2325                       "\0<\0a\0>\0<\0!\0[\0C\0D\0A\0T\0A\0["
2326                       "\xdc\x00\xd8\x00"
2327                       "\0]\0]\0>\0<\0/\0a\0>";
2328 
2329   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE)
2330       != XML_STATUS_ERROR)
2331     fail("Reversed UTF-16 surrogate pair not faulted");
2332   if (XML_GetErrorCode(g_parser) != XML_ERROR_INVALID_TOKEN)
2333     xml_failure(g_parser);
2334 }
2335 END_TEST
2336 
2337 START_TEST(test_bad_cdata) {
2338   struct CaseData {
2339     const char *text;
2340     enum XML_Error expectedError;
2341   };
2342 
2343   struct CaseData cases[]
2344       = {{"<a><", XML_ERROR_UNCLOSED_TOKEN},
2345          {"<a><!", XML_ERROR_UNCLOSED_TOKEN},
2346          {"<a><![", XML_ERROR_UNCLOSED_TOKEN},
2347          {"<a><![C", XML_ERROR_UNCLOSED_TOKEN},
2348          {"<a><![CD", XML_ERROR_UNCLOSED_TOKEN},
2349          {"<a><![CDA", XML_ERROR_UNCLOSED_TOKEN},
2350          {"<a><![CDAT", XML_ERROR_UNCLOSED_TOKEN},
2351          {"<a><![CDATA", XML_ERROR_UNCLOSED_TOKEN},
2352 
2353          {"<a><![CDATA[", XML_ERROR_UNCLOSED_CDATA_SECTION},
2354          {"<a><![CDATA[]", XML_ERROR_UNCLOSED_CDATA_SECTION},
2355          {"<a><![CDATA[]]", XML_ERROR_UNCLOSED_CDATA_SECTION},
2356 
2357          {"<a><!<a/>", XML_ERROR_INVALID_TOKEN},
2358          {"<a><![<a/>", XML_ERROR_UNCLOSED_TOKEN},  /* ?! */
2359          {"<a><![C<a/>", XML_ERROR_UNCLOSED_TOKEN}, /* ?! */
2360          {"<a><![CD<a/>", XML_ERROR_INVALID_TOKEN},
2361          {"<a><![CDA<a/>", XML_ERROR_INVALID_TOKEN},
2362          {"<a><![CDAT<a/>", XML_ERROR_INVALID_TOKEN},
2363          {"<a><![CDATA<a/>", XML_ERROR_INVALID_TOKEN},
2364 
2365          {"<a><![CDATA[<a/>", XML_ERROR_UNCLOSED_CDATA_SECTION},
2366          {"<a><![CDATA[]<a/>", XML_ERROR_UNCLOSED_CDATA_SECTION},
2367          {"<a><![CDATA[]]<a/>", XML_ERROR_UNCLOSED_CDATA_SECTION}};
2368 
2369   size_t i = 0;
2370   for (; i < sizeof(cases) / sizeof(struct CaseData); i++) {
2371     const enum XML_Status actualStatus = _XML_Parse_SINGLE_BYTES(
2372         g_parser, cases[i].text, (int)strlen(cases[i].text), XML_TRUE);
2373     const enum XML_Error actualError = XML_GetErrorCode(g_parser);
2374 
2375     assert(actualStatus == XML_STATUS_ERROR);
2376 
2377     if (actualError != cases[i].expectedError) {
2378       char message[100];
2379       sprintf(message,
2380               "Expected error %d but got error %d for case %u: \"%s\"\n",
2381               cases[i].expectedError, actualError, (unsigned int)i + 1,
2382               cases[i].text);
2383       fail(message);
2384     }
2385 
2386     XML_ParserReset(g_parser, NULL);
2387   }
2388 }
2389 END_TEST
2390 
2391 /* Test failures in UTF-16 CDATA */
2392 #ifndef XML_MIN_SIZE /* FIXME workaround -DXML_MIN_SIZE + ASan (issue #332) */
2393 START_TEST(test_bad_cdata_utf16) {
2394   struct CaseData {
2395     size_t text_bytes;
2396     const char *text;
2397     enum XML_Error expected_error;
2398   };
2399 
2400   const char prolog[] = "\0<\0?\0x\0m\0l\0"
2401                         " \0v\0e\0r\0s\0i\0o\0n\0=\0'\0\x31\0.\0\x30\0'\0"
2402                         " \0e\0n\0c\0o\0d\0i\0n\0g\0=\0'\0u\0t\0f\0-\0"
2403                         "1\0"
2404                         "6\0'"
2405                         "\0?\0>\0\n"
2406                         "\0<\0a\0>";
2407   struct CaseData cases[] = {
2408       {1, "\0", XML_ERROR_UNCLOSED_TOKEN},
2409       {2, "\0<", XML_ERROR_UNCLOSED_TOKEN},
2410       {3, "\0<\0", XML_ERROR_UNCLOSED_TOKEN},
2411       {4, "\0<\0!", XML_ERROR_UNCLOSED_TOKEN},
2412       {5, "\0<\0!\0", XML_ERROR_UNCLOSED_TOKEN},
2413       {6, "\0<\0!\0[", XML_ERROR_UNCLOSED_TOKEN},
2414       {7, "\0<\0!\0[\0", XML_ERROR_UNCLOSED_TOKEN},
2415       {8, "\0<\0!\0[\0C", XML_ERROR_UNCLOSED_TOKEN},
2416       {9, "\0<\0!\0[\0C\0", XML_ERROR_UNCLOSED_TOKEN},
2417       {10, "\0<\0!\0[\0C\0D", XML_ERROR_UNCLOSED_TOKEN},
2418       {11, "\0<\0!\0[\0C\0D\0", XML_ERROR_UNCLOSED_TOKEN},
2419       {12, "\0<\0!\0[\0C\0D\0A", XML_ERROR_UNCLOSED_TOKEN},
2420       {13, "\0<\0!\0[\0C\0D\0A\0", XML_ERROR_UNCLOSED_TOKEN},
2421       {14, "\0<\0!\0[\0C\0D\0A\0T", XML_ERROR_UNCLOSED_TOKEN},
2422       {15, "\0<\0!\0[\0C\0D\0A\0T\0", XML_ERROR_UNCLOSED_TOKEN},
2423       {16, "\0<\0!\0[\0C\0D\0A\0T\0A", XML_ERROR_UNCLOSED_TOKEN},
2424       {17, "\0<\0!\0[\0C\0D\0A\0T\0A\0", XML_ERROR_UNCLOSED_TOKEN},
2425       {18, "\0<\0!\0[\0C\0D\0A\0T\0A\0[", XML_ERROR_UNCLOSED_CDATA_SECTION},
2426       {19, "\0<\0!\0[\0C\0D\0A\0T\0A\0[\0", XML_ERROR_UNCLOSED_CDATA_SECTION},
2427       {20, "\0<\0!\0[\0C\0D\0A\0T\0A\0[\0Z", XML_ERROR_UNCLOSED_CDATA_SECTION},
2428       /* Now add a four-byte UTF-16 character */
2429       {21, "\0<\0!\0[\0C\0D\0A\0T\0A\0[\0Z\xd8",
2430        XML_ERROR_UNCLOSED_CDATA_SECTION},
2431       {22, "\0<\0!\0[\0C\0D\0A\0T\0A\0[\0Z\xd8\x34", XML_ERROR_PARTIAL_CHAR},
2432       {23, "\0<\0!\0[\0C\0D\0A\0T\0A\0[\0Z\xd8\x34\xdd",
2433        XML_ERROR_PARTIAL_CHAR},
2434       {24, "\0<\0!\0[\0C\0D\0A\0T\0A\0[\0Z\xd8\x34\xdd\x5e",
2435        XML_ERROR_UNCLOSED_CDATA_SECTION}};
2436   size_t i;
2437 
2438   for (i = 0; i < sizeof(cases) / sizeof(struct CaseData); i++) {
2439     enum XML_Status actual_status;
2440     enum XML_Error actual_error;
2441 
2442     if (_XML_Parse_SINGLE_BYTES(g_parser, prolog, (int)sizeof(prolog) - 1,
2443                                 XML_FALSE)
2444         == XML_STATUS_ERROR)
2445       xml_failure(g_parser);
2446     actual_status = _XML_Parse_SINGLE_BYTES(g_parser, cases[i].text,
2447                                             (int)cases[i].text_bytes, XML_TRUE);
2448     assert(actual_status == XML_STATUS_ERROR);
2449     actual_error = XML_GetErrorCode(g_parser);
2450     if (actual_error != cases[i].expected_error) {
2451       char message[1024];
2452 
2453       sprintf(message,
2454               "Expected error %d (%" XML_FMT_STR "), got %d (%" XML_FMT_STR
2455               ") for case %lu\n",
2456               cases[i].expected_error, XML_ErrorString(cases[i].expected_error),
2457               actual_error, XML_ErrorString(actual_error),
2458               (long unsigned)(i + 1));
2459       fail(message);
2460     }
2461     XML_ParserReset(g_parser, NULL);
2462   }
2463 }
2464 END_TEST
2465 #endif /* ifndef XML_MIN_SIZE */
2466 
2467 static const char *long_cdata_text
2468     = "<s><![CDATA["
2469       "012345678901234567890123456789012345678901234567890123456789"
2470       "012345678901234567890123456789012345678901234567890123456789"
2471       "012345678901234567890123456789012345678901234567890123456789"
2472       "012345678901234567890123456789012345678901234567890123456789"
2473       "012345678901234567890123456789012345678901234567890123456789"
2474       "012345678901234567890123456789012345678901234567890123456789"
2475       "012345678901234567890123456789012345678901234567890123456789"
2476       "012345678901234567890123456789012345678901234567890123456789"
2477       "012345678901234567890123456789012345678901234567890123456789"
2478       "012345678901234567890123456789012345678901234567890123456789"
2479       "012345678901234567890123456789012345678901234567890123456789"
2480       "012345678901234567890123456789012345678901234567890123456789"
2481       "012345678901234567890123456789012345678901234567890123456789"
2482       "012345678901234567890123456789012345678901234567890123456789"
2483       "012345678901234567890123456789012345678901234567890123456789"
2484       "012345678901234567890123456789012345678901234567890123456789"
2485       "012345678901234567890123456789012345678901234567890123456789"
2486       "012345678901234567890123456789012345678901234567890123456789"
2487       "012345678901234567890123456789012345678901234567890123456789"
2488       "012345678901234567890123456789012345678901234567890123456789"
2489       "]]></s>";
2490 
2491 /* Test stopping the parser in cdata handler */
2492 START_TEST(test_stop_parser_between_cdata_calls) {
2493   const char *text = long_cdata_text;
2494 
2495   XML_SetCharacterDataHandler(g_parser, clearing_aborting_character_handler);
2496   resumable = XML_FALSE;
2497   expect_failure(text, XML_ERROR_ABORTED, "Parse not aborted in CDATA handler");
2498 }
2499 END_TEST
2500 
2501 /* Test suspending the parser in cdata handler */
2502 START_TEST(test_suspend_parser_between_cdata_calls) {
2503   const char *text = long_cdata_text;
2504   enum XML_Status result;
2505 
2506   XML_SetCharacterDataHandler(g_parser, clearing_aborting_character_handler);
2507   resumable = XML_TRUE;
2508   result = _XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE);
2509   if (result != XML_STATUS_SUSPENDED) {
2510     if (result == XML_STATUS_ERROR)
2511       xml_failure(g_parser);
2512     fail("Parse not suspended in CDATA handler");
2513   }
2514   if (XML_GetErrorCode(g_parser) != XML_ERROR_NONE)
2515     xml_failure(g_parser);
2516 }
2517 END_TEST
2518 
2519 /* Test memory allocation functions */
2520 START_TEST(test_memory_allocation) {
2521   char *buffer = (char *)XML_MemMalloc(g_parser, 256);
2522   char *p;
2523 
2524   if (buffer == NULL) {
2525     fail("Allocation failed");
2526   } else {
2527     /* Try writing to memory; some OSes try to cheat! */
2528     buffer[0] = 'T';
2529     buffer[1] = 'E';
2530     buffer[2] = 'S';
2531     buffer[3] = 'T';
2532     buffer[4] = '\0';
2533     if (strcmp(buffer, "TEST") != 0) {
2534       fail("Memory not writable");
2535     } else {
2536       p = (char *)XML_MemRealloc(g_parser, buffer, 512);
2537       if (p == NULL) {
2538         fail("Reallocation failed");
2539       } else {
2540         /* Write again, just to be sure */
2541         buffer = p;
2542         buffer[0] = 'V';
2543         if (strcmp(buffer, "VEST") != 0) {
2544           fail("Reallocated memory not writable");
2545         }
2546       }
2547     }
2548     XML_MemFree(g_parser, buffer);
2549   }
2550 }
2551 END_TEST
2552 
2553 static void XMLCALL
2554 record_default_handler(void *userData, const XML_Char *s, int len) {
2555   UNUSED_P(s);
2556   UNUSED_P(len);
2557   CharData_AppendXMLChars((CharData *)userData, XCS("D"), 1);
2558 }
2559 
2560 static void XMLCALL
2561 record_cdata_handler(void *userData, const XML_Char *s, int len) {
2562   UNUSED_P(s);
2563   UNUSED_P(len);
2564   CharData_AppendXMLChars((CharData *)userData, XCS("C"), 1);
2565   XML_DefaultCurrent(g_parser);
2566 }
2567 
2568 static void XMLCALL
2569 record_cdata_nodefault_handler(void *userData, const XML_Char *s, int len) {
2570   UNUSED_P(s);
2571   UNUSED_P(len);
2572   CharData_AppendXMLChars((CharData *)userData, XCS("c"), 1);
2573 }
2574 
2575 static void XMLCALL
2576 record_skip_handler(void *userData, const XML_Char *entityName,
2577                     int is_parameter_entity) {
2578   UNUSED_P(entityName);
2579   CharData_AppendXMLChars((CharData *)userData,
2580                           is_parameter_entity ? XCS("E") : XCS("e"), 1);
2581 }
2582 
2583 /* Test XML_DefaultCurrent() passes handling on correctly */
2584 START_TEST(test_default_current) {
2585   const char *text = "<doc>hell]</doc>";
2586   const char *entity_text = "<!DOCTYPE doc [\n"
2587                             "<!ENTITY entity '&#37;'>\n"
2588                             "]>\n"
2589                             "<doc>&entity;</doc>";
2590   CharData storage;
2591 
2592   XML_SetDefaultHandler(g_parser, record_default_handler);
2593   XML_SetCharacterDataHandler(g_parser, record_cdata_handler);
2594   CharData_Init(&storage);
2595   XML_SetUserData(g_parser, &storage);
2596   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
2597       == XML_STATUS_ERROR)
2598     xml_failure(g_parser);
2599   CharData_CheckXMLChars(&storage, XCS("DCDCDCDCDCDD"));
2600 
2601   /* Again, without the defaulting */
2602   XML_ParserReset(g_parser, NULL);
2603   XML_SetDefaultHandler(g_parser, record_default_handler);
2604   XML_SetCharacterDataHandler(g_parser, record_cdata_nodefault_handler);
2605   CharData_Init(&storage);
2606   XML_SetUserData(g_parser, &storage);
2607   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
2608       == XML_STATUS_ERROR)
2609     xml_failure(g_parser);
2610   CharData_CheckXMLChars(&storage, XCS("DcccccD"));
2611 
2612   /* Now with an internal entity to complicate matters */
2613   XML_ParserReset(g_parser, NULL);
2614   XML_SetDefaultHandler(g_parser, record_default_handler);
2615   XML_SetCharacterDataHandler(g_parser, record_cdata_handler);
2616   CharData_Init(&storage);
2617   XML_SetUserData(g_parser, &storage);
2618   if (_XML_Parse_SINGLE_BYTES(g_parser, entity_text, (int)strlen(entity_text),
2619                               XML_TRUE)
2620       == XML_STATUS_ERROR)
2621     xml_failure(g_parser);
2622   /* The default handler suppresses the entity */
2623   CharData_CheckXMLChars(&storage, XCS("DDDDDDDDDDDDDDDDDDD"));
2624 
2625   /* Again, with a skip handler */
2626   XML_ParserReset(g_parser, NULL);
2627   XML_SetDefaultHandler(g_parser, record_default_handler);
2628   XML_SetCharacterDataHandler(g_parser, record_cdata_handler);
2629   XML_SetSkippedEntityHandler(g_parser, record_skip_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   /* The default handler suppresses the entity */
2637   CharData_CheckXMLChars(&storage, XCS("DDDDDDDDDDDDDDDDDeD"));
2638 
2639   /* This time, allow the entity through */
2640   XML_ParserReset(g_parser, NULL);
2641   XML_SetDefaultHandlerExpand(g_parser, record_default_handler);
2642   XML_SetCharacterDataHandler(g_parser, record_cdata_handler);
2643   CharData_Init(&storage);
2644   XML_SetUserData(g_parser, &storage);
2645   if (_XML_Parse_SINGLE_BYTES(g_parser, entity_text, (int)strlen(entity_text),
2646                               XML_TRUE)
2647       == XML_STATUS_ERROR)
2648     xml_failure(g_parser);
2649   CharData_CheckXMLChars(&storage, XCS("DDDDDDDDDDDDDDDDDCDD"));
2650 
2651   /* Finally, without passing the cdata to the default handler */
2652   XML_ParserReset(g_parser, NULL);
2653   XML_SetDefaultHandlerExpand(g_parser, record_default_handler);
2654   XML_SetCharacterDataHandler(g_parser, record_cdata_nodefault_handler);
2655   CharData_Init(&storage);
2656   XML_SetUserData(g_parser, &storage);
2657   if (_XML_Parse_SINGLE_BYTES(g_parser, entity_text, (int)strlen(entity_text),
2658                               XML_TRUE)
2659       == XML_STATUS_ERROR)
2660     xml_failure(g_parser);
2661   CharData_CheckXMLChars(&storage, XCS("DDDDDDDDDDDDDDDDDcD"));
2662 }
2663 END_TEST
2664 
2665 /* Test DTD element parsing code paths */
2666 START_TEST(test_dtd_elements) {
2667   const char *text = "<!DOCTYPE doc [\n"
2668                      "<!ELEMENT doc (chapter)>\n"
2669                      "<!ELEMENT chapter (#PCDATA)>\n"
2670                      "]>\n"
2671                      "<doc><chapter>Wombats are go</chapter></doc>";
2672 
2673   XML_SetElementDeclHandler(g_parser, dummy_element_decl_handler);
2674   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
2675       == XML_STATUS_ERROR)
2676     xml_failure(g_parser);
2677 }
2678 END_TEST
2679 
2680 /* Test foreign DTD handling */
2681 START_TEST(test_set_foreign_dtd) {
2682   const char *text1 = "<?xml version='1.0' encoding='us-ascii'?>\n";
2683   const char *text2 = "<doc>&entity;</doc>";
2684   ExtTest test_data = {"<!ELEMENT doc (#PCDATA)*>", NULL, NULL};
2685 
2686   /* Check hash salt is passed through too */
2687   XML_SetHashSalt(g_parser, 0x12345678);
2688   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
2689   XML_SetUserData(g_parser, &test_data);
2690   XML_SetExternalEntityRefHandler(g_parser, external_entity_loader);
2691   /* Add a default handler to exercise more code paths */
2692   XML_SetDefaultHandler(g_parser, dummy_default_handler);
2693   if (XML_UseForeignDTD(g_parser, XML_TRUE) != XML_ERROR_NONE)
2694     fail("Could not set foreign DTD");
2695   if (_XML_Parse_SINGLE_BYTES(g_parser, text1, (int)strlen(text1), XML_FALSE)
2696       == XML_STATUS_ERROR)
2697     xml_failure(g_parser);
2698 
2699   /* Ensure that trying to set the DTD after parsing has started
2700    * is faulted, even if it's the same setting.
2701    */
2702   if (XML_UseForeignDTD(g_parser, XML_TRUE)
2703       != XML_ERROR_CANT_CHANGE_FEATURE_ONCE_PARSING)
2704     fail("Failed to reject late foreign DTD setting");
2705   /* Ditto for the hash salt */
2706   if (XML_SetHashSalt(g_parser, 0x23456789))
2707     fail("Failed to reject late hash salt change");
2708 
2709   /* Now finish the parse */
2710   if (_XML_Parse_SINGLE_BYTES(g_parser, text2, (int)strlen(text2), XML_TRUE)
2711       == XML_STATUS_ERROR)
2712     xml_failure(g_parser);
2713 }
2714 END_TEST
2715 
2716 /* Test foreign DTD handling with a failing NotStandalone handler */
2717 START_TEST(test_foreign_dtd_not_standalone) {
2718   const char *text = "<?xml version='1.0' encoding='us-ascii'?>\n"
2719                      "<doc>&entity;</doc>";
2720   ExtTest test_data = {"<!ELEMENT doc (#PCDATA)*>", NULL, NULL};
2721 
2722   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
2723   XML_SetUserData(g_parser, &test_data);
2724   XML_SetExternalEntityRefHandler(g_parser, external_entity_loader);
2725   XML_SetNotStandaloneHandler(g_parser, reject_not_standalone_handler);
2726   if (XML_UseForeignDTD(g_parser, XML_TRUE) != XML_ERROR_NONE)
2727     fail("Could not set foreign DTD");
2728   expect_failure(text, XML_ERROR_NOT_STANDALONE,
2729                  "NotStandalonehandler failed to reject");
2730 }
2731 END_TEST
2732 
2733 /* Test invalid character in a foreign DTD is faulted */
2734 START_TEST(test_invalid_foreign_dtd) {
2735   const char *text = "<?xml version='1.0' encoding='us-ascii'?>\n"
2736                      "<doc>&entity;</doc>";
2737   ExtFaults test_data
2738       = {"$", "Dollar not faulted", NULL, XML_ERROR_INVALID_TOKEN};
2739 
2740   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
2741   XML_SetUserData(g_parser, &test_data);
2742   XML_SetExternalEntityRefHandler(g_parser, external_entity_faulter);
2743   XML_UseForeignDTD(g_parser, XML_TRUE);
2744   expect_failure(text, XML_ERROR_EXTERNAL_ENTITY_HANDLING,
2745                  "Bad DTD should not have been accepted");
2746 }
2747 END_TEST
2748 
2749 /* Test foreign DTD use with a doctype */
2750 START_TEST(test_foreign_dtd_with_doctype) {
2751   const char *text1 = "<?xml version='1.0' encoding='us-ascii'?>\n"
2752                       "<!DOCTYPE doc [<!ENTITY entity 'hello world'>]>\n";
2753   const char *text2 = "<doc>&entity;</doc>";
2754   ExtTest test_data = {"<!ELEMENT doc (#PCDATA)*>", NULL, NULL};
2755 
2756   /* Check hash salt is passed through too */
2757   XML_SetHashSalt(g_parser, 0x12345678);
2758   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
2759   XML_SetUserData(g_parser, &test_data);
2760   XML_SetExternalEntityRefHandler(g_parser, external_entity_loader);
2761   /* Add a default handler to exercise more code paths */
2762   XML_SetDefaultHandler(g_parser, dummy_default_handler);
2763   if (XML_UseForeignDTD(g_parser, XML_TRUE) != XML_ERROR_NONE)
2764     fail("Could not set foreign DTD");
2765   if (_XML_Parse_SINGLE_BYTES(g_parser, text1, (int)strlen(text1), XML_FALSE)
2766       == XML_STATUS_ERROR)
2767     xml_failure(g_parser);
2768 
2769   /* Ensure that trying to set the DTD after parsing has started
2770    * is faulted, even if it's the same setting.
2771    */
2772   if (XML_UseForeignDTD(g_parser, XML_TRUE)
2773       != XML_ERROR_CANT_CHANGE_FEATURE_ONCE_PARSING)
2774     fail("Failed to reject late foreign DTD setting");
2775   /* Ditto for the hash salt */
2776   if (XML_SetHashSalt(g_parser, 0x23456789))
2777     fail("Failed to reject late hash salt change");
2778 
2779   /* Now finish the parse */
2780   if (_XML_Parse_SINGLE_BYTES(g_parser, text2, (int)strlen(text2), XML_TRUE)
2781       == XML_STATUS_ERROR)
2782     xml_failure(g_parser);
2783 }
2784 END_TEST
2785 
2786 /* Test XML_UseForeignDTD with no external subset present */
2787 static int XMLCALL
2788 external_entity_null_loader(XML_Parser parser, const XML_Char *context,
2789                             const XML_Char *base, const XML_Char *systemId,
2790                             const XML_Char *publicId) {
2791   UNUSED_P(parser);
2792   UNUSED_P(context);
2793   UNUSED_P(base);
2794   UNUSED_P(systemId);
2795   UNUSED_P(publicId);
2796   return XML_STATUS_OK;
2797 }
2798 
2799 START_TEST(test_foreign_dtd_without_external_subset) {
2800   const char *text = "<!DOCTYPE doc [<!ENTITY foo 'bar'>]>\n"
2801                      "<doc>&foo;</doc>";
2802 
2803   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
2804   XML_SetUserData(g_parser, NULL);
2805   XML_SetExternalEntityRefHandler(g_parser, external_entity_null_loader);
2806   XML_UseForeignDTD(g_parser, XML_TRUE);
2807   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
2808       == XML_STATUS_ERROR)
2809     xml_failure(g_parser);
2810 }
2811 END_TEST
2812 
2813 START_TEST(test_empty_foreign_dtd) {
2814   const char *text = "<?xml version='1.0' encoding='us-ascii'?>\n"
2815                      "<doc>&entity;</doc>";
2816 
2817   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
2818   XML_SetExternalEntityRefHandler(g_parser, external_entity_null_loader);
2819   XML_UseForeignDTD(g_parser, XML_TRUE);
2820   expect_failure(text, XML_ERROR_UNDEFINED_ENTITY,
2821                  "Undefined entity not faulted");
2822 }
2823 END_TEST
2824 
2825 /* Test XML Base is set and unset appropriately */
2826 START_TEST(test_set_base) {
2827   const XML_Char *old_base;
2828   const XML_Char *new_base = XCS("/local/file/name.xml");
2829 
2830   old_base = XML_GetBase(g_parser);
2831   if (XML_SetBase(g_parser, new_base) != XML_STATUS_OK)
2832     fail("Unable to set base");
2833   if (xcstrcmp(XML_GetBase(g_parser), new_base) != 0)
2834     fail("Base setting not correct");
2835   if (XML_SetBase(g_parser, NULL) != XML_STATUS_OK)
2836     fail("Unable to NULL base");
2837   if (XML_GetBase(g_parser) != NULL)
2838     fail("Base setting not nulled");
2839   XML_SetBase(g_parser, old_base);
2840 }
2841 END_TEST
2842 
2843 /* Test attribute counts, indexing, etc */
2844 typedef struct attrInfo {
2845   const XML_Char *name;
2846   const XML_Char *value;
2847 } AttrInfo;
2848 
2849 typedef struct elementInfo {
2850   const XML_Char *name;
2851   int attr_count;
2852   const XML_Char *id_name;
2853   AttrInfo *attributes;
2854 } ElementInfo;
2855 
2856 static void XMLCALL
2857 counting_start_element_handler(void *userData, const XML_Char *name,
2858                                const XML_Char **atts) {
2859   ElementInfo *info = (ElementInfo *)userData;
2860   AttrInfo *attr;
2861   int count, id, i;
2862 
2863   while (info->name != NULL) {
2864     if (! xcstrcmp(name, info->name))
2865       break;
2866     info++;
2867   }
2868   if (info->name == NULL)
2869     fail("Element not recognised");
2870   /* The attribute count is twice what you might expect.  It is a
2871    * count of items in atts, an array which contains alternating
2872    * attribute names and attribute values.  For the naive user this
2873    * is possibly a little unexpected, but it is what the
2874    * documentation in expat.h tells us to expect.
2875    */
2876   count = XML_GetSpecifiedAttributeCount(g_parser);
2877   if (info->attr_count * 2 != count) {
2878     fail("Not got expected attribute count");
2879     return;
2880   }
2881   id = XML_GetIdAttributeIndex(g_parser);
2882   if (id == -1 && info->id_name != NULL) {
2883     fail("ID not present");
2884     return;
2885   }
2886   if (id != -1 && xcstrcmp(atts[id], info->id_name)) {
2887     fail("ID does not have the correct name");
2888     return;
2889   }
2890   for (i = 0; i < info->attr_count; i++) {
2891     attr = info->attributes;
2892     while (attr->name != NULL) {
2893       if (! xcstrcmp(atts[0], attr->name))
2894         break;
2895       attr++;
2896     }
2897     if (attr->name == NULL) {
2898       fail("Attribute not recognised");
2899       return;
2900     }
2901     if (xcstrcmp(atts[1], attr->value)) {
2902       fail("Attribute has wrong value");
2903       return;
2904     }
2905     /* Remember, two entries in atts per attribute (see above) */
2906     atts += 2;
2907   }
2908 }
2909 
2910 START_TEST(test_attributes) {
2911   const char *text = "<!DOCTYPE doc [\n"
2912                      "<!ELEMENT doc (tag)>\n"
2913                      "<!ATTLIST doc id ID #REQUIRED>\n"
2914                      "]>"
2915                      "<doc a='1' id='one' b='2'>"
2916                      "<tag c='3'/>"
2917                      "</doc>";
2918   AttrInfo doc_info[] = {{XCS("a"), XCS("1")},
2919                          {XCS("b"), XCS("2")},
2920                          {XCS("id"), XCS("one")},
2921                          {NULL, NULL}};
2922   AttrInfo tag_info[] = {{XCS("c"), XCS("3")}, {NULL, NULL}};
2923   ElementInfo info[] = {{XCS("doc"), 3, XCS("id"), NULL},
2924                         {XCS("tag"), 1, NULL, NULL},
2925                         {NULL, 0, NULL, NULL}};
2926   info[0].attributes = doc_info;
2927   info[1].attributes = tag_info;
2928 
2929   XML_SetStartElementHandler(g_parser, counting_start_element_handler);
2930   XML_SetUserData(g_parser, info);
2931   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
2932       == XML_STATUS_ERROR)
2933     xml_failure(g_parser);
2934 }
2935 END_TEST
2936 
2937 /* Test reset works correctly in the middle of processing an internal
2938  * entity.  Exercises some obscure code in XML_ParserReset().
2939  */
2940 START_TEST(test_reset_in_entity) {
2941   const char *text = "<!DOCTYPE doc [\n"
2942                      "<!ENTITY wombat 'wom'>\n"
2943                      "<!ENTITY entity 'hi &wom; there'>\n"
2944                      "]>\n"
2945                      "<doc>&entity;</doc>";
2946   XML_ParsingStatus status;
2947 
2948   resumable = XML_TRUE;
2949   XML_SetCharacterDataHandler(g_parser, clearing_aborting_character_handler);
2950   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_FALSE)
2951       == XML_STATUS_ERROR)
2952     xml_failure(g_parser);
2953   XML_GetParsingStatus(g_parser, &status);
2954   if (status.parsing != XML_SUSPENDED)
2955     fail("Parsing status not SUSPENDED");
2956   XML_ParserReset(g_parser, NULL);
2957   XML_GetParsingStatus(g_parser, &status);
2958   if (status.parsing != XML_INITIALIZED)
2959     fail("Parsing status doesn't reset to INITIALIZED");
2960 }
2961 END_TEST
2962 
2963 /* Test that resume correctly passes through parse errors */
2964 START_TEST(test_resume_invalid_parse) {
2965   const char *text = "<doc>Hello</doc"; /* Missing closing wedge */
2966 
2967   resumable = XML_TRUE;
2968   XML_SetCharacterDataHandler(g_parser, clearing_aborting_character_handler);
2969   if (XML_Parse(g_parser, text, (int)strlen(text), XML_TRUE)
2970       == XML_STATUS_ERROR)
2971     xml_failure(g_parser);
2972   if (XML_ResumeParser(g_parser) == XML_STATUS_OK)
2973     fail("Resumed invalid parse not faulted");
2974   if (XML_GetErrorCode(g_parser) != XML_ERROR_UNCLOSED_TOKEN)
2975     fail("Invalid parse not correctly faulted");
2976 }
2977 END_TEST
2978 
2979 /* Test that re-suspended parses are correctly passed through */
2980 START_TEST(test_resume_resuspended) {
2981   const char *text = "<doc>Hello<meep/>world</doc>";
2982 
2983   resumable = XML_TRUE;
2984   XML_SetCharacterDataHandler(g_parser, clearing_aborting_character_handler);
2985   if (XML_Parse(g_parser, text, (int)strlen(text), XML_TRUE)
2986       == XML_STATUS_ERROR)
2987     xml_failure(g_parser);
2988   resumable = XML_TRUE;
2989   XML_SetCharacterDataHandler(g_parser, clearing_aborting_character_handler);
2990   if (XML_ResumeParser(g_parser) != XML_STATUS_SUSPENDED)
2991     fail("Resumption not suspended");
2992   /* This one should succeed and finish up */
2993   if (XML_ResumeParser(g_parser) != XML_STATUS_OK)
2994     xml_failure(g_parser);
2995 }
2996 END_TEST
2997 
2998 /* Test that CDATA shows up correctly through a default handler */
2999 START_TEST(test_cdata_default) {
3000   const char *text = "<doc><![CDATA[Hello\nworld]]></doc>";
3001   const XML_Char *expected = XCS("<doc><![CDATA[Hello\nworld]]></doc>");
3002   CharData storage;
3003 
3004   CharData_Init(&storage);
3005   XML_SetUserData(g_parser, &storage);
3006   XML_SetDefaultHandler(g_parser, accumulate_characters);
3007 
3008   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
3009       == XML_STATUS_ERROR)
3010     xml_failure(g_parser);
3011   CharData_CheckXMLChars(&storage, expected);
3012 }
3013 END_TEST
3014 
3015 /* Test resetting a subordinate parser does exactly nothing */
3016 static int XMLCALL
3017 external_entity_resetter(XML_Parser parser, const XML_Char *context,
3018                          const XML_Char *base, const XML_Char *systemId,
3019                          const XML_Char *publicId) {
3020   const char *text = "<!ELEMENT doc (#PCDATA)*>";
3021   XML_Parser ext_parser;
3022   XML_ParsingStatus status;
3023 
3024   UNUSED_P(base);
3025   UNUSED_P(systemId);
3026   UNUSED_P(publicId);
3027   ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
3028   if (ext_parser == NULL)
3029     fail("Could not create external entity parser");
3030   XML_GetParsingStatus(ext_parser, &status);
3031   if (status.parsing != XML_INITIALIZED) {
3032     fail("Parsing status is not INITIALIZED");
3033     return XML_STATUS_ERROR;
3034   }
3035   if (_XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE)
3036       == XML_STATUS_ERROR) {
3037     xml_failure(parser);
3038     return XML_STATUS_ERROR;
3039   }
3040   XML_GetParsingStatus(ext_parser, &status);
3041   if (status.parsing != XML_FINISHED) {
3042     fail("Parsing status is not FINISHED");
3043     return XML_STATUS_ERROR;
3044   }
3045   /* Check we can't parse here */
3046   if (XML_Parse(ext_parser, text, (int)strlen(text), XML_TRUE)
3047       != XML_STATUS_ERROR)
3048     fail("Parsing when finished not faulted");
3049   if (XML_GetErrorCode(ext_parser) != XML_ERROR_FINISHED)
3050     fail("Parsing when finished faulted with wrong code");
3051   XML_ParserReset(ext_parser, NULL);
3052   XML_GetParsingStatus(ext_parser, &status);
3053   if (status.parsing != XML_FINISHED) {
3054     fail("Parsing status not still FINISHED");
3055     return XML_STATUS_ERROR;
3056   }
3057   XML_ParserFree(ext_parser);
3058   return XML_STATUS_OK;
3059 }
3060 
3061 START_TEST(test_subordinate_reset) {
3062   const char *text = "<?xml version='1.0' encoding='us-ascii'?>\n"
3063                      "<!DOCTYPE doc SYSTEM 'foo'>\n"
3064                      "<doc>&entity;</doc>";
3065 
3066   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
3067   XML_SetExternalEntityRefHandler(g_parser, external_entity_resetter);
3068   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
3069       == XML_STATUS_ERROR)
3070     xml_failure(g_parser);
3071 }
3072 END_TEST
3073 
3074 /* Test suspending a subordinate parser */
3075 
3076 static void XMLCALL
3077 entity_suspending_decl_handler(void *userData, const XML_Char *name,
3078                                XML_Content *model) {
3079   XML_Parser ext_parser = (XML_Parser)userData;
3080 
3081   UNUSED_P(name);
3082   if (XML_StopParser(ext_parser, XML_TRUE) != XML_STATUS_ERROR)
3083     fail("Attempting to suspend a subordinate parser not faulted");
3084   if (XML_GetErrorCode(ext_parser) != XML_ERROR_SUSPEND_PE)
3085     fail("Suspending subordinate parser get wrong code");
3086   XML_SetElementDeclHandler(ext_parser, NULL);
3087   XML_FreeContentModel(g_parser, model);
3088 }
3089 
3090 static int XMLCALL
3091 external_entity_suspender(XML_Parser parser, const XML_Char *context,
3092                           const XML_Char *base, const XML_Char *systemId,
3093                           const XML_Char *publicId) {
3094   const char *text = "<!ELEMENT doc (#PCDATA)*>";
3095   XML_Parser ext_parser;
3096 
3097   UNUSED_P(base);
3098   UNUSED_P(systemId);
3099   UNUSED_P(publicId);
3100   ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
3101   if (ext_parser == NULL)
3102     fail("Could not create external entity parser");
3103   XML_SetElementDeclHandler(ext_parser, entity_suspending_decl_handler);
3104   XML_SetUserData(ext_parser, ext_parser);
3105   if (_XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE)
3106       == XML_STATUS_ERROR) {
3107     xml_failure(ext_parser);
3108     return XML_STATUS_ERROR;
3109   }
3110   XML_ParserFree(ext_parser);
3111   return XML_STATUS_OK;
3112 }
3113 
3114 START_TEST(test_subordinate_suspend) {
3115   const char *text = "<?xml version='1.0' encoding='us-ascii'?>\n"
3116                      "<!DOCTYPE doc SYSTEM 'foo'>\n"
3117                      "<doc>&entity;</doc>";
3118 
3119   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
3120   XML_SetExternalEntityRefHandler(g_parser, external_entity_suspender);
3121   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
3122       == XML_STATUS_ERROR)
3123     xml_failure(g_parser);
3124 }
3125 END_TEST
3126 
3127 /* Test suspending a subordinate parser from an XML declaration */
3128 /* Increases code coverage of the tests */
3129 static void XMLCALL
3130 entity_suspending_xdecl_handler(void *userData, const XML_Char *version,
3131                                 const XML_Char *encoding, int standalone) {
3132   XML_Parser ext_parser = (XML_Parser)userData;
3133 
3134   UNUSED_P(version);
3135   UNUSED_P(encoding);
3136   UNUSED_P(standalone);
3137   XML_StopParser(ext_parser, resumable);
3138   XML_SetXmlDeclHandler(ext_parser, NULL);
3139 }
3140 
3141 static int XMLCALL
3142 external_entity_suspend_xmldecl(XML_Parser parser, const XML_Char *context,
3143                                 const XML_Char *base, const XML_Char *systemId,
3144                                 const XML_Char *publicId) {
3145   const char *text = "<?xml version='1.0' encoding='us-ascii'?>";
3146   XML_Parser ext_parser;
3147   XML_ParsingStatus status;
3148   enum XML_Status rc;
3149 
3150   UNUSED_P(base);
3151   UNUSED_P(systemId);
3152   UNUSED_P(publicId);
3153   ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
3154   if (ext_parser == NULL)
3155     fail("Could not create external entity parser");
3156   XML_SetXmlDeclHandler(ext_parser, entity_suspending_xdecl_handler);
3157   XML_SetUserData(ext_parser, ext_parser);
3158   rc = _XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE);
3159   XML_GetParsingStatus(ext_parser, &status);
3160   if (resumable) {
3161     if (rc == XML_STATUS_ERROR)
3162       xml_failure(ext_parser);
3163     if (status.parsing != XML_SUSPENDED)
3164       fail("Ext Parsing status not SUSPENDED");
3165   } else {
3166     if (rc != XML_STATUS_ERROR)
3167       fail("Ext parsing not aborted");
3168     if (XML_GetErrorCode(ext_parser) != XML_ERROR_ABORTED)
3169       xml_failure(ext_parser);
3170     if (status.parsing != XML_FINISHED)
3171       fail("Ext Parsing status not FINISHED");
3172   }
3173 
3174   XML_ParserFree(ext_parser);
3175   return XML_STATUS_OK;
3176 }
3177 
3178 START_TEST(test_subordinate_xdecl_suspend) {
3179   const char *text
3180       = "<!DOCTYPE doc [\n"
3181         "  <!ENTITY entity SYSTEM 'http://example.org/dummy.ent'>\n"
3182         "]>\n"
3183         "<doc>&entity;</doc>";
3184 
3185   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
3186   XML_SetExternalEntityRefHandler(g_parser, external_entity_suspend_xmldecl);
3187   resumable = XML_TRUE;
3188   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
3189       == XML_STATUS_ERROR)
3190     xml_failure(g_parser);
3191 }
3192 END_TEST
3193 
3194 START_TEST(test_subordinate_xdecl_abort) {
3195   const char *text
3196       = "<!DOCTYPE doc [\n"
3197         "  <!ENTITY entity SYSTEM 'http://example.org/dummy.ent'>\n"
3198         "]>\n"
3199         "<doc>&entity;</doc>";
3200 
3201   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
3202   XML_SetExternalEntityRefHandler(g_parser, external_entity_suspend_xmldecl);
3203   resumable = XML_FALSE;
3204   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
3205       == XML_STATUS_ERROR)
3206     xml_failure(g_parser);
3207 }
3208 END_TEST
3209 
3210 /* Test external entity fault handling with suspension */
3211 static int XMLCALL
3212 external_entity_suspending_faulter(XML_Parser parser, const XML_Char *context,
3213                                    const XML_Char *base,
3214                                    const XML_Char *systemId,
3215                                    const XML_Char *publicId) {
3216   XML_Parser ext_parser;
3217   ExtFaults *fault = (ExtFaults *)XML_GetUserData(parser);
3218   void *buffer;
3219   int parse_len = (int)strlen(fault->parse_text);
3220 
3221   UNUSED_P(base);
3222   UNUSED_P(systemId);
3223   UNUSED_P(publicId);
3224   ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
3225   if (ext_parser == NULL)
3226     fail("Could not create external entity parser");
3227   XML_SetXmlDeclHandler(ext_parser, entity_suspending_xdecl_handler);
3228   XML_SetUserData(ext_parser, ext_parser);
3229   resumable = XML_TRUE;
3230   buffer = XML_GetBuffer(ext_parser, parse_len);
3231   if (buffer == NULL)
3232     fail("Could not allocate parse buffer");
3233   assert(buffer != NULL);
3234   memcpy(buffer, fault->parse_text, parse_len);
3235   if (XML_ParseBuffer(ext_parser, parse_len, XML_FALSE) != XML_STATUS_SUSPENDED)
3236     fail("XML declaration did not suspend");
3237   if (XML_ResumeParser(ext_parser) != XML_STATUS_OK)
3238     xml_failure(ext_parser);
3239   if (XML_ParseBuffer(ext_parser, 0, XML_TRUE) != XML_STATUS_ERROR)
3240     fail(fault->fail_text);
3241   if (XML_GetErrorCode(ext_parser) != fault->error)
3242     xml_failure(ext_parser);
3243 
3244   XML_ParserFree(ext_parser);
3245   return XML_STATUS_ERROR;
3246 }
3247 
3248 START_TEST(test_ext_entity_invalid_suspended_parse) {
3249   const char *text = "<!DOCTYPE doc [\n"
3250                      "  <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n"
3251                      "]>\n"
3252                      "<doc>&en;</doc>";
3253   ExtFaults faults[]
3254       = {{"<?xml version='1.0' encoding='us-ascii'?><",
3255           "Incomplete element declaration not faulted", NULL,
3256           XML_ERROR_UNCLOSED_TOKEN},
3257          {/* First two bytes of a three-byte char */
3258           "<?xml version='1.0' encoding='utf-8'?>\xe2\x82",
3259           "Incomplete character not faulted", NULL, XML_ERROR_PARTIAL_CHAR},
3260          {NULL, NULL, NULL, XML_ERROR_NONE}};
3261   ExtFaults *fault;
3262 
3263   for (fault = &faults[0]; fault->parse_text != NULL; fault++) {
3264     XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
3265     XML_SetExternalEntityRefHandler(g_parser,
3266                                     external_entity_suspending_faulter);
3267     XML_SetUserData(g_parser, fault);
3268     expect_failure(text, XML_ERROR_EXTERNAL_ENTITY_HANDLING,
3269                    "Parser did not report external entity error");
3270     XML_ParserReset(g_parser, NULL);
3271   }
3272 }
3273 END_TEST
3274 
3275 /* Test setting an explicit encoding */
3276 START_TEST(test_explicit_encoding) {
3277   const char *text1 = "<doc>Hello ";
3278   const char *text2 = " World</doc>";
3279 
3280   /* Just check that we can set the encoding to NULL before starting */
3281   if (XML_SetEncoding(g_parser, NULL) != XML_STATUS_OK)
3282     fail("Failed to initialise encoding to NULL");
3283   /* Say we are UTF-8 */
3284   if (XML_SetEncoding(g_parser, XCS("utf-8")) != XML_STATUS_OK)
3285     fail("Failed to set explicit encoding");
3286   if (_XML_Parse_SINGLE_BYTES(g_parser, text1, (int)strlen(text1), XML_FALSE)
3287       == XML_STATUS_ERROR)
3288     xml_failure(g_parser);
3289   /* Try to switch encodings mid-parse */
3290   if (XML_SetEncoding(g_parser, XCS("us-ascii")) != XML_STATUS_ERROR)
3291     fail("Allowed encoding change");
3292   if (_XML_Parse_SINGLE_BYTES(g_parser, text2, (int)strlen(text2), XML_TRUE)
3293       == XML_STATUS_ERROR)
3294     xml_failure(g_parser);
3295   /* Try now the parse is over */
3296   if (XML_SetEncoding(g_parser, NULL) != XML_STATUS_OK)
3297     fail("Failed to unset encoding");
3298 }
3299 END_TEST
3300 
3301 /* Test handling of trailing CR (rather than newline) */
3302 static void XMLCALL
3303 cr_cdata_handler(void *userData, const XML_Char *s, int len) {
3304   int *pfound = (int *)userData;
3305 
3306   /* Internal processing turns the CR into a newline for the
3307    * character data handler, but not for the default handler
3308    */
3309   if (len == 1 && (*s == XCS('\n') || *s == XCS('\r')))
3310     *pfound = 1;
3311 }
3312 
3313 START_TEST(test_trailing_cr) {
3314   const char *text = "<doc>\r";
3315   int found_cr;
3316 
3317   /* Try with a character handler, for code coverage */
3318   XML_SetCharacterDataHandler(g_parser, cr_cdata_handler);
3319   XML_SetUserData(g_parser, &found_cr);
3320   found_cr = 0;
3321   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
3322       == XML_STATUS_OK)
3323     fail("Failed to fault unclosed doc");
3324   if (found_cr == 0)
3325     fail("Did not catch the carriage return");
3326   XML_ParserReset(g_parser, NULL);
3327 
3328   /* Now with a default handler instead */
3329   XML_SetDefaultHandler(g_parser, cr_cdata_handler);
3330   XML_SetUserData(g_parser, &found_cr);
3331   found_cr = 0;
3332   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
3333       == XML_STATUS_OK)
3334     fail("Failed to fault unclosed doc");
3335   if (found_cr == 0)
3336     fail("Did not catch default carriage return");
3337 }
3338 END_TEST
3339 
3340 /* Test trailing CR in an external entity parse */
3341 static int XMLCALL
3342 external_entity_cr_catcher(XML_Parser parser, const XML_Char *context,
3343                            const XML_Char *base, const XML_Char *systemId,
3344                            const XML_Char *publicId) {
3345   const char *text = "\r";
3346   XML_Parser ext_parser;
3347 
3348   UNUSED_P(base);
3349   UNUSED_P(systemId);
3350   UNUSED_P(publicId);
3351   ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
3352   if (ext_parser == NULL)
3353     fail("Could not create external entity parser");
3354   XML_SetCharacterDataHandler(ext_parser, cr_cdata_handler);
3355   if (_XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE)
3356       == XML_STATUS_ERROR)
3357     xml_failure(ext_parser);
3358   XML_ParserFree(ext_parser);
3359   return XML_STATUS_OK;
3360 }
3361 
3362 static int XMLCALL
3363 external_entity_bad_cr_catcher(XML_Parser parser, const XML_Char *context,
3364                                const XML_Char *base, const XML_Char *systemId,
3365                                const XML_Char *publicId) {
3366   const char *text = "<tag>\r";
3367   XML_Parser ext_parser;
3368 
3369   UNUSED_P(base);
3370   UNUSED_P(systemId);
3371   UNUSED_P(publicId);
3372   ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
3373   if (ext_parser == NULL)
3374     fail("Could not create external entity parser");
3375   XML_SetCharacterDataHandler(ext_parser, cr_cdata_handler);
3376   if (_XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE)
3377       == XML_STATUS_OK)
3378     fail("Async entity error not caught");
3379   if (XML_GetErrorCode(ext_parser) != XML_ERROR_ASYNC_ENTITY)
3380     xml_failure(ext_parser);
3381   XML_ParserFree(ext_parser);
3382   return XML_STATUS_OK;
3383 }
3384 
3385 START_TEST(test_ext_entity_trailing_cr) {
3386   const char *text = "<!DOCTYPE doc [\n"
3387                      "  <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n"
3388                      "]>\n"
3389                      "<doc>&en;</doc>";
3390   int found_cr;
3391 
3392   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
3393   XML_SetExternalEntityRefHandler(g_parser, external_entity_cr_catcher);
3394   XML_SetUserData(g_parser, &found_cr);
3395   found_cr = 0;
3396   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
3397       != XML_STATUS_OK)
3398     xml_failure(g_parser);
3399   if (found_cr == 0)
3400     fail("No carriage return found");
3401   XML_ParserReset(g_parser, NULL);
3402 
3403   /* Try again with a different trailing CR */
3404   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
3405   XML_SetExternalEntityRefHandler(g_parser, external_entity_bad_cr_catcher);
3406   XML_SetUserData(g_parser, &found_cr);
3407   found_cr = 0;
3408   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
3409       != XML_STATUS_OK)
3410     xml_failure(g_parser);
3411   if (found_cr == 0)
3412     fail("No carriage return found");
3413 }
3414 END_TEST
3415 
3416 /* Test handling of trailing square bracket */
3417 static void XMLCALL
3418 rsqb_handler(void *userData, const XML_Char *s, int len) {
3419   int *pfound = (int *)userData;
3420 
3421   if (len == 1 && *s == XCS(']'))
3422     *pfound = 1;
3423 }
3424 
3425 START_TEST(test_trailing_rsqb) {
3426   const char *text8 = "<doc>]";
3427   const char text16[] = "\xFF\xFE<\000d\000o\000c\000>\000]\000";
3428   int found_rsqb;
3429   int text8_len = (int)strlen(text8);
3430 
3431   XML_SetCharacterDataHandler(g_parser, rsqb_handler);
3432   XML_SetUserData(g_parser, &found_rsqb);
3433   found_rsqb = 0;
3434   if (_XML_Parse_SINGLE_BYTES(g_parser, text8, text8_len, XML_TRUE)
3435       == XML_STATUS_OK)
3436     fail("Failed to fault unclosed doc");
3437   if (found_rsqb == 0)
3438     fail("Did not catch the right square bracket");
3439 
3440   /* Try again with a different encoding */
3441   XML_ParserReset(g_parser, NULL);
3442   XML_SetCharacterDataHandler(g_parser, rsqb_handler);
3443   XML_SetUserData(g_parser, &found_rsqb);
3444   found_rsqb = 0;
3445   if (_XML_Parse_SINGLE_BYTES(g_parser, text16, (int)sizeof(text16) - 1,
3446                               XML_TRUE)
3447       == XML_STATUS_OK)
3448     fail("Failed to fault unclosed doc");
3449   if (found_rsqb == 0)
3450     fail("Did not catch the right square bracket");
3451 
3452   /* And finally with a default handler */
3453   XML_ParserReset(g_parser, NULL);
3454   XML_SetDefaultHandler(g_parser, rsqb_handler);
3455   XML_SetUserData(g_parser, &found_rsqb);
3456   found_rsqb = 0;
3457   if (_XML_Parse_SINGLE_BYTES(g_parser, text16, (int)sizeof(text16) - 1,
3458                               XML_TRUE)
3459       == XML_STATUS_OK)
3460     fail("Failed to fault unclosed doc");
3461   if (found_rsqb == 0)
3462     fail("Did not catch the right square bracket");
3463 }
3464 END_TEST
3465 
3466 /* Test trailing right square bracket in an external entity parse */
3467 static int XMLCALL
3468 external_entity_rsqb_catcher(XML_Parser parser, const XML_Char *context,
3469                              const XML_Char *base, const XML_Char *systemId,
3470                              const XML_Char *publicId) {
3471   const char *text = "<tag>]";
3472   XML_Parser ext_parser;
3473 
3474   UNUSED_P(base);
3475   UNUSED_P(systemId);
3476   UNUSED_P(publicId);
3477   ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
3478   if (ext_parser == NULL)
3479     fail("Could not create external entity parser");
3480   XML_SetCharacterDataHandler(ext_parser, rsqb_handler);
3481   if (_XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE)
3482       != XML_STATUS_ERROR)
3483     fail("Async entity error not caught");
3484   if (XML_GetErrorCode(ext_parser) != XML_ERROR_ASYNC_ENTITY)
3485     xml_failure(ext_parser);
3486   XML_ParserFree(ext_parser);
3487   return XML_STATUS_OK;
3488 }
3489 
3490 START_TEST(test_ext_entity_trailing_rsqb) {
3491   const char *text = "<!DOCTYPE doc [\n"
3492                      "  <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n"
3493                      "]>\n"
3494                      "<doc>&en;</doc>";
3495   int found_rsqb;
3496 
3497   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
3498   XML_SetExternalEntityRefHandler(g_parser, external_entity_rsqb_catcher);
3499   XML_SetUserData(g_parser, &found_rsqb);
3500   found_rsqb = 0;
3501   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
3502       != XML_STATUS_OK)
3503     xml_failure(g_parser);
3504   if (found_rsqb == 0)
3505     fail("No right square bracket found");
3506 }
3507 END_TEST
3508 
3509 /* Test CDATA handling in an external entity */
3510 static int XMLCALL
3511 external_entity_good_cdata_ascii(XML_Parser parser, const XML_Char *context,
3512                                  const XML_Char *base, const XML_Char *systemId,
3513                                  const XML_Char *publicId) {
3514   const char *text = "<a><![CDATA[<greeting>Hello, world!</greeting>]]></a>";
3515   const XML_Char *expected = XCS("<greeting>Hello, world!</greeting>");
3516   CharData storage;
3517   XML_Parser ext_parser;
3518 
3519   UNUSED_P(base);
3520   UNUSED_P(systemId);
3521   UNUSED_P(publicId);
3522   CharData_Init(&storage);
3523   ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
3524   if (ext_parser == NULL)
3525     fail("Could not create external entity parser");
3526   XML_SetUserData(ext_parser, &storage);
3527   XML_SetCharacterDataHandler(ext_parser, accumulate_characters);
3528 
3529   if (_XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE)
3530       == XML_STATUS_ERROR)
3531     xml_failure(ext_parser);
3532   CharData_CheckXMLChars(&storage, expected);
3533 
3534   XML_ParserFree(ext_parser);
3535   return XML_STATUS_OK;
3536 }
3537 
3538 START_TEST(test_ext_entity_good_cdata) {
3539   const char *text = "<!DOCTYPE doc [\n"
3540                      "  <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n"
3541                      "]>\n"
3542                      "<doc>&en;</doc>";
3543 
3544   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
3545   XML_SetExternalEntityRefHandler(g_parser, external_entity_good_cdata_ascii);
3546   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
3547       != XML_STATUS_OK)
3548     xml_failure(g_parser);
3549 }
3550 END_TEST
3551 
3552 /* Test user parameter settings */
3553 /* Variable holding the expected handler userData */
3554 static void *handler_data = NULL;
3555 /* Count of the number of times the comment handler has been invoked */
3556 static int comment_count = 0;
3557 /* Count of the number of skipped entities */
3558 static int skip_count = 0;
3559 /* Count of the number of times the XML declaration handler is invoked */
3560 static int xdecl_count = 0;
3561 
3562 static void XMLCALL
3563 xml_decl_handler(void *userData, const XML_Char *version,
3564                  const XML_Char *encoding, int standalone) {
3565   UNUSED_P(version);
3566   UNUSED_P(encoding);
3567   if (userData != handler_data)
3568     fail("User data (xml decl) not correctly set");
3569   if (standalone != -1)
3570     fail("Standalone not flagged as not present in XML decl");
3571   xdecl_count++;
3572 }
3573 
3574 static void XMLCALL
3575 param_check_skip_handler(void *userData, const XML_Char *entityName,
3576                          int is_parameter_entity) {
3577   UNUSED_P(entityName);
3578   UNUSED_P(is_parameter_entity);
3579   if (userData != handler_data)
3580     fail("User data (skip) not correctly set");
3581   skip_count++;
3582 }
3583 
3584 static void XMLCALL
3585 data_check_comment_handler(void *userData, const XML_Char *data) {
3586   UNUSED_P(data);
3587   /* Check that the userData passed through is what we expect */
3588   if (userData != handler_data)
3589     fail("User data (parser) not correctly set");
3590   /* Check that the user data in the parser is appropriate */
3591   if (XML_GetUserData(userData) != (void *)1)
3592     fail("User data in parser not correctly set");
3593   comment_count++;
3594 }
3595 
3596 static int XMLCALL
3597 external_entity_param_checker(XML_Parser parser, const XML_Char *context,
3598                               const XML_Char *base, const XML_Char *systemId,
3599                               const XML_Char *publicId) {
3600   const char *text = "<!-- Subordinate parser -->\n"
3601                      "<!ELEMENT doc (#PCDATA)*>";
3602   XML_Parser ext_parser;
3603 
3604   UNUSED_P(base);
3605   UNUSED_P(systemId);
3606   UNUSED_P(publicId);
3607   ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
3608   if (ext_parser == NULL)
3609     fail("Could not create external entity parser");
3610   handler_data = ext_parser;
3611   if (_XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE)
3612       == XML_STATUS_ERROR) {
3613     xml_failure(parser);
3614     return XML_STATUS_ERROR;
3615   }
3616   handler_data = parser;
3617   XML_ParserFree(ext_parser);
3618   return XML_STATUS_OK;
3619 }
3620 
3621 START_TEST(test_user_parameters) {
3622   const char *text = "<?xml version='1.0' encoding='us-ascii'?>\n"
3623                      "<!-- Primary parse -->\n"
3624                      "<!DOCTYPE doc SYSTEM 'foo'>\n"
3625                      "<doc>&entity;";
3626   const char *epilog = "<!-- Back to primary parser -->\n"
3627                        "</doc>";
3628 
3629   comment_count = 0;
3630   skip_count = 0;
3631   xdecl_count = 0;
3632   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
3633   XML_SetXmlDeclHandler(g_parser, xml_decl_handler);
3634   XML_SetExternalEntityRefHandler(g_parser, external_entity_param_checker);
3635   XML_SetCommentHandler(g_parser, data_check_comment_handler);
3636   XML_SetSkippedEntityHandler(g_parser, param_check_skip_handler);
3637   XML_UseParserAsHandlerArg(g_parser);
3638   XML_SetUserData(g_parser, (void *)1);
3639   handler_data = g_parser;
3640   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_FALSE)
3641       == XML_STATUS_ERROR)
3642     xml_failure(g_parser);
3643   if (comment_count != 2)
3644     fail("Comment handler not invoked enough times");
3645   /* Ensure we can't change policy mid-parse */
3646   if (XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_NEVER))
3647     fail("Changed param entity parsing policy while parsing");
3648   if (_XML_Parse_SINGLE_BYTES(g_parser, epilog, (int)strlen(epilog), XML_TRUE)
3649       == XML_STATUS_ERROR)
3650     xml_failure(g_parser);
3651   if (comment_count != 3)
3652     fail("Comment handler not invoked enough times");
3653   if (skip_count != 1)
3654     fail("Skip handler not invoked enough times");
3655   if (xdecl_count != 1)
3656     fail("XML declaration handler not invoked");
3657 }
3658 END_TEST
3659 
3660 /* Test that an explicit external entity handler argument replaces
3661  * the parser as the first argument.
3662  *
3663  * We do not call the first parameter to the external entity handler
3664  * 'parser' for once, since the first time the handler is called it
3665  * will actually be a text string.  We need to be able to access the
3666  * global 'parser' variable to create our external entity parser from,
3667  * since there are code paths we need to ensure get executed.
3668  */
3669 static int XMLCALL
3670 external_entity_ref_param_checker(XML_Parser parameter, const XML_Char *context,
3671                                   const XML_Char *base,
3672                                   const XML_Char *systemId,
3673                                   const XML_Char *publicId) {
3674   const char *text = "<!ELEMENT doc (#PCDATA)*>";
3675   XML_Parser ext_parser;
3676 
3677   UNUSED_P(base);
3678   UNUSED_P(systemId);
3679   UNUSED_P(publicId);
3680   if ((void *)parameter != handler_data)
3681     fail("External entity ref handler parameter not correct");
3682 
3683   /* Here we use the global 'parser' variable */
3684   ext_parser = XML_ExternalEntityParserCreate(g_parser, context, NULL);
3685   if (ext_parser == NULL)
3686     fail("Could not create external entity parser");
3687   if (_XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE)
3688       == XML_STATUS_ERROR)
3689     xml_failure(ext_parser);
3690 
3691   XML_ParserFree(ext_parser);
3692   return XML_STATUS_OK;
3693 }
3694 
3695 START_TEST(test_ext_entity_ref_parameter) {
3696   const char *text = "<?xml version='1.0' encoding='us-ascii'?>\n"
3697                      "<!DOCTYPE doc SYSTEM 'foo'>\n"
3698                      "<doc>&entity;</doc>";
3699 
3700   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
3701   XML_SetExternalEntityRefHandler(g_parser, external_entity_ref_param_checker);
3702   /* Set a handler arg that is not NULL and not parser (which is
3703    * what NULL would cause to be passed.
3704    */
3705   XML_SetExternalEntityRefHandlerArg(g_parser, (void *)text);
3706   handler_data = (void *)text;
3707   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
3708       == XML_STATUS_ERROR)
3709     xml_failure(g_parser);
3710 
3711   /* Now try again with unset args */
3712   XML_ParserReset(g_parser, NULL);
3713   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
3714   XML_SetExternalEntityRefHandler(g_parser, external_entity_ref_param_checker);
3715   XML_SetExternalEntityRefHandlerArg(g_parser, NULL);
3716   handler_data = (void *)g_parser;
3717   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
3718       == XML_STATUS_ERROR)
3719     xml_failure(g_parser);
3720 }
3721 END_TEST
3722 
3723 /* Test the parsing of an empty string */
3724 START_TEST(test_empty_parse) {
3725   const char *text = "<doc></doc>";
3726   const char *partial = "<doc>";
3727 
3728   if (XML_Parse(g_parser, NULL, 0, XML_FALSE) == XML_STATUS_ERROR)
3729     fail("Parsing empty string faulted");
3730   if (XML_Parse(g_parser, NULL, 0, XML_TRUE) != XML_STATUS_ERROR)
3731     fail("Parsing final empty string not faulted");
3732   if (XML_GetErrorCode(g_parser) != XML_ERROR_NO_ELEMENTS)
3733     fail("Parsing final empty string faulted for wrong reason");
3734 
3735   /* Now try with valid text before the empty end */
3736   XML_ParserReset(g_parser, NULL);
3737   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_FALSE)
3738       == XML_STATUS_ERROR)
3739     xml_failure(g_parser);
3740   if (XML_Parse(g_parser, NULL, 0, XML_TRUE) == XML_STATUS_ERROR)
3741     fail("Parsing final empty string faulted");
3742 
3743   /* Now try with invalid text before the empty end */
3744   XML_ParserReset(g_parser, NULL);
3745   if (_XML_Parse_SINGLE_BYTES(g_parser, partial, (int)strlen(partial),
3746                               XML_FALSE)
3747       == XML_STATUS_ERROR)
3748     xml_failure(g_parser);
3749   if (XML_Parse(g_parser, NULL, 0, XML_TRUE) != XML_STATUS_ERROR)
3750     fail("Parsing final incomplete empty string not faulted");
3751 }
3752 END_TEST
3753 
3754 /* Test odd corners of the XML_GetBuffer interface */
3755 static enum XML_Status
3756 get_feature(enum XML_FeatureEnum feature_id, long *presult) {
3757   const XML_Feature *feature = XML_GetFeatureList();
3758 
3759   if (feature == NULL)
3760     return XML_STATUS_ERROR;
3761   for (; feature->feature != XML_FEATURE_END; feature++) {
3762     if (feature->feature == feature_id) {
3763       *presult = feature->value;
3764       return XML_STATUS_OK;
3765     }
3766   }
3767   return XML_STATUS_ERROR;
3768 }
3769 
3770 /* Having an element name longer than 1024 characters exercises some
3771  * of the pool allocation code in the parser that otherwise does not
3772  * get executed.  The count at the end of the line is the number of
3773  * characters (bytes) in the element name by that point.x
3774  */
3775 static const char *get_buffer_test_text
3776     = "<documentwitharidiculouslylongelementnametotease"  /* 0x030 */
3777       "aparticularcorneroftheallocationinXML_GetBuffers"  /* 0x060 */
3778       "othatwecanimprovethecoverageyetagain012345678901"  /* 0x090 */
3779       "123456789abcdef0123456789abcdef0123456789abcdef0"  /* 0x0c0 */
3780       "123456789abcdef0123456789abcdef0123456789abcdef0"  /* 0x0f0 */
3781       "123456789abcdef0123456789abcdef0123456789abcdef0"  /* 0x120 */
3782       "123456789abcdef0123456789abcdef0123456789abcdef0"  /* 0x150 */
3783       "123456789abcdef0123456789abcdef0123456789abcdef0"  /* 0x180 */
3784       "123456789abcdef0123456789abcdef0123456789abcdef0"  /* 0x1b0 */
3785       "123456789abcdef0123456789abcdef0123456789abcdef0"  /* 0x1e0 */
3786       "123456789abcdef0123456789abcdef0123456789abcdef0"  /* 0x210 */
3787       "123456789abcdef0123456789abcdef0123456789abcdef0"  /* 0x240 */
3788       "123456789abcdef0123456789abcdef0123456789abcdef0"  /* 0x270 */
3789       "123456789abcdef0123456789abcdef0123456789abcdef0"  /* 0x2a0 */
3790       "123456789abcdef0123456789abcdef0123456789abcdef0"  /* 0x2d0 */
3791       "123456789abcdef0123456789abcdef0123456789abcdef0"  /* 0x300 */
3792       "123456789abcdef0123456789abcdef0123456789abcdef0"  /* 0x330 */
3793       "123456789abcdef0123456789abcdef0123456789abcdef0"  /* 0x360 */
3794       "123456789abcdef0123456789abcdef0123456789abcdef0"  /* 0x390 */
3795       "123456789abcdef0123456789abcdef0123456789abcdef0"  /* 0x3c0 */
3796       "123456789abcdef0123456789abcdef0123456789abcdef0"  /* 0x3f0 */
3797       "123456789abcdef0123456789abcdef0123456789>\n<ef0"; /* 0x420 */
3798 
3799 /* Test odd corners of the XML_GetBuffer interface */
3800 START_TEST(test_get_buffer_1) {
3801   const char *text = get_buffer_test_text;
3802   void *buffer;
3803   long context_bytes;
3804 
3805   /* Attempt to allocate a negative length buffer */
3806   if (XML_GetBuffer(g_parser, -12) != NULL)
3807     fail("Negative length buffer not failed");
3808 
3809   /* Now get a small buffer and extend it past valid length */
3810   buffer = XML_GetBuffer(g_parser, 1536);
3811   if (buffer == NULL)
3812     fail("1.5K buffer failed");
3813   assert(buffer != NULL);
3814   memcpy(buffer, text, strlen(text));
3815   if (XML_ParseBuffer(g_parser, (int)strlen(text), XML_FALSE)
3816       == XML_STATUS_ERROR)
3817     xml_failure(g_parser);
3818   if (XML_GetBuffer(g_parser, INT_MAX) != NULL)
3819     fail("INT_MAX buffer not failed");
3820 
3821   /* Now try extending it a more reasonable but still too large
3822    * amount.  The allocator in XML_GetBuffer() doubles the buffer
3823    * size until it exceeds the requested amount or INT_MAX.  If it
3824    * exceeds INT_MAX, it rejects the request, so we want a request
3825    * between INT_MAX and INT_MAX/2.  A gap of 1K seems comfortable,
3826    * with an extra byte just to ensure that the request is off any
3827    * boundary.  The request will be inflated internally by
3828    * XML_CONTEXT_BYTES (if defined), so we subtract that from our
3829    * request.
3830    */
3831   if (get_feature(XML_FEATURE_CONTEXT_BYTES, &context_bytes) != XML_STATUS_OK)
3832     context_bytes = 0;
3833   if (XML_GetBuffer(g_parser, INT_MAX - (context_bytes + 1025)) != NULL)
3834     fail("INT_MAX- buffer not failed");
3835 
3836   /* Now try extending it a carefully crafted amount */
3837   if (XML_GetBuffer(g_parser, 1000) == NULL)
3838     fail("1000 buffer failed");
3839 }
3840 END_TEST
3841 
3842 /* Test more corners of the XML_GetBuffer interface */
3843 START_TEST(test_get_buffer_2) {
3844   const char *text = get_buffer_test_text;
3845   void *buffer;
3846 
3847   /* Now get a decent buffer */
3848   buffer = XML_GetBuffer(g_parser, 1536);
3849   if (buffer == NULL)
3850     fail("1.5K buffer failed");
3851   assert(buffer != NULL);
3852   memcpy(buffer, text, strlen(text));
3853   if (XML_ParseBuffer(g_parser, (int)strlen(text), XML_FALSE)
3854       == XML_STATUS_ERROR)
3855     xml_failure(g_parser);
3856 
3857   /* Extend it, to catch a different code path */
3858   if (XML_GetBuffer(g_parser, 1024) == NULL)
3859     fail("1024 buffer failed");
3860 }
3861 END_TEST
3862 
3863 /* Test position information macros */
3864 START_TEST(test_byte_info_at_end) {
3865   const char *text = "<doc></doc>";
3866 
3867   if (XML_GetCurrentByteIndex(g_parser) != -1
3868       || XML_GetCurrentByteCount(g_parser) != 0)
3869     fail("Byte index/count incorrect at start of parse");
3870   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
3871       == XML_STATUS_ERROR)
3872     xml_failure(g_parser);
3873   /* At end, the count will be zero and the index the end of string */
3874   if (XML_GetCurrentByteCount(g_parser) != 0)
3875     fail("Terminal byte count incorrect");
3876   if (XML_GetCurrentByteIndex(g_parser) != (XML_Index)strlen(text))
3877     fail("Terminal byte index incorrect");
3878 }
3879 END_TEST
3880 
3881 /* Test position information from errors */
3882 #define PRE_ERROR_STR "<doc></"
3883 #define POST_ERROR_STR "wombat></doc>"
3884 START_TEST(test_byte_info_at_error) {
3885   const char *text = PRE_ERROR_STR POST_ERROR_STR;
3886 
3887   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
3888       == XML_STATUS_OK)
3889     fail("Syntax error not faulted");
3890   if (XML_GetCurrentByteCount(g_parser) != 0)
3891     fail("Error byte count incorrect");
3892   if (XML_GetCurrentByteIndex(g_parser) != strlen(PRE_ERROR_STR))
3893     fail("Error byte index incorrect");
3894 }
3895 END_TEST
3896 #undef PRE_ERROR_STR
3897 #undef POST_ERROR_STR
3898 
3899 /* Test position information in handler */
3900 typedef struct ByteTestData {
3901   int start_element_len;
3902   int cdata_len;
3903   int total_string_len;
3904 } ByteTestData;
3905 
3906 static void
3907 byte_character_handler(void *userData, const XML_Char *s, int len) {
3908 #ifdef XML_CONTEXT_BYTES
3909   int offset, size;
3910   const char *buffer;
3911   ByteTestData *data = (ByteTestData *)userData;
3912 
3913   UNUSED_P(s);
3914   buffer = XML_GetInputContext(g_parser, &offset, &size);
3915   if (buffer == NULL)
3916     fail("Failed to get context buffer");
3917   if (offset != data->start_element_len)
3918     fail("Context offset in unexpected position");
3919   if (len != data->cdata_len)
3920     fail("CDATA length reported incorrectly");
3921   if (size != data->total_string_len)
3922     fail("Context size is not full buffer");
3923   if (XML_GetCurrentByteIndex(g_parser) != offset)
3924     fail("Character byte index incorrect");
3925   if (XML_GetCurrentByteCount(g_parser) != len)
3926     fail("Character byte count incorrect");
3927 #else
3928   UNUSED_P(s);
3929   UNUSED_P(userData);
3930   UNUSED_P(len);
3931 #endif
3932 }
3933 
3934 #define START_ELEMENT "<e>"
3935 #define CDATA_TEXT "Hello"
3936 #define END_ELEMENT "</e>"
3937 START_TEST(test_byte_info_at_cdata) {
3938   const char *text = START_ELEMENT CDATA_TEXT END_ELEMENT;
3939   int offset, size;
3940   ByteTestData data;
3941 
3942   /* Check initial context is empty */
3943   if (XML_GetInputContext(g_parser, &offset, &size) != NULL)
3944     fail("Unexpected context at start of parse");
3945 
3946   data.start_element_len = (int)strlen(START_ELEMENT);
3947   data.cdata_len = (int)strlen(CDATA_TEXT);
3948   data.total_string_len = (int)strlen(text);
3949   XML_SetCharacterDataHandler(g_parser, byte_character_handler);
3950   XML_SetUserData(g_parser, &data);
3951   if (XML_Parse(g_parser, text, (int)strlen(text), XML_TRUE) != XML_STATUS_OK)
3952     xml_failure(g_parser);
3953 }
3954 END_TEST
3955 #undef START_ELEMENT
3956 #undef CDATA_TEXT
3957 #undef END_ELEMENT
3958 
3959 /* Test predefined entities are correctly recognised */
3960 START_TEST(test_predefined_entities) {
3961   const char *text = "<doc>&lt;&gt;&amp;&quot;&apos;</doc>";
3962   const XML_Char *expected = XCS("<doc>&lt;&gt;&amp;&quot;&apos;</doc>");
3963   const XML_Char *result = XCS("<>&\"'");
3964   CharData storage;
3965 
3966   XML_SetDefaultHandler(g_parser, accumulate_characters);
3967   /* run_character_check uses XML_SetCharacterDataHandler(), which
3968    * unfortunately heads off a code path that we need to exercise.
3969    */
3970   CharData_Init(&storage);
3971   XML_SetUserData(g_parser, &storage);
3972   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
3973       == XML_STATUS_ERROR)
3974     xml_failure(g_parser);
3975   /* The default handler doesn't translate the entities */
3976   CharData_CheckXMLChars(&storage, expected);
3977 
3978   /* Now try again and check the translation */
3979   XML_ParserReset(g_parser, NULL);
3980   run_character_check(text, result);
3981 }
3982 END_TEST
3983 
3984 /* Regression test that an invalid tag in an external parameter
3985  * reference in an external DTD is correctly faulted.
3986  *
3987  * Only a few specific tags are legal in DTDs ignoring comments and
3988  * processing instructions, all of which begin with an exclamation
3989  * mark.  "<el/>" is not one of them, so the parser should raise an
3990  * error on encountering it.
3991  */
3992 static int XMLCALL
3993 external_entity_param(XML_Parser parser, const XML_Char *context,
3994                       const XML_Char *base, const XML_Char *systemId,
3995                       const XML_Char *publicId) {
3996   const char *text1 = "<!ELEMENT doc EMPTY>\n"
3997                       "<!ENTITY % e1 SYSTEM '004-2.ent'>\n"
3998                       "<!ENTITY % e2 '%e1;'>\n"
3999                       "%e1;\n";
4000   const char *text2 = "<!ELEMENT el EMPTY>\n"
4001                       "<el/>\n";
4002   XML_Parser ext_parser;
4003 
4004   UNUSED_P(base);
4005   UNUSED_P(publicId);
4006   if (systemId == NULL)
4007     return XML_STATUS_OK;
4008 
4009   ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
4010   if (ext_parser == NULL)
4011     fail("Could not create external entity parser");
4012 
4013   if (! xcstrcmp(systemId, XCS("004-1.ent"))) {
4014     if (_XML_Parse_SINGLE_BYTES(ext_parser, text1, (int)strlen(text1), XML_TRUE)
4015         != XML_STATUS_ERROR)
4016       fail("Inner DTD with invalid tag not rejected");
4017     if (XML_GetErrorCode(ext_parser) != XML_ERROR_EXTERNAL_ENTITY_HANDLING)
4018       xml_failure(ext_parser);
4019   } else if (! xcstrcmp(systemId, XCS("004-2.ent"))) {
4020     if (_XML_Parse_SINGLE_BYTES(ext_parser, text2, (int)strlen(text2), XML_TRUE)
4021         != XML_STATUS_ERROR)
4022       fail("Invalid tag in external param not rejected");
4023     if (XML_GetErrorCode(ext_parser) != XML_ERROR_SYNTAX)
4024       xml_failure(ext_parser);
4025   } else {
4026     fail("Unknown system ID");
4027   }
4028 
4029   XML_ParserFree(ext_parser);
4030   return XML_STATUS_ERROR;
4031 }
4032 
4033 START_TEST(test_invalid_tag_in_dtd) {
4034   const char *text = "<!DOCTYPE doc SYSTEM '004-1.ent'>\n"
4035                      "<doc></doc>\n";
4036 
4037   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
4038   XML_SetExternalEntityRefHandler(g_parser, external_entity_param);
4039   expect_failure(text, XML_ERROR_EXTERNAL_ENTITY_HANDLING,
4040                  "Invalid tag IN DTD external param not rejected");
4041 }
4042 END_TEST
4043 
4044 /* Test entities not quite the predefined ones are not mis-recognised */
4045 START_TEST(test_not_predefined_entities) {
4046   const char *text[] = {"<doc>&pt;</doc>", "<doc>&amo;</doc>",
4047                         "<doc>&quid;</doc>", "<doc>&apod;</doc>", NULL};
4048   int i = 0;
4049 
4050   while (text[i] != NULL) {
4051     expect_failure(text[i], XML_ERROR_UNDEFINED_ENTITY,
4052                    "Undefined entity not rejected");
4053     XML_ParserReset(g_parser, NULL);
4054     i++;
4055   }
4056 }
4057 END_TEST
4058 
4059 /* Test conditional inclusion (IGNORE) */
4060 static int XMLCALL
4061 external_entity_load_ignore(XML_Parser parser, const XML_Char *context,
4062                             const XML_Char *base, const XML_Char *systemId,
4063                             const XML_Char *publicId) {
4064   const char *text = "<![IGNORE[<!ELEMENT e (#PCDATA)*>]]>";
4065   XML_Parser ext_parser;
4066 
4067   UNUSED_P(base);
4068   UNUSED_P(systemId);
4069   UNUSED_P(publicId);
4070   ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
4071   if (ext_parser == NULL)
4072     fail("Could not create external entity parser");
4073   if (_XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE)
4074       == XML_STATUS_ERROR)
4075     xml_failure(parser);
4076 
4077   XML_ParserFree(ext_parser);
4078   return XML_STATUS_OK;
4079 }
4080 
4081 START_TEST(test_ignore_section) {
4082   const char *text = "<!DOCTYPE doc SYSTEM 'foo'>\n"
4083                      "<doc><e>&entity;</e></doc>";
4084   const XML_Char *expected
4085       = XCS("<![IGNORE[<!ELEMENT e (#PCDATA)*>]]>\n&entity;");
4086   CharData storage;
4087 
4088   CharData_Init(&storage);
4089   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
4090   XML_SetUserData(g_parser, &storage);
4091   XML_SetExternalEntityRefHandler(g_parser, external_entity_load_ignore);
4092   XML_SetDefaultHandler(g_parser, accumulate_characters);
4093   XML_SetStartDoctypeDeclHandler(g_parser, dummy_start_doctype_handler);
4094   XML_SetEndDoctypeDeclHandler(g_parser, dummy_end_doctype_handler);
4095   XML_SetElementDeclHandler(g_parser, dummy_element_decl_handler);
4096   XML_SetStartElementHandler(g_parser, dummy_start_element);
4097   XML_SetEndElementHandler(g_parser, dummy_end_element);
4098   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
4099       == XML_STATUS_ERROR)
4100     xml_failure(g_parser);
4101   CharData_CheckXMLChars(&storage, expected);
4102 }
4103 END_TEST
4104 
4105 static int XMLCALL
4106 external_entity_load_ignore_utf16(XML_Parser parser, const XML_Char *context,
4107                                   const XML_Char *base,
4108                                   const XML_Char *systemId,
4109                                   const XML_Char *publicId) {
4110   const char text[] =
4111       /* <![IGNORE[<!ELEMENT e (#PCDATA)*>]]> */
4112       "<\0!\0[\0I\0G\0N\0O\0R\0E\0[\0"
4113       "<\0!\0E\0L\0E\0M\0E\0N\0T\0 \0e\0 \0"
4114       "(\0#\0P\0C\0D\0A\0T\0A\0)\0*\0>\0]\0]\0>\0";
4115   XML_Parser ext_parser;
4116 
4117   UNUSED_P(base);
4118   UNUSED_P(systemId);
4119   UNUSED_P(publicId);
4120   ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
4121   if (ext_parser == NULL)
4122     fail("Could not create external entity parser");
4123   if (_XML_Parse_SINGLE_BYTES(ext_parser, text, (int)sizeof(text) - 1, XML_TRUE)
4124       == XML_STATUS_ERROR)
4125     xml_failure(parser);
4126 
4127   XML_ParserFree(ext_parser);
4128   return XML_STATUS_OK;
4129 }
4130 
4131 START_TEST(test_ignore_section_utf16) {
4132   const char text[] =
4133       /* <!DOCTYPE d SYSTEM 's'> */
4134       "<\0!\0D\0O\0C\0T\0Y\0P\0E\0 \0d\0 "
4135       "\0S\0Y\0S\0T\0E\0M\0 \0'\0s\0'\0>\0\n\0"
4136       /* <d><e>&en;</e></d> */
4137       "<\0d\0>\0<\0e\0>\0&\0e\0n\0;\0<\0/\0e\0>\0<\0/\0d\0>\0";
4138   const XML_Char *expected = XCS("<![IGNORE[<!ELEMENT e (#PCDATA)*>]]>\n&en;");
4139   CharData storage;
4140 
4141   CharData_Init(&storage);
4142   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
4143   XML_SetUserData(g_parser, &storage);
4144   XML_SetExternalEntityRefHandler(g_parser, external_entity_load_ignore_utf16);
4145   XML_SetDefaultHandler(g_parser, accumulate_characters);
4146   XML_SetStartDoctypeDeclHandler(g_parser, dummy_start_doctype_handler);
4147   XML_SetEndDoctypeDeclHandler(g_parser, dummy_end_doctype_handler);
4148   XML_SetElementDeclHandler(g_parser, dummy_element_decl_handler);
4149   XML_SetStartElementHandler(g_parser, dummy_start_element);
4150   XML_SetEndElementHandler(g_parser, dummy_end_element);
4151   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE)
4152       == XML_STATUS_ERROR)
4153     xml_failure(g_parser);
4154   CharData_CheckXMLChars(&storage, expected);
4155 }
4156 END_TEST
4157 
4158 static int XMLCALL
4159 external_entity_load_ignore_utf16_be(XML_Parser parser, const XML_Char *context,
4160                                      const XML_Char *base,
4161                                      const XML_Char *systemId,
4162                                      const XML_Char *publicId) {
4163   const char text[] =
4164       /* <![IGNORE[<!ELEMENT e (#PCDATA)*>]]> */
4165       "\0<\0!\0[\0I\0G\0N\0O\0R\0E\0["
4166       "\0<\0!\0E\0L\0E\0M\0E\0N\0T\0 \0e\0 "
4167       "\0(\0#\0P\0C\0D\0A\0T\0A\0)\0*\0>\0]\0]\0>";
4168   XML_Parser ext_parser;
4169 
4170   UNUSED_P(base);
4171   UNUSED_P(systemId);
4172   UNUSED_P(publicId);
4173   ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
4174   if (ext_parser == NULL)
4175     fail("Could not create external entity parser");
4176   if (_XML_Parse_SINGLE_BYTES(ext_parser, text, (int)sizeof(text) - 1, XML_TRUE)
4177       == XML_STATUS_ERROR)
4178     xml_failure(parser);
4179 
4180   XML_ParserFree(ext_parser);
4181   return XML_STATUS_OK;
4182 }
4183 
4184 START_TEST(test_ignore_section_utf16_be) {
4185   const char text[] =
4186       /* <!DOCTYPE d SYSTEM 's'> */
4187       "\0<\0!\0D\0O\0C\0T\0Y\0P\0E\0 \0d\0 "
4188       "\0S\0Y\0S\0T\0E\0M\0 \0'\0s\0'\0>\0\n"
4189       /* <d><e>&en;</e></d> */
4190       "\0<\0d\0>\0<\0e\0>\0&\0e\0n\0;\0<\0/\0e\0>\0<\0/\0d\0>";
4191   const XML_Char *expected = XCS("<![IGNORE[<!ELEMENT e (#PCDATA)*>]]>\n&en;");
4192   CharData storage;
4193 
4194   CharData_Init(&storage);
4195   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
4196   XML_SetUserData(g_parser, &storage);
4197   XML_SetExternalEntityRefHandler(g_parser,
4198                                   external_entity_load_ignore_utf16_be);
4199   XML_SetDefaultHandler(g_parser, accumulate_characters);
4200   XML_SetStartDoctypeDeclHandler(g_parser, dummy_start_doctype_handler);
4201   XML_SetEndDoctypeDeclHandler(g_parser, dummy_end_doctype_handler);
4202   XML_SetElementDeclHandler(g_parser, dummy_element_decl_handler);
4203   XML_SetStartElementHandler(g_parser, dummy_start_element);
4204   XML_SetEndElementHandler(g_parser, dummy_end_element);
4205   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE)
4206       == XML_STATUS_ERROR)
4207     xml_failure(g_parser);
4208   CharData_CheckXMLChars(&storage, expected);
4209 }
4210 END_TEST
4211 
4212 /* Test mis-formatted conditional exclusion */
4213 START_TEST(test_bad_ignore_section) {
4214   const char *text = "<!DOCTYPE doc SYSTEM 'foo'>\n"
4215                      "<doc><e>&entity;</e></doc>";
4216   ExtFaults faults[]
4217       = {{"<![IGNORE[<!ELEM", "Broken-off declaration not faulted", NULL,
4218           XML_ERROR_SYNTAX},
4219          {"<![IGNORE[\x01]]>", "Invalid XML character not faulted", NULL,
4220           XML_ERROR_INVALID_TOKEN},
4221          {/* FIrst two bytes of a three-byte char */
4222           "<![IGNORE[\xe2\x82", "Partial XML character not faulted", NULL,
4223           XML_ERROR_PARTIAL_CHAR},
4224          {NULL, NULL, NULL, XML_ERROR_NONE}};
4225   ExtFaults *fault;
4226 
4227   for (fault = &faults[0]; fault->parse_text != NULL; fault++) {
4228     XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
4229     XML_SetExternalEntityRefHandler(g_parser, external_entity_faulter);
4230     XML_SetUserData(g_parser, fault);
4231     expect_failure(text, XML_ERROR_EXTERNAL_ENTITY_HANDLING,
4232                    "Incomplete IGNORE section not failed");
4233     XML_ParserReset(g_parser, NULL);
4234   }
4235 }
4236 END_TEST
4237 
4238 /* Test recursive parsing */
4239 static int XMLCALL
4240 external_entity_valuer(XML_Parser parser, const XML_Char *context,
4241                        const XML_Char *base, const XML_Char *systemId,
4242                        const XML_Char *publicId) {
4243   const char *text1 = "<!ELEMENT doc EMPTY>\n"
4244                       "<!ENTITY % e1 SYSTEM '004-2.ent'>\n"
4245                       "<!ENTITY % e2 '%e1;'>\n"
4246                       "%e1;\n";
4247   XML_Parser ext_parser;
4248 
4249   UNUSED_P(base);
4250   UNUSED_P(publicId);
4251   if (systemId == NULL)
4252     return XML_STATUS_OK;
4253   ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
4254   if (ext_parser == NULL)
4255     fail("Could not create external entity parser");
4256   if (! xcstrcmp(systemId, XCS("004-1.ent"))) {
4257     if (_XML_Parse_SINGLE_BYTES(ext_parser, text1, (int)strlen(text1), XML_TRUE)
4258         == XML_STATUS_ERROR)
4259       xml_failure(ext_parser);
4260   } else if (! xcstrcmp(systemId, XCS("004-2.ent"))) {
4261     ExtFaults *fault = (ExtFaults *)XML_GetUserData(parser);
4262     enum XML_Status status;
4263     enum XML_Error error;
4264 
4265     status = _XML_Parse_SINGLE_BYTES(ext_parser, fault->parse_text,
4266                                      (int)strlen(fault->parse_text), XML_TRUE);
4267     if (fault->error == XML_ERROR_NONE) {
4268       if (status == XML_STATUS_ERROR)
4269         xml_failure(ext_parser);
4270     } else {
4271       if (status != XML_STATUS_ERROR)
4272         fail(fault->fail_text);
4273       error = XML_GetErrorCode(ext_parser);
4274       if (error != fault->error
4275           && (fault->error != XML_ERROR_XML_DECL
4276               || error != XML_ERROR_TEXT_DECL))
4277         xml_failure(ext_parser);
4278     }
4279   }
4280 
4281   XML_ParserFree(ext_parser);
4282   return XML_STATUS_OK;
4283 }
4284 
4285 START_TEST(test_external_entity_values) {
4286   const char *text = "<!DOCTYPE doc SYSTEM '004-1.ent'>\n"
4287                      "<doc></doc>\n";
4288   ExtFaults data_004_2[] = {
4289       {"<!ATTLIST doc a1 CDATA 'value'>", NULL, NULL, XML_ERROR_NONE},
4290       {"<!ATTLIST $doc a1 CDATA 'value'>", "Invalid token not faulted", NULL,
4291        XML_ERROR_INVALID_TOKEN},
4292       {"'wombat", "Unterminated string not faulted", NULL,
4293        XML_ERROR_UNCLOSED_TOKEN},
4294       {"\xe2\x82", "Partial UTF-8 character not faulted", NULL,
4295        XML_ERROR_PARTIAL_CHAR},
4296       {"<?xml version='1.0' encoding='utf-8'?>\n", NULL, NULL, XML_ERROR_NONE},
4297       {"<?xml?>", "Malformed XML declaration not faulted", NULL,
4298        XML_ERROR_XML_DECL},
4299       {/* UTF-8 BOM */
4300        "\xEF\xBB\xBF<!ATTLIST doc a1 CDATA 'value'>", NULL, NULL,
4301        XML_ERROR_NONE},
4302       {"<?xml version='1.0' encoding='utf-8'?>\n$",
4303        "Invalid token after text declaration not faulted", NULL,
4304        XML_ERROR_INVALID_TOKEN},
4305       {"<?xml version='1.0' encoding='utf-8'?>\n'wombat",
4306        "Unterminated string after text decl not faulted", NULL,
4307        XML_ERROR_UNCLOSED_TOKEN},
4308       {"<?xml version='1.0' encoding='utf-8'?>\n\xe2\x82",
4309        "Partial UTF-8 character after text decl not faulted", NULL,
4310        XML_ERROR_PARTIAL_CHAR},
4311       {"%e1;", "Recursive parameter entity not faulted", NULL,
4312        XML_ERROR_RECURSIVE_ENTITY_REF},
4313       {NULL, NULL, NULL, XML_ERROR_NONE}};
4314   int i;
4315 
4316   for (i = 0; data_004_2[i].parse_text != NULL; i++) {
4317     XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
4318     XML_SetExternalEntityRefHandler(g_parser, external_entity_valuer);
4319     XML_SetUserData(g_parser, &data_004_2[i]);
4320     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
4321         == XML_STATUS_ERROR)
4322       xml_failure(g_parser);
4323     XML_ParserReset(g_parser, NULL);
4324   }
4325 }
4326 END_TEST
4327 
4328 /* Test the recursive parse interacts with a not standalone handler */
4329 static int XMLCALL
4330 external_entity_not_standalone(XML_Parser parser, const XML_Char *context,
4331                                const XML_Char *base, const XML_Char *systemId,
4332                                const XML_Char *publicId) {
4333   const char *text1 = "<!ELEMENT doc EMPTY>\n"
4334                       "<!ENTITY % e1 SYSTEM 'bar'>\n"
4335                       "%e1;\n";
4336   const char *text2 = "<!ATTLIST doc a1 CDATA 'value'>";
4337   XML_Parser ext_parser;
4338 
4339   UNUSED_P(base);
4340   UNUSED_P(publicId);
4341   if (systemId == NULL)
4342     return XML_STATUS_OK;
4343   ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
4344   if (ext_parser == NULL)
4345     fail("Could not create external entity parser");
4346   if (! xcstrcmp(systemId, XCS("foo"))) {
4347     XML_SetNotStandaloneHandler(ext_parser, reject_not_standalone_handler);
4348     if (_XML_Parse_SINGLE_BYTES(ext_parser, text1, (int)strlen(text1), XML_TRUE)
4349         != XML_STATUS_ERROR)
4350       fail("Expected not standalone rejection");
4351     if (XML_GetErrorCode(ext_parser) != XML_ERROR_NOT_STANDALONE)
4352       xml_failure(ext_parser);
4353     XML_SetNotStandaloneHandler(ext_parser, NULL);
4354     XML_ParserFree(ext_parser);
4355     return XML_STATUS_ERROR;
4356   } else if (! xcstrcmp(systemId, XCS("bar"))) {
4357     if (_XML_Parse_SINGLE_BYTES(ext_parser, text2, (int)strlen(text2), XML_TRUE)
4358         == XML_STATUS_ERROR)
4359       xml_failure(ext_parser);
4360   }
4361 
4362   XML_ParserFree(ext_parser);
4363   return XML_STATUS_OK;
4364 }
4365 
4366 START_TEST(test_ext_entity_not_standalone) {
4367   const char *text = "<!DOCTYPE doc SYSTEM 'foo'>\n"
4368                      "<doc></doc>";
4369 
4370   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
4371   XML_SetExternalEntityRefHandler(g_parser, external_entity_not_standalone);
4372   expect_failure(text, XML_ERROR_EXTERNAL_ENTITY_HANDLING,
4373                  "Standalone rejection not caught");
4374 }
4375 END_TEST
4376 
4377 static int XMLCALL
4378 external_entity_value_aborter(XML_Parser parser, const XML_Char *context,
4379                               const XML_Char *base, const XML_Char *systemId,
4380                               const XML_Char *publicId) {
4381   const char *text1 = "<!ELEMENT doc EMPTY>\n"
4382                       "<!ENTITY % e1 SYSTEM '004-2.ent'>\n"
4383                       "<!ENTITY % e2 '%e1;'>\n"
4384                       "%e1;\n";
4385   const char *text2 = "<?xml version='1.0' encoding='utf-8'?>";
4386   XML_Parser ext_parser;
4387 
4388   UNUSED_P(base);
4389   UNUSED_P(publicId);
4390   if (systemId == NULL)
4391     return XML_STATUS_OK;
4392   ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
4393   if (ext_parser == NULL)
4394     fail("Could not create external entity parser");
4395   if (! xcstrcmp(systemId, XCS("004-1.ent"))) {
4396     if (_XML_Parse_SINGLE_BYTES(ext_parser, text1, (int)strlen(text1), XML_TRUE)
4397         == XML_STATUS_ERROR)
4398       xml_failure(ext_parser);
4399   }
4400   if (! xcstrcmp(systemId, XCS("004-2.ent"))) {
4401     XML_SetXmlDeclHandler(ext_parser, entity_suspending_xdecl_handler);
4402     XML_SetUserData(ext_parser, ext_parser);
4403     if (_XML_Parse_SINGLE_BYTES(ext_parser, text2, (int)strlen(text2), XML_TRUE)
4404         != XML_STATUS_ERROR)
4405       fail("Aborted parse not faulted");
4406     if (XML_GetErrorCode(ext_parser) != XML_ERROR_ABORTED)
4407       xml_failure(ext_parser);
4408   }
4409 
4410   XML_ParserFree(ext_parser);
4411   return XML_STATUS_OK;
4412 }
4413 
4414 START_TEST(test_ext_entity_value_abort) {
4415   const char *text = "<!DOCTYPE doc SYSTEM '004-1.ent'>\n"
4416                      "<doc></doc>\n";
4417 
4418   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
4419   XML_SetExternalEntityRefHandler(g_parser, external_entity_value_aborter);
4420   resumable = XML_FALSE;
4421   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
4422       == XML_STATUS_ERROR)
4423     xml_failure(g_parser);
4424 }
4425 END_TEST
4426 
4427 START_TEST(test_bad_public_doctype) {
4428   const char *text = "<?xml version='1.0' encoding='utf-8'?>\n"
4429                      "<!DOCTYPE doc PUBLIC '{BadName}' 'test'>\n"
4430                      "<doc></doc>";
4431 
4432   /* Setting a handler provokes a particular code path */
4433   XML_SetDoctypeDeclHandler(g_parser, dummy_start_doctype_handler,
4434                             dummy_end_doctype_handler);
4435   expect_failure(text, XML_ERROR_PUBLICID, "Bad Public ID not failed");
4436 }
4437 END_TEST
4438 
4439 /* Test based on ibm/valid/P32/ibm32v04.xml */
4440 START_TEST(test_attribute_enum_value) {
4441   const char *text = "<?xml version='1.0' standalone='no'?>\n"
4442                      "<!DOCTYPE animal SYSTEM 'test.dtd'>\n"
4443                      "<animal>This is a \n    <a/>  \n\nyellow tiger</animal>";
4444   ExtTest dtd_data
4445       = {"<!ELEMENT animal (#PCDATA|a)*>\n"
4446          "<!ELEMENT a EMPTY>\n"
4447          "<!ATTLIST animal xml:space (default|preserve) 'preserve'>",
4448          NULL, NULL};
4449   const XML_Char *expected = XCS("This is a \n      \n\nyellow tiger");
4450 
4451   XML_SetExternalEntityRefHandler(g_parser, external_entity_loader);
4452   XML_SetUserData(g_parser, &dtd_data);
4453   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
4454   /* An attribute list handler provokes a different code path */
4455   XML_SetAttlistDeclHandler(g_parser, dummy_attlist_decl_handler);
4456   run_ext_character_check(text, &dtd_data, expected);
4457 }
4458 END_TEST
4459 
4460 /* Slightly bizarrely, the library seems to silently ignore entity
4461  * definitions for predefined entities, even when they are wrong.  The
4462  * language of the XML 1.0 spec is somewhat unhelpful as to what ought
4463  * to happen, so this is currently treated as acceptable.
4464  */
4465 START_TEST(test_predefined_entity_redefinition) {
4466   const char *text = "<!DOCTYPE doc [\n"
4467                      "<!ENTITY apos 'foo'>\n"
4468                      "]>\n"
4469                      "<doc>&apos;</doc>";
4470   run_character_check(text, XCS("'"));
4471 }
4472 END_TEST
4473 
4474 /* Test that the parser stops processing the DTD after an unresolved
4475  * parameter entity is encountered.
4476  */
4477 START_TEST(test_dtd_stop_processing) {
4478   const char *text = "<!DOCTYPE doc [\n"
4479                      "%foo;\n"
4480                      "<!ENTITY bar 'bas'>\n"
4481                      "]><doc/>";
4482 
4483   XML_SetEntityDeclHandler(g_parser, dummy_entity_decl_handler);
4484   dummy_handler_flags = 0;
4485   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
4486       == XML_STATUS_ERROR)
4487     xml_failure(g_parser);
4488   if (dummy_handler_flags != 0)
4489     fail("DTD processing still going after undefined PE");
4490 }
4491 END_TEST
4492 
4493 /* Test public notations with no system ID */
4494 START_TEST(test_public_notation_no_sysid) {
4495   const char *text = "<!DOCTYPE doc [\n"
4496                      "<!NOTATION note PUBLIC 'foo'>\n"
4497                      "<!ELEMENT doc EMPTY>\n"
4498                      "]>\n<doc/>";
4499 
4500   dummy_handler_flags = 0;
4501   XML_SetNotationDeclHandler(g_parser, dummy_notation_decl_handler);
4502   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
4503       == XML_STATUS_ERROR)
4504     xml_failure(g_parser);
4505   if (dummy_handler_flags != DUMMY_NOTATION_DECL_HANDLER_FLAG)
4506     fail("Notation declaration handler not called");
4507 }
4508 END_TEST
4509 
4510 static void XMLCALL
4511 record_element_start_handler(void *userData, const XML_Char *name,
4512                              const XML_Char **atts) {
4513   UNUSED_P(atts);
4514   CharData_AppendXMLChars((CharData *)userData, name, (int)xcstrlen(name));
4515 }
4516 
4517 START_TEST(test_nested_groups) {
4518   const char *text
4519       = "<!DOCTYPE doc [\n"
4520         "<!ELEMENT doc "
4521         /* Sixteen elements per line */
4522         "(e,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,"
4523         "(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?"
4524         "))))))))))))))))))))))))))))))))>\n"
4525         "<!ELEMENT e EMPTY>"
4526         "]>\n"
4527         "<doc><e/></doc>";
4528   CharData storage;
4529 
4530   CharData_Init(&storage);
4531   XML_SetElementDeclHandler(g_parser, dummy_element_decl_handler);
4532   XML_SetStartElementHandler(g_parser, record_element_start_handler);
4533   XML_SetUserData(g_parser, &storage);
4534   dummy_handler_flags = 0;
4535   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
4536       == XML_STATUS_ERROR)
4537     xml_failure(g_parser);
4538   CharData_CheckXMLChars(&storage, XCS("doce"));
4539   if (dummy_handler_flags != DUMMY_ELEMENT_DECL_HANDLER_FLAG)
4540     fail("Element handler not fired");
4541 }
4542 END_TEST
4543 
4544 START_TEST(test_group_choice) {
4545   const char *text = "<!DOCTYPE doc [\n"
4546                      "<!ELEMENT doc (a|b|c)+>\n"
4547                      "<!ELEMENT a EMPTY>\n"
4548                      "<!ELEMENT b (#PCDATA)>\n"
4549                      "<!ELEMENT c ANY>\n"
4550                      "]>\n"
4551                      "<doc>\n"
4552                      "<a/>\n"
4553                      "<b attr='foo'>This is a foo</b>\n"
4554                      "<c></c>\n"
4555                      "</doc>\n";
4556 
4557   XML_SetElementDeclHandler(g_parser, dummy_element_decl_handler);
4558   dummy_handler_flags = 0;
4559   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
4560       == XML_STATUS_ERROR)
4561     xml_failure(g_parser);
4562   if (dummy_handler_flags != DUMMY_ELEMENT_DECL_HANDLER_FLAG)
4563     fail("Element handler flag not raised");
4564 }
4565 END_TEST
4566 
4567 static int XMLCALL
4568 external_entity_public(XML_Parser parser, const XML_Char *context,
4569                        const XML_Char *base, const XML_Char *systemId,
4570                        const XML_Char *publicId) {
4571   const char *text1 = (const char *)XML_GetUserData(parser);
4572   const char *text2 = "<!ATTLIST doc a CDATA 'value'>";
4573   const char *text = NULL;
4574   XML_Parser ext_parser;
4575   int parse_res;
4576 
4577   UNUSED_P(base);
4578   ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
4579   if (ext_parser == NULL)
4580     return XML_STATUS_ERROR;
4581   if (systemId != NULL && ! xcstrcmp(systemId, XCS("http://example.org/"))) {
4582     text = text1;
4583   } else if (publicId != NULL && ! xcstrcmp(publicId, XCS("foo"))) {
4584     text = text2;
4585   } else
4586     fail("Unexpected parameters to external entity parser");
4587   assert(text != NULL);
4588   parse_res
4589       = _XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE);
4590   XML_ParserFree(ext_parser);
4591   return parse_res;
4592 }
4593 
4594 START_TEST(test_standalone_parameter_entity) {
4595   const char *text = "<?xml version='1.0' standalone='yes'?>\n"
4596                      "<!DOCTYPE doc SYSTEM 'http://example.org/' [\n"
4597                      "<!ENTITY % entity '<!ELEMENT doc (#PCDATA)>'>\n"
4598                      "%entity;\n"
4599                      "]>\n"
4600                      "<doc></doc>";
4601   char dtd_data[] = "<!ENTITY % e1 'foo'>\n";
4602 
4603   XML_SetUserData(g_parser, dtd_data);
4604   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
4605   XML_SetExternalEntityRefHandler(g_parser, external_entity_public);
4606   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
4607       == XML_STATUS_ERROR)
4608     xml_failure(g_parser);
4609 }
4610 END_TEST
4611 
4612 /* Test skipping of parameter entity in an external DTD */
4613 /* Derived from ibm/invalid/P69/ibm69i01.xml */
4614 START_TEST(test_skipped_parameter_entity) {
4615   const char *text = "<?xml version='1.0'?>\n"
4616                      "<!DOCTYPE root SYSTEM 'http://example.org/dtd.ent' [\n"
4617                      "<!ELEMENT root (#PCDATA|a)* >\n"
4618                      "]>\n"
4619                      "<root></root>";
4620   ExtTest dtd_data = {"%pe2;", NULL, NULL};
4621 
4622   XML_SetExternalEntityRefHandler(g_parser, external_entity_loader);
4623   XML_SetUserData(g_parser, &dtd_data);
4624   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
4625   XML_SetSkippedEntityHandler(g_parser, dummy_skip_handler);
4626   dummy_handler_flags = 0;
4627   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
4628       == XML_STATUS_ERROR)
4629     xml_failure(g_parser);
4630   if (dummy_handler_flags != DUMMY_SKIP_HANDLER_FLAG)
4631     fail("Skip handler not executed");
4632 }
4633 END_TEST
4634 
4635 /* Test recursive parameter entity definition rejected in external DTD */
4636 START_TEST(test_recursive_external_parameter_entity) {
4637   const char *text = "<?xml version='1.0'?>\n"
4638                      "<!DOCTYPE root SYSTEM 'http://example.org/dtd.ent' [\n"
4639                      "<!ELEMENT root (#PCDATA|a)* >\n"
4640                      "]>\n"
4641                      "<root></root>";
4642   ExtFaults dtd_data = {"<!ENTITY % pe2 '&#37;pe2;'>\n%pe2;",
4643                         "Recursive external parameter entity not faulted", NULL,
4644                         XML_ERROR_RECURSIVE_ENTITY_REF};
4645 
4646   XML_SetExternalEntityRefHandler(g_parser, external_entity_faulter);
4647   XML_SetUserData(g_parser, &dtd_data);
4648   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
4649   expect_failure(text, XML_ERROR_EXTERNAL_ENTITY_HANDLING,
4650                  "Recursive external parameter not spotted");
4651 }
4652 END_TEST
4653 
4654 /* Test undefined parameter entity in external entity handler */
4655 static int XMLCALL
4656 external_entity_devaluer(XML_Parser parser, const XML_Char *context,
4657                          const XML_Char *base, const XML_Char *systemId,
4658                          const XML_Char *publicId) {
4659   const char *text = "<!ELEMENT doc EMPTY>\n"
4660                      "<!ENTITY % e1 SYSTEM 'bar'>\n"
4661                      "%e1;\n";
4662   XML_Parser ext_parser;
4663   intptr_t clear_handler = (intptr_t)XML_GetUserData(parser);
4664 
4665   UNUSED_P(base);
4666   UNUSED_P(publicId);
4667   if (systemId == NULL || ! xcstrcmp(systemId, XCS("bar")))
4668     return XML_STATUS_OK;
4669   if (xcstrcmp(systemId, XCS("foo")))
4670     fail("Unexpected system ID");
4671   ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
4672   if (ext_parser == NULL)
4673     fail("Could note create external entity parser");
4674   if (clear_handler)
4675     XML_SetExternalEntityRefHandler(ext_parser, NULL);
4676   if (_XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE)
4677       == XML_STATUS_ERROR)
4678     xml_failure(ext_parser);
4679 
4680   XML_ParserFree(ext_parser);
4681   return XML_STATUS_OK;
4682 }
4683 
4684 START_TEST(test_undefined_ext_entity_in_external_dtd) {
4685   const char *text = "<!DOCTYPE doc SYSTEM 'foo'>\n"
4686                      "<doc></doc>\n";
4687 
4688   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
4689   XML_SetExternalEntityRefHandler(g_parser, external_entity_devaluer);
4690   XML_SetUserData(g_parser, (void *)(intptr_t)XML_FALSE);
4691   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
4692       == XML_STATUS_ERROR)
4693     xml_failure(g_parser);
4694 
4695   /* Now repeat without the external entity ref handler invoking
4696    * another copy of itself.
4697    */
4698   XML_ParserReset(g_parser, NULL);
4699   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
4700   XML_SetExternalEntityRefHandler(g_parser, external_entity_devaluer);
4701   XML_SetUserData(g_parser, (void *)(intptr_t)XML_TRUE);
4702   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
4703       == XML_STATUS_ERROR)
4704     xml_failure(g_parser);
4705 }
4706 END_TEST
4707 
4708 static void XMLCALL
4709 aborting_xdecl_handler(void *userData, const XML_Char *version,
4710                        const XML_Char *encoding, int standalone) {
4711   UNUSED_P(userData);
4712   UNUSED_P(version);
4713   UNUSED_P(encoding);
4714   UNUSED_P(standalone);
4715   XML_StopParser(g_parser, resumable);
4716   XML_SetXmlDeclHandler(g_parser, NULL);
4717 }
4718 
4719 /* Test suspending the parse on receiving an XML declaration works */
4720 START_TEST(test_suspend_xdecl) {
4721   const char *text = long_character_data_text;
4722 
4723   XML_SetXmlDeclHandler(g_parser, aborting_xdecl_handler);
4724   resumable = XML_TRUE;
4725   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
4726       != XML_STATUS_SUSPENDED)
4727     xml_failure(g_parser);
4728   if (XML_GetErrorCode(g_parser) != XML_ERROR_NONE)
4729     xml_failure(g_parser);
4730   /* Attempt to start a new parse while suspended */
4731   if (XML_Parse(g_parser, text, (int)strlen(text), XML_TRUE)
4732       != XML_STATUS_ERROR)
4733     fail("Attempt to parse while suspended not faulted");
4734   if (XML_GetErrorCode(g_parser) != XML_ERROR_SUSPENDED)
4735     fail("Suspended parse not faulted with correct error");
4736 }
4737 END_TEST
4738 
4739 /* Test aborting the parse in an epilog works */
4740 static void XMLCALL
4741 selective_aborting_default_handler(void *userData, const XML_Char *s, int len) {
4742   const XML_Char *match = (const XML_Char *)userData;
4743 
4744   if (match == NULL
4745       || (xcstrlen(match) == (unsigned)len && ! xcstrncmp(match, s, len))) {
4746     XML_StopParser(g_parser, resumable);
4747     XML_SetDefaultHandler(g_parser, NULL);
4748   }
4749 }
4750 
4751 START_TEST(test_abort_epilog) {
4752   const char *text = "<doc></doc>\n\r\n";
4753   XML_Char match[] = XCS("\r");
4754 
4755   XML_SetDefaultHandler(g_parser, selective_aborting_default_handler);
4756   XML_SetUserData(g_parser, match);
4757   resumable = XML_FALSE;
4758   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
4759       != XML_STATUS_ERROR)
4760     fail("Abort not triggered");
4761   if (XML_GetErrorCode(g_parser) != XML_ERROR_ABORTED)
4762     xml_failure(g_parser);
4763 }
4764 END_TEST
4765 
4766 /* Test a different code path for abort in the epilog */
4767 START_TEST(test_abort_epilog_2) {
4768   const char *text = "<doc></doc>\n";
4769   XML_Char match[] = XCS("\n");
4770 
4771   XML_SetDefaultHandler(g_parser, selective_aborting_default_handler);
4772   XML_SetUserData(g_parser, match);
4773   resumable = XML_FALSE;
4774   expect_failure(text, XML_ERROR_ABORTED, "Abort not triggered");
4775 }
4776 END_TEST
4777 
4778 /* Test suspension from the epilog */
4779 START_TEST(test_suspend_epilog) {
4780   const char *text = "<doc></doc>\n";
4781   XML_Char match[] = XCS("\n");
4782 
4783   XML_SetDefaultHandler(g_parser, selective_aborting_default_handler);
4784   XML_SetUserData(g_parser, match);
4785   resumable = XML_TRUE;
4786   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
4787       != XML_STATUS_SUSPENDED)
4788     xml_failure(g_parser);
4789 }
4790 END_TEST
4791 
4792 static void XMLCALL
4793 suspending_end_handler(void *userData, const XML_Char *s) {
4794   UNUSED_P(s);
4795   XML_StopParser((XML_Parser)userData, 1);
4796 }
4797 
4798 START_TEST(test_suspend_in_sole_empty_tag) {
4799   const char *text = "<doc/>";
4800   enum XML_Status rc;
4801 
4802   XML_SetEndElementHandler(g_parser, suspending_end_handler);
4803   XML_SetUserData(g_parser, g_parser);
4804   rc = _XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE);
4805   if (rc == XML_STATUS_ERROR)
4806     xml_failure(g_parser);
4807   else if (rc != XML_STATUS_SUSPENDED)
4808     fail("Suspend not triggered");
4809   rc = XML_ResumeParser(g_parser);
4810   if (rc == XML_STATUS_ERROR)
4811     xml_failure(g_parser);
4812   else if (rc != XML_STATUS_OK)
4813     fail("Resume failed");
4814 }
4815 END_TEST
4816 
4817 START_TEST(test_unfinished_epilog) {
4818   const char *text = "<doc></doc><";
4819 
4820   expect_failure(text, XML_ERROR_UNCLOSED_TOKEN,
4821                  "Incomplete epilog entry not faulted");
4822 }
4823 END_TEST
4824 
4825 START_TEST(test_partial_char_in_epilog) {
4826   const char *text = "<doc></doc>\xe2\x82";
4827 
4828   /* First check that no fault is raised if the parse is not finished */
4829   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_FALSE)
4830       == XML_STATUS_ERROR)
4831     xml_failure(g_parser);
4832   /* Now check that it is faulted once we finish */
4833   if (XML_ParseBuffer(g_parser, 0, XML_TRUE) != XML_STATUS_ERROR)
4834     fail("Partial character in epilog not faulted");
4835   if (XML_GetErrorCode(g_parser) != XML_ERROR_PARTIAL_CHAR)
4836     xml_failure(g_parser);
4837 }
4838 END_TEST
4839 
4840 START_TEST(test_hash_collision) {
4841   /* For full coverage of the lookup routine, we need to ensure a
4842    * hash collision even though we can only tell that we have one
4843    * through breakpoint debugging or coverage statistics.  The
4844    * following will cause a hash collision on machines with a 64-bit
4845    * long type; others will have to experiment.  The full coverage
4846    * tests invoked from qa.sh usually provide a hash collision, but
4847    * not always.  This is an attempt to provide insurance.
4848    */
4849 #define COLLIDING_HASH_SALT (unsigned long)_SIP_ULL(0xffffffffU, 0xff99fc90U)
4850   const char *text
4851       = "<doc>\n"
4852         "<a1/><a2/><a3/><a4/><a5/><a6/><a7/><a8/>\n"
4853         "<b1></b1><b2 attr='foo'>This is a foo</b2><b3></b3><b4></b4>\n"
4854         "<b5></b5><b6></b6><b7></b7><b8></b8>\n"
4855         "<c1/><c2/><c3/><c4/><c5/><c6/><c7/><c8/>\n"
4856         "<d1/><d2/><d3/><d4/><d5/><d6/><d7/>\n"
4857         "<d8>This triggers the table growth and collides with b2</d8>\n"
4858         "</doc>\n";
4859 
4860   XML_SetHashSalt(g_parser, COLLIDING_HASH_SALT);
4861   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
4862       == XML_STATUS_ERROR)
4863     xml_failure(g_parser);
4864 }
4865 END_TEST
4866 #undef COLLIDING_HASH_SALT
4867 
4868 /* Test resuming a parse suspended in entity substitution */
4869 static void XMLCALL
4870 start_element_suspender(void *userData, const XML_Char *name,
4871                         const XML_Char **atts) {
4872   UNUSED_P(userData);
4873   UNUSED_P(atts);
4874   if (! xcstrcmp(name, XCS("suspend")))
4875     XML_StopParser(g_parser, XML_TRUE);
4876   if (! xcstrcmp(name, XCS("abort")))
4877     XML_StopParser(g_parser, XML_FALSE);
4878 }
4879 
4880 START_TEST(test_suspend_resume_internal_entity) {
4881   const char *text
4882       = "<!DOCTYPE doc [\n"
4883         "<!ENTITY foo '<suspend>Hi<suspend>Ho</suspend></suspend>'>\n"
4884         "]>\n"
4885         "<doc>&foo;</doc>\n";
4886   const XML_Char *expected1 = XCS("Hi");
4887   const XML_Char *expected2 = XCS("HiHo");
4888   CharData storage;
4889 
4890   CharData_Init(&storage);
4891   XML_SetStartElementHandler(g_parser, start_element_suspender);
4892   XML_SetCharacterDataHandler(g_parser, accumulate_characters);
4893   XML_SetUserData(g_parser, &storage);
4894   if (XML_Parse(g_parser, text, (int)strlen(text), XML_TRUE)
4895       != XML_STATUS_SUSPENDED)
4896     xml_failure(g_parser);
4897   CharData_CheckXMLChars(&storage, XCS(""));
4898   if (XML_ResumeParser(g_parser) != XML_STATUS_SUSPENDED)
4899     xml_failure(g_parser);
4900   CharData_CheckXMLChars(&storage, expected1);
4901   if (XML_ResumeParser(g_parser) != XML_STATUS_OK)
4902     xml_failure(g_parser);
4903   CharData_CheckXMLChars(&storage, expected2);
4904 }
4905 END_TEST
4906 
4907 /* Test syntax error is caught at parse resumption */
4908 START_TEST(test_resume_entity_with_syntax_error) {
4909   const char *text = "<!DOCTYPE doc [\n"
4910                      "<!ENTITY foo '<suspend>Hi</wombat>'>\n"
4911                      "]>\n"
4912                      "<doc>&foo;</doc>\n";
4913 
4914   XML_SetStartElementHandler(g_parser, start_element_suspender);
4915   if (XML_Parse(g_parser, text, (int)strlen(text), XML_TRUE)
4916       != XML_STATUS_SUSPENDED)
4917     xml_failure(g_parser);
4918   if (XML_ResumeParser(g_parser) != XML_STATUS_ERROR)
4919     fail("Syntax error in entity not faulted");
4920   if (XML_GetErrorCode(g_parser) != XML_ERROR_TAG_MISMATCH)
4921     xml_failure(g_parser);
4922 }
4923 END_TEST
4924 
4925 /* Test suspending and resuming in a parameter entity substitution */
4926 static void XMLCALL
4927 element_decl_suspender(void *userData, const XML_Char *name,
4928                        XML_Content *model) {
4929   UNUSED_P(userData);
4930   UNUSED_P(name);
4931   XML_StopParser(g_parser, XML_TRUE);
4932   XML_FreeContentModel(g_parser, model);
4933 }
4934 
4935 START_TEST(test_suspend_resume_parameter_entity) {
4936   const char *text = "<!DOCTYPE doc [\n"
4937                      "<!ENTITY % foo '<!ELEMENT doc (#PCDATA)*>'>\n"
4938                      "%foo;\n"
4939                      "]>\n"
4940                      "<doc>Hello, world</doc>";
4941   const XML_Char *expected = XCS("Hello, world");
4942   CharData storage;
4943 
4944   CharData_Init(&storage);
4945   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
4946   XML_SetElementDeclHandler(g_parser, element_decl_suspender);
4947   XML_SetCharacterDataHandler(g_parser, accumulate_characters);
4948   XML_SetUserData(g_parser, &storage);
4949   if (XML_Parse(g_parser, text, (int)strlen(text), XML_TRUE)
4950       != XML_STATUS_SUSPENDED)
4951     xml_failure(g_parser);
4952   CharData_CheckXMLChars(&storage, XCS(""));
4953   if (XML_ResumeParser(g_parser) != XML_STATUS_OK)
4954     xml_failure(g_parser);
4955   CharData_CheckXMLChars(&storage, expected);
4956 }
4957 END_TEST
4958 
4959 /* Test attempting to use parser after an error is faulted */
4960 START_TEST(test_restart_on_error) {
4961   const char *text = "<$doc><doc></doc>";
4962 
4963   if (XML_Parse(g_parser, text, (int)strlen(text), XML_TRUE)
4964       != XML_STATUS_ERROR)
4965     fail("Invalid tag name not faulted");
4966   if (XML_GetErrorCode(g_parser) != XML_ERROR_INVALID_TOKEN)
4967     xml_failure(g_parser);
4968   if (XML_Parse(g_parser, NULL, 0, XML_TRUE) != XML_STATUS_ERROR)
4969     fail("Restarting invalid parse not faulted");
4970   if (XML_GetErrorCode(g_parser) != XML_ERROR_INVALID_TOKEN)
4971     xml_failure(g_parser);
4972 }
4973 END_TEST
4974 
4975 /* Test that angle brackets in an attribute default value are faulted */
4976 START_TEST(test_reject_lt_in_attribute_value) {
4977   const char *text = "<!DOCTYPE doc [<!ATTLIST doc a CDATA '<bar>'>]>\n"
4978                      "<doc></doc>";
4979 
4980   expect_failure(text, XML_ERROR_INVALID_TOKEN,
4981                  "Bad attribute default not faulted");
4982 }
4983 END_TEST
4984 
4985 START_TEST(test_reject_unfinished_param_in_att_value) {
4986   const char *text = "<!DOCTYPE doc [<!ATTLIST doc a CDATA '&foo'>]>\n"
4987                      "<doc></doc>";
4988 
4989   expect_failure(text, XML_ERROR_INVALID_TOKEN,
4990                  "Bad attribute default not faulted");
4991 }
4992 END_TEST
4993 
4994 START_TEST(test_trailing_cr_in_att_value) {
4995   const char *text = "<doc a='value\r'/>";
4996 
4997   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
4998       == XML_STATUS_ERROR)
4999     xml_failure(g_parser);
5000 }
5001 END_TEST
5002 
5003 /* Try parsing a general entity within a parameter entity in a
5004  * standalone internal DTD.  Covers a corner case in the parser.
5005  */
5006 START_TEST(test_standalone_internal_entity) {
5007   const char *text = "<?xml version='1.0' standalone='yes' ?>\n"
5008                      "<!DOCTYPE doc [\n"
5009                      "  <!ELEMENT doc (#PCDATA)>\n"
5010                      "  <!ENTITY % pe '<!ATTLIST doc att2 CDATA \"&ge;\">'>\n"
5011                      "  <!ENTITY ge 'AttDefaultValue'>\n"
5012                      "  %pe;\n"
5013                      "]>\n"
5014                      "<doc att2='any'/>";
5015 
5016   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
5017   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
5018       == XML_STATUS_ERROR)
5019     xml_failure(g_parser);
5020 }
5021 END_TEST
5022 
5023 /* Test that a reference to an unknown external entity is skipped */
5024 START_TEST(test_skipped_external_entity) {
5025   const char *text = "<!DOCTYPE doc SYSTEM 'http://example.org/'>\n"
5026                      "<doc></doc>\n";
5027   ExtTest test_data = {"<!ELEMENT doc EMPTY>\n"
5028                        "<!ENTITY % e2 '%e1;'>\n",
5029                        NULL, NULL};
5030 
5031   XML_SetUserData(g_parser, &test_data);
5032   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
5033   XML_SetExternalEntityRefHandler(g_parser, external_entity_loader);
5034   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
5035       == XML_STATUS_ERROR)
5036     xml_failure(g_parser);
5037 }
5038 END_TEST
5039 
5040 /* Test a different form of unknown external entity */
5041 typedef struct ext_hdlr_data {
5042   const char *parse_text;
5043   XML_ExternalEntityRefHandler handler;
5044 } ExtHdlrData;
5045 
5046 static int XMLCALL
5047 external_entity_oneshot_loader(XML_Parser parser, const XML_Char *context,
5048                                const XML_Char *base, const XML_Char *systemId,
5049                                const XML_Char *publicId) {
5050   ExtHdlrData *test_data = (ExtHdlrData *)XML_GetUserData(parser);
5051   XML_Parser ext_parser;
5052 
5053   UNUSED_P(base);
5054   UNUSED_P(systemId);
5055   UNUSED_P(publicId);
5056   ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
5057   if (ext_parser == NULL)
5058     fail("Could not create external entity parser.");
5059   /* Use the requested entity parser for further externals */
5060   XML_SetExternalEntityRefHandler(ext_parser, test_data->handler);
5061   if (_XML_Parse_SINGLE_BYTES(ext_parser, test_data->parse_text,
5062                               (int)strlen(test_data->parse_text), XML_TRUE)
5063       == XML_STATUS_ERROR) {
5064     xml_failure(ext_parser);
5065   }
5066 
5067   XML_ParserFree(ext_parser);
5068   return XML_STATUS_OK;
5069 }
5070 
5071 START_TEST(test_skipped_null_loaded_ext_entity) {
5072   const char *text = "<!DOCTYPE doc SYSTEM 'http://example.org/one.ent'>\n"
5073                      "<doc />";
5074   ExtHdlrData test_data
5075       = {"<!ENTITY % pe1 SYSTEM 'http://example.org/two.ent'>\n"
5076          "<!ENTITY % pe2 '%pe1;'>\n"
5077          "%pe2;\n",
5078          external_entity_null_loader};
5079 
5080   XML_SetUserData(g_parser, &test_data);
5081   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
5082   XML_SetExternalEntityRefHandler(g_parser, external_entity_oneshot_loader);
5083   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
5084       == XML_STATUS_ERROR)
5085     xml_failure(g_parser);
5086 }
5087 END_TEST
5088 
5089 START_TEST(test_skipped_unloaded_ext_entity) {
5090   const char *text = "<!DOCTYPE doc SYSTEM 'http://example.org/one.ent'>\n"
5091                      "<doc />";
5092   ExtHdlrData test_data
5093       = {"<!ENTITY % pe1 SYSTEM 'http://example.org/two.ent'>\n"
5094          "<!ENTITY % pe2 '%pe1;'>\n"
5095          "%pe2;\n",
5096          NULL};
5097 
5098   XML_SetUserData(g_parser, &test_data);
5099   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
5100   XML_SetExternalEntityRefHandler(g_parser, external_entity_oneshot_loader);
5101   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
5102       == XML_STATUS_ERROR)
5103     xml_failure(g_parser);
5104 }
5105 END_TEST
5106 
5107 /* Test that a parameter entity value ending with a carriage return
5108  * has it translated internally into a newline.
5109  */
5110 START_TEST(test_param_entity_with_trailing_cr) {
5111 #define PARAM_ENTITY_NAME "pe"
5112 #define PARAM_ENTITY_CORE_VALUE "<!ATTLIST doc att CDATA \"default\">"
5113   const char *text = "<!DOCTYPE doc SYSTEM 'http://example.org/'>\n"
5114                      "<doc/>";
5115   ExtTest test_data
5116       = {"<!ENTITY % " PARAM_ENTITY_NAME " '" PARAM_ENTITY_CORE_VALUE "\r'>\n"
5117          "%" PARAM_ENTITY_NAME ";\n",
5118          NULL, NULL};
5119 
5120   XML_SetUserData(g_parser, &test_data);
5121   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
5122   XML_SetExternalEntityRefHandler(g_parser, external_entity_loader);
5123   XML_SetEntityDeclHandler(g_parser, param_entity_match_handler);
5124   entity_name_to_match = XCS(PARAM_ENTITY_NAME);
5125   entity_value_to_match = XCS(PARAM_ENTITY_CORE_VALUE) XCS("\n");
5126   entity_match_flag = ENTITY_MATCH_NOT_FOUND;
5127   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
5128       == XML_STATUS_ERROR)
5129     xml_failure(g_parser);
5130   if (entity_match_flag == ENTITY_MATCH_FAIL)
5131     fail("Parameter entity CR->NEWLINE conversion failed");
5132   else if (entity_match_flag == ENTITY_MATCH_NOT_FOUND)
5133     fail("Parameter entity not parsed");
5134 }
5135 #undef PARAM_ENTITY_NAME
5136 #undef PARAM_ENTITY_CORE_VALUE
5137 END_TEST
5138 
5139 START_TEST(test_invalid_character_entity) {
5140   const char *text = "<!DOCTYPE doc [\n"
5141                      "  <!ENTITY entity '&#x110000;'>\n"
5142                      "]>\n"
5143                      "<doc>&entity;</doc>";
5144 
5145   expect_failure(text, XML_ERROR_BAD_CHAR_REF,
5146                  "Out of range character reference not faulted");
5147 }
5148 END_TEST
5149 
5150 START_TEST(test_invalid_character_entity_2) {
5151   const char *text = "<!DOCTYPE doc [\n"
5152                      "  <!ENTITY entity '&#xg0;'>\n"
5153                      "]>\n"
5154                      "<doc>&entity;</doc>";
5155 
5156   expect_failure(text, XML_ERROR_INVALID_TOKEN,
5157                  "Out of range character reference not faulted");
5158 }
5159 END_TEST
5160 
5161 START_TEST(test_invalid_character_entity_3) {
5162   const char text[] =
5163       /* <!DOCTYPE doc [\n */
5164       "\0<\0!\0D\0O\0C\0T\0Y\0P\0E\0 \0d\0o\0c\0 \0[\0\n"
5165       /* U+0E04 = KHO KHWAI
5166        * U+0E08 = CHO CHAN */
5167       /* <!ENTITY entity '&\u0e04\u0e08;'>\n */
5168       "\0<\0!\0E\0N\0T\0I\0T\0Y\0 \0e\0n\0t\0i\0t\0y\0 "
5169       "\0'\0&\x0e\x04\x0e\x08\0;\0'\0>\0\n"
5170       /* ]>\n */
5171       "\0]\0>\0\n"
5172       /* <doc>&entity;</doc> */
5173       "\0<\0d\0o\0c\0>\0&\0e\0n\0t\0i\0t\0y\0;\0<\0/\0d\0o\0c\0>";
5174 
5175   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE)
5176       != XML_STATUS_ERROR)
5177     fail("Invalid start of entity name not faulted");
5178   if (XML_GetErrorCode(g_parser) != XML_ERROR_UNDEFINED_ENTITY)
5179     xml_failure(g_parser);
5180 }
5181 END_TEST
5182 
5183 START_TEST(test_invalid_character_entity_4) {
5184   const char *text = "<!DOCTYPE doc [\n"
5185                      "  <!ENTITY entity '&#1114112;'>\n" /* = &#x110000 */
5186                      "]>\n"
5187                      "<doc>&entity;</doc>";
5188 
5189   expect_failure(text, XML_ERROR_BAD_CHAR_REF,
5190                  "Out of range character reference not faulted");
5191 }
5192 END_TEST
5193 
5194 /* Test that processing instructions are picked up by a default handler */
5195 START_TEST(test_pi_handled_in_default) {
5196   const char *text = "<?test processing instruction?>\n<doc/>";
5197   const XML_Char *expected = XCS("<?test processing instruction?>\n<doc/>");
5198   CharData storage;
5199 
5200   CharData_Init(&storage);
5201   XML_SetDefaultHandler(g_parser, accumulate_characters);
5202   XML_SetUserData(g_parser, &storage);
5203   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
5204       == XML_STATUS_ERROR)
5205     xml_failure(g_parser);
5206   CharData_CheckXMLChars(&storage, expected);
5207 }
5208 END_TEST
5209 
5210 /* Test that comments are picked up by a default handler */
5211 START_TEST(test_comment_handled_in_default) {
5212   const char *text = "<!-- This is a comment -->\n<doc/>";
5213   const XML_Char *expected = XCS("<!-- This is a comment -->\n<doc/>");
5214   CharData storage;
5215 
5216   CharData_Init(&storage);
5217   XML_SetDefaultHandler(g_parser, accumulate_characters);
5218   XML_SetUserData(g_parser, &storage);
5219   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
5220       == XML_STATUS_ERROR)
5221     xml_failure(g_parser);
5222   CharData_CheckXMLChars(&storage, expected);
5223 }
5224 END_TEST
5225 
5226 /* Test PIs that look almost but not quite like XML declarations */
5227 static void XMLCALL
5228 accumulate_pi_characters(void *userData, const XML_Char *target,
5229                          const XML_Char *data) {
5230   CharData *storage = (CharData *)userData;
5231 
5232   CharData_AppendXMLChars(storage, target, -1);
5233   CharData_AppendXMLChars(storage, XCS(": "), 2);
5234   CharData_AppendXMLChars(storage, data, -1);
5235   CharData_AppendXMLChars(storage, XCS("\n"), 1);
5236 }
5237 
5238 START_TEST(test_pi_yml) {
5239   const char *text = "<?yml something like data?><doc/>";
5240   const XML_Char *expected = XCS("yml: something like data\n");
5241   CharData storage;
5242 
5243   CharData_Init(&storage);
5244   XML_SetProcessingInstructionHandler(g_parser, accumulate_pi_characters);
5245   XML_SetUserData(g_parser, &storage);
5246   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
5247       == XML_STATUS_ERROR)
5248     xml_failure(g_parser);
5249   CharData_CheckXMLChars(&storage, expected);
5250 }
5251 END_TEST
5252 
5253 START_TEST(test_pi_xnl) {
5254   const char *text = "<?xnl nothing like data?><doc/>";
5255   const XML_Char *expected = XCS("xnl: nothing like data\n");
5256   CharData storage;
5257 
5258   CharData_Init(&storage);
5259   XML_SetProcessingInstructionHandler(g_parser, accumulate_pi_characters);
5260   XML_SetUserData(g_parser, &storage);
5261   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
5262       == XML_STATUS_ERROR)
5263     xml_failure(g_parser);
5264   CharData_CheckXMLChars(&storage, expected);
5265 }
5266 END_TEST
5267 
5268 START_TEST(test_pi_xmm) {
5269   const char *text = "<?xmm everything like data?><doc/>";
5270   const XML_Char *expected = XCS("xmm: everything like data\n");
5271   CharData storage;
5272 
5273   CharData_Init(&storage);
5274   XML_SetProcessingInstructionHandler(g_parser, accumulate_pi_characters);
5275   XML_SetUserData(g_parser, &storage);
5276   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
5277       == XML_STATUS_ERROR)
5278     xml_failure(g_parser);
5279   CharData_CheckXMLChars(&storage, expected);
5280 }
5281 END_TEST
5282 
5283 START_TEST(test_utf16_pi) {
5284   const char text[] =
5285       /* <?{KHO KHWAI}{CHO CHAN}?>
5286        * where {KHO KHWAI} = U+0E04
5287        * and   {CHO CHAN}  = U+0E08
5288        */
5289       "<\0?\0\x04\x0e\x08\x0e?\0>\0"
5290       /* <q/> */
5291       "<\0q\0/\0>\0";
5292 #ifdef XML_UNICODE
5293   const XML_Char *expected = XCS("\x0e04\x0e08: \n");
5294 #else
5295   const XML_Char *expected = XCS("\xe0\xb8\x84\xe0\xb8\x88: \n");
5296 #endif
5297   CharData storage;
5298 
5299   CharData_Init(&storage);
5300   XML_SetProcessingInstructionHandler(g_parser, accumulate_pi_characters);
5301   XML_SetUserData(g_parser, &storage);
5302   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE)
5303       == XML_STATUS_ERROR)
5304     xml_failure(g_parser);
5305   CharData_CheckXMLChars(&storage, expected);
5306 }
5307 END_TEST
5308 
5309 START_TEST(test_utf16_be_pi) {
5310   const char text[] =
5311       /* <?{KHO KHWAI}{CHO CHAN}?>
5312        * where {KHO KHWAI} = U+0E04
5313        * and   {CHO CHAN}  = U+0E08
5314        */
5315       "\0<\0?\x0e\x04\x0e\x08\0?\0>"
5316       /* <q/> */
5317       "\0<\0q\0/\0>";
5318 #ifdef XML_UNICODE
5319   const XML_Char *expected = XCS("\x0e04\x0e08: \n");
5320 #else
5321   const XML_Char *expected = XCS("\xe0\xb8\x84\xe0\xb8\x88: \n");
5322 #endif
5323   CharData storage;
5324 
5325   CharData_Init(&storage);
5326   XML_SetProcessingInstructionHandler(g_parser, accumulate_pi_characters);
5327   XML_SetUserData(g_parser, &storage);
5328   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE)
5329       == XML_STATUS_ERROR)
5330     xml_failure(g_parser);
5331   CharData_CheckXMLChars(&storage, expected);
5332 }
5333 END_TEST
5334 
5335 /* Test that comments can be picked up and translated */
5336 static void XMLCALL
5337 accumulate_comment(void *userData, const XML_Char *data) {
5338   CharData *storage = (CharData *)userData;
5339 
5340   CharData_AppendXMLChars(storage, data, -1);
5341 }
5342 
5343 START_TEST(test_utf16_be_comment) {
5344   const char text[] =
5345       /* <!-- Comment A --> */
5346       "\0<\0!\0-\0-\0 \0C\0o\0m\0m\0e\0n\0t\0 \0A\0 \0-\0-\0>\0\n"
5347       /* <doc/> */
5348       "\0<\0d\0o\0c\0/\0>";
5349   const XML_Char *expected = XCS(" Comment A ");
5350   CharData storage;
5351 
5352   CharData_Init(&storage);
5353   XML_SetCommentHandler(g_parser, accumulate_comment);
5354   XML_SetUserData(g_parser, &storage);
5355   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE)
5356       == XML_STATUS_ERROR)
5357     xml_failure(g_parser);
5358   CharData_CheckXMLChars(&storage, expected);
5359 }
5360 END_TEST
5361 
5362 START_TEST(test_utf16_le_comment) {
5363   const char text[] =
5364       /* <!-- Comment B --> */
5365       "<\0!\0-\0-\0 \0C\0o\0m\0m\0e\0n\0t\0 \0B\0 \0-\0-\0>\0\n\0"
5366       /* <doc/> */
5367       "<\0d\0o\0c\0/\0>\0";
5368   const XML_Char *expected = XCS(" Comment B ");
5369   CharData storage;
5370 
5371   CharData_Init(&storage);
5372   XML_SetCommentHandler(g_parser, accumulate_comment);
5373   XML_SetUserData(g_parser, &storage);
5374   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE)
5375       == XML_STATUS_ERROR)
5376     xml_failure(g_parser);
5377   CharData_CheckXMLChars(&storage, expected);
5378 }
5379 END_TEST
5380 
5381 /* Test that the unknown encoding handler with map entries that expect
5382  * conversion but no conversion function is faulted
5383  */
5384 static int XMLCALL
5385 failing_converter(void *data, const char *s) {
5386   UNUSED_P(data);
5387   UNUSED_P(s);
5388   /* Always claim to have failed */
5389   return -1;
5390 }
5391 
5392 static int XMLCALL
5393 prefix_converter(void *data, const char *s) {
5394   UNUSED_P(data);
5395   /* If the first byte is 0xff, raise an error */
5396   if (s[0] == (char)-1)
5397     return -1;
5398   /* Just add the low bits of the first byte to the second */
5399   return (s[1] + (s[0] & 0x7f)) & 0x01ff;
5400 }
5401 
5402 static int XMLCALL
5403 MiscEncodingHandler(void *data, const XML_Char *encoding, XML_Encoding *info) {
5404   int i;
5405   int high_map = -2; /* Assume a 2-byte sequence */
5406 
5407   if (! xcstrcmp(encoding, XCS("invalid-9"))
5408       || ! xcstrcmp(encoding, XCS("ascii-like"))
5409       || ! xcstrcmp(encoding, XCS("invalid-len"))
5410       || ! xcstrcmp(encoding, XCS("invalid-a"))
5411       || ! xcstrcmp(encoding, XCS("invalid-surrogate"))
5412       || ! xcstrcmp(encoding, XCS("invalid-high")))
5413     high_map = -1;
5414 
5415   for (i = 0; i < 128; ++i)
5416     info->map[i] = i;
5417   for (; i < 256; ++i)
5418     info->map[i] = high_map;
5419 
5420   /* If required, put an invalid value in the ASCII entries */
5421   if (! xcstrcmp(encoding, XCS("invalid-9")))
5422     info->map[9] = 5;
5423   /* If required, have a top-bit set character starts a 5-byte sequence */
5424   if (! xcstrcmp(encoding, XCS("invalid-len")))
5425     info->map[0x81] = -5;
5426   /* If required, make a top-bit set character a valid ASCII character */
5427   if (! xcstrcmp(encoding, XCS("invalid-a")))
5428     info->map[0x82] = 'a';
5429   /* If required, give a top-bit set character a forbidden value,
5430    * what would otherwise be the first of a surrogate pair.
5431    */
5432   if (! xcstrcmp(encoding, XCS("invalid-surrogate")))
5433     info->map[0x83] = 0xd801;
5434   /* If required, give a top-bit set character too high a value */
5435   if (! xcstrcmp(encoding, XCS("invalid-high")))
5436     info->map[0x84] = 0x010101;
5437 
5438   info->data = data;
5439   info->release = NULL;
5440   if (! xcstrcmp(encoding, XCS("failing-conv")))
5441     info->convert = failing_converter;
5442   else if (! xcstrcmp(encoding, XCS("prefix-conv")))
5443     info->convert = prefix_converter;
5444   else
5445     info->convert = NULL;
5446   return XML_STATUS_OK;
5447 }
5448 
5449 START_TEST(test_missing_encoding_conversion_fn) {
5450   const char *text = "<?xml version='1.0' encoding='no-conv'?>\n"
5451                      "<doc>\x81</doc>";
5452 
5453   XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL);
5454   /* MiscEncodingHandler sets up an encoding with every top-bit-set
5455    * character introducing a two-byte sequence.  For this, it
5456    * requires a convert function.  The above function call doesn't
5457    * pass one through, so when BadEncodingHandler actually gets
5458    * called it should supply an invalid encoding.
5459    */
5460   expect_failure(text, XML_ERROR_UNKNOWN_ENCODING,
5461                  "Encoding with missing convert() not faulted");
5462 }
5463 END_TEST
5464 
5465 START_TEST(test_failing_encoding_conversion_fn) {
5466   const char *text = "<?xml version='1.0' encoding='failing-conv'?>\n"
5467                      "<doc>\x81</doc>";
5468 
5469   XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL);
5470   /* BadEncodingHandler sets up an encoding with every top-bit-set
5471    * character introducing a two-byte sequence.  For this, it
5472    * requires a convert function.  The above function call passes
5473    * one that insists all possible sequences are invalid anyway.
5474    */
5475   expect_failure(text, XML_ERROR_INVALID_TOKEN,
5476                  "Encoding with failing convert() not faulted");
5477 }
5478 END_TEST
5479 
5480 /* Test unknown encoding conversions */
5481 START_TEST(test_unknown_encoding_success) {
5482   const char *text = "<?xml version='1.0' encoding='prefix-conv'?>\n"
5483                      /* Equivalent to <eoc>Hello, world</eoc> */
5484                      "<\x81\x64\x80oc>Hello, world</\x81\x64\x80oc>";
5485 
5486   XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL);
5487   run_character_check(text, XCS("Hello, world"));
5488 }
5489 END_TEST
5490 
5491 /* Test bad name character in unknown encoding */
5492 START_TEST(test_unknown_encoding_bad_name) {
5493   const char *text = "<?xml version='1.0' encoding='prefix-conv'?>\n"
5494                      "<\xff\x64oc>Hello, world</\xff\x64oc>";
5495 
5496   XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL);
5497   expect_failure(text, XML_ERROR_INVALID_TOKEN,
5498                  "Bad name start in unknown encoding not faulted");
5499 }
5500 END_TEST
5501 
5502 /* Test bad mid-name character in unknown encoding */
5503 START_TEST(test_unknown_encoding_bad_name_2) {
5504   const char *text = "<?xml version='1.0' encoding='prefix-conv'?>\n"
5505                      "<d\xffoc>Hello, world</d\xffoc>";
5506 
5507   XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL);
5508   expect_failure(text, XML_ERROR_INVALID_TOKEN,
5509                  "Bad name in unknown encoding not faulted");
5510 }
5511 END_TEST
5512 
5513 /* Test element name that is long enough to fill the conversion buffer
5514  * in an unknown encoding, finishing with an encoded character.
5515  */
5516 START_TEST(test_unknown_encoding_long_name_1) {
5517   const char *text = "<?xml version='1.0' encoding='prefix-conv'?>\n"
5518                      "<abcdefghabcdefghabcdefghijkl\x80m\x80n\x80o\x80p>"
5519                      "Hi"
5520                      "</abcdefghabcdefghabcdefghijkl\x80m\x80n\x80o\x80p>";
5521   const XML_Char *expected = XCS("abcdefghabcdefghabcdefghijklmnop");
5522   CharData storage;
5523 
5524   CharData_Init(&storage);
5525   XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL);
5526   XML_SetStartElementHandler(g_parser, record_element_start_handler);
5527   XML_SetUserData(g_parser, &storage);
5528   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
5529       == XML_STATUS_ERROR)
5530     xml_failure(g_parser);
5531   CharData_CheckXMLChars(&storage, expected);
5532 }
5533 END_TEST
5534 
5535 /* Test element name that is long enough to fill the conversion buffer
5536  * in an unknown encoding, finishing with an simple character.
5537  */
5538 START_TEST(test_unknown_encoding_long_name_2) {
5539   const char *text = "<?xml version='1.0' encoding='prefix-conv'?>\n"
5540                      "<abcdefghabcdefghabcdefghijklmnop>"
5541                      "Hi"
5542                      "</abcdefghabcdefghabcdefghijklmnop>";
5543   const XML_Char *expected = XCS("abcdefghabcdefghabcdefghijklmnop");
5544   CharData storage;
5545 
5546   CharData_Init(&storage);
5547   XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL);
5548   XML_SetStartElementHandler(g_parser, record_element_start_handler);
5549   XML_SetUserData(g_parser, &storage);
5550   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
5551       == XML_STATUS_ERROR)
5552     xml_failure(g_parser);
5553   CharData_CheckXMLChars(&storage, expected);
5554 }
5555 END_TEST
5556 
5557 START_TEST(test_invalid_unknown_encoding) {
5558   const char *text = "<?xml version='1.0' encoding='invalid-9'?>\n"
5559                      "<doc>Hello world</doc>";
5560 
5561   XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL);
5562   expect_failure(text, XML_ERROR_UNKNOWN_ENCODING,
5563                  "Invalid unknown encoding not faulted");
5564 }
5565 END_TEST
5566 
5567 START_TEST(test_unknown_ascii_encoding_ok) {
5568   const char *text = "<?xml version='1.0' encoding='ascii-like'?>\n"
5569                      "<doc>Hello, world</doc>";
5570 
5571   XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL);
5572   run_character_check(text, XCS("Hello, world"));
5573 }
5574 END_TEST
5575 
5576 START_TEST(test_unknown_ascii_encoding_fail) {
5577   const char *text = "<?xml version='1.0' encoding='ascii-like'?>\n"
5578                      "<doc>Hello, \x80 world</doc>";
5579 
5580   XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL);
5581   expect_failure(text, XML_ERROR_INVALID_TOKEN,
5582                  "Invalid character not faulted");
5583 }
5584 END_TEST
5585 
5586 START_TEST(test_unknown_encoding_invalid_length) {
5587   const char *text = "<?xml version='1.0' encoding='invalid-len'?>\n"
5588                      "<doc>Hello, world</doc>";
5589 
5590   XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL);
5591   expect_failure(text, XML_ERROR_UNKNOWN_ENCODING,
5592                  "Invalid unknown encoding not faulted");
5593 }
5594 END_TEST
5595 
5596 START_TEST(test_unknown_encoding_invalid_topbit) {
5597   const char *text = "<?xml version='1.0' encoding='invalid-a'?>\n"
5598                      "<doc>Hello, world</doc>";
5599 
5600   XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL);
5601   expect_failure(text, XML_ERROR_UNKNOWN_ENCODING,
5602                  "Invalid unknown encoding not faulted");
5603 }
5604 END_TEST
5605 
5606 START_TEST(test_unknown_encoding_invalid_surrogate) {
5607   const char *text = "<?xml version='1.0' encoding='invalid-surrogate'?>\n"
5608                      "<doc>Hello, \x82 world</doc>";
5609 
5610   XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL);
5611   expect_failure(text, XML_ERROR_INVALID_TOKEN,
5612                  "Invalid unknown encoding not faulted");
5613 }
5614 END_TEST
5615 
5616 START_TEST(test_unknown_encoding_invalid_high) {
5617   const char *text = "<?xml version='1.0' encoding='invalid-high'?>\n"
5618                      "<doc>Hello, world</doc>";
5619 
5620   XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL);
5621   expect_failure(text, XML_ERROR_UNKNOWN_ENCODING,
5622                  "Invalid unknown encoding not faulted");
5623 }
5624 END_TEST
5625 
5626 START_TEST(test_unknown_encoding_invalid_attr_value) {
5627   const char *text = "<?xml version='1.0' encoding='prefix-conv'?>\n"
5628                      "<doc attr='\xff\x30'/>";
5629 
5630   XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL);
5631   expect_failure(text, XML_ERROR_INVALID_TOKEN,
5632                  "Invalid attribute valid not faulted");
5633 }
5634 END_TEST
5635 
5636 /* Test an external entity parser set to use latin-1 detects UTF-16
5637  * BOMs correctly.
5638  */
5639 enum ee_parse_flags { EE_PARSE_NONE = 0x00, EE_PARSE_FULL_BUFFER = 0x01 };
5640 
5641 typedef struct ExtTest2 {
5642   const char *parse_text;
5643   int parse_len;
5644   const XML_Char *encoding;
5645   CharData *storage;
5646   enum ee_parse_flags flags;
5647 } ExtTest2;
5648 
5649 static int XMLCALL
5650 external_entity_loader2(XML_Parser parser, const XML_Char *context,
5651                         const XML_Char *base, const XML_Char *systemId,
5652                         const XML_Char *publicId) {
5653   ExtTest2 *test_data = (ExtTest2 *)XML_GetUserData(parser);
5654   XML_Parser extparser;
5655 
5656   UNUSED_P(base);
5657   UNUSED_P(systemId);
5658   UNUSED_P(publicId);
5659   extparser = XML_ExternalEntityParserCreate(parser, context, NULL);
5660   if (extparser == NULL)
5661     fail("Coulr not create external entity parser");
5662   if (test_data->encoding != NULL) {
5663     if (! XML_SetEncoding(extparser, test_data->encoding))
5664       fail("XML_SetEncoding() ignored for external entity");
5665   }
5666   if (test_data->flags & EE_PARSE_FULL_BUFFER) {
5667     if (XML_Parse(extparser, test_data->parse_text, test_data->parse_len,
5668                   XML_TRUE)
5669         == XML_STATUS_ERROR) {
5670       xml_failure(extparser);
5671     }
5672   } else if (_XML_Parse_SINGLE_BYTES(extparser, test_data->parse_text,
5673                                      test_data->parse_len, XML_TRUE)
5674              == XML_STATUS_ERROR) {
5675     xml_failure(extparser);
5676   }
5677 
5678   XML_ParserFree(extparser);
5679   return XML_STATUS_OK;
5680 }
5681 
5682 /* Test that UTF-16 BOM does not select UTF-16 given explicit encoding */
5683 static void XMLCALL
5684 ext2_accumulate_characters(void *userData, const XML_Char *s, int len) {
5685   ExtTest2 *test_data = (ExtTest2 *)userData;
5686   accumulate_characters(test_data->storage, s, len);
5687 }
5688 
5689 START_TEST(test_ext_entity_latin1_utf16le_bom) {
5690   const char *text = "<!DOCTYPE doc [\n"
5691                      "  <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n"
5692                      "]>\n"
5693                      "<doc>&en;</doc>";
5694   ExtTest2 test_data
5695       = {/* If UTF-16, 0xfeff is the BOM and 0x204c is black left bullet */
5696          /* If Latin-1, 0xff = Y-diaeresis, 0xfe = lowercase thorn,
5697           *   0x4c = L and 0x20 is a space
5698           */
5699          "\xff\xfe\x4c\x20", 4, XCS("iso-8859-1"), NULL, EE_PARSE_NONE};
5700 #ifdef XML_UNICODE
5701   const XML_Char *expected = XCS("\x00ff\x00feL ");
5702 #else
5703   /* In UTF-8, y-diaeresis is 0xc3 0xbf, lowercase thorn is 0xc3 0xbe */
5704   const XML_Char *expected = XCS("\xc3\xbf\xc3\xbeL ");
5705 #endif
5706   CharData storage;
5707 
5708   CharData_Init(&storage);
5709   test_data.storage = &storage;
5710   XML_SetExternalEntityRefHandler(g_parser, external_entity_loader2);
5711   XML_SetUserData(g_parser, &test_data);
5712   XML_SetCharacterDataHandler(g_parser, ext2_accumulate_characters);
5713   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
5714       == XML_STATUS_ERROR)
5715     xml_failure(g_parser);
5716   CharData_CheckXMLChars(&storage, expected);
5717 }
5718 END_TEST
5719 
5720 START_TEST(test_ext_entity_latin1_utf16be_bom) {
5721   const char *text = "<!DOCTYPE doc [\n"
5722                      "  <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n"
5723                      "]>\n"
5724                      "<doc>&en;</doc>";
5725   ExtTest2 test_data
5726       = {/* If UTF-16, 0xfeff is the BOM and 0x204c is black left bullet */
5727          /* If Latin-1, 0xff = Y-diaeresis, 0xfe = lowercase thorn,
5728           *   0x4c = L and 0x20 is a space
5729           */
5730          "\xfe\xff\x20\x4c", 4, XCS("iso-8859-1"), NULL, EE_PARSE_NONE};
5731 #ifdef XML_UNICODE
5732   const XML_Char *expected = XCS("\x00fe\x00ff L");
5733 #else
5734   /* In UTF-8, y-diaeresis is 0xc3 0xbf, lowercase thorn is 0xc3 0xbe */
5735   const XML_Char *expected = XCS("\xc3\xbe\xc3\xbf L");
5736 #endif
5737   CharData storage;
5738 
5739   CharData_Init(&storage);
5740   test_data.storage = &storage;
5741   XML_SetExternalEntityRefHandler(g_parser, external_entity_loader2);
5742   XML_SetUserData(g_parser, &test_data);
5743   XML_SetCharacterDataHandler(g_parser, ext2_accumulate_characters);
5744   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
5745       == XML_STATUS_ERROR)
5746     xml_failure(g_parser);
5747   CharData_CheckXMLChars(&storage, expected);
5748 }
5749 END_TEST
5750 
5751 /* Parsing the full buffer rather than a byte at a time makes a
5752  * difference to the encoding scanning code, so repeat the above tests
5753  * without breaking them down by byte.
5754  */
5755 START_TEST(test_ext_entity_latin1_utf16le_bom2) {
5756   const char *text = "<!DOCTYPE doc [\n"
5757                      "  <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n"
5758                      "]>\n"
5759                      "<doc>&en;</doc>";
5760   ExtTest2 test_data
5761       = {/* If UTF-16, 0xfeff is the BOM and 0x204c is black left bullet */
5762          /* If Latin-1, 0xff = Y-diaeresis, 0xfe = lowercase thorn,
5763           *   0x4c = L and 0x20 is a space
5764           */
5765          "\xff\xfe\x4c\x20", 4, XCS("iso-8859-1"), NULL, EE_PARSE_FULL_BUFFER};
5766 #ifdef XML_UNICODE
5767   const XML_Char *expected = XCS("\x00ff\x00feL ");
5768 #else
5769   /* In UTF-8, y-diaeresis is 0xc3 0xbf, lowercase thorn is 0xc3 0xbe */
5770   const XML_Char *expected = XCS("\xc3\xbf\xc3\xbeL ");
5771 #endif
5772   CharData storage;
5773 
5774   CharData_Init(&storage);
5775   test_data.storage = &storage;
5776   XML_SetExternalEntityRefHandler(g_parser, external_entity_loader2);
5777   XML_SetUserData(g_parser, &test_data);
5778   XML_SetCharacterDataHandler(g_parser, ext2_accumulate_characters);
5779   if (XML_Parse(g_parser, text, (int)strlen(text), XML_TRUE)
5780       == XML_STATUS_ERROR)
5781     xml_failure(g_parser);
5782   CharData_CheckXMLChars(&storage, expected);
5783 }
5784 END_TEST
5785 
5786 START_TEST(test_ext_entity_latin1_utf16be_bom2) {
5787   const char *text = "<!DOCTYPE doc [\n"
5788                      "  <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n"
5789                      "]>\n"
5790                      "<doc>&en;</doc>";
5791   ExtTest2 test_data
5792       = {/* If UTF-16, 0xfeff is the BOM and 0x204c is black left bullet */
5793          /* If Latin-1, 0xff = Y-diaeresis, 0xfe = lowercase thorn,
5794           *   0x4c = L and 0x20 is a space
5795           */
5796          "\xfe\xff\x20\x4c", 4, XCS("iso-8859-1"), NULL, EE_PARSE_FULL_BUFFER};
5797 #ifdef XML_UNICODE
5798   const XML_Char *expected = XCS("\x00fe\x00ff L");
5799 #else
5800   /* In UTF-8, y-diaeresis is 0xc3 0xbf, lowercase thorn is 0xc3 0xbe */
5801   const XML_Char *expected = "\xc3\xbe\xc3\xbf L";
5802 #endif
5803   CharData storage;
5804 
5805   CharData_Init(&storage);
5806   test_data.storage = &storage;
5807   XML_SetExternalEntityRefHandler(g_parser, external_entity_loader2);
5808   XML_SetUserData(g_parser, &test_data);
5809   XML_SetCharacterDataHandler(g_parser, ext2_accumulate_characters);
5810   if (XML_Parse(g_parser, text, (int)strlen(text), XML_TRUE)
5811       == XML_STATUS_ERROR)
5812     xml_failure(g_parser);
5813   CharData_CheckXMLChars(&storage, expected);
5814 }
5815 END_TEST
5816 
5817 /* Test little-endian UTF-16 given an explicit big-endian encoding */
5818 START_TEST(test_ext_entity_utf16_be) {
5819   const char *text = "<!DOCTYPE doc [\n"
5820                      "  <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n"
5821                      "]>\n"
5822                      "<doc>&en;</doc>";
5823   ExtTest2 test_data
5824       = {"<\0e\0/\0>\0", 8, XCS("utf-16be"), NULL, EE_PARSE_NONE};
5825 #ifdef XML_UNICODE
5826   const XML_Char *expected = XCS("\x3c00\x6500\x2f00\x3e00");
5827 #else
5828   const XML_Char *expected = XCS("\xe3\xb0\x80"   /* U+3C00 */
5829                                  "\xe6\x94\x80"   /* U+6500 */
5830                                  "\xe2\xbc\x80"   /* U+2F00 */
5831                                  "\xe3\xb8\x80"); /* U+3E00 */
5832 #endif
5833   CharData storage;
5834 
5835   CharData_Init(&storage);
5836   test_data.storage = &storage;
5837   XML_SetExternalEntityRefHandler(g_parser, external_entity_loader2);
5838   XML_SetUserData(g_parser, &test_data);
5839   XML_SetCharacterDataHandler(g_parser, ext2_accumulate_characters);
5840   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
5841       == XML_STATUS_ERROR)
5842     xml_failure(g_parser);
5843   CharData_CheckXMLChars(&storage, expected);
5844 }
5845 END_TEST
5846 
5847 /* Test big-endian UTF-16 given an explicit little-endian encoding */
5848 START_TEST(test_ext_entity_utf16_le) {
5849   const char *text = "<!DOCTYPE doc [\n"
5850                      "  <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n"
5851                      "]>\n"
5852                      "<doc>&en;</doc>";
5853   ExtTest2 test_data
5854       = {"\0<\0e\0/\0>", 8, XCS("utf-16le"), NULL, EE_PARSE_NONE};
5855 #ifdef XML_UNICODE
5856   const XML_Char *expected = XCS("\x3c00\x6500\x2f00\x3e00");
5857 #else
5858   const XML_Char *expected = XCS("\xe3\xb0\x80"   /* U+3C00 */
5859                                  "\xe6\x94\x80"   /* U+6500 */
5860                                  "\xe2\xbc\x80"   /* U+2F00 */
5861                                  "\xe3\xb8\x80"); /* U+3E00 */
5862 #endif
5863   CharData storage;
5864 
5865   CharData_Init(&storage);
5866   test_data.storage = &storage;
5867   XML_SetExternalEntityRefHandler(g_parser, external_entity_loader2);
5868   XML_SetUserData(g_parser, &test_data);
5869   XML_SetCharacterDataHandler(g_parser, ext2_accumulate_characters);
5870   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
5871       == XML_STATUS_ERROR)
5872     xml_failure(g_parser);
5873   CharData_CheckXMLChars(&storage, expected);
5874 }
5875 END_TEST
5876 
5877 /* Test little-endian UTF-16 given no explicit encoding.
5878  * The existing default encoding (UTF-8) is assumed to hold without a
5879  * BOM to contradict it, so the entity value will in fact provoke an
5880  * error because 0x00 is not a valid XML character.  We parse the
5881  * whole buffer in one go rather than feeding it in byte by byte to
5882  * exercise different code paths in the initial scanning routines.
5883  */
5884 typedef struct ExtFaults2 {
5885   const char *parse_text;
5886   int parse_len;
5887   const char *fail_text;
5888   const XML_Char *encoding;
5889   enum XML_Error error;
5890 } ExtFaults2;
5891 
5892 static int XMLCALL
5893 external_entity_faulter2(XML_Parser parser, const XML_Char *context,
5894                          const XML_Char *base, const XML_Char *systemId,
5895                          const XML_Char *publicId) {
5896   ExtFaults2 *test_data = (ExtFaults2 *)XML_GetUserData(parser);
5897   XML_Parser extparser;
5898 
5899   UNUSED_P(base);
5900   UNUSED_P(systemId);
5901   UNUSED_P(publicId);
5902   extparser = XML_ExternalEntityParserCreate(parser, context, NULL);
5903   if (extparser == NULL)
5904     fail("Could not create external entity parser");
5905   if (test_data->encoding != NULL) {
5906     if (! XML_SetEncoding(extparser, test_data->encoding))
5907       fail("XML_SetEncoding() ignored for external entity");
5908   }
5909   if (XML_Parse(extparser, test_data->parse_text, test_data->parse_len,
5910                 XML_TRUE)
5911       != XML_STATUS_ERROR)
5912     fail(test_data->fail_text);
5913   if (XML_GetErrorCode(extparser) != test_data->error)
5914     xml_failure(extparser);
5915 
5916   XML_ParserFree(extparser);
5917   return XML_STATUS_ERROR;
5918 }
5919 
5920 START_TEST(test_ext_entity_utf16_unknown) {
5921   const char *text = "<!DOCTYPE doc [\n"
5922                      "  <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n"
5923                      "]>\n"
5924                      "<doc>&en;</doc>";
5925   ExtFaults2 test_data
5926       = {"a\0b\0c\0", 6, "Invalid character in entity not faulted", NULL,
5927          XML_ERROR_INVALID_TOKEN};
5928 
5929   XML_SetExternalEntityRefHandler(g_parser, external_entity_faulter2);
5930   XML_SetUserData(g_parser, &test_data);
5931   expect_failure(text, XML_ERROR_EXTERNAL_ENTITY_HANDLING,
5932                  "Invalid character should not have been accepted");
5933 }
5934 END_TEST
5935 
5936 /* Test not-quite-UTF-8 BOM (0xEF 0xBB 0xBF) */
5937 START_TEST(test_ext_entity_utf8_non_bom) {
5938   const char *text = "<!DOCTYPE doc [\n"
5939                      "  <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n"
5940                      "]>\n"
5941                      "<doc>&en;</doc>";
5942   ExtTest2 test_data
5943       = {"\xef\xbb\x80", /* Arabic letter DAD medial form, U+FEC0 */
5944          3, NULL, NULL, EE_PARSE_NONE};
5945 #ifdef XML_UNICODE
5946   const XML_Char *expected = XCS("\xfec0");
5947 #else
5948   const XML_Char *expected = XCS("\xef\xbb\x80");
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 that UTF-8 in a CDATA section is correctly passed through */
5965 START_TEST(test_utf8_in_cdata_section) {
5966   const char *text = "<doc><![CDATA[one \xc3\xa9 two]]></doc>";
5967 #ifdef XML_UNICODE
5968   const XML_Char *expected = XCS("one \x00e9 two");
5969 #else
5970   const XML_Char *expected = XCS("one \xc3\xa9 two");
5971 #endif
5972 
5973   run_character_check(text, expected);
5974 }
5975 END_TEST
5976 
5977 /* Test that little-endian UTF-16 in a CDATA section is handled */
5978 START_TEST(test_utf8_in_cdata_section_2) {
5979   const char *text = "<doc><![CDATA[\xc3\xa9]\xc3\xa9two]]></doc>";
5980 #ifdef XML_UNICODE
5981   const XML_Char *expected = XCS("\x00e9]\x00e9two");
5982 #else
5983   const XML_Char *expected = XCS("\xc3\xa9]\xc3\xa9two");
5984 #endif
5985 
5986   run_character_check(text, expected);
5987 }
5988 END_TEST
5989 
5990 /* Test trailing spaces in elements are accepted */
5991 static void XMLCALL
5992 record_element_end_handler(void *userData, const XML_Char *name) {
5993   CharData *storage = (CharData *)userData;
5994 
5995   CharData_AppendXMLChars(storage, XCS("/"), 1);
5996   CharData_AppendXMLChars(storage, name, -1);
5997 }
5998 
5999 START_TEST(test_trailing_spaces_in_elements) {
6000   const char *text = "<doc   >Hi</doc >";
6001   const XML_Char *expected = XCS("doc/doc");
6002   CharData storage;
6003 
6004   CharData_Init(&storage);
6005   XML_SetElementHandler(g_parser, record_element_start_handler,
6006                         record_element_end_handler);
6007   XML_SetUserData(g_parser, &storage);
6008   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
6009       == XML_STATUS_ERROR)
6010     xml_failure(g_parser);
6011   CharData_CheckXMLChars(&storage, expected);
6012 }
6013 END_TEST
6014 
6015 START_TEST(test_utf16_attribute) {
6016   const char text[] =
6017       /* <d {KHO KHWAI}{CHO CHAN}='a'/>
6018        * where {KHO KHWAI} = U+0E04 = 0xe0 0xb8 0x84 in UTF-8
6019        * and   {CHO CHAN}  = U+0E08 = 0xe0 0xb8 0x88 in UTF-8
6020        */
6021       "<\0d\0 \0\x04\x0e\x08\x0e=\0'\0a\0'\0/\0>\0";
6022   const XML_Char *expected = XCS("a");
6023   CharData storage;
6024 
6025   CharData_Init(&storage);
6026   XML_SetStartElementHandler(g_parser, accumulate_attribute);
6027   XML_SetUserData(g_parser, &storage);
6028   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE)
6029       == XML_STATUS_ERROR)
6030     xml_failure(g_parser);
6031   CharData_CheckXMLChars(&storage, expected);
6032 }
6033 END_TEST
6034 
6035 START_TEST(test_utf16_second_attr) {
6036   /* <d a='1' {KHO KHWAI}{CHO CHAN}='2'/>
6037    * where {KHO KHWAI} = U+0E04 = 0xe0 0xb8 0x84 in UTF-8
6038    * and   {CHO CHAN}  = U+0E08 = 0xe0 0xb8 0x88 in UTF-8
6039    */
6040   const char text[] = "<\0d\0 \0a\0=\0'\0\x31\0'\0 \0"
6041                       "\x04\x0e\x08\x0e=\0'\0\x32\0'\0/\0>\0";
6042   const XML_Char *expected = XCS("1");
6043   CharData storage;
6044 
6045   CharData_Init(&storage);
6046   XML_SetStartElementHandler(g_parser, accumulate_attribute);
6047   XML_SetUserData(g_parser, &storage);
6048   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE)
6049       == XML_STATUS_ERROR)
6050     xml_failure(g_parser);
6051   CharData_CheckXMLChars(&storage, expected);
6052 }
6053 END_TEST
6054 
6055 START_TEST(test_attr_after_solidus) {
6056   const char *text = "<doc attr1='a' / attr2='b'>";
6057 
6058   expect_failure(text, XML_ERROR_INVALID_TOKEN, "Misplaced / not faulted");
6059 }
6060 END_TEST
6061 
6062 static void XMLCALL
6063 accumulate_entity_decl(void *userData, const XML_Char *entityName,
6064                        int is_parameter_entity, const XML_Char *value,
6065                        int value_length, const XML_Char *base,
6066                        const XML_Char *systemId, const XML_Char *publicId,
6067                        const XML_Char *notationName) {
6068   CharData *storage = (CharData *)userData;
6069 
6070   UNUSED_P(is_parameter_entity);
6071   UNUSED_P(base);
6072   UNUSED_P(systemId);
6073   UNUSED_P(publicId);
6074   UNUSED_P(notationName);
6075   CharData_AppendXMLChars(storage, entityName, -1);
6076   CharData_AppendXMLChars(storage, XCS("="), 1);
6077   CharData_AppendXMLChars(storage, value, value_length);
6078   CharData_AppendXMLChars(storage, XCS("\n"), 1);
6079 }
6080 
6081 START_TEST(test_utf16_pe) {
6082   /* <!DOCTYPE doc [
6083    * <!ENTITY % {KHO KHWAI}{CHO CHAN} '<!ELEMENT doc (#PCDATA)>'>
6084    * %{KHO KHWAI}{CHO CHAN};
6085    * ]>
6086    * <doc></doc>
6087    *
6088    * where {KHO KHWAI} = U+0E04 = 0xe0 0xb8 0x84 in UTF-8
6089    * and   {CHO CHAN}  = U+0E08 = 0xe0 0xb8 0x88 in UTF-8
6090    */
6091   const char text[] = "\0<\0!\0D\0O\0C\0T\0Y\0P\0E\0 \0d\0o\0c\0 \0[\0\n"
6092                       "\0<\0!\0E\0N\0T\0I\0T\0Y\0 \0%\0 \x0e\x04\x0e\x08\0 "
6093                       "\0'\0<\0!\0E\0L\0E\0M\0E\0N\0T\0 "
6094                       "\0d\0o\0c\0 \0(\0#\0P\0C\0D\0A\0T\0A\0)\0>\0'\0>\0\n"
6095                       "\0%\x0e\x04\x0e\x08\0;\0\n"
6096                       "\0]\0>\0\n"
6097                       "\0<\0d\0o\0c\0>\0<\0/\0d\0o\0c\0>";
6098 #ifdef XML_UNICODE
6099   const XML_Char *expected = XCS("\x0e04\x0e08=<!ELEMENT doc (#PCDATA)>\n");
6100 #else
6101   const XML_Char *expected
6102       = XCS("\xe0\xb8\x84\xe0\xb8\x88=<!ELEMENT doc (#PCDATA)>\n");
6103 #endif
6104   CharData storage;
6105 
6106   CharData_Init(&storage);
6107   XML_SetUserData(g_parser, &storage);
6108   XML_SetEntityDeclHandler(g_parser, accumulate_entity_decl);
6109   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE)
6110       == XML_STATUS_ERROR)
6111     xml_failure(g_parser);
6112   CharData_CheckXMLChars(&storage, expected);
6113 }
6114 END_TEST
6115 
6116 /* Test that duff attribute description keywords are rejected */
6117 START_TEST(test_bad_attr_desc_keyword) {
6118   const char *text = "<!DOCTYPE doc [\n"
6119                      "  <!ATTLIST doc attr CDATA #!IMPLIED>\n"
6120                      "]>\n"
6121                      "<doc />";
6122 
6123   expect_failure(text, XML_ERROR_INVALID_TOKEN,
6124                  "Bad keyword !IMPLIED not faulted");
6125 }
6126 END_TEST
6127 
6128 /* Test that an invalid attribute description keyword consisting of
6129  * UTF-16 characters with their top bytes non-zero are correctly
6130  * faulted
6131  */
6132 START_TEST(test_bad_attr_desc_keyword_utf16) {
6133   /* <!DOCTYPE d [
6134    * <!ATTLIST d a CDATA #{KHO KHWAI}{CHO CHAN}>
6135    * ]><d/>
6136    *
6137    * where {KHO KHWAI} = U+0E04 = 0xe0 0xb8 0x84 in UTF-8
6138    * and   {CHO CHAN}  = U+0E08 = 0xe0 0xb8 0x88 in UTF-8
6139    */
6140   const char text[]
6141       = "\0<\0!\0D\0O\0C\0T\0Y\0P\0E\0 \0d\0 \0[\0\n"
6142         "\0<\0!\0A\0T\0T\0L\0I\0S\0T\0 \0d\0 \0a\0 \0C\0D\0A\0T\0A\0 "
6143         "\0#\x0e\x04\x0e\x08\0>\0\n"
6144         "\0]\0>\0<\0d\0/\0>";
6145 
6146   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE)
6147       != XML_STATUS_ERROR)
6148     fail("Invalid UTF16 attribute keyword not faulted");
6149   if (XML_GetErrorCode(g_parser) != XML_ERROR_SYNTAX)
6150     xml_failure(g_parser);
6151 }
6152 END_TEST
6153 
6154 /* Test that invalid syntax in a <!DOCTYPE> is rejected.  Do this
6155  * using prefix-encoding (see above) to trigger specific code paths
6156  */
6157 START_TEST(test_bad_doctype) {
6158   const char *text = "<?xml version='1.0' encoding='prefix-conv'?>\n"
6159                      "<!DOCTYPE doc [ \x80\x44 ]><doc/>";
6160 
6161   XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL);
6162   expect_failure(text, XML_ERROR_SYNTAX,
6163                  "Invalid bytes in DOCTYPE not faulted");
6164 }
6165 END_TEST
6166 
6167 START_TEST(test_bad_doctype_utf16) {
6168   const char text[] =
6169       /* <!DOCTYPE doc [ \x06f2 ]><doc/>
6170        *
6171        * U+06F2 = EXTENDED ARABIC-INDIC DIGIT TWO, a valid number
6172        * (name character) but not a valid letter (name start character)
6173        */
6174       "\0<\0!\0D\0O\0C\0T\0Y\0P\0E\0 \0d\0o\0c\0 \0[\0 "
6175       "\x06\xf2"
6176       "\0 \0]\0>\0<\0d\0o\0c\0/\0>";
6177 
6178   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE)
6179       != XML_STATUS_ERROR)
6180     fail("Invalid bytes in DOCTYPE not faulted");
6181   if (XML_GetErrorCode(g_parser) != XML_ERROR_SYNTAX)
6182     xml_failure(g_parser);
6183 }
6184 END_TEST
6185 
6186 START_TEST(test_bad_doctype_plus) {
6187   const char *text = "<!DOCTYPE 1+ [ <!ENTITY foo 'bar'> ]>\n"
6188                      "<1+>&foo;</1+>";
6189 
6190   expect_failure(text, XML_ERROR_INVALID_TOKEN,
6191                  "'+' in document name not faulted");
6192 }
6193 END_TEST
6194 
6195 START_TEST(test_bad_doctype_star) {
6196   const char *text = "<!DOCTYPE 1* [ <!ENTITY foo 'bar'> ]>\n"
6197                      "<1*>&foo;</1*>";
6198 
6199   expect_failure(text, XML_ERROR_INVALID_TOKEN,
6200                  "'*' in document name not faulted");
6201 }
6202 END_TEST
6203 
6204 START_TEST(test_bad_doctype_query) {
6205   const char *text = "<!DOCTYPE 1? [ <!ENTITY foo 'bar'> ]>\n"
6206                      "<1?>&foo;</1?>";
6207 
6208   expect_failure(text, XML_ERROR_INVALID_TOKEN,
6209                  "'?' in document name not faulted");
6210 }
6211 END_TEST
6212 
6213 START_TEST(test_unknown_encoding_bad_ignore) {
6214   const char *text = "<?xml version='1.0' encoding='prefix-conv'?>"
6215                      "<!DOCTYPE doc SYSTEM 'foo'>"
6216                      "<doc><e>&entity;</e></doc>";
6217   ExtFaults fault = {"<![IGNORE[<!ELEMENT \xffG (#PCDATA)*>]]>",
6218                      "Invalid character not faulted", XCS("prefix-conv"),
6219                      XML_ERROR_INVALID_TOKEN};
6220 
6221   XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL);
6222   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
6223   XML_SetExternalEntityRefHandler(g_parser, external_entity_faulter);
6224   XML_SetUserData(g_parser, &fault);
6225   expect_failure(text, XML_ERROR_EXTERNAL_ENTITY_HANDLING,
6226                  "Bad IGNORE section with unknown encoding not failed");
6227 }
6228 END_TEST
6229 
6230 START_TEST(test_entity_in_utf16_be_attr) {
6231   const char text[] =
6232       /* <e a='&#228; &#x00E4;'></e> */
6233       "\0<\0e\0 \0a\0=\0'\0&\0#\0\x32\0\x32\0\x38\0;\0 "
6234       "\0&\0#\0x\0\x30\0\x30\0E\0\x34\0;\0'\0>\0<\0/\0e\0>";
6235 #ifdef XML_UNICODE
6236   const XML_Char *expected = XCS("\x00e4 \x00e4");
6237 #else
6238   const XML_Char *expected = XCS("\xc3\xa4 \xc3\xa4");
6239 #endif
6240   CharData storage;
6241 
6242   CharData_Init(&storage);
6243   XML_SetUserData(g_parser, &storage);
6244   XML_SetStartElementHandler(g_parser, accumulate_attribute);
6245   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE)
6246       == XML_STATUS_ERROR)
6247     xml_failure(g_parser);
6248   CharData_CheckXMLChars(&storage, expected);
6249 }
6250 END_TEST
6251 
6252 START_TEST(test_entity_in_utf16_le_attr) {
6253   const char text[] =
6254       /* <e a='&#228; &#x00E4;'></e> */
6255       "<\0e\0 \0a\0=\0'\0&\0#\0\x32\0\x32\0\x38\0;\0 \0"
6256       "&\0#\0x\0\x30\0\x30\0E\0\x34\0;\0'\0>\0<\0/\0e\0>\0";
6257 #ifdef XML_UNICODE
6258   const XML_Char *expected = XCS("\x00e4 \x00e4");
6259 #else
6260   const XML_Char *expected = XCS("\xc3\xa4 \xc3\xa4");
6261 #endif
6262   CharData storage;
6263 
6264   CharData_Init(&storage);
6265   XML_SetUserData(g_parser, &storage);
6266   XML_SetStartElementHandler(g_parser, accumulate_attribute);
6267   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE)
6268       == XML_STATUS_ERROR)
6269     xml_failure(g_parser);
6270   CharData_CheckXMLChars(&storage, expected);
6271 }
6272 END_TEST
6273 
6274 START_TEST(test_entity_public_utf16_be) {
6275   const char text[] =
6276       /* <!DOCTYPE d [ */
6277       "\0<\0!\0D\0O\0C\0T\0Y\0P\0E\0 \0d\0 \0[\0\n"
6278       /* <!ENTITY % e PUBLIC 'foo' 'bar.ent'> */
6279       "\0<\0!\0E\0N\0T\0I\0T\0Y\0 \0%\0 \0e\0 \0P\0U\0B\0L\0I\0C\0 "
6280       "\0'\0f\0o\0o\0'\0 \0'\0b\0a\0r\0.\0e\0n\0t\0'\0>\0\n"
6281       /* %e; */
6282       "\0%\0e\0;\0\n"
6283       /* ]> */
6284       "\0]\0>\0\n"
6285       /* <d>&j;</d> */
6286       "\0<\0d\0>\0&\0j\0;\0<\0/\0d\0>";
6287   ExtTest2 test_data = {/* <!ENTITY j 'baz'> */
6288                         "\0<\0!\0E\0N\0T\0I\0T\0Y\0 \0j\0 \0'\0b\0a\0z\0'\0>",
6289                         34, NULL, NULL, EE_PARSE_NONE};
6290   const XML_Char *expected = XCS("baz");
6291   CharData storage;
6292 
6293   CharData_Init(&storage);
6294   test_data.storage = &storage;
6295   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
6296   XML_SetExternalEntityRefHandler(g_parser, external_entity_loader2);
6297   XML_SetUserData(g_parser, &test_data);
6298   XML_SetCharacterDataHandler(g_parser, ext2_accumulate_characters);
6299   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE)
6300       == XML_STATUS_ERROR)
6301     xml_failure(g_parser);
6302   CharData_CheckXMLChars(&storage, expected);
6303 }
6304 END_TEST
6305 
6306 START_TEST(test_entity_public_utf16_le) {
6307   const char text[] =
6308       /* <!DOCTYPE d [ */
6309       "<\0!\0D\0O\0C\0T\0Y\0P\0E\0 \0d\0 \0[\0\n\0"
6310       /* <!ENTITY % e PUBLIC 'foo' 'bar.ent'> */
6311       "<\0!\0E\0N\0T\0I\0T\0Y\0 \0%\0 \0e\0 \0P\0U\0B\0L\0I\0C\0 \0"
6312       "'\0f\0o\0o\0'\0 \0'\0b\0a\0r\0.\0e\0n\0t\0'\0>\0\n\0"
6313       /* %e; */
6314       "%\0e\0;\0\n\0"
6315       /* ]> */
6316       "]\0>\0\n\0"
6317       /* <d>&j;</d> */
6318       "<\0d\0>\0&\0j\0;\0<\0/\0d\0>\0";
6319   ExtTest2 test_data = {/* <!ENTITY j 'baz'> */
6320                         "<\0!\0E\0N\0T\0I\0T\0Y\0 \0j\0 \0'\0b\0a\0z\0'\0>\0",
6321                         34, NULL, NULL, EE_PARSE_NONE};
6322   const XML_Char *expected = XCS("baz");
6323   CharData storage;
6324 
6325   CharData_Init(&storage);
6326   test_data.storage = &storage;
6327   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
6328   XML_SetExternalEntityRefHandler(g_parser, external_entity_loader2);
6329   XML_SetUserData(g_parser, &test_data);
6330   XML_SetCharacterDataHandler(g_parser, ext2_accumulate_characters);
6331   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE)
6332       == XML_STATUS_ERROR)
6333     xml_failure(g_parser);
6334   CharData_CheckXMLChars(&storage, expected);
6335 }
6336 END_TEST
6337 
6338 /* Test that a doctype with neither an internal nor external subset is
6339  * faulted
6340  */
6341 START_TEST(test_short_doctype) {
6342   const char *text = "<!DOCTYPE doc></doc>";
6343   expect_failure(text, XML_ERROR_INVALID_TOKEN,
6344                  "DOCTYPE without subset not rejected");
6345 }
6346 END_TEST
6347 
6348 START_TEST(test_short_doctype_2) {
6349   const char *text = "<!DOCTYPE doc PUBLIC></doc>";
6350   expect_failure(text, XML_ERROR_SYNTAX,
6351                  "DOCTYPE without Public ID not rejected");
6352 }
6353 END_TEST
6354 
6355 START_TEST(test_short_doctype_3) {
6356   const char *text = "<!DOCTYPE doc SYSTEM></doc>";
6357   expect_failure(text, XML_ERROR_SYNTAX,
6358                  "DOCTYPE without System ID not rejected");
6359 }
6360 END_TEST
6361 
6362 START_TEST(test_long_doctype) {
6363   const char *text = "<!DOCTYPE doc PUBLIC 'foo' 'bar' 'baz'></doc>";
6364   expect_failure(text, XML_ERROR_SYNTAX, "DOCTYPE with extra ID not rejected");
6365 }
6366 END_TEST
6367 
6368 START_TEST(test_bad_entity) {
6369   const char *text = "<!DOCTYPE doc [\n"
6370                      "  <!ENTITY foo PUBLIC>\n"
6371                      "]>\n"
6372                      "<doc/>";
6373   expect_failure(text, XML_ERROR_SYNTAX,
6374                  "ENTITY without Public ID is not rejected");
6375 }
6376 END_TEST
6377 
6378 /* Test unquoted value is faulted */
6379 START_TEST(test_bad_entity_2) {
6380   const char *text = "<!DOCTYPE doc [\n"
6381                      "  <!ENTITY % foo bar>\n"
6382                      "]>\n"
6383                      "<doc/>";
6384   expect_failure(text, XML_ERROR_SYNTAX,
6385                  "ENTITY without Public ID is not rejected");
6386 }
6387 END_TEST
6388 
6389 START_TEST(test_bad_entity_3) {
6390   const char *text = "<!DOCTYPE doc [\n"
6391                      "  <!ENTITY % foo PUBLIC>\n"
6392                      "]>\n"
6393                      "<doc/>";
6394   expect_failure(text, XML_ERROR_SYNTAX,
6395                  "Parameter ENTITY without Public ID is not rejected");
6396 }
6397 END_TEST
6398 
6399 START_TEST(test_bad_entity_4) {
6400   const char *text = "<!DOCTYPE doc [\n"
6401                      "  <!ENTITY % foo SYSTEM>\n"
6402                      "]>\n"
6403                      "<doc/>";
6404   expect_failure(text, XML_ERROR_SYNTAX,
6405                  "Parameter ENTITY without Public ID is not rejected");
6406 }
6407 END_TEST
6408 
6409 START_TEST(test_bad_notation) {
6410   const char *text = "<!DOCTYPE doc [\n"
6411                      "  <!NOTATION n SYSTEM>\n"
6412                      "]>\n"
6413                      "<doc/>";
6414   expect_failure(text, XML_ERROR_SYNTAX,
6415                  "Notation without System ID is not rejected");
6416 }
6417 END_TEST
6418 
6419 /* Test for issue #11, wrongly suppressed default handler */
6420 typedef struct default_check {
6421   const XML_Char *expected;
6422   const int expectedLen;
6423   XML_Bool seen;
6424 } DefaultCheck;
6425 
6426 static void XMLCALL
6427 checking_default_handler(void *userData, const XML_Char *s, int len) {
6428   DefaultCheck *data = (DefaultCheck *)userData;
6429   int i;
6430 
6431   for (i = 0; data[i].expected != NULL; i++) {
6432     if (data[i].expectedLen == len
6433         && ! memcmp(data[i].expected, s, len * sizeof(XML_Char))) {
6434       data[i].seen = XML_TRUE;
6435       break;
6436     }
6437   }
6438 }
6439 
6440 START_TEST(test_default_doctype_handler) {
6441   const char *text = "<!DOCTYPE doc PUBLIC 'pubname' 'test.dtd' [\n"
6442                      "  <!ENTITY foo 'bar'>\n"
6443                      "]>\n"
6444                      "<doc>&foo;</doc>";
6445   DefaultCheck test_data[] = {{XCS("'pubname'"), 9, XML_FALSE},
6446                               {XCS("'test.dtd'"), 10, XML_FALSE},
6447                               {NULL, 0, XML_FALSE}};
6448   int i;
6449 
6450   XML_SetUserData(g_parser, &test_data);
6451   XML_SetDefaultHandler(g_parser, checking_default_handler);
6452   XML_SetEntityDeclHandler(g_parser, dummy_entity_decl_handler);
6453   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
6454       == XML_STATUS_ERROR)
6455     xml_failure(g_parser);
6456   for (i = 0; test_data[i].expected != NULL; i++)
6457     if (! test_data[i].seen)
6458       fail("Default handler not run for public !DOCTYPE");
6459 }
6460 END_TEST
6461 
6462 START_TEST(test_empty_element_abort) {
6463   const char *text = "<abort/>";
6464 
6465   XML_SetStartElementHandler(g_parser, start_element_suspender);
6466   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
6467       != XML_STATUS_ERROR)
6468     fail("Expected to error on abort");
6469 }
6470 END_TEST
6471 
6472 /*
6473  * Namespaces tests.
6474  */
6475 
6476 static void
6477 namespace_setup(void) {
6478   g_parser = XML_ParserCreateNS(NULL, XCS(' '));
6479   if (g_parser == NULL)
6480     fail("Parser not created.");
6481 }
6482 
6483 static void
6484 namespace_teardown(void) {
6485   basic_teardown();
6486 }
6487 
6488 /* Check that an element name and attribute name match the expected values.
6489    The expected values are passed as an array reference of string pointers
6490    provided as the userData argument; the first is the expected
6491    element name, and the second is the expected attribute name.
6492 */
6493 static int triplet_start_flag = XML_FALSE;
6494 static int triplet_end_flag = XML_FALSE;
6495 
6496 static void XMLCALL
6497 triplet_start_checker(void *userData, const XML_Char *name,
6498                       const XML_Char **atts) {
6499   XML_Char **elemstr = (XML_Char **)userData;
6500   char buffer[1024];
6501   if (xcstrcmp(elemstr[0], name) != 0) {
6502     sprintf(buffer, "unexpected start string: '%" XML_FMT_STR "'", name);
6503     fail(buffer);
6504   }
6505   if (xcstrcmp(elemstr[1], atts[0]) != 0) {
6506     sprintf(buffer, "unexpected attribute string: '%" XML_FMT_STR "'", atts[0]);
6507     fail(buffer);
6508   }
6509   triplet_start_flag = XML_TRUE;
6510 }
6511 
6512 /* Check that the element name passed to the end-element handler matches
6513    the expected value.  The expected value is passed as the first element
6514    in an array of strings passed as the userData argument.
6515 */
6516 static void XMLCALL
6517 triplet_end_checker(void *userData, const XML_Char *name) {
6518   XML_Char **elemstr = (XML_Char **)userData;
6519   if (xcstrcmp(elemstr[0], name) != 0) {
6520     char buffer[1024];
6521     sprintf(buffer, "unexpected end string: '%" XML_FMT_STR "'", name);
6522     fail(buffer);
6523   }
6524   triplet_end_flag = XML_TRUE;
6525 }
6526 
6527 START_TEST(test_return_ns_triplet) {
6528   const char *text = "<foo:e xmlns:foo='http://example.org/' bar:a='12'\n"
6529                      "       xmlns:bar='http://example.org/'>";
6530   const char *epilog = "</foo:e>";
6531   const XML_Char *elemstr[]
6532       = {XCS("http://example.org/ e foo"), XCS("http://example.org/ a bar")};
6533   XML_SetReturnNSTriplet(g_parser, XML_TRUE);
6534   XML_SetUserData(g_parser, (void *)elemstr);
6535   XML_SetElementHandler(g_parser, triplet_start_checker, triplet_end_checker);
6536   XML_SetNamespaceDeclHandler(g_parser, dummy_start_namespace_decl_handler,
6537                               dummy_end_namespace_decl_handler);
6538   triplet_start_flag = XML_FALSE;
6539   triplet_end_flag = XML_FALSE;
6540   dummy_handler_flags = 0;
6541   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_FALSE)
6542       == XML_STATUS_ERROR)
6543     xml_failure(g_parser);
6544   if (! triplet_start_flag)
6545     fail("triplet_start_checker not invoked");
6546   /* Check that unsetting "return triplets" fails while still parsing */
6547   XML_SetReturnNSTriplet(g_parser, XML_FALSE);
6548   if (_XML_Parse_SINGLE_BYTES(g_parser, epilog, (int)strlen(epilog), XML_TRUE)
6549       == XML_STATUS_ERROR)
6550     xml_failure(g_parser);
6551   if (! triplet_end_flag)
6552     fail("triplet_end_checker not invoked");
6553   if (dummy_handler_flags
6554       != (DUMMY_START_NS_DECL_HANDLER_FLAG | DUMMY_END_NS_DECL_HANDLER_FLAG))
6555     fail("Namespace handlers not called");
6556 }
6557 END_TEST
6558 
6559 static void XMLCALL
6560 overwrite_start_checker(void *userData, const XML_Char *name,
6561                         const XML_Char **atts) {
6562   CharData *storage = (CharData *)userData;
6563   CharData_AppendXMLChars(storage, XCS("start "), 6);
6564   CharData_AppendXMLChars(storage, name, -1);
6565   while (*atts != NULL) {
6566     CharData_AppendXMLChars(storage, XCS("\nattribute "), 11);
6567     CharData_AppendXMLChars(storage, *atts, -1);
6568     atts += 2;
6569   }
6570   CharData_AppendXMLChars(storage, XCS("\n"), 1);
6571 }
6572 
6573 static void XMLCALL
6574 overwrite_end_checker(void *userData, const XML_Char *name) {
6575   CharData *storage = (CharData *)userData;
6576   CharData_AppendXMLChars(storage, XCS("end "), 4);
6577   CharData_AppendXMLChars(storage, name, -1);
6578   CharData_AppendXMLChars(storage, XCS("\n"), 1);
6579 }
6580 
6581 static void
6582 run_ns_tagname_overwrite_test(const char *text, const XML_Char *result) {
6583   CharData storage;
6584   CharData_Init(&storage);
6585   XML_SetUserData(g_parser, &storage);
6586   XML_SetElementHandler(g_parser, overwrite_start_checker,
6587                         overwrite_end_checker);
6588   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
6589       == XML_STATUS_ERROR)
6590     xml_failure(g_parser);
6591   CharData_CheckXMLChars(&storage, result);
6592 }
6593 
6594 /* Regression test for SF bug #566334. */
6595 START_TEST(test_ns_tagname_overwrite) {
6596   const char *text = "<n:e xmlns:n='http://example.org/'>\n"
6597                      "  <n:f n:attr='foo'/>\n"
6598                      "  <n:g n:attr2='bar'/>\n"
6599                      "</n:e>";
6600   const XML_Char *result = XCS("start http://example.org/ e\n")
6601       XCS("start http://example.org/ f\n")
6602           XCS("attribute http://example.org/ attr\n")
6603               XCS("end http://example.org/ f\n")
6604                   XCS("start http://example.org/ g\n")
6605                       XCS("attribute http://example.org/ attr2\n")
6606                           XCS("end http://example.org/ g\n")
6607                               XCS("end http://example.org/ e\n");
6608   run_ns_tagname_overwrite_test(text, result);
6609 }
6610 END_TEST
6611 
6612 /* Regression test for SF bug #566334. */
6613 START_TEST(test_ns_tagname_overwrite_triplet) {
6614   const char *text = "<n:e xmlns:n='http://example.org/'>\n"
6615                      "  <n:f n:attr='foo'/>\n"
6616                      "  <n:g n:attr2='bar'/>\n"
6617                      "</n:e>";
6618   const XML_Char *result = XCS("start http://example.org/ e n\n")
6619       XCS("start http://example.org/ f n\n")
6620           XCS("attribute http://example.org/ attr n\n")
6621               XCS("end http://example.org/ f n\n")
6622                   XCS("start http://example.org/ g n\n")
6623                       XCS("attribute http://example.org/ attr2 n\n")
6624                           XCS("end http://example.org/ g n\n")
6625                               XCS("end http://example.org/ e n\n");
6626   XML_SetReturnNSTriplet(g_parser, XML_TRUE);
6627   run_ns_tagname_overwrite_test(text, result);
6628 }
6629 END_TEST
6630 
6631 /* Regression test for SF bug #620343. */
6632 static void XMLCALL
6633 start_element_fail(void *userData, const XML_Char *name,
6634                    const XML_Char **atts) {
6635   UNUSED_P(userData);
6636   UNUSED_P(name);
6637   UNUSED_P(atts);
6638 
6639   /* We should never get here. */
6640   fail("should never reach start_element_fail()");
6641 }
6642 
6643 static void XMLCALL
6644 start_ns_clearing_start_element(void *userData, const XML_Char *prefix,
6645                                 const XML_Char *uri) {
6646   UNUSED_P(prefix);
6647   UNUSED_P(uri);
6648   XML_SetStartElementHandler((XML_Parser)userData, NULL);
6649 }
6650 
6651 START_TEST(test_start_ns_clears_start_element) {
6652   /* This needs to use separate start/end tags; using the empty tag
6653      syntax doesn't cause the problematic path through Expat to be
6654      taken.
6655   */
6656   const char *text = "<e xmlns='http://example.org/'></e>";
6657 
6658   XML_SetStartElementHandler(g_parser, start_element_fail);
6659   XML_SetStartNamespaceDeclHandler(g_parser, start_ns_clearing_start_element);
6660   XML_SetEndNamespaceDeclHandler(g_parser, dummy_end_namespace_decl_handler);
6661   XML_UseParserAsHandlerArg(g_parser);
6662   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
6663       == XML_STATUS_ERROR)
6664     xml_failure(g_parser);
6665 }
6666 END_TEST
6667 
6668 /* Regression test for SF bug #616863. */
6669 static int XMLCALL
6670 external_entity_handler(XML_Parser parser, const XML_Char *context,
6671                         const XML_Char *base, const XML_Char *systemId,
6672                         const XML_Char *publicId) {
6673   intptr_t callno = 1 + (intptr_t)XML_GetUserData(parser);
6674   const char *text;
6675   XML_Parser p2;
6676 
6677   UNUSED_P(base);
6678   UNUSED_P(systemId);
6679   UNUSED_P(publicId);
6680   if (callno == 1)
6681     text = ("<!ELEMENT doc (e+)>\n"
6682             "<!ATTLIST doc xmlns CDATA #IMPLIED>\n"
6683             "<!ELEMENT e EMPTY>\n");
6684   else
6685     text = ("<?xml version='1.0' encoding='us-ascii'?>"
6686             "<e/>");
6687 
6688   XML_SetUserData(parser, (void *)callno);
6689   p2 = XML_ExternalEntityParserCreate(parser, context, NULL);
6690   if (_XML_Parse_SINGLE_BYTES(p2, text, (int)strlen(text), XML_TRUE)
6691       == XML_STATUS_ERROR) {
6692     xml_failure(p2);
6693     return XML_STATUS_ERROR;
6694   }
6695   XML_ParserFree(p2);
6696   return XML_STATUS_OK;
6697 }
6698 
6699 START_TEST(test_default_ns_from_ext_subset_and_ext_ge) {
6700   const char *text = "<?xml version='1.0'?>\n"
6701                      "<!DOCTYPE doc SYSTEM 'http://example.org/doc.dtd' [\n"
6702                      "  <!ENTITY en SYSTEM 'http://example.org/entity.ent'>\n"
6703                      "]>\n"
6704                      "<doc xmlns='http://example.org/ns1'>\n"
6705                      "&en;\n"
6706                      "</doc>";
6707 
6708   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
6709   XML_SetExternalEntityRefHandler(g_parser, external_entity_handler);
6710   /* We actually need to set this handler to tickle this bug. */
6711   XML_SetStartElementHandler(g_parser, dummy_start_element);
6712   XML_SetUserData(g_parser, NULL);
6713   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
6714       == XML_STATUS_ERROR)
6715     xml_failure(g_parser);
6716 }
6717 END_TEST
6718 
6719 /* Regression test #1 for SF bug #673791. */
6720 START_TEST(test_ns_prefix_with_empty_uri_1) {
6721   const char *text = "<doc xmlns:prefix='http://example.org/'>\n"
6722                      "  <e xmlns:prefix=''/>\n"
6723                      "</doc>";
6724 
6725   expect_failure(text, XML_ERROR_UNDECLARING_PREFIX,
6726                  "Did not report re-setting namespace"
6727                  " URI with prefix to ''.");
6728 }
6729 END_TEST
6730 
6731 /* Regression test #2 for SF bug #673791. */
6732 START_TEST(test_ns_prefix_with_empty_uri_2) {
6733   const char *text = "<?xml version='1.0'?>\n"
6734                      "<docelem xmlns:pre=''/>";
6735 
6736   expect_failure(text, XML_ERROR_UNDECLARING_PREFIX,
6737                  "Did not report setting namespace URI with prefix to ''.");
6738 }
6739 END_TEST
6740 
6741 /* Regression test #3 for SF bug #673791. */
6742 START_TEST(test_ns_prefix_with_empty_uri_3) {
6743   const char *text = "<!DOCTYPE doc [\n"
6744                      "  <!ELEMENT doc EMPTY>\n"
6745                      "  <!ATTLIST doc\n"
6746                      "    xmlns:prefix CDATA ''>\n"
6747                      "]>\n"
6748                      "<doc/>";
6749 
6750   expect_failure(text, XML_ERROR_UNDECLARING_PREFIX,
6751                  "Didn't report attr default setting NS w/ prefix to ''.");
6752 }
6753 END_TEST
6754 
6755 /* Regression test #4 for SF bug #673791. */
6756 START_TEST(test_ns_prefix_with_empty_uri_4) {
6757   const char *text = "<!DOCTYPE doc [\n"
6758                      "  <!ELEMENT prefix:doc EMPTY>\n"
6759                      "  <!ATTLIST prefix:doc\n"
6760                      "    xmlns:prefix CDATA 'http://example.org/'>\n"
6761                      "]>\n"
6762                      "<prefix:doc/>";
6763   /* Packaged info expected by the end element handler;
6764      the weird structuring lets us re-use the triplet_end_checker()
6765      function also used for another test. */
6766   const XML_Char *elemstr[] = {XCS("http://example.org/ doc prefix")};
6767   XML_SetReturnNSTriplet(g_parser, XML_TRUE);
6768   XML_SetUserData(g_parser, (void *)elemstr);
6769   XML_SetEndElementHandler(g_parser, triplet_end_checker);
6770   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
6771       == XML_STATUS_ERROR)
6772     xml_failure(g_parser);
6773 }
6774 END_TEST
6775 
6776 /* Test with non-xmlns prefix */
6777 START_TEST(test_ns_unbound_prefix) {
6778   const char *text = "<!DOCTYPE doc [\n"
6779                      "  <!ELEMENT prefix:doc EMPTY>\n"
6780                      "  <!ATTLIST prefix:doc\n"
6781                      "    notxmlns:prefix CDATA 'http://example.org/'>\n"
6782                      "]>\n"
6783                      "<prefix:doc/>";
6784 
6785   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
6786       != XML_STATUS_ERROR)
6787     fail("Unbound prefix incorrectly passed");
6788   if (XML_GetErrorCode(g_parser) != XML_ERROR_UNBOUND_PREFIX)
6789     xml_failure(g_parser);
6790 }
6791 END_TEST
6792 
6793 START_TEST(test_ns_default_with_empty_uri) {
6794   const char *text = "<doc xmlns='http://example.org/'>\n"
6795                      "  <e xmlns=''/>\n"
6796                      "</doc>";
6797   /* Add some handlers to exercise extra code paths */
6798   XML_SetStartNamespaceDeclHandler(g_parser,
6799                                    dummy_start_namespace_decl_handler);
6800   XML_SetEndNamespaceDeclHandler(g_parser, dummy_end_namespace_decl_handler);
6801   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
6802       == XML_STATUS_ERROR)
6803     xml_failure(g_parser);
6804 }
6805 END_TEST
6806 
6807 /* Regression test for SF bug #692964: two prefixes for one namespace. */
6808 START_TEST(test_ns_duplicate_attrs_diff_prefixes) {
6809   const char *text = "<doc xmlns:a='http://example.org/a'\n"
6810                      "     xmlns:b='http://example.org/a'\n"
6811                      "     a:a='v' b:a='v' />";
6812   expect_failure(text, XML_ERROR_DUPLICATE_ATTRIBUTE,
6813                  "did not report multiple attributes with same URI+name");
6814 }
6815 END_TEST
6816 
6817 START_TEST(test_ns_duplicate_hashes) {
6818   /* The hash of an attribute is calculated as the hash of its URI
6819    * concatenated with a space followed by its name (after the
6820    * colon).  We wish to generate attributes with the same hash
6821    * value modulo the attribute table size so that we can check that
6822    * the attribute hash table works correctly.  The attribute hash
6823    * table size will be the smallest power of two greater than the
6824    * number of attributes, but at least eight.  There is
6825    * unfortunately no programmatic way of getting the hash or the
6826    * table size at user level, but the test code coverage percentage
6827    * will drop if the hashes cease to point to the same row.
6828    *
6829    * The cunning plan is to have few enough attributes to have a
6830    * reliable table size of 8, and have the single letter attribute
6831    * names be 8 characters apart, producing a hash which will be the
6832    * same modulo 8.
6833    */
6834   const char *text = "<doc xmlns:a='http://example.org/a'\n"
6835                      "     a:a='v' a:i='w' />";
6836   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
6837       == XML_STATUS_ERROR)
6838     xml_failure(g_parser);
6839 }
6840 END_TEST
6841 
6842 /* Regression test for SF bug #695401: unbound prefix. */
6843 START_TEST(test_ns_unbound_prefix_on_attribute) {
6844   const char *text = "<doc a:attr=''/>";
6845   expect_failure(text, XML_ERROR_UNBOUND_PREFIX,
6846                  "did not report unbound prefix on attribute");
6847 }
6848 END_TEST
6849 
6850 /* Regression test for SF bug #695401: unbound prefix. */
6851 START_TEST(test_ns_unbound_prefix_on_element) {
6852   const char *text = "<a:doc/>";
6853   expect_failure(text, XML_ERROR_UNBOUND_PREFIX,
6854                  "did not report unbound prefix on element");
6855 }
6856 END_TEST
6857 
6858 /* Test that the parsing status is correctly reset by XML_ParserReset().
6859  * We usE test_return_ns_triplet() for our example parse to improve
6860  * coverage of tidying up code executed.
6861  */
6862 START_TEST(test_ns_parser_reset) {
6863   XML_ParsingStatus status;
6864 
6865   XML_GetParsingStatus(g_parser, &status);
6866   if (status.parsing != XML_INITIALIZED)
6867     fail("parsing status doesn't start INITIALIZED");
6868   test_return_ns_triplet();
6869   XML_GetParsingStatus(g_parser, &status);
6870   if (status.parsing != XML_FINISHED)
6871     fail("parsing status doesn't end FINISHED");
6872   XML_ParserReset(g_parser, NULL);
6873   XML_GetParsingStatus(g_parser, &status);
6874   if (status.parsing != XML_INITIALIZED)
6875     fail("parsing status doesn't reset to INITIALIZED");
6876 }
6877 END_TEST
6878 
6879 /* Test that long element names with namespaces are handled correctly */
6880 START_TEST(test_ns_long_element) {
6881   const char *text
6882       = "<foo:thisisalongenoughelementnametotriggerareallocation\n"
6883         " xmlns:foo='http://example.org/' bar:a='12'\n"
6884         " xmlns:bar='http://example.org/'>"
6885         "</foo:thisisalongenoughelementnametotriggerareallocation>";
6886   const XML_Char *elemstr[]
6887       = {XCS("http://example.org/")
6888              XCS(" thisisalongenoughelementnametotriggerareallocation foo"),
6889          XCS("http://example.org/ a bar")};
6890 
6891   XML_SetReturnNSTriplet(g_parser, XML_TRUE);
6892   XML_SetUserData(g_parser, (void *)elemstr);
6893   XML_SetElementHandler(g_parser, triplet_start_checker, triplet_end_checker);
6894   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
6895       == XML_STATUS_ERROR)
6896     xml_failure(g_parser);
6897 }
6898 END_TEST
6899 
6900 /* Test mixed population of prefixed and unprefixed attributes */
6901 START_TEST(test_ns_mixed_prefix_atts) {
6902   const char *text = "<e a='12' bar:b='13'\n"
6903                      " xmlns:bar='http://example.org/'>"
6904                      "</e>";
6905 
6906   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
6907       == XML_STATUS_ERROR)
6908     xml_failure(g_parser);
6909 }
6910 END_TEST
6911 
6912 /* Test having a long namespaced element name inside a short one.
6913  * This exercises some internal buffer reallocation that is shared
6914  * across elements with the same namespace URI.
6915  */
6916 START_TEST(test_ns_extend_uri_buffer) {
6917   const char *text = "<foo:e xmlns:foo='http://example.org/'>"
6918                      " <foo:thisisalongenoughnametotriggerallocationaction"
6919                      "   foo:a='12' />"
6920                      "</foo:e>";
6921   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
6922       == XML_STATUS_ERROR)
6923     xml_failure(g_parser);
6924 }
6925 END_TEST
6926 
6927 /* Test that xmlns is correctly rejected as an attribute in the xmlns
6928  * namespace, but not in other namespaces
6929  */
6930 START_TEST(test_ns_reserved_attributes) {
6931   const char *text1
6932       = "<foo:e xmlns:foo='http://example.org/' xmlns:xmlns='12' />";
6933   const char *text2
6934       = "<foo:e xmlns:foo='http://example.org/' foo:xmlns='12' />";
6935   expect_failure(text1, XML_ERROR_RESERVED_PREFIX_XMLNS,
6936                  "xmlns not rejected as an attribute");
6937   XML_ParserReset(g_parser, NULL);
6938   if (_XML_Parse_SINGLE_BYTES(g_parser, text2, (int)strlen(text2), XML_TRUE)
6939       == XML_STATUS_ERROR)
6940     xml_failure(g_parser);
6941 }
6942 END_TEST
6943 
6944 /* Test more reserved attributes */
6945 START_TEST(test_ns_reserved_attributes_2) {
6946   const char *text1 = "<foo:e xmlns:foo='http://example.org/'"
6947                       "  xmlns:xml='http://example.org/' />";
6948   const char *text2
6949       = "<foo:e xmlns:foo='http://www.w3.org/XML/1998/namespace' />";
6950   const char *text3 = "<foo:e xmlns:foo='http://www.w3.org/2000/xmlns/' />";
6951 
6952   expect_failure(text1, XML_ERROR_RESERVED_PREFIX_XML,
6953                  "xml not rejected as an attribute");
6954   XML_ParserReset(g_parser, NULL);
6955   expect_failure(text2, XML_ERROR_RESERVED_NAMESPACE_URI,
6956                  "Use of w3.org URL not faulted");
6957   XML_ParserReset(g_parser, NULL);
6958   expect_failure(text3, XML_ERROR_RESERVED_NAMESPACE_URI,
6959                  "Use of w3.org xmlns URL not faulted");
6960 }
6961 END_TEST
6962 
6963 /* Test string pool handling of namespace names of 2048 characters */
6964 /* Exercises a particular string pool growth path */
6965 START_TEST(test_ns_extremely_long_prefix) {
6966   /* C99 compilers are only required to support 4095-character
6967    * strings, so the following needs to be split in two to be safe
6968    * for all compilers.
6969    */
6970   const char *text1
6971       = "<doc "
6972         /* 64 character on each line */
6973         /* ...gives a total length of 2048 */
6974         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
6975         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
6976         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
6977         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
6978         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
6979         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
6980         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
6981         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
6982         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
6983         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
6984         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
6985         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
6986         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
6987         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
6988         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
6989         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
6990         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
6991         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
6992         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
6993         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
6994         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
6995         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
6996         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
6997         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
6998         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
6999         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7000         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7001         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7002         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7003         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7004         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7005         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7006         ":a='12'";
7007   const char *text2
7008       = " xmlns:"
7009         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7010         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7011         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7012         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7013         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7014         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7015         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7016         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7017         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7018         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7019         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7020         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7021         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7022         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7023         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7024         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7025         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7026         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7027         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7028         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7029         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7030         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7031         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7032         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7033         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7034         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7035         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7036         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7037         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7038         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7039         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7040         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7041         "='foo'\n>"
7042         "</doc>";
7043 
7044   if (_XML_Parse_SINGLE_BYTES(g_parser, text1, (int)strlen(text1), XML_FALSE)
7045       == XML_STATUS_ERROR)
7046     xml_failure(g_parser);
7047   if (_XML_Parse_SINGLE_BYTES(g_parser, text2, (int)strlen(text2), XML_TRUE)
7048       == XML_STATUS_ERROR)
7049     xml_failure(g_parser);
7050 }
7051 END_TEST
7052 
7053 /* Test unknown encoding handlers in namespace setup */
7054 START_TEST(test_ns_unknown_encoding_success) {
7055   const char *text = "<?xml version='1.0' encoding='prefix-conv'?>\n"
7056                      "<foo:e xmlns:foo='http://example.org/'>Hi</foo:e>";
7057 
7058   XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL);
7059   run_character_check(text, XCS("Hi"));
7060 }
7061 END_TEST
7062 
7063 /* Test that too many colons are rejected */
7064 START_TEST(test_ns_double_colon) {
7065   const char *text = "<foo:e xmlns:foo='http://example.org/' foo:a:b='bar' />";
7066   const enum XML_Status status
7067       = _XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE);
7068 #ifdef XML_NS
7069   if ((status == XML_STATUS_OK)
7070       || (XML_GetErrorCode(g_parser) != XML_ERROR_INVALID_TOKEN)) {
7071     fail("Double colon in attribute name not faulted"
7072          " (despite active namespace support)");
7073   }
7074 #else
7075   if (status != XML_STATUS_OK) {
7076     fail("Double colon in attribute name faulted"
7077          " (despite inactive namespace support");
7078   }
7079 #endif
7080 }
7081 END_TEST
7082 
7083 START_TEST(test_ns_double_colon_element) {
7084   const char *text = "<foo:bar:e xmlns:foo='http://example.org/' />";
7085   const enum XML_Status status
7086       = _XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE);
7087 #ifdef XML_NS
7088   if ((status == XML_STATUS_OK)
7089       || (XML_GetErrorCode(g_parser) != XML_ERROR_INVALID_TOKEN)) {
7090     fail("Double colon in element name not faulted"
7091          " (despite active namespace support)");
7092   }
7093 #else
7094   if (status != XML_STATUS_OK) {
7095     fail("Double colon in element name faulted"
7096          " (despite inactive namespace support");
7097   }
7098 #endif
7099 }
7100 END_TEST
7101 
7102 /* Test that non-name characters after a colon are rejected */
7103 START_TEST(test_ns_bad_attr_leafname) {
7104   const char *text = "<foo:e xmlns:foo='http://example.org/' foo:?ar='baz' />";
7105 
7106   expect_failure(text, XML_ERROR_INVALID_TOKEN,
7107                  "Invalid character in leafname not faulted");
7108 }
7109 END_TEST
7110 
7111 START_TEST(test_ns_bad_element_leafname) {
7112   const char *text = "<foo:?oc xmlns:foo='http://example.org/' />";
7113 
7114   expect_failure(text, XML_ERROR_INVALID_TOKEN,
7115                  "Invalid character in element leafname not faulted");
7116 }
7117 END_TEST
7118 
7119 /* Test high-byte-set UTF-16 characters are valid in a leafname */
7120 START_TEST(test_ns_utf16_leafname) {
7121   const char text[] =
7122       /* <n:e xmlns:n='URI' n:{KHO KHWAI}='a' />
7123        * where {KHO KHWAI} = U+0E04 = 0xe0 0xb8 0x84 in UTF-8
7124        */
7125       "<\0n\0:\0e\0 \0x\0m\0l\0n\0s\0:\0n\0=\0'\0U\0R\0I\0'\0 \0"
7126       "n\0:\0\x04\x0e=\0'\0a\0'\0 \0/\0>\0";
7127   const XML_Char *expected = XCS("a");
7128   CharData storage;
7129 
7130   CharData_Init(&storage);
7131   XML_SetStartElementHandler(g_parser, accumulate_attribute);
7132   XML_SetUserData(g_parser, &storage);
7133   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE)
7134       == XML_STATUS_ERROR)
7135     xml_failure(g_parser);
7136   CharData_CheckXMLChars(&storage, expected);
7137 }
7138 END_TEST
7139 
7140 START_TEST(test_ns_utf16_element_leafname) {
7141   const char text[] =
7142       /* <n:{KHO KHWAI} xmlns:n='URI'/>
7143        * where {KHO KHWAI} = U+0E04 = 0xe0 0xb8 0x84 in UTF-8
7144        */
7145       "\0<\0n\0:\x0e\x04\0 \0x\0m\0l\0n\0s\0:\0n\0=\0'\0U\0R\0I\0'\0/\0>";
7146 #ifdef XML_UNICODE
7147   const XML_Char *expected = XCS("URI \x0e04");
7148 #else
7149   const XML_Char *expected = XCS("URI \xe0\xb8\x84");
7150 #endif
7151   CharData storage;
7152 
7153   CharData_Init(&storage);
7154   XML_SetStartElementHandler(g_parser, start_element_event_handler);
7155   XML_SetUserData(g_parser, &storage);
7156   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE)
7157       == XML_STATUS_ERROR)
7158     xml_failure(g_parser);
7159   CharData_CheckXMLChars(&storage, expected);
7160 }
7161 END_TEST
7162 
7163 START_TEST(test_ns_utf16_doctype) {
7164   const char text[] =
7165       /* <!DOCTYPE foo:{KHO KHWAI} [ <!ENTITY bar 'baz'> ]>\n
7166        * where {KHO KHWAI} = U+0E04 = 0xe0 0xb8 0x84 in UTF-8
7167        */
7168       "\0<\0!\0D\0O\0C\0T\0Y\0P\0E\0 \0f\0o\0o\0:\x0e\x04\0 "
7169       "\0[\0 \0<\0!\0E\0N\0T\0I\0T\0Y\0 \0b\0a\0r\0 \0'\0b\0a\0z\0'\0>\0 "
7170       "\0]\0>\0\n"
7171       /* <foo:{KHO KHWAI} xmlns:foo='URI'>&bar;</foo:{KHO KHWAI}> */
7172       "\0<\0f\0o\0o\0:\x0e\x04\0 "
7173       "\0x\0m\0l\0n\0s\0:\0f\0o\0o\0=\0'\0U\0R\0I\0'\0>"
7174       "\0&\0b\0a\0r\0;"
7175       "\0<\0/\0f\0o\0o\0:\x0e\x04\0>";
7176 #ifdef XML_UNICODE
7177   const XML_Char *expected = XCS("URI \x0e04");
7178 #else
7179   const XML_Char *expected = XCS("URI \xe0\xb8\x84");
7180 #endif
7181   CharData storage;
7182 
7183   CharData_Init(&storage);
7184   XML_SetUserData(g_parser, &storage);
7185   XML_SetStartElementHandler(g_parser, start_element_event_handler);
7186   XML_SetUnknownEncodingHandler(g_parser, MiscEncodingHandler, NULL);
7187   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE)
7188       == XML_STATUS_ERROR)
7189     xml_failure(g_parser);
7190   CharData_CheckXMLChars(&storage, expected);
7191 }
7192 END_TEST
7193 
7194 START_TEST(test_ns_invalid_doctype) {
7195   const char *text = "<!DOCTYPE foo:!bad [ <!ENTITY bar 'baz' ]>\n"
7196                      "<foo:!bad>&bar;</foo:!bad>";
7197 
7198   expect_failure(text, XML_ERROR_INVALID_TOKEN,
7199                  "Invalid character in document local name not faulted");
7200 }
7201 END_TEST
7202 
7203 START_TEST(test_ns_double_colon_doctype) {
7204   const char *text = "<!DOCTYPE foo:a:doc [ <!ENTITY bar 'baz' ]>\n"
7205                      "<foo:a:doc>&bar;</foo:a:doc>";
7206 
7207   expect_failure(text, XML_ERROR_SYNTAX,
7208                  "Double colon in document name not faulted");
7209 }
7210 END_TEST
7211 
7212 /* Control variable; the number of times duff_allocator() will successfully
7213  * allocate */
7214 #define ALLOC_ALWAYS_SUCCEED (-1)
7215 #define REALLOC_ALWAYS_SUCCEED (-1)
7216 
7217 static intptr_t allocation_count = ALLOC_ALWAYS_SUCCEED;
7218 static intptr_t reallocation_count = REALLOC_ALWAYS_SUCCEED;
7219 
7220 /* Crocked allocator for allocation failure tests */
7221 static void *
7222 duff_allocator(size_t size) {
7223   if (allocation_count == 0)
7224     return NULL;
7225   if (allocation_count != ALLOC_ALWAYS_SUCCEED)
7226     allocation_count--;
7227   return malloc(size);
7228 }
7229 
7230 /* Crocked reallocator for allocation failure tests */
7231 static void *
7232 duff_reallocator(void *ptr, size_t size) {
7233   if (reallocation_count == 0)
7234     return NULL;
7235   if (reallocation_count != REALLOC_ALWAYS_SUCCEED)
7236     reallocation_count--;
7237   return realloc(ptr, size);
7238 }
7239 
7240 /* Test that a failure to allocate the parser structure fails gracefully */
7241 START_TEST(test_misc_alloc_create_parser) {
7242   XML_Memory_Handling_Suite memsuite = {duff_allocator, realloc, free};
7243   unsigned int i;
7244   const unsigned int max_alloc_count = 10;
7245 
7246   /* Something this simple shouldn't need more than 10 allocations */
7247   for (i = 0; i < max_alloc_count; i++) {
7248     allocation_count = i;
7249     g_parser = XML_ParserCreate_MM(NULL, &memsuite, NULL);
7250     if (g_parser != NULL)
7251       break;
7252   }
7253   if (i == 0)
7254     fail("Parser unexpectedly ignored failing allocator");
7255   else if (i == max_alloc_count)
7256     fail("Parser not created with max allocation count");
7257 }
7258 END_TEST
7259 
7260 /* Test memory allocation failures for a parser with an encoding */
7261 START_TEST(test_misc_alloc_create_parser_with_encoding) {
7262   XML_Memory_Handling_Suite memsuite = {duff_allocator, realloc, free};
7263   unsigned int i;
7264   const unsigned int max_alloc_count = 10;
7265 
7266   /* Try several levels of allocation */
7267   for (i = 0; i < max_alloc_count; i++) {
7268     allocation_count = i;
7269     g_parser = XML_ParserCreate_MM(XCS("us-ascii"), &memsuite, NULL);
7270     if (g_parser != NULL)
7271       break;
7272   }
7273   if (i == 0)
7274     fail("Parser ignored failing allocator");
7275   else if (i == max_alloc_count)
7276     fail("Parser not created with max allocation count");
7277 }
7278 END_TEST
7279 
7280 /* Test that freeing a NULL parser doesn't cause an explosion.
7281  * (Not actually tested anywhere else)
7282  */
7283 START_TEST(test_misc_null_parser) {
7284   XML_ParserFree(NULL);
7285 }
7286 END_TEST
7287 
7288 /* Test that XML_ErrorString rejects out-of-range codes */
7289 START_TEST(test_misc_error_string) {
7290   if (XML_ErrorString((enum XML_Error) - 1) != NULL)
7291     fail("Negative error code not rejected");
7292   if (XML_ErrorString((enum XML_Error)100) != NULL)
7293     fail("Large error code not rejected");
7294 }
7295 END_TEST
7296 
7297 /* Test the version information is consistent */
7298 
7299 /* Since we are working in XML_LChars (potentially 16-bits), we
7300  * can't use the standard C library functions for character
7301  * manipulation and have to roll our own.
7302  */
7303 static int
7304 parse_version(const XML_LChar *version_text,
7305               XML_Expat_Version *version_struct) {
7306   if (! version_text)
7307     return XML_FALSE;
7308 
7309   while (*version_text != 0x00) {
7310     if (*version_text >= ASCII_0 && *version_text <= ASCII_9)
7311       break;
7312     version_text++;
7313   }
7314   if (*version_text == 0x00)
7315     return XML_FALSE;
7316 
7317   /* version_struct->major = strtoul(version_text, 10, &version_text) */
7318   version_struct->major = 0;
7319   while (*version_text >= ASCII_0 && *version_text <= ASCII_9) {
7320     version_struct->major
7321         = 10 * version_struct->major + (*version_text++ - ASCII_0);
7322   }
7323   if (*version_text++ != ASCII_PERIOD)
7324     return XML_FALSE;
7325 
7326   /* Now for the minor version number */
7327   version_struct->minor = 0;
7328   while (*version_text >= ASCII_0 && *version_text <= ASCII_9) {
7329     version_struct->minor
7330         = 10 * version_struct->minor + (*version_text++ - ASCII_0);
7331   }
7332   if (*version_text++ != ASCII_PERIOD)
7333     return XML_FALSE;
7334 
7335   /* Finally the micro version number */
7336   version_struct->micro = 0;
7337   while (*version_text >= ASCII_0 && *version_text <= ASCII_9) {
7338     version_struct->micro
7339         = 10 * version_struct->micro + (*version_text++ - ASCII_0);
7340   }
7341   if (*version_text != 0x00)
7342     return XML_FALSE;
7343   return XML_TRUE;
7344 }
7345 
7346 static int
7347 versions_equal(const XML_Expat_Version *first,
7348                const XML_Expat_Version *second) {
7349   return (first->major == second->major && first->minor == second->minor
7350           && first->micro == second->micro);
7351 }
7352 
7353 START_TEST(test_misc_version) {
7354   XML_Expat_Version read_version = XML_ExpatVersionInfo();
7355   /* Silence compiler warning with the following assignment */
7356   XML_Expat_Version parsed_version = {0, 0, 0};
7357   const XML_LChar *version_text = XML_ExpatVersion();
7358 
7359   if (version_text == NULL)
7360     fail("Could not obtain version text");
7361   assert(version_text != NULL);
7362   if (! parse_version(version_text, &parsed_version))
7363     fail("Unable to parse version text");
7364   if (! versions_equal(&read_version, &parsed_version))
7365     fail("Version mismatch");
7366 
7367 #if ! defined(XML_UNICODE) || defined(XML_UNICODE_WCHAR_T)
7368   if (xcstrcmp(version_text, XCS("expat_2.2.10"))) /* needs bump on releases */
7369     fail("XML_*_VERSION in expat.h out of sync?\n");
7370 #else
7371   /* If we have XML_UNICODE defined but not XML_UNICODE_WCHAR_T
7372    * then XML_LChar is defined as char, for some reason.
7373    */
7374   if (strcmp(version_text, "expat_2.2.5")) /* needs bump on releases */
7375     fail("XML_*_VERSION in expat.h out of sync?\n");
7376 #endif /* ! defined(XML_UNICODE) || defined(XML_UNICODE_WCHAR_T) */
7377 }
7378 END_TEST
7379 
7380 /* Test feature information */
7381 START_TEST(test_misc_features) {
7382   const XML_Feature *features = XML_GetFeatureList();
7383 
7384   /* Prevent problems with double-freeing parsers */
7385   g_parser = NULL;
7386   if (features == NULL) {
7387     fail("Failed to get feature information");
7388   } else {
7389     /* Loop through the features checking what we can */
7390     while (features->feature != XML_FEATURE_END) {
7391       switch (features->feature) {
7392       case XML_FEATURE_SIZEOF_XML_CHAR:
7393         if (features->value != sizeof(XML_Char))
7394           fail("Incorrect size of XML_Char");
7395         break;
7396       case XML_FEATURE_SIZEOF_XML_LCHAR:
7397         if (features->value != sizeof(XML_LChar))
7398           fail("Incorrect size of XML_LChar");
7399         break;
7400       default:
7401         break;
7402       }
7403       features++;
7404     }
7405   }
7406 }
7407 END_TEST
7408 
7409 /* Regression test for GitHub Issue #17: memory leak parsing attribute
7410  * values with mixed bound and unbound namespaces.
7411  */
7412 START_TEST(test_misc_attribute_leak) {
7413   const char *text = "<D xmlns:L=\"D\" l:a='' L:a=''/>";
7414   XML_Memory_Handling_Suite memsuite
7415       = {tracking_malloc, tracking_realloc, tracking_free};
7416 
7417   g_parser = XML_ParserCreate_MM(XCS("UTF-8"), &memsuite, XCS("\n"));
7418   expect_failure(text, XML_ERROR_UNBOUND_PREFIX, "Unbound prefixes not found");
7419   XML_ParserFree(g_parser);
7420   /* Prevent the teardown trying to double free */
7421   g_parser = NULL;
7422 
7423   if (! tracking_report())
7424     fail("Memory leak found");
7425 }
7426 END_TEST
7427 
7428 /* Test parser created for UTF-16LE is successful */
7429 START_TEST(test_misc_utf16le) {
7430   const char text[] =
7431       /* <?xml version='1.0'?><q>Hi</q> */
7432       "<\0?\0x\0m\0l\0 \0"
7433       "v\0e\0r\0s\0i\0o\0n\0=\0'\0\x31\0.\0\x30\0'\0?\0>\0"
7434       "<\0q\0>\0H\0i\0<\0/\0q\0>\0";
7435   const XML_Char *expected = XCS("Hi");
7436   CharData storage;
7437 
7438   g_parser = XML_ParserCreate(XCS("UTF-16LE"));
7439   if (g_parser == NULL)
7440     fail("Parser not created");
7441 
7442   CharData_Init(&storage);
7443   XML_SetUserData(g_parser, &storage);
7444   XML_SetCharacterDataHandler(g_parser, accumulate_characters);
7445   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)sizeof(text) - 1, XML_TRUE)
7446       == XML_STATUS_ERROR)
7447     xml_failure(g_parser);
7448   CharData_CheckXMLChars(&storage, expected);
7449 }
7450 END_TEST
7451 
7452 typedef struct {
7453   XML_Parser parser;
7454   int deep;
7455 } DataIssue240;
7456 
7457 static void
7458 start_element_issue_240(void *userData, const XML_Char *name,
7459                         const XML_Char **atts) {
7460   DataIssue240 *mydata = (DataIssue240 *)userData;
7461   UNUSED_P(name);
7462   UNUSED_P(atts);
7463   mydata->deep++;
7464 }
7465 
7466 static void
7467 end_element_issue_240(void *userData, const XML_Char *name) {
7468   DataIssue240 *mydata = (DataIssue240 *)userData;
7469 
7470   UNUSED_P(name);
7471   mydata->deep--;
7472   if (mydata->deep == 0) {
7473     XML_StopParser(mydata->parser, 0);
7474   }
7475 }
7476 
7477 START_TEST(test_misc_stop_during_end_handler_issue_240_1) {
7478   XML_Parser parser;
7479   DataIssue240 *mydata;
7480   enum XML_Status result;
7481   const char *const doc1 = "<doc><e1/><e><foo/></e></doc>";
7482 
7483   parser = XML_ParserCreate(NULL);
7484   XML_SetElementHandler(parser, start_element_issue_240, end_element_issue_240);
7485   mydata = (DataIssue240 *)malloc(sizeof(DataIssue240));
7486   mydata->parser = parser;
7487   mydata->deep = 0;
7488   XML_SetUserData(parser, mydata);
7489 
7490   result = XML_Parse(parser, doc1, (int)strlen(doc1), 1);
7491   XML_ParserFree(parser);
7492   free(mydata);
7493   if (result != XML_STATUS_ERROR)
7494     fail("Stopping the parser did not work as expected");
7495 }
7496 END_TEST
7497 
7498 START_TEST(test_misc_stop_during_end_handler_issue_240_2) {
7499   XML_Parser parser;
7500   DataIssue240 *mydata;
7501   enum XML_Status result;
7502   const char *const doc2 = "<doc><elem/></doc>";
7503 
7504   parser = XML_ParserCreate(NULL);
7505   XML_SetElementHandler(parser, start_element_issue_240, end_element_issue_240);
7506   mydata = (DataIssue240 *)malloc(sizeof(DataIssue240));
7507   mydata->parser = parser;
7508   mydata->deep = 0;
7509   XML_SetUserData(parser, mydata);
7510 
7511   result = XML_Parse(parser, doc2, (int)strlen(doc2), 1);
7512   XML_ParserFree(parser);
7513   free(mydata);
7514   if (result != XML_STATUS_ERROR)
7515     fail("Stopping the parser did not work as expected");
7516 }
7517 END_TEST
7518 
7519 START_TEST(test_misc_deny_internal_entity_closing_doctype_issue_317) {
7520   const char *const inputOne = "<!DOCTYPE d [\n"
7521                                "<!ENTITY % e ']><d/>'>\n"
7522                                "\n"
7523                                "%e;";
7524   const char *const inputTwo = "<!DOCTYPE d [\n"
7525                                "<!ENTITY % e1 ']><d/>'><!ENTITY % e2 '&e1;'>\n"
7526                                "\n"
7527                                "%e2;";
7528   const char *const inputThree = "<!DOCTYPE d [\n"
7529                                  "<!ENTITY % e ']><d'>\n"
7530                                  "\n"
7531                                  "%e;";
7532   const char *const inputIssue317 = "<!DOCTYPE doc [\n"
7533                                     "<!ENTITY % foo ']>\n"
7534                                     "<doc>Hell<oc (#PCDATA)*>'>\n"
7535                                     "%foo;\n"
7536                                     "]>\n"
7537                                     "<doc>Hello, world</dVc>";
7538 
7539   const char *const inputs[] = {inputOne, inputTwo, inputThree, inputIssue317};
7540   size_t inputIndex = 0;
7541 
7542   for (; inputIndex < sizeof(inputs) / sizeof(inputs[0]); inputIndex++) {
7543     XML_Parser parser;
7544     enum XML_Status parseResult;
7545     int setParamEntityResult;
7546     XML_Size lineNumber;
7547     XML_Size columnNumber;
7548     const char *const input = inputs[inputIndex];
7549 
7550     parser = XML_ParserCreate(NULL);
7551     setParamEntityResult
7552         = XML_SetParamEntityParsing(parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
7553     if (setParamEntityResult != 1)
7554       fail("Failed to set XML_PARAM_ENTITY_PARSING_ALWAYS.");
7555 
7556     parseResult = XML_Parse(parser, input, (int)strlen(input), 0);
7557     if (parseResult != XML_STATUS_ERROR) {
7558       parseResult = XML_Parse(parser, "", 0, 1);
7559       if (parseResult != XML_STATUS_ERROR) {
7560         fail("Parsing was expected to fail but succeeded.");
7561       }
7562     }
7563 
7564     if (XML_GetErrorCode(parser) != XML_ERROR_INVALID_TOKEN)
7565       fail("Error code does not match XML_ERROR_INVALID_TOKEN");
7566 
7567     lineNumber = XML_GetCurrentLineNumber(parser);
7568     if (lineNumber != 4)
7569       fail("XML_GetCurrentLineNumber does not work as expected.");
7570 
7571     columnNumber = XML_GetCurrentColumnNumber(parser);
7572     if (columnNumber != 0)
7573       fail("XML_GetCurrentColumnNumber does not work as expected.");
7574 
7575     XML_ParserFree(parser);
7576   }
7577 }
7578 END_TEST
7579 
7580 static void
7581 alloc_setup(void) {
7582   XML_Memory_Handling_Suite memsuite = {duff_allocator, duff_reallocator, free};
7583 
7584   /* Ensure the parser creation will go through */
7585   allocation_count = ALLOC_ALWAYS_SUCCEED;
7586   reallocation_count = REALLOC_ALWAYS_SUCCEED;
7587   g_parser = XML_ParserCreate_MM(NULL, &memsuite, NULL);
7588   if (g_parser == NULL)
7589     fail("Parser not created");
7590 }
7591 
7592 static void
7593 alloc_teardown(void) {
7594   basic_teardown();
7595 }
7596 
7597 /* Test the effects of allocation failures on xml declaration processing */
7598 START_TEST(test_alloc_parse_xdecl) {
7599   const char *text = "<?xml version='1.0' encoding='utf-8'?>\n"
7600                      "<doc>Hello, world</doc>";
7601   int i;
7602   const int max_alloc_count = 15;
7603 
7604   for (i = 0; i < max_alloc_count; i++) {
7605     allocation_count = i;
7606     XML_SetXmlDeclHandler(g_parser, dummy_xdecl_handler);
7607     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
7608         != XML_STATUS_ERROR)
7609       break;
7610     /* Resetting the parser is insufficient, because some memory
7611      * allocations are cached within the parser.  Instead we use
7612      * the teardown and setup routines to ensure that we have the
7613      * right sort of parser back in our hands.
7614      */
7615     alloc_teardown();
7616     alloc_setup();
7617   }
7618   if (i == 0)
7619     fail("Parse succeeded despite failing allocator");
7620   if (i == max_alloc_count)
7621     fail("Parse failed with max allocations");
7622 }
7623 END_TEST
7624 
7625 /* As above, but with an encoding big enough to cause storing the
7626  * version information to expand the string pool being used.
7627  */
7628 static int XMLCALL
7629 long_encoding_handler(void *userData, const XML_Char *encoding,
7630                       XML_Encoding *info) {
7631   int i;
7632 
7633   UNUSED_P(userData);
7634   UNUSED_P(encoding);
7635   for (i = 0; i < 256; i++)
7636     info->map[i] = i;
7637   info->data = NULL;
7638   info->convert = NULL;
7639   info->release = NULL;
7640   return XML_STATUS_OK;
7641 }
7642 
7643 START_TEST(test_alloc_parse_xdecl_2) {
7644   const char *text
7645       = "<?xml version='1.0' encoding='"
7646         /* Each line is 64 characters */
7647         "ThisIsAStupidlyLongEncodingNameIntendedToTriggerPoolGrowth123456"
7648         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7649         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7650         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7651         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7652         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7653         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7654         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7655         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7656         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7657         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7658         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7659         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7660         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7661         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7662         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMN"
7663         "'?>"
7664         "<doc>Hello, world</doc>";
7665   int i;
7666   const int max_alloc_count = 20;
7667 
7668   for (i = 0; i < max_alloc_count; i++) {
7669     allocation_count = i;
7670     XML_SetXmlDeclHandler(g_parser, dummy_xdecl_handler);
7671     XML_SetUnknownEncodingHandler(g_parser, long_encoding_handler, NULL);
7672     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
7673         != XML_STATUS_ERROR)
7674       break;
7675     /* See comment in test_alloc_parse_xdecl() */
7676     alloc_teardown();
7677     alloc_setup();
7678   }
7679   if (i == 0)
7680     fail("Parse succeeded despite failing allocator");
7681   if (i == max_alloc_count)
7682     fail("Parse failed with max allocations");
7683 }
7684 END_TEST
7685 
7686 /* Test the effects of allocation failures on a straightforward parse */
7687 START_TEST(test_alloc_parse_pi) {
7688   const char *text = "<?xml version='1.0' encoding='utf-8'?>\n"
7689                      "<?pi unknown?>\n"
7690                      "<doc>"
7691                      "Hello, world"
7692                      "</doc>";
7693   int i;
7694   const int max_alloc_count = 15;
7695 
7696   for (i = 0; i < max_alloc_count; i++) {
7697     allocation_count = i;
7698     XML_SetProcessingInstructionHandler(g_parser, dummy_pi_handler);
7699     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
7700         != XML_STATUS_ERROR)
7701       break;
7702     /* See comment in test_alloc_parse_xdecl() */
7703     alloc_teardown();
7704     alloc_setup();
7705   }
7706   if (i == 0)
7707     fail("Parse succeeded despite failing allocator");
7708   if (i == max_alloc_count)
7709     fail("Parse failed with max allocations");
7710 }
7711 END_TEST
7712 
7713 START_TEST(test_alloc_parse_pi_2) {
7714   const char *text = "<?xml version='1.0' encoding='utf-8'?>\n"
7715                      "<doc>"
7716                      "Hello, world"
7717                      "<?pi unknown?>\n"
7718                      "</doc>";
7719   int i;
7720   const int max_alloc_count = 15;
7721 
7722   for (i = 0; i < max_alloc_count; i++) {
7723     allocation_count = i;
7724     XML_SetProcessingInstructionHandler(g_parser, dummy_pi_handler);
7725     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
7726         != XML_STATUS_ERROR)
7727       break;
7728     /* See comment in test_alloc_parse_xdecl() */
7729     alloc_teardown();
7730     alloc_setup();
7731   }
7732   if (i == 0)
7733     fail("Parse succeeded despite failing allocator");
7734   if (i == max_alloc_count)
7735     fail("Parse failed with max allocations");
7736 }
7737 END_TEST
7738 
7739 START_TEST(test_alloc_parse_pi_3) {
7740   const char *text
7741       = "<?"
7742         /* 64 characters per line */
7743         "This processing instruction should be long enough to ensure that"
7744         "it triggers the growth of an internal string pool when the      "
7745         "allocator fails at a cruicial moment FGHIJKLMNOPABCDEFGHIJKLMNOP"
7746         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7747         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7748         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7749         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7750         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7751         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7752         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7753         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7754         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7755         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7756         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7757         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7758         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
7759         "Q?><doc/>";
7760   int i;
7761   const int max_alloc_count = 20;
7762 
7763   for (i = 0; i < max_alloc_count; i++) {
7764     allocation_count = i;
7765     XML_SetProcessingInstructionHandler(g_parser, dummy_pi_handler);
7766     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
7767         != XML_STATUS_ERROR)
7768       break;
7769     /* See comment in test_alloc_parse_xdecl() */
7770     alloc_teardown();
7771     alloc_setup();
7772   }
7773   if (i == 0)
7774     fail("Parse succeeded despite failing allocator");
7775   if (i == max_alloc_count)
7776     fail("Parse failed with max allocations");
7777 }
7778 END_TEST
7779 
7780 START_TEST(test_alloc_parse_comment) {
7781   const char *text = "<?xml version='1.0' encoding='utf-8'?>\n"
7782                      "<!-- Test parsing this comment -->"
7783                      "<doc>Hi</doc>";
7784   int i;
7785   const int max_alloc_count = 15;
7786 
7787   for (i = 0; i < max_alloc_count; i++) {
7788     allocation_count = i;
7789     XML_SetCommentHandler(g_parser, dummy_comment_handler);
7790     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
7791         != XML_STATUS_ERROR)
7792       break;
7793     /* See comment in test_alloc_parse_xdecl() */
7794     alloc_teardown();
7795     alloc_setup();
7796   }
7797   if (i == 0)
7798     fail("Parse succeeded despite failing allocator");
7799   if (i == max_alloc_count)
7800     fail("Parse failed with max allocations");
7801 }
7802 END_TEST
7803 
7804 START_TEST(test_alloc_parse_comment_2) {
7805   const char *text = "<?xml version='1.0' encoding='utf-8'?>\n"
7806                      "<doc>"
7807                      "Hello, world"
7808                      "<!-- Parse this comment too -->"
7809                      "</doc>";
7810   int i;
7811   const int max_alloc_count = 15;
7812 
7813   for (i = 0; i < max_alloc_count; i++) {
7814     allocation_count = i;
7815     XML_SetCommentHandler(g_parser, dummy_comment_handler);
7816     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
7817         != XML_STATUS_ERROR)
7818       break;
7819     /* See comment in test_alloc_parse_xdecl() */
7820     alloc_teardown();
7821     alloc_setup();
7822   }
7823   if (i == 0)
7824     fail("Parse succeeded despite failing allocator");
7825   if (i == max_alloc_count)
7826     fail("Parse failed with max allocations");
7827 }
7828 END_TEST
7829 
7830 static int XMLCALL
7831 external_entity_duff_loader(XML_Parser parser, const XML_Char *context,
7832                             const XML_Char *base, const XML_Char *systemId,
7833                             const XML_Char *publicId) {
7834   XML_Parser new_parser;
7835   unsigned int i;
7836   const unsigned int max_alloc_count = 10;
7837 
7838   UNUSED_P(base);
7839   UNUSED_P(systemId);
7840   UNUSED_P(publicId);
7841   /* Try a few different allocation levels */
7842   for (i = 0; i < max_alloc_count; i++) {
7843     allocation_count = i;
7844     new_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
7845     if (new_parser != NULL) {
7846       XML_ParserFree(new_parser);
7847       break;
7848     }
7849   }
7850   if (i == 0)
7851     fail("External parser creation ignored failing allocator");
7852   else if (i == max_alloc_count)
7853     fail("Extern parser not created with max allocation count");
7854 
7855   /* Make sure other random allocation doesn't now fail */
7856   allocation_count = ALLOC_ALWAYS_SUCCEED;
7857 
7858   /* Make sure the failure code path is executed too */
7859   return XML_STATUS_ERROR;
7860 }
7861 
7862 /* Test that external parser creation running out of memory is
7863  * correctly reported.  Based on the external entity test cases.
7864  */
7865 START_TEST(test_alloc_create_external_parser) {
7866   const char *text = "<?xml version='1.0' encoding='us-ascii'?>\n"
7867                      "<!DOCTYPE doc SYSTEM 'foo'>\n"
7868                      "<doc>&entity;</doc>";
7869   char foo_text[] = "<!ELEMENT doc (#PCDATA)*>";
7870 
7871   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
7872   XML_SetUserData(g_parser, foo_text);
7873   XML_SetExternalEntityRefHandler(g_parser, external_entity_duff_loader);
7874   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
7875       != XML_STATUS_ERROR) {
7876     fail("External parser allocator returned success incorrectly");
7877   }
7878 }
7879 END_TEST
7880 
7881 /* More external parser memory allocation testing */
7882 START_TEST(test_alloc_run_external_parser) {
7883   const char *text = "<?xml version='1.0' encoding='us-ascii'?>\n"
7884                      "<!DOCTYPE doc SYSTEM 'foo'>\n"
7885                      "<doc>&entity;</doc>";
7886   char foo_text[] = "<!ELEMENT doc (#PCDATA)*>";
7887   unsigned int i;
7888   const unsigned int max_alloc_count = 15;
7889 
7890   for (i = 0; i < max_alloc_count; i++) {
7891     XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
7892     XML_SetUserData(g_parser, foo_text);
7893     XML_SetExternalEntityRefHandler(g_parser, external_entity_null_loader);
7894     allocation_count = i;
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("Parsing ignored failing allocator");
7904   else if (i == max_alloc_count)
7905     fail("Parsing failed with allocation count 10");
7906 }
7907 END_TEST
7908 
7909 static int XMLCALL
7910 external_entity_dbl_handler(XML_Parser parser, const XML_Char *context,
7911                             const XML_Char *base, const XML_Char *systemId,
7912                             const XML_Char *publicId) {
7913   intptr_t callno = (intptr_t)XML_GetUserData(parser);
7914   const char *text;
7915   XML_Parser new_parser;
7916   int i;
7917   const int max_alloc_count = 20;
7918 
7919   UNUSED_P(base);
7920   UNUSED_P(systemId);
7921   UNUSED_P(publicId);
7922   if (callno == 0) {
7923     /* First time through, check how many calls to malloc occur */
7924     text = ("<!ELEMENT doc (e+)>\n"
7925             "<!ATTLIST doc xmlns CDATA #IMPLIED>\n"
7926             "<!ELEMENT e EMPTY>\n");
7927     allocation_count = 10000;
7928     new_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
7929     if (new_parser == NULL) {
7930       fail("Unable to allocate first external parser");
7931       return XML_STATUS_ERROR;
7932     }
7933     /* Stash the number of calls in the user data */
7934     XML_SetUserData(parser, (void *)(intptr_t)(10000 - allocation_count));
7935   } else {
7936     text = ("<?xml version='1.0' encoding='us-ascii'?>"
7937             "<e/>");
7938     /* Try at varying levels to exercise more code paths */
7939     for (i = 0; i < max_alloc_count; i++) {
7940       allocation_count = callno + i;
7941       new_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
7942       if (new_parser != NULL)
7943         break;
7944     }
7945     if (i == 0) {
7946       fail("Second external parser unexpectedly created");
7947       XML_ParserFree(new_parser);
7948       return XML_STATUS_ERROR;
7949     } else if (i == max_alloc_count) {
7950       fail("Second external parser not created");
7951       return XML_STATUS_ERROR;
7952     }
7953   }
7954 
7955   allocation_count = ALLOC_ALWAYS_SUCCEED;
7956   if (_XML_Parse_SINGLE_BYTES(new_parser, text, (int)strlen(text), XML_TRUE)
7957       == XML_STATUS_ERROR) {
7958     xml_failure(new_parser);
7959     return XML_STATUS_ERROR;
7960   }
7961   XML_ParserFree(new_parser);
7962   return XML_STATUS_OK;
7963 }
7964 
7965 /* Test that running out of memory in dtdCopy is correctly reported.
7966  * Based on test_default_ns_from_ext_subset_and_ext_ge()
7967  */
7968 START_TEST(test_alloc_dtd_copy_default_atts) {
7969   const char *text = "<?xml version='1.0'?>\n"
7970                      "<!DOCTYPE doc SYSTEM 'http://example.org/doc.dtd' [\n"
7971                      "  <!ENTITY en SYSTEM 'http://example.org/entity.ent'>\n"
7972                      "]>\n"
7973                      "<doc xmlns='http://example.org/ns1'>\n"
7974                      "&en;\n"
7975                      "</doc>";
7976 
7977   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
7978   XML_SetExternalEntityRefHandler(g_parser, external_entity_dbl_handler);
7979   XML_SetUserData(g_parser, NULL);
7980   if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
7981       == XML_STATUS_ERROR)
7982     xml_failure(g_parser);
7983 }
7984 END_TEST
7985 
7986 static int XMLCALL
7987 external_entity_dbl_handler_2(XML_Parser parser, const XML_Char *context,
7988                               const XML_Char *base, const XML_Char *systemId,
7989                               const XML_Char *publicId) {
7990   intptr_t callno = (intptr_t)XML_GetUserData(parser);
7991   const char *text;
7992   XML_Parser new_parser;
7993   enum XML_Status rv;
7994 
7995   UNUSED_P(base);
7996   UNUSED_P(systemId);
7997   UNUSED_P(publicId);
7998   if (callno == 0) {
7999     /* Try different allocation levels for whole exercise */
8000     text = ("<!ELEMENT doc (e+)>\n"
8001             "<!ATTLIST doc xmlns CDATA #IMPLIED>\n"
8002             "<!ELEMENT e EMPTY>\n");
8003     XML_SetUserData(parser, (void *)(intptr_t)1);
8004     new_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
8005     if (new_parser == NULL)
8006       return XML_STATUS_ERROR;
8007     rv = _XML_Parse_SINGLE_BYTES(new_parser, text, (int)strlen(text), XML_TRUE);
8008   } else {
8009     /* Just run through once */
8010     text = ("<?xml version='1.0' encoding='us-ascii'?>"
8011             "<e/>");
8012     new_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
8013     if (new_parser == NULL)
8014       return XML_STATUS_ERROR;
8015     rv = _XML_Parse_SINGLE_BYTES(new_parser, text, (int)strlen(text), XML_TRUE);
8016   }
8017   XML_ParserFree(new_parser);
8018   if (rv == XML_STATUS_ERROR)
8019     return XML_STATUS_ERROR;
8020   return XML_STATUS_OK;
8021 }
8022 
8023 /* Test more external entity allocation failure paths */
8024 START_TEST(test_alloc_external_entity) {
8025   const char *text = "<?xml version='1.0'?>\n"
8026                      "<!DOCTYPE doc SYSTEM 'http://example.org/doc.dtd' [\n"
8027                      "  <!ENTITY en SYSTEM 'http://example.org/entity.ent'>\n"
8028                      "]>\n"
8029                      "<doc xmlns='http://example.org/ns1'>\n"
8030                      "&en;\n"
8031                      "</doc>";
8032   int i;
8033   const int alloc_test_max_repeats = 50;
8034 
8035   for (i = 0; i < alloc_test_max_repeats; i++) {
8036     allocation_count = -1;
8037     XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
8038     XML_SetExternalEntityRefHandler(g_parser, external_entity_dbl_handler_2);
8039     XML_SetUserData(g_parser, NULL);
8040     allocation_count = i;
8041     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
8042         == XML_STATUS_OK)
8043       break;
8044     /* See comment in test_alloc_parse_xdecl() */
8045     alloc_teardown();
8046     alloc_setup();
8047   }
8048   allocation_count = -1;
8049   if (i == 0)
8050     fail("External entity parsed despite duff allocator");
8051   if (i == alloc_test_max_repeats)
8052     fail("External entity not parsed at max allocation count");
8053 }
8054 END_TEST
8055 
8056 /* Test more allocation failure paths */
8057 static int XMLCALL
8058 external_entity_alloc_set_encoding(XML_Parser parser, const XML_Char *context,
8059                                    const XML_Char *base,
8060                                    const XML_Char *systemId,
8061                                    const XML_Char *publicId) {
8062   /* As for external_entity_loader() */
8063   const char *text = "<?xml encoding='iso-8859-3'?>"
8064                      "\xC3\xA9";
8065   XML_Parser ext_parser;
8066   enum XML_Status status;
8067 
8068   UNUSED_P(base);
8069   UNUSED_P(systemId);
8070   UNUSED_P(publicId);
8071   ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
8072   if (ext_parser == NULL)
8073     return XML_STATUS_ERROR;
8074   if (! XML_SetEncoding(ext_parser, XCS("utf-8"))) {
8075     XML_ParserFree(ext_parser);
8076     return XML_STATUS_ERROR;
8077   }
8078   status
8079       = _XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE);
8080   XML_ParserFree(ext_parser);
8081   if (status == XML_STATUS_ERROR)
8082     return XML_STATUS_ERROR;
8083   return XML_STATUS_OK;
8084 }
8085 
8086 START_TEST(test_alloc_ext_entity_set_encoding) {
8087   const char *text = "<!DOCTYPE doc [\n"
8088                      "  <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n"
8089                      "]>\n"
8090                      "<doc>&en;</doc>";
8091   int i;
8092   const int max_allocation_count = 30;
8093 
8094   for (i = 0; i < max_allocation_count; i++) {
8095     XML_SetExternalEntityRefHandler(g_parser,
8096                                     external_entity_alloc_set_encoding);
8097     allocation_count = i;
8098     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
8099         == XML_STATUS_OK)
8100       break;
8101     allocation_count = -1;
8102     /* See comment in test_alloc_parse_xdecl() */
8103     alloc_teardown();
8104     alloc_setup();
8105   }
8106   if (i == 0)
8107     fail("Encoding check succeeded despite failing allocator");
8108   if (i == max_allocation_count)
8109     fail("Encoding failed at max allocation count");
8110 }
8111 END_TEST
8112 
8113 static int XMLCALL
8114 unknown_released_encoding_handler(void *data, const XML_Char *encoding,
8115                                   XML_Encoding *info) {
8116   UNUSED_P(data);
8117   if (! xcstrcmp(encoding, XCS("unsupported-encoding"))) {
8118     int i;
8119 
8120     for (i = 0; i < 256; i++)
8121       info->map[i] = i;
8122     info->data = NULL;
8123     info->convert = NULL;
8124     info->release = dummy_release;
8125     return XML_STATUS_OK;
8126   }
8127   return XML_STATUS_ERROR;
8128 }
8129 
8130 /* Test the effects of allocation failure in internal entities.
8131  * Based on test_unknown_encoding_internal_entity
8132  */
8133 START_TEST(test_alloc_internal_entity) {
8134   const char *text = "<?xml version='1.0' encoding='unsupported-encoding'?>\n"
8135                      "<!DOCTYPE test [<!ENTITY foo 'bar'>]>\n"
8136                      "<test a='&foo;'/>";
8137   unsigned int i;
8138   const unsigned int max_alloc_count = 20;
8139 
8140   for (i = 0; i < max_alloc_count; i++) {
8141     allocation_count = i;
8142     XML_SetUnknownEncodingHandler(g_parser, unknown_released_encoding_handler,
8143                                   NULL);
8144     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
8145         != XML_STATUS_ERROR)
8146       break;
8147     /* See comment in test_alloc_parse_xdecl() */
8148     alloc_teardown();
8149     alloc_setup();
8150   }
8151   if (i == 0)
8152     fail("Internal entity worked despite failing allocations");
8153   else if (i == max_alloc_count)
8154     fail("Internal entity failed at max allocation count");
8155 }
8156 END_TEST
8157 
8158 /* Test the robustness against allocation failure of element handling
8159  * Based on test_dtd_default_handling().
8160  */
8161 START_TEST(test_alloc_dtd_default_handling) {
8162   const char *text = "<!DOCTYPE doc [\n"
8163                      "<!ENTITY e SYSTEM 'http://example.org/e'>\n"
8164                      "<!NOTATION n SYSTEM 'http://example.org/n'>\n"
8165                      "<!ENTITY e1 SYSTEM 'http://example.org/e' NDATA n>\n"
8166                      "<!ELEMENT doc (#PCDATA)>\n"
8167                      "<!ATTLIST doc a CDATA #IMPLIED>\n"
8168                      "<?pi in dtd?>\n"
8169                      "<!--comment in dtd-->\n"
8170                      "]>\n"
8171                      "<doc><![CDATA[text in doc]]></doc>";
8172   const XML_Char *expected = XCS("\n\n\n\n\n\n\n\n\n<doc>text in doc</doc>");
8173   CharData storage;
8174   int i;
8175   const int max_alloc_count = 25;
8176 
8177   for (i = 0; i < max_alloc_count; i++) {
8178     allocation_count = i;
8179     dummy_handler_flags = 0;
8180     XML_SetDefaultHandler(g_parser, accumulate_characters);
8181     XML_SetDoctypeDeclHandler(g_parser, dummy_start_doctype_handler,
8182                               dummy_end_doctype_handler);
8183     XML_SetEntityDeclHandler(g_parser, dummy_entity_decl_handler);
8184     XML_SetNotationDeclHandler(g_parser, dummy_notation_decl_handler);
8185     XML_SetElementDeclHandler(g_parser, dummy_element_decl_handler);
8186     XML_SetAttlistDeclHandler(g_parser, dummy_attlist_decl_handler);
8187     XML_SetProcessingInstructionHandler(g_parser, dummy_pi_handler);
8188     XML_SetCommentHandler(g_parser, dummy_comment_handler);
8189     XML_SetCdataSectionHandler(g_parser, dummy_start_cdata_handler,
8190                                dummy_end_cdata_handler);
8191     XML_SetUnparsedEntityDeclHandler(g_parser,
8192                                      dummy_unparsed_entity_decl_handler);
8193     CharData_Init(&storage);
8194     XML_SetUserData(g_parser, &storage);
8195     XML_SetCharacterDataHandler(g_parser, accumulate_characters);
8196     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
8197         != XML_STATUS_ERROR)
8198       break;
8199     /* See comment in test_alloc_parse_xdecl() */
8200     alloc_teardown();
8201     alloc_setup();
8202   }
8203   if (i == 0)
8204     fail("Default DTD parsed despite allocation failures");
8205   if (i == max_alloc_count)
8206     fail("Default DTD not parsed with maximum alloc count");
8207   CharData_CheckXMLChars(&storage, expected);
8208   if (dummy_handler_flags
8209       != (DUMMY_START_DOCTYPE_HANDLER_FLAG | DUMMY_END_DOCTYPE_HANDLER_FLAG
8210           | DUMMY_ENTITY_DECL_HANDLER_FLAG | DUMMY_NOTATION_DECL_HANDLER_FLAG
8211           | DUMMY_ELEMENT_DECL_HANDLER_FLAG | DUMMY_ATTLIST_DECL_HANDLER_FLAG
8212           | DUMMY_COMMENT_HANDLER_FLAG | DUMMY_PI_HANDLER_FLAG
8213           | DUMMY_START_CDATA_HANDLER_FLAG | DUMMY_END_CDATA_HANDLER_FLAG
8214           | DUMMY_UNPARSED_ENTITY_DECL_HANDLER_FLAG))
8215     fail("Not all handlers were called");
8216 }
8217 END_TEST
8218 
8219 /* Test robustness of XML_SetEncoding() with a failing allocator */
8220 START_TEST(test_alloc_explicit_encoding) {
8221   int i;
8222   const int max_alloc_count = 5;
8223 
8224   for (i = 0; i < max_alloc_count; i++) {
8225     allocation_count = i;
8226     if (XML_SetEncoding(g_parser, XCS("us-ascii")) == XML_STATUS_OK)
8227       break;
8228   }
8229   if (i == 0)
8230     fail("Encoding set despite failing allocator");
8231   else if (i == max_alloc_count)
8232     fail("Encoding not set at max allocation count");
8233 }
8234 END_TEST
8235 
8236 /* Test robustness of XML_SetBase against a failing allocator */
8237 START_TEST(test_alloc_set_base) {
8238   const XML_Char *new_base = XCS("/local/file/name.xml");
8239   int i;
8240   const int max_alloc_count = 5;
8241 
8242   for (i = 0; i < max_alloc_count; i++) {
8243     allocation_count = i;
8244     if (XML_SetBase(g_parser, new_base) == XML_STATUS_OK)
8245       break;
8246   }
8247   if (i == 0)
8248     fail("Base set despite failing allocator");
8249   else if (i == max_alloc_count)
8250     fail("Base not set with max allocation count");
8251 }
8252 END_TEST
8253 
8254 /* Test buffer extension in the face of a duff reallocator */
8255 START_TEST(test_alloc_realloc_buffer) {
8256   const char *text = get_buffer_test_text;
8257   void *buffer;
8258   int i;
8259   const int max_realloc_count = 10;
8260 
8261   /* Get a smallish buffer */
8262   for (i = 0; i < max_realloc_count; i++) {
8263     reallocation_count = i;
8264     buffer = XML_GetBuffer(g_parser, 1536);
8265     if (buffer == NULL)
8266       fail("1.5K buffer reallocation failed");
8267     assert(buffer != NULL);
8268     memcpy(buffer, text, strlen(text));
8269     if (XML_ParseBuffer(g_parser, (int)strlen(text), XML_FALSE)
8270         == XML_STATUS_OK)
8271       break;
8272     /* See comment in test_alloc_parse_xdecl() */
8273     alloc_teardown();
8274     alloc_setup();
8275   }
8276   reallocation_count = -1;
8277   if (i == 0)
8278     fail("Parse succeeded with no reallocation");
8279   else if (i == max_realloc_count)
8280     fail("Parse failed with max reallocation count");
8281 }
8282 END_TEST
8283 
8284 /* Same test for external entity parsers */
8285 static int XMLCALL
8286 external_entity_reallocator(XML_Parser parser, const XML_Char *context,
8287                             const XML_Char *base, const XML_Char *systemId,
8288                             const XML_Char *publicId) {
8289   const char *text = get_buffer_test_text;
8290   XML_Parser ext_parser;
8291   void *buffer;
8292   enum XML_Status status;
8293 
8294   UNUSED_P(base);
8295   UNUSED_P(systemId);
8296   UNUSED_P(publicId);
8297   ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
8298   if (ext_parser == NULL)
8299     fail("Could not create external entity parser");
8300 
8301   reallocation_count = (intptr_t)XML_GetUserData(parser);
8302   buffer = XML_GetBuffer(ext_parser, 1536);
8303   if (buffer == NULL)
8304     fail("Buffer allocation failed");
8305   assert(buffer != NULL);
8306   memcpy(buffer, text, strlen(text));
8307   status = XML_ParseBuffer(ext_parser, (int)strlen(text), XML_FALSE);
8308   reallocation_count = -1;
8309   XML_ParserFree(ext_parser);
8310   return (status == XML_STATUS_OK) ? XML_STATUS_OK : XML_STATUS_ERROR;
8311 }
8312 
8313 START_TEST(test_alloc_ext_entity_realloc_buffer) {
8314   const char *text = "<!DOCTYPE doc [\n"
8315                      "  <!ENTITY en SYSTEM 'http://example.org/dummy.ent'>\n"
8316                      "]>\n"
8317                      "<doc>&en;</doc>";
8318   int i;
8319   const int max_realloc_count = 10;
8320 
8321   for (i = 0; i < max_realloc_count; i++) {
8322     XML_SetExternalEntityRefHandler(g_parser, external_entity_reallocator);
8323     XML_SetUserData(g_parser, (void *)(intptr_t)i);
8324     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
8325         == XML_STATUS_OK)
8326       break;
8327     /* See comment in test_alloc_parse_xdecl() */
8328     alloc_teardown();
8329     alloc_setup();
8330   }
8331   if (i == 0)
8332     fail("Succeeded with no reallocations");
8333   if (i == max_realloc_count)
8334     fail("Failed with max reallocations");
8335 }
8336 END_TEST
8337 
8338 /* Test elements with many attributes are handled correctly */
8339 START_TEST(test_alloc_realloc_many_attributes) {
8340   const char *text = "<!DOCTYPE doc [\n"
8341                      "<!ATTLIST doc za CDATA 'default'>\n"
8342                      "<!ATTLIST doc zb CDATA 'def2'>\n"
8343                      "<!ATTLIST doc zc CDATA 'def3'>\n"
8344                      "]>\n"
8345                      "<doc a='1'"
8346                      "     b='2'"
8347                      "     c='3'"
8348                      "     d='4'"
8349                      "     e='5'"
8350                      "     f='6'"
8351                      "     g='7'"
8352                      "     h='8'"
8353                      "     i='9'"
8354                      "     j='10'"
8355                      "     k='11'"
8356                      "     l='12'"
8357                      "     m='13'"
8358                      "     n='14'"
8359                      "     p='15'"
8360                      "     q='16'"
8361                      "     r='17'"
8362                      "     s='18'>"
8363                      "</doc>";
8364   int i;
8365   const int max_realloc_count = 10;
8366 
8367   for (i = 0; i < max_realloc_count; i++) {
8368     reallocation_count = i;
8369     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
8370         != XML_STATUS_ERROR)
8371       break;
8372     /* See comment in test_alloc_parse_xdecl() */
8373     alloc_teardown();
8374     alloc_setup();
8375   }
8376   if (i == 0)
8377     fail("Parse succeeded despite no reallocations");
8378   if (i == max_realloc_count)
8379     fail("Parse failed at max reallocations");
8380 }
8381 END_TEST
8382 
8383 /* Test handling of a public entity with failing allocator */
8384 START_TEST(test_alloc_public_entity_value) {
8385   const char *text = "<!DOCTYPE doc SYSTEM 'http://example.org/'>\n"
8386                      "<doc></doc>\n";
8387   char dtd_text[]
8388       = "<!ELEMENT doc EMPTY>\n"
8389         "<!ENTITY % e1 PUBLIC 'foo' 'bar.ent'>\n"
8390         "<!ENTITY % "
8391         /* Each line is 64 characters */
8392         "ThisIsAStupidlyLongParameterNameIntendedToTriggerPoolGrowth12345"
8393         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8394         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8395         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8396         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8397         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8398         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8399         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8400         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8401         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8402         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8403         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8404         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8405         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8406         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8407         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8408         " '%e1;'>\n"
8409         "%e1;\n";
8410   int i;
8411   const int max_alloc_count = 50;
8412 
8413   for (i = 0; i < max_alloc_count; i++) {
8414     allocation_count = i;
8415     dummy_handler_flags = 0;
8416     XML_SetUserData(g_parser, dtd_text);
8417     XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
8418     XML_SetExternalEntityRefHandler(g_parser, external_entity_public);
8419     /* Provoke a particular code path */
8420     XML_SetEntityDeclHandler(g_parser, dummy_entity_decl_handler);
8421     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
8422         != XML_STATUS_ERROR)
8423       break;
8424     /* See comment in test_alloc_parse_xdecl() */
8425     alloc_teardown();
8426     alloc_setup();
8427   }
8428   if (i == 0)
8429     fail("Parsing worked despite failing allocation");
8430   if (i == max_alloc_count)
8431     fail("Parsing failed at max allocation count");
8432   if (dummy_handler_flags != DUMMY_ENTITY_DECL_HANDLER_FLAG)
8433     fail("Entity declaration handler not called");
8434 }
8435 END_TEST
8436 
8437 START_TEST(test_alloc_realloc_subst_public_entity_value) {
8438   const char *text = "<!DOCTYPE doc SYSTEM 'http://example.org/'>\n"
8439                      "<doc></doc>\n";
8440   char dtd_text[]
8441       = "<!ELEMENT doc EMPTY>\n"
8442         "<!ENTITY % "
8443         /* Each line is 64 characters */
8444         "ThisIsAStupidlyLongParameterNameIntendedToTriggerPoolGrowth12345"
8445         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8446         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8447         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8448         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8449         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8450         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8451         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8452         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8453         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8454         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8455         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8456         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8457         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8458         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8459         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8460         " PUBLIC 'foo' 'bar.ent'>\n"
8461         "%ThisIsAStupidlyLongParameterNameIntendedToTriggerPoolGrowth12345"
8462         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8463         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8464         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8465         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8466         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8467         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8468         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8469         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8470         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8471         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8472         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8473         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8474         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8475         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8476         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP;";
8477   int i;
8478   const int max_realloc_count = 10;
8479 
8480   for (i = 0; i < max_realloc_count; i++) {
8481     reallocation_count = i;
8482     XML_SetUserData(g_parser, dtd_text);
8483     XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
8484     XML_SetExternalEntityRefHandler(g_parser, external_entity_public);
8485     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
8486         != XML_STATUS_ERROR)
8487       break;
8488     /* See comment in test_alloc_parse_xdecl() */
8489     alloc_teardown();
8490     alloc_setup();
8491   }
8492   if (i == 0)
8493     fail("Parsing worked despite failing reallocation");
8494   if (i == max_realloc_count)
8495     fail("Parsing failed at max reallocation count");
8496 }
8497 END_TEST
8498 
8499 START_TEST(test_alloc_parse_public_doctype) {
8500   const char *text
8501       = "<?xml version='1.0' encoding='utf-8'?>\n"
8502         "<!DOCTYPE doc PUBLIC '"
8503         /* 64 characters per line */
8504         "http://example.com/a/long/enough/name/to/trigger/pool/growth/zz/"
8505         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8506         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8507         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8508         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8509         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8510         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8511         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8512         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8513         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8514         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8515         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8516         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8517         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8518         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8519         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8520         "' 'test'>\n"
8521         "<doc></doc>";
8522   int i;
8523   const int max_alloc_count = 25;
8524 
8525   for (i = 0; i < max_alloc_count; i++) {
8526     allocation_count = i;
8527     dummy_handler_flags = 0;
8528     XML_SetDoctypeDeclHandler(g_parser, dummy_start_doctype_decl_handler,
8529                               dummy_end_doctype_decl_handler);
8530     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
8531         != XML_STATUS_ERROR)
8532       break;
8533     /* See comment in test_alloc_parse_xdecl() */
8534     alloc_teardown();
8535     alloc_setup();
8536   }
8537   if (i == 0)
8538     fail("Parse succeeded despite failing allocator");
8539   if (i == max_alloc_count)
8540     fail("Parse failed at maximum allocation count");
8541   if (dummy_handler_flags
8542       != (DUMMY_START_DOCTYPE_DECL_HANDLER_FLAG
8543           | DUMMY_END_DOCTYPE_DECL_HANDLER_FLAG))
8544     fail("Doctype handler functions not called");
8545 }
8546 END_TEST
8547 
8548 START_TEST(test_alloc_parse_public_doctype_long_name) {
8549   const char *text
8550       = "<?xml version='1.0' encoding='utf-8'?>\n"
8551         "<!DOCTYPE doc PUBLIC 'http://example.com/foo' '"
8552         /* 64 characters per line */
8553         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP"
8554         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP"
8555         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP"
8556         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP"
8557         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP"
8558         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP"
8559         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP"
8560         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP"
8561         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP"
8562         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP"
8563         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP"
8564         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP"
8565         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP"
8566         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP"
8567         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP"
8568         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP"
8569         "'>\n"
8570         "<doc></doc>";
8571   int i;
8572   const int max_alloc_count = 25;
8573 
8574   for (i = 0; i < max_alloc_count; i++) {
8575     allocation_count = i;
8576     XML_SetDoctypeDeclHandler(g_parser, dummy_start_doctype_decl_handler,
8577                               dummy_end_doctype_decl_handler);
8578     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
8579         != XML_STATUS_ERROR)
8580       break;
8581     /* See comment in test_alloc_parse_xdecl() */
8582     alloc_teardown();
8583     alloc_setup();
8584   }
8585   if (i == 0)
8586     fail("Parse succeeded despite failing allocator");
8587   if (i == max_alloc_count)
8588     fail("Parse failed at maximum allocation count");
8589 }
8590 END_TEST
8591 
8592 static int XMLCALL
8593 external_entity_alloc(XML_Parser parser, const XML_Char *context,
8594                       const XML_Char *base, const XML_Char *systemId,
8595                       const XML_Char *publicId) {
8596   const char *text = (const char *)XML_GetUserData(parser);
8597   XML_Parser ext_parser;
8598   int parse_res;
8599 
8600   UNUSED_P(base);
8601   UNUSED_P(systemId);
8602   UNUSED_P(publicId);
8603   ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL);
8604   if (ext_parser == NULL)
8605     return XML_STATUS_ERROR;
8606   parse_res
8607       = _XML_Parse_SINGLE_BYTES(ext_parser, text, (int)strlen(text), XML_TRUE);
8608   XML_ParserFree(ext_parser);
8609   return parse_res;
8610 }
8611 
8612 /* Test foreign DTD handling */
8613 START_TEST(test_alloc_set_foreign_dtd) {
8614   const char *text1 = "<?xml version='1.0' encoding='us-ascii'?>\n"
8615                       "<doc>&entity;</doc>";
8616   char text2[] = "<!ELEMENT doc (#PCDATA)*>";
8617   int i;
8618   const int max_alloc_count = 25;
8619 
8620   for (i = 0; i < max_alloc_count; i++) {
8621     allocation_count = i;
8622     XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
8623     XML_SetUserData(g_parser, &text2);
8624     XML_SetExternalEntityRefHandler(g_parser, external_entity_alloc);
8625     if (XML_UseForeignDTD(g_parser, XML_TRUE) != XML_ERROR_NONE)
8626       fail("Could not set foreign DTD");
8627     if (_XML_Parse_SINGLE_BYTES(g_parser, text1, (int)strlen(text1), XML_TRUE)
8628         != XML_STATUS_ERROR)
8629       break;
8630     /* See comment in test_alloc_parse_xdecl() */
8631     alloc_teardown();
8632     alloc_setup();
8633   }
8634   if (i == 0)
8635     fail("Parse succeeded despite failing allocator");
8636   if (i == max_alloc_count)
8637     fail("Parse failed at maximum allocation count");
8638 }
8639 END_TEST
8640 
8641 /* Test based on ibm/valid/P32/ibm32v04.xml */
8642 START_TEST(test_alloc_attribute_enum_value) {
8643   const char *text = "<?xml version='1.0' standalone='no'?>\n"
8644                      "<!DOCTYPE animal SYSTEM 'test.dtd'>\n"
8645                      "<animal>This is a \n    <a/>  \n\nyellow tiger</animal>";
8646   char dtd_text[] = "<!ELEMENT animal (#PCDATA|a)*>\n"
8647                     "<!ELEMENT a EMPTY>\n"
8648                     "<!ATTLIST animal xml:space (default|preserve) 'preserve'>";
8649   int i;
8650   const int max_alloc_count = 30;
8651 
8652   for (i = 0; i < max_alloc_count; i++) {
8653     allocation_count = i;
8654     XML_SetExternalEntityRefHandler(g_parser, external_entity_alloc);
8655     XML_SetUserData(g_parser, dtd_text);
8656     XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
8657     /* An attribute list handler provokes a different code path */
8658     XML_SetAttlistDeclHandler(g_parser, dummy_attlist_decl_handler);
8659     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
8660         != XML_STATUS_ERROR)
8661       break;
8662     /* See comment in test_alloc_parse_xdecl() */
8663     alloc_teardown();
8664     alloc_setup();
8665   }
8666   if (i == 0)
8667     fail("Parse succeeded despite failing allocator");
8668   if (i == max_alloc_count)
8669     fail("Parse failed at maximum allocation count");
8670 }
8671 END_TEST
8672 
8673 /* Test attribute enums sufficient to overflow the string pool */
8674 START_TEST(test_alloc_realloc_attribute_enum_value) {
8675   const char *text = "<?xml version='1.0' standalone='no'?>\n"
8676                      "<!DOCTYPE animal SYSTEM 'test.dtd'>\n"
8677                      "<animal>This is a yellow tiger</animal>";
8678   /* We wish to define a collection of attribute enums that will
8679    * cause the string pool storing them to have to expand.  This
8680    * means more than 1024 bytes, including the parentheses and
8681    * separator bars.
8682    */
8683   char dtd_text[]
8684       = "<!ELEMENT animal (#PCDATA)*>\n"
8685         "<!ATTLIST animal thing "
8686         "(default"
8687         /* Each line is 64 characters */
8688         "|ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8689         "|BBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8690         "|CBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8691         "|DBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8692         "|EBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8693         "|FBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8694         "|GBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8695         "|HBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8696         "|IBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8697         "|JBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8698         "|KBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8699         "|LBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8700         "|MBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8701         "|NBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8702         "|OBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8703         "|PBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO)"
8704         " 'default'>";
8705   int i;
8706   const int max_realloc_count = 10;
8707 
8708   for (i = 0; i < max_realloc_count; i++) {
8709     reallocation_count = i;
8710     XML_SetExternalEntityRefHandler(g_parser, external_entity_alloc);
8711     XML_SetUserData(g_parser, dtd_text);
8712     XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
8713     /* An attribute list handler provokes a different code path */
8714     XML_SetAttlistDeclHandler(g_parser, dummy_attlist_decl_handler);
8715     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
8716         != XML_STATUS_ERROR)
8717       break;
8718     /* See comment in test_alloc_parse_xdecl() */
8719     alloc_teardown();
8720     alloc_setup();
8721   }
8722   if (i == 0)
8723     fail("Parse succeeded despite failing reallocator");
8724   if (i == max_realloc_count)
8725     fail("Parse failed at maximum reallocation count");
8726 }
8727 END_TEST
8728 
8729 /* Test attribute enums in a #IMPLIED attribute forcing pool growth */
8730 START_TEST(test_alloc_realloc_implied_attribute) {
8731   /* Forcing this particular code path is a balancing act.  The
8732    * addition of the closing parenthesis and terminal NUL must be
8733    * what pushes the string of enums over the 1024-byte limit,
8734    * otherwise a different code path will pick up the realloc.
8735    */
8736   const char *text
8737       = "<!DOCTYPE doc [\n"
8738         "<!ELEMENT doc EMPTY>\n"
8739         "<!ATTLIST doc a "
8740         /* Each line is 64 characters */
8741         "(ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8742         "|BBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8743         "|CBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8744         "|DBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8745         "|EBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8746         "|FBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8747         "|GBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8748         "|HBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8749         "|IBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8750         "|JBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8751         "|KBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8752         "|LBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8753         "|MBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8754         "|NBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8755         "|OBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8756         "|PBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMN)"
8757         " #IMPLIED>\n"
8758         "]><doc/>";
8759   int i;
8760   const int max_realloc_count = 10;
8761 
8762   for (i = 0; i < max_realloc_count; i++) {
8763     reallocation_count = i;
8764     XML_SetAttlistDeclHandler(g_parser, dummy_attlist_decl_handler);
8765     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
8766         != XML_STATUS_ERROR)
8767       break;
8768     /* See comment in test_alloc_parse_xdecl() */
8769     alloc_teardown();
8770     alloc_setup();
8771   }
8772   if (i == 0)
8773     fail("Parse succeeded despite failing reallocator");
8774   if (i == max_realloc_count)
8775     fail("Parse failed at maximum reallocation count");
8776 }
8777 END_TEST
8778 
8779 /* Test attribute enums in a defaulted attribute forcing pool growth */
8780 START_TEST(test_alloc_realloc_default_attribute) {
8781   /* Forcing this particular code path is a balancing act.  The
8782    * addition of the closing parenthesis and terminal NUL must be
8783    * what pushes the string of enums over the 1024-byte limit,
8784    * otherwise a different code path will pick up the realloc.
8785    */
8786   const char *text
8787       = "<!DOCTYPE doc [\n"
8788         "<!ELEMENT doc EMPTY>\n"
8789         "<!ATTLIST doc a "
8790         /* Each line is 64 characters */
8791         "(ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8792         "|BBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8793         "|CBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8794         "|DBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8795         "|EBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8796         "|FBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8797         "|GBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8798         "|HBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8799         "|IBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8800         "|JBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8801         "|KBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8802         "|LBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8803         "|MBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8804         "|NBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8805         "|OBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO"
8806         "|PBCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMN)"
8807         " 'ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNO'"
8808         ">\n]><doc/>";
8809   int i;
8810   const int max_realloc_count = 10;
8811 
8812   for (i = 0; i < max_realloc_count; i++) {
8813     reallocation_count = i;
8814     XML_SetAttlistDeclHandler(g_parser, dummy_attlist_decl_handler);
8815     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
8816         != XML_STATUS_ERROR)
8817       break;
8818     /* See comment in test_alloc_parse_xdecl() */
8819     alloc_teardown();
8820     alloc_setup();
8821   }
8822   if (i == 0)
8823     fail("Parse succeeded despite failing reallocator");
8824   if (i == max_realloc_count)
8825     fail("Parse failed at maximum reallocation count");
8826 }
8827 END_TEST
8828 
8829 /* Test long notation name with dodgy allocator */
8830 START_TEST(test_alloc_notation) {
8831   const char *text
8832       = "<!DOCTYPE doc [\n"
8833         "<!NOTATION "
8834         /* Each line is 64 characters */
8835         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8836         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8837         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8838         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8839         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8840         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8841         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8842         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8843         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8844         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8845         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8846         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8847         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8848         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8849         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8850         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8851         " SYSTEM 'http://example.org/n'>\n"
8852         "<!ENTITY e SYSTEM 'http://example.org/e' NDATA "
8853         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8854         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8855         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8856         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8857         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8858         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8859         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8860         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8861         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8862         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8863         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8864         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8865         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8866         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8867         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8868         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
8869         ">\n"
8870         "<!ELEMENT doc EMPTY>\n"
8871         "]>\n<doc/>";
8872   int i;
8873   const int max_alloc_count = 20;
8874 
8875   for (i = 0; i < max_alloc_count; i++) {
8876     allocation_count = i;
8877     dummy_handler_flags = 0;
8878     XML_SetNotationDeclHandler(g_parser, dummy_notation_decl_handler);
8879     XML_SetEntityDeclHandler(g_parser, dummy_entity_decl_handler);
8880     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
8881         != XML_STATUS_ERROR)
8882       break;
8883     /* See comment in test_alloc_parse_xdecl() */
8884     alloc_teardown();
8885     alloc_setup();
8886   }
8887   if (i == 0)
8888     fail("Parse succeeded despite allocation failures");
8889   if (i == max_alloc_count)
8890     fail("Parse failed at maximum allocation count");
8891   if (dummy_handler_flags
8892       != (DUMMY_ENTITY_DECL_HANDLER_FLAG | DUMMY_NOTATION_DECL_HANDLER_FLAG))
8893     fail("Entity declaration handler not called");
8894 }
8895 END_TEST
8896 
8897 /* Test public notation with dodgy allocator */
8898 START_TEST(test_alloc_public_notation) {
8899   const char *text
8900       = "<!DOCTYPE doc [\n"
8901         "<!NOTATION note PUBLIC '"
8902         /* 64 characters per line */
8903         "http://example.com/a/long/enough/name/to/trigger/pool/growth/zz/"
8904         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8905         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8906         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8907         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8908         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8909         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8910         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8911         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8912         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8913         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8914         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8915         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8916         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8917         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8918         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8919         "' 'foo'>\n"
8920         "<!ENTITY e SYSTEM 'http://example.com/e' NDATA note>\n"
8921         "<!ELEMENT doc EMPTY>\n"
8922         "]>\n<doc/>";
8923   int i;
8924   const int max_alloc_count = 20;
8925 
8926   for (i = 0; i < max_alloc_count; i++) {
8927     allocation_count = i;
8928     dummy_handler_flags = 0;
8929     XML_SetNotationDeclHandler(g_parser, dummy_notation_decl_handler);
8930     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
8931         != XML_STATUS_ERROR)
8932       break;
8933     /* See comment in test_alloc_parse_xdecl() */
8934     alloc_teardown();
8935     alloc_setup();
8936   }
8937   if (i == 0)
8938     fail("Parse succeeded despite allocation failures");
8939   if (i == max_alloc_count)
8940     fail("Parse failed at maximum allocation count");
8941   if (dummy_handler_flags != DUMMY_NOTATION_DECL_HANDLER_FLAG)
8942     fail("Notation handler not called");
8943 }
8944 END_TEST
8945 
8946 /* Test public notation with dodgy allocator */
8947 START_TEST(test_alloc_system_notation) {
8948   const char *text
8949       = "<!DOCTYPE doc [\n"
8950         "<!NOTATION note SYSTEM '"
8951         /* 64 characters per line */
8952         "http://example.com/a/long/enough/name/to/trigger/pool/growth/zz/"
8953         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8954         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8955         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8956         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8957         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8958         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8959         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8960         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8961         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8962         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8963         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8964         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8965         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8966         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8967         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
8968         "'>\n"
8969         "<!ENTITY e SYSTEM 'http://example.com/e' NDATA note>\n"
8970         "<!ELEMENT doc EMPTY>\n"
8971         "]>\n<doc/>";
8972   int i;
8973   const int max_alloc_count = 20;
8974 
8975   for (i = 0; i < max_alloc_count; i++) {
8976     allocation_count = i;
8977     dummy_handler_flags = 0;
8978     XML_SetNotationDeclHandler(g_parser, dummy_notation_decl_handler);
8979     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
8980         != XML_STATUS_ERROR)
8981       break;
8982     /* See comment in test_alloc_parse_xdecl() */
8983     alloc_teardown();
8984     alloc_setup();
8985   }
8986   if (i == 0)
8987     fail("Parse succeeded despite allocation failures");
8988   if (i == max_alloc_count)
8989     fail("Parse failed at maximum allocation count");
8990   if (dummy_handler_flags != DUMMY_NOTATION_DECL_HANDLER_FLAG)
8991     fail("Notation handler not called");
8992 }
8993 END_TEST
8994 
8995 START_TEST(test_alloc_nested_groups) {
8996   const char *text
8997       = "<!DOCTYPE doc [\n"
8998         "<!ELEMENT doc "
8999         /* Sixteen elements per line */
9000         "(e,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,"
9001         "(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?"
9002         "))))))))))))))))))))))))))))))))>\n"
9003         "<!ELEMENT e EMPTY>"
9004         "]>\n"
9005         "<doc><e/></doc>";
9006   CharData storage;
9007   int i;
9008   const int max_alloc_count = 20;
9009 
9010   for (i = 0; i < max_alloc_count; i++) {
9011     allocation_count = i;
9012     CharData_Init(&storage);
9013     XML_SetElementDeclHandler(g_parser, dummy_element_decl_handler);
9014     XML_SetStartElementHandler(g_parser, record_element_start_handler);
9015     XML_SetUserData(g_parser, &storage);
9016     dummy_handler_flags = 0;
9017     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
9018         != XML_STATUS_ERROR)
9019       break;
9020     /* See comment in test_alloc_parse_xdecl() */
9021     alloc_teardown();
9022     alloc_setup();
9023   }
9024 
9025   if (i == 0)
9026     fail("Parse succeeded despite failing reallocator");
9027   if (i == max_alloc_count)
9028     fail("Parse failed at maximum reallocation count");
9029   CharData_CheckXMLChars(&storage, XCS("doce"));
9030   if (dummy_handler_flags != DUMMY_ELEMENT_DECL_HANDLER_FLAG)
9031     fail("Element handler not fired");
9032 }
9033 END_TEST
9034 
9035 START_TEST(test_alloc_realloc_nested_groups) {
9036   const char *text
9037       = "<!DOCTYPE doc [\n"
9038         "<!ELEMENT doc "
9039         /* Sixteen elements per line */
9040         "(e,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,"
9041         "(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?,(e?"
9042         "))))))))))))))))))))))))))))))))>\n"
9043         "<!ELEMENT e EMPTY>"
9044         "]>\n"
9045         "<doc><e/></doc>";
9046   CharData storage;
9047   int i;
9048   const int max_realloc_count = 10;
9049 
9050   for (i = 0; i < max_realloc_count; i++) {
9051     reallocation_count = i;
9052     CharData_Init(&storage);
9053     XML_SetElementDeclHandler(g_parser, dummy_element_decl_handler);
9054     XML_SetStartElementHandler(g_parser, record_element_start_handler);
9055     XML_SetUserData(g_parser, &storage);
9056     dummy_handler_flags = 0;
9057     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
9058         != XML_STATUS_ERROR)
9059       break;
9060     /* See comment in test_alloc_parse_xdecl() */
9061     alloc_teardown();
9062     alloc_setup();
9063   }
9064 
9065   if (i == 0)
9066     fail("Parse succeeded despite failing reallocator");
9067   if (i == max_realloc_count)
9068     fail("Parse failed at maximum reallocation count");
9069   CharData_CheckXMLChars(&storage, XCS("doce"));
9070   if (dummy_handler_flags != DUMMY_ELEMENT_DECL_HANDLER_FLAG)
9071     fail("Element handler not fired");
9072 }
9073 END_TEST
9074 
9075 START_TEST(test_alloc_large_group) {
9076   const char *text = "<!DOCTYPE doc [\n"
9077                      "<!ELEMENT doc ("
9078                      "a1|a2|a3|a4|a5|a6|a7|a8|"
9079                      "b1|b2|b3|b4|b5|b6|b7|b8|"
9080                      "c1|c2|c3|c4|c5|c6|c7|c8|"
9081                      "d1|d2|d3|d4|d5|d6|d7|d8|"
9082                      "e1"
9083                      ")+>\n"
9084                      "]>\n"
9085                      "<doc>\n"
9086                      "<a1/>\n"
9087                      "</doc>\n";
9088   int i;
9089   const int max_alloc_count = 50;
9090 
9091   for (i = 0; i < max_alloc_count; i++) {
9092     allocation_count = i;
9093     XML_SetElementDeclHandler(g_parser, dummy_element_decl_handler);
9094     dummy_handler_flags = 0;
9095     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
9096         != XML_STATUS_ERROR)
9097       break;
9098     /* See comment in test_alloc_parse_xdecl() */
9099     alloc_teardown();
9100     alloc_setup();
9101   }
9102   if (i == 0)
9103     fail("Parse succeeded despite failing allocator");
9104   if (i == max_alloc_count)
9105     fail("Parse failed at maximum allocation count");
9106   if (dummy_handler_flags != DUMMY_ELEMENT_DECL_HANDLER_FLAG)
9107     fail("Element handler flag not raised");
9108 }
9109 END_TEST
9110 
9111 START_TEST(test_alloc_realloc_group_choice) {
9112   const char *text = "<!DOCTYPE doc [\n"
9113                      "<!ELEMENT doc ("
9114                      "a1|a2|a3|a4|a5|a6|a7|a8|"
9115                      "b1|b2|b3|b4|b5|b6|b7|b8|"
9116                      "c1|c2|c3|c4|c5|c6|c7|c8|"
9117                      "d1|d2|d3|d4|d5|d6|d7|d8|"
9118                      "e1"
9119                      ")+>\n"
9120                      "]>\n"
9121                      "<doc>\n"
9122                      "<a1/>\n"
9123                      "<b2 attr='foo'>This is a foo</b2>\n"
9124                      "<c3></c3>\n"
9125                      "</doc>\n";
9126   int i;
9127   const int max_realloc_count = 10;
9128 
9129   for (i = 0; i < max_realloc_count; i++) {
9130     reallocation_count = i;
9131     XML_SetElementDeclHandler(g_parser, dummy_element_decl_handler);
9132     dummy_handler_flags = 0;
9133     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
9134         != XML_STATUS_ERROR)
9135       break;
9136     /* See comment in test_alloc_parse_xdecl() */
9137     alloc_teardown();
9138     alloc_setup();
9139   }
9140   if (i == 0)
9141     fail("Parse succeeded despite failing reallocator");
9142   if (i == max_realloc_count)
9143     fail("Parse failed at maximum reallocation count");
9144   if (dummy_handler_flags != DUMMY_ELEMENT_DECL_HANDLER_FLAG)
9145     fail("Element handler flag not raised");
9146 }
9147 END_TEST
9148 
9149 START_TEST(test_alloc_pi_in_epilog) {
9150   const char *text = "<doc></doc>\n"
9151                      "<?pi in epilog?>";
9152   int i;
9153   const int max_alloc_count = 15;
9154 
9155   for (i = 0; i < max_alloc_count; i++) {
9156     allocation_count = i;
9157     XML_SetProcessingInstructionHandler(g_parser, dummy_pi_handler);
9158     dummy_handler_flags = 0;
9159     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
9160         != XML_STATUS_ERROR)
9161       break;
9162     /* See comment in test_alloc_parse_xdecl() */
9163     alloc_teardown();
9164     alloc_setup();
9165   }
9166   if (i == 0)
9167     fail("Parse completed despite failing allocator");
9168   if (i == max_alloc_count)
9169     fail("Parse failed at maximum allocation count");
9170   if (dummy_handler_flags != DUMMY_PI_HANDLER_FLAG)
9171     fail("Processing instruction handler not invoked");
9172 }
9173 END_TEST
9174 
9175 START_TEST(test_alloc_comment_in_epilog) {
9176   const char *text = "<doc></doc>\n"
9177                      "<!-- comment in epilog -->";
9178   int i;
9179   const int max_alloc_count = 15;
9180 
9181   for (i = 0; i < max_alloc_count; i++) {
9182     allocation_count = i;
9183     XML_SetCommentHandler(g_parser, dummy_comment_handler);
9184     dummy_handler_flags = 0;
9185     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
9186         != XML_STATUS_ERROR)
9187       break;
9188     /* See comment in test_alloc_parse_xdecl() */
9189     alloc_teardown();
9190     alloc_setup();
9191   }
9192   if (i == 0)
9193     fail("Parse completed despite failing allocator");
9194   if (i == max_alloc_count)
9195     fail("Parse failed at maximum allocation count");
9196   if (dummy_handler_flags != DUMMY_COMMENT_HANDLER_FLAG)
9197     fail("Processing instruction handler not invoked");
9198 }
9199 END_TEST
9200 
9201 START_TEST(test_alloc_realloc_long_attribute_value) {
9202   const char *text
9203       = "<!DOCTYPE doc [<!ENTITY foo '"
9204         /* Each line is 64 characters */
9205         "This entity will be substituted as an attribute value, and is   "
9206         "calculated to be exactly long enough that the terminating NUL   "
9207         "that the library adds internally will trigger the string pool to"
9208         "grow. GHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9209         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9210         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9211         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9212         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9213         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9214         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9215         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9216         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9217         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9218         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9219         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9220         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9221         "'>]>\n"
9222         "<doc a='&foo;'></doc>";
9223   int i;
9224   const int max_realloc_count = 10;
9225 
9226   for (i = 0; i < max_realloc_count; i++) {
9227     reallocation_count = i;
9228     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
9229         != XML_STATUS_ERROR)
9230       break;
9231     /* See comment in test_alloc_parse_xdecl() */
9232     alloc_teardown();
9233     alloc_setup();
9234   }
9235   if (i == 0)
9236     fail("Parse succeeded despite failing reallocator");
9237   if (i == max_realloc_count)
9238     fail("Parse failed at maximum reallocation count");
9239 }
9240 END_TEST
9241 
9242 START_TEST(test_alloc_attribute_whitespace) {
9243   const char *text = "<doc a=' '></doc>";
9244   int i;
9245   const int max_alloc_count = 15;
9246 
9247   for (i = 0; i < max_alloc_count; i++) {
9248     allocation_count = i;
9249     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
9250         != XML_STATUS_ERROR)
9251       break;
9252     /* See comment in test_alloc_parse_xdecl() */
9253     alloc_teardown();
9254     alloc_setup();
9255   }
9256   if (i == 0)
9257     fail("Parse succeeded despite failing allocator");
9258   if (i == max_alloc_count)
9259     fail("Parse failed at maximum allocation count");
9260 }
9261 END_TEST
9262 
9263 START_TEST(test_alloc_attribute_predefined_entity) {
9264   const char *text = "<doc a='&amp;'></doc>";
9265   int i;
9266   const int max_alloc_count = 15;
9267 
9268   for (i = 0; i < max_alloc_count; i++) {
9269     allocation_count = i;
9270     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
9271         != XML_STATUS_ERROR)
9272       break;
9273     /* See comment in test_alloc_parse_xdecl() */
9274     alloc_teardown();
9275     alloc_setup();
9276   }
9277   if (i == 0)
9278     fail("Parse succeeded despite failing allocator");
9279   if (i == max_alloc_count)
9280     fail("Parse failed at maximum allocation count");
9281 }
9282 END_TEST
9283 
9284 /* Test that a character reference at the end of a suitably long
9285  * default value for an attribute can trigger pool growth, and recovers
9286  * if the allocator fails on it.
9287  */
9288 START_TEST(test_alloc_long_attr_default_with_char_ref) {
9289   const char *text
9290       = "<!DOCTYPE doc [<!ATTLIST doc a CDATA '"
9291         /* 64 characters per line */
9292         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9293         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9294         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9295         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9296         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9297         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9298         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9299         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9300         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9301         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9302         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9303         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9304         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9305         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9306         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9307         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHI"
9308         "&#x31;'>]>\n"
9309         "<doc/>";
9310   int i;
9311   const int max_alloc_count = 20;
9312 
9313   for (i = 0; i < max_alloc_count; i++) {
9314     allocation_count = i;
9315     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
9316         != XML_STATUS_ERROR)
9317       break;
9318     /* See comment in test_alloc_parse_xdecl() */
9319     alloc_teardown();
9320     alloc_setup();
9321   }
9322   if (i == 0)
9323     fail("Parse succeeded despite failing allocator");
9324   if (i == max_alloc_count)
9325     fail("Parse failed at maximum allocation count");
9326 }
9327 END_TEST
9328 
9329 /* Test that a long character reference substitution triggers a pool
9330  * expansion correctly for an attribute value.
9331  */
9332 START_TEST(test_alloc_long_attr_value) {
9333   const char *text
9334       = "<!DOCTYPE test [<!ENTITY foo '\n"
9335         /* 64 characters per line */
9336         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9337         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9338         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9339         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9340         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9341         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9342         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9343         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9344         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9345         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9346         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9347         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9348         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9349         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9350         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9351         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9352         "'>]>\n"
9353         "<test a='&foo;'/>";
9354   int i;
9355   const int max_alloc_count = 25;
9356 
9357   for (i = 0; i < max_alloc_count; i++) {
9358     allocation_count = i;
9359     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
9360         != XML_STATUS_ERROR)
9361       break;
9362     /* See comment in test_alloc_parse_xdecl() */
9363     alloc_teardown();
9364     alloc_setup();
9365   }
9366   if (i == 0)
9367     fail("Parse succeeded despite failing allocator");
9368   if (i == max_alloc_count)
9369     fail("Parse failed at maximum allocation count");
9370 }
9371 END_TEST
9372 
9373 /* Test that an error in a nested parameter entity substitution is
9374  * handled correctly.  It seems unlikely that the code path being
9375  * exercised can be reached purely by carefully crafted XML, but an
9376  * allocation error in the right place will definitely do it.
9377  */
9378 START_TEST(test_alloc_nested_entities) {
9379   const char *text = "<!DOCTYPE doc SYSTEM 'http://example.org/one.ent'>\n"
9380                      "<doc />";
9381   ExtFaults test_data
9382       = {"<!ENTITY % pe1 '"
9383          /* 64 characters per line */
9384          "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9385          "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9386          "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9387          "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9388          "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9389          "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9390          "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9391          "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9392          "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9393          "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9394          "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9395          "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9396          "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9397          "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9398          "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9399          "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9400          "'>\n"
9401          "<!ENTITY % pe2 '%pe1;'>\n"
9402          "%pe2;",
9403          "Memory Fail not faulted", NULL, XML_ERROR_NO_MEMORY};
9404 
9405   /* Causes an allocation error in a nested storeEntityValue() */
9406   allocation_count = 12;
9407   XML_SetUserData(g_parser, &test_data);
9408   XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
9409   XML_SetExternalEntityRefHandler(g_parser, external_entity_faulter);
9410   expect_failure(text, XML_ERROR_EXTERNAL_ENTITY_HANDLING,
9411                  "Entity allocation failure not noted");
9412 }
9413 END_TEST
9414 
9415 START_TEST(test_alloc_realloc_param_entity_newline) {
9416   const char *text = "<!DOCTYPE doc SYSTEM 'http://example.org/'>\n"
9417                      "<doc/>";
9418   char dtd_text[]
9419       = "<!ENTITY % pe '<!ATTLIST doc att CDATA \""
9420         /* 64 characters per line */
9421         "This default value is carefully crafted so that the carriage    "
9422         "return right at the end of the entity string causes an internal "
9423         "string pool to have to grow.  This allows us to test the alloc  "
9424         "failure path from that point. OPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9425         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9426         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9427         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9428         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9429         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9430         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9431         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9432         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9433         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9434         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9435         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9436         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDE"
9437         "\">\n'>"
9438         "%pe;\n";
9439   int i;
9440   const int max_realloc_count = 5;
9441 
9442   for (i = 0; i < max_realloc_count; i++) {
9443     reallocation_count = i;
9444     XML_SetUserData(g_parser, dtd_text);
9445     XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
9446     XML_SetExternalEntityRefHandler(g_parser, external_entity_alloc);
9447     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
9448         != XML_STATUS_ERROR)
9449       break;
9450     /* See comment in test_alloc_parse_xdecl() */
9451     alloc_teardown();
9452     alloc_setup();
9453   }
9454   if (i == 0)
9455     fail("Parse succeeded despite failing reallocator");
9456   if (i == max_realloc_count)
9457     fail("Parse failed at maximum reallocation count");
9458 }
9459 END_TEST
9460 
9461 START_TEST(test_alloc_realloc_ce_extends_pe) {
9462   const char *text = "<!DOCTYPE doc SYSTEM 'http://example.org/'>\n"
9463                      "<doc/>";
9464   char dtd_text[]
9465       = "<!ENTITY % pe '<!ATTLIST doc att CDATA \""
9466         /* 64 characters per line */
9467         "This default value is carefully crafted so that the character   "
9468         "entity at the end causes an internal string pool to have to     "
9469         "grow.  This allows us to test the allocation failure path from  "
9470         "that point onwards. EFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9471         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9472         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9473         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9474         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9475         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9476         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9477         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9478         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9479         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9480         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9481         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
9482         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFG&#x51;"
9483         "\">\n'>"
9484         "%pe;\n";
9485   int i;
9486   const int max_realloc_count = 5;
9487 
9488   for (i = 0; i < max_realloc_count; i++) {
9489     reallocation_count = i;
9490     XML_SetUserData(g_parser, dtd_text);
9491     XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
9492     XML_SetExternalEntityRefHandler(g_parser, external_entity_alloc);
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 reallocator");
9502   if (i == max_realloc_count)
9503     fail("Parse failed at maximum reallocation count");
9504 }
9505 END_TEST
9506 
9507 START_TEST(test_alloc_realloc_attributes) {
9508   const char *text = "<!DOCTYPE doc [\n"
9509                      "  <!ATTLIST doc\n"
9510                      "    a1  (a|b|c)   'a'\n"
9511                      "    a2  (foo|bar) #IMPLIED\n"
9512                      "    a3  NMTOKEN   #IMPLIED\n"
9513                      "    a4  NMTOKENS  #IMPLIED\n"
9514                      "    a5  ID        #IMPLIED\n"
9515                      "    a6  IDREF     #IMPLIED\n"
9516                      "    a7  IDREFS    #IMPLIED\n"
9517                      "    a8  ENTITY    #IMPLIED\n"
9518                      "    a9  ENTITIES  #IMPLIED\n"
9519                      "    a10 CDATA     #IMPLIED\n"
9520                      "  >]>\n"
9521                      "<doc>wombat</doc>\n";
9522   int i;
9523   const int max_realloc_count = 5;
9524 
9525   for (i = 0; i < max_realloc_count; i++) {
9526     reallocation_count = i;
9527     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
9528         != XML_STATUS_ERROR)
9529       break;
9530     /* See comment in test_alloc_parse_xdecl() */
9531     alloc_teardown();
9532     alloc_setup();
9533   }
9534 
9535   if (i == 0)
9536     fail("Parse succeeded despite failing reallocator");
9537   if (i == max_realloc_count)
9538     fail("Parse failed at maximum reallocation count");
9539 }
9540 END_TEST
9541 
9542 START_TEST(test_alloc_long_doc_name) {
9543   const char *text =
9544       /* 64 characters per line */
9545       "<LongRootElementNameThatWillCauseTheNextAllocationToExpandTheStr"
9546       "ingPoolForTheDTDQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9547       "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9548       "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9549       "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9550       "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9551       "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9552       "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9553       "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9554       "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9555       "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9556       "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9557       "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9558       "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9559       "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9560       "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9561       " a='1'/>";
9562   int i;
9563   const int max_alloc_count = 20;
9564 
9565   for (i = 0; i < max_alloc_count; i++) {
9566     allocation_count = i;
9567     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
9568         != XML_STATUS_ERROR)
9569       break;
9570     /* See comment in test_alloc_parse_xdecl() */
9571     alloc_teardown();
9572     alloc_setup();
9573   }
9574   if (i == 0)
9575     fail("Parsing worked despite failing reallocations");
9576   else if (i == max_alloc_count)
9577     fail("Parsing failed even at max reallocation count");
9578 }
9579 END_TEST
9580 
9581 START_TEST(test_alloc_long_base) {
9582   const char *text = "<!DOCTYPE doc [\n"
9583                      "  <!ENTITY e SYSTEM 'foo'>\n"
9584                      "]>\n"
9585                      "<doc>&e;</doc>";
9586   char entity_text[] = "Hello world";
9587   const XML_Char *base =
9588       /* 64 characters per line */
9589       /* clang-format off */
9590         XCS("LongBaseURI/that/will/overflow/an/internal/buffer/and/cause/it/t")
9591         XCS("o/have/to/grow/PQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/")
9592         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/")
9593         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/")
9594         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/")
9595         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/")
9596         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/")
9597         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/")
9598         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/")
9599         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/")
9600         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/")
9601         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/")
9602         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/")
9603         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/")
9604         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/")
9605         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/");
9606   /* clang-format on */
9607   int i;
9608   const int max_alloc_count = 25;
9609 
9610   for (i = 0; i < max_alloc_count; i++) {
9611     allocation_count = i;
9612     XML_SetUserData(g_parser, entity_text);
9613     XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
9614     XML_SetExternalEntityRefHandler(g_parser, external_entity_alloc);
9615     if (XML_SetBase(g_parser, base) == XML_STATUS_ERROR) {
9616       XML_ParserReset(g_parser, NULL);
9617       continue;
9618     }
9619     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
9620         != XML_STATUS_ERROR)
9621       break;
9622     /* See comment in test_alloc_parse_xdecl() */
9623     alloc_teardown();
9624     alloc_setup();
9625   }
9626   if (i == 0)
9627     fail("Parsing worked despite failing allocations");
9628   else if (i == max_alloc_count)
9629     fail("Parsing failed even at max allocation count");
9630 }
9631 END_TEST
9632 
9633 START_TEST(test_alloc_long_public_id) {
9634   const char *text
9635       = "<!DOCTYPE doc [\n"
9636         "  <!ENTITY e PUBLIC '"
9637         /* 64 characters per line */
9638         "LongPublicIDThatShouldResultInAnInternalStringPoolGrowingAtASpec"
9639         "ificMomentKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9640         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9641         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9642         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9643         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9644         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9645         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9646         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9647         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9648         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9649         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9650         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9651         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9652         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9653         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9654         "' 'bar'>\n"
9655         "]>\n"
9656         "<doc>&e;</doc>";
9657   char entity_text[] = "Hello world";
9658   int i;
9659   const int max_alloc_count = 40;
9660 
9661   for (i = 0; i < max_alloc_count; i++) {
9662     allocation_count = i;
9663     XML_SetUserData(g_parser, entity_text);
9664     XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
9665     XML_SetExternalEntityRefHandler(g_parser, external_entity_alloc);
9666     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
9667         != XML_STATUS_ERROR)
9668       break;
9669     /* See comment in test_alloc_parse_xdecl() */
9670     alloc_teardown();
9671     alloc_setup();
9672   }
9673   if (i == 0)
9674     fail("Parsing worked despite failing allocations");
9675   else if (i == max_alloc_count)
9676     fail("Parsing failed even at max allocation count");
9677 }
9678 END_TEST
9679 
9680 START_TEST(test_alloc_long_entity_value) {
9681   const char *text
9682       = "<!DOCTYPE doc [\n"
9683         "  <!ENTITY e1 '"
9684         /* 64 characters per line */
9685         "Long entity value that should provoke a string pool to grow whil"
9686         "e setting up to parse the external entity below. xyz0123456789AB"
9687         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9688         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9689         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9690         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9691         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9692         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9693         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9694         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9695         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9696         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9697         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9698         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9699         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9700         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9701         "'>\n"
9702         "  <!ENTITY e2 SYSTEM 'bar'>\n"
9703         "]>\n"
9704         "<doc>&e2;</doc>";
9705   char entity_text[] = "Hello world";
9706   int i;
9707   const int max_alloc_count = 40;
9708 
9709   for (i = 0; i < max_alloc_count; i++) {
9710     allocation_count = i;
9711     XML_SetUserData(g_parser, entity_text);
9712     XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
9713     XML_SetExternalEntityRefHandler(g_parser, external_entity_alloc);
9714     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
9715         != XML_STATUS_ERROR)
9716       break;
9717     /* See comment in test_alloc_parse_xdecl() */
9718     alloc_teardown();
9719     alloc_setup();
9720   }
9721   if (i == 0)
9722     fail("Parsing worked despite failing allocations");
9723   else if (i == max_alloc_count)
9724     fail("Parsing failed even at max allocation count");
9725 }
9726 END_TEST
9727 
9728 START_TEST(test_alloc_long_notation) {
9729   const char *text
9730       = "<!DOCTYPE doc [\n"
9731         "  <!NOTATION note SYSTEM '"
9732         /* 64 characters per line */
9733         "ALongNotationNameThatShouldProvokeStringPoolGrowthWhileCallingAn"
9734         "ExternalEntityParserUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9735         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9736         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9737         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9738         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9739         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9740         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9741         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9742         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9743         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9744         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9745         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9746         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9747         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9748         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9749         "'>\n"
9750         "  <!ENTITY e1 SYSTEM 'foo' NDATA "
9751         /* 64 characters per line */
9752         "ALongNotationNameThatShouldProvokeStringPoolGrowthWhileCallingAn"
9753         "ExternalEntityParserUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9754         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9755         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9756         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9757         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9758         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9759         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9760         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9761         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9762         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9763         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9764         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9765         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9766         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9767         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AB"
9768         ">\n"
9769         "  <!ENTITY e2 SYSTEM 'bar'>\n"
9770         "]>\n"
9771         "<doc>&e2;</doc>";
9772   ExtOption options[]
9773       = {{XCS("foo"), "Entity Foo"}, {XCS("bar"), "Entity Bar"}, {NULL, NULL}};
9774   int i;
9775   const int max_alloc_count = 40;
9776 
9777   for (i = 0; i < max_alloc_count; i++) {
9778     allocation_count = i;
9779     XML_SetUserData(g_parser, options);
9780     XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
9781     XML_SetExternalEntityRefHandler(g_parser, external_entity_optioner);
9782     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
9783         != XML_STATUS_ERROR)
9784       break;
9785 
9786     /* See comment in test_alloc_parse_xdecl() */
9787     alloc_teardown();
9788     alloc_setup();
9789   }
9790   if (i == 0)
9791     fail("Parsing worked despite failing allocations");
9792   else if (i == max_alloc_count)
9793     fail("Parsing failed even at max allocation count");
9794 }
9795 END_TEST
9796 
9797 static void
9798 nsalloc_setup(void) {
9799   XML_Memory_Handling_Suite memsuite = {duff_allocator, duff_reallocator, free};
9800   XML_Char ns_sep[2] = {' ', '\0'};
9801 
9802   /* Ensure the parser creation will go through */
9803   allocation_count = ALLOC_ALWAYS_SUCCEED;
9804   reallocation_count = REALLOC_ALWAYS_SUCCEED;
9805   g_parser = XML_ParserCreate_MM(NULL, &memsuite, ns_sep);
9806   if (g_parser == NULL)
9807     fail("Parser not created");
9808 }
9809 
9810 static void
9811 nsalloc_teardown(void) {
9812   basic_teardown();
9813 }
9814 
9815 /* Test the effects of allocation failure in simple namespace parsing.
9816  * Based on test_ns_default_with_empty_uri()
9817  */
9818 START_TEST(test_nsalloc_xmlns) {
9819   const char *text = "<doc xmlns='http://example.org/'>\n"
9820                      "  <e xmlns=''/>\n"
9821                      "</doc>";
9822   unsigned int i;
9823   const unsigned int max_alloc_count = 30;
9824 
9825   for (i = 0; i < max_alloc_count; i++) {
9826     allocation_count = i;
9827     /* Exercise more code paths with a default handler */
9828     XML_SetDefaultHandler(g_parser, dummy_default_handler);
9829     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
9830         != XML_STATUS_ERROR)
9831       break;
9832     /* Resetting the parser is insufficient, because some memory
9833      * allocations are cached within the parser.  Instead we use
9834      * the teardown and setup routines to ensure that we have the
9835      * right sort of parser back in our hands.
9836      */
9837     nsalloc_teardown();
9838     nsalloc_setup();
9839   }
9840   if (i == 0)
9841     fail("Parsing worked despite failing allocations");
9842   else if (i == max_alloc_count)
9843     fail("Parsing failed even at maximum allocation count");
9844 }
9845 END_TEST
9846 
9847 /* Test XML_ParseBuffer interface with namespace and a dicky allocator */
9848 START_TEST(test_nsalloc_parse_buffer) {
9849   const char *text = "<doc>Hello</doc>";
9850   void *buffer;
9851 
9852   /* Try a parse before the start of the world */
9853   /* (Exercises new code path) */
9854   allocation_count = 0;
9855   if (XML_ParseBuffer(g_parser, 0, XML_FALSE) != XML_STATUS_ERROR)
9856     fail("Pre-init XML_ParseBuffer not faulted");
9857   if (XML_GetErrorCode(g_parser) != XML_ERROR_NO_MEMORY)
9858     fail("Pre-init XML_ParseBuffer faulted for wrong reason");
9859 
9860   /* Now with actual memory allocation */
9861   allocation_count = ALLOC_ALWAYS_SUCCEED;
9862   if (XML_ParseBuffer(g_parser, 0, XML_FALSE) != XML_STATUS_OK)
9863     xml_failure(g_parser);
9864 
9865   /* Check that resuming an unsuspended parser is faulted */
9866   if (XML_ResumeParser(g_parser) != XML_STATUS_ERROR)
9867     fail("Resuming unsuspended parser not faulted");
9868   if (XML_GetErrorCode(g_parser) != XML_ERROR_NOT_SUSPENDED)
9869     xml_failure(g_parser);
9870 
9871   /* Get the parser into suspended state */
9872   XML_SetCharacterDataHandler(g_parser, clearing_aborting_character_handler);
9873   resumable = XML_TRUE;
9874   buffer = XML_GetBuffer(g_parser, (int)strlen(text));
9875   if (buffer == NULL)
9876     fail("Could not acquire parse buffer");
9877   assert(buffer != NULL);
9878   memcpy(buffer, text, strlen(text));
9879   if (XML_ParseBuffer(g_parser, (int)strlen(text), XML_TRUE)
9880       != XML_STATUS_SUSPENDED)
9881     xml_failure(g_parser);
9882   if (XML_GetErrorCode(g_parser) != XML_ERROR_NONE)
9883     xml_failure(g_parser);
9884   if (XML_ParseBuffer(g_parser, (int)strlen(text), XML_TRUE)
9885       != XML_STATUS_ERROR)
9886     fail("Suspended XML_ParseBuffer not faulted");
9887   if (XML_GetErrorCode(g_parser) != XML_ERROR_SUSPENDED)
9888     xml_failure(g_parser);
9889   if (XML_GetBuffer(g_parser, (int)strlen(text)) != NULL)
9890     fail("Suspended XML_GetBuffer not faulted");
9891 
9892   /* Get it going again and complete the world */
9893   XML_SetCharacterDataHandler(g_parser, NULL);
9894   if (XML_ResumeParser(g_parser) != XML_STATUS_OK)
9895     xml_failure(g_parser);
9896   if (XML_ParseBuffer(g_parser, (int)strlen(text), XML_TRUE)
9897       != XML_STATUS_ERROR)
9898     fail("Post-finishing XML_ParseBuffer not faulted");
9899   if (XML_GetErrorCode(g_parser) != XML_ERROR_FINISHED)
9900     xml_failure(g_parser);
9901   if (XML_GetBuffer(g_parser, (int)strlen(text)) != NULL)
9902     fail("Post-finishing XML_GetBuffer not faulted");
9903 }
9904 END_TEST
9905 
9906 /* Check handling of long prefix names (pool growth) */
9907 START_TEST(test_nsalloc_long_prefix) {
9908   const char *text
9909       = "<"
9910         /* 64 characters per line */
9911         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9912         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9913         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9914         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9915         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9916         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9917         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9918         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9919         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9920         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9921         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9922         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9923         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9924         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9925         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9926         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9927         ":foo xmlns:"
9928         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9929         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9930         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9931         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9932         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9933         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9934         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9935         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9936         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9937         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9938         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9939         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9940         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9941         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9942         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9943         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9944         "='http://example.org/'>"
9945         "</"
9946         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9947         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9948         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9949         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9950         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9951         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9952         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9953         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9954         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9955         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9956         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9957         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9958         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9959         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9960         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9961         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
9962         ":foo>";
9963   int i;
9964   const int max_alloc_count = 40;
9965 
9966   for (i = 0; i < max_alloc_count; i++) {
9967     allocation_count = i;
9968     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
9969         != XML_STATUS_ERROR)
9970       break;
9971     /* See comment in test_nsalloc_xmlns() */
9972     nsalloc_teardown();
9973     nsalloc_setup();
9974   }
9975   if (i == 0)
9976     fail("Parsing worked despite failing allocations");
9977   else if (i == max_alloc_count)
9978     fail("Parsing failed even at max allocation count");
9979 }
9980 END_TEST
9981 
9982 /* Check handling of long uri names (pool growth) */
9983 START_TEST(test_nsalloc_long_uri) {
9984   const char *text
9985       = "<foo:e xmlns:foo='http://example.org/"
9986         /* 64 characters per line */
9987         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
9988         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
9989         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
9990         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
9991         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
9992         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
9993         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
9994         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
9995         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
9996         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
9997         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
9998         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
9999         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10000         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10001         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10002         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10003         "' bar:a='12'\n"
10004         "xmlns:bar='http://example.org/"
10005         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10006         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10007         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10008         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10009         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10010         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10011         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10012         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10013         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10014         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10015         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10016         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10017         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10018         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10019         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10020         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789A/"
10021         "'>"
10022         "</foo:e>";
10023   int i;
10024   const int max_alloc_count = 40;
10025 
10026   for (i = 0; i < max_alloc_count; i++) {
10027     allocation_count = i;
10028     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
10029         != XML_STATUS_ERROR)
10030       break;
10031     /* See comment in test_nsalloc_xmlns() */
10032     nsalloc_teardown();
10033     nsalloc_setup();
10034   }
10035   if (i == 0)
10036     fail("Parsing worked despite failing allocations");
10037   else if (i == max_alloc_count)
10038     fail("Parsing failed even at max allocation count");
10039 }
10040 END_TEST
10041 
10042 /* Test handling of long attribute names with prefixes */
10043 START_TEST(test_nsalloc_long_attr) {
10044   const char *text
10045       = "<foo:e xmlns:foo='http://example.org/' bar:"
10046         /* 64 characters per line */
10047         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10048         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10049         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10050         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10051         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10052         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10053         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10054         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10055         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10056         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10057         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10058         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10059         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10060         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10061         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10062         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10063         "='12'\n"
10064         "xmlns:bar='http://example.org/'>"
10065         "</foo:e>";
10066   int i;
10067   const int max_alloc_count = 40;
10068 
10069   for (i = 0; i < max_alloc_count; i++) {
10070     allocation_count = i;
10071     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
10072         != XML_STATUS_ERROR)
10073       break;
10074     /* See comment in test_nsalloc_xmlns() */
10075     nsalloc_teardown();
10076     nsalloc_setup();
10077   }
10078   if (i == 0)
10079     fail("Parsing worked despite failing allocations");
10080   else if (i == max_alloc_count)
10081     fail("Parsing failed even at max allocation count");
10082 }
10083 END_TEST
10084 
10085 /* Test handling of an attribute name with a long namespace prefix */
10086 START_TEST(test_nsalloc_long_attr_prefix) {
10087   const char *text
10088       = "<foo:e xmlns:foo='http://example.org/' "
10089         /* 64 characters per line */
10090         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10091         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10092         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10093         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10094         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10095         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10096         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10097         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10098         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10099         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10100         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10101         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10102         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10103         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10104         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10105         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10106         ":a='12'\n"
10107         "xmlns:"
10108         /* 64 characters per line */
10109         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10110         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10111         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10112         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10113         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10114         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10115         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10116         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10117         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10118         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10119         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10120         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10121         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10122         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10123         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10124         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10125         "='http://example.org/'>"
10126         "</foo:e>";
10127   const XML_Char *elemstr[] = {
10128       /* clang-format off */
10129         XCS("http://example.org/ e foo"),
10130         XCS("http://example.org/ a ")
10131         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ")
10132         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ")
10133         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ")
10134         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ")
10135         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ")
10136         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ")
10137         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ")
10138         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ")
10139         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ")
10140         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ")
10141         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ")
10142         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ")
10143         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ")
10144         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ")
10145         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ")
10146         XCS("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ")
10147       /* clang-format on */
10148   };
10149   int i;
10150   const int max_alloc_count = 40;
10151 
10152   for (i = 0; i < max_alloc_count; i++) {
10153     allocation_count = i;
10154     XML_SetReturnNSTriplet(g_parser, XML_TRUE);
10155     XML_SetUserData(g_parser, (void *)elemstr);
10156     XML_SetElementHandler(g_parser, triplet_start_checker, triplet_end_checker);
10157     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
10158         != XML_STATUS_ERROR)
10159       break;
10160     /* See comment in test_nsalloc_xmlns() */
10161     nsalloc_teardown();
10162     nsalloc_setup();
10163   }
10164   if (i == 0)
10165     fail("Parsing worked despite failing allocations");
10166   else if (i == max_alloc_count)
10167     fail("Parsing failed even at max allocation count");
10168 }
10169 END_TEST
10170 
10171 /* Test attribute handling in the face of a dodgy reallocator */
10172 START_TEST(test_nsalloc_realloc_attributes) {
10173   const char *text = "<foo:e xmlns:foo='http://example.org/' bar:a='12'\n"
10174                      "       xmlns:bar='http://example.org/'>"
10175                      "</foo:e>";
10176   int i;
10177   const int max_realloc_count = 10;
10178 
10179   for (i = 0; i < max_realloc_count; i++) {
10180     reallocation_count = i;
10181     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
10182         != XML_STATUS_ERROR)
10183       break;
10184     /* See comment in test_nsalloc_xmlns() */
10185     nsalloc_teardown();
10186     nsalloc_setup();
10187   }
10188   if (i == 0)
10189     fail("Parsing worked despite failing reallocations");
10190   else if (i == max_realloc_count)
10191     fail("Parsing failed at max reallocation count");
10192 }
10193 END_TEST
10194 
10195 /* Test long element names with namespaces under a failing allocator */
10196 START_TEST(test_nsalloc_long_element) {
10197   const char *text
10198       = "<foo:thisisalongenoughelementnametotriggerareallocation\n"
10199         " xmlns:foo='http://example.org/' bar:a='12'\n"
10200         " xmlns:bar='http://example.org/'>"
10201         "</foo:thisisalongenoughelementnametotriggerareallocation>";
10202   const XML_Char *elemstr[]
10203       = {XCS("http://example.org/")
10204              XCS(" thisisalongenoughelementnametotriggerareallocation foo"),
10205          XCS("http://example.org/ a bar")};
10206   int i;
10207   const int max_alloc_count = 30;
10208 
10209   for (i = 0; i < max_alloc_count; i++) {
10210     allocation_count = i;
10211     XML_SetReturnNSTriplet(g_parser, XML_TRUE);
10212     XML_SetUserData(g_parser, (void *)elemstr);
10213     XML_SetElementHandler(g_parser, triplet_start_checker, triplet_end_checker);
10214     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
10215         != XML_STATUS_ERROR)
10216       break;
10217     /* See comment in test_nsalloc_xmlns() */
10218     nsalloc_teardown();
10219     nsalloc_setup();
10220   }
10221   if (i == 0)
10222     fail("Parsing worked despite failing reallocations");
10223   else if (i == max_alloc_count)
10224     fail("Parsing failed at max reallocation count");
10225 }
10226 END_TEST
10227 
10228 /* Test the effects of reallocation failure when reassigning a
10229  * binding.
10230  *
10231  * XML_ParserReset does not free the BINDING structures used by a
10232  * parser, but instead adds them to an internal free list to be reused
10233  * as necessary.  Likewise the URI buffers allocated for the binding
10234  * aren't freed, but kept attached to their existing binding.  If the
10235  * new binding has a longer URI, it will need reallocation.  This test
10236  * provokes that reallocation, and tests the control path if it fails.
10237  */
10238 START_TEST(test_nsalloc_realloc_binding_uri) {
10239   const char *first = "<doc xmlns='http://example.org/'>\n"
10240                       "  <e xmlns='' />\n"
10241                       "</doc>";
10242   const char *second
10243       = "<doc xmlns='http://example.org/long/enough/URI/to/reallocate/'>\n"
10244         "  <e xmlns='' />\n"
10245         "</doc>";
10246   unsigned i;
10247   const unsigned max_realloc_count = 10;
10248 
10249   /* First, do a full parse that will leave bindings around */
10250   if (_XML_Parse_SINGLE_BYTES(g_parser, first, (int)strlen(first), XML_TRUE)
10251       == XML_STATUS_ERROR)
10252     xml_failure(g_parser);
10253 
10254   /* Now repeat with a longer URI and a duff reallocator */
10255   for (i = 0; i < max_realloc_count; i++) {
10256     XML_ParserReset(g_parser, NULL);
10257     reallocation_count = i;
10258     if (_XML_Parse_SINGLE_BYTES(g_parser, second, (int)strlen(second), XML_TRUE)
10259         != XML_STATUS_ERROR)
10260       break;
10261   }
10262   if (i == 0)
10263     fail("Parsing worked despite failing reallocation");
10264   else if (i == max_realloc_count)
10265     fail("Parsing failed at max reallocation count");
10266 }
10267 END_TEST
10268 
10269 /* Check handling of long prefix names (pool growth) */
10270 START_TEST(test_nsalloc_realloc_long_prefix) {
10271   const char *text
10272       = "<"
10273         /* 64 characters per line */
10274         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10275         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10276         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10277         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10278         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10279         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10280         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10281         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10282         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10283         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10284         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10285         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10286         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10287         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10288         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10289         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10290         ":foo xmlns:"
10291         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10292         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10293         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10294         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10295         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10296         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10297         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10298         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10299         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10300         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10301         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10302         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10303         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10304         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10305         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10306         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10307         "='http://example.org/'>"
10308         "</"
10309         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10310         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10311         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10312         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10313         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10314         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10315         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10316         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10317         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10318         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10319         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10320         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10321         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10322         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10323         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10324         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10325         ":foo>";
10326   int i;
10327   const int max_realloc_count = 12;
10328 
10329   for (i = 0; i < max_realloc_count; i++) {
10330     reallocation_count = i;
10331     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
10332         != XML_STATUS_ERROR)
10333       break;
10334     /* See comment in test_nsalloc_xmlns() */
10335     nsalloc_teardown();
10336     nsalloc_setup();
10337   }
10338   if (i == 0)
10339     fail("Parsing worked despite failing reallocations");
10340   else if (i == max_realloc_count)
10341     fail("Parsing failed even at max reallocation count");
10342 }
10343 END_TEST
10344 
10345 /* Check handling of even long prefix names (different code path) */
10346 START_TEST(test_nsalloc_realloc_longer_prefix) {
10347   const char *text
10348       = "<"
10349         /* 64 characters per line */
10350         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10351         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10352         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10353         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10354         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10355         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10356         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10357         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10358         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10359         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10360         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10361         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10362         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10363         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10364         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10365         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10366         "Q:foo xmlns:"
10367         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10368         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10369         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10370         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10371         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10372         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10373         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10374         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10375         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10376         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10377         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10378         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10379         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10380         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10381         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10382         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10383         "Q='http://example.org/'>"
10384         "</"
10385         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10386         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10387         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10388         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10389         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10390         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10391         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10392         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10393         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10394         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10395         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10396         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10397         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10398         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10399         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10400         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10401         "Q:foo>";
10402   int i;
10403   const int max_realloc_count = 12;
10404 
10405   for (i = 0; i < max_realloc_count; i++) {
10406     reallocation_count = i;
10407     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
10408         != XML_STATUS_ERROR)
10409       break;
10410     /* See comment in test_nsalloc_xmlns() */
10411     nsalloc_teardown();
10412     nsalloc_setup();
10413   }
10414   if (i == 0)
10415     fail("Parsing worked despite failing reallocations");
10416   else if (i == max_realloc_count)
10417     fail("Parsing failed even at max reallocation count");
10418 }
10419 END_TEST
10420 
10421 START_TEST(test_nsalloc_long_namespace) {
10422   const char *text1
10423       = "<"
10424         /* 64 characters per line */
10425         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10426         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10427         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10428         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10429         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10430         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10431         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10432         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10433         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10434         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10435         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10436         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10437         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10438         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10439         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10440         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10441         ":e xmlns:"
10442         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10443         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10444         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10445         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10446         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10447         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10448         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10449         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10450         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10451         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10452         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10453         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10454         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10455         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10456         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10457         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10458         "='http://example.org/'>\n";
10459   const char *text2
10460       = "<"
10461         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10462         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10463         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10464         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10465         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10466         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10467         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10468         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10469         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10470         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10471         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10472         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10473         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10474         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10475         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10476         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10477         ":f "
10478         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10479         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10480         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10481         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10482         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10483         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10484         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10485         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10486         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10487         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10488         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10489         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10490         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10491         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10492         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10493         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10494         ":attr='foo'/>\n"
10495         "</"
10496         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10497         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10498         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10499         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10500         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10501         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10502         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10503         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10504         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10505         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10506         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10507         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10508         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10509         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10510         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10511         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10512         ":e>";
10513   int i;
10514   const int max_alloc_count = 40;
10515 
10516   for (i = 0; i < max_alloc_count; i++) {
10517     allocation_count = i;
10518     if (_XML_Parse_SINGLE_BYTES(g_parser, text1, (int)strlen(text1), XML_FALSE)
10519             != XML_STATUS_ERROR
10520         && _XML_Parse_SINGLE_BYTES(g_parser, text2, (int)strlen(text2),
10521                                    XML_TRUE)
10522                != XML_STATUS_ERROR)
10523       break;
10524     /* See comment in test_nsalloc_xmlns() */
10525     nsalloc_teardown();
10526     nsalloc_setup();
10527   }
10528   if (i == 0)
10529     fail("Parsing worked despite failing allocations");
10530   else if (i == max_alloc_count)
10531     fail("Parsing failed even at max allocation count");
10532 }
10533 END_TEST
10534 
10535 /* Using a slightly shorter namespace name provokes allocations in
10536  * slightly different places in the code.
10537  */
10538 START_TEST(test_nsalloc_less_long_namespace) {
10539   const char *text
10540       = "<"
10541         /* 64 characters per line */
10542         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10543         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10544         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10545         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10546         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10547         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10548         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10549         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz012345678"
10550         ":e xmlns:"
10551         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10552         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10553         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10554         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10555         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10556         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10557         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10558         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz012345678"
10559         "='http://example.org/'>\n"
10560         "<"
10561         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10562         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10563         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10564         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10565         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10566         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10567         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10568         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz012345678"
10569         ":f "
10570         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10571         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10572         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10573         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10574         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10575         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10576         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10577         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz012345678"
10578         ":att='foo'/>\n"
10579         "</"
10580         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10581         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10582         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10583         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10584         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10585         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10586         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789AZ"
10587         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz012345678"
10588         ":e>";
10589   int i;
10590   const int max_alloc_count = 40;
10591 
10592   for (i = 0; i < max_alloc_count; i++) {
10593     allocation_count = i;
10594     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
10595         != XML_STATUS_ERROR)
10596       break;
10597     /* See comment in test_nsalloc_xmlns() */
10598     nsalloc_teardown();
10599     nsalloc_setup();
10600   }
10601   if (i == 0)
10602     fail("Parsing worked despite failing allocations");
10603   else if (i == max_alloc_count)
10604     fail("Parsing failed even at max allocation count");
10605 }
10606 END_TEST
10607 
10608 START_TEST(test_nsalloc_long_context) {
10609   const char *text
10610       = "<!DOCTYPE doc SYSTEM 'foo' [\n"
10611         "  <!ATTLIST doc baz ID #REQUIRED>\n"
10612         "  <!ENTITY en SYSTEM 'bar'>\n"
10613         "]>\n"
10614         "<doc xmlns='http://example.org/"
10615         /* 64 characters per line */
10616         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10617         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10618         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10619         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10620         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10621         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10622         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10623         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10624         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10625         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10626         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10627         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10628         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10629         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10630         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10631         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKL"
10632         "' baz='2'>\n"
10633         "&en;"
10634         "</doc>";
10635   ExtOption options[] = {
10636       {XCS("foo"), "<!ELEMENT e EMPTY>"}, {XCS("bar"), "<e/>"}, {NULL, NULL}};
10637   int i;
10638   const int max_alloc_count = 70;
10639 
10640   for (i = 0; i < max_alloc_count; i++) {
10641     allocation_count = i;
10642     XML_SetUserData(g_parser, options);
10643     XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
10644     XML_SetExternalEntityRefHandler(g_parser, external_entity_optioner);
10645     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
10646         != XML_STATUS_ERROR)
10647       break;
10648 
10649     /* See comment in test_nsalloc_xmlns() */
10650     nsalloc_teardown();
10651     nsalloc_setup();
10652   }
10653   if (i == 0)
10654     fail("Parsing worked despite failing allocations");
10655   else if (i == max_alloc_count)
10656     fail("Parsing failed even at max allocation count");
10657 }
10658 END_TEST
10659 
10660 /* This function is void; it will throw a fail() on error, so if it
10661  * returns normally it must have succeeded.
10662  */
10663 static void
10664 context_realloc_test(const char *text) {
10665   ExtOption options[] = {
10666       {XCS("foo"), "<!ELEMENT e EMPTY>"}, {XCS("bar"), "<e/>"}, {NULL, NULL}};
10667   int i;
10668   const int max_realloc_count = 6;
10669 
10670   for (i = 0; i < max_realloc_count; i++) {
10671     reallocation_count = i;
10672     XML_SetUserData(g_parser, options);
10673     XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
10674     XML_SetExternalEntityRefHandler(g_parser, external_entity_optioner);
10675     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
10676         != XML_STATUS_ERROR)
10677       break;
10678     /* See comment in test_nsalloc_xmlns() */
10679     nsalloc_teardown();
10680     nsalloc_setup();
10681   }
10682   if (i == 0)
10683     fail("Parsing worked despite failing reallocations");
10684   else if (i == max_realloc_count)
10685     fail("Parsing failed even at max reallocation count");
10686 }
10687 
10688 START_TEST(test_nsalloc_realloc_long_context) {
10689   const char *text
10690       = "<!DOCTYPE doc SYSTEM 'foo' [\n"
10691         "  <!ENTITY en SYSTEM 'bar'>\n"
10692         "]>\n"
10693         "<doc xmlns='http://example.org/"
10694         /* 64 characters per line */
10695         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10696         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10697         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10698         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10699         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10700         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10701         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10702         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10703         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10704         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10705         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10706         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10707         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10708         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10709         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10710         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKL"
10711         "'>\n"
10712         "&en;"
10713         "</doc>";
10714 
10715   context_realloc_test(text);
10716 }
10717 END_TEST
10718 
10719 START_TEST(test_nsalloc_realloc_long_context_2) {
10720   const char *text
10721       = "<!DOCTYPE doc SYSTEM 'foo' [\n"
10722         "  <!ENTITY en SYSTEM 'bar'>\n"
10723         "]>\n"
10724         "<doc xmlns='http://example.org/"
10725         /* 64 characters per line */
10726         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10727         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10728         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10729         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10730         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10731         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10732         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10733         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10734         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10735         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10736         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10737         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10738         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10739         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10740         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10741         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJK"
10742         "'>\n"
10743         "&en;"
10744         "</doc>";
10745 
10746   context_realloc_test(text);
10747 }
10748 END_TEST
10749 
10750 START_TEST(test_nsalloc_realloc_long_context_3) {
10751   const char *text
10752       = "<!DOCTYPE doc SYSTEM 'foo' [\n"
10753         "  <!ENTITY en SYSTEM 'bar'>\n"
10754         "]>\n"
10755         "<doc xmlns='http://example.org/"
10756         /* 64 characters per line */
10757         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10758         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10759         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10760         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10761         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10762         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10763         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10764         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10765         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10766         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10767         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10768         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10769         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10770         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10771         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10772         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGH"
10773         "'>\n"
10774         "&en;"
10775         "</doc>";
10776 
10777   context_realloc_test(text);
10778 }
10779 END_TEST
10780 
10781 START_TEST(test_nsalloc_realloc_long_context_4) {
10782   const char *text
10783       = "<!DOCTYPE doc SYSTEM 'foo' [\n"
10784         "  <!ENTITY en SYSTEM 'bar'>\n"
10785         "]>\n"
10786         "<doc xmlns='http://example.org/"
10787         /* 64 characters per line */
10788         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10789         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10790         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10791         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10792         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10793         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10794         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10795         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10796         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10797         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10798         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10799         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10800         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10801         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10802         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10803         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO"
10804         "'>\n"
10805         "&en;"
10806         "</doc>";
10807 
10808   context_realloc_test(text);
10809 }
10810 END_TEST
10811 
10812 START_TEST(test_nsalloc_realloc_long_context_5) {
10813   const char *text
10814       = "<!DOCTYPE doc SYSTEM 'foo' [\n"
10815         "  <!ENTITY en SYSTEM 'bar'>\n"
10816         "]>\n"
10817         "<doc xmlns='http://example.org/"
10818         /* 64 characters per line */
10819         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10820         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10821         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10822         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10823         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10824         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10825         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10826         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10827         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10828         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10829         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10830         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10831         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10832         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10833         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10834         "ABC"
10835         "'>\n"
10836         "&en;"
10837         "</doc>";
10838 
10839   context_realloc_test(text);
10840 }
10841 END_TEST
10842 
10843 START_TEST(test_nsalloc_realloc_long_context_6) {
10844   const char *text
10845       = "<!DOCTYPE doc SYSTEM 'foo' [\n"
10846         "  <!ENTITY en SYSTEM 'bar'>\n"
10847         "]>\n"
10848         "<doc xmlns='http://example.org/"
10849         /* 64 characters per line */
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/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10864         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNOP"
10865         "'>\n"
10866         "&en;"
10867         "</doc>";
10868 
10869   context_realloc_test(text);
10870 }
10871 END_TEST
10872 
10873 START_TEST(test_nsalloc_realloc_long_context_7) {
10874   const char *text
10875       = "<!DOCTYPE doc SYSTEM 'foo' [\n"
10876         "  <!ENTITY en SYSTEM 'bar'>\n"
10877         "]>\n"
10878         "<doc xmlns='http://example.org/"
10879         /* 64 characters per line */
10880         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10881         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10882         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10883         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10884         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10885         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10886         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10887         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10888         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10889         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10890         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10891         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10892         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10893         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10894         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
10895         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLM"
10896         "'>\n"
10897         "&en;"
10898         "</doc>";
10899 
10900   context_realloc_test(text);
10901 }
10902 END_TEST
10903 
10904 START_TEST(test_nsalloc_realloc_long_ge_name) {
10905   const char *text
10906       = "<!DOCTYPE doc SYSTEM 'foo' [\n"
10907         "  <!ENTITY "
10908         /* 64 characters per line */
10909         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
10910         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
10911         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
10912         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
10913         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
10914         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
10915         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
10916         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
10917         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
10918         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
10919         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
10920         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
10921         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
10922         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
10923         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
10924         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
10925         " SYSTEM 'bar'>\n"
10926         "]>\n"
10927         "<doc xmlns='http://example.org/baz'>\n"
10928         "&"
10929         /* 64 characters per line */
10930         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
10931         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
10932         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
10933         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
10934         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
10935         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
10936         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
10937         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
10938         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
10939         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
10940         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
10941         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
10942         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
10943         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
10944         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
10945         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
10946         ";"
10947         "</doc>";
10948   ExtOption options[] = {
10949       {XCS("foo"), "<!ELEMENT el EMPTY>"}, {XCS("bar"), "<el/>"}, {NULL, NULL}};
10950   int i;
10951   const int max_realloc_count = 10;
10952 
10953   for (i = 0; i < max_realloc_count; i++) {
10954     reallocation_count = i;
10955     XML_SetUserData(g_parser, options);
10956     XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
10957     XML_SetExternalEntityRefHandler(g_parser, external_entity_optioner);
10958     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
10959         != XML_STATUS_ERROR)
10960       break;
10961     /* See comment in test_nsalloc_xmlns() */
10962     nsalloc_teardown();
10963     nsalloc_setup();
10964   }
10965   if (i == 0)
10966     fail("Parsing worked despite failing reallocations");
10967   else if (i == max_realloc_count)
10968     fail("Parsing failed even at max reallocation count");
10969 }
10970 END_TEST
10971 
10972 /* Test that when a namespace is passed through the context mechanism
10973  * to an external entity parser, the parsers handle reallocation
10974  * failures correctly.  The prefix is exactly the right length to
10975  * provoke particular uncommon code paths.
10976  */
10977 START_TEST(test_nsalloc_realloc_long_context_in_dtd) {
10978   const char *text1
10979       = "<!DOCTYPE "
10980         /* 64 characters per line */
10981         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
10982         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
10983         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
10984         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
10985         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
10986         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
10987         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
10988         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
10989         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
10990         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
10991         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
10992         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
10993         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
10994         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
10995         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
10996         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
10997         ":doc [\n"
10998         "  <!ENTITY First SYSTEM 'foo/First'>\n"
10999         "]>\n"
11000         "<"
11001         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11002         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11003         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11004         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11005         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11006         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11007         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11008         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11009         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11010         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11011         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11012         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11013         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11014         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11015         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11016         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11017         ":doc xmlns:"
11018         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11019         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11020         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11021         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11022         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11023         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11024         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11025         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11026         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11027         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11028         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11029         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11030         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11031         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11032         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11033         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11034         "='foo/Second'>&First;";
11035   const char *text2
11036       = "</"
11037         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11038         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11039         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11040         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11041         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11042         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11043         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11044         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11045         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11046         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11047         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11048         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11049         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11050         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11051         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11052         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11053         ":doc>";
11054   ExtOption options[] = {{XCS("foo/First"), "Hello world"}, {NULL, NULL}};
11055   int i;
11056   const int max_realloc_count = 20;
11057 
11058   for (i = 0; i < max_realloc_count; i++) {
11059     reallocation_count = i;
11060     XML_SetUserData(g_parser, options);
11061     XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
11062     XML_SetExternalEntityRefHandler(g_parser, external_entity_optioner);
11063     if (_XML_Parse_SINGLE_BYTES(g_parser, text1, (int)strlen(text1), XML_FALSE)
11064             != XML_STATUS_ERROR
11065         && _XML_Parse_SINGLE_BYTES(g_parser, text2, (int)strlen(text2),
11066                                    XML_TRUE)
11067                != XML_STATUS_ERROR)
11068       break;
11069     /* See comment in test_nsalloc_xmlns() */
11070     nsalloc_teardown();
11071     nsalloc_setup();
11072   }
11073   if (i == 0)
11074     fail("Parsing worked despite failing reallocations");
11075   else if (i == max_realloc_count)
11076     fail("Parsing failed even at max reallocation count");
11077 }
11078 END_TEST
11079 
11080 START_TEST(test_nsalloc_long_default_in_ext) {
11081   const char *text
11082       = "<!DOCTYPE doc [\n"
11083         "  <!ATTLIST e a1 CDATA '"
11084         /* 64 characters per line */
11085         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11086         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11087         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11088         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11089         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11090         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11091         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11092         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11093         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11094         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11095         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11096         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11097         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11098         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11099         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11100         "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"
11101         "'>\n"
11102         "  <!ENTITY x SYSTEM 'foo'>\n"
11103         "]>\n"
11104         "<doc>&x;</doc>";
11105   ExtOption options[] = {{XCS("foo"), "<e/>"}, {NULL, NULL}};
11106   int i;
11107   const int max_alloc_count = 50;
11108 
11109   for (i = 0; i < max_alloc_count; i++) {
11110     allocation_count = i;
11111     XML_SetUserData(g_parser, options);
11112     XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
11113     XML_SetExternalEntityRefHandler(g_parser, external_entity_optioner);
11114     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
11115         != XML_STATUS_ERROR)
11116       break;
11117 
11118     /* See comment in test_nsalloc_xmlns() */
11119     nsalloc_teardown();
11120     nsalloc_setup();
11121   }
11122   if (i == 0)
11123     fail("Parsing worked despite failing allocations");
11124   else if (i == max_alloc_count)
11125     fail("Parsing failed even at max allocation count");
11126 }
11127 END_TEST
11128 
11129 START_TEST(test_nsalloc_long_systemid_in_ext) {
11130   const char *text
11131       = "<!DOCTYPE doc SYSTEM 'foo' [\n"
11132         "  <!ENTITY en SYSTEM '"
11133         /* 64 characters per line */
11134         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11135         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11136         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11137         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11138         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11139         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11140         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11141         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11142         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11143         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11144         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11145         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11146         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11147         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11148         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11149         "ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"
11150         "'>\n"
11151         "]>\n"
11152         "<doc>&en;</doc>";
11153   ExtOption options[] = {
11154       {XCS("foo"), "<!ELEMENT e EMPTY>"},
11155       {/* clang-format off */
11156             XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/")
11157             XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/")
11158             XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/")
11159             XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/")
11160             XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/")
11161             XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/")
11162             XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/")
11163             XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/")
11164             XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/")
11165             XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/")
11166             XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/")
11167             XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/")
11168             XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/")
11169             XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/")
11170             XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/")
11171             XCS("ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/ABCDEFGHIJKLMNO/"),
11172        /* clang-format on */
11173        "<e/>"},
11174       {NULL, NULL}};
11175   int i;
11176   const int max_alloc_count = 55;
11177 
11178   for (i = 0; i < max_alloc_count; i++) {
11179     allocation_count = i;
11180     XML_SetUserData(g_parser, options);
11181     XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
11182     XML_SetExternalEntityRefHandler(g_parser, external_entity_optioner);
11183     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
11184         != XML_STATUS_ERROR)
11185       break;
11186 
11187     /* See comment in test_nsalloc_xmlns() */
11188     nsalloc_teardown();
11189     nsalloc_setup();
11190   }
11191   if (i == 0)
11192     fail("Parsing worked despite failing allocations");
11193   else if (i == max_alloc_count)
11194     fail("Parsing failed even at max allocation count");
11195 }
11196 END_TEST
11197 
11198 /* Test the effects of allocation failure on parsing an element in a
11199  * namespace.  Based on test_nsalloc_long_context.
11200  */
11201 START_TEST(test_nsalloc_prefixed_element) {
11202   const char *text = "<!DOCTYPE pfx:element SYSTEM 'foo' [\n"
11203                      "  <!ATTLIST pfx:element baz ID #REQUIRED>\n"
11204                      "  <!ENTITY en SYSTEM 'bar'>\n"
11205                      "]>\n"
11206                      "<pfx:element xmlns:pfx='http://example.org/' baz='2'>\n"
11207                      "&en;"
11208                      "</pfx:element>";
11209   ExtOption options[] = {
11210       {XCS("foo"), "<!ELEMENT e EMPTY>"}, {XCS("bar"), "<e/>"}, {NULL, NULL}};
11211   int i;
11212   const int max_alloc_count = 70;
11213 
11214   for (i = 0; i < max_alloc_count; i++) {
11215     allocation_count = i;
11216     XML_SetUserData(g_parser, options);
11217     XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
11218     XML_SetExternalEntityRefHandler(g_parser, external_entity_optioner);
11219     if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
11220         != XML_STATUS_ERROR)
11221       break;
11222 
11223     /* See comment in test_nsalloc_xmlns() */
11224     nsalloc_teardown();
11225     nsalloc_setup();
11226   }
11227   if (i == 0)
11228     fail("Success despite failing allocator");
11229   else if (i == max_alloc_count)
11230     fail("Failed even at full allocation count");
11231 }
11232 END_TEST
11233 
11234 static Suite *
11235 make_suite(void) {
11236   Suite *s = suite_create("basic");
11237   TCase *tc_basic = tcase_create("basic tests");
11238   TCase *tc_namespace = tcase_create("XML namespaces");
11239   TCase *tc_misc = tcase_create("miscellaneous tests");
11240   TCase *tc_alloc = tcase_create("allocation tests");
11241   TCase *tc_nsalloc = tcase_create("namespace allocation tests");
11242 
11243   suite_add_tcase(s, tc_basic);
11244   tcase_add_checked_fixture(tc_basic, basic_setup, basic_teardown);
11245   tcase_add_test(tc_basic, test_nul_byte);
11246   tcase_add_test(tc_basic, test_u0000_char);
11247   tcase_add_test(tc_basic, test_siphash_self);
11248   tcase_add_test(tc_basic, test_siphash_spec);
11249   tcase_add_test(tc_basic, test_bom_utf8);
11250   tcase_add_test(tc_basic, test_bom_utf16_be);
11251   tcase_add_test(tc_basic, test_bom_utf16_le);
11252   tcase_add_test(tc_basic, test_nobom_utf16_le);
11253   tcase_add_test(tc_basic, test_illegal_utf8);
11254   tcase_add_test(tc_basic, test_utf8_auto_align);
11255   tcase_add_test(tc_basic, test_utf16);
11256   tcase_add_test(tc_basic, test_utf16_le_epilog_newline);
11257   tcase_add_test(tc_basic, test_not_utf16);
11258   tcase_add_test(tc_basic, test_bad_encoding);
11259   tcase_add_test(tc_basic, test_latin1_umlauts);
11260   tcase_add_test(tc_basic, test_long_utf8_character);
11261   tcase_add_test(tc_basic, test_long_latin1_attribute);
11262   tcase_add_test(tc_basic, test_long_ascii_attribute);
11263   /* Regression test for SF bug #491986. */
11264   tcase_add_test(tc_basic, test_danish_latin1);
11265   /* Regression test for SF bug #514281. */
11266   tcase_add_test(tc_basic, test_french_charref_hexidecimal);
11267   tcase_add_test(tc_basic, test_french_charref_decimal);
11268   tcase_add_test(tc_basic, test_french_latin1);
11269   tcase_add_test(tc_basic, test_french_utf8);
11270   tcase_add_test(tc_basic, test_utf8_false_rejection);
11271   tcase_add_test(tc_basic, test_line_number_after_parse);
11272   tcase_add_test(tc_basic, test_column_number_after_parse);
11273   tcase_add_test(tc_basic, test_line_and_column_numbers_inside_handlers);
11274   tcase_add_test(tc_basic, test_line_number_after_error);
11275   tcase_add_test(tc_basic, test_column_number_after_error);
11276   tcase_add_test(tc_basic, test_really_long_lines);
11277   tcase_add_test(tc_basic, test_really_long_encoded_lines);
11278   tcase_add_test(tc_basic, test_end_element_events);
11279   tcase_add_test(tc_basic, test_attr_whitespace_normalization);
11280   tcase_add_test(tc_basic, test_xmldecl_misplaced);
11281   tcase_add_test(tc_basic, test_xmldecl_invalid);
11282   tcase_add_test(tc_basic, test_xmldecl_missing_attr);
11283   tcase_add_test(tc_basic, test_xmldecl_missing_value);
11284   tcase_add_test(tc_basic, test_unknown_encoding_internal_entity);
11285   tcase_add_test(tc_basic, test_unrecognised_encoding_internal_entity);
11286   tcase_add_test(tc_basic, test_wfc_undeclared_entity_unread_external_subset);
11287   tcase_add_test(tc_basic, test_wfc_undeclared_entity_no_external_subset);
11288   tcase_add_test(tc_basic, test_wfc_undeclared_entity_standalone);
11289   tcase_add_test(tc_basic, test_wfc_undeclared_entity_with_external_subset);
11290   tcase_add_test(tc_basic, test_not_standalone_handler_reject);
11291   tcase_add_test(tc_basic, test_not_standalone_handler_accept);
11292   tcase_add_test(tc_basic,
11293                  test_wfc_undeclared_entity_with_external_subset_standalone);
11294   tcase_add_test(tc_basic, test_entity_with_external_subset_unless_standalone);
11295   tcase_add_test(tc_basic, test_wfc_no_recursive_entity_refs);
11296   tcase_add_test__ifdef_xml_dtd(tc_basic, test_ext_entity_set_encoding);
11297   tcase_add_test__ifdef_xml_dtd(tc_basic, test_ext_entity_no_handler);
11298   tcase_add_test__ifdef_xml_dtd(tc_basic, test_ext_entity_set_bom);
11299   tcase_add_test__ifdef_xml_dtd(tc_basic, test_ext_entity_bad_encoding);
11300   tcase_add_test__ifdef_xml_dtd(tc_basic, test_ext_entity_bad_encoding_2);
11301   tcase_add_test__ifdef_xml_dtd(tc_basic, test_ext_entity_invalid_parse);
11302   tcase_add_test__ifdef_xml_dtd(tc_basic,
11303                                 test_ext_entity_invalid_suspended_parse);
11304   tcase_add_test(tc_basic, test_dtd_default_handling);
11305   tcase_add_test(tc_basic, test_dtd_attr_handling);
11306   tcase_add_test(tc_basic, test_empty_ns_without_namespaces);
11307   tcase_add_test(tc_basic, test_ns_in_attribute_default_without_namespaces);
11308   tcase_add_test(tc_basic, test_stop_parser_between_char_data_calls);
11309   tcase_add_test(tc_basic, test_suspend_parser_between_char_data_calls);
11310   tcase_add_test(tc_basic, test_repeated_stop_parser_between_char_data_calls);
11311   tcase_add_test(tc_basic, test_good_cdata_ascii);
11312   tcase_add_test(tc_basic, test_good_cdata_utf16);
11313   tcase_add_test(tc_basic, test_good_cdata_utf16_le);
11314   tcase_add_test(tc_basic, test_long_cdata_utf16);
11315 #ifndef XML_MIN_SIZE /* FIXME workaround -DXML_MIN_SIZE + ASan (issue #332) */
11316   tcase_add_test(tc_basic, test_multichar_cdata_utf16);
11317 #endif
11318   tcase_add_test(tc_basic, test_utf16_bad_surrogate_pair);
11319   tcase_add_test(tc_basic, test_bad_cdata);
11320 #ifndef XML_MIN_SIZE /* FIXME workaround -DXML_MIN_SIZE + ASan (issue #332) */
11321   tcase_add_test(tc_basic, test_bad_cdata_utf16);
11322 #endif
11323   tcase_add_test(tc_basic, test_stop_parser_between_cdata_calls);
11324   tcase_add_test(tc_basic, test_suspend_parser_between_cdata_calls);
11325   tcase_add_test(tc_basic, test_memory_allocation);
11326   tcase_add_test(tc_basic, test_default_current);
11327   tcase_add_test(tc_basic, test_dtd_elements);
11328   tcase_add_test__ifdef_xml_dtd(tc_basic, test_set_foreign_dtd);
11329   tcase_add_test__ifdef_xml_dtd(tc_basic, test_foreign_dtd_not_standalone);
11330   tcase_add_test__ifdef_xml_dtd(tc_basic, test_invalid_foreign_dtd);
11331   tcase_add_test__ifdef_xml_dtd(tc_basic, test_foreign_dtd_with_doctype);
11332   tcase_add_test__ifdef_xml_dtd(tc_basic,
11333                                 test_foreign_dtd_without_external_subset);
11334   tcase_add_test__ifdef_xml_dtd(tc_basic, test_empty_foreign_dtd);
11335   tcase_add_test(tc_basic, test_set_base);
11336   tcase_add_test(tc_basic, test_attributes);
11337   tcase_add_test(tc_basic, test_reset_in_entity);
11338   tcase_add_test(tc_basic, test_resume_invalid_parse);
11339   tcase_add_test(tc_basic, test_resume_resuspended);
11340   tcase_add_test(tc_basic, test_cdata_default);
11341   tcase_add_test(tc_basic, test_subordinate_reset);
11342   tcase_add_test(tc_basic, test_subordinate_suspend);
11343   tcase_add_test(tc_basic, test_subordinate_xdecl_suspend);
11344   tcase_add_test(tc_basic, test_subordinate_xdecl_abort);
11345   tcase_add_test(tc_basic, test_explicit_encoding);
11346   tcase_add_test(tc_basic, test_trailing_cr);
11347   tcase_add_test(tc_basic, test_ext_entity_trailing_cr);
11348   tcase_add_test(tc_basic, test_trailing_rsqb);
11349   tcase_add_test(tc_basic, test_ext_entity_trailing_rsqb);
11350   tcase_add_test(tc_basic, test_ext_entity_good_cdata);
11351   tcase_add_test__ifdef_xml_dtd(tc_basic, test_user_parameters);
11352   tcase_add_test__ifdef_xml_dtd(tc_basic, test_ext_entity_ref_parameter);
11353   tcase_add_test(tc_basic, test_empty_parse);
11354   tcase_add_test(tc_basic, test_get_buffer_1);
11355   tcase_add_test(tc_basic, test_get_buffer_2);
11356   tcase_add_test(tc_basic, test_byte_info_at_end);
11357   tcase_add_test(tc_basic, test_byte_info_at_error);
11358   tcase_add_test(tc_basic, test_byte_info_at_cdata);
11359   tcase_add_test(tc_basic, test_predefined_entities);
11360   tcase_add_test__ifdef_xml_dtd(tc_basic, test_invalid_tag_in_dtd);
11361   tcase_add_test(tc_basic, test_not_predefined_entities);
11362   tcase_add_test__ifdef_xml_dtd(tc_basic, test_ignore_section);
11363   tcase_add_test__ifdef_xml_dtd(tc_basic, test_ignore_section_utf16);
11364   tcase_add_test__ifdef_xml_dtd(tc_basic, test_ignore_section_utf16_be);
11365   tcase_add_test__ifdef_xml_dtd(tc_basic, test_bad_ignore_section);
11366   tcase_add_test__ifdef_xml_dtd(tc_basic, test_external_entity_values);
11367   tcase_add_test__ifdef_xml_dtd(tc_basic, test_ext_entity_not_standalone);
11368   tcase_add_test__ifdef_xml_dtd(tc_basic, test_ext_entity_value_abort);
11369   tcase_add_test(tc_basic, test_bad_public_doctype);
11370   tcase_add_test(tc_basic, test_attribute_enum_value);
11371   tcase_add_test(tc_basic, test_predefined_entity_redefinition);
11372   tcase_add_test__ifdef_xml_dtd(tc_basic, test_dtd_stop_processing);
11373   tcase_add_test(tc_basic, test_public_notation_no_sysid);
11374   tcase_add_test(tc_basic, test_nested_groups);
11375   tcase_add_test(tc_basic, test_group_choice);
11376   tcase_add_test(tc_basic, test_standalone_parameter_entity);
11377   tcase_add_test__ifdef_xml_dtd(tc_basic, test_skipped_parameter_entity);
11378   tcase_add_test__ifdef_xml_dtd(tc_basic,
11379                                 test_recursive_external_parameter_entity);
11380   tcase_add_test(tc_basic, test_undefined_ext_entity_in_external_dtd);
11381   tcase_add_test(tc_basic, test_suspend_xdecl);
11382   tcase_add_test(tc_basic, test_abort_epilog);
11383   tcase_add_test(tc_basic, test_abort_epilog_2);
11384   tcase_add_test(tc_basic, test_suspend_epilog);
11385   tcase_add_test(tc_basic, test_suspend_in_sole_empty_tag);
11386   tcase_add_test(tc_basic, test_unfinished_epilog);
11387   tcase_add_test(tc_basic, test_partial_char_in_epilog);
11388   tcase_add_test(tc_basic, test_hash_collision);
11389   tcase_add_test__ifdef_xml_dtd(tc_basic, test_suspend_resume_internal_entity);
11390   tcase_add_test__ifdef_xml_dtd(tc_basic, test_resume_entity_with_syntax_error);
11391   tcase_add_test__ifdef_xml_dtd(tc_basic, test_suspend_resume_parameter_entity);
11392   tcase_add_test(tc_basic, test_restart_on_error);
11393   tcase_add_test(tc_basic, test_reject_lt_in_attribute_value);
11394   tcase_add_test(tc_basic, test_reject_unfinished_param_in_att_value);
11395   tcase_add_test(tc_basic, test_trailing_cr_in_att_value);
11396   tcase_add_test(tc_basic, test_standalone_internal_entity);
11397   tcase_add_test(tc_basic, test_skipped_external_entity);
11398   tcase_add_test(tc_basic, test_skipped_null_loaded_ext_entity);
11399   tcase_add_test(tc_basic, test_skipped_unloaded_ext_entity);
11400   tcase_add_test__ifdef_xml_dtd(tc_basic, test_param_entity_with_trailing_cr);
11401   tcase_add_test(tc_basic, test_invalid_character_entity);
11402   tcase_add_test(tc_basic, test_invalid_character_entity_2);
11403   tcase_add_test(tc_basic, test_invalid_character_entity_3);
11404   tcase_add_test(tc_basic, test_invalid_character_entity_4);
11405   tcase_add_test(tc_basic, test_pi_handled_in_default);
11406   tcase_add_test(tc_basic, test_comment_handled_in_default);
11407   tcase_add_test(tc_basic, test_pi_yml);
11408   tcase_add_test(tc_basic, test_pi_xnl);
11409   tcase_add_test(tc_basic, test_pi_xmm);
11410   tcase_add_test(tc_basic, test_utf16_pi);
11411   tcase_add_test(tc_basic, test_utf16_be_pi);
11412   tcase_add_test(tc_basic, test_utf16_be_comment);
11413   tcase_add_test(tc_basic, test_utf16_le_comment);
11414   tcase_add_test(tc_basic, test_missing_encoding_conversion_fn);
11415   tcase_add_test(tc_basic, test_failing_encoding_conversion_fn);
11416   tcase_add_test(tc_basic, test_unknown_encoding_success);
11417   tcase_add_test(tc_basic, test_unknown_encoding_bad_name);
11418   tcase_add_test(tc_basic, test_unknown_encoding_bad_name_2);
11419   tcase_add_test(tc_basic, test_unknown_encoding_long_name_1);
11420   tcase_add_test(tc_basic, test_unknown_encoding_long_name_2);
11421   tcase_add_test(tc_basic, test_invalid_unknown_encoding);
11422   tcase_add_test(tc_basic, test_unknown_ascii_encoding_ok);
11423   tcase_add_test(tc_basic, test_unknown_ascii_encoding_fail);
11424   tcase_add_test(tc_basic, test_unknown_encoding_invalid_length);
11425   tcase_add_test(tc_basic, test_unknown_encoding_invalid_topbit);
11426   tcase_add_test(tc_basic, test_unknown_encoding_invalid_surrogate);
11427   tcase_add_test(tc_basic, test_unknown_encoding_invalid_high);
11428   tcase_add_test(tc_basic, test_unknown_encoding_invalid_attr_value);
11429   tcase_add_test(tc_basic, test_ext_entity_latin1_utf16le_bom);
11430   tcase_add_test(tc_basic, test_ext_entity_latin1_utf16be_bom);
11431   tcase_add_test(tc_basic, test_ext_entity_latin1_utf16le_bom2);
11432   tcase_add_test(tc_basic, test_ext_entity_latin1_utf16be_bom2);
11433   tcase_add_test(tc_basic, test_ext_entity_utf16_be);
11434   tcase_add_test(tc_basic, test_ext_entity_utf16_le);
11435   tcase_add_test(tc_basic, test_ext_entity_utf16_unknown);
11436   tcase_add_test(tc_basic, test_ext_entity_utf8_non_bom);
11437   tcase_add_test(tc_basic, test_utf8_in_cdata_section);
11438   tcase_add_test(tc_basic, test_utf8_in_cdata_section_2);
11439   tcase_add_test(tc_basic, test_trailing_spaces_in_elements);
11440   tcase_add_test(tc_basic, test_utf16_attribute);
11441   tcase_add_test(tc_basic, test_utf16_second_attr);
11442   tcase_add_test(tc_basic, test_attr_after_solidus);
11443   tcase_add_test__ifdef_xml_dtd(tc_basic, test_utf16_pe);
11444   tcase_add_test(tc_basic, test_bad_attr_desc_keyword);
11445   tcase_add_test(tc_basic, test_bad_attr_desc_keyword_utf16);
11446   tcase_add_test(tc_basic, test_bad_doctype);
11447   tcase_add_test(tc_basic, test_bad_doctype_utf16);
11448   tcase_add_test(tc_basic, test_bad_doctype_plus);
11449   tcase_add_test(tc_basic, test_bad_doctype_star);
11450   tcase_add_test(tc_basic, test_bad_doctype_query);
11451   tcase_add_test__ifdef_xml_dtd(tc_basic, test_unknown_encoding_bad_ignore);
11452   tcase_add_test(tc_basic, test_entity_in_utf16_be_attr);
11453   tcase_add_test(tc_basic, test_entity_in_utf16_le_attr);
11454   tcase_add_test__ifdef_xml_dtd(tc_basic, test_entity_public_utf16_be);
11455   tcase_add_test__ifdef_xml_dtd(tc_basic, test_entity_public_utf16_le);
11456   tcase_add_test(tc_basic, test_short_doctype);
11457   tcase_add_test(tc_basic, test_short_doctype_2);
11458   tcase_add_test(tc_basic, test_short_doctype_3);
11459   tcase_add_test(tc_basic, test_long_doctype);
11460   tcase_add_test(tc_basic, test_bad_entity);
11461   tcase_add_test(tc_basic, test_bad_entity_2);
11462   tcase_add_test(tc_basic, test_bad_entity_3);
11463   tcase_add_test(tc_basic, test_bad_entity_4);
11464   tcase_add_test(tc_basic, test_bad_notation);
11465   tcase_add_test(tc_basic, test_default_doctype_handler);
11466   tcase_add_test(tc_basic, test_empty_element_abort);
11467 
11468   suite_add_tcase(s, tc_namespace);
11469   tcase_add_checked_fixture(tc_namespace, namespace_setup, namespace_teardown);
11470   tcase_add_test(tc_namespace, test_return_ns_triplet);
11471   tcase_add_test(tc_namespace, test_ns_tagname_overwrite);
11472   tcase_add_test(tc_namespace, test_ns_tagname_overwrite_triplet);
11473   tcase_add_test(tc_namespace, test_start_ns_clears_start_element);
11474   tcase_add_test__ifdef_xml_dtd(tc_namespace,
11475                                 test_default_ns_from_ext_subset_and_ext_ge);
11476   tcase_add_test(tc_namespace, test_ns_prefix_with_empty_uri_1);
11477   tcase_add_test(tc_namespace, test_ns_prefix_with_empty_uri_2);
11478   tcase_add_test(tc_namespace, test_ns_prefix_with_empty_uri_3);
11479   tcase_add_test(tc_namespace, test_ns_prefix_with_empty_uri_4);
11480   tcase_add_test(tc_namespace, test_ns_unbound_prefix);
11481   tcase_add_test(tc_namespace, test_ns_default_with_empty_uri);
11482   tcase_add_test(tc_namespace, test_ns_duplicate_attrs_diff_prefixes);
11483   tcase_add_test(tc_namespace, test_ns_duplicate_hashes);
11484   tcase_add_test(tc_namespace, test_ns_unbound_prefix_on_attribute);
11485   tcase_add_test(tc_namespace, test_ns_unbound_prefix_on_element);
11486   tcase_add_test(tc_namespace, test_ns_parser_reset);
11487   tcase_add_test(tc_namespace, test_ns_long_element);
11488   tcase_add_test(tc_namespace, test_ns_mixed_prefix_atts);
11489   tcase_add_test(tc_namespace, test_ns_extend_uri_buffer);
11490   tcase_add_test(tc_namespace, test_ns_reserved_attributes);
11491   tcase_add_test(tc_namespace, test_ns_reserved_attributes_2);
11492   tcase_add_test(tc_namespace, test_ns_extremely_long_prefix);
11493   tcase_add_test(tc_namespace, test_ns_unknown_encoding_success);
11494   tcase_add_test(tc_namespace, test_ns_double_colon);
11495   tcase_add_test(tc_namespace, test_ns_double_colon_element);
11496   tcase_add_test(tc_namespace, test_ns_bad_attr_leafname);
11497   tcase_add_test(tc_namespace, test_ns_bad_element_leafname);
11498   tcase_add_test(tc_namespace, test_ns_utf16_leafname);
11499   tcase_add_test(tc_namespace, test_ns_utf16_element_leafname);
11500   tcase_add_test(tc_namespace, test_ns_utf16_doctype);
11501   tcase_add_test(tc_namespace, test_ns_invalid_doctype);
11502   tcase_add_test(tc_namespace, test_ns_double_colon_doctype);
11503 
11504   suite_add_tcase(s, tc_misc);
11505   tcase_add_checked_fixture(tc_misc, NULL, basic_teardown);
11506   tcase_add_test(tc_misc, test_misc_alloc_create_parser);
11507   tcase_add_test(tc_misc, test_misc_alloc_create_parser_with_encoding);
11508   tcase_add_test(tc_misc, test_misc_null_parser);
11509   tcase_add_test(tc_misc, test_misc_error_string);
11510   tcase_add_test(tc_misc, test_misc_version);
11511   tcase_add_test(tc_misc, test_misc_features);
11512   tcase_add_test(tc_misc, test_misc_attribute_leak);
11513   tcase_add_test(tc_misc, test_misc_utf16le);
11514   tcase_add_test(tc_misc, test_misc_stop_during_end_handler_issue_240_1);
11515   tcase_add_test(tc_misc, test_misc_stop_during_end_handler_issue_240_2);
11516   tcase_add_test__ifdef_xml_dtd(
11517       tc_misc, test_misc_deny_internal_entity_closing_doctype_issue_317);
11518 
11519   suite_add_tcase(s, tc_alloc);
11520   tcase_add_checked_fixture(tc_alloc, alloc_setup, alloc_teardown);
11521   tcase_add_test(tc_alloc, test_alloc_parse_xdecl);
11522   tcase_add_test(tc_alloc, test_alloc_parse_xdecl_2);
11523   tcase_add_test(tc_alloc, test_alloc_parse_pi);
11524   tcase_add_test(tc_alloc, test_alloc_parse_pi_2);
11525   tcase_add_test(tc_alloc, test_alloc_parse_pi_3);
11526   tcase_add_test(tc_alloc, test_alloc_parse_comment);
11527   tcase_add_test(tc_alloc, test_alloc_parse_comment_2);
11528   tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_create_external_parser);
11529   tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_run_external_parser);
11530   tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_dtd_copy_default_atts);
11531   tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_external_entity);
11532   tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_ext_entity_set_encoding);
11533   tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_internal_entity);
11534   tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_dtd_default_handling);
11535   tcase_add_test(tc_alloc, test_alloc_explicit_encoding);
11536   tcase_add_test(tc_alloc, test_alloc_set_base);
11537   tcase_add_test(tc_alloc, test_alloc_realloc_buffer);
11538   tcase_add_test(tc_alloc, test_alloc_ext_entity_realloc_buffer);
11539   tcase_add_test(tc_alloc, test_alloc_realloc_many_attributes);
11540   tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_public_entity_value);
11541   tcase_add_test__ifdef_xml_dtd(tc_alloc,
11542                                 test_alloc_realloc_subst_public_entity_value);
11543   tcase_add_test(tc_alloc, test_alloc_parse_public_doctype);
11544   tcase_add_test(tc_alloc, test_alloc_parse_public_doctype_long_name);
11545   tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_set_foreign_dtd);
11546   tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_attribute_enum_value);
11547   tcase_add_test__ifdef_xml_dtd(tc_alloc,
11548                                 test_alloc_realloc_attribute_enum_value);
11549   tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_realloc_implied_attribute);
11550   tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_realloc_default_attribute);
11551   tcase_add_test(tc_alloc, test_alloc_notation);
11552   tcase_add_test(tc_alloc, test_alloc_public_notation);
11553   tcase_add_test(tc_alloc, test_alloc_system_notation);
11554   tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_nested_groups);
11555   tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_realloc_nested_groups);
11556   tcase_add_test(tc_alloc, test_alloc_large_group);
11557   tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_realloc_group_choice);
11558   tcase_add_test(tc_alloc, test_alloc_pi_in_epilog);
11559   tcase_add_test(tc_alloc, test_alloc_comment_in_epilog);
11560   tcase_add_test__ifdef_xml_dtd(tc_alloc,
11561                                 test_alloc_realloc_long_attribute_value);
11562   tcase_add_test(tc_alloc, test_alloc_attribute_whitespace);
11563   tcase_add_test(tc_alloc, test_alloc_attribute_predefined_entity);
11564   tcase_add_test(tc_alloc, test_alloc_long_attr_default_with_char_ref);
11565   tcase_add_test(tc_alloc, test_alloc_long_attr_value);
11566   tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_nested_entities);
11567   tcase_add_test__ifdef_xml_dtd(tc_alloc,
11568                                 test_alloc_realloc_param_entity_newline);
11569   tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_realloc_ce_extends_pe);
11570   tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_realloc_attributes);
11571   tcase_add_test(tc_alloc, test_alloc_long_doc_name);
11572   tcase_add_test(tc_alloc, test_alloc_long_base);
11573   tcase_add_test(tc_alloc, test_alloc_long_public_id);
11574   tcase_add_test(tc_alloc, test_alloc_long_entity_value);
11575   tcase_add_test(tc_alloc, test_alloc_long_notation);
11576 
11577   suite_add_tcase(s, tc_nsalloc);
11578   tcase_add_checked_fixture(tc_nsalloc, nsalloc_setup, nsalloc_teardown);
11579   tcase_add_test(tc_nsalloc, test_nsalloc_xmlns);
11580   tcase_add_test(tc_nsalloc, test_nsalloc_parse_buffer);
11581   tcase_add_test(tc_nsalloc, test_nsalloc_long_prefix);
11582   tcase_add_test(tc_nsalloc, test_nsalloc_long_uri);
11583   tcase_add_test(tc_nsalloc, test_nsalloc_long_attr);
11584   tcase_add_test(tc_nsalloc, test_nsalloc_long_attr_prefix);
11585   tcase_add_test(tc_nsalloc, test_nsalloc_realloc_attributes);
11586   tcase_add_test(tc_nsalloc, test_nsalloc_long_element);
11587   tcase_add_test(tc_nsalloc, test_nsalloc_realloc_binding_uri);
11588   tcase_add_test(tc_nsalloc, test_nsalloc_realloc_long_prefix);
11589   tcase_add_test(tc_nsalloc, test_nsalloc_realloc_longer_prefix);
11590   tcase_add_test(tc_nsalloc, test_nsalloc_long_namespace);
11591   tcase_add_test(tc_nsalloc, test_nsalloc_less_long_namespace);
11592   tcase_add_test(tc_nsalloc, test_nsalloc_long_context);
11593   tcase_add_test(tc_nsalloc, test_nsalloc_realloc_long_context);
11594   tcase_add_test(tc_nsalloc, test_nsalloc_realloc_long_context_2);
11595   tcase_add_test(tc_nsalloc, test_nsalloc_realloc_long_context_3);
11596   tcase_add_test(tc_nsalloc, test_nsalloc_realloc_long_context_4);
11597   tcase_add_test(tc_nsalloc, test_nsalloc_realloc_long_context_5);
11598   tcase_add_test(tc_nsalloc, test_nsalloc_realloc_long_context_6);
11599   tcase_add_test(tc_nsalloc, test_nsalloc_realloc_long_context_7);
11600   tcase_add_test(tc_nsalloc, test_nsalloc_realloc_long_ge_name);
11601   tcase_add_test(tc_nsalloc, test_nsalloc_realloc_long_context_in_dtd);
11602   tcase_add_test(tc_nsalloc, test_nsalloc_long_default_in_ext);
11603   tcase_add_test(tc_nsalloc, test_nsalloc_long_systemid_in_ext);
11604   tcase_add_test(tc_nsalloc, test_nsalloc_prefixed_element);
11605 
11606   return s;
11607 }
11608 
11609 int
11610 main(int argc, char *argv[]) {
11611   int i, nf;
11612   int verbosity = CK_NORMAL;
11613   Suite *s = make_suite();
11614   SRunner *sr = srunner_create(s);
11615 
11616   /* run the tests for internal helper functions */
11617   testhelper_is_whitespace_normalized();
11618 
11619   for (i = 1; i < argc; ++i) {
11620     char *opt = argv[i];
11621     if (strcmp(opt, "-v") == 0 || strcmp(opt, "--verbose") == 0)
11622       verbosity = CK_VERBOSE;
11623     else if (strcmp(opt, "-q") == 0 || strcmp(opt, "--quiet") == 0)
11624       verbosity = CK_SILENT;
11625     else {
11626       fprintf(stderr, "runtests: unknown option '%s'\n", opt);
11627       return 2;
11628     }
11629   }
11630   if (verbosity != CK_SILENT)
11631     printf("Expat version: %" XML_FMT_STR "\n", XML_ExpatVersion());
11632   srunner_run_all(sr, verbosity);
11633   nf = srunner_ntests_failed(sr);
11634   srunner_free(sr);
11635 
11636   return (nf == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
11637 }
11638