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