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