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