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